Files
oceanbase/src/sql/rewrite/ob_expand_aggregate_utils.cpp
oceanbase-admin cea7de1475 init push
2021-05-31 22:56:52 +08:00

1822 lines
95 KiB
C++

/**
* 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.
*/
#define USING_LOG_PREFIX SQL_REWRITE
#include "sql/rewrite/ob_expand_aggregate_utils.h"
#include "common/ob_common_utility.h"
#include "lib/allocator/ob_allocator.h"
#include "lib/oblog/ob_log_module.h"
#include "share/ob_errno.h"
#include "share/schema/ob_table_schema.h"
#include "sql/resolver/expr/ob_raw_expr.h"
#include "sql/resolver/ob_resolver_utils.h"
#include "common/ob_common_utility.h"
#include "sql/resolver/dml/ob_select_stmt.h"
#include "sql/resolver/dml/ob_dml_stmt.h"
#include "sql/resolver/expr/ob_raw_expr_util.h"
#include "sql/rewrite/ob_stmt_comparer.h"
#include "sql/rewrite/ob_transform_utils.h"
#include "sql/optimizer/ob_optimizer_util.h"
#include "sql/rewrite/ob_transform_rule.h"
namespace oceanbase {
using namespace common;
using namespace share::schema;
namespace sql {
int ObExpandAggregateUtils::expand_aggr_expr(ObDMLStmt* stmt, ObTransformerCtx* ctx, bool& trans_happened)
{
int ret = OB_SUCCESS;
ObSEArray<ObRawExpr*, 4> candi_aggr_items;
ObSEArray<ObRawExpr*, 4> replace_exprs;
ObSEArray<ObAggFunRawExpr*, 4> new_aggr_items;
trans_happened = false;
if (OB_ISNULL(stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(stmt));
} else if (OB_FAIL(extract_candi_aggr(stmt, candi_aggr_items, new_aggr_items))) {
LOG_WARN("failed to extact candi aggr", K(ret));
} else if (candi_aggr_items.empty()) {
/*do nothing */
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < candi_aggr_items.count(); ++i) {
ObRawExpr* replace_expr = NULL;
ObAggFunRawExpr* aggr_expr = static_cast<ObAggFunRawExpr*>(candi_aggr_items.at(i));
if (OB_ISNULL(aggr_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr));
} else if (is_covar_expr_type(aggr_expr->get_expr_type()) &&
OB_FAIL(expand_covar_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand covar expr", K(ret));
} else if (aggr_expr->get_expr_type() == T_FUN_CORR &&
OB_FAIL(expand_corr_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand corr expr", K(ret));
} else if (is_var_expr_type(aggr_expr->get_expr_type()) &&
OB_FAIL(expand_var_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand var expr", K(ret));
} else if (is_regr_expr_type(aggr_expr->get_expr_type()) &&
OB_FAIL(expand_regr_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr expr", K(ret));
} else if (is_keep_aggr_type(aggr_expr->get_expr_type()) &&
OB_FAIL(expand_keep_aggr_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand keep aggr expr", K(ret));
} else if (is_common_aggr_type(aggr_expr->get_expr_type()) &&
OB_FAIL(expand_common_aggr_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand common aggr expr", K(ret));
} else if (OB_ISNULL(replace_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(replace_expr), K(aggr_expr->get_expr_type()));
} else if (OB_FAIL(replace_expr->formalize(ctx->session_info_))) {
LOG_WARN("failed to formalize", K(ret));
} else if (OB_FAIL(replace_expr->pull_relation_id_and_levels(stmt->get_current_level()))) {
LOG_WARN("failed to pull relation id and levels", K(ret));
} else if (OB_FAIL(replace_exprs.push_back(replace_expr))) {
LOG_WARN("failed to push back expr", K(ret));
} else { /*do nothing*/
}
}
if (OB_SUCC(ret)) {
if (stmt->is_select_stmt() &&
OB_FAIL(static_cast<ObSelectStmt*>(stmt)->get_aggr_items().assign(new_aggr_items))) {
LOG_WARN("failed to assign expr", K(ret));
} else if (!stmt->is_select_stmt() &&
OB_FAIL(static_cast<ObDelUpdStmt*>(stmt)->get_returning_aggr_items().assign(new_aggr_items))) {
LOG_WARN("failed to assign expr", K(ret));
} else if (OB_FAIL(stmt->replace_inner_stmt_expr(candi_aggr_items, replace_exprs))) {
LOG_WARN("failed to replace stmt expr", K(ret));
} else {
trans_happened = true;
}
}
}
return ret;
}
int ObExpandAggregateUtils::expand_window_aggr_expr(ObDMLStmt* stmt, ObTransformerCtx* ctx, bool& trans_happened)
{
int ret = OB_SUCCESS;
ObSEArray<ObRawExpr*, 4> candi_win_items;
ObSEArray<ObAggFunRawExpr*, 4> new_aggr_items;
ObSEArray<ObRawExpr*, 4> replace_exprs;
ObSEArray<ObWinFunRawExpr*, 4> new_win_exprs;
trans_happened = false;
if (OB_ISNULL(stmt) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table item is null", K(ret), K(stmt), K(ctx));
} else if (!stmt->is_select_stmt()) {
/*do nothing*/
} else if (OB_FAIL(extract_candi_window_aggr(static_cast<ObSelectStmt*>(stmt), candi_win_items, new_win_exprs))) {
LOG_WARN("failed to extract candi window aggr", K(ret));
} else if (candi_win_items.empty()) {
/*do nothing */
} else {
ObSelectStmt* select_stmt = static_cast<ObSelectStmt*>(stmt);
for (int64_t i = 0; OB_SUCC(ret) && i < candi_win_items.count(); ++i) {
ObRawExpr* replace_expr = NULL;
ObWinFunRawExpr* win_expr = static_cast<ObWinFunRawExpr*>(candi_win_items.at(i));
if (OB_ISNULL(win_expr) || OB_ISNULL(win_expr->get_agg_expr())) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(win_expr));
} else if (is_covar_expr_type(win_expr->get_agg_expr()->get_expr_type()) &&
OB_FAIL(expand_covar_expr(ctx, win_expr->get_agg_expr(), replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand covar expr", K(ret));
} else if (win_expr->get_agg_expr()->get_expr_type() == T_FUN_CORR &&
OB_FAIL(expand_corr_expr(ctx, win_expr->get_agg_expr(), replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand corr expr", K(ret));
} else if (is_var_expr_type(win_expr->get_agg_expr()->get_expr_type()) &&
OB_FAIL(expand_var_expr(ctx, win_expr->get_agg_expr(), replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand var expr", K(ret));
} else if (is_regr_expr_type(win_expr->get_agg_expr()->get_expr_type()) &&
OB_FAIL(expand_regr_expr(ctx, win_expr->get_agg_expr(), replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr exprs", K(ret));
} else if (is_keep_aggr_type(win_expr->get_agg_expr()->get_expr_type()) &&
OB_FAIL(expand_keep_aggr_expr(ctx, win_expr->get_agg_expr(), replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand keep aggr exprs", K(ret));
} else if (is_common_aggr_type(win_expr->get_agg_expr()->get_expr_type()) &&
OB_FAIL(expand_common_aggr_expr(ctx, win_expr->get_agg_expr(), replace_expr, new_aggr_items))) {
LOG_WARN("failed to common aggr exprs", K(ret));
} else if (OB_ISNULL(replace_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(replace_expr), K(win_expr->get_agg_expr()->get_expr_type()));
} else if (OB_FAIL(replace_expr->formalize(ctx->session_info_))) {
LOG_WARN("failed to formalize", K(ret));
} else if (OB_FAIL(ObRawExprUtils::process_window_complex_agg_expr(
*ctx->expr_factory_, replace_expr->get_expr_type(), win_expr, replace_expr, &new_win_exprs))) {
LOG_WARN("failed to process window complex agg expr", K(ret));
} else if (replace_expr->is_aggr_expr() &&
OB_FAIL(replace_exprs.push_back(new_win_exprs.at(new_win_exprs.count() - 1)))) {
LOG_WARN("failed to push back expr", K(ret));
} else if (!replace_expr->is_aggr_expr() && OB_FAIL(replace_exprs.push_back(replace_expr))) {
LOG_WARN("failed to push back expr", K(ret));
} else { /*do nothing*/
}
}
if (OB_SUCC(ret)) {
if (OB_FAIL(add_win_exprs(select_stmt, replace_exprs, new_win_exprs))) {
LOG_WARN("failed to win exprs", K(ret));
} else if (OB_FAIL(select_stmt->replace_inner_stmt_expr(candi_win_items, replace_exprs))) {
LOG_WARN("failed to replace stmt expr");
} else {
trans_happened = true;
}
}
}
return ret;
}
int ObExpandAggregateUtils::add_linear_inter_expr(ObDMLStmt* stmt, ObTransformerCtx* ctx, bool& trans_happened)
{
int ret = OB_SUCCESS;
ObSEArray<ObAggFunRawExpr*, 4> aggr_exprs;
ObSEArray<ObWinFunRawExpr*, 4> win_exprs;
trans_happened = false;
if (OB_ISNULL(stmt) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("table item is null", K(ret), K(stmt), K(ctx));
} else if (!ctx->session_info_->use_static_typing_engine()) {
/* do nothing*/
} else if (stmt->is_select_stmt() &&
OB_FAIL(append(aggr_exprs, static_cast<ObSelectStmt*>(stmt)->get_aggr_items()))) {
LOG_WARN("failed to append aggr exprs", K(ret));
} else if (stmt->is_select_stmt() &&
OB_FAIL(append(win_exprs, static_cast<ObSelectStmt*>(stmt)->get_window_func_exprs()))) {
LOG_WARN("failed to append win exprs", K(ret));
} else if ((stmt->is_delete_stmt() || stmt->is_update_stmt() || stmt->is_merge_stmt() || stmt->is_insert_stmt()) &&
OB_FAIL(append(aggr_exprs, static_cast<ObDelUpdStmt*>(stmt)->get_returning_aggr_items()))) {
LOG_WARN("failed to append aggr exprs", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < aggr_exprs.count(); ++i) {
if (OB_ISNULL(aggr_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_exprs.at(i)));
} else if (!is_medain_percentile_aggr_type(aggr_exprs.at(i)->get_expr_type())) {
/* do nothing */
} else if (OB_FAIL(add_linear_inter_expr(ctx, aggr_exprs.at(i)))) {
LOG_WARN("failed to add linear inter expr", K(ret), K(aggr_exprs.at(i)));
} else {
trans_happened = true;
}
}
for (int64_t i = 0; OB_SUCC(ret) && i < win_exprs.count(); ++i) {
ObWinFunRawExpr* win_expr = win_exprs.at(i);
ObAggFunRawExpr* aggr_expr = NULL;
if (OB_ISNULL(win_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(win_expr));
} else if (OB_ISNULL(aggr_expr = win_expr->get_agg_expr()) ||
!is_medain_percentile_aggr_type(aggr_expr->get_expr_type())) {
/* do nothing */
} else if (OB_FAIL(add_linear_inter_expr(ctx, aggr_expr))) {
LOG_WARN("failed to add linear inter expr", K(ret), K(aggr_expr));
} else {
trans_happened = true;
}
}
}
return ret;
}
int ObExpandAggregateUtils::add_linear_inter_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr)
{
int ret = OB_SUCCESS;
ObRawExpr* obj_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(
T_FUN_MEDIAN != aggr_expr->get_expr_type() && T_FUN_GROUP_PERCENTILE_CONT != aggr_expr->get_expr_type()) ||
OB_UNLIKELY(1 != aggr_expr->get_real_param_exprs().count() || 1 != aggr_expr->get_order_items().count()) ||
OB_ISNULL(obj_expr = aggr_expr->get_order_items().at(0).expr_)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else if (OB_NOT_NULL(aggr_expr->get_linear_inter_expr())) {
/* do nothing */
} else {
ObRawExpr* minus_expr = NULL;
ObRawExpr* mul_expr = NULL;
ObRawExpr* add_expr = NULL;
ObVarRawExpr* right_expr = NULL;
ObVarRawExpr* left_expr = NULL;
ObVarRawExpr* factor_expr = NULL;
const ObExprResType& obj_result_type = obj_expr->get_result_type();
ObExprResType factor_result_type(*ctx->allocator_);
factor_result_type.set_number();
factor_result_type.set_scale(ObAccuracy::DDL_DEFAULT_ACCURACY2[ORACLE_MODE][ObNumberType].get_scale());
factor_result_type.set_precision(ObAccuracy::DDL_DEFAULT_ACCURACY2[ORACLE_MODE][ObNumberType].get_precision());
if (OB_FAIL(ObRawExprUtils::build_variable_expr(*ctx->expr_factory_, obj_result_type, right_expr))) {
LOG_WARN("failed to build const empty op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_variable_expr(*ctx->expr_factory_, obj_result_type, left_expr))) {
LOG_WARN("failed to build const empty op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_variable_expr(*ctx->expr_factory_, factor_result_type, factor_expr))) {
LOG_WARN("failed to build const empty op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, right_expr, left_expr, minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, factor_expr, minus_expr, mul_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_ADD, mul_expr, left_expr, add_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(add_expr->formalize(ctx->session_info_))) {
LOG_WARN("formalize linear inter expr failed", K(ret));
} else {
aggr_expr->set_linear_inter_expr(add_expr);
}
}
return ret;
}
// Premise: (expr1, expr2) neither expr is NULL
// T_FUN_COVAR_POP == node->type_: (SUM(expr1 * expr2) - SUM(expr2) * SUM(expr1) / count(expr1 * expr2)) / count(expr1 *
// expr2) T_FUN_COVAR_SAMP== node->type_: (SUM(expr1 * expr2) - SUM(expr1) * SUM(expr2) / count(expr1 * expr2)) /
// (count(expr1 * expr2)-1)
int ObExpandAggregateUtils::expand_covar_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr1 = NULL;
ObRawExpr* parma_expr2 = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(!is_covar_expr_type(aggr_expr->get_expr_type()) || aggr_expr->get_real_param_exprs().count() != 2) ||
OB_ISNULL(parma_expr1 = aggr_expr->get_real_param_exprs().at(0)) ||
OB_ISNULL(parma_expr2 = aggr_expr->get_real_param_exprs().at(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObRawExpr* case_when_expr1 = NULL;
ObRawExpr* case_when_expr2 = NULL;
ObRawExpr* multi_expr = NULL;
ObRawExpr* multi_sum_expr = NULL;
ObRawExpr* and_expr = NULL;
ObAggFunRawExpr* sum_expr1 = NULL;
ObAggFunRawExpr* sum_expr2 = NULL;
ObAggFunRawExpr* sum_product_expr = NULL;
ObAggFunRawExpr* count_product_expr = NULL;
ObRawExpr* div_expr = NULL;
ObRawExpr* minus_expr = NULL;
ObRawExpr* div_sum_expr = NULL;
if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr1, case_when_expr1))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr2, case_when_expr2))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, parma_expr1, parma_expr2, multi_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, case_when_expr1, sum_expr1))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_expr1))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, case_when_expr2, sum_expr2))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_expr2))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, sum_expr1, sum_expr2, multi_sum_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, multi_expr, sum_product_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_product_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, multi_expr, count_product_expr))) {
LOG_WARN("failed to build count expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, count_product_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, multi_sum_expr, count_product_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, sum_product_expr, div_expr, minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (aggr_expr->get_expr_type() == T_FUN_COVAR_POP) {
if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, minus_expr, count_product_expr, div_sum_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
sum_expr1->set_expr_level(aggr_expr->get_expr_level());
sum_expr2->set_expr_level(aggr_expr->get_expr_level());
sum_product_expr->set_expr_level(aggr_expr->get_expr_level());
count_product_expr->set_expr_level(aggr_expr->get_expr_level());
replace_expr = div_sum_expr;
}
} else {
ObRawExpr* null_expr = NULL;
ObConstRawExpr* one_expr = NULL;
ObConstRawExpr* zero_expr = NULL;
ObRawExpr* minus_expr2 = NULL;
ObRawExpr* ne_expr = NULL;
ObRawExpr* case_when_expr = NULL;
if (OB_FAIL(OB_FAIL(ObRawExprUtils::build_null_expr(*ctx->expr_factory_, null_expr)))) {
LOG_WARN("failed to build null expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, ObIntType, 1, one_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, ObIntType, 0, zero_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, count_product_expr, one_expr, minus_expr2))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_NE, minus_expr2, zero_expr, ne_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(
*ctx->expr_factory_, ne_expr, minus_expr2, null_expr, case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, minus_expr, case_when_expr, div_sum_expr))) {
LOG_WARN("failed to common binary op expr", K(ret));
} else {
sum_expr1->set_expr_level(aggr_expr->get_expr_level());
sum_expr2->set_expr_level(aggr_expr->get_expr_level());
sum_product_expr->set_expr_level(aggr_expr->get_expr_level());
count_product_expr->set_expr_level(aggr_expr->get_expr_level());
replace_expr = div_sum_expr;
}
}
}
return ret;
}
// Premise: (expr1, expr2) neither expr is NULL
// COVAR_POP(expr1, expr2) / (STDDEV_POP(expr1) * STDDEV_POP(expr2))
int ObExpandAggregateUtils::expand_corr_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr1 = NULL;
ObRawExpr* parma_expr2 = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_CORR || aggr_expr->get_real_param_exprs().count() != 2) ||
OB_ISNULL(parma_expr1 = aggr_expr->get_real_param_exprs().at(0)) ||
OB_ISNULL(parma_expr2 = aggr_expr->get_real_param_exprs().at(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected error", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* covar_pop_expr = NULL;
ObAggFunRawExpr* stddev_pop_expr1 = NULL;
ObAggFunRawExpr* stddev_pop_expr2 = NULL;
ObRawExpr* null_expr = NULL;
ObRawExpr* case_when_expr1 = NULL;
ObRawExpr* case_when_expr2 = NULL;
ObRawExpr* multi_stddev_expr = NULL;
ObRawExpr* left_multi_expr = NULL;
ObRawExpr* right_multi_expr = NULL;
ObRawExpr* div_expr = NULL;
ObRawExpr* left_div_expr = NULL;
ObRawExpr* ne_expr = NULL;
ObRawExpr* case_when_expr = NULL;
ObConstRawExpr* zero_expr = NULL;
if (OB_FAIL(OB_FAIL(ObRawExprUtils::build_null_expr(*ctx->expr_factory_, null_expr)))) {
LOG_WARN("failed to build null expr", K(ret));
} else if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr1, case_when_expr1))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr2, case_when_expr2))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_STDDEV_POP, stddev_pop_expr1))) {
LOG_WARN("create ObOpRawExpr failed", K(ret));
} else if (OB_FAIL(stddev_pop_expr1->add_real_param_expr(case_when_expr1))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
stddev_pop_expr1->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_stddev_pop_expr(ctx, stddev_pop_expr1, left_multi_expr, new_aggr_items))) {
LOG_WARN("fail to expand stddev pop expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_STDDEV_POP, stddev_pop_expr2))) {
LOG_WARN("create ObOpRawExpr failed", K(ret));
} else if (OB_FAIL(stddev_pop_expr2->add_real_param_expr(case_when_expr2))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
stddev_pop_expr2->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_stddev_pop_expr(ctx, stddev_pop_expr2, right_multi_expr, new_aggr_items))) {
LOG_WARN("fail to expand stddev pop expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, left_multi_expr, right_multi_expr, multi_stddev_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, ObIntType, 0, zero_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_NE, multi_stddev_expr, zero_expr, ne_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(
*ctx->expr_factory_, ne_expr, multi_stddev_expr, null_expr, case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_COVAR_POP, covar_pop_expr))) {
LOG_WARN("create ObOpRawExpr failed", K(ret));
} else if (OB_FAIL(covar_pop_expr->add_real_param_expr(parma_expr1))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else if (OB_FAIL(covar_pop_expr->add_real_param_expr(parma_expr2))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
covar_pop_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_covar_expr(ctx, covar_pop_expr, left_div_expr, new_aggr_items))) {
LOG_WARN("failed to expand covar expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, left_div_expr, case_when_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
replace_expr = div_expr;
}
}
}
}
}
return ret;
}
int ObExpandAggregateUtils::extract_candi_aggr(
ObDMLStmt* stmt, ObIArray<ObRawExpr*>& candi_aggr_items, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(stmt));
} else {
ObSEArray<ObAggFunRawExpr*, 4> aggr_items;
if (stmt->is_select_stmt() && OB_FAIL(append(aggr_items, static_cast<ObSelectStmt*>(stmt)->get_aggr_items()))) {
LOG_WARN("failed to append aggr items", K(ret));
} else if (!stmt->is_select_stmt() &&
OB_FAIL(append(aggr_items, static_cast<ObDelUpdStmt*>(stmt)->get_returning_aggr_items()))) {
LOG_WARN("failed to append aggr items", K(ret));
} else {
for (int64_t i = 0; OB_SUCC(ret) && i < aggr_items.count(); ++i) {
if (OB_ISNULL(aggr_items.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_items.at(i)));
} else if (is_valid_aggr_type(aggr_items.at(i)->get_expr_type())) {
if (OB_FAIL(candi_aggr_items.push_back(aggr_items.at(i)))) {
LOG_WARN("failed to push back aggr items", K(ret));
} else { /*do nothing*/
}
} else if (OB_FAIL(new_aggr_items.push_back(aggr_items.at(i)))) {
LOG_WARN("failed to push back aggr items", K(ret));
}
}
}
}
return ret;
}
int ObExpandAggregateUtils::extract_candi_window_aggr(
ObSelectStmt* select_stmt, ObIArray<ObRawExpr*>& candi_win_items, ObIArray<ObWinFunRawExpr*>& new_win_exprs)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(select_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(select_stmt));
} else {
ObIArray<ObWinFunRawExpr*>& win_exprs = select_stmt->get_window_func_exprs();
for (int64_t i = 0; OB_SUCC(ret) && i < win_exprs.count(); ++i) {
ObWinFunRawExpr* win_expr = win_exprs.at(i);
if (OB_ISNULL(win_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(win_expr));
} else if (win_expr->get_agg_expr() != NULL && is_valid_aggr_type(win_expr->get_agg_expr()->get_expr_type())) {
if (OB_FAIL(candi_win_items.push_back(win_expr))) {
LOG_WARN("failed to push back win expr", K(ret));
} else { /*do nothing*/
}
} else if (OB_FAIL(new_win_exprs.push_back(win_expr))) {
LOG_WARN("failed to push back win expr", K(ret));
}
}
}
return ret;
}
int ObExpandAggregateUtils::add_aggr_item(ObIArray<ObAggFunRawExpr*>& new_aggr_items, ObAggFunRawExpr*& aggr_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(aggr_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr));
} else {
int64_t i = 0;
for (; OB_SUCC(ret) && i < new_aggr_items.count(); ++i) {
if (OB_ISNULL(new_aggr_items.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(new_aggr_items.at(i)));
} else if (aggr_expr->same_as(*new_aggr_items.at(i))) {
aggr_expr = new_aggr_items.at(i);
break;
} else { /*do nothing*/
}
}
if (OB_SUCC(ret) && i == new_aggr_items.count()) {
if (OB_FAIL(new_aggr_items.push_back(aggr_expr))) {
LOG_WARN("failed to push back aggr expr", K(ret));
}
}
}
return ret;
}
// T_FUN_VAR_POP == node->type_: (SUM(expr*expr) - SUM(expr)* SUM(expr)/ COUNT(expr)) / COUNT(expr)
// T_FUN_VAR_SAMP== node->type_: (SUM(expr*expr) - SUM(expr)* SUM(expr)/ COUNT(expr)) / (COUNT(expr) - 1)
int ObExpandAggregateUtils::expand_var_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr, ObRawExpr*& replace_expr,
ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(!is_var_expr_type(aggr_expr->get_expr_type()) || aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else if (share::is_mysql_mode() && aggr_expr->get_expr_type() == T_FUN_VAR_POP) {
if (OB_FAIL(expand_mysql_variance_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand mysql variance expr", K(ret));
} else { /*do nothing*/
}
} else {
ObRawExpr* multi_expr = NULL;
ObRawExpr* multi_sum_expr = NULL;
ObAggFunRawExpr* sum_expr = NULL;
ObRawExpr* cast_sum_expr = NULL;
ObAggFunRawExpr* sum_product_expr = NULL;
ObRawExpr* cast_sum_product_expr = NULL;
ObAggFunRawExpr* count_expr = NULL;
ObRawExpr* div_expr = NULL;
ObRawExpr* minus_expr = NULL;
ObRawExpr* div_minus_expr = NULL;
ObExprResType dst_type;
dst_type.set_number();
dst_type.set_scale(ObAccuracy::MAX_ACCURACY2[MYSQL_MODE][ObNumberType].get_scale());
dst_type.set_precision(ObAccuracy::MAX_ACCURACY2[MYSQL_MODE][ObNumberType].get_precision());
if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, parma_expr, parma_expr, multi_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, parma_expr, sum_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_expr))) {
LOG_WARN("failed to push back aggr item", K(ret));
} else if (share::is_mysql_mode() && OB_FAIL(add_cast_expr(ctx, sum_expr, dst_type, cast_sum_expr))) {
LOG_WARN("failed to add cast expr", K(ret));
} else if (share::is_mysql_mode() &&
OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, cast_sum_expr, cast_sum_expr, multi_sum_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (share::is_oracle_mode() && OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, sum_expr, sum_expr, multi_sum_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, multi_expr, sum_product_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_product_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (share::is_mysql_mode() &&
OB_FAIL(add_cast_expr(ctx, sum_product_expr, dst_type, cast_sum_product_expr))) {
LOG_WARN("failed to add cast expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, parma_expr, count_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, count_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, multi_sum_expr, count_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (share::is_mysql_mode() &&
OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, cast_sum_product_expr, div_expr, minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (share::is_oracle_mode() &&
OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, sum_product_expr, div_expr, minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (aggr_expr->get_expr_type() == T_FUN_VAR_POP) {
if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, minus_expr, count_expr, div_minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
sum_expr->set_expr_level(aggr_expr->get_expr_level());
sum_product_expr->set_expr_level(aggr_expr->get_expr_level());
count_expr->set_expr_level(aggr_expr->get_expr_level());
replace_expr = div_minus_expr;
}
} else {
ObConstRawExpr* one_expr = NULL;
ObConstRawExpr* zero_expr = NULL;
ObRawExpr* minus_expr2 = NULL;
ObRawExpr* ne_expr = NULL;
ObRawExpr* case_when_expr = NULL;
ObRawExpr* null_expr = NULL;
if (OB_FAIL(OB_FAIL(ObRawExprUtils::build_null_expr(*ctx->expr_factory_, null_expr)))) {
LOG_WARN("failed to build null expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, ObIntType, 1, one_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, ObIntType, 0, zero_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, count_expr, one_expr, minus_expr2))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_NE, minus_expr2, zero_expr, ne_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(
*ctx->expr_factory_, ne_expr, minus_expr2, null_expr, case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, minus_expr, case_when_expr, div_minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
sum_expr->set_expr_level(aggr_expr->get_expr_level());
sum_product_expr->set_expr_level(aggr_expr->get_expr_level());
count_expr->set_expr_level(aggr_expr->get_expr_level());
replace_expr = div_minus_expr;
}
}
}
return ret;
}
int ObExpandAggregateUtils::expand_regr_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(!is_regr_expr_type(aggr_expr->get_expr_type()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else if (aggr_expr->get_expr_type() == T_FUN_REGR_SLOPE) {
if (OB_FAIL(expand_regr_slope_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr slope expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_REGR_INTERCEPT) {
if (OB_FAIL(expand_regr_intercept_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr intercept expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_REGR_COUNT) {
if (OB_FAIL(expand_regr_count_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr count expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_REGR_R2) {
if (OB_FAIL(expand_regr_r2_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr r2 expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_REGR_AVGX || aggr_expr->get_expr_type() == T_FUN_REGR_AVGY) {
if (OB_FAIL(expand_regr_avg_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr avg expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_REGR_SXX || aggr_expr->get_expr_type() == T_FUN_REGR_SYY ||
aggr_expr->get_expr_type() == T_FUN_REGR_SXY) {
if (OB_FAIL(expand_regr_s_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr s expr", K(ret));
}
} else { /*do nothing*/
}
return ret;
}
// Premise: (expr1, expr2) neither expr is NULL
// REGR_SLOPE(expr1, expr2) = COVAR_POP(expr1, expr2) / VAR_POP(expr2)
int ObExpandAggregateUtils::expand_regr_slope_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr1 = NULL;
ObRawExpr* parma_expr2 = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_REGR_SLOPE || aggr_expr->get_real_param_exprs().count() != 2) ||
OB_ISNULL(parma_expr1 = aggr_expr->get_real_param_exprs().at(0)) ||
OB_ISNULL(parma_expr2 = aggr_expr->get_real_param_exprs().at(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* covar_pop_expr = NULL;
ObAggFunRawExpr* var_pop_expr = NULL;
ObConstRawExpr* zero_expr = NULL;
ObRawExpr* null_expr = NULL;
ObRawExpr* ne_expr = NULL;
ObRawExpr* case_when_expr = NULL;
ObRawExpr* left_div_expr = NULL;
ObRawExpr* right_div_expr = NULL;
ObRawExpr* div_expr = NULL;
ObRawExpr* right_div_case_when_expr = NULL;
if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_COVAR_POP, covar_pop_expr))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(covar_pop_expr->add_real_param_expr(parma_expr1))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else if (OB_FAIL(covar_pop_expr->add_real_param_expr(parma_expr2))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
covar_pop_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_covar_expr(ctx, covar_pop_expr, left_div_expr, new_aggr_items))) {
LOG_WARN("failed to expand covar expr", K(ret));
} else if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr2, case_when_expr))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_VAR_POP, var_pop_expr))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(var_pop_expr->add_real_param_expr(case_when_expr))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
var_pop_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_var_expr(ctx, var_pop_expr, right_div_expr, new_aggr_items))) {
LOG_WARN("failed to expand var expr", K(ret));
} else if (OB_FAIL(OB_FAIL(ObRawExprUtils::build_null_expr(*ctx->expr_factory_, null_expr)))) {
LOG_WARN("failed to build null expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, ObIntType, 0, zero_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_NE, right_div_expr, zero_expr, ne_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(
*ctx->expr_factory_, ne_expr, right_div_expr, null_expr, right_div_case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, left_div_expr, right_div_case_when_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
replace_expr = div_expr;
}
}
}
}
return ret;
}
// Premise: (expr1, expr2) neither expr is NULL
// REGR_INTERCEPT(expr1, expr2) = AVG(expr1) - REGR_SLOPE(expr1, expr2) * AVG(expr2)
int ObExpandAggregateUtils::expand_regr_intercept_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr1 = NULL;
ObRawExpr* parma_expr2 = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(
aggr_expr->get_expr_type() != T_FUN_REGR_INTERCEPT || aggr_expr->get_real_param_exprs().count() != 2) ||
OB_ISNULL(parma_expr1 = aggr_expr->get_real_param_exprs().at(0)) ||
OB_ISNULL(parma_expr2 = aggr_expr->get_real_param_exprs().at(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* regr_slope_expr = NULL;
ObAggFunRawExpr* sum_expr1 = NULL;
ObAggFunRawExpr* sum_expr2 = NULL;
ObAggFunRawExpr* count_expr1 = NULL;
ObAggFunRawExpr* count_expr2 = NULL;
ObRawExpr* case_when_expr1 = NULL;
ObRawExpr* case_when_expr2 = NULL;
ObRawExpr* minus_expr = NULL;
ObRawExpr* multi_expr = NULL;
ObRawExpr* div_expr1 = NULL;
ObRawExpr* div_expr2 = NULL;
ObRawExpr* left_minus_expr = NULL;
ObRawExpr* right_minus_expr = NULL;
ObRawExpr* left_multi_expr = NULL;
if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr1, case_when_expr1))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr2, case_when_expr2))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_REGR_SLOPE, regr_slope_expr))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(regr_slope_expr->add_real_param_expr(parma_expr1))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else if (OB_FAIL(regr_slope_expr->add_real_param_expr(parma_expr2))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
regr_slope_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_regr_slope_expr(ctx, regr_slope_expr, left_multi_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr slope expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, case_when_expr1, sum_expr1))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_expr1))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, case_when_expr1, count_expr1))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, count_expr1))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, case_when_expr2, sum_expr2))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_expr2))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, case_when_expr2, count_expr2))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, count_expr2))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, sum_expr1, count_expr1, div_expr1))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, sum_expr2, count_expr2, div_expr2))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, left_multi_expr, div_expr2, multi_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, div_expr1, multi_expr, minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
sum_expr1->set_expr_level(aggr_expr->get_expr_level());
sum_expr2->set_expr_level(aggr_expr->get_expr_level());
count_expr1->set_expr_level(aggr_expr->get_expr_level());
count_expr2->set_expr_level(aggr_expr->get_expr_level());
replace_expr = minus_expr;
}
}
}
return ret;
}
// Premise: (expr1, expr2) neither expr is NULL
// REGR_COUNT(expr1, expr2) = COUNT(case expr1 is not null and c2 is not null then expr1 else null end);
int ObExpandAggregateUtils::expand_regr_count_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr1 = NULL;
ObRawExpr* parma_expr2 = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_REGR_COUNT || aggr_expr->get_real_param_exprs().count() != 2) ||
OB_ISNULL(parma_expr1 = aggr_expr->get_real_param_exprs().at(0)) ||
OB_ISNULL(parma_expr2 = aggr_expr->get_real_param_exprs().at(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* count_expr = NULL;
ObRawExpr* case_when_expr = NULL;
if (OB_FAIL(
build_special_case_when_expr(*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr1, case_when_expr))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, case_when_expr, count_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, count_expr))) {
LOG_WARN("failed to push back aggr item");
} else {
count_expr->set_expr_level(aggr_expr->get_expr_level());
replace_expr = count_expr;
}
}
return ret;
}
// Premise: (expr1, expr2) neither expr is NULL
// REGR_R2(expr1, expr2) = if VAR_POP(expr2) = 0 ==> NULL
// if VAR_POP(expr1) = 0 and VAR_POP(expr2) != 0 ==> 1
// if VAR_POP(expr1) > 0 and VAR_POP(expr2) != 0 ==> POWER(CORR(expr1,expr),2)
// ==> case when VAR_POP(expr2) = 0 then NULL else (case when VAR_POP(expr1) = 0 then 1 else
// POWER(CORR(expr1,expr2),2));
int ObExpandAggregateUtils::expand_regr_r2_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr1 = NULL;
ObRawExpr* parma_expr2 = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_REGR_R2 || aggr_expr->get_real_param_exprs().count() != 2) ||
OB_ISNULL(parma_expr1 = aggr_expr->get_real_param_exprs().at(0)) ||
OB_ISNULL(parma_expr2 = aggr_expr->get_real_param_exprs().at(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* var_pop_expr1 = NULL;
ObAggFunRawExpr* var_pop_expr2 = NULL;
ObAggFunRawExpr* corr_expr = NULL;
ObRawExpr* case_when_expr1 = NULL;
ObRawExpr* case_when_expr2 = NULL;
ObConstRawExpr* one_expr = NULL;
ObConstRawExpr* two_expr = NULL;
ObConstRawExpr* zero_expr = NULL;
ObRawExpr* ne_expr = NULL;
ObRawExpr* case_when_expr = NULL;
ObRawExpr* null_expr = NULL;
ObRawExpr* eq_left_expr1 = NULL;
ObRawExpr* eq_left_expr2 = NULL;
ObRawExpr* eq_expr1 = NULL;
ObRawExpr* eq_expr2 = NULL;
ObRawExpr* power_param_expr = NULL;
ObSysFunRawExpr* power_expr = NULL;
if (OB_FAIL(OB_FAIL(ObRawExprUtils::build_null_expr(*ctx->expr_factory_, null_expr)))) {
LOG_WARN("failed to build null expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, ObIntType, 1, one_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, ObIntType, 2, two_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*ctx->expr_factory_, ObIntType, 0, zero_expr))) {
LOG_WARN("failed to build const int expr", K(ret));
} else if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr1, case_when_expr1))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, parma_expr2, case_when_expr2))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_VAR_POP, var_pop_expr1))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(var_pop_expr1->add_real_param_expr(case_when_expr1))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
var_pop_expr1->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_var_expr(ctx, var_pop_expr1, eq_left_expr1, new_aggr_items))) {
LOG_WARN("failed to expand var expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_VAR_POP, var_pop_expr2))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(var_pop_expr2->add_real_param_expr(case_when_expr2))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
var_pop_expr2->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_var_expr(ctx, var_pop_expr2, eq_left_expr2, new_aggr_items))) {
LOG_WARN("failed to expand var expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_CORR, corr_expr))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(corr_expr->add_real_param_expr(parma_expr1))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else if (OB_FAIL(corr_expr->add_real_param_expr(parma_expr2))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
corr_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_corr_expr(ctx, corr_expr, power_param_expr, new_aggr_items))) {
LOG_WARN("failed to expand corr expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_SYS_POWER, power_expr))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(power_expr->add_param_expr(power_param_expr))) {
LOG_WARN("failed to add param expr", K(ret));
} else if (OB_FAIL(power_expr->add_param_expr(two_expr))) {
LOG_WARN("failed to add param expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_EQ, eq_left_expr1, zero_expr, eq_expr1))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(
*ctx->expr_factory_, eq_expr1, one_expr, power_expr, case_when_expr2))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_EQ, eq_left_expr2, zero_expr, eq_expr2))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(
*ctx->expr_factory_, eq_expr2, null_expr, case_when_expr2, case_when_expr1))) {
LOG_WARN("failed to build case when expr", K(ret));
} else {
replace_expr = case_when_expr1;
}
}
}
}
}
return ret;
}
// Premise: (expr1, expr2) neither expr is NULL
// REGR_AVGX(expr1, expr2) = AVG(expr2);
// REGR_AVGY(expr1, expr2) = AVG(expr1);
int ObExpandAggregateUtils::expand_regr_avg_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr1 = NULL;
ObRawExpr* parma_expr2 = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY((aggr_expr->get_expr_type() != T_FUN_REGR_AVGX && aggr_expr->get_expr_type() != T_FUN_REGR_AVGY) ||
aggr_expr->get_real_param_exprs().count() != 2) ||
OB_ISNULL(parma_expr1 = aggr_expr->get_real_param_exprs().at(0)) ||
OB_ISNULL(parma_expr2 = aggr_expr->get_real_param_exprs().at(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* sum_expr = NULL;
ObAggFunRawExpr* count_expr = NULL;
ObRawExpr* div_expr = NULL;
ObRawExpr* case_when_expr = NULL;
ObRawExpr* then_expr = aggr_expr->get_expr_type() == T_FUN_REGR_AVGX ? parma_expr2 : parma_expr1;
if (OB_FAIL(
build_special_case_when_expr(*ctx->expr_factory_, parma_expr1, parma_expr2, then_expr, case_when_expr))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, case_when_expr, sum_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, case_when_expr, count_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, count_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, sum_expr, count_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
sum_expr->set_expr_level(aggr_expr->get_expr_level());
count_expr->set_expr_level(aggr_expr->get_expr_level());
replace_expr = div_expr;
}
}
return ret;
}
// Premise: (expr1, expr2) neither expr is NULL
// REGR_SXX(expr1, expr2) = REGR_COUNT(expr1, expr2) * VAR_POP(expr2)
// REGR_SYY(expr1, expr2) = REGR_COUNT(expr1, expr2) * VAR_POP(expr1)
// REGR_SXY(expr1, expr2) = REGR_COUNT(expr1, expr2) * COVAR_POP(expr1, expr2)
int ObExpandAggregateUtils::expand_regr_s_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr1 = NULL;
ObRawExpr* parma_expr2 = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY((aggr_expr->get_expr_type() != T_FUN_REGR_SXX && aggr_expr->get_expr_type() != T_FUN_REGR_SYY &&
aggr_expr->get_expr_type() != T_FUN_REGR_SXY) ||
aggr_expr->get_real_param_exprs().count() != 2) ||
OB_ISNULL(parma_expr1 = aggr_expr->get_real_param_exprs().at(0)) ||
OB_ISNULL(parma_expr2 = aggr_expr->get_real_param_exprs().at(1))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* regr_count_expr = NULL;
ObAggFunRawExpr* var_pop_expr = NULL;
ObAggFunRawExpr* covar_pop_expr = NULL;
ObRawExpr* left_multi_expr = NULL;
ObRawExpr* right_multi_expr = NULL;
ObRawExpr* multi_expr = NULL;
ObRawExpr* case_when_expr = NULL;
if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_REGR_COUNT, regr_count_expr))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(regr_count_expr->add_real_param_expr(parma_expr1))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else if (OB_FAIL(regr_count_expr->add_real_param_expr(parma_expr2))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
regr_count_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_regr_count_expr(ctx, regr_count_expr, left_multi_expr, new_aggr_items))) {
LOG_WARN("failed to expand regr count expr", K(ret));
} else if (aggr_expr->get_expr_type() == T_FUN_REGR_SXX || aggr_expr->get_expr_type() == T_FUN_REGR_SYY) {
ObRawExpr* then_expr = aggr_expr->get_expr_type() == T_FUN_REGR_SXX ? parma_expr2 : parma_expr1;
if (OB_FAIL(build_special_case_when_expr(
*ctx->expr_factory_, parma_expr1, parma_expr2, then_expr, case_when_expr))) {
LOG_WARN("failed to build special case when expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_VAR_POP, var_pop_expr))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(var_pop_expr->add_real_param_expr(case_when_expr))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
var_pop_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_var_expr(ctx, var_pop_expr, right_multi_expr, new_aggr_items))) {
LOG_WARN("failed to expand var expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, left_multi_expr, right_multi_expr, multi_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
replace_expr = multi_expr;
}
}
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_COVAR_POP, covar_pop_expr))) {
LOG_WARN("failed to create expr", K(ret));
} else if (OB_FAIL(covar_pop_expr->add_real_param_expr(parma_expr1))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else if (OB_FAIL(covar_pop_expr->add_real_param_expr(parma_expr2))) {
LOG_WARN("fail to add param expr to agg expr", K(ret));
} else {
covar_pop_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_covar_expr(ctx, covar_pop_expr, right_multi_expr, new_aggr_items))) {
LOG_WARN("failed to expand covar expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, left_multi_expr, right_multi_expr, multi_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
replace_expr = multi_expr;
}
}
}
}
return ret;
}
bool ObExpandAggregateUtils::is_valid_aggr_type(const ObItemType aggr_type)
{
return aggr_type == T_FUN_CORR || aggr_type == T_FUN_COVAR_POP || aggr_type == T_FUN_COVAR_SAMP ||
aggr_type == T_FUN_VAR_POP || aggr_type == T_FUN_VAR_SAMP || aggr_type == T_FUN_REGR_SLOPE ||
aggr_type == T_FUN_REGR_INTERCEPT || aggr_type == T_FUN_REGR_COUNT || aggr_type == T_FUN_REGR_R2 ||
aggr_type == T_FUN_REGR_AVGX || aggr_type == T_FUN_REGR_AVGY || aggr_type == T_FUN_REGR_SXX ||
aggr_type == T_FUN_REGR_SYY || aggr_type == T_FUN_REGR_SXY || aggr_type == T_FUN_KEEP_AVG ||
aggr_type == T_FUN_KEEP_STDDEV || aggr_type == T_FUN_KEEP_VARIANCE || aggr_type == T_FUN_AVG ||
aggr_type == T_FUN_VARIANCE || aggr_type == T_FUN_STDDEV || aggr_type == T_FUN_STDDEV_POP ||
aggr_type == T_FUN_STDDEV_SAMP;
}
bool ObExpandAggregateUtils::is_regr_expr_type(const ObItemType aggr_type)
{
return aggr_type == T_FUN_REGR_SLOPE || aggr_type == T_FUN_REGR_INTERCEPT || aggr_type == T_FUN_REGR_COUNT ||
aggr_type == T_FUN_REGR_R2 || aggr_type == T_FUN_REGR_AVGX || aggr_type == T_FUN_REGR_AVGY ||
aggr_type == T_FUN_REGR_SXX || aggr_type == T_FUN_REGR_SYY || aggr_type == T_FUN_REGR_SXY;
}
int ObExpandAggregateUtils::build_special_case_when_expr(ObRawExprFactory& expr_factory, ObRawExpr* param_expr1,
ObRawExpr* param_expr2, ObRawExpr* then_expr, ObRawExpr*& case_when_expr)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(param_expr1) || OB_ISNULL(param_expr2) || OB_ISNULL(then_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("invalid argument", K(param_expr1), K(param_expr2), K(then_expr), K(ret));
} else {
ObRawExpr* null_expr = NULL;
ObRawExpr* false_expr = NULL;
ObRawExpr* is_not_expr1 = NULL;
ObRawExpr* is_not_expr2 = NULL;
ObRawExpr* and_expr = NULL;
case_when_expr = NULL;
if (OB_FAIL(OB_FAIL(ObRawExprUtils::build_null_expr(expr_factory, null_expr)))) {
LOG_WARN("failed to build null expr", K(ret));
} else if (ObRawExprUtils::build_const_bool_expr(&expr_factory, false_expr, false)) {
LOG_WARN("failed to build const bool expr", K(ret));
} else if (OB_FAIL(
ObRawExprUtils::build_is_not_expr(expr_factory, param_expr1, null_expr, false_expr, is_not_expr1))) {
LOG_WARN("failed to build is not expr", K(ret));
} else if (OB_FAIL(
ObRawExprUtils::build_is_not_expr(expr_factory, param_expr2, null_expr, false_expr, is_not_expr2))) {
LOG_WARN("failed to build is not expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
expr_factory, T_OP_AND, is_not_expr1, is_not_expr2, and_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(
expr_factory, and_expr, then_expr, null_expr, case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else { /*do nothing*/
}
}
return ret;
}
int ObExpandAggregateUtils::expand_keep_aggr_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(aggr_expr) || OB_UNLIKELY(!is_keep_aggr_type(aggr_expr->get_expr_type()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else if (aggr_expr->get_expr_type() == T_FUN_KEEP_AVG) {
if (OB_FAIL(expand_keep_avg_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand keep avg expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_KEEP_STDDEV) {
if (OB_FAIL(expand_keep_stddev_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand keep stddev expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_KEEP_VARIANCE) {
if (OB_FAIL(expand_keep_variance_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand keep variance expr", K(ret));
}
} else { /*do nothing*/
}
return ret;
}
/*avg(expr) keep(...) <==> sum(expr) keep(...) / count(expr) keep(...)
*/
int ObExpandAggregateUtils::expand_keep_avg_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_KEEP_AVG || aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* keep_sum_expr = NULL;
ObAggFunRawExpr* keep_count_expr = NULL;
ObRawExpr* div_expr = NULL;
const ObIArray<OrderItem>& order_items = aggr_expr->get_order_items();
if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_KEEP_SUM, parma_expr, keep_sum_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(append(keep_sum_expr->get_order_items_for_update(), order_items))) {
LOG_WARN("fail to append order items", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, keep_sum_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_KEEP_COUNT, parma_expr, keep_count_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(append(keep_count_expr->get_order_items_for_update(), order_items))) {
LOG_WARN("fail to append order items", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, keep_count_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, keep_sum_expr, keep_count_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
keep_sum_expr->set_expr_level(aggr_expr->get_expr_level());
keep_count_expr->set_expr_level(aggr_expr->get_expr_level());
replace_expr = div_expr;
}
}
return ret;
}
// variance:
// D(x) <==> if count(x) = 1 ==> (SUM(x*x) - SUM(x)* SUM(x)/ COUNT(x)) / (1) = 0
// if count(x) > 1 ==> var_samp(x) ==> (SUM(x*x) - SUM(x)* SUM(x)/ COUNT(x)) / (COUNT(x) - 1)
int ObExpandAggregateUtils::expand_keep_variance_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(
aggr_expr->get_expr_type() != T_FUN_KEEP_VARIANCE || aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObRawExpr* multi_expr = NULL;
ObRawExpr* multi_keep_sum_expr = NULL;
ObAggFunRawExpr* keep_sum_expr = NULL;
ObAggFunRawExpr* keep_sum_product_expr = NULL;
ObAggFunRawExpr* keep_count_expr = NULL;
ObRawExpr* div_expr = NULL;
ObRawExpr* minus_expr = NULL;
ObRawExpr* keep_count_minus_expr = NULL;
ObRawExpr* div_minus_expr = NULL;
ObConstRawExpr* one_expr = NULL;
ObRawExpr* eq_expr = NULL;
ObRawExpr* case_when_expr = NULL;
const ObIArray<OrderItem>& order_items = aggr_expr->get_order_items();
if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_KEEP_COUNT, parma_expr, keep_count_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(append(keep_count_expr->get_order_items_for_update(), order_items))) {
LOG_WARN("fail to append order items", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, keep_count_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_const_number_expr(
*ctx->expr_factory_, ObNumberType, number::ObNumber::get_positive_one(), one_expr))) {
LOG_WARN("failed to build const number expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_EQ, keep_count_expr, one_expr, eq_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, parma_expr, parma_expr, multi_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_KEEP_SUM, parma_expr, keep_sum_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(append(keep_sum_expr->get_order_items_for_update(), order_items))) {
LOG_WARN("fail to append order items", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, keep_sum_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, keep_sum_expr, keep_sum_expr, multi_keep_sum_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_KEEP_SUM, multi_expr, keep_sum_product_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(append(keep_sum_product_expr->get_order_items_for_update(), order_items))) {
LOG_WARN("fail to append order items", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, keep_sum_product_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, multi_keep_sum_expr, keep_count_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, keep_count_expr, one_expr, keep_count_minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, keep_sum_product_expr, div_expr, minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(
*ctx->expr_factory_, eq_expr, one_expr, keep_count_minus_expr, case_when_expr))) {
LOG_WARN("failed to build case when expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, minus_expr, case_when_expr, div_minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
keep_sum_expr->set_expr_level(aggr_expr->get_expr_level());
keep_sum_product_expr->set_expr_level(aggr_expr->get_expr_level());
keep_count_expr->set_expr_level(aggr_expr->get_expr_level());
replace_expr = div_minus_expr;
}
}
return ret;
}
// stddev(expr) <==> sqrt(variance(expr))
int ObExpandAggregateUtils::expand_keep_stddev_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_KEEP_STDDEV || aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObSysFunRawExpr* sqrt_expr = NULL;
ObRawExpr* sqrt_param_expr = NULL;
ObAggFunRawExpr* keep_variance_expr = NULL;
const ObIArray<OrderItem>& order_items = aggr_expr->get_order_items();
if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_KEEP_VARIANCE, parma_expr, keep_variance_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(append(keep_variance_expr->get_order_items_for_update(), order_items))) {
LOG_WARN("fail to append order items", K(ret));
} else {
keep_variance_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_keep_variance_expr(ctx, keep_variance_expr, sqrt_param_expr, new_aggr_items))) {
LOG_WARN("fail to expand keep variance expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_SYS_SQRT, sqrt_expr))) {
LOG_WARN("failed to crate sqrt expr", K(ret));
} else if (OB_ISNULL(sqrt_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("add expr is null", K(ret), K(sqrt_expr));
} else if (OB_FAIL(sqrt_expr->add_param_expr(sqrt_param_expr))) {
LOG_WARN("add text expr to add expr failed", K(ret));
} else {
ObString func_name = ObString::make_string("sqrt");
sqrt_expr->set_func_name(func_name);
replace_expr = sqrt_expr;
}
}
}
return ret;
}
int ObExpandAggregateUtils::expand_common_aggr_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(aggr_expr) || OB_UNLIKELY(!is_common_aggr_type(aggr_expr->get_expr_type()))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else if (aggr_expr->get_expr_type() == T_FUN_AVG) {
if (OB_FAIL(expand_avg_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand avg expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_STDDEV) {
if (OB_FAIL(expand_stddev_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand stddev expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_VARIANCE) {
if (share::is_oracle_mode() && OB_FAIL(expand_oracle_variance_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand oracle variance expr", K(ret));
} else if (share::is_mysql_mode() &&
OB_FAIL(expand_mysql_variance_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand mysql variance expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_STDDEV_POP) {
if (OB_FAIL(expand_stddev_pop_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand stddev expr", K(ret));
}
} else if (aggr_expr->get_expr_type() == T_FUN_STDDEV_SAMP) {
if (OB_FAIL(expand_stddev_samp_expr(ctx, aggr_expr, replace_expr, new_aggr_items))) {
LOG_WARN("failed to expand stddev expr", K(ret));
}
} else { /*do nothing*/
}
return ret;
}
/*avg(expr) keep(...) <==> sum(expr) keep(...) / count(expr) keep(...)
*/
int ObExpandAggregateUtils::expand_avg_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr, ObRawExpr*& replace_expr,
ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_AVG || aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* sum_expr = NULL;
ObAggFunRawExpr* count_expr = NULL;
ObRawExpr* div_expr = NULL;
if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, parma_expr, sum_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else {
sum_expr->set_expr_level(aggr_expr->get_expr_level());
sum_expr->set_param_distinct(aggr_expr->is_param_distinct());
if (OB_FAIL(add_aggr_item(new_aggr_items, sum_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, parma_expr, count_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else {
count_expr->set_expr_level(aggr_expr->get_expr_level());
count_expr->set_param_distinct(aggr_expr->is_param_distinct());
if (OB_FAIL(add_aggr_item(new_aggr_items, count_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_AGG_DIV, sum_expr, count_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
replace_expr = div_expr;
}
}
}
}
return ret;
}
// oracle variance:
// D(x) <==> if count(x) = 1 ==> (SUM(x*x) - SUM(x)* SUM(x)/ COUNT(x)) / (1) = 0
// if count(x) > 1 ==> var_samp(x) ==> (SUM(x*x) - SUM(x)* SUM(x)/ COUNT(x)) / (COUNT(x) - 1)
int ObExpandAggregateUtils::expand_oracle_variance_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_VARIANCE || aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObRawExpr* multi_expr = NULL;
ObRawExpr* multi_sum_expr = NULL;
ObAggFunRawExpr* sum_expr = NULL;
ObAggFunRawExpr* sum_product_expr = NULL;
ObAggFunRawExpr* count_expr = NULL;
ObRawExpr* div_expr = NULL;
ObRawExpr* minus_expr = NULL;
ObRawExpr* count_minus_expr = NULL;
ObRawExpr* div_minus_expr = NULL;
ObConstRawExpr* one_expr = NULL; // oracle mode count result type is number
ObRawExpr* eq_expr = NULL;
ObRawExpr* case_when_expr = NULL;
if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, parma_expr, count_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else {
count_expr->set_param_distinct(aggr_expr->is_param_distinct());
count_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(add_aggr_item(new_aggr_items, count_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_const_number_expr(
*ctx->expr_factory_, ObNumberType, number::ObNumber::get_positive_one(), one_expr))) {
LOG_WARN("failed to build const number expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_EQ, count_expr, one_expr, eq_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, parma_expr, parma_expr, multi_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, parma_expr, sum_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else {
sum_expr->set_expr_level(aggr_expr->get_expr_level());
sum_expr->set_param_distinct(aggr_expr->is_param_distinct());
if (OB_FAIL(add_aggr_item(new_aggr_items, sum_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MUL, sum_expr, sum_expr, multi_sum_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, multi_expr, sum_product_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else {
sum_product_expr->set_expr_level(aggr_expr->get_expr_level());
sum_product_expr->set_param_distinct(aggr_expr->is_param_distinct());
if (OB_FAIL(add_aggr_item(new_aggr_items, sum_product_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, multi_sum_expr, count_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, count_expr, one_expr, count_minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_MINUS, sum_product_expr, div_expr, minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_case_when_expr(
*ctx->expr_factory_, eq_expr, one_expr, count_minus_expr, case_when_expr))) {
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_DIV, minus_expr, case_when_expr, div_minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else {
replace_expr = div_minus_expr;
}
}
}
}
}
return ret;
}
// mysql variance: avg(expr1*expr1) - avg(expr1)*avg(expr1)
int ObExpandAggregateUtils::expand_mysql_variance_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY((aggr_expr->get_expr_type() != T_FUN_VARIANCE && aggr_expr->get_expr_type() != T_FUN_VAR_POP) ||
aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObAggFunRawExpr* sum_expr = NULL;
ObRawExpr* cast_sum_expr = NULL;
ObAggFunRawExpr* count_expr = NULL;
ObAggFunRawExpr* sum_product_expr = NULL;
ObRawExpr* cast_sum_product_expr = NULL;
ObAggFunRawExpr* count_product_expr = NULL;
ObRawExpr* minus_expr = NULL;
ObRawExpr* multi_expr = NULL;
ObRawExpr* multi_sum_expr = NULL;
ObRawExpr* multi_count_expr = NULL;
ObRawExpr* div_expr = NULL;
ObRawExpr* div_multi_expr = NULL;
ObRawExpr* cast_minus_expr = NULL;
ObExprResType dst_type;
dst_type.set_number();
dst_type.set_scale(ObAccuracy::MAX_ACCURACY2[MYSQL_MODE][ObNumberType].get_scale());
dst_type.set_precision(ObAccuracy::MAX_ACCURACY2[MYSQL_MODE][ObNumberType].get_precision());
ObExprResType result_type;
result_type.set_double();
result_type.set_scale(ObAccuracy(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET).get_scale());
result_type.set_precision(ObAccuracy(PRECISION_UNKNOWN_YET, SCALE_UNKNOWN_YET).get_precision());
if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_AGG_MUL, parma_expr, parma_expr, multi_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, parma_expr, sum_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(add_cast_expr(ctx, sum_expr, dst_type, cast_sum_expr))) {
LOG_WARN("failed to add cast expr");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_SUM, multi_expr, sum_product_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, sum_product_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(add_cast_expr(ctx, sum_product_expr, dst_type, cast_sum_product_expr))) {
LOG_WARN("failed to add cast expr");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, parma_expr, count_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, count_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_COUNT, multi_expr, count_product_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else if (OB_FAIL(add_aggr_item(new_aggr_items, count_product_expr))) {
LOG_WARN("failed to push back aggr item");
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_AGG_MUL, cast_sum_expr, cast_sum_expr, multi_sum_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_AGG_MUL, count_expr, count_expr, multi_count_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_AGG_DIV, multi_sum_expr, multi_count_expr, div_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_AGG_DIV, cast_sum_product_expr, count_product_expr, div_multi_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(ObRawExprUtils::build_common_binary_op_expr(
*ctx->expr_factory_, T_OP_AGG_MINUS, div_multi_expr, div_expr, minus_expr))) {
LOG_WARN("failed to build common binary op expr", K(ret));
} else if (OB_FAIL(add_cast_expr(ctx, minus_expr, result_type, cast_minus_expr))) {
LOG_WARN("failed to add cast expr");
} else {
sum_expr->set_expr_level(aggr_expr->get_expr_level());
count_expr->set_expr_level(aggr_expr->get_expr_level());
sum_product_expr->set_expr_level(aggr_expr->get_expr_level());
count_product_expr->set_expr_level(aggr_expr->get_expr_level());
replace_expr = cast_minus_expr;
}
}
return ret;
}
// stddev(expr) <==> sqrt(variance(expr))
int ObExpandAggregateUtils::expand_stddev_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_STDDEV || aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObSysFunRawExpr* sqrt_expr = NULL;
ObRawExpr* sqrt_param_expr = NULL;
ObAggFunRawExpr* variance_expr = NULL;
if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_VARIANCE, parma_expr, variance_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else {
variance_expr->set_expr_level(aggr_expr->get_expr_level());
variance_expr->set_param_distinct(aggr_expr->is_param_distinct());
if (share::is_oracle_mode() &&
OB_FAIL(expand_oracle_variance_expr(ctx, variance_expr, sqrt_param_expr, new_aggr_items))) {
LOG_WARN("fail to expand oracle variance expr", K(ret));
} else if (share::is_mysql_mode() &&
OB_FAIL(expand_mysql_variance_expr(ctx, variance_expr, sqrt_param_expr, new_aggr_items))) {
LOG_WARN("fail to expand mysql variance expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_SYS_SQRT, sqrt_expr))) {
LOG_WARN("failed to crate sqrt expr", K(ret));
} else if (OB_ISNULL(sqrt_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("add expr is null", K(ret), K(sqrt_expr));
} else if (OB_FAIL(sqrt_expr->add_param_expr(sqrt_param_expr))) {
LOG_WARN("add text expr to add expr failed", K(ret));
} else {
ObString func_name = ObString::make_string("sqrt");
sqrt_expr->set_func_name(func_name);
replace_expr = sqrt_expr;
}
}
}
return ret;
}
// stddev_pop(expr) <==> sqrt(var_pop(expr))
int ObExpandAggregateUtils::expand_stddev_pop_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_STDDEV_POP || aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObSysFunRawExpr* sqrt_expr = NULL;
ObRawExpr* sqrt_param_expr = NULL;
ObAggFunRawExpr* var_expr = NULL;
if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_VAR_POP, parma_expr, var_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else {
var_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_var_expr(ctx, var_expr, sqrt_param_expr, new_aggr_items))) {
LOG_WARN("fail to expand keep variance expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_SYS_SQRT, sqrt_expr))) {
LOG_WARN("failed to crate sqrt expr", K(ret));
} else if (OB_ISNULL(sqrt_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("add expr is null", K(ret), K(sqrt_expr));
} else if (OB_FAIL(sqrt_expr->add_param_expr(sqrt_param_expr))) {
LOG_WARN("add text expr to add expr failed", K(ret));
} else {
ObString func_name = ObString::make_string("sqrt");
sqrt_expr->set_func_name(func_name);
replace_expr = sqrt_expr;
}
}
}
return ret;
}
// stddev_samp(expr) <==> sqrt(var_samp(expr))
int ObExpandAggregateUtils::expand_stddev_samp_expr(ObTransformerCtx* ctx, ObAggFunRawExpr* aggr_expr,
ObRawExpr*& replace_expr, ObIArray<ObAggFunRawExpr*>& new_aggr_items)
{
int ret = OB_SUCCESS;
ObRawExpr* parma_expr = NULL;
if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx) || OB_ISNULL(ctx->expr_factory_) ||
OB_UNLIKELY(aggr_expr->get_expr_type() != T_FUN_STDDEV_SAMP || aggr_expr->get_real_param_exprs().count() != 1) ||
OB_ISNULL(parma_expr = aggr_expr->get_real_param_exprs().at(0))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(aggr_expr), K(ctx));
} else {
ObSysFunRawExpr* sqrt_expr = NULL;
ObRawExpr* sqrt_param_expr = NULL;
ObAggFunRawExpr* var_expr = NULL;
if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(
*ctx->expr_factory_, ctx->session_info_, T_FUN_VAR_SAMP, parma_expr, var_expr))) {
LOG_WARN("failed to build common aggr expr", K(ret));
} else {
var_expr->set_expr_level(aggr_expr->get_expr_level());
if (OB_FAIL(expand_var_expr(ctx, var_expr, sqrt_param_expr, new_aggr_items))) {
LOG_WARN("fail to expand keep variance expr", K(ret));
} else if (OB_FAIL(ctx->expr_factory_->create_raw_expr(T_FUN_SYS_SQRT, sqrt_expr))) {
LOG_WARN("failed to crate sqrt expr", K(ret));
} else if (OB_ISNULL(sqrt_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("add expr is null", K(ret), K(sqrt_expr));
} else if (OB_FAIL(sqrt_expr->add_param_expr(sqrt_param_expr))) {
LOG_WARN("add text expr to add expr failed", K(ret));
} else {
ObString func_name = ObString::make_string("sqrt");
sqrt_expr->set_func_name(func_name);
replace_expr = sqrt_expr;
}
}
}
return ret;
}
int ObExpandAggregateUtils::add_cast_expr(
ObTransformerCtx* ctx, ObRawExpr* expr, ObExprResType& dst_type, ObRawExpr*& new_expr)
{
int ret = OB_SUCCESS;
ObSysFunRawExpr* cast_expr = NULL;
if (OB_ISNULL(expr) || OB_ISNULL(ctx)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(expr), K(ctx));
} else if (OB_FAIL(ObRawExprUtils::create_cast_expr(
*ctx->expr_factory_, expr, dst_type, cast_expr, ctx->session_info_))) {
LOG_WARN("failed to add cast expr", K(ret));
} else if (OB_ISNULL(cast_expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(cast_expr));
} else {
new_expr = cast_expr;
}
return ret;
}
int ObExpandAggregateUtils::add_win_exprs(
ObSelectStmt* select_stmt, ObIArray<ObRawExpr*>& replace_exprs, ObIArray<ObWinFunRawExpr*>& new_win_exprs)
{
int ret = OB_SUCCESS;
if (OB_ISNULL(select_stmt)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(select_stmt));
} else if (replace_exprs.count() > 0 && new_win_exprs.count() > 0) {
select_stmt->get_window_func_exprs().reset();
for (int64_t i = 0; OB_SUCC(ret) && i < new_win_exprs.count(); ++i) {
ObWinFunRawExpr* win_expr = NULL;
if (OB_ISNULL(new_win_exprs.at(i))) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("get unexpected null", K(ret), K(new_win_exprs.at(i)));
} else if (OB_ISNULL(win_expr = select_stmt->get_same_win_func_item(new_win_exprs.at(i)))) {
if (OB_FAIL(select_stmt->add_window_func_expr(new_win_exprs.at(i)))) {
LOG_WARN("failed to add window func expr", K(ret));
}
} else {
for (int64_t j = 0; OB_SUCC(ret) && j < replace_exprs.count(); ++j) {
if (ObRawExprUtils::replace_ref_column(replace_exprs.at(j), new_win_exprs.at(i), win_expr)) {
LOG_WARN("failed to replace ref column.", K(ret));
}
}
}
}
}
return ret;
}
} // namespace sql
} // namespace oceanbase