Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add expression propagation for case when rewrite #1513

Open
wants to merge 2 commits into
base: master
Choose a base branch
from

Conversation

fhkong
Copy link
Contributor

@fhkong fhkong commented Aug 15, 2023

Task Description

某些情况下,表达式会出现冗余判断,我们希望借助于先验的表达式集合来消除这种冗余判断。例如下列SQL:

select 1 from t1 where c1 > c2 and case when c1 > c2 then c1 else c2 end > 1
由于c1 > c2在case when表达式之前已经判断过,导致case when中的c1 > c2表达式为恒真;对于这种情况,我们可以将case when表达式消除掉。
得到最终的SQL语句

select 1 from t1 where c1 > c2 and c1 > 1

Solution Description

借助于常量传播的代码框架,实现表达式传播。方案的关键是:为每个表达式正确地找到作用域,并在其作用域内进行传播。
主要步骤为:

找到会产生新的作用域的情况。
在每个作用域内抽取表达式,并在离开作用域时,对该作用域进行传播。
判断目标表达式 E 是否可以被改写(规避共享表达式、连接条件表达式)。
子作用域的表达式不能传播到父层,但父作用域可以传播到子层。

Passed Regressions

已有testcase:transformer_const_propagate.test
自测testcase:transformer_expr_propagate.test

Upgrade Compatibility

None

Other Information

None

Release Note

None

@CLAassistant
Copy link

CLAassistant commented Aug 15, 2023

CLA assistant check
All committers have signed the CLA.

@fhkong fhkong changed the title Const propagate feat: add expression propagation for case when rewrite Aug 15, 2023
if (OB_ISNULL(expr)) {
ret = OB_ERR_UNEXPECTED;
LOG_WARN("unexpected param is NULL", K(ret));
} else if (ObOptimizerUtil::find_item(propagate_exprs_, expr)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

直接 add_var_to_array_no_dup

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

@@ -322,7 +342,7 @@ int ObTransformConstPropagate::do_transform(ObDMLStmt *stmt,
}
}

if (OB_SUCC(ret) && !const_ctx.active_const_infos_.empty()) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这些地方可以再梳理下,有的地方继续使用 !const_ctx.active_const_infos_.empty()判断,没必要都进行 case when的替换

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

if (const_ctx.hint_allowed_trans_) {
ObSEArray<ObRawExpr *, 8> parent_exprs;
if (OB_FAIL(recursive_replace_expr(cur_expr,
parent_exprs,
const_ctx,
used_in_compare,
trans_happened))) {
const_trans_happended))) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

recursive_replace 入口处分别用 !const_ctx.active_const_infos_.empty() 和 propagate_exprs_.empty() 判断下

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

{
int ret = OB_SUCCESS;
trans_happended = false;
bool is_happended = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when 表达式内部有必要递归替换吗,如果 when expr 不能匹配 propagate_exprs_, 能直接在 simplify expr 里消除 case when 的场景也很有限吧。要做到什么程度在文档里说明下吧

{
int ret = OB_SUCCESS;
trans_happended = false;
bool is_happended = false;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

when 表达式内部有必要递归替换吗,如果 when expr 不能匹配 propagate_exprs_, 能直接在 simplify expr 里消除 case when 的场景也很有限吧。要做到什么程度在文档里说明下吧

LOG_WARN("failed to replace case when expr internal", K(ret));
} else {
trans_happended |= is_happended;
int64_t N = cur_expr->get_param_count();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

把 case when 中 when 替换为 true 是为了 simpify expr 中消除 case when 做准备,应该没有必要把所有的 when 进行替换

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

这里可以只对第一个when表达式替换,因为先前已经做了一次simplify改写;

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

3 participants