Fix null aware anti join bug
This commit is contained in:
parent
b5ac0c7bf6
commit
11437edf50
@ -7635,6 +7635,7 @@ int ObJoinOrder::inner_generate_join_paths(const ObJoinOrder &left_tree,
|
||||
other_cond_sel,
|
||||
get_plan()->get_predicate_selectivities()))) {
|
||||
LOG_WARN("failed to calculate selectivity", K(ret), K(hash_join_filters));
|
||||
} else if (FALSE_IT(naaj_info.set_is_sna(path_info.join_type_, false))) {
|
||||
} else if ((HASH_JOIN & path_info.local_methods_) &&
|
||||
OB_FAIL(generate_hash_paths(equal_sets,
|
||||
left_paths,
|
||||
@ -7648,9 +7649,9 @@ int ObJoinOrder::inner_generate_join_paths(const ObJoinOrder &left_tree,
|
||||
equal_cond_sel,
|
||||
other_cond_sel,
|
||||
path_info,
|
||||
naaj_info.is_naaj_,
|
||||
naaj_info.get_is_sna(path_info.join_type_, false)))) {
|
||||
naaj_info))) {
|
||||
LOG_WARN("failed to generate hash join paths", K(ret));
|
||||
} else if (FALSE_IT(naaj_info.set_is_sna(reverse_path_info.join_type_, true))) {
|
||||
} else if ((HASH_JOIN & reverse_path_info.local_methods_) &&
|
||||
OB_FAIL(generate_hash_paths(equal_sets,
|
||||
right_paths,
|
||||
@ -7664,8 +7665,7 @@ int ObJoinOrder::inner_generate_join_paths(const ObJoinOrder &left_tree,
|
||||
equal_cond_sel,
|
||||
other_cond_sel,
|
||||
reverse_path_info,
|
||||
naaj_info.is_naaj_,
|
||||
naaj_info.get_is_sna(reverse_path_info.join_type_, true)))) {
|
||||
naaj_info))) {
|
||||
LOG_WARN("failed to generate hash join paths", K(ret));
|
||||
} else {
|
||||
int64_t hash_join_path_num = interesting_paths_.count() - path_number;
|
||||
@ -7819,8 +7819,7 @@ int ObJoinOrder::generate_hash_paths(const EqualSets &equal_sets,
|
||||
const double equal_cond_sel,
|
||||
const double other_cond_sel,
|
||||
const ValidPathInfo &path_info,
|
||||
const bool is_naaj,
|
||||
const bool is_sna)
|
||||
const NullAwareAntiJoinInfo &naaj_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<Path*, 8> left_best_paths;
|
||||
@ -7852,7 +7851,7 @@ int ObJoinOrder::generate_hash_paths(const EqualSets &equal_sets,
|
||||
path_info,
|
||||
HASH_JOIN,
|
||||
false,
|
||||
is_naaj,
|
||||
naaj_info.is_naaj_,
|
||||
dist_method))) {
|
||||
LOG_WARN("failed to get distributed join method", K(ret));
|
||||
} else {
|
||||
@ -7874,8 +7873,7 @@ int ObJoinOrder::generate_hash_paths(const EqualSets &equal_sets,
|
||||
join_quals,
|
||||
equal_cond_sel,
|
||||
other_cond_sel,
|
||||
is_naaj,
|
||||
is_sna))) {
|
||||
naaj_info))) {
|
||||
LOG_WARN("failed to create and add hash path", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
@ -9110,8 +9108,7 @@ int ObJoinOrder::create_and_add_hash_path(const Path *left_path,
|
||||
const ObIArray<ObRawExpr*> &filters,
|
||||
const double equal_cond_sel,
|
||||
const double other_cond_sel,
|
||||
const bool is_naaj,
|
||||
const bool is_sna)
|
||||
const NullAwareAntiJoinInfo &naaj_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
JoinPath *join_path = NULL;
|
||||
@ -9137,9 +9134,9 @@ int ObJoinOrder::create_and_add_hash_path(const Path *left_path,
|
||||
join_type);
|
||||
join_path->equal_cond_sel_ = equal_cond_sel;
|
||||
join_path->other_cond_sel_ = other_cond_sel;
|
||||
join_path->is_naaj_ = is_naaj;
|
||||
join_path->is_sna_ = is_sna;
|
||||
join_path->is_slave_mapping_ &= (!is_naaj);
|
||||
join_path->is_naaj_ = naaj_info.is_naaj_;
|
||||
join_path->is_sna_ = naaj_info.is_sna_;
|
||||
join_path->is_slave_mapping_ &= (!naaj_info.is_naaj_);
|
||||
OPT_TRACE("create new Hash Join path:", join_path);
|
||||
if (OB_FAIL(append(join_path->equal_join_conditions_, equal_join_conditions))) {
|
||||
LOG_WARN("failed to append join conditions", K(ret));
|
||||
@ -9147,12 +9144,14 @@ int ObJoinOrder::create_and_add_hash_path(const Path *left_path,
|
||||
LOG_WARN("failed to append join filters", K(ret));
|
||||
} else if (OB_FAIL(append(join_path->filter_, normal_filters))) {
|
||||
LOG_WARN("failed to append join quals", K(ret));
|
||||
} else if (OB_FAIL(append(join_path->expr_constraints_, naaj_info.expr_constraints_))) {
|
||||
LOG_WARN("failed to append constraints", K(ret));
|
||||
} else if (OB_FAIL(generate_join_filter_infos(*left_path,
|
||||
*right_path,
|
||||
join_type,
|
||||
join_dist_algo,
|
||||
equal_join_conditions,
|
||||
is_naaj,
|
||||
naaj_info.is_naaj_,
|
||||
join_path->join_filter_infos_))) {
|
||||
LOG_WARN("failed to generate join filter info", K(ret));
|
||||
} else if (OB_FAIL(join_path->compute_join_path_property())) {
|
||||
@ -9922,8 +9921,7 @@ int ObJoinOrder::extract_hashjoin_conditions(const ObIArray<ObRawExpr*> &join_qu
|
||||
LOG_WARN("failed to get sys var naaj enabled", K(ret));
|
||||
} else if (naaj_enabled) {
|
||||
if (OB_FAIL(extract_naaj_join_conditions(join_quals, left_tables, right_tables,
|
||||
equal_join_conditions, other_join_conditions,
|
||||
naaj_info))) {
|
||||
equal_join_conditions, naaj_info))) {
|
||||
LOG_WARN("failed to extract naaj join conditions", K(ret));
|
||||
}
|
||||
}
|
||||
@ -13716,7 +13714,6 @@ int ObJoinOrder::extract_naaj_join_conditions(const ObIArray<ObRawExpr*> &join_q
|
||||
const ObRelIds &left_tables,
|
||||
const ObRelIds &right_tables,
|
||||
ObIArray<ObRawExpr*> &equal_join_conditions,
|
||||
ObIArray<ObRawExpr*> &other_join_conditions,
|
||||
NullAwareAntiJoinInfo &naaj_info)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -13731,17 +13728,18 @@ int ObJoinOrder::extract_naaj_join_conditions(const ObIArray<ObRawExpr*> &join_q
|
||||
} else if (T_OP_OR == join_quals.at(0)->get_expr_type()) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < join_quals.at(0)->get_param_count(); ++i) {
|
||||
bool is_equal_cond = false;
|
||||
bool skip_left = false;
|
||||
bool skip_right = false;
|
||||
cur_expr = join_quals.at(0)->get_param_expr(i);
|
||||
if (OB_FAIL(check_is_join_equal_conditions(cur_expr, left_tables,
|
||||
right_tables, is_equal_cond))) {
|
||||
LOG_WARN("failed to check equal cond", K(cur_expr), K(ret));
|
||||
} else if (is_equal_cond) {
|
||||
OZ (join_quals_naaj.push_back(cur_expr));
|
||||
if (OB_FAIL(join_quals_naaj.push_back(cur_expr))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
}
|
||||
} else {
|
||||
if (cur_expr->get_relation_ids().is_subset(get_tables())) {
|
||||
OZ (join_other_naaj.push_back(cur_expr));
|
||||
if (cur_expr->get_relation_ids().is_subset(get_tables()) &&
|
||||
OB_FAIL(join_other_naaj.push_back(cur_expr))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -13752,33 +13750,68 @@ int ObJoinOrder::extract_naaj_join_conditions(const ObIArray<ObRawExpr*> &join_q
|
||||
left_join_key = join_quals_naaj.at(0)->get_param_expr(1);
|
||||
right_join_key = join_quals_naaj.at(0)->get_param_expr(0);
|
||||
}
|
||||
bool left_is_null_eliminate = true;
|
||||
bool right_is_null_eliminate = true;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < join_other_naaj.count(); ++i) {
|
||||
bool left_has_is_null = false;
|
||||
bool right_has_is_null = false;
|
||||
bool is_valid = true;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < join_other_naaj.count(); ++i) {
|
||||
//eliminate join_key is null
|
||||
cur_expr = join_other_naaj.at(i);
|
||||
if (T_OP_IS == cur_expr->get_expr_type()
|
||||
&& ObNullType == cur_expr->get_param_expr(1)->get_result_type().get_type()) {
|
||||
if (left_join_key == cur_expr->get_param_expr(0)) {
|
||||
left_is_null_eliminate = false;
|
||||
left_has_is_null = true;
|
||||
} else if (right_join_key == cur_expr->get_param_expr(0)) {
|
||||
right_is_null_eliminate = false;
|
||||
right_has_is_null = true;
|
||||
} else {
|
||||
OZ (other_join_conditions.push_back(join_other_naaj.at(i)));
|
||||
is_valid = false;
|
||||
}
|
||||
} else {
|
||||
is_valid = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret) || !is_valid) {
|
||||
// do nothing
|
||||
} else if (left_has_is_null && right_has_is_null) {
|
||||
// Both "is null" was eliminated
|
||||
// anti join na
|
||||
// e.g. (a = b) or (a is null) or (b is null)
|
||||
naaj_info.is_naaj_ = true;
|
||||
if (OB_FAIL(equal_join_conditions.push_back(join_quals_naaj.at(0)))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
}
|
||||
} else if (left_has_is_null || right_has_is_null) {
|
||||
// Only one "is null" was eliminated,
|
||||
// Other side should be not null
|
||||
// e.g. ((a = b) or (a is null)) and (b is not null)
|
||||
// <=> ((a = b) or (a is null) or (b is null)) and (b is not null)
|
||||
ObNotNullContext not_null_ctx(get_plan()->get_optimizer_context().get_exec_ctx(),
|
||||
&get_plan()->get_allocator(),
|
||||
get_plan()->get_stmt());
|
||||
ObArray<ObRawExpr *> constraints;
|
||||
if (OB_FAIL(not_null_ctx.generate_stmt_context(NULLABLE_SCOPE::NS_WHERE))) {
|
||||
LOG_WARN("failed to generate stmt context", K(ret));
|
||||
} else if (OB_FAIL(not_null_ctx.remove_filter(join_quals.at(0)))){
|
||||
LOG_WARN("failed to remove filter", K(ret));
|
||||
} else if (!left_has_is_null &&
|
||||
OB_FAIL(ObTransformUtils::is_expr_not_null(not_null_ctx, left_join_key,
|
||||
naaj_info.left_side_not_null_, &constraints))) {
|
||||
LOG_WARN("failed to check is expr not null");
|
||||
} else if (!right_has_is_null &&
|
||||
OB_FAIL(ObTransformUtils::is_expr_not_null(not_null_ctx, right_join_key,
|
||||
naaj_info.right_side_not_null_, &constraints))) {
|
||||
LOG_WARN("failed to check is expr not null");
|
||||
} else if (OB_FAIL(ObTransformUtils::add_param_not_null_constraint(naaj_info.expr_constraints_, constraints))) {
|
||||
LOG_WARN("append expr constraints failed", K(ret));
|
||||
} else if (naaj_info.left_side_not_null_ || naaj_info.right_side_not_null_) {
|
||||
naaj_info.is_naaj_ = true;
|
||||
if (OB_FAIL(equal_join_conditions.push_back(join_quals_naaj.at(0)))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
// at least 1 isnull cond to choose naaj
|
||||
if (!left_is_null_eliminate || !right_is_null_eliminate) {
|
||||
naaj_info.is_naaj_ = true;
|
||||
naaj_info.left_side_not_null_ = left_is_null_eliminate;
|
||||
naaj_info.right_side_not_null_ = right_is_null_eliminate;
|
||||
OZ (equal_join_conditions.push_back(join_quals_naaj.at(0)));
|
||||
} else {
|
||||
//rollback for other_join_conditions
|
||||
other_join_conditions.reset();
|
||||
}
|
||||
}
|
||||
LOG_TRACE("extract naaj info", K(naaj_info), K(equal_join_conditions));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -1195,25 +1195,28 @@ struct InnerPathInfo {
|
||||
typedef common::ObSEArray<InnerPathInfo, 8, common::ModulePageAllocator, true> InnerPathInfos;
|
||||
|
||||
struct NullAwareAntiJoinInfo {
|
||||
NullAwareAntiJoinInfo() : is_naaj_(false),
|
||||
NullAwareAntiJoinInfo() : is_naaj_(false), is_sna_(false),
|
||||
left_side_not_null_(false), right_side_not_null_(false) {}
|
||||
~NullAwareAntiJoinInfo() {}
|
||||
TO_STRING_KV(K_(is_naaj), K_(left_side_not_null), K_(right_side_not_null));
|
||||
bool get_is_sna(const ObJoinType &join_type, const bool is_reverse_path) const
|
||||
TO_STRING_KV(K_(is_naaj), K_(is_sna), K_(left_side_not_null), K_(right_side_not_null), K_(expr_constraints));
|
||||
void set_is_sna(const ObJoinType &join_type, const bool is_reverse_path)
|
||||
{
|
||||
bool is_sna = false;
|
||||
if (is_reverse_path) {
|
||||
is_sna = ((LEFT_ANTI_JOIN == join_type && left_side_not_null_)
|
||||
|| (RIGHT_ANTI_JOIN == join_type && right_side_not_null_));
|
||||
} else {
|
||||
is_sna = ((LEFT_ANTI_JOIN == join_type && right_side_not_null_)
|
||||
|| (RIGHT_ANTI_JOIN == join_type && left_side_not_null_));
|
||||
if (is_naaj_) {
|
||||
if (is_reverse_path) {
|
||||
is_sna_ = ((LEFT_ANTI_JOIN == join_type && left_side_not_null_)
|
||||
|| (RIGHT_ANTI_JOIN == join_type && right_side_not_null_));
|
||||
} else {
|
||||
is_sna_ = ((LEFT_ANTI_JOIN == join_type && right_side_not_null_)
|
||||
|| (RIGHT_ANTI_JOIN == join_type && left_side_not_null_));
|
||||
}
|
||||
}
|
||||
return is_sna;
|
||||
return;
|
||||
}
|
||||
bool is_naaj_;
|
||||
bool is_sna_;
|
||||
bool left_side_not_null_;
|
||||
bool right_side_not_null_;
|
||||
ObSEArray<ObExprConstraint, 2> expr_constraints_;
|
||||
};
|
||||
|
||||
class ObJoinOrder
|
||||
@ -1807,8 +1810,7 @@ struct NullAwareAntiJoinInfo {
|
||||
const double equal_cond_sel,
|
||||
const double other_cond_sel,
|
||||
const ValidPathInfo &path_info,
|
||||
const bool is_naaj,
|
||||
const bool is_sna);
|
||||
const NullAwareAntiJoinInfo &naaj_info);
|
||||
|
||||
int generate_mj_paths(const EqualSets &equal_sets,
|
||||
const ObIArray<ObSEArray<Path*, 16>> &left_paths,
|
||||
@ -1884,8 +1886,7 @@ struct NullAwareAntiJoinInfo {
|
||||
const common::ObIArray<ObRawExpr*> &filters,
|
||||
const double equal_cond_sel,
|
||||
const double other_cond_sel,
|
||||
const bool is_naaj,
|
||||
const bool is_sna);
|
||||
const NullAwareAntiJoinInfo &naaj_info);
|
||||
|
||||
int generate_join_filter_infos(const Path &left_path,
|
||||
const Path &right_path,
|
||||
@ -2440,7 +2441,6 @@ struct NullAwareAntiJoinInfo {
|
||||
const ObRelIds &left_tables,
|
||||
const ObRelIds &right_tables,
|
||||
ObIArray<ObRawExpr*> &equal_join_conditions,
|
||||
ObIArray<ObRawExpr*> &other_join_conditions,
|
||||
NullAwareAntiJoinInfo &naaj_info);
|
||||
bool is_main_table_use_das(const common::ObIArray<AccessPath *> &access_paths);
|
||||
int add_deduced_expr(ObRawExpr *deduced_expr, ObRawExpr *deduce_from, bool is_persistent);
|
||||
|
@ -9518,20 +9518,19 @@ int ObTransformUtils::extract_shared_expr(ObDMLStmt *upper_stmt,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
|
||||
int ObTransformUtils::add_param_not_null_constraint(ObIArray<ObExprConstraint> &constraints,
|
||||
ObIArray<ObRawExpr *> ¬_null_exprs)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < not_null_exprs.count(); ++i) {
|
||||
if (OB_FAIL(add_param_not_null_constraint(ctx, not_null_exprs.at(i)))) {
|
||||
if (OB_FAIL(add_param_not_null_constraint(constraints, not_null_exprs.at(i)))) {
|
||||
LOG_WARN("failed to add param not null constraint", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
|
||||
int ObTransformUtils::add_param_not_null_constraint(ObIArray<ObExprConstraint> &constraints,
|
||||
ObRawExpr *not_null_expr,
|
||||
bool is_true)
|
||||
{
|
||||
@ -9544,16 +9543,16 @@ int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("pre calculable expr is expected here", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < ctx.expr_constraints_.count(); ++i) {
|
||||
if (ctx.expr_constraints_.at(i).expect_result_ == PRE_CALC_RESULT_NOT_NULL &&
|
||||
ctx.expr_constraints_.at(i).pre_calc_expr_ == not_null_expr) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < constraints.count(); ++i) {
|
||||
if (constraints.at(i).expect_result_ == PRE_CALC_RESULT_NOT_NULL &&
|
||||
constraints.at(i).pre_calc_expr_ == not_null_expr) {
|
||||
existed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !existed) {
|
||||
ObExprConstraint cons(not_null_expr, PRE_CALC_RESULT_NOT_NULL);
|
||||
if (OB_FAIL(ctx.expr_constraints_.push_back(cons))) {
|
||||
if (OB_FAIL(constraints.push_back(cons))) {
|
||||
LOG_WARN("failed to push back pre calc constraints", K(ret));
|
||||
}
|
||||
}
|
||||
@ -9561,6 +9560,23 @@ int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
|
||||
ObIArray<ObRawExpr *> ¬_null_exprs)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ret = add_param_not_null_constraint(ctx.expr_constraints_, not_null_exprs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformUtils::add_param_not_null_constraint(ObTransformerCtx &ctx,
|
||||
ObRawExpr *not_null_expr,
|
||||
bool is_true)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ret = add_param_not_null_constraint(ctx.expr_constraints_, not_null_expr, is_true);
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformUtils::add_param_null_constraint(ObTransformerCtx &ctx,
|
||||
ObRawExpr *null_expr)
|
||||
{
|
||||
|
@ -1434,6 +1434,13 @@ public:
|
||||
bool in_add_expr);
|
||||
static int add_constraint_for_groupby_expr(ObTransformerCtx *trans_ctx, ObSelectStmt *select_stmt, ObRawExpr* groupby_expr, ObRawExpr* old_expr);
|
||||
|
||||
static int add_param_not_null_constraint(ObIArray<ObExprConstraint> &constraints,
|
||||
ObIArray<ObRawExpr *> ¬_null_exprs);
|
||||
|
||||
static int add_param_not_null_constraint(ObIArray<ObExprConstraint> &constraints,
|
||||
ObRawExpr *not_null_expr,
|
||||
bool is_true = true);
|
||||
|
||||
static int add_param_not_null_constraint(ObTransformerCtx &ctx,
|
||||
ObIArray<ObRawExpr *> ¬_null_exprs);
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user