fix some outline/hint bugs
This commit is contained in:
parent
c7b8a188c3
commit
b6a15b6111
@ -2381,6 +2381,7 @@ typedef enum ObItemType
|
||||
T_COLUMN_GROUP_DROP,
|
||||
T_ALTER_COLUMN_GROUP_OPTION,
|
||||
T_BLOCKING,
|
||||
T_PQ_SUBQUERY,
|
||||
T_MAX //Attention: add a new type before T_MAX
|
||||
} ObItemType;
|
||||
|
||||
|
@ -7636,10 +7636,6 @@ int ObJoinOrder::generate_base_table_paths(PathHelper &helper)
|
||||
LOG_WARN("failed to calc table location", K(ret));
|
||||
} else if (OB_FAIL(estimate_size_for_base_table(helper, access_paths))) {
|
||||
LOG_WARN("failed to estimate_size", K(ret));
|
||||
} else if (!helper.is_inner_path_ && !is_virtual_table(ref_table_id)
|
||||
&& EXTERNAL_TABLE != table_meta_info_.table_type_
|
||||
&& OB_FAIL(compute_one_row_info_for_table_scan(access_paths))) {
|
||||
LOG_WARN("failed to compute one row info", K(ret));
|
||||
} else if (OB_FAIL(pruning_unstable_access_path(helper.table_opt_info_, access_paths))) {
|
||||
LOG_WARN("failed to pruning unstable access path", K(ret));
|
||||
} else if (OB_FAIL(get_plan()->select_location(tbl_part_infos))) {
|
||||
@ -7677,6 +7673,12 @@ int ObJoinOrder::compute_base_table_property(uint64_t table_id,
|
||||
ref_table_id,
|
||||
get_restrict_infos()))) {
|
||||
LOG_WARN("failed to extract fd item set", K(ret));
|
||||
} else if (OB_FAIL(ObOptimizerUtil::is_exprs_unique(get_output_const_exprs(),
|
||||
get_fd_item_set(),
|
||||
get_output_equal_sets(),
|
||||
get_output_const_exprs(),
|
||||
is_at_most_one_row_))) {
|
||||
LOG_WARN("failed to compute at most one row", K(ret));
|
||||
} else if (OB_FAIL(compute_table_location(table_id,
|
||||
ref_table_id,
|
||||
false,
|
||||
@ -13170,30 +13172,6 @@ int ObJoinOrder::compute_fd_item_set_for_subquery(const uint64_t table_id,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObJoinOrder::compute_one_row_info_for_table_scan(ObIArray<AccessPath *> &access_paths)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
AccessPath *access_path = NULL;
|
||||
is_at_most_one_row_ = false;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && !is_at_most_one_row_ && i < access_paths.count(); i++) {
|
||||
bool is_one_row = false;
|
||||
if (OB_ISNULL(access_path = access_paths.at(i)) ||
|
||||
OB_ISNULL(access_path->pre_query_range_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (access_path->is_inner_path_) {
|
||||
/*do nothing*/
|
||||
} else if (OB_FAIL(access_path->pre_query_range_->is_at_most_one_row(is_one_row))) {
|
||||
LOG_WARN("failed to check if is at most one row", K(ret));
|
||||
} else if (is_one_row && (1 == access_path->est_cost_info_.ranges_.count())) {
|
||||
is_at_most_one_row_ = true;
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
LOG_TRACE("succeed to compute one row info for table scan", K(is_at_most_one_row_),
|
||||
K(table_id_));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObJoinOrder::compute_one_row_info_for_join(const ObJoinOrder *left_tree,
|
||||
const ObJoinOrder *right_tree,
|
||||
const ObIArray<ObRawExpr*> &join_condition,
|
||||
|
@ -2315,8 +2315,6 @@ struct NullAwareAntiJoinInfo {
|
||||
int compute_fd_item_set_for_subquery(const uint64_t table_id,
|
||||
ObLogicalOperator *subplan_root);
|
||||
|
||||
int compute_one_row_info_for_table_scan(ObIArray<AccessPath *> &access_paths);
|
||||
|
||||
int compute_one_row_info_for_join(const ObJoinOrder *left_tree,
|
||||
const ObJoinOrder *right_tree,
|
||||
const ObIArray<ObRawExpr*> &join_condition,
|
||||
|
@ -7346,6 +7346,7 @@ int ObLogPlan::adjust_sort_expr_ordering(ObIArray<ObRawExpr*> &sort_exprs,
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !adjusted && stmt->get_order_item_size() > 0) {
|
||||
adjusted = true;
|
||||
if (prefix_count > 0) {
|
||||
/* used part of input ordering, try adjust sort_exprs after prefix_count by order item */
|
||||
if (OB_FAIL(adjust_postfix_sort_expr_ordering(stmt->get_order_items(),
|
||||
@ -7368,6 +7369,11 @@ int ObLogPlan::adjust_sort_expr_ordering(ObIArray<ObRawExpr*> &sort_exprs,
|
||||
LOG_WARN("failed to adjust exprs by ordering", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && !adjusted) {
|
||||
if (OB_FAIL(ObOptimizerUtil::generate_stable_ordering(sort_exprs, sort_directions))) {
|
||||
LOG_WARN("failed to generate stable ordering", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -9021,7 +9027,7 @@ int ObLogPlan::candi_allocate_subplan_filter(const ObIArray<ObRawExpr*> &subquer
|
||||
onetime_exprs,
|
||||
initplan_idxs,
|
||||
onetime_idxs,
|
||||
NULL == filters ? NULL : &new_filters,
|
||||
new_filters,
|
||||
for_cursor_expr,
|
||||
is_update_set))) {
|
||||
LOG_WARN("failed to allocate subplan filter", K(ret));
|
||||
@ -9036,24 +9042,83 @@ int ObLogPlan::inner_candi_allocate_subplan_filter(ObIArray<ObLogPlan*> &subplan
|
||||
ObIArray<ObExecParamRawExpr *> &onetime_exprs,
|
||||
ObBitSet<> &initplan_idxs,
|
||||
ObBitSet<> &onetime_idxs,
|
||||
const ObIArray<ObRawExpr *> *filters,
|
||||
const ObIArray<ObRawExpr *> &filters,
|
||||
const bool for_cursor_expr,
|
||||
const bool is_update_set)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<ObSEArray<CandidatePlan, 4>, 8> best_subplan_list;
|
||||
ObSEArray<ObSEArray<CandidatePlan, 4>, 8> best_dist_subplan_list;
|
||||
ObSEArray<CandidatePlan, 4> subquery_plans;
|
||||
int64_t dist_methods = DIST_INVALID_METHOD;
|
||||
if (OB_FAIL(prepare_subplan_candidate_list(subplans, params, best_subplan_list,
|
||||
best_dist_subplan_list))) {
|
||||
LOG_WARN("failed to prepare subplan candidate list", K(ret));
|
||||
} else if (OB_FAIL(get_valid_subplan_filter_dist_method(subplans, for_cursor_expr, false,
|
||||
dist_methods))) {
|
||||
LOG_WARN("failed to get valid subplan filter dist method", K(ret));
|
||||
} else if (OB_FAIL(inner_candi_allocate_subplan_filter(best_subplan_list,
|
||||
best_dist_subplan_list,
|
||||
query_refs,
|
||||
params,
|
||||
onetime_exprs,
|
||||
initplan_idxs,
|
||||
onetime_idxs,
|
||||
filters,
|
||||
for_cursor_expr,
|
||||
is_update_set,
|
||||
dist_methods,
|
||||
subquery_plans))) {
|
||||
LOG_WARN("failed to allocate subplan filter", K(ret));
|
||||
} else if (!subquery_plans.empty()) {
|
||||
LOG_TRACE("succeed to allocate subplan filter using hint", K(subquery_plans.count()), K(dist_methods));
|
||||
OPT_TRACE("success to generate subplan filter plan with hint");
|
||||
} else if (OB_FAIL(get_log_plan_hint().check_status())) {
|
||||
LOG_WARN("failed to generate plans with hint", K(ret));
|
||||
} else if (OB_FAIL(get_valid_subplan_filter_dist_method(subplans, for_cursor_expr, true,
|
||||
dist_methods))) {
|
||||
LOG_WARN("failed to get valid subplan filter dist method", K(ret));
|
||||
} else if (OB_FAIL(inner_candi_allocate_subplan_filter(best_subplan_list,
|
||||
best_dist_subplan_list,
|
||||
query_refs,
|
||||
params,
|
||||
onetime_exprs,
|
||||
initplan_idxs,
|
||||
onetime_idxs,
|
||||
filters,
|
||||
for_cursor_expr,
|
||||
is_update_set,
|
||||
dist_methods,
|
||||
subquery_plans))) {
|
||||
LOG_WARN("failed to allocate subplan filter", K(ret));
|
||||
} else {
|
||||
LOG_TRACE("succeed to allocate subplan filter ignore hint", K(subquery_plans.count()), K(dist_methods));
|
||||
OPT_TRACE("success to generate subplan filter plan ignore hint");
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
/*do nothing*/
|
||||
} else if (OB_FAIL(prune_and_keep_best_plans(subquery_plans))) {
|
||||
LOG_WARN("failed to prune and keep best plans", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
return ret;
|
||||
}
|
||||
|
||||
// get best candidate list
|
||||
int ObLogPlan::prepare_subplan_candidate_list(ObIArray<ObLogPlan*> &subplans,
|
||||
ObIArray<ObExecParamRawExpr *> ¶ms,
|
||||
ObIArray<ObSEArray<CandidatePlan, 4>> &best_list,
|
||||
ObIArray<ObSEArray<CandidatePlan, 4>> &dist_best_list)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
best_list.reuse();
|
||||
dist_best_list.reuse();
|
||||
ObLogPlan *log_plan = NULL;
|
||||
const ObDMLStmt *stmt = NULL;
|
||||
CandidatePlan candidate_plan;
|
||||
ObSEArray<int64_t, 4> move_pos;
|
||||
ObSEArray<CandidatePlan, 4> temp_plans;
|
||||
ObSEArray<CandidatePlan, 4> dist_temp_plans;
|
||||
ObSEArray<CandidatePlan, 4> subquery_plans;
|
||||
ObSEArray<ObSEArray<CandidatePlan, 4>, 8> best_list;
|
||||
ObSEArray<ObSEArray<CandidatePlan, 4>, 8> dist_best_list;
|
||||
ObSEArray<ObLogicalOperator*, 4> child_ops;
|
||||
ObSEArray<ObLogicalOperator*, 4> dist_child_ops;
|
||||
ObExchangeInfo exch_info;
|
||||
// get best candidate list
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < subplans.count(); i++) {
|
||||
temp_plans.reuse();
|
||||
if (OB_ISNULL(subplans.at(i))) {
|
||||
@ -9099,6 +9164,82 @@ int ObLogPlan::inner_candi_allocate_subplan_filter(ObIArray<ObLogPlan*> &subplan
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogPlan::get_valid_subplan_filter_dist_method(ObIArray<ObLogPlan*> &subplans,
|
||||
const bool for_cursor_expr,
|
||||
const bool ignore_hint,
|
||||
int64_t &dist_methods)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
dist_methods = DIST_BASIC_METHOD | DIST_PULL_TO_LOCAL
|
||||
| DIST_PARTITION_WISE | DIST_PARTITION_NONE
|
||||
| DIST_NONE_ALL;
|
||||
const ObLogicalOperator *op = NULL;
|
||||
bool contain_recursive_cte = false;
|
||||
if (OB_ISNULL(get_stmt()) || OB_UNLIKELY(candidates_.candidate_plans_.empty()
|
||||
|| OB_UNLIKELY(subplans.empty()))
|
||||
|| OB_ISNULL(op = candidates_.candidate_plans_.at(0).plan_tree_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected list", K(ret), K(subplans.count()), K(op));
|
||||
} else {
|
||||
contain_recursive_cte |= op->get_contains_fake_cte();
|
||||
ObSEArray<ObString, 4> sub_qb_names;
|
||||
ObString qb_name;
|
||||
ObLogPlan *subplan = NULL;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < subplans.count(); i++) {
|
||||
if (OB_ISNULL(subplan = subplans.at(i)) || OB_ISNULL(subplan->get_stmt())
|
||||
|| OB_UNLIKELY(subplan->candidates_.candidate_plans_.empty())
|
||||
|| OB_ISNULL(op = subplan->candidates_.candidate_plans_.at(0).plan_tree_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected list", K(ret), K(subplan), K(op));
|
||||
} else if (OB_FAIL(subplan->get_stmt()->get_qb_name(qb_name))) {
|
||||
LOG_WARN("failed to get qb name", K(ret));
|
||||
} else if (OB_FAIL(sub_qb_names.push_back(qb_name))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
} else {
|
||||
contain_recursive_cte |= op->get_contains_fake_cte();
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && !ignore_hint) {
|
||||
const bool implicit_hint_allowed = (subplans.count() == get_stmt()->get_subquery_expr_size());
|
||||
dist_methods &= get_log_plan_hint().get_valid_pq_subquery_dist_algo(sub_qb_names,
|
||||
implicit_hint_allowed);
|
||||
}
|
||||
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (for_cursor_expr || contain_recursive_cte) {
|
||||
dist_methods &= (DIST_BASIC_METHOD | DIST_PULL_TO_LOCAL);
|
||||
OPT_TRACE("SPF will use basic method");
|
||||
} else if (!get_optimizer_context().is_var_assign_only_in_root_stmt()
|
||||
&& get_optimizer_context().has_var_assign()) {
|
||||
dist_methods &= (DIST_BASIC_METHOD | DIST_PULL_TO_LOCAL);
|
||||
OPT_TRACE("SPF will use pull to local method for var assign");
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogPlan::inner_candi_allocate_subplan_filter(ObIArray<ObSEArray<CandidatePlan,4>> &best_list,
|
||||
ObIArray<ObSEArray<CandidatePlan,4>> &dist_best_list,
|
||||
ObIArray<ObQueryRefRawExpr *> &query_refs,
|
||||
ObIArray<ObExecParamRawExpr *> ¶ms,
|
||||
ObIArray<ObExecParamRawExpr *> &onetime_exprs,
|
||||
ObBitSet<> &initplan_idxs,
|
||||
ObBitSet<> &onetime_idxs,
|
||||
const ObIArray<ObRawExpr *> &filters,
|
||||
const bool for_cursor_expr,
|
||||
const bool is_update_set,
|
||||
const int64_t dist_methods,
|
||||
ObIArray<CandidatePlan> &subquery_plans)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
CandidatePlan candidate_plan;
|
||||
ObSEArray<int64_t, 4> move_pos;
|
||||
ObSEArray<ObLogicalOperator*, 4> child_ops;
|
||||
ObSEArray<ObLogicalOperator*, 4> dist_child_ops;
|
||||
// generate subplan filter
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < candidates_.candidate_plans_.count(); i++) {
|
||||
candidate_plan = candidates_.candidate_plans_.at(i);
|
||||
@ -9132,17 +9273,27 @@ int ObLogPlan::inner_candi_allocate_subplan_filter(ObIArray<ObLogPlan*> &subplan
|
||||
if (OB_SUCC(ret)) {
|
||||
CandidatePlan curr_candidate_plan;
|
||||
curr_candidate_plan.plan_tree_ = candidate_plan.plan_tree_;
|
||||
if (OB_FAIL(create_subplan_filter_plan(curr_candidate_plan.plan_tree_,
|
||||
child_ops,
|
||||
dist_child_ops,
|
||||
query_refs,
|
||||
params,
|
||||
onetime_exprs,
|
||||
initplan_idxs,
|
||||
onetime_idxs,
|
||||
for_cursor_expr,
|
||||
filters,
|
||||
is_update_set))) {
|
||||
int64_t cur_dist_methods = dist_methods;
|
||||
if (OB_FAIL(get_subplan_filter_distributed_method(curr_candidate_plan.plan_tree_,
|
||||
child_ops,
|
||||
params,
|
||||
for_cursor_expr,
|
||||
!onetime_idxs.is_empty(),
|
||||
cur_dist_methods))) {
|
||||
LOG_WARN("failed to get subplan filter distributed method", K(ret));
|
||||
} else if (0 == cur_dist_methods) {
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(create_subplan_filter_plan(curr_candidate_plan.plan_tree_,
|
||||
child_ops,
|
||||
dist_child_ops,
|
||||
query_refs,
|
||||
params,
|
||||
onetime_exprs,
|
||||
initplan_idxs,
|
||||
onetime_idxs,
|
||||
cur_dist_methods,
|
||||
filters,
|
||||
is_update_set))) {
|
||||
LOG_WARN("failed to create subplan filter plan", K(ret));
|
||||
} else if (OB_FAIL(subquery_plans.push_back(curr_candidate_plan))) {
|
||||
LOG_WARN("failed to push back subquery plans", K(ret));
|
||||
@ -9164,11 +9315,6 @@ int ObLogPlan::inner_candi_allocate_subplan_filter(ObIArray<ObLogPlan*> &subplan
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
/*do nothing*/
|
||||
} else if (OB_FAIL(prune_and_keep_best_plans(subquery_plans))) {
|
||||
LOG_WARN("failed to prune and keep best plans", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -9310,18 +9456,12 @@ int ObLogPlan::adjust_exprs_with_onetime(ObIArray<ObRawExpr *> &exprs)
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObLogPlan::create_subplan_filter_plan(ObLogicalOperator *&top,
|
||||
const ObIArray<ObLogicalOperator*> &subquery_ops,
|
||||
const ObIArray<ObLogicalOperator*> &dist_subquery_ops,
|
||||
const ObIArray<ObQueryRefRawExpr *> &query_ref_exprs,
|
||||
const ObIArray<ObExecParamRawExpr *> ¶ms,
|
||||
const ObIArray<ObExecParamRawExpr *> &onetime_exprs,
|
||||
const ObBitSet<> &initplan_idxs,
|
||||
const ObBitSet<> &onetime_idxs,
|
||||
const bool for_cursor_expr,
|
||||
const ObIArray<ObRawExpr*> *filters,
|
||||
const bool is_update_set)
|
||||
int ObLogPlan::get_subplan_filter_distributed_method(ObLogicalOperator *&top,
|
||||
const ObIArray<ObLogicalOperator*> &subquery_ops,
|
||||
const ObIArray<ObExecParamRawExpr *> ¶ms,
|
||||
const bool for_cursor_expr,
|
||||
const bool has_onetime,
|
||||
int64_t &distributed_methods)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool is_basic = false;
|
||||
@ -9332,7 +9472,7 @@ int ObLogPlan::create_subplan_filter_plan(ObLogicalOperator *&top,
|
||||
bool is_all_none = false;
|
||||
bool is_partition_none = false;
|
||||
ObSEArray<ObLogicalOperator*, 8> sf_childs;
|
||||
DistAlgo dist_algo = DistAlgo::DIST_INVALID_METHOD;
|
||||
|
||||
if (OB_ISNULL(top)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
@ -9344,93 +9484,105 @@ int ObLogPlan::create_subplan_filter_plan(ObLogicalOperator *&top,
|
||||
is_basic,
|
||||
is_remote))) {
|
||||
LOG_WARN("failed to check if match basic sharding info", K(ret));
|
||||
} else if ((!for_cursor_expr && is_basic) ||
|
||||
(for_cursor_expr && is_basic && !is_remote)) {
|
||||
dist_algo = DistAlgo::DIST_BASIC_METHOD;
|
||||
OPT_TRACE("SPF will use basic method");
|
||||
} else if (for_cursor_expr) {
|
||||
dist_algo = DistAlgo::DIST_PULL_TO_LOCAL;
|
||||
OPT_TRACE("SPF will use pull to local method for cursor subquery expr");
|
||||
} else if (OB_FAIL(check_contains_recursive_cte(sf_childs,
|
||||
is_recursive_cte))) {
|
||||
LOG_WARN("failed to check whether contains recursive cte", K(ret));
|
||||
} else if (is_recursive_cte) {
|
||||
dist_algo = DistAlgo::DIST_PULL_TO_LOCAL;
|
||||
OPT_TRACE("SPF will use pull to local method for recursive cte");
|
||||
} else if (!get_optimizer_context().is_var_assign_only_in_root_stmt() &&
|
||||
get_optimizer_context().has_var_assign()) {
|
||||
dist_algo = DistAlgo::DIST_PULL_TO_LOCAL;
|
||||
OPT_TRACE("SPF will use pull to local method for var assign");
|
||||
} else if (OB_FAIL(check_if_subplan_filter_match_partition_wise(top,
|
||||
subquery_ops,
|
||||
params,
|
||||
is_partition_wise))) {
|
||||
LOG_WARN("failed to check if match partition wise", K(ret));
|
||||
} else if (is_partition_wise) {
|
||||
dist_algo = DistAlgo::DIST_PARTITION_WISE;
|
||||
OPT_TRACE("SPF will use partition wise method");
|
||||
} else if (OB_FAIL(check_if_subplan_filter_match_repart(top,
|
||||
subquery_ops,
|
||||
params,
|
||||
is_partition_none))) {
|
||||
LOG_WARN("failed to check if match repart", K(ret));
|
||||
} else if (is_partition_none) {
|
||||
dist_algo = DistAlgo::DIST_PARTITION_NONE;
|
||||
OPT_TRACE("SPF will use repartition method");
|
||||
} else if (OB_FAIL(check_if_match_none_all(top,
|
||||
subquery_ops,
|
||||
is_none_all))) {
|
||||
LOG_WARN("failed to check if match none all", K(ret));
|
||||
} else if (is_none_all && onetime_idxs.is_empty()) {
|
||||
dist_algo = DistAlgo::DIST_NONE_ALL;
|
||||
OPT_TRACE("SPF will use none all method");
|
||||
} else {
|
||||
dist_algo = DistAlgo::DIST_PULL_TO_LOCAL;
|
||||
} else if (is_basic && !is_remote) {
|
||||
distributed_methods &= DistAlgo::DIST_BASIC_METHOD;
|
||||
} else if (is_remote) {
|
||||
distributed_methods &= (DIST_BASIC_METHOD | DIST_PULL_TO_LOCAL);
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && (distributed_methods & DistAlgo::DIST_NONE_ALL)) {
|
||||
if (OB_FAIL(check_if_match_none_all(top, subquery_ops, is_none_all))) {
|
||||
LOG_WARN("failed to check if match repart", K(ret));
|
||||
} else if (is_none_all && !has_onetime) {
|
||||
distributed_methods = DistAlgo::DIST_NONE_ALL;
|
||||
OPT_TRACE("SPF will use none all method");
|
||||
} else {
|
||||
distributed_methods &= ~DIST_NONE_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && (distributed_methods & DistAlgo::DIST_BASIC_METHOD)) {
|
||||
if (is_basic && (!for_cursor_expr || !is_remote)) {
|
||||
distributed_methods = DistAlgo::DIST_BASIC_METHOD;
|
||||
OPT_TRACE("SPF will use basic method");
|
||||
} else {
|
||||
distributed_methods &= ~DIST_BASIC_METHOD;
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && (distributed_methods & DistAlgo::DIST_PARTITION_WISE)) {
|
||||
if (OB_FAIL(check_if_subplan_filter_match_partition_wise(top, subquery_ops, params, is_partition_wise))) {
|
||||
LOG_WARN("failed to check if match partition wise", K(ret));
|
||||
} else if (is_partition_wise) {
|
||||
distributed_methods = DistAlgo::DIST_PARTITION_WISE;
|
||||
OPT_TRACE("SPF will use partition wise method");
|
||||
} else {
|
||||
distributed_methods &= ~DIST_PARTITION_WISE;
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && (distributed_methods & DistAlgo::DIST_PARTITION_NONE)) {
|
||||
if (OB_FAIL(check_if_subplan_filter_match_repart(top, subquery_ops, params, is_partition_none))) {
|
||||
LOG_WARN("failed to check if match repart", K(ret));
|
||||
} else if (is_partition_none) {
|
||||
distributed_methods = DistAlgo::DIST_PARTITION_NONE;
|
||||
OPT_TRACE("SPF will use repartition method");
|
||||
} else {
|
||||
distributed_methods &= ~DIST_PARTITION_NONE;
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && (distributed_methods & DistAlgo::DIST_PULL_TO_LOCAL)) {
|
||||
distributed_methods = DistAlgo::DIST_PULL_TO_LOCAL;
|
||||
OPT_TRACE("SPF will use pull to local method");
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
ObExchangeInfo exch_info;
|
||||
if (DistAlgo::DIST_BASIC_METHOD == dist_algo ||
|
||||
DistAlgo::DIST_PARTITION_WISE == dist_algo ||
|
||||
DistAlgo::DIST_NONE_ALL == dist_algo) {
|
||||
// is basic or is_partition_wise
|
||||
if (OB_FAIL(allocate_subplan_filter_as_top(top,
|
||||
subquery_ops,
|
||||
query_ref_exprs,
|
||||
params,
|
||||
onetime_exprs,
|
||||
initplan_idxs,
|
||||
onetime_idxs,
|
||||
filters,
|
||||
dist_algo,
|
||||
is_update_set))) {
|
||||
LOG_WARN("failed to allocate subplan filter as top", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
} else if (DistAlgo::DIST_PARTITION_NONE == dist_algo) {
|
||||
if (OB_FAIL(compute_subplan_filter_repartition_distribution_info(top,
|
||||
subquery_ops,
|
||||
params,
|
||||
exch_info))) {
|
||||
LOG_WARN("failed to compute subplan filter distribution info", K(ret));
|
||||
} else if (OB_FAIL(allocate_exchange_as_top(top, exch_info))) {
|
||||
LOG_WARN("failed to allocate exchange as top");
|
||||
} else if (OB_FAIL(allocate_subplan_filter_as_top(top,
|
||||
subquery_ops,
|
||||
query_ref_exprs,
|
||||
params,
|
||||
onetime_exprs,
|
||||
initplan_idxs,
|
||||
onetime_idxs,
|
||||
filters,
|
||||
dist_algo,
|
||||
is_update_set))) {
|
||||
LOG_WARN("failed to allocate subplan filter as top", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
} else if (top->is_sharding() &&
|
||||
OB_FAIL(allocate_exchange_as_top(top, exch_info))) {
|
||||
LOG_WARN("failed to allocate exchange as top", K(ret));
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogPlan::create_subplan_filter_plan(ObLogicalOperator *&top,
|
||||
const ObIArray<ObLogicalOperator*> &subquery_ops,
|
||||
const ObIArray<ObLogicalOperator*> &dist_subquery_ops,
|
||||
const ObIArray<ObQueryRefRawExpr *> &query_ref_exprs,
|
||||
const ObIArray<ObExecParamRawExpr *> ¶ms,
|
||||
const ObIArray<ObExecParamRawExpr *> &onetime_exprs,
|
||||
const ObBitSet<> &initplan_idxs,
|
||||
const ObBitSet<> &onetime_idxs,
|
||||
const int64_t dist_methods,
|
||||
const ObIArray<ObRawExpr*> &filters,
|
||||
const bool is_update_set)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObExchangeInfo exch_info;
|
||||
const DistAlgo dist_algo = get_dist_algo(dist_methods);
|
||||
if (OB_ISNULL(top)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else if (DistAlgo::DIST_BASIC_METHOD == dist_algo ||
|
||||
DistAlgo::DIST_PARTITION_WISE == dist_algo ||
|
||||
DistAlgo::DIST_NONE_ALL == dist_algo) {
|
||||
// is basic or is_partition_wise
|
||||
if (OB_FAIL(allocate_subplan_filter_as_top(top,
|
||||
subquery_ops,
|
||||
query_ref_exprs,
|
||||
params,
|
||||
onetime_exprs,
|
||||
initplan_idxs,
|
||||
onetime_idxs,
|
||||
filters,
|
||||
dist_algo,
|
||||
is_update_set))) {
|
||||
LOG_WARN("failed to allocate subplan filter as top", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
} else if (DistAlgo::DIST_PARTITION_NONE == dist_algo) {
|
||||
if (OB_FAIL(compute_subplan_filter_repartition_distribution_info(top,
|
||||
subquery_ops,
|
||||
params,
|
||||
exch_info))) {
|
||||
LOG_WARN("failed to compute subplan filter distribution info", K(ret));
|
||||
} else if (OB_FAIL(allocate_exchange_as_top(top, exch_info))) {
|
||||
LOG_WARN("failed to allocate exchange as top");
|
||||
} else if (OB_FAIL(allocate_subplan_filter_as_top(top,
|
||||
dist_subquery_ops,
|
||||
subquery_ops,
|
||||
query_ref_exprs,
|
||||
params,
|
||||
onetime_exprs,
|
||||
@ -9441,23 +9593,23 @@ int ObLogPlan::create_subplan_filter_plan(ObLogicalOperator *&top,
|
||||
is_update_set))) {
|
||||
LOG_WARN("failed to allocate subplan filter as top", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogPlan::check_contains_recursive_cte(ObIArray<ObLogicalOperator*> &child_ops,
|
||||
bool &is_recursive_cte)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
is_recursive_cte = false;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && !is_recursive_cte && i < child_ops.count(); i++) {
|
||||
if (OB_ISNULL(child_ops.at(i))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret));
|
||||
} else {
|
||||
is_recursive_cte |= child_ops.at(i)->get_contains_fake_cte();
|
||||
}
|
||||
}
|
||||
} else if (OB_UNLIKELY(DistAlgo::DIST_PULL_TO_LOCAL != dist_algo)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected subplan filter distributed method", K(ret), K(dist_algo));
|
||||
} else if (top->is_sharding() && OB_FAIL(allocate_exchange_as_top(top, exch_info))) {
|
||||
LOG_WARN("failed to allocate exchange as top", K(ret));
|
||||
} else if (OB_FAIL(allocate_subplan_filter_as_top(top,
|
||||
dist_subquery_ops,
|
||||
query_ref_exprs,
|
||||
params,
|
||||
onetime_exprs,
|
||||
initplan_idxs,
|
||||
onetime_idxs,
|
||||
filters,
|
||||
dist_algo,
|
||||
is_update_set))) {
|
||||
LOG_WARN("failed to allocate subplan filter as top", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -9851,7 +10003,7 @@ int ObLogPlan::allocate_subplan_filter_as_top(ObLogicalOperator *&top,
|
||||
const ObIArray<ObExecParamRawExpr *> &onetime_exprs,
|
||||
const ObBitSet<> &initplan_idxs,
|
||||
const ObBitSet<> &onetime_idxs,
|
||||
const ObIArray<ObRawExpr*> *filters,
|
||||
const ObIArray<ObRawExpr*> &filters,
|
||||
const DistAlgo dist_algo,
|
||||
const bool is_update_set)
|
||||
{
|
||||
@ -9871,7 +10023,7 @@ int ObLogPlan::allocate_subplan_filter_as_top(ObLogicalOperator *&top,
|
||||
} else {
|
||||
spf_node->set_distributed_algo(dist_algo);
|
||||
spf_node->set_update_set(is_update_set);
|
||||
if (NULL != filters && OB_FAIL(append(spf_node->get_filter_exprs(), *filters))) {
|
||||
if (OB_FAIL(append(spf_node->get_filter_exprs(), filters))) {
|
||||
LOG_WARN("failed to append filter exprs", K(ret));
|
||||
} else if (OB_FAIL(spf_node->add_subquery_exprs(query_ref_exprs))) {
|
||||
LOG_WARN("failed to add subquery exprs", K(ret));
|
||||
|
@ -1017,10 +1017,32 @@ public:
|
||||
ObIArray<ObExecParamRawExpr *> &onetime_exprs,
|
||||
ObBitSet<> &initplan_idxs,
|
||||
ObBitSet<> &onetime_idxs,
|
||||
const ObIArray<ObRawExpr *> *filters,
|
||||
const ObIArray<ObRawExpr *> &filters,
|
||||
const bool or_cursor_expr,
|
||||
const bool is_update_set);
|
||||
|
||||
int inner_candi_allocate_subplan_filter(ObIArray<ObSEArray<CandidatePlan, 4>> &best_list,
|
||||
ObIArray<ObSEArray<CandidatePlan, 4>> &dist_best_list,
|
||||
ObIArray<ObQueryRefRawExpr *> &query_refs,
|
||||
ObIArray<ObExecParamRawExpr *> ¶ms,
|
||||
ObIArray<ObExecParamRawExpr *> &onetime_exprs,
|
||||
ObBitSet<> &initplan_idxs,
|
||||
ObBitSet<> &onetime_idxs,
|
||||
const ObIArray<ObRawExpr *> &filters,
|
||||
const bool for_cursor_expr,
|
||||
const bool is_update_set,
|
||||
const int64_t dist_methods,
|
||||
ObIArray<CandidatePlan> &subquery_plans);
|
||||
|
||||
int prepare_subplan_candidate_list(ObIArray<ObLogPlan*> &subplans,
|
||||
ObIArray<ObExecParamRawExpr *> ¶ms,
|
||||
ObIArray<ObSEArray<CandidatePlan, 4>> &best_list,
|
||||
ObIArray<ObSEArray<CandidatePlan, 4>> &dist_best_list);
|
||||
int get_valid_subplan_filter_dist_method(ObIArray<ObLogPlan*> &subplans,
|
||||
const bool for_cursor_expr,
|
||||
const bool ignore_hint,
|
||||
int64_t &dist_methods);
|
||||
|
||||
int generate_subplan_filter_info(const ObIArray<ObRawExpr*> &subquery_exprs,
|
||||
ObIArray<ObLogPlan*> &subquery_ops,
|
||||
ObIArray<ObQueryRefRawExpr *> &query_refs,
|
||||
@ -1038,6 +1060,12 @@ public:
|
||||
|
||||
int adjust_exprs_with_onetime(ObIArray<ObRawExpr *> &exprs);
|
||||
|
||||
int get_subplan_filter_distributed_method(ObLogicalOperator *&top,
|
||||
const ObIArray<ObLogicalOperator*> &subquery_ops,
|
||||
const ObIArray<ObExecParamRawExpr *> ¶ms,
|
||||
const bool for_cursor_expr,
|
||||
const bool has_onetime,
|
||||
int64_t &distributed_methods);
|
||||
int create_subplan_filter_plan(ObLogicalOperator *&top,
|
||||
const ObIArray<ObLogicalOperator*> &subquery_ops,
|
||||
const ObIArray<ObLogicalOperator*> &dist_subquery_ops,
|
||||
@ -1046,8 +1074,8 @@ public:
|
||||
const ObIArray<ObExecParamRawExpr *> &onetime_exprs,
|
||||
const ObBitSet<> &initplan_idxs,
|
||||
const ObBitSet<> &onetime_idxs,
|
||||
const bool for_cursor_expr,
|
||||
const ObIArray<ObRawExpr*> *filters,
|
||||
const int64_t dist_methods,
|
||||
const ObIArray<ObRawExpr*> &filters,
|
||||
const bool is_update_set);
|
||||
|
||||
int check_contains_recursive_cte(ObIArray<ObLogicalOperator*> &child_ops,
|
||||
@ -1095,7 +1123,7 @@ public:
|
||||
const ObIArray<ObExecParamRawExpr *> &onetime_exprs,
|
||||
const ObBitSet<> &initplan_idxs,
|
||||
const ObBitSet<> &onetime_idxs,
|
||||
const ObIArray<ObRawExpr*> *filters,
|
||||
const ObIArray<ObRawExpr*> &filters,
|
||||
const DistAlgo dist_algo,
|
||||
const bool is_update_set);
|
||||
int allocate_subplan_filter_as_top(ObLogicalOperator *&old_top,
|
||||
|
@ -837,3 +837,77 @@ int ObLogSubPlanFilter::compute_op_parallel_and_server_info()
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogSubPlanFilter::print_outline_data(PlanText &plan_text)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObPQSubqueryHint hint;
|
||||
const ObDMLStmt *stmt = NULL;
|
||||
ObString qb_name;
|
||||
if (OB_ISNULL(get_plan()) || OB_ISNULL(stmt = get_plan()->get_stmt())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected NULl", K(ret), K(get_plan()), K(stmt));
|
||||
} else if (DistAlgo::DIST_BASIC_METHOD == get_distributed_algo()) {
|
||||
/* do not print data for basic. need remove this when support split subplan filter op */
|
||||
} else if (OB_FAIL(get_sub_qb_names(hint.get_sub_qb_names()))) {
|
||||
LOG_WARN("fail to get subplan qb_names", K(ret));
|
||||
} else if (OB_FAIL(stmt->get_qb_name(qb_name))) {
|
||||
LOG_WARN("fail to get qb_name", K(ret), K(stmt->get_stmt_id()));
|
||||
} else {
|
||||
hint.set_dist_algo(get_distributed_algo());
|
||||
hint.set_qb_name(qb_name);
|
||||
if (OB_FAIL(hint.print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print pq subquery hint", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogSubPlanFilter::print_used_hint(PlanText &plan_text)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObPQSubqueryHint *explicit_hint = NULL;
|
||||
const ObPQSubqueryHint *implicit_hint = NULL;
|
||||
const ObPQSubqueryHint *hint = NULL;
|
||||
ObSEArray<ObString, 4> sub_qb_names;
|
||||
if (OB_ISNULL(get_plan()) || OB_ISNULL(get_plan()->get_stmt())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected NULl", K(ret), K(get_plan()));
|
||||
} else if (OB_FAIL(get_sub_qb_names(sub_qb_names))) {
|
||||
LOG_WARN("fail to get subplan qb_names", K(ret));
|
||||
} else if (OB_FAIL(get_plan()->get_log_plan_hint().get_valid_pq_subquery_hint(sub_qb_names,
|
||||
explicit_hint,
|
||||
implicit_hint))) {
|
||||
LOG_WARN("fail to get valid pq subquery hint", K(ret));
|
||||
} else if (NULL == (hint = (NULL == explicit_hint
|
||||
&& sub_qb_names.count() == get_plan()->get_stmt()->get_subquery_expr_size())
|
||||
? implicit_hint : explicit_hint)) {
|
||||
/* do nothing */
|
||||
} else if (get_distributed_algo() != hint->get_dist_algo()) {
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(hint->print_hint(plan_text))) {
|
||||
LOG_WARN("failed to print used pq pq subquery hint", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogSubPlanFilter::get_sub_qb_names(ObIArray<ObString> &sub_qb_names)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
sub_qb_names.reuse();
|
||||
ObLogicalOperator *child = NULL;
|
||||
const ObDMLStmt *stmt = NULL;
|
||||
ObString qb_name;
|
||||
for (int64_t i = 1; OB_SUCC(ret) && i < get_num_of_child(); i++) {
|
||||
if (OB_ISNULL(child = get_child(i)) || OB_ISNULL(child->get_plan())
|
||||
|| OB_ISNULL(stmt = child->get_plan()->get_stmt())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null", K(ret), K(child), K(stmt));
|
||||
} else if (OB_FAIL(stmt->get_qb_name(qb_name))) {
|
||||
LOG_WARN("fail to get qb_name", K(ret), K(stmt->get_stmt_id()));
|
||||
} else if (OB_FAIL(sub_qb_names.push_back(qb_name))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
@ -131,11 +131,14 @@ public:
|
||||
ObShardingInfo *&out_sharding);
|
||||
|
||||
virtual int compute_op_parallel_and_server_info() override;
|
||||
virtual int print_outline_data(PlanText &plan_text) override;
|
||||
virtual int print_used_hint(PlanText &plan_text) override;
|
||||
private:
|
||||
int extract_exist_style_subquery_exprs(ObRawExpr *expr,
|
||||
ObIArray<ObRawExpr*> &exist_style_exprs);
|
||||
int check_expr_contain_row_subquery(const ObRawExpr *expr,
|
||||
bool &contains);
|
||||
int get_sub_qb_names(ObIArray<ObString>& sub_qb_names);
|
||||
protected:
|
||||
DistAlgo dist_algo_;
|
||||
common::ObSEArray<ObQueryRefRawExpr *, 8, common::ModulePageAllocator, true> subquery_exprs_;
|
||||
|
@ -425,39 +425,142 @@ int ObOptimizerUtil::adjust_exprs_by_ordering(ObIArray<ObRawExpr *> &exprs,
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
prefix_count = adjusted_exprs.count();
|
||||
ordering_all_used = prefix_count > 0;
|
||||
}
|
||||
for (int64_t j = 0; OB_SUCC(ret) && j < exprs.count(); ++j) {
|
||||
if (expr_idxs.has_member(j)) {
|
||||
//已经和其它序的表达式对应了,不再参与比较
|
||||
} else if (OB_FAIL(adjusted_exprs.push_back(exprs.at(j)))) {
|
||||
LOG_WARN("store ordered expr failed", K(ret), K(j));
|
||||
} else if (OB_FAIL(expr_map.push_back(j))) {
|
||||
LOG_WARN("failed to push back expr index", K(ret));
|
||||
} else if (OB_FAIL(order_types.push_back(directions.at(j)))) {
|
||||
LOG_WARN("failed to push back order type", K(ret));
|
||||
} else if (OB_FAIL(expr_idxs.add_member(j))) {
|
||||
LOG_WARN("add expr idxs member failed", K(ret), K(j));
|
||||
} else {
|
||||
ordering_all_used = false;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (adjusted_exprs.count() != exprs.count()
|
||||
|| order_types.count() != exprs.count()) {
|
||||
ordering_all_used = prefix_count > 0 && expr_idxs.num_members() == exprs.count();
|
||||
if (OB_FAIL(generate_stable_ordering(exprs, directions, expr_idxs, expr_map,
|
||||
adjusted_exprs, order_types))) {
|
||||
LOG_WARN("failed to generate stable ordering", K(ret));
|
||||
} else if (OB_UNLIKELY(adjusted_exprs.count() != exprs.count()
|
||||
|| order_types.count() != exprs.count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("exprs don't covered completely by ordering",
|
||||
K(adjusted_exprs.count()), K(exprs.count()), K(order_types.count()));
|
||||
} else if (OB_FAIL(exprs.assign(adjusted_exprs))) {
|
||||
LOG_WARN("assign adjusted exprs failed", K(ret));
|
||||
} else if (OB_FAIL(directions.assign(order_types))) {
|
||||
LOG_WARN("failed to assign order types", K(ret));
|
||||
} else if (match_map != NULL && OB_FAIL(match_map->assign(expr_map))) {
|
||||
LOG_WARN("failed to assign expr indexs", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// when there is no input ordering or interesting ordering, generate a stable ordering use this function
|
||||
int ObOptimizerUtil::generate_stable_ordering(common::ObIArray<ObRawExpr *> &exprs,
|
||||
ObIArray<ObOrderDirection> &directions)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObBitSet<64> used_expr_idxs;
|
||||
ObSEArray<int64_t, 8> expr_map;
|
||||
ObSEArray<ObRawExpr *, 8> adjusted_exprs;
|
||||
ObSEArray<ObOrderDirection, 8> adjusted_directions;
|
||||
if (OB_FAIL(generate_stable_ordering(exprs,
|
||||
directions,
|
||||
used_expr_idxs,
|
||||
expr_map,
|
||||
adjusted_exprs,
|
||||
adjusted_directions))) {
|
||||
LOG_WARN("failed to generate stable ordering", K(ret));
|
||||
} else if (OB_FAIL(exprs.assign(adjusted_exprs))) {
|
||||
LOG_WARN("assign adjusted exprs failed", K(ret));
|
||||
} else if (OB_FAIL(directions.assign(adjusted_directions))) {
|
||||
LOG_WARN("failed to assign order types", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// when there is no input ordering or interesting ordering, generate a stable ordering use this function
|
||||
int ObOptimizerUtil::generate_stable_ordering(common::ObIArray<ObRawExpr *> &exprs,
|
||||
ObIArray<ObOrderDirection> &directions,
|
||||
ObBitSet<64> &used_expr_idxs,
|
||||
ObIArray<int64_t> &expr_map,
|
||||
ObIArray<ObRawExpr*> &adjusted_exprs,
|
||||
ObIArray<ObOrderDirection> &adjusted_directions)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<std::pair<ObRawExpr*,int64_t>, 8> sort_pairs;
|
||||
int64_t idx = OB_INVALID_INDEX;
|
||||
if (OB_UNLIKELY(exprs.count() != directions.count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected array count", K(ret), K(exprs.count()), K(directions.count()));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) {
|
||||
if (!used_expr_idxs.has_member(i) &&
|
||||
OB_FAIL(sort_pairs.push_back(std::pair<ObRawExpr*,int64_t>(exprs.at(i), i)))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
// do not generate stable ordering now, remove comment for this sort when need stable ordering
|
||||
// std::sort(sort_pairs.begin(), sort_pairs.end(), stable_expr_cmp_func);
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < sort_pairs.count(); ++i) {
|
||||
idx = sort_pairs.at(i).second;
|
||||
if (OB_UNLIKELY(exprs.count() <= idx)) {
|
||||
LOG_WARN("unexpected idx", K(ret), K(exprs.count()), K(i), K(idx));
|
||||
} else if (OB_FAIL(adjusted_exprs.push_back(exprs.at(idx)))) {
|
||||
LOG_WARN("store ordered expr failed", K(ret), K(idx));
|
||||
} else if (OB_FAIL(expr_map.push_back(idx))) {
|
||||
LOG_WARN("failed to push back expr index", K(ret));
|
||||
} else if (OB_FAIL(adjusted_directions.push_back(directions.at(idx)))) {
|
||||
LOG_WARN("failed to push back order type", K(ret));
|
||||
} else if (OB_FAIL(used_expr_idxs.add_member(idx))) {
|
||||
LOG_WARN("add expr idxs member failed", K(ret), K(idx));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
// used to generate specific ordering exprs
|
||||
bool ObOptimizerUtil::stable_expr_cmp_func(std::pair<ObRawExpr*,int64_t> l_pair,
|
||||
std::pair<ObRawExpr*,int64_t> r_pair)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
bool bret = false;
|
||||
int64_t res = 0;
|
||||
if (OB_FAIL(cmp_expr(l_pair.first, r_pair.first, res))) {
|
||||
LOG_WARN("failed to compare two expr", K(ret), K(res), K(lbt()), KPC(l_pair.first), KPC(r_pair.first));
|
||||
} else {
|
||||
bret = (res <= 0);
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
|
||||
// used to generate specific ordering exprs
|
||||
int ObOptimizerUtil::cmp_expr(ObRawExpr *l_expr, ObRawExpr *r_expr, int64_t &res)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
res = 0;
|
||||
if (OB_ISNULL(l_expr) || OB_ISNULL(r_expr)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(l_expr), K(r_expr));
|
||||
} else if (l_expr->get_expr_type() != r_expr->get_expr_type()) {
|
||||
if (l_expr->is_column_ref_expr() || r_expr->is_column_ref_expr()) {
|
||||
res = l_expr->is_column_ref_expr() ? -1 : 1;
|
||||
} else {
|
||||
exprs.reuse();
|
||||
if (OB_FAIL(exprs.assign(adjusted_exprs))) {
|
||||
LOG_WARN("assign adjusted exprs failed", K(ret));
|
||||
} else if (OB_FAIL(directions.assign(order_types))) {
|
||||
LOG_WARN("failed to assign order types", K(ret));
|
||||
} else if (match_map != NULL && OB_FAIL(match_map->assign(expr_map))) {
|
||||
LOG_WARN("failed to assign expr indexs", K(ret));
|
||||
res = l_expr->get_expr_type() < r_expr->get_expr_type() ? -1 : 1;
|
||||
}
|
||||
} else if (l_expr->is_column_ref_expr()) {
|
||||
ObColumnRefRawExpr *l_col = static_cast<ObColumnRefRawExpr*>(l_expr);
|
||||
ObColumnRefRawExpr *r_col = static_cast<ObColumnRefRawExpr*>(r_expr);
|
||||
if (l_col->get_table_id() != r_col->get_table_id()) {
|
||||
res = l_col->get_table_id() < r_col->get_table_id() ? -1 : 1;
|
||||
} else if (l_col->get_column_id() != r_col->get_column_id()) {
|
||||
res = l_col->get_column_id() < r_col->get_column_id() ? -1 : 1;
|
||||
}
|
||||
} else if (l_expr->is_set_op_expr()) {
|
||||
res = static_cast<ObSetOpRawExpr*>(l_expr)->get_idx() < static_cast<ObSetOpRawExpr*>(r_expr)->get_idx()
|
||||
? -1 : 1;
|
||||
} else if (l_expr->get_param_count() != r_expr->get_param_count()) {
|
||||
res = l_expr->get_param_count() < r_expr->get_param_count() ? -1 : 1;
|
||||
} else if (0 != l_expr->get_param_count()) {
|
||||
for (int64_t i = 0; 0 == res && OB_SUCC(ret) && i < l_expr->get_param_count(); ++i) {
|
||||
if (OB_FAIL(SMART_CALL(cmp_expr(l_expr->get_param_expr(i), r_expr->get_param_expr(i), res)))) {
|
||||
LOG_WARN("failed to smart call compare two expr", K(ret), K(res));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* do nothing now */
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@ -4615,6 +4718,8 @@ int ObOptimizerUtil::simplify_exprs(const ObFdItemSet &fd_item_set,
|
||||
ObRawExprSet *min_parent_exprs = NULL;
|
||||
bool is_contain = false;
|
||||
bool is_in_child = false;
|
||||
ObSqlBitSet<> root_exprs_set;
|
||||
int64_t expr_idx = -1;
|
||||
root_exprs.reset();
|
||||
// 将 fd item 分为unique的和非unique的
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < fd_item_set.count(); ++i) {
|
||||
@ -4647,11 +4752,10 @@ int ObOptimizerUtil::simplify_exprs(const ObFdItemSet &fd_item_set,
|
||||
}
|
||||
// 找到一个unique fd item, 直接从candi exprs里找出匹配parent set的expr
|
||||
if (OB_SUCC(ret) && NULL != min_parent_exprs) {
|
||||
int64_t expr_idx = -1;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < min_parent_exprs->count(); ++i) {
|
||||
if (find_equal_expr(candi_exprs, min_parent_exprs->at(i), equal_sets, expr_idx)) {
|
||||
if (OB_FAIL(root_exprs.push_back(candi_exprs.at(expr_idx)))) {
|
||||
LOG_WARN("failed to push back root expr", K(ret));
|
||||
if (OB_FAIL(root_exprs_set.add_member(expr_idx))) {
|
||||
LOG_WARN("failed to add member", K(ret));
|
||||
}
|
||||
} else { /* not find means min_parent_exprs->at(i) is const, do nothing */ }
|
||||
}
|
||||
@ -4671,7 +4775,6 @@ int ObOptimizerUtil::simplify_exprs(const ObFdItemSet &fd_item_set,
|
||||
} else if (is_contain) {
|
||||
ObSEArray<ObRawExpr *, 8> left_domain;
|
||||
ObSEArray<ObRawExpr *, 8> right_domain;
|
||||
int64_t expr_idx = -1;
|
||||
// 生成新的root exprs集合
|
||||
for (int64_t j = 0; OB_SUCC(ret) && j < root_exprs.count(); ++j) {
|
||||
if (OB_FAIL(left_domain.push_back(root_exprs.at(j)))) {
|
||||
@ -4720,18 +4823,35 @@ int ObOptimizerUtil::simplify_exprs(const ObFdItemSet &fd_item_set,
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < root_exprs.count(); ++i) {
|
||||
if(OB_UNLIKELY(!find_item(candi_exprs, root_exprs.at(i), &expr_idx))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("failed to find item", K(ret));
|
||||
} else if (OB_FAIL(root_exprs_set.add_member(expr_idx))) {
|
||||
LOG_WARN("failed to add member", K(ret));
|
||||
}
|
||||
}
|
||||
// 所有non unique fd item都遍历过了, 但是还有其它无法被决定的expr, 直接加入到root exprs中
|
||||
if (OB_SUCC(ret) && eliminate_set.num_members() < candi_exprs.count()) {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < candi_exprs.count(); ++i) {
|
||||
if (eliminate_set.has_member(i)) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(root_exprs.push_back(candi_exprs.at(i)))) {
|
||||
LOG_WARN("failed to push back candi expr", K(ret));
|
||||
} else if (OB_FAIL(root_exprs_set.add_member(i))) {
|
||||
LOG_WARN("failed to add member", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
root_exprs.reuse();
|
||||
// use bitset to keep exprs ordering
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < candi_exprs.count(); ++i) {
|
||||
if (!root_exprs_set.has_member(i)) {
|
||||
// do nothing
|
||||
} else if (OB_FAIL(root_exprs.push_back(candi_exprs.at(i)))) {
|
||||
LOG_WARN("failed to push back candi expr", K(ret));
|
||||
}
|
||||
}
|
||||
LOG_TRACE("succeed to simply exprs", K(fd_item_set), K(equal_sets), K(const_exprs),
|
||||
K(candi_exprs), K(root_exprs));
|
||||
}
|
||||
|
@ -127,6 +127,18 @@ public:
|
||||
bool &ordering_all_used,
|
||||
common::ObIArray<ObOrderDirection> &directions,
|
||||
common::ObIArray<int64_t> *match_map = NULL);
|
||||
// when there is no input ordering or interesting ordering, generate a stable ordering use this function
|
||||
static int generate_stable_ordering(common::ObIArray<ObRawExpr *> &exprs,
|
||||
ObIArray<ObOrderDirection> &directions);
|
||||
static int generate_stable_ordering(common::ObIArray<ObRawExpr *> &exprs,
|
||||
ObIArray<ObOrderDirection> &directions,
|
||||
ObBitSet<64> &used_expr_idxs,
|
||||
ObIArray<int64_t> &expr_map,
|
||||
ObIArray<ObRawExpr*> &adjusted_exprs,
|
||||
ObIArray<ObOrderDirection> &adjusted_directions);
|
||||
static bool stable_expr_cmp_func(std::pair<ObRawExpr*,int64_t> l_pair,
|
||||
std::pair<ObRawExpr*,int64_t> r_pair);
|
||||
static int cmp_expr(ObRawExpr *l_expr, ObRawExpr *r_expr, int64_t &res);
|
||||
|
||||
static int adjust_exprs_by_mapping(const common::ObIArray<ObRawExpr *> &exprs,
|
||||
const common::ObIArray<int64_t> &match_map,
|
||||
|
@ -1038,6 +1038,7 @@ Timestamp{whitespace}?\"[^\"]*\" {
|
||||
<hint>PQ_DISTRIBUTE_WINDOW { return PQ_DISTRIBUTE_WINDOW; }
|
||||
<hint>PQ_MAP { return PQ_MAP; }
|
||||
<hint>PQ_SET { return PQ_SET; }
|
||||
<hint>PQ_SUBQUERY { return PQ_SUBQUERY; }
|
||||
<hint>RANDOM_LOCAL { return RANDOM_LOCAL; }
|
||||
<hint>RANDOM { return RANDOM; }
|
||||
<hint>BROADCAST { return BROADCAST; }
|
||||
|
@ -185,7 +185,7 @@ USE_HASH_AGGREGATION NO_USE_HASH_AGGREGATION
|
||||
PARTITION_SORT NO_PARTITION_SORT WF_TOPN
|
||||
USE_LATE_MATERIALIZATION NO_USE_LATE_MATERIALIZATION
|
||||
PX_JOIN_FILTER NO_PX_JOIN_FILTER PX_PART_JOIN_FILTER NO_PX_PART_JOIN_FILTER
|
||||
PQ_MAP PQ_DISTRIBUTE PQ_DISTRIBUTE_WINDOW PQ_SET RANDOM_LOCAL BROADCAST BC2HOST LIST
|
||||
PQ_MAP PQ_DISTRIBUTE PQ_DISTRIBUTE_WINDOW PQ_SET PQ_SUBQUERY RANDOM_LOCAL BROADCAST BC2HOST LIST
|
||||
GBY_PUSHDOWN NO_GBY_PUSHDOWN
|
||||
USE_HASH_DISTINCT NO_USE_HASH_DISTINCT
|
||||
DISTINCT_PUSHDOWN NO_DISTINCT_PUSHDOWN
|
||||
@ -507,7 +507,7 @@ END_P SET_VAR DELIMITER
|
||||
%type <node> optimize_stmt
|
||||
%type <node> dump_memory_stmt
|
||||
%type <node> create_savepoint_stmt rollback_savepoint_stmt release_savepoint_stmt
|
||||
%type <node> opt_qb_name parallel_hint pq_set_hint_desc
|
||||
%type <node> opt_qb_name opt_qb_name_list_with_quotes parallel_hint pq_set_hint_desc pq_subquery_hint_desc
|
||||
%type <node> create_tablespace_stmt drop_tablespace_stmt tablespace rotate_master_key_stmt
|
||||
%type <node> alter_tablespace_stmt
|
||||
%type <node> permanent_tablespace permanent_tablespace_options permanent_tablespace_option alter_tablespace_actions alter_tablespace_action opt_force_purge
|
||||
@ -10434,6 +10434,11 @@ INDEX_HINT '(' qb_name_option relation_factor_in_hint NAME_OB ')'
|
||||
{
|
||||
$$ = $3;
|
||||
}
|
||||
| PQ_SUBQUERY '('qb_name_option opt_comma pq_subquery_hint_desc ')'
|
||||
{
|
||||
(void)($4); /* unused */
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_PQ_SUBQUERY, 3, $3, $5->children_[0], $5->children_[1]);
|
||||
}
|
||||
| GBY_PUSHDOWN opt_qb_name
|
||||
{
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_GBY_PUSHDOWN, 1, $2);
|
||||
@ -10563,6 +10568,26 @@ pq_set_hint_desc:
|
||||
}
|
||||
;
|
||||
|
||||
pq_subquery_hint_desc:
|
||||
opt_qb_name_list_with_quotes distribute_method_list
|
||||
{
|
||||
ParseNode *method_list = NULL;
|
||||
merge_nodes(method_list, result, T_DISTRIBUTE_METHOD_LIST, $2);
|
||||
malloc_non_terminal_node($$, result->malloc_pool_, T_INVALID, 2, $1, method_list);
|
||||
}
|
||||
;
|
||||
|
||||
opt_qb_name_list_with_quotes:
|
||||
'(' qb_name_list ')'
|
||||
{
|
||||
merge_nodes($$, result, T_QB_NAME_LIST, $2);
|
||||
}
|
||||
| /*empty*/
|
||||
{
|
||||
$$ = NULL;
|
||||
}
|
||||
;
|
||||
|
||||
opt_qb_name:
|
||||
'(' qb_name_option ')'
|
||||
{
|
||||
|
@ -4479,17 +4479,21 @@ int ObDMLResolver::resolve_generate_table_item(ObSelectStmt *ref_query,
|
||||
int ret = OB_SUCCESS;
|
||||
TableItem *item = NULL;
|
||||
ObDMLStmt *dml_stmt = get_stmt();
|
||||
ObString used_alias_name = alias_name;
|
||||
if (OB_ISNULL(dml_stmt) || OB_ISNULL(allocator_)) {
|
||||
ret = OB_NOT_INIT;
|
||||
LOG_WARN("resolver isn't init");
|
||||
} else if (OB_UNLIKELY(NULL == (item = dml_stmt->create_table_item(*allocator_)))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("create table item failed");
|
||||
} else if (used_alias_name.empty()
|
||||
&& OB_FAIL(dml_stmt->generate_anonymous_view_name(*allocator_, used_alias_name))) {
|
||||
LOG_WARN("failed to generate view name", K(ret));
|
||||
} else {
|
||||
item->ref_query_ = ref_query;
|
||||
item->table_id_ = generate_table_id();
|
||||
item->table_name_ = alias_name;
|
||||
item->alias_name_ = alias_name;
|
||||
item->table_name_ = used_alias_name;
|
||||
item->alias_name_ = used_alias_name;
|
||||
item->type_ = TableItem::GENERATED_TABLE;
|
||||
item->is_view_table_ = false;
|
||||
if (OB_FAIL(dml_stmt->add_table_item(session_info_, item, params_.have_same_table_name_))) {
|
||||
@ -13377,6 +13381,12 @@ int ObDMLResolver::resolve_optimize_hint(const ParseNode &hint_node,
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_PQ_SUBQUERY: {
|
||||
if (OB_FAIL(resolve_pq_subquery_hint(hint_node, opt_hint))) {
|
||||
LOG_WARN("failed to resolve pq subquery hint", K(ret));
|
||||
}
|
||||
break;
|
||||
}
|
||||
case T_USE_LATE_MATERIALIZATION:
|
||||
case T_NO_USE_LATE_MATERIALIZATION:
|
||||
case T_GBY_PUSHDOWN:
|
||||
@ -13783,6 +13793,66 @@ int ObDMLResolver::get_valid_dist_methods(const ParseNode *dist_methods_node,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDMLResolver::resolve_pq_subquery_hint(const ParseNode &hint_node,
|
||||
ObOptHint *&opt_hint)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
opt_hint = NULL;
|
||||
const ParseNode *dist_methods_node = NULL;
|
||||
if (OB_UNLIKELY(3 != hint_node.num_child_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected pq_subquery hint node", K(ret), K(hint_node.num_child_));
|
||||
} else {
|
||||
DistAlgo dist_algo = DistAlgo::DIST_INVALID_METHOD;
|
||||
if (OB_ISNULL(dist_methods_node = hint_node.children_[2])) {
|
||||
dist_algo = DistAlgo::DIST_BASIC_METHOD;
|
||||
} else if (OB_UNLIKELY(T_DISTRIBUTE_METHOD_LIST != dist_methods_node->type_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected pq_subquery hint node", K(ret), K(get_type_name(dist_methods_node->type_)));
|
||||
} else if (OB_UNLIKELY(2 != dist_methods_node->num_child_)
|
||||
|| OB_ISNULL(dist_methods_node->children_[0])
|
||||
|| OB_ISNULL(dist_methods_node->children_[1])) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected disdist methods node", K(ret));
|
||||
} else {
|
||||
ObItemType outer = dist_methods_node->children_[0]->type_;
|
||||
ObItemType inner = dist_methods_node->children_[1]->type_;
|
||||
// pq_subquery(@sel$1 (sel$2 sel$3)) basic
|
||||
// pq_subquery(@sel$1 (sel$2 sel$3) LOCAL LOCAL)
|
||||
// pq_subquery(@sel$1 (sel$2 sel$3) NONE NONE)
|
||||
// pq_subquery(@sel$1 (sel$2 sel$3) PARTITION NONE)
|
||||
// pq_subquery(@sel$1 (sel$2 sel$3) NONE ALL)
|
||||
if (T_DISTRIBUTE_LOCAL == outer && T_DISTRIBUTE_LOCAL == inner) {
|
||||
dist_algo = DistAlgo::DIST_PULL_TO_LOCAL;
|
||||
} else if (T_DISTRIBUTE_NONE == outer && T_DISTRIBUTE_NONE == inner) {
|
||||
dist_algo = DistAlgo::DIST_PARTITION_WISE;
|
||||
} else if (T_DISTRIBUTE_PARTITION == outer && T_DISTRIBUTE_NONE == inner) {
|
||||
dist_algo = DistAlgo::DIST_PARTITION_NONE;
|
||||
} else if (T_DISTRIBUTE_NONE == outer && T_DISTRIBUTE_ALL == inner) {
|
||||
dist_algo = DistAlgo::DIST_NONE_ALL;
|
||||
}
|
||||
}
|
||||
|
||||
if (DistAlgo::DIST_INVALID_METHOD != dist_algo) {
|
||||
ObPQSubqueryHint *pq_subquery_hint = NULL;
|
||||
ObString qb_name;
|
||||
if (OB_FAIL(ObQueryHint::create_hint(allocator_, hint_node.type_, pq_subquery_hint))) {
|
||||
LOG_WARN("failed to create hint", K(ret));
|
||||
} else if (OB_FAIL(resolve_qb_name_node(hint_node.children_[0], qb_name))) {
|
||||
LOG_WARN("failed to resolve query block name", K(ret));
|
||||
} else if (hint_node.children_[1] != NULL &&
|
||||
OB_FAIL(resolve_qb_name_list(hint_node.children_[1], pq_subquery_hint->get_sub_qb_names()))) {
|
||||
LOG_WARN("failed to resolve qb name list", K(ret));
|
||||
} else {
|
||||
pq_subquery_hint->set_qb_name(qb_name);
|
||||
pq_subquery_hint->set_dist_algo(dist_algo);
|
||||
opt_hint = pq_subquery_hint;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDMLResolver::resolve_join_filter_hint(const ParseNode &hint_node,
|
||||
ObOptHint *&opt_hint)
|
||||
{
|
||||
@ -13969,7 +14039,7 @@ int ObDMLResolver::resolve_count_to_exists_hint(const ParseNode &hint_node,
|
||||
} else {
|
||||
const ParseNode *qb_name_list_node = hint_node.children_[1];
|
||||
if (qb_name_list_node != NULL &&
|
||||
OB_FAIL(resolve_qb_name_list(qb_name_list_node, count_to_exists_hint->get_qb_name_list()))) {
|
||||
OB_FAIL(resolve_qb_name_list(qb_name_list_node, count_to_exists_hint->get_qb_names()))) {
|
||||
LOG_WARN("failed to resolve qb name list", K(ret));
|
||||
} else {
|
||||
count_to_exists_hint->set_qb_name(qb_name);
|
||||
|
@ -878,6 +878,7 @@ private:
|
||||
int resolve_pq_map_hint(const ParseNode &hint_node, ObOptHint *&opt_hint);
|
||||
int resolve_pq_distribute_hint(const ParseNode &hint_node, ObOptHint *&opt_hint);
|
||||
int resolve_pq_set_hint(const ParseNode &hint_node, ObOptHint *&opt_hint);
|
||||
int resolve_pq_subquery_hint(const ParseNode &hint_node, ObOptHint *&opt_hint);
|
||||
int resolve_join_filter_hint(const ParseNode &join_node, ObOptHint *&opt_hint);
|
||||
int resolve_aggregation_hint(const ParseNode &hint_node, ObOptHint *&hint);
|
||||
int resolve_normal_transform_hint(const ParseNode &hint_node, ObTransHint *&hint);
|
||||
|
@ -1045,7 +1045,7 @@ int ObDMLStmt::construct_join_table(const ObDMLStmt &other_stmt,
|
||||
* for or-expansion transformation
|
||||
* todo: do not update semi id in semi info now
|
||||
*/
|
||||
int ObDMLStmt::update_stmt_table_id(const ObDMLStmt &other)
|
||||
int ObDMLStmt::update_stmt_table_id(ObIAllocator *allocator, const ObDMLStmt &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(other.table_items_.count() != table_items_.count())) {
|
||||
@ -1072,7 +1072,7 @@ int ObDMLStmt::update_stmt_table_id(const ObDMLStmt &other)
|
||||
other.table_items_.at(i)->is_generated_table() &&
|
||||
NULL != table_items_.at(i)->ref_query_ &&
|
||||
NULL != other.table_items_.at(i)->ref_query_ &&
|
||||
OB_FAIL(table_items_.at(i)->ref_query_->update_stmt_table_id(
|
||||
OB_FAIL(table_items_.at(i)->ref_query_->update_stmt_table_id(allocator,
|
||||
*other.table_items_.at(i)->ref_query_))) {
|
||||
LOG_WARN("failed to update table id for generated table", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
@ -1087,7 +1087,7 @@ int ObDMLStmt::update_stmt_table_id(const ObDMLStmt &other)
|
||||
LOG_WARN("null point error", K(subquery_exprs_.at(i)), K(other.subquery_exprs_.at(i)),
|
||||
K(subquery_exprs_.at(i)->get_ref_stmt()), K(other.subquery_exprs_.at(i)->get_ref_stmt()),
|
||||
K(ret));
|
||||
} else if (OB_FAIL(subquery_exprs_.at(i)->get_ref_stmt()->update_stmt_table_id(
|
||||
} else if (OB_FAIL(subquery_exprs_.at(i)->get_ref_stmt()->update_stmt_table_id(allocator,
|
||||
*other.subquery_exprs_.at(i)->get_ref_stmt()))) {
|
||||
LOG_WARN("failed to update table id for subquery exprs", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
@ -1116,7 +1116,8 @@ int ObDMLStmt::update_stmt_table_id(const ObDMLStmt &other)
|
||||
} else if (OB_FAIL(update_table_item_id(other,
|
||||
*other.table_items_.at(i),
|
||||
true,
|
||||
*table_items_.at(i)))) {
|
||||
*table_items_.at(i),
|
||||
allocator))) {
|
||||
LOG_WARN("failed to update table id for table item", K(ret));
|
||||
} else { /*do nothing*/ }
|
||||
}
|
||||
@ -1270,7 +1271,7 @@ int ObDMLStmt::update_table_item_id_for_joined_table(const ObDMLStmt &other_stmt
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("null table item", K(other.left_table_), K(other.right_table_),
|
||||
K(current.left_table_), K(current.right_table_), K(ret));
|
||||
} else if (OB_FAIL(update_table_item_id(other_stmt, other, false, current))) {
|
||||
} else if (OB_FAIL(update_table_item_id(other_stmt, other, false, current, NULL))) {
|
||||
LOG_WARN("failed to update table id", K(ret));
|
||||
} else if (other.left_table_->is_joined_table() &&
|
||||
current.left_table_->is_joined_table() &&
|
||||
@ -1291,27 +1292,29 @@ int ObDMLStmt::update_table_item_id_for_joined_table(const ObDMLStmt &other_stmt
|
||||
int ObDMLStmt::update_table_item_id(const ObDMLStmt &other,
|
||||
const TableItem &old_item,
|
||||
const bool has_bit_index,
|
||||
TableItem &new_item)
|
||||
TableItem &new_item,
|
||||
ObIAllocator *allocator)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(query_ctx_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("null query ctx", K(ret));
|
||||
// } else if (OB_FAIL(get_qb_name(new_item.qb_name_))) {
|
||||
// LOG_WARN("fail to get qb_name", K(ret), K(get_stmt_id()));
|
||||
// do not update table item qb name
|
||||
} else {
|
||||
uint64_t old_table_id = old_item.table_id_;
|
||||
uint64_t new_table_id = query_ctx_->available_tb_id_--;
|
||||
int32_t old_bit_id = OB_INVALID_INDEX;
|
||||
int32_t new_bit_id = OB_INVALID_INDEX;
|
||||
new_item.table_id_ = new_table_id;
|
||||
if (TableItem::TableType::BASE_TABLE == new_item.type_) {
|
||||
new_item.type_ = TableItem::TableType::ALIAS_TABLE;
|
||||
new_item.alias_name_ = ObString::make_string("");
|
||||
}
|
||||
if (has_bit_index) {
|
||||
if (OB_FAIL(set_table_bit_index(new_table_id))) {
|
||||
bool adjusted = false;
|
||||
if (OB_ISNULL(allocator)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(ret), K(allocator));
|
||||
} else if (OB_FAIL(get_qb_name(new_item.qb_name_))) {
|
||||
LOG_WARN("fail to get qb_name", K(ret), K(get_stmt_id()));
|
||||
} else if (OB_FAIL(adjust_duplicated_table_name(*allocator, new_item, adjusted))) {
|
||||
LOG_WARN("fail to update dup table name", K(ret), K(new_item));
|
||||
} else if (OB_FAIL(set_table_bit_index(new_table_id))) {
|
||||
LOG_WARN("failed to set table bit index", K(ret));
|
||||
} else if (&new_item == &old_item) {
|
||||
/* do nothing */
|
||||
@ -1361,6 +1364,93 @@ int ObDMLStmt::update_table_item_id(const ObDMLStmt &other,
|
||||
return ret;
|
||||
}
|
||||
|
||||
// to keep object_name@qb_name unique in query, need adjust table alias name when update table item qb name
|
||||
int ObDMLStmt::adjust_duplicated_table_name(ObIAllocator &allocator,
|
||||
TableItem &table_item,
|
||||
bool &adjusted)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
adjusted = false;
|
||||
const TableItem *cur_table = NULL;
|
||||
bool find_dup = false;
|
||||
for (int64_t i = 0; !find_dup && OB_SUCC(ret) && i < table_items_.count(); i++) {
|
||||
if (OB_ISNULL(cur_table = table_items_.at(i))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("null table item", K(ret), K(i), K(table_items_));
|
||||
} else if (cur_table == &table_item) {
|
||||
/* do nothing */
|
||||
} else if (0 != table_item.get_object_name().case_compare(cur_table->get_object_name())) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
find_dup = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && find_dup) {
|
||||
int64_t pos = 0;
|
||||
// just to generate an unique alias name, use a minimal max name length value: OB_MAX_USER_TABLE_NAME_LENGTH_MYSQL = 64
|
||||
// ignore oracle mode max name length OB_MAX_USER_TABLE_NAME_LENGTH_ORACLE = 128
|
||||
char buf[OB_MAX_USER_TABLE_NAME_LENGTH_MYSQL + 1];
|
||||
const int64_t MAX_TIMES_FOR_GET_NO_DUP_ALIAS_NAME = 20;
|
||||
int64_t buf_len = OB_MAX_USER_TABLE_NAME_LENGTH_MYSQL;
|
||||
int32_t prefix_len = table_item.get_object_name().length();
|
||||
prefix_len = prefix_len > buf_len - 3 ? buf_len - 3 : prefix_len;
|
||||
if (OB_FAIL(BUF_PRINTF("%.*s_", prefix_len, table_item.get_object_name().ptr()))) {
|
||||
LOG_WARN("append name to buf error", K(ret));
|
||||
} else {
|
||||
int64_t old_pos = pos;
|
||||
int64_t id = 1;
|
||||
for (; find_dup && OB_SUCC(ret) && id <= MAX_TIMES_FOR_GET_NO_DUP_ALIAS_NAME; id++) {
|
||||
pos = old_pos;
|
||||
if (OB_FAIL(BUF_PRINTF("%ld", id))) {
|
||||
LOG_WARN("failed to print id", K(ret), K(id));
|
||||
} else {
|
||||
find_dup = false;
|
||||
for (int64_t i = 0; !find_dup && OB_SUCC(ret) && i < table_items_.count(); ++i) {
|
||||
if (OB_ISNULL(table_items_.at(i))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("null table item", K(ret), K(i), K(table_items_));
|
||||
} else {
|
||||
find_dup = (0 == table_items_.at(i)->get_object_name().case_compare(buf));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
} else if (find_dup) {
|
||||
LOG_WARN("failed to update alias table name no dup", K(MAX_TIMES_FOR_GET_NO_DUP_ALIAS_NAME),
|
||||
K(id), K(table_item.get_object_name()));
|
||||
} else if (OB_FAIL(ob_write_string(allocator, ObString(pos, buf), table_item.alias_name_))) {
|
||||
LOG_WARN("failed to write string", K(ret));
|
||||
} else {
|
||||
adjusted = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObDMLStmt::adjust_duplicated_table_names(ObIAllocator &allocator, bool &adjusted)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
adjusted = false;
|
||||
bool is_adjusted = false;
|
||||
TableItem *table_item = NULL;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < table_items_.count(); ++i) {
|
||||
if (OB_ISNULL(table_item = table_items_.at(i))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect null", K(ret), K(table_item));
|
||||
} else if (OB_FAIL(adjust_duplicated_table_name(allocator,
|
||||
*table_item,
|
||||
is_adjusted))) {
|
||||
LOG_WARN("fail to update dup table name", K(ret), KPC(table_item));
|
||||
} else {
|
||||
adjusted |= is_adjusted;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ObDMLStmt::has_subquery() const
|
||||
{
|
||||
return subquery_exprs_.count() > 0;
|
||||
|
@ -695,7 +695,8 @@ public:
|
||||
int iterate_joined_table_expr(JoinedTable *joined_table,
|
||||
ObStmtExprVisitor &visitor) const;
|
||||
|
||||
int update_stmt_table_id(const ObDMLStmt &other);
|
||||
int update_stmt_table_id(ObIAllocator *allocator, const ObDMLStmt &other);
|
||||
int adjust_duplicated_table_names(ObIAllocator &allocator, bool &adjusted);
|
||||
int set_table_item_qb_name();
|
||||
int adjust_qb_name(ObIAllocator *allocator,
|
||||
const ObString &src_qb_name,
|
||||
@ -1179,7 +1180,9 @@ protected:
|
||||
int update_table_item_id(const ObDMLStmt &other,
|
||||
const TableItem &old_item,
|
||||
const bool has_bit_index,
|
||||
TableItem &new_item);
|
||||
TableItem &new_item,
|
||||
ObIAllocator *allocator);
|
||||
int adjust_duplicated_table_name(ObIAllocator &allocator, TableItem &table_item, bool &adjusted);
|
||||
|
||||
protected:
|
||||
/**
|
||||
|
@ -927,8 +927,6 @@ ObItemType ObHint::get_hint_type(ObItemType type)
|
||||
case T_NO_DISTINCT_PUSHDOWN: return T_DISTINCT_PUSHDOWN;
|
||||
case T_NO_USE_HASH_SET: return T_USE_HASH_SET;
|
||||
case T_NO_USE_DISTRIBUTED_DML: return T_USE_DISTRIBUTED_DML;
|
||||
case T_DYNAMIC_SAMPLING: return T_DYNAMIC_SAMPLING;
|
||||
|
||||
default: return type;
|
||||
}
|
||||
}
|
||||
@ -999,6 +997,7 @@ const char* ObHint::get_hint_name(ObItemType type, bool is_enable_hint /* defaul
|
||||
case T_USE_HASH_SET: return is_enable_hint ? "USE_HASH_SET" : "NO_USE_HASH_SET";
|
||||
case T_USE_DISTRIBUTED_DML: return is_enable_hint ? "USE_DISTRIBUTED_DML" : "NO_USE_DISTRIBUTED_DML";
|
||||
case T_TABLE_DYNAMIC_SAMPLING: return "DYNAMIC_SAMPLING";
|
||||
case T_PQ_SUBQUERY: return "PQ_SUBQUERY";
|
||||
default: return NULL;
|
||||
}
|
||||
}
|
||||
@ -1073,7 +1072,6 @@ int ObHint::deep_copy_hint_contain_table(ObIAllocator *allocator, ObHint *&hint)
|
||||
case HINT_GROUPBY_PLACEMENT: DEEP_COPY_NORMAL_HINT(ObGroupByPlacementHint); break;
|
||||
case HINT_JOIN_FILTER: DEEP_COPY_NORMAL_HINT(ObJoinFilterHint); break;
|
||||
case HINT_WIN_MAGIC: DEEP_COPY_NORMAL_HINT(ObWinMagicHint); break;
|
||||
case HINT_TABLE_DYNAMIC_SAMPLING: DEEP_COPY_NORMAL_HINT(ObTableDynamicSamplingHint); break;
|
||||
default: {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected hint type to deep copy", K(ret), K(hint_class_));
|
||||
@ -1224,6 +1222,29 @@ bool ObHint::is_expr_match_str(const ObRawExpr &expr, const ObString &str)
|
||||
return bret;
|
||||
}
|
||||
|
||||
int ObHint::print_table_list(const ObIArray<TablesInHint> &table_list, PlanText &plan_text)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!table_list.empty()) {
|
||||
char *buf = plan_text.buf_;
|
||||
int64_t &buf_len = plan_text.buf_len_;
|
||||
int64_t &pos = plan_text.pos_;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < table_list.count(); ++i) {
|
||||
const TablesInHint &cur_table = table_list.at(i);
|
||||
if (cur_table.count() > 1 && OB_FAIL(BUF_PRINTF("("))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
} else if (OB_FAIL(ObTableInHint::print_join_tables_in_hint(plan_text, cur_table))) {
|
||||
LOG_WARN("failed to print joined tables in hint", K(ret));
|
||||
} else if (cur_table.count() > 1 && OB_FAIL(BUF_PRINTF(")"))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
} else if (i < table_list.count() - 1 && OB_FAIL(BUF_PRINTF(" "))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObViewMergeHint::assign(const ObViewMergeHint &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -1402,10 +1423,35 @@ bool QbNameList::is_subset(const ObIArray<ObString> &qb_name_list) const
|
||||
return bret;
|
||||
}
|
||||
|
||||
int QbNameList::print_qb_names(PlanText &plan_text, const bool print_quote) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!qb_names_.empty()) {
|
||||
char *buf = plan_text.buf_;
|
||||
int64_t &buf_len = plan_text.buf_len_;
|
||||
int64_t &pos = plan_text.pos_;
|
||||
if (print_quote && OB_FAIL(BUF_PRINTF("("))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < qb_names_.count(); ++i) {
|
||||
const ObString &qb_name = qb_names_.at(i);
|
||||
if (OB_FAIL(BUF_PRINTF("\"%.*s\"", qb_name.length(), qb_name.ptr()))) {
|
||||
LOG_WARN("failed to print qb name", K(ret));
|
||||
} else if (i != qb_names_.count() - 1 && OB_FAIL(BUF_PRINTF(" "))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret) && print_quote && OB_FAIL(BUF_PRINTF(")"))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCountToExistsHint::assign(const ObCountToExistsHint &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(qb_name_list_.assign(other.qb_name_list_))) {
|
||||
if (OB_FAIL(qb_names_.assign(other.qb_names_))) {
|
||||
LOG_WARN("failed to assign qb name list", K(ret));
|
||||
} else if (OB_FAIL(ObTransHint::assign(other))) {
|
||||
LOG_WARN("fail to assign hint", K(ret));
|
||||
@ -1413,40 +1459,6 @@ int ObCountToExistsHint::assign(const ObCountToExistsHint &other)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObCountToExistsHint::print_hint_desc(PlanText &plan_text) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!qb_name_list_.empty()) {
|
||||
char *buf = plan_text.buf_;
|
||||
int64_t &buf_len = plan_text.buf_len_;
|
||||
int64_t &pos = plan_text.pos_;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < qb_name_list_.count(); ++i) {
|
||||
ObString qb_name = qb_name_list_.at(i);
|
||||
if (OB_FAIL(BUF_PRINTF("\"%.*s\"", qb_name.length(), qb_name.ptr()))) {
|
||||
LOG_WARN("failed to print qb name", K(ret));
|
||||
} else if (i != qb_name_list_.count() - 1) {
|
||||
if (OB_FAIL(BUF_PRINTF(" "))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ObCountToExistsHint::enable_count_to_exists(const ObString &qb_name) const
|
||||
{
|
||||
bool bret = false;
|
||||
if (is_enable_hint()) {
|
||||
bool found = false;
|
||||
for (int64_t i = 0; !found && i < qb_name_list_.count(); ++i) {
|
||||
found = 0 == qb_name.case_compare(qb_name_list_.at(i));
|
||||
}
|
||||
bret = found || qb_name_list_.empty();
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
|
||||
int ObLeftToAntiHint::assign(const ObLeftToAntiHint &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -1458,29 +1470,6 @@ int ObLeftToAntiHint::assign(const ObLeftToAntiHint &other)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLeftToAntiHint::print_hint_desc(PlanText &plan_text) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!table_list_.empty()) {
|
||||
char *buf = plan_text.buf_;
|
||||
int64_t &buf_len = plan_text.buf_len_;
|
||||
int64_t &pos = plan_text.pos_;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < table_list_.count(); ++i) {
|
||||
single_or_joined_table cur_table = table_list_.at(i);
|
||||
if (cur_table.count() > 1 && OB_FAIL(BUF_PRINTF("("))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
} else if (OB_FAIL(ObTableInHint::print_join_tables_in_hint(plan_text, cur_table))) {
|
||||
LOG_WARN("failed to print joined tables in hint", K(ret));
|
||||
} else if (cur_table.count() > 1 && OB_FAIL(BUF_PRINTF(")"))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
} else if (i < table_list_.count() - 1 && OB_FAIL(BUF_PRINTF(" "))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLeftToAntiHint::get_all_table_in_hint(ObIArray<ObTableInHint*> &all_tables)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -1497,8 +1486,7 @@ bool ObLeftToAntiHint::enable_left_to_anti(ObCollationType cs_type, const TableI
|
||||
bool bret = false;
|
||||
if (is_enable_hint()) {
|
||||
for (int64_t i = 0; !bret && i < table_list_.count(); ++i) {
|
||||
single_or_joined_table cur_table = table_list_.at(i);
|
||||
bret = ObTableInHint::is_match_table_item(cs_type, cur_table, table);
|
||||
bret = ObTableInHint::is_match_table_item(cs_type, table_list_.at(i), table);
|
||||
}
|
||||
bret |= table_list_.empty();
|
||||
}
|
||||
@ -1516,29 +1504,6 @@ int ObEliminateJoinHint::assign(const ObEliminateJoinHint &other)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObEliminateJoinHint::print_hint_desc(PlanText &plan_text) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!table_list_.empty()) {
|
||||
char *buf = plan_text.buf_;
|
||||
int64_t &buf_len = plan_text.buf_len_;
|
||||
int64_t &pos = plan_text.pos_;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < table_list_.count(); ++i) {
|
||||
single_or_joined_table cur_table = table_list_.at(i);
|
||||
if (cur_table.count() > 1 && OB_FAIL(BUF_PRINTF("("))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
} else if (OB_FAIL(ObTableInHint::print_join_tables_in_hint(plan_text, cur_table))) {
|
||||
LOG_WARN("failed to print joined tables in hint", K(ret));
|
||||
} else if (cur_table.count() > 1 && OB_FAIL(BUF_PRINTF(")"))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
} else if (i < table_list_.count() - 1 && OB_FAIL(BUF_PRINTF(" "))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObEliminateJoinHint::get_all_table_in_hint(ObIArray<ObTableInHint*> &all_tables)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -1555,8 +1520,7 @@ bool ObEliminateJoinHint::enable_eliminate_join(ObCollationType cs_type, const T
|
||||
bool bret = false;
|
||||
if (is_enable_hint()) {
|
||||
for (int64_t i = 0; !bret && i < table_list_.count(); ++i) {
|
||||
single_or_joined_table cur_table = table_list_.at(i);
|
||||
bret = ObTableInHint::is_match_table_item(cs_type, cur_table, table);
|
||||
bret = ObTableInHint::is_match_table_item(cs_type, table_list_.at(i), table);
|
||||
}
|
||||
bret |= table_list_.empty();
|
||||
}
|
||||
@ -1575,29 +1539,6 @@ int ObGroupByPlacementHint::assign(const ObGroupByPlacementHint &other)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObGroupByPlacementHint::print_hint_desc(PlanText &plan_text) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!table_list_.empty()) {
|
||||
char *buf = plan_text.buf_;
|
||||
int64_t &buf_len = plan_text.buf_len_;
|
||||
int64_t &pos = plan_text.pos_;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < table_list_.count(); ++i) {
|
||||
single_or_joined_table cur_table = table_list_.at(i);
|
||||
if (cur_table.count() > 1 && OB_FAIL(BUF_PRINTF("("))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
} else if (OB_FAIL(ObTableInHint::print_join_tables_in_hint(plan_text, cur_table))) {
|
||||
LOG_WARN("failed to print joined tables in hint", K(ret));
|
||||
} else if (cur_table.count() > 1 && OB_FAIL(BUF_PRINTF(")"))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
} else if (i < table_list_.count() - 1 && OB_FAIL(BUF_PRINTF(" "))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObGroupByPlacementHint::get_all_table_in_hint(ObIArray<ObTableInHint*> &all_tables)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
@ -1614,8 +1555,7 @@ bool ObGroupByPlacementHint::enable_groupby_placement(ObCollationType cs_type, c
|
||||
bool bret = false;
|
||||
if (is_enable_hint()) {
|
||||
for (int64_t i = 0; !bret && i < table_list_.count(); i++) {
|
||||
single_or_joined_table cur_table = table_list_.at(i);
|
||||
bret = ObTableInHint::is_match_table_item(cs_type, cur_table, table);
|
||||
bret = ObTableInHint::is_match_table_item(cs_type, table_list_.at(i), table);
|
||||
}
|
||||
bret |= table_list_.empty();
|
||||
}
|
||||
@ -1633,8 +1573,7 @@ bool ObGroupByPlacementHint::enable_groupby_placement(ObCollationType cs_type,
|
||||
LOG_WARN("assign failed", K(ret));
|
||||
}
|
||||
for (int64_t i = 0; !bret && i < table_list_.count(); i++) {
|
||||
single_or_joined_table cur_table = table_list_.at(i);
|
||||
bret = ObTableInHint::is_match_table_items(cs_type, cur_table, check_tables);
|
||||
bret = ObTableInHint::is_match_table_items(cs_type, table_list_.at(i), check_tables);
|
||||
}
|
||||
bret |= table_list_.empty();
|
||||
}
|
||||
@ -1674,7 +1613,7 @@ int ObWinMagicHint::print_hint_desc(PlanText &plan_text) const
|
||||
LOG_WARN("table in hint count < 2", K(ret));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < table_list_.count(); ++i) {
|
||||
ObTableInHint cur_table = table_list_.at(i);
|
||||
const ObTableInHint &cur_table = table_list_.at(i);
|
||||
if (table_list_.count() > 2 && i == 1 && OB_FAIL(BUF_PRINTF("("))) {
|
||||
LOG_WARN("failed to do BUF_PRINTF", K(ret));
|
||||
} else if (OB_FAIL(cur_table.print_table_in_hint(plan_text))) {
|
||||
@ -1991,7 +1930,7 @@ int ObJoinHint::print_hint_desc(PlanText &plan_text) const
|
||||
} else if (tables_.count() > 1 && OB_FAIL(BUF_PRINTF(")"))) {
|
||||
LOG_WARN("failed to print hint", K(ret));
|
||||
} else if (T_PQ_DISTRIBUTE == hint_type_ && NULL != algo_str
|
||||
&& OB_FAIL(BUF_PRINTF(" %s", get_dist_algo_str()))) {
|
||||
&& OB_FAIL(BUF_PRINTF(" %s", algo_str))) {
|
||||
LOG_WARN("failed to print dist algo", K(ret));
|
||||
}
|
||||
return ret;
|
||||
@ -2314,6 +2253,34 @@ const char *ObPQSetHint::get_dist_method_str(const ObItemType dist_method)
|
||||
return NULL;
|
||||
};
|
||||
|
||||
int ObPQSubqueryHint::assign(const ObPQSubqueryHint &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
dist_algo_ = other.dist_algo_;
|
||||
if (OB_FAIL(sub_qb_names_.assign(other.sub_qb_names_))) {
|
||||
LOG_WARN("fail to assign subplan qb names", K(ret));
|
||||
} else if (OB_FAIL(ObOptHint::assign(other))) {
|
||||
LOG_WARN("fail to assign hint", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObPQSubqueryHint::print_hint_desc(PlanText &plan_text) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
char *buf = plan_text.buf_;
|
||||
int64_t &buf_len = plan_text.buf_len_;
|
||||
int64_t &pos = plan_text.pos_;
|
||||
const char *algo_str = NULL;
|
||||
if (OB_FAIL(sub_qb_names_.print_qb_names(plan_text, true))) {
|
||||
LOG_WARN("failed to print qb names", K(ret));
|
||||
} else if (NULL != (algo_str = ObJoinHint::get_dist_algo_str(get_dist_algo()))
|
||||
&& OB_FAIL(BUF_PRINTF(" %s", algo_str))) {
|
||||
LOG_WARN("failed to print dist algo", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObJoinOrderHint::print_hint_desc(PlanText &plan_text) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
@ -377,6 +377,20 @@ struct ObLeadingTable {
|
||||
ObLeadingTable *right_table_;
|
||||
};
|
||||
|
||||
struct QbNameList {
|
||||
int assign(const QbNameList& other);
|
||||
bool has_qb_name(const ObDMLStmt *stmt) const;
|
||||
bool has_qb_name(const ObString &qb_name) const;
|
||||
bool is_equal(const ObIArray<ObSelectStmt*> &stmts) const;
|
||||
bool is_equal(const ObIArray<ObString> &qb_name_list) const;
|
||||
bool is_subset(const ObIArray<ObSelectStmt*> &stmts) const;
|
||||
bool is_subset(const ObIArray<ObString> &qb_name_list) const;
|
||||
bool empty() const { return qb_names_.empty(); }
|
||||
int print_qb_names(PlanText &plan_text, const bool print_quote) const;
|
||||
TO_STRING_KV(K_(qb_names));
|
||||
common::ObSEArray<ObString, 4, common::ModulePageAllocator, true> qb_names_;
|
||||
};
|
||||
|
||||
class ObHint
|
||||
{
|
||||
public:
|
||||
@ -408,6 +422,10 @@ public:
|
||||
|
||||
static const int64_t MAX_EXPR_STR_LENGTH_IN_HINT = 1024;
|
||||
|
||||
// basic/generated table: size = 1
|
||||
// joined table: size > 1
|
||||
typedef ObSEArray<ObTableInHint, 4> TablesInHint;
|
||||
|
||||
ObHint(ObItemType hint_type = T_INVALID)
|
||||
: hint_class_(HINT_INVALID_CLASS),
|
||||
qb_name_(),
|
||||
@ -445,6 +463,7 @@ public:
|
||||
int add_tables(ObIArray<ObTableInHint> &tables, ObIArray<ObTableInHint*> &tables_ptr);
|
||||
static int get_expr_str_in_hint(ObIAllocator &allocator, const ObRawExpr &expr, ObString &str);
|
||||
static bool is_expr_match_str(const ObRawExpr &expr, const ObString &str);
|
||||
static int print_table_list(const ObIArray<TablesInHint> &table_list, PlanText &plan_text);
|
||||
bool is_transform_outline_hint() const { return is_transform_hint() && (is_enable_hint() || is_materialize_hint()); };
|
||||
bool is_transform_hint() const { return hint_class_ >= HINT_TRANSFORM && hint_class_ < HINT_OPTIMIZE; }
|
||||
bool is_view_merge_hint() const { return HINT_VIEW_MERGE == hint_class_; }
|
||||
@ -468,7 +487,8 @@ public:
|
||||
bool is_table_parallel_hint() const { return HINT_TABLE_PARALLEL == hint_class_; }
|
||||
bool is_join_filter_hint() const { return HINT_JOIN_FILTER == hint_class_; }
|
||||
bool is_project_prune_hint() const { return T_PROJECT_PRUNE == hint_type_; }
|
||||
bool is_table_dynamic_sampling_hint() const { return HINT_TABLE_DYNAMIC_SAMPLING == hint_class_; }
|
||||
bool is_table_dynamic_sampling_hint() const { return T_TABLE_DYNAMIC_SAMPLING == hint_type_; }
|
||||
bool is_pq_subquery_hint() const { return T_PQ_SUBQUERY == hint_type_; }
|
||||
|
||||
VIRTUAL_TO_STRING_KV("hint_type", get_type_name(hint_type_),
|
||||
K_(hint_class), K_(qb_name),
|
||||
@ -570,30 +590,28 @@ class ObCountToExistsHint : public ObTransHint
|
||||
public:
|
||||
ObCountToExistsHint(ObItemType hint_type)
|
||||
: ObTransHint(hint_type),
|
||||
qb_name_list_()
|
||||
qb_names_()
|
||||
{
|
||||
set_hint_class(HINT_COUNT_TO_EXISTS);
|
||||
}
|
||||
int assign(const ObCountToExistsHint &other);
|
||||
virtual ~ObCountToExistsHint() {}
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override;
|
||||
common::ObIArray<ObString> & get_qb_name_list() { return qb_name_list_; }
|
||||
const common::ObIArray<ObString> & get_qb_name_list() const { return qb_name_list_; }
|
||||
bool enable_count_to_exists(const ObString &qb_name) const;
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override
|
||||
{ return qb_names_.print_qb_names(plan_text, false); }
|
||||
common::ObIArray<ObString> & get_qb_names() { return qb_names_.qb_names_; }
|
||||
const common::ObIArray<ObString> & get_qb_names() const { return qb_names_.qb_names_; }
|
||||
bool enable_count_to_exists(const ObString &qb_name) const
|
||||
{ return is_enable_hint() && (qb_names_.has_qb_name(qb_name) || qb_names_.empty()); }
|
||||
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(qb_name_list));
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(qb_names));
|
||||
|
||||
private:
|
||||
common::ObSEArray<ObString, 4, common::ModulePageAllocator, true> qb_name_list_;
|
||||
QbNameList qb_names_;
|
||||
};
|
||||
|
||||
class ObLeftToAntiHint : public ObTransHint
|
||||
{
|
||||
public:
|
||||
// basic/generated table: size = 1
|
||||
// joined table: size > 1
|
||||
typedef ObSEArray<ObTableInHint, 4> single_or_joined_table;
|
||||
|
||||
ObLeftToAntiHint(ObItemType hint_type)
|
||||
: ObTransHint(hint_type),
|
||||
table_list_()
|
||||
@ -603,24 +621,20 @@ public:
|
||||
int assign(const ObLeftToAntiHint &other);
|
||||
virtual ~ObLeftToAntiHint() {}
|
||||
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override;
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override { return ObHint::print_table_list(table_list_, plan_text); }
|
||||
virtual int get_all_table_in_hint(ObIArray<ObTableInHint*> &all_tables) override;
|
||||
common::ObIArray<single_or_joined_table> & get_tb_name_list() { return table_list_; }
|
||||
const common::ObIArray<single_or_joined_table> & get_tb_name_list() const { return table_list_; }
|
||||
common::ObIArray<TablesInHint> & get_tb_name_list() { return table_list_; }
|
||||
const common::ObIArray<TablesInHint> & get_tb_name_list() const { return table_list_; }
|
||||
bool enable_left_to_anti(ObCollationType cs_type, const TableItem &table) const;
|
||||
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(table_list));
|
||||
|
||||
private:
|
||||
common::ObSEArray<single_or_joined_table, 4, common::ModulePageAllocator, true> table_list_;
|
||||
common::ObSEArray<TablesInHint, 4, common::ModulePageAllocator, true> table_list_;
|
||||
};
|
||||
class ObEliminateJoinHint : public ObTransHint
|
||||
{
|
||||
public:
|
||||
// basic/generated table: size = 1
|
||||
// joined table: size > 1
|
||||
typedef ObSEArray<ObTableInHint, 4> single_or_joined_table;
|
||||
|
||||
ObEliminateJoinHint(ObItemType hint_type)
|
||||
: ObTransHint(hint_type),
|
||||
table_list_()
|
||||
@ -630,25 +644,21 @@ public:
|
||||
int assign(const ObEliminateJoinHint &other);
|
||||
virtual ~ObEliminateJoinHint() {}
|
||||
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override;
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override { return ObHint::print_table_list(table_list_, plan_text); }
|
||||
virtual int get_all_table_in_hint(ObIArray<ObTableInHint*> &all_tables) override;
|
||||
common::ObIArray<single_or_joined_table> & get_tb_name_list() { return table_list_; }
|
||||
const common::ObIArray<single_or_joined_table> & get_tb_name_list() const { return table_list_; }
|
||||
common::ObIArray<TablesInHint> & get_tb_name_list() { return table_list_; }
|
||||
const common::ObIArray<TablesInHint> & get_tb_name_list() const { return table_list_; }
|
||||
bool enable_eliminate_join(ObCollationType cs_type, const TableItem &table) const;
|
||||
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(table_list));
|
||||
|
||||
private:
|
||||
common::ObSEArray<single_or_joined_table, 4, common::ModulePageAllocator, true> table_list_;
|
||||
common::ObSEArray<TablesInHint, 4, common::ModulePageAllocator, true> table_list_;
|
||||
};
|
||||
|
||||
class ObGroupByPlacementHint : public ObTransHint
|
||||
{
|
||||
public:
|
||||
// basic/generated table: size = 1
|
||||
// joined table: size > 1
|
||||
typedef ObSEArray<ObTableInHint, 4> single_or_joined_table;
|
||||
|
||||
ObGroupByPlacementHint(ObItemType hint_type)
|
||||
: ObTransHint(hint_type),
|
||||
table_list_()
|
||||
@ -658,17 +668,17 @@ public:
|
||||
int assign(const ObGroupByPlacementHint &other);
|
||||
virtual ~ObGroupByPlacementHint() {}
|
||||
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override;
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override { return ObHint::print_table_list(table_list_, plan_text); }
|
||||
virtual int get_all_table_in_hint(ObIArray<ObTableInHint*> &all_tables) override;
|
||||
common::ObIArray<single_or_joined_table> & get_tb_name_list() { return table_list_; }
|
||||
const common::ObIArray<single_or_joined_table> & get_tb_name_list() const { return table_list_; }
|
||||
common::ObIArray<TablesInHint> & get_tb_name_list() { return table_list_; }
|
||||
const common::ObIArray<TablesInHint> & get_tb_name_list() const { return table_list_; }
|
||||
bool enable_groupby_placement(ObCollationType cs_type, const TableItem &table) const;
|
||||
bool enable_groupby_placement(ObCollationType cs_type, const ObIArray<TableItem *> &tables) const;
|
||||
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(table_list));
|
||||
|
||||
private:
|
||||
common::ObSEArray<single_or_joined_table, 4, common::ModulePageAllocator, true> table_list_;
|
||||
common::ObSEArray<TablesInHint, 4, common::ModulePageAllocator, true> table_list_;
|
||||
};
|
||||
class ObWinMagicHint : public ObTransHint
|
||||
{
|
||||
@ -694,20 +704,6 @@ private:
|
||||
common::ObSEArray<ObTableInHint, 4, common::ModulePageAllocator, true> table_list_;
|
||||
};
|
||||
|
||||
|
||||
struct QbNameList {
|
||||
int assign(const QbNameList& other);
|
||||
bool has_qb_name(const ObDMLStmt *stmt) const;
|
||||
bool has_qb_name(const ObString &qb_name) const;
|
||||
bool is_equal(const ObIArray<ObSelectStmt*> &stmts) const;
|
||||
bool is_equal(const ObIArray<ObString> &qb_name_list) const;
|
||||
bool is_subset(const ObIArray<ObSelectStmt*> &stmts) const;
|
||||
bool is_subset(const ObIArray<ObString> &qb_name_list) const;
|
||||
bool empty() const { return qb_names_.empty(); }
|
||||
TO_STRING_KV(K_(qb_names));
|
||||
common::ObSEArray<ObString, 4, common::ModulePageAllocator, true> qb_names_;
|
||||
};
|
||||
|
||||
class ObMaterializeHint : public ObTransHint
|
||||
{
|
||||
public:
|
||||
@ -932,6 +928,29 @@ private:
|
||||
common::ObString left_branch_; // qb_name for first branch of set, used for union distinct / intersect
|
||||
};
|
||||
|
||||
class ObPQSubqueryHint : public ObOptHint
|
||||
{
|
||||
public:
|
||||
ObPQSubqueryHint(ObItemType hint_type = T_PQ_SUBQUERY)
|
||||
: ObOptHint(hint_type),
|
||||
dist_algo_(DistAlgo::DIST_INVALID_METHOD),
|
||||
sub_qb_names_()
|
||||
{}
|
||||
int assign(const ObPQSubqueryHint &other);
|
||||
virtual ~ObPQSubqueryHint() {}
|
||||
virtual int print_hint_desc(PlanText &plan_text) const override;
|
||||
DistAlgo get_dist_algo() const { return dist_algo_; }
|
||||
void set_dist_algo(DistAlgo dist_algo) { dist_algo_ = dist_algo; }
|
||||
common::ObIArray<ObString> &get_sub_qb_names() { return sub_qb_names_.qb_names_; }
|
||||
const common::ObIArray<ObString> &get_sub_qb_names() const { return sub_qb_names_.qb_names_; }
|
||||
bool is_match_subplans(const ObIArray<ObString> &qb_names) const { return sub_qb_names_.is_equal(qb_names); }
|
||||
|
||||
INHERIT_TO_STRING_KV("ObHint", ObHint, K_(dist_algo), K_(sub_qb_names));
|
||||
private:
|
||||
DistAlgo dist_algo_;
|
||||
QbNameList sub_qb_names_;
|
||||
};
|
||||
|
||||
class ObJoinOrderHint : public ObOptHint {
|
||||
public:
|
||||
ObJoinOrderHint(ObItemType hint_type = T_LEADING)
|
||||
|
@ -590,6 +590,10 @@ int ObInsertResolver::resolve_values(const ParseNode &value_node,
|
||||
} else {
|
||||
table_alias_node = alias_node;
|
||||
}
|
||||
if (NULL != table_alias_node) {
|
||||
view_name.assign_ptr(const_cast<char*>(table_alias_node->str_value_),
|
||||
static_cast<int32_t>(table_alias_node->str_len_));
|
||||
}
|
||||
}
|
||||
if (OB_UNLIKELY(T_SELECT != value_node.type_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -608,17 +612,14 @@ int ObInsertResolver::resolve_values(const ParseNode &value_node,
|
||||
label_se_columns,
|
||||
*select_stmt))) {
|
||||
LOG_WARN("add label security columns to select item failed", K(ret));
|
||||
} else if (NULL != table_alias_node) {
|
||||
view_name.assign_ptr(const_cast<char*>(table_alias_node->str_value_),
|
||||
static_cast<int32_t>(table_alias_node->str_len_));
|
||||
} else if (OB_FAIL(insert_stmt->generate_anonymous_view_name(*allocator_, view_name))) {
|
||||
LOG_WARN("failed to generate view name", K(ret));
|
||||
} else if (OB_FAIL(resolve_generate_table_item(select_stmt, view_name, sub_select_table))) {
|
||||
LOG_WARN("failed to resolve generate table item", K(ret));
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret) && is_mock) {
|
||||
ObString ori_table_name = table_item->table_name_;
|
||||
ObSEArray<ObString, 4> ori_column_names;
|
||||
ObString row_alias_table_name = view_name;
|
||||
ObString row_alias_table_name = sub_select_table->get_table_name();
|
||||
ObSEArray<ObString, 4> row_alias_column_names;
|
||||
//1. check_table_and_column_name
|
||||
if (OB_FAIL(check_table_and_column_name(insert_stmt->get_values_desc(),
|
||||
@ -644,8 +645,6 @@ int ObInsertResolver::resolve_values(const ParseNode &value_node,
|
||||
}
|
||||
if (OB_FAIL(ret)) {
|
||||
//do nothing
|
||||
} else if (OB_FAIL(resolve_generate_table_item(select_stmt, view_name, sub_select_table))) {
|
||||
LOG_WARN("failed to resolve generate table item", K(ret));
|
||||
} else if (OB_FAIL(resolve_all_generated_table_columns(*sub_select_table,
|
||||
column_items))) {
|
||||
LOG_WARN("failed to resolve all generated table columns", K(ret));
|
||||
|
@ -444,6 +444,10 @@ int ObMergeResolver::resolve_generate_table(const ParseNode &table_node,
|
||||
select_resolver.set_is_sub_stmt(true);
|
||||
select_resolver.set_parent_namespace_resolver(parent_namespace_resolver_);
|
||||
select_resolver.set_current_view_level(current_view_level_);
|
||||
ObString alias_name;
|
||||
if (alias_node != NULL) {
|
||||
alias_name.assign_ptr((char *)(alias_node->str_value_), static_cast<int32_t>(alias_node->str_len_));
|
||||
}
|
||||
if (OB_ISNULL(merge_stmt)
|
||||
|| OB_ISNULL(allocator_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -458,11 +462,9 @@ int ObMergeResolver::resolve_generate_table(const ParseNode &table_node,
|
||||
} else if (OB_UNLIKELY(NULL == (item = merge_stmt->create_table_item(*allocator_)))) {
|
||||
ret = OB_ALLOCATE_MEMORY_FAILED;
|
||||
LOG_ERROR("create table item failed", K(ret));
|
||||
} else if (alias_name.empty() && OB_FAIL(merge_stmt->generate_anonymous_view_name(*allocator_, alias_name))) {
|
||||
LOG_WARN("failed to generate view name", K(ret));
|
||||
} else {
|
||||
ObString alias_name;
|
||||
if (alias_node != NULL) {
|
||||
alias_name.assign_ptr((char *)(alias_node->str_value_), static_cast<int32_t>(alias_node->str_len_));
|
||||
}
|
||||
item->ref_query_ = child_stmt;
|
||||
item->table_id_ = generate_table_id();
|
||||
item->table_name_ = alias_name;
|
||||
|
@ -282,8 +282,6 @@ int ObMultiTableInsertResolver::resolve_multi_insert_subquey(const ParseNode &su
|
||||
LOG_WARN("add session id value to select item failed", K(ret));
|
||||
} else if (OB_FAIL(add_new_sel_item_for_oracle_label_security_table(*select_stmt))) {
|
||||
LOG_WARN("add label security columns to select item failed", K(ret));
|
||||
} else if (OB_FAIL(insert_all_stmt->generate_anonymous_view_name(*allocator_, view_name))) {
|
||||
LOG_WARN("failed to generate view name", K(ret));
|
||||
} else if (OB_FAIL(resolve_generate_table_item(select_stmt, view_name, sub_select_table))) {
|
||||
LOG_WARN("failed to resolve generate table item", K(ret));
|
||||
} else if (OB_FAIL(resolve_all_generated_table_columns(*sub_select_table, column_items))) {
|
||||
|
@ -1212,11 +1212,6 @@ int ObSelectResolver::resolve_normal_query(const ParseNode &parse_tree)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// add table_name for anonymous view(view in from)
|
||||
if (OB_SUCC(ret) && OB_FAIL(add_name_for_anonymous_view())) {
|
||||
LOG_WARN("fail to add name for anonymous view", K(ret));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
@ -6705,34 +6700,6 @@ int ObSelectResolver::recursive_check_grouping_columns(ObSelectStmt *stmt, ObRaw
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ObSelectResolver::add_name_for_anonymous_view()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSelectStmt *stmt = get_select_stmt();
|
||||
if (OB_ISNULL(stmt)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null pointer", K(ret));
|
||||
} else {
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_table_size(); i++) {
|
||||
TableItem *tmp_table = stmt->get_table_item(i);
|
||||
if (OB_ISNULL(tmp_table)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("get unexpected null pointer", K(ret));
|
||||
} else if (tmp_table->is_generated_table()
|
||||
&& tmp_table->alias_name_.empty()
|
||||
&& tmp_table->table_name_.empty()) {
|
||||
// found anonymous view, generate new name.
|
||||
if (OB_FAIL(stmt->generate_anonymous_view_name(*params_.allocator_, tmp_table->table_name_))) {
|
||||
LOG_WARN("fail to generate view name", K(ret));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSelectResolver::resolve_shared_order_item(OrderItem &order_item, ObSelectStmt *select_stmt)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
|
@ -341,9 +341,6 @@ private:
|
||||
int check_cube_items_valid(const common::ObIArray<ObCubeItem> &cube_items);
|
||||
int recursive_check_grouping_columns(ObSelectStmt *stmt, ObRawExpr *expr);
|
||||
|
||||
int add_name_for_anonymous_view();
|
||||
int add_name_for_anonymous_view_recursive(TableItem *table_item);
|
||||
|
||||
int is_need_check_col_dup(const ObRawExpr *expr, bool &need_check);
|
||||
|
||||
int resolve_shared_order_item(OrderItem &order_item, ObSelectStmt *select_stmt);
|
||||
|
@ -374,10 +374,10 @@ int ObSelectStmt::create_select_list_for_set_stmt(ObRawExprFactory &expr_factory
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObSelectStmt::update_stmt_table_id(const ObSelectStmt &other)
|
||||
int ObSelectStmt::update_stmt_table_id(ObIAllocator *allocator, const ObSelectStmt &other)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_FAIL(ObDMLStmt::update_stmt_table_id(other))) {
|
||||
if (OB_FAIL(ObDMLStmt::update_stmt_table_id(allocator, other))) {
|
||||
LOG_WARN("failed to update stmt table id", K(ret));
|
||||
} else if (OB_UNLIKELY(set_query_.count() != other.set_query_.count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -391,7 +391,7 @@ int ObSelectStmt::update_stmt_table_id(const ObSelectStmt &other)
|
||||
|| OB_ISNULL(child_query = set_query_.at(i))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("null statement", K(ret), K(child_query), K(other_child_query));
|
||||
} else if (OB_FAIL(SMART_CALL(child_query->update_stmt_table_id(*other_child_query)))) {
|
||||
} else if (OB_FAIL(SMART_CALL(child_query->update_stmt_table_id(allocator, *other_child_query)))) {
|
||||
LOG_WARN("failed to update stmt table id", K(ret));
|
||||
} else { /* do nothing*/ }
|
||||
}
|
||||
|
@ -342,7 +342,7 @@ public:
|
||||
ObStmtExprVisitor &visitor);
|
||||
int iterate_rollup_items(ObIArray<ObRollupItem> &rollup_items, ObStmtExprVisitor &visitor);
|
||||
int iterate_cube_items(ObIArray<ObCubeItem> &cube_items, ObStmtExprVisitor &visitor);
|
||||
int update_stmt_table_id(const ObSelectStmt &other);
|
||||
int update_stmt_table_id(ObIAllocator *allocator, const ObSelectStmt &other);
|
||||
int64_t get_select_item_size() const { return select_items_.count(); }
|
||||
int64_t get_group_expr_size() const { return group_exprs_.count(); }
|
||||
int64_t get_rollup_expr_size() const { return rollup_exprs_.count(); }
|
||||
|
@ -824,40 +824,31 @@ int ObQueryHint::get_table_item_by_hint_table(const ObDMLStmt &stmt,
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
table_item = NULL;
|
||||
bool implicit_match_allowed = table.qb_name_.empty();
|
||||
const ObIArray<TableItem*> &table_items = stmt.get_table_items();
|
||||
int64_t num = table_items.count();
|
||||
TableItem *item = NULL;
|
||||
TableItem *final_item = NULL;
|
||||
TableItem *tmp_item = NULL;
|
||||
bool qb_name_matched = false;
|
||||
bool tmp_qb_name_matched = false;
|
||||
bool valid = true;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && NULL == final_item && i < num; ++i) {
|
||||
if (OB_ISNULL(item = table_items.at(i)) || OB_UNLIKELY(item->qb_name_.empty())) {
|
||||
TableItem *cur_table_item = NULL;
|
||||
TableItem *explicit_matched = NULL;
|
||||
TableItem *implicit_matched = NULL;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && NULL == explicit_matched && i < table_items.count(); ++i) {
|
||||
if (OB_ISNULL(cur_table_item = table_items.at(i)) || OB_UNLIKELY(cur_table_item->qb_name_.empty())) {
|
||||
ret = OB_ERR_UNEXPECTED; // qb_name_ should not be empty
|
||||
LOG_WARN("unexpected table item.", K(ret), K(item));
|
||||
} else if (!table.is_match_table_item(cs_type_, *item)) {
|
||||
LOG_WARN("unexpected table item.", K(ret), K(cur_table_item));
|
||||
} else if (!table.is_match_table_item(cs_type_, *cur_table_item)) {
|
||||
/* do nothing */
|
||||
} else if (OB_FALSE_IT(tmp_qb_name_matched = (0 == item->qb_name_.case_compare(table.qb_name_)))) {
|
||||
} else if (!table.db_name_.empty() && tmp_qb_name_matched) {
|
||||
final_item = item;
|
||||
} else if ((NULL == tmp_item) || (!qb_name_matched && tmp_qb_name_matched)) {
|
||||
tmp_item = item;
|
||||
qb_name_matched = tmp_qb_name_matched;
|
||||
} else if (qb_name_matched && !tmp_qb_name_matched) {
|
||||
} else if (0 == cur_table_item->qb_name_.case_compare(table.qb_name_)) {
|
||||
explicit_matched = cur_table_item;
|
||||
} else if (!implicit_match_allowed) {
|
||||
/* do nothing */
|
||||
} else if (NULL == implicit_matched) {
|
||||
implicit_matched = cur_table_item;
|
||||
} else {
|
||||
tmp_item = NULL;
|
||||
qb_name_matched = false;
|
||||
valid = false;
|
||||
implicit_match_allowed = false;
|
||||
implicit_matched = NULL;
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
if (NULL != final_item) {
|
||||
table_item = final_item;
|
||||
} else if (valid && NULL != tmp_item) {
|
||||
table_item = tmp_item;
|
||||
} else {
|
||||
table_item = NULL != explicit_matched ? explicit_matched : implicit_matched;
|
||||
if (NULL == table_item) {
|
||||
LOG_TRACE("no table item matched hint table", K(table), K(table_items));
|
||||
}
|
||||
}
|
||||
@ -1315,7 +1306,8 @@ int ObStmtHint::merge_hint(ObHint &hint,
|
||||
|| hint.is_join_hint()
|
||||
|| hint.is_join_filter_hint()
|
||||
|| hint.is_table_parallel_hint()
|
||||
|| hint.is_table_dynamic_sampling_hint()) {
|
||||
|| hint.is_table_dynamic_sampling_hint()
|
||||
|| hint.is_pq_subquery_hint()) {
|
||||
if (OB_FAIL(add_var_to_array_no_dup(other_opt_hints_, &hint))) {
|
||||
LOG_WARN("failed to add var to array", K(ret));
|
||||
}
|
||||
@ -1370,30 +1362,6 @@ int ObStmtHint::reset_explicit_trans_hint(ObItemType hint_type)
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObStmtHint::get_max_table_parallel(const ObDMLStmt &stmt, int64_t &max_table_parallel) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
max_table_parallel = ObGlobalHint::UNSET_PARALLEL;
|
||||
const ObHint *hint = NULL;
|
||||
bool matched = false;
|
||||
if (OB_ISNULL(query_hint_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(query_hint_));
|
||||
}
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < other_opt_hints_.count(); ++i) {
|
||||
if (OB_NOT_NULL(hint = other_opt_hints_.at(i)) && hint->is_table_parallel_hint()) {
|
||||
if (OB_FAIL(stmt.check_hint_table_matched_table_item(query_hint_->cs_type_,
|
||||
static_cast<const ObTableParallelHint*>(hint)->get_table(), matched))) {
|
||||
LOG_WARN("failed to check hint table matched table item", K(ret));
|
||||
} else if (matched) {
|
||||
max_table_parallel = std::max(max_table_parallel,
|
||||
static_cast<const ObTableParallelHint*>(hint)->get_parallel());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool ObStmtHint::has_enable_hint(ObItemType hint_type) const
|
||||
{
|
||||
const ObHint *cur_hint = get_normal_hint(hint_type);
|
||||
@ -1498,6 +1466,10 @@ int ObLogPlanHint::init_other_opt_hints(ObSqlSchemaGuard &schema_guard,
|
||||
*static_cast<const ObTableDynamicSamplingHint*>(hint)))) {
|
||||
LOG_WARN("failed to add dynamic sampling hint", K(ret));
|
||||
}
|
||||
} else if (hint->is_pq_subquery_hint()) {
|
||||
if (OB_FAIL(normal_hints_.push_back(hint))) {
|
||||
LOG_WARN("failed to push back", K(ret));
|
||||
}
|
||||
} else {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected hint type in other_opt_hints_", K(ret), K(*hint));
|
||||
@ -1979,6 +1951,43 @@ int ObLogPlanHint::check_valid_set_left_branch(const ObSelectStmt *select_stmt,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObLogPlanHint::get_valid_pq_subquery_hint(const ObIArray<ObString> &sub_qb_names,
|
||||
const ObPQSubqueryHint *&explicit_hint,
|
||||
const ObPQSubqueryHint *&implicit_hint) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
for (int64_t i = 0; NULL == explicit_hint && i < normal_hints_.count(); ++i) {
|
||||
if (NULL != normal_hints_.at(i) && normal_hints_.at(i)->get_hint_type() == T_PQ_SUBQUERY) {
|
||||
const ObPQSubqueryHint *cur_hint = static_cast<const ObPQSubqueryHint*>(normal_hints_.at(i));
|
||||
if (NULL == explicit_hint && cur_hint->is_match_subplans(sub_qb_names)) {
|
||||
explicit_hint = cur_hint;
|
||||
} else if (NULL == implicit_hint && cur_hint->get_sub_qb_names().empty()) {
|
||||
implicit_hint = cur_hint;
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
DistAlgo ObLogPlanHint::get_valid_pq_subquery_dist_algo(const ObIArray<ObString> &sub_qb_names,
|
||||
const bool implicit_allowed) const
|
||||
{
|
||||
int ret = OB_SUCCESS; // ignore this ret
|
||||
DistAlgo dist_algo = DistAlgo::DIST_INVALID_METHOD;
|
||||
const ObPQSubqueryHint *explicit_hint = NULL;
|
||||
const ObPQSubqueryHint *implicit_hint = NULL;
|
||||
if (OB_FAIL(get_valid_pq_subquery_hint(sub_qb_names, explicit_hint, implicit_hint))) {
|
||||
LOG_WARN("failed to get valid subplan filter hint", K(ret));
|
||||
} else if (NULL != explicit_hint) {
|
||||
dist_algo = explicit_hint->get_dist_algo();
|
||||
} else if (is_outline_data_) {
|
||||
dist_algo = DistAlgo::DIST_BASIC_METHOD;
|
||||
} else if (NULL != implicit_hint && implicit_allowed) {
|
||||
dist_algo = implicit_hint->get_dist_algo();
|
||||
}
|
||||
return dist_algo;
|
||||
}
|
||||
|
||||
// generate spm evolution plan, throw a error code when can not get valid hint
|
||||
int ObLogPlanHint::check_status() const
|
||||
{
|
||||
|
@ -219,7 +219,6 @@ struct ObStmtHint
|
||||
int merge_hint(ObHint &hint, ObHintMergePolicy policy, ObIArray<ObItemType> &conflict_hints);
|
||||
int merge_normal_hint(ObHint &hint, ObHintMergePolicy policy, ObIArray<ObItemType> &conflict_hints);
|
||||
int reset_explicit_trans_hint(ObItemType hint_type);
|
||||
int get_max_table_parallel(const ObDMLStmt &stmt, int64_t &max_table_parallel) const;
|
||||
|
||||
|
||||
bool has_enable_hint(ObItemType hint_type) const;
|
||||
@ -458,6 +457,11 @@ struct ObLogPlanHint
|
||||
bool &force_use_merge,
|
||||
bool &force_part_sort,
|
||||
bool &force_normal_sort) const;
|
||||
int get_valid_pq_subquery_hint(const ObIArray<ObString> &sub_qb_names,
|
||||
const ObPQSubqueryHint *&explicit_hint,
|
||||
const ObPQSubqueryHint *&implicit_hint) const;
|
||||
DistAlgo get_valid_pq_subquery_dist_algo(const ObIArray<ObString> &sub_qb_names,
|
||||
const bool implicit_allowed) const;
|
||||
|
||||
bool use_late_material() const { return has_enable_hint(T_USE_LATE_MATERIALIZATION); }
|
||||
bool no_use_late_material() const { return has_disable_hint(T_USE_LATE_MATERIALIZATION); }
|
||||
|
@ -1070,13 +1070,6 @@ int ObQueryRange::compute_range_size(const ObIArray<ObKeyPart*> &key_parts,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObQueryRange::is_at_most_one_row(bool &is_one_row) const
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
is_one_row = table_graph_.is_precise_get_;
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObQueryRange::is_get(bool &is_range_get) const
|
||||
{
|
||||
return is_get(column_count_, is_range_get);
|
||||
|
@ -457,7 +457,6 @@ public:
|
||||
}
|
||||
return bret;
|
||||
}
|
||||
int is_at_most_one_row(bool &is_one_row) const;
|
||||
int is_get(bool &is_get) const;
|
||||
int is_get(int64_t column_count, bool &is_get) const;
|
||||
bool is_precise_get() const { return table_graph_.is_precise_get_; }
|
||||
|
@ -1409,7 +1409,7 @@ int ObTransformAggrSubquery::check_stmt_valid(ObDMLStmt &stmt, bool &is_valid)
|
||||
bool can_set_unique = false;
|
||||
if (stmt.is_set_stmt() || stmt.is_hierarchical_query() || !stmt.is_sel_del_upd()) {
|
||||
is_valid = false;
|
||||
} else if (OB_FAIL(ObTransformUtils::check_can_set_stmt_unique(&stmt, can_set_unique))) {
|
||||
} else if (OB_FAIL(StmtUniqueKeyProvider::check_can_set_stmt_unique(&stmt, can_set_unique))) {
|
||||
LOG_WARN("failed to check can set stmt unque", K(ret));
|
||||
} else if (!can_set_unique) {
|
||||
is_valid = false;
|
||||
@ -1856,7 +1856,8 @@ int ObTransformAggrSubquery::get_unique_keys(ObDMLStmt &stmt,
|
||||
LOG_WARN("transform context is invalid", K(ret), K(ctx_), K(query_hint));
|
||||
} else if (is_first_trans) {
|
||||
// 第一次改写时需要生成所有from table的unique 可以
|
||||
if (OB_FAIL(ObTransformUtils::generate_unique_key(ctx_, &stmt, empty_ignore_tables, pkeys))) {
|
||||
StmtUniqueKeyProvider unique_key_provider(false);
|
||||
if (OB_FAIL(unique_key_provider.generate_unique_key(ctx_, &stmt, empty_ignore_tables, pkeys))) {
|
||||
LOG_WARN("failed to generate unique key", K(ret));
|
||||
}
|
||||
} else if ((query_hint->has_outline_data() && stmt.get_table_items().count() < 1) ||
|
||||
|
@ -96,7 +96,7 @@ int ObTransformCountToExists::construct_transform_hint(ObDMLStmt &stmt, void *tr
|
||||
LOG_WARN("get unexpected null", K(ret), K(query_expr));
|
||||
} else if (OB_FAIL(query_expr->get_ref_stmt()->get_qb_name(qb_name))) {
|
||||
LOG_WARN("failed to get qb name", K(ret));
|
||||
} else if (OB_FAIL(hint->get_qb_name_list().push_back(qb_name))) {
|
||||
} else if (OB_FAIL(hint->get_qb_names().push_back(qb_name))) {
|
||||
LOG_WARN("failed to push back qb name", K(ret));
|
||||
}
|
||||
}
|
||||
|
@ -68,6 +68,8 @@ int ObTransformGroupByPullup::transform_one_stmt(common::ObIArray<ObParentDMLStm
|
||||
ObSelectStmt *view_stmt = NULL;
|
||||
int64_t view_id = valid_views.at(i).table_id_;
|
||||
TableItem *view = NULL;
|
||||
StmtUniqueKeyProvider unique_key_provider;
|
||||
try_trans_helper.unique_key_provider_ = &unique_key_provider;
|
||||
LOG_DEBUG("begin pull up", K(valid_views.count()), K(valid_views.at(i).need_merge_));
|
||||
if (OB_FAIL(ObTransformUtils::deep_copy_stmt(*ctx_->stmt_factory_,
|
||||
*ctx_->expr_factory_,
|
||||
@ -80,7 +82,7 @@ int ObTransformGroupByPullup::transform_one_stmt(common::ObIArray<ObParentDMLStm
|
||||
} else if (OB_FALSE_IT(pullup_ctx.view_talbe_id_ = valid_views.at(i).table_id_)) {
|
||||
} else if (OB_FAIL(get_trans_view(trans_stmt, view_stmt))) {
|
||||
LOG_WARN("failed to get transform view", K(ret));
|
||||
} else if (OB_FAIL(do_groupby_pull_up(view_stmt, valid_views.at(i)))) {
|
||||
} else if (OB_FAIL(do_groupby_pull_up(view_stmt, valid_views.at(i), unique_key_provider))) {
|
||||
LOG_WARN("failed to do pull up group by", K(ret));
|
||||
} else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt,
|
||||
valid_views.at(i).need_merge_, true,
|
||||
@ -226,7 +228,7 @@ int ObTransformGroupByPullup::check_groupby_pullup_validity(ObDMLStmt *stmt,
|
||||
OPT_TRACE("stmt contain for update, can not transform");
|
||||
} else if (OB_FAIL(stmt->check_if_contain_inner_table(contain_inner_table))) {
|
||||
LOG_WARN("failed to check if contain inner table", K(ret));
|
||||
} else if (OB_FAIL(ObTransformUtils::check_can_set_stmt_unique(stmt, has_unique_keys))) {
|
||||
} else if (OB_FAIL(StmtUniqueKeyProvider::check_can_set_stmt_unique(stmt, has_unique_keys))) {
|
||||
LOG_WARN("failed to check stmt has unique keys", K(ret));
|
||||
} else if (!has_unique_keys) {
|
||||
//如果当前stmt不能生成唯一键,do nothing
|
||||
@ -704,7 +706,9 @@ int ObTransformGroupByPullup::get_trans_view(ObDMLStmt *stmt, ObSelectStmt *&vie
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformGroupByPullup::do_groupby_pull_up(ObSelectStmt *stmt, PullupHelper &helper)
|
||||
int ObTransformGroupByPullup::do_groupby_pull_up(ObSelectStmt *stmt,
|
||||
PullupHelper &helper,
|
||||
StmtUniqueKeyProvider &unique_key_provider)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<ObRawExpr *, 4> unique_exprs;
|
||||
@ -724,10 +728,10 @@ int ObTransformGroupByPullup::do_groupby_pull_up(ObSelectStmt *stmt, PullupHelpe
|
||||
LOG_WARN("subquery is null", K(*table_item), K(ret));
|
||||
} else if (OB_FAIL(ignore_tables.add_member(stmt->get_table_bit_index(table_item->table_id_)))) {
|
||||
LOG_WARN("failed to add ignore table index", K(ret));
|
||||
} else if (OB_FAIL(ObTransformUtils::generate_unique_key(ctx_,
|
||||
stmt,
|
||||
ignore_tables,
|
||||
unique_exprs))) {
|
||||
} else if (OB_FAIL(unique_key_provider.generate_unique_key(ctx_,
|
||||
stmt,
|
||||
ignore_tables,
|
||||
unique_exprs))) {
|
||||
LOG_WARN("failed to generated unique keys", K(ret));
|
||||
} else if (OB_FAIL(append(stmt->get_group_exprs(), unique_exprs))) {
|
||||
LOG_WARN("failed to append group exprs", K(ret));
|
||||
|
@ -127,7 +127,9 @@ private:
|
||||
ObRawExpr *&null_propagate_column,
|
||||
bool &is_valid);
|
||||
|
||||
int do_groupby_pull_up(ObSelectStmt *stmt, PullupHelper &helper);
|
||||
int do_groupby_pull_up(ObSelectStmt *stmt,
|
||||
PullupHelper &helper,
|
||||
StmtUniqueKeyProvider &unique_key_provider);
|
||||
|
||||
int get_trans_view(ObDMLStmt *stmt, ObSelectStmt *&view_stmt);
|
||||
|
||||
|
@ -160,11 +160,15 @@ int ObTransformOrExpansion::transform_in_where_conditon(ObIArray<ObParentDMLStmt
|
||||
ctx.expand_exprs_.reuse();
|
||||
ObDMLStmt *trans_stmt = upper_stmt;
|
||||
ObSelectStmt *transformed_union_stmt = NULL;
|
||||
StmtUniqueKeyProvider unique_key_provider;
|
||||
try_trans_helper2.unique_key_provider_ = &unique_key_provider;
|
||||
if (reached_max_times_for_or_expansion()) {
|
||||
/*do nothing*/
|
||||
OPT_TRACE("retry count reached max times:", try_times_);
|
||||
} else if (OB_FAIL(transform_or_expansion(spj_stmt, OB_INVALID_ID, trans_infos.at(i).pos_,
|
||||
!expect_ordering.empty(), ctx, transformed_union_stmt))) {
|
||||
!expect_ordering.empty(), ctx,
|
||||
transformed_union_stmt,
|
||||
unique_key_provider))) {
|
||||
LOG_WARN("failed to do transformation", K(ret));
|
||||
} else if (OB_FAIL(merge_stmt(trans_stmt, spj_stmt, transformed_union_stmt))) {
|
||||
LOG_WARN("failed to merge stmt", K(ret));
|
||||
@ -252,6 +256,8 @@ int ObTransformOrExpansion::transform_in_semi_info(ObIArray<ObParentDMLStmt> &pa
|
||||
ctx.expand_exprs_.reuse();
|
||||
ObSelectStmt *transformed_union_stmt = NULL;
|
||||
trans_stmt = upper_stmt;
|
||||
StmtUniqueKeyProvider unique_key_provider;
|
||||
try_trans_helper2.unique_key_provider_ = &unique_key_provider;
|
||||
if (reached_max_times_for_or_expansion()) {
|
||||
/*do nothing*/
|
||||
OPT_TRACE("retry count reached max times:", try_times_);
|
||||
@ -261,7 +267,8 @@ int ObTransformOrExpansion::transform_in_semi_info(ObIArray<ObParentDMLStmt> &pa
|
||||
} else if (INVALID_OR_EXPAND_TYPE == ctx.or_expand_type_) {
|
||||
/*do nothing*/
|
||||
} else if (OB_FAIL(transform_or_expansion(spj_stmt, semi_info->semi_id_, i,
|
||||
false, ctx, transformed_union_stmt))) {
|
||||
false, ctx, transformed_union_stmt,
|
||||
unique_key_provider))) {
|
||||
LOG_WARN("failed to do transformation", K(ret));
|
||||
} else if (OB_FAIL(merge_stmt(trans_stmt, spj_stmt, transformed_union_stmt))) {
|
||||
LOG_WARN("failed to merge stmt", K(ret));
|
||||
@ -419,12 +426,14 @@ int ObTransformOrExpansion::try_do_transform_inner_join(ObIArray<ObParentDMLStmt
|
||||
ctx.expand_exprs_.reuse();
|
||||
ObDMLStmt *trans_stmt = ref_query;
|
||||
ObSelectStmt *union_stmt = NULL;
|
||||
StmtUniqueKeyProvider unique_key_provider;
|
||||
try_trans_helper2.unique_key_provider_ = &unique_key_provider;
|
||||
if (reached_max_times_for_or_expansion()) {
|
||||
/*do nothing*/
|
||||
OPT_TRACE("retry count reached max times:", try_times_);
|
||||
} else if (OB_FAIL(transform_or_expansion(ref_query, OB_INVALID_ID,
|
||||
trans_infos.at(i).pos_, false,
|
||||
ctx, union_stmt))) {
|
||||
ctx, union_stmt, unique_key_provider))) {
|
||||
LOG_WARN("failed to do transformation", K(ret));
|
||||
} else if (OB_FAIL(merge_stmt(trans_stmt, ref_query, union_stmt))) {
|
||||
LOG_WARN("failed to merge stmt", K(ret));
|
||||
@ -488,6 +497,8 @@ int ObTransformOrExpansion::try_do_transform_left_join(ObIArray<ObParentDMLStmt>
|
||||
ObSEArray<ObRawExpr*, 1> dummy_exprs;
|
||||
ObTryTransHelper try_trans_helper1;
|
||||
ObTryTransHelper try_trans_helper2;
|
||||
StmtUniqueKeyProvider unique_key_provider1;
|
||||
try_trans_helper1.unique_key_provider_ = &unique_key_provider1;
|
||||
if (OB_ISNULL(stmt) || OB_ISNULL(joined_table) || OB_ISNULL(ctx_) ||
|
||||
OB_ISNULL(ctx_->stmt_factory_) || OB_ISNULL(ctx_->expr_factory_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
@ -521,6 +532,7 @@ int ObTransformOrExpansion::try_do_transform_left_join(ObIArray<ObParentDMLStmt>
|
||||
dummy_exprs, cur_joined_table, trans_infos))) {
|
||||
LOG_WARN("failed to get conds trans infos", K(ret));
|
||||
} else if (OB_FAIL(add_select_item_to_ref_query(ref_query, not_null_side_table->table_id_,
|
||||
unique_key_provider1,
|
||||
left_unique_pos, right_flag_pos))) {
|
||||
LOG_WARN("failed to set stmt unique", K(ret));
|
||||
} else if (OB_FAIL(try_trans_helper2.fill_helper(stmt->get_query_ctx()))) {
|
||||
@ -533,12 +545,14 @@ int ObTransformOrExpansion::try_do_transform_left_join(ObIArray<ObParentDMLStmt>
|
||||
ctx.expand_exprs_.reuse();
|
||||
ObSelectStmt *trans_ref_query = NULL;
|
||||
ObDMLStmt *trans_stmt = origin_trans_stmt;
|
||||
StmtUniqueKeyProvider unique_key_provider2;
|
||||
try_trans_helper2.unique_key_provider_ = &unique_key_provider2;
|
||||
if (reached_max_times_for_or_expansion()) {
|
||||
/*do nothing*/
|
||||
OPT_TRACE("retry count reached max times:", try_times_);
|
||||
} else if (OB_FAIL(transform_or_expansion(ref_query, joined_table->table_id_,
|
||||
trans_infos.at(i).pos_, false, ctx,
|
||||
trans_ref_query))) {
|
||||
trans_ref_query, unique_key_provider2))) {
|
||||
LOG_WARN("failed to do transformation", K(ret));
|
||||
} else if (OB_FAIL(do_transform_for_left_join(trans_ref_query, left_unique_pos,
|
||||
right_flag_pos))) {
|
||||
@ -634,7 +648,7 @@ int ObTransformOrExpansion::check_child_table_valid(JoinedTable *cur_table,
|
||||
not_null_side_table = child_stmt->is_set_distinct() ? not_null_side_table : NULL;
|
||||
} else if (child_stmt->is_hierarchical_query() || child_stmt->has_rollup()) {
|
||||
not_null_side_table = NULL;
|
||||
} else if (OB_FAIL(ObTransformUtils::check_can_set_stmt_unique(child_stmt, can_set_unique))) {
|
||||
} else if (OB_FAIL(StmtUniqueKeyProvider::check_can_set_stmt_unique(child_stmt, can_set_unique))) {
|
||||
LOG_WARN("failed to check can set stmt unique", K(ret));
|
||||
} else if (!can_set_unique) {
|
||||
not_null_side_table = NULL;
|
||||
@ -678,6 +692,7 @@ int ObTransformOrExpansion::get_table_not_on_null_side(TableItem *cur_table,
|
||||
// add left table unique key, right table falg expr to stmt select
|
||||
int ObTransformOrExpansion::add_select_item_to_ref_query(ObSelectStmt *stmt,
|
||||
const uint64_t flag_table_id,
|
||||
StmtUniqueKeyProvider &unique_key_provider,
|
||||
ObSqlBitSet<> &left_unique_pos,
|
||||
ObSqlBitSet<> &right_flag_pos)
|
||||
{
|
||||
@ -703,8 +718,8 @@ int ObTransformOrExpansion::add_select_item_to_ref_query(ObSelectStmt *stmt,
|
||||
LOG_WARN("failed to get select exprs", K(ret));
|
||||
} else if (OB_FAIL(stmt->get_table_rel_ids(*right_table, right_tables))) {
|
||||
LOG_WARN("faield to get table rel ids", K(ret), K(*right_table));
|
||||
} else if (OB_FAIL(ObTransformUtils::generate_unique_key(ctx_, stmt, right_tables,
|
||||
left_unique_exprs))) {
|
||||
} else if (OB_FAIL(unique_key_provider.generate_unique_key(ctx_, stmt, right_tables,
|
||||
left_unique_exprs))) {
|
||||
LOG_WARN("faield to get table rel ids", K(ret), K(*right_table));
|
||||
} else if (OB_ISNULL(flag_table = stmt->get_table_item_by_id(flag_table_id))) {
|
||||
LOG_WARN("faield to get table item", K(ret), K(flag_table), K(flag_table_id));
|
||||
@ -728,12 +743,9 @@ int ObTransformOrExpansion::add_select_item_to_ref_query(ObSelectStmt *stmt,
|
||||
select_list, right_flag_exprs))) {
|
||||
LOG_WARN("failed to create columns for view", K(ret));
|
||||
}
|
||||
} else if (!flag_table->is_basic_table()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect table item type", K(*flag_table), K(ret));
|
||||
} else if (OB_FAIL(ObTransformUtils::generate_unique_key(ctx_, stmt, flag_table,
|
||||
right_flag_exprs))) {
|
||||
LOG_WARN("failed to generate unique key", K(ret));
|
||||
} else if (OB_FAIL(ObTransformUtils::generate_unique_key_for_basic_table(ctx_, stmt, flag_table,
|
||||
right_flag_exprs))) {
|
||||
LOG_WARN("failed to generate unique key for basic table", K(ret));
|
||||
} else if (OB_UNLIKELY(right_flag_exprs.empty())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect exprs", K(ret), K(right_flag_exprs));
|
||||
@ -1068,7 +1080,7 @@ int ObTransformOrExpansion::has_valid_condition(ObDMLStmt &stmt,
|
||||
OPT_TRACE("check conditions:", conds);
|
||||
if (NULL == expect_ordering) {
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(ObTransformUtils::check_can_set_stmt_unique(&stmt, can_set_distinct))) {
|
||||
} else if (OB_FAIL(StmtUniqueKeyProvider::check_can_set_stmt_unique(&stmt, can_set_distinct))) {
|
||||
LOG_WARN("failed to check can set stmt unique", K(ret));
|
||||
} else if (!can_set_distinct) {
|
||||
/* do nothing */
|
||||
@ -2061,7 +2073,8 @@ int ObTransformOrExpansion::transform_or_expansion(ObSelectStmt *stmt,
|
||||
const int64_t expr_pos,
|
||||
bool is_topk,
|
||||
ObCostBasedRewriteCtx &ctx,
|
||||
ObSelectStmt *&trans_stmt)
|
||||
ObSelectStmt *&trans_stmt,
|
||||
StmtUniqueKeyProvider &unique_key_provider)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSelectStmt *copy_stmt = NULL;
|
||||
@ -2106,7 +2119,7 @@ int ObTransformOrExpansion::transform_or_expansion(ObSelectStmt *stmt,
|
||||
} else if (!ctx.is_set_distinct_ && OB_FAIL(preprocess_or_condition(*view_stmt, trans_id, view_expr_pos))) {
|
||||
LOG_WARN("failed to preprocess or condition", K(ret));
|
||||
} else if (ctx.is_set_distinct_ && !ctx.is_unique_ &&
|
||||
OB_FAIL(ObTransformUtils::recursive_set_stmt_unique(view_stmt, ctx_, true))) {
|
||||
OB_FAIL(unique_key_provider.recursive_set_stmt_unique(view_stmt, ctx_, true))) {
|
||||
LOG_WARN("failed to set stmt unique", K(ret));
|
||||
} else if (!is_topk &&
|
||||
OB_FAIL(classify_or_expr(*view_stmt, conds_exprs->at(view_expr_pos)))) {
|
||||
@ -2134,7 +2147,7 @@ int ObTransformOrExpansion::transform_or_expansion(ObSelectStmt *stmt,
|
||||
LOG_WARN("failed to recursive adjust statement id", K(ret));
|
||||
} else if (OB_FAIL(get_expand_conds(*child_stmt, trans_id, conds_exprs))) {
|
||||
LOG_WARN("failed to get expand conds", K(ret));
|
||||
} else if (OB_FAIL(child_stmt->update_stmt_table_id(*view_stmt))) {
|
||||
} else if (OB_FAIL(child_stmt->update_stmt_table_id(ctx_->allocator_, *view_stmt))) {
|
||||
//update stmt table id after find conds_exprs
|
||||
LOG_WARN("failed to update table id", K(ret));
|
||||
} else if (OB_FAIL(adjust_or_expansion_stmt(conds_exprs, view_expr_pos, i,
|
||||
@ -2355,7 +2368,7 @@ int ObTransformOrExpansion::has_valid_semi_anti_cond(ObDMLStmt &stmt,
|
||||
} else if (has_lob) {
|
||||
// do nothing
|
||||
OPT_TRACE("select expr has lob expr");
|
||||
} else if (OB_FAIL(ObTransformUtils::check_can_set_stmt_unique(&stmt, can_set_unique))) {
|
||||
} else if (OB_FAIL(StmtUniqueKeyProvider::check_can_set_stmt_unique(&stmt, can_set_unique))) {
|
||||
LOG_WARN("failed to check can set stmt unique", K(ret));
|
||||
} else if (!can_set_unique) {
|
||||
// do nothing
|
||||
@ -2491,7 +2504,7 @@ int ObTransformOrExpansion::gather_transform_infos(ObSelectStmt *stmt,
|
||||
LOG_WARN("failed to check stmt has lob", K(ret));
|
||||
} else if (has_lob) {
|
||||
can_set_distinct = false;
|
||||
} else if (OB_FAIL(ObTransformUtils::check_can_set_stmt_unique(stmt, can_set_distinct))) {
|
||||
} else if (OB_FAIL(StmtUniqueKeyProvider::check_can_set_stmt_unique(stmt, can_set_distinct))) {
|
||||
LOG_WARN("failed to check can set stmt unique", K(ret));
|
||||
}
|
||||
|
||||
|
@ -160,6 +160,7 @@ private:
|
||||
|
||||
int add_select_item_to_ref_query(ObSelectStmt *stmt,
|
||||
const uint64_t flag_table_id,
|
||||
StmtUniqueKeyProvider &unique_key_provider,
|
||||
ObSqlBitSet<> &left_unique_pos,
|
||||
ObSqlBitSet<> &right_flag_pos);
|
||||
|
||||
@ -298,7 +299,8 @@ private:
|
||||
const int64_t expr_pos,
|
||||
bool is_topk,
|
||||
ObCostBasedRewriteCtx &ctx,
|
||||
ObSelectStmt *&trans_stmt);
|
||||
ObSelectStmt *&trans_stmt,
|
||||
StmtUniqueKeyProvider &unique_key_provider);
|
||||
int adjust_or_expansion_stmt(ObIArray<ObRawExpr*> *conds_exprs,
|
||||
const int64_t expr_pos,
|
||||
const int64_t param_pos,
|
||||
|
@ -60,15 +60,21 @@ int ObTransformPreProcess::transform_one_stmt(common::ObIArray<ObParentDMLStmt>
|
||||
int ret = OB_SUCCESS;
|
||||
trans_happened = false;
|
||||
bool is_happened = false;
|
||||
if (OB_ISNULL(stmt)) {
|
||||
if (OB_ISNULL(stmt) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->allocator_)) {
|
||||
ret = OB_INVALID_ARGUMENT;
|
||||
LOG_WARN("stmt is NULL", K(ret));
|
||||
LOG_WARN("unexpected NULL", K(ret), K(stmt), K(ctx_));
|
||||
} else if (OB_FAIL(ObTransformUtils::right_join_to_left(stmt))) {
|
||||
LOG_WARN("failed to transform right join as left", K(ret));
|
||||
} else if (parent_stmts.empty() && lib::is_oracle_mode() &&
|
||||
OB_FAIL(formalize_limit_expr(*stmt))) {
|
||||
LOG_WARN("formalize stmt fialed", K(ret));
|
||||
} else if (OB_FAIL(stmt->adjust_duplicated_table_names(*ctx_->allocator_, is_happened))) {
|
||||
LOG_WARN("failed to adjust duplicated table names", K(ret));
|
||||
} else {
|
||||
trans_happened |= is_happened;
|
||||
OPT_TRACE("adjust duplicated table name", is_happened);
|
||||
LOG_TRACE("succeed to adjust duplicated table name", K(is_happened), K(ret));
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
if (OB_FAIL(flatten_conditions(stmt, is_happened))) {
|
||||
LOG_WARN("failed to flatten_condition", K(ret));
|
||||
@ -1494,7 +1500,7 @@ int ObTransformPreProcess::create_child_stmts_for_groupby_sets(ObSelectStmt *ori
|
||||
ctx_->src_hash_val_,
|
||||
i + 1))) {
|
||||
LOG_WARN("failed to recursive adjust statement id", K(ret));
|
||||
} else if (OB_FAIL(groupby_stmt->update_stmt_table_id(*origin_stmt))) {
|
||||
} else if (OB_FAIL(groupby_stmt->update_stmt_table_id(ctx_->allocator_, *origin_stmt))) {
|
||||
LOG_WARN("failed to update stmt table id.", K(ret));
|
||||
} else if (OB_FAIL(groupby_stmt->formalize_stmt(ctx_->session_info_))) {
|
||||
LOG_WARN("failed to formalized stmt.", K(ret));
|
||||
@ -2346,7 +2352,7 @@ int ObTransformPreProcess::create_and_mock_join_view(ObSelectStmt &stmt)
|
||||
ctx_->src_hash_val_,
|
||||
sub_num))) {
|
||||
LOG_WARN("failed to adjust statement id", K(ret));
|
||||
} else if (OB_FAIL(right_view_stmt->update_stmt_table_id(*left_view_stmt))) {
|
||||
} else if (OB_FAIL(right_view_stmt->update_stmt_table_id(ctx_->allocator_, *left_view_stmt))) {
|
||||
LOG_WARN("failed to update stmt table id", K(ret));
|
||||
} else {
|
||||
right_view_stmt->get_start_with_exprs().reset();
|
||||
@ -5153,7 +5159,7 @@ int ObTransformPreProcess::transform_insert_only_merge_into(ObDMLStmt* stmt, ObD
|
||||
ctx_->src_hash_val_,
|
||||
1))) {
|
||||
LOG_WARN("failed to recursive adjust statement id", K(ret));
|
||||
} else if (OB_FAIL(ref_stmt->update_stmt_table_id(*target_table->ref_query_))) {
|
||||
} else if (OB_FAIL(ref_stmt->update_stmt_table_id(ctx_->allocator_, *target_table->ref_query_))) {
|
||||
LOG_WARN("failed to update table id", K(ret));
|
||||
} else if (OB_FALSE_IT(inner_target_table->ref_query_ = ref_stmt)) {
|
||||
} else if (OB_FAIL(ref_stmt->adjust_subquery_list())) {
|
||||
@ -8802,7 +8808,7 @@ int ObTransformPreProcess::expand_full_outer_join(ObSelectStmt *&ref_query)
|
||||
ctx_->src_hash_val_,
|
||||
sub_num))) {
|
||||
LOG_WARN("failed to recursive adjust statement id", K(ret));
|
||||
} else if (OB_FAIL(right_stmt->update_stmt_table_id(*left_stmt))) {
|
||||
} else if (OB_FAIL(right_stmt->update_stmt_table_id(ctx_->allocator_, *left_stmt))) {
|
||||
LOG_WARN("failed to updatew table id in stmt.", K(ret));
|
||||
} else if (right_stmt->get_joined_tables().count() != 1) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
|
@ -1258,12 +1258,8 @@ int ObTransformPredicateMoveAround::pushdown_predicates(
|
||||
pushdown_preds))) {
|
||||
LOG_WARN("recursive pushdown preds into set stmt failed", K(ret));
|
||||
} else {/*do nothing*/}
|
||||
} else if (stmt->is_hierarchical_query() || enable_no_pred_deduce) {
|
||||
} else if (stmt->is_hierarchical_query()) {
|
||||
// do not transform for current level stmt, but need call function to transform child query
|
||||
if (enable_no_pred_deduce) {
|
||||
LOG_TRACE("NO PRED DEDUCE");
|
||||
OPT_TRACE("hint disable transform");
|
||||
}
|
||||
ObArray<ObRawExpr *> dummy_preds;
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_table_size(); ++i) {
|
||||
TableItem *table = stmt->get_table_item(i);
|
||||
@ -1276,6 +1272,13 @@ int ObTransformPredicateMoveAround::pushdown_predicates(
|
||||
LOG_WARN("failed to push down predicates", K(ret));
|
||||
} else {/*do nothing*/}
|
||||
}
|
||||
} else if (enable_no_pred_deduce) {
|
||||
// do not transform for current level stmt, but need call function to transform child query
|
||||
LOG_TRACE("NO PRED DEDUCE");
|
||||
OPT_TRACE("hint disable transform");
|
||||
if (OB_FAIL(pushdown_into_tables_skip_current_level_stmt(*stmt))) {
|
||||
LOG_WARN("failed to pushdown predicates into tables skip current level stmt", K(ret));
|
||||
}
|
||||
} else {
|
||||
const uint64_t pushdown_pred_count = pushdown_preds.count();
|
||||
bool is_happened = false;
|
||||
@ -1383,6 +1386,67 @@ int ObTransformPredicateMoveAround::pushdown_predicates(
|
||||
return ret;
|
||||
}
|
||||
|
||||
// when hint disabled transform for current level stmt, need try transform child stmt in table item in specific ordering.
|
||||
int ObTransformPredicateMoveAround::pushdown_into_tables_skip_current_level_stmt(ObDMLStmt &stmt)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObArray<ObRawExpr *> dummy_preds;
|
||||
TableItem *table_item = NULL;
|
||||
ObIArray<FromItem> &from_items = stmt.get_from_items();
|
||||
ObIArray<SemiInfo*> &semi_infos = stmt.get_semi_infos();
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < from_items.count(); ++i) {
|
||||
if (OB_ISNULL(table_item = stmt.get_table_item(from_items.at(i)))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("params have null", K(ret), K(table_item));
|
||||
} else if (table_item->is_generated_table()) {
|
||||
if (OB_FAIL(SMART_CALL(pushdown_predicates(table_item->ref_query_, dummy_preds)))) {
|
||||
LOG_WARN("failed to push down predicates", K(ret));
|
||||
}
|
||||
} else if (!table_item->is_joined_table()) {
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(pushdown_into_joined_table_skip_current_level_stmt(table_item))) {
|
||||
LOG_WARN("failed to push down predicates", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < semi_infos.count(); ++i) {
|
||||
if (OB_ISNULL(semi_infos.at(i)) ||
|
||||
OB_ISNULL(table_item = stmt.get_table_item_by_id(semi_infos.at(i)->right_table_id_))) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("params have null", K(ret), K(i), K(table_item), K(semi_infos));
|
||||
} else if (!table_item->is_generated_table()) {
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(SMART_CALL(pushdown_predicates(table_item->ref_query_, dummy_preds)))) {
|
||||
LOG_WARN("failed to push down predicates", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformPredicateMoveAround::pushdown_into_joined_table_skip_current_level_stmt(TableItem *table_item)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_ISNULL(table_item)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(table_item));
|
||||
} else if (table_item->is_generated_table()) {
|
||||
ObArray<ObRawExpr *> dummy_preds;
|
||||
if (OB_FAIL(SMART_CALL(pushdown_predicates(table_item->ref_query_, dummy_preds)))) {
|
||||
LOG_WARN("failed to push down predicates", K(ret));
|
||||
}
|
||||
} else if (!table_item->is_joined_table()) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
JoinedTable *joined_table = static_cast<JoinedTable*>(table_item);
|
||||
if (OB_FAIL(SMART_CALL(pushdown_into_joined_table_skip_current_level_stmt(joined_table->left_table_)))) {
|
||||
LOG_WARN("failed to push down predicates", K(ret));
|
||||
} else if (OB_FAIL(SMART_CALL(pushdown_into_joined_table_skip_current_level_stmt(joined_table->right_table_)))) {
|
||||
LOG_WARN("failed to push down predicates", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformPredicateMoveAround::store_all_preds(const ObDMLStmt &stmt,
|
||||
ObIArray<ObSEArray<ObRawExpr*, 16>> &all_preds)
|
||||
{
|
||||
|
@ -156,6 +156,9 @@ private:
|
||||
int pushdown_predicates(ObDMLStmt *stmt,
|
||||
ObIArray<ObRawExpr *> &predicates);
|
||||
|
||||
int pushdown_into_tables_skip_current_level_stmt(ObDMLStmt &stmt);
|
||||
int pushdown_into_joined_table_skip_current_level_stmt(TableItem *table_item);
|
||||
|
||||
/**
|
||||
* @brief pushdown_into_set_stmt
|
||||
* 下推谓词到set stmt的左右子查询中
|
||||
|
@ -923,7 +923,11 @@ int ObTryTransHelper::recover(ObQueryCtx *query_ctx)
|
||||
LOG_WARN("unexpected null query context", K(ret), K(query_ctx));
|
||||
} else if (OB_FAIL(query_ctx->query_hint_.recover_qb_names(qb_name_counts_, query_ctx->stmt_count_))) {
|
||||
LOG_WARN("failed to revover qb names", K(ret));
|
||||
} else if (NULL != unique_key_provider_
|
||||
&& OB_FAIL(unique_key_provider_->recover_useless_unique_for_temp_table())) {
|
||||
LOG_WARN("failed to recover useless unique for temp table", K(ret));
|
||||
} else {
|
||||
unique_key_provider_ = NULL;
|
||||
query_ctx->available_tb_id_ = available_tb_id_;
|
||||
query_ctx->subquery_count_ = subquery_count_;
|
||||
query_ctx->temp_table_count_ = temp_table_count_;
|
||||
|
@ -36,6 +36,7 @@ class ObStmtFactory;
|
||||
class ObPhysicalPlan;
|
||||
class ObCodeGeneratorImpl;
|
||||
class ObLogPlan;
|
||||
class StmtUniqueKeyProvider;
|
||||
|
||||
struct ObTransformerCtx
|
||||
{
|
||||
@ -192,7 +193,11 @@ struct ObParentDMLStmt
|
||||
// use to keep view name/stmt id/qb name stable after copy stmt and try transform
|
||||
struct ObTryTransHelper
|
||||
{
|
||||
ObTryTransHelper() : available_tb_id_(0), subquery_count_(0), temp_table_count_(0)
|
||||
ObTryTransHelper() :
|
||||
available_tb_id_(0),
|
||||
subquery_count_(0),
|
||||
temp_table_count_(0),
|
||||
unique_key_provider_(NULL)
|
||||
{}
|
||||
|
||||
int fill_helper(const ObQueryCtx *query_ctx);
|
||||
@ -203,6 +208,7 @@ struct ObTryTransHelper
|
||||
int64_t subquery_count_;
|
||||
int64_t temp_table_count_;
|
||||
ObSEArray<int64_t, 4, common::ModulePageAllocator, true> qb_name_counts_;
|
||||
StmtUniqueKeyProvider *unique_key_provider_;
|
||||
};
|
||||
|
||||
// record context param values or array/list size
|
||||
|
@ -715,7 +715,8 @@ int ObTransformSemiToInner::collect_unique_property_of_from_items(ObTransformerC
|
||||
if (OB_ISNULL(table)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect null table", K(ret), K(table));
|
||||
} else if (OB_FAIL(ObTransformUtils::generate_unique_key(ctx, stmt, table, pkeys))) {
|
||||
// lijinmao todo: fix bug here, need generate unique from table except basic table
|
||||
} else if (OB_FAIL(ObTransformUtils::generate_unique_key_for_basic_table(ctx, stmt, table, pkeys))) {
|
||||
LOG_WARN("failed to generate unique key", K(ret));
|
||||
} else if (pkeys.empty()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
|
@ -1149,7 +1149,7 @@ int ObTransformTempTable::create_temp_table(ObDMLStmt &root_stmt,
|
||||
if (OB_FAIL(ObTransformUtils::deep_copy_stmt(*ctx_->stmt_factory_, *ctx_->expr_factory_,
|
||||
table->ref_query_, temp_table_stmt))) {
|
||||
LOG_WARN("failed to deep copy stmt", K(ret));
|
||||
} else if (OB_FAIL(temp_table_stmt->update_stmt_table_id(*table->ref_query_))) {
|
||||
} else if (OB_FAIL(temp_table_stmt->update_stmt_table_id(ctx_->allocator_, *table->ref_query_))) {
|
||||
LOG_WARN("failed to update table id", K(ret));
|
||||
} else if (OB_FAIL(stmt->generate_view_name(*ctx_->allocator_,
|
||||
temp_table->table_name_,
|
||||
|
@ -5769,10 +5769,10 @@ int ObTransformUtils::find_relation_expr(ObDMLStmt *stmt,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformUtils::generate_unique_key(ObTransformerCtx *ctx,
|
||||
ObDMLStmt *stmt,
|
||||
TableItem *item,
|
||||
ObIArray<ObRawExpr *> &unique_keys)
|
||||
int ObTransformUtils::generate_unique_key_for_basic_table(ObTransformerCtx *ctx,
|
||||
ObDMLStmt *stmt,
|
||||
TableItem *item,
|
||||
ObIArray<ObRawExpr *> &unique_keys)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
const ObTableSchema *table_schema = NULL;
|
||||
@ -5814,10 +5814,10 @@ int ObTransformUtils::generate_unique_key(ObTransformerCtx *ctx,
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformUtils::generate_unique_key(ObTransformerCtx *ctx,
|
||||
ObDMLStmt *stmt,
|
||||
ObSqlBitSet<> &ignore_tables,
|
||||
ObIArray<ObRawExpr *> &unique_keys)
|
||||
int StmtUniqueKeyProvider::generate_unique_key(ObTransformerCtx *ctx,
|
||||
ObDMLStmt *stmt,
|
||||
ObSqlBitSet<> &ignore_tables,
|
||||
ObIArray<ObRawExpr *> &unique_keys)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSqlBitSet<> from_rel_ids;
|
||||
@ -5831,6 +5831,7 @@ int ObTransformUtils::generate_unique_key(ObTransformerCtx *ctx,
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < table_items.count(); ++i) {
|
||||
TableItem *table = table_items.at(i);
|
||||
int32_t idx = OB_INVALID_INDEX;
|
||||
in_temp_table_ = false;
|
||||
if (OB_ISNULL(table)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("table item is null", K(table), K(ret));
|
||||
@ -5843,13 +5844,11 @@ int ObTransformUtils::generate_unique_key(ObTransformerCtx *ctx,
|
||||
} else if (ignore_tables.has_member(idx)) {
|
||||
//do nothing
|
||||
} else if (table->is_basic_table()) {
|
||||
if (OB_FAIL(generate_unique_key(ctx,
|
||||
stmt,
|
||||
table,
|
||||
unique_keys))) {
|
||||
LOG_WARN("failed to generate unique key", K(ret));
|
||||
if (OB_FAIL(ObTransformUtils::generate_unique_key_for_basic_table(ctx, stmt, table, unique_keys))) {
|
||||
LOG_WARN("failed to generate unique key for basic table", K(ret));
|
||||
}
|
||||
} else if (table->is_generated_table() || table->is_temp_table()) {
|
||||
in_temp_table_ = table->is_temp_table();
|
||||
ObSelectStmt *view_stmt = NULL;
|
||||
ObSEArray<ObRawExpr*, 4> stmt_unique_keys;
|
||||
ObSEArray<ObRawExpr*, 4> column_exprs;
|
||||
@ -5861,17 +5860,17 @@ int ObTransformUtils::generate_unique_key(ObTransformerCtx *ctx,
|
||||
false,
|
||||
&stmt_unique_keys))) {
|
||||
LOG_WARN("recursive set stmt unique failed", K(ret));
|
||||
} else if (OB_FAIL(create_columns_for_view(ctx,
|
||||
*table,
|
||||
stmt,
|
||||
column_exprs))) {
|
||||
} else if (OB_FAIL(ObTransformUtils::create_columns_for_view(ctx,
|
||||
*table,
|
||||
stmt,
|
||||
column_exprs))) {
|
||||
//为view生成column exprs
|
||||
LOG_WARN("failed to create columns for view", K(ret));
|
||||
} else if (OB_FAIL(convert_select_expr_to_column_expr(stmt_unique_keys,
|
||||
*view_stmt,
|
||||
*stmt,
|
||||
table->table_id_,
|
||||
unique_keys))) {
|
||||
} else if (OB_FAIL(ObTransformUtils::convert_select_expr_to_column_expr(stmt_unique_keys,
|
||||
*view_stmt,
|
||||
*stmt,
|
||||
table->table_id_,
|
||||
unique_keys))) {
|
||||
//找到view的unique keys对应的本层column expr
|
||||
LOG_WARN("failed to get stmt unique keys columns expr", K(ret));
|
||||
} else {
|
||||
@ -9295,10 +9294,10 @@ int ObTransformUtils::make_pushdown_limit_count(ObRawExprFactory &expr_factory,
|
||||
* 注意:使用之前需要调用check_can_set_stmt_unique函数确保select_stmt不存在union all,
|
||||
* 因为unoin all不能通过添加主键方式保证输出唯一
|
||||
*/
|
||||
int ObTransformUtils::recursive_set_stmt_unique(ObSelectStmt *select_stmt,
|
||||
ObTransformerCtx *ctx,
|
||||
bool ignore_check_unique,/*default false */
|
||||
ObIArray<ObRawExpr *> *unique_keys)
|
||||
int StmtUniqueKeyProvider::recursive_set_stmt_unique(ObSelectStmt *select_stmt,
|
||||
ObTransformerCtx *ctx,
|
||||
bool ignore_check_unique,/*default false */
|
||||
ObIArray<ObRawExpr *> *unique_keys)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (NULL != unique_keys) {
|
||||
@ -9307,16 +9306,21 @@ int ObTransformUtils::recursive_set_stmt_unique(ObSelectStmt *select_stmt,
|
||||
bool is_unique = false;
|
||||
ObSqlBitSet<> origin_output_rel_ids;
|
||||
ObSEArray<ObRawExpr*, 4> added_unique_keys;
|
||||
const bool in_temp_table = in_temp_table_;
|
||||
int64_t sel_item_count = 0;
|
||||
int64_t col_item_count = 0;
|
||||
if (OB_ISNULL(select_stmt) || OB_ISNULL(ctx) || OB_ISNULL(ctx->allocator_)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected null", K(ret), K(select_stmt), K(ctx));
|
||||
} else if (!ignore_check_unique && (OB_FAIL(check_stmt_unique(select_stmt,
|
||||
ctx->session_info_,
|
||||
ctx->schema_checker_,
|
||||
true /* strict */,
|
||||
is_unique)))) {
|
||||
} else if (!ignore_check_unique && (OB_FAIL(ObTransformUtils::check_stmt_unique(select_stmt,
|
||||
ctx->session_info_,
|
||||
ctx->schema_checker_,
|
||||
true /* strict */,
|
||||
is_unique)))) {
|
||||
LOG_WARN("failed to check stmt unique", K(ret));
|
||||
} else if (is_unique) {
|
||||
sel_item_count = select_stmt->get_select_item_size();
|
||||
col_item_count = select_stmt->get_column_size();
|
||||
if (NULL != unique_keys && OB_FAIL(get_unique_keys_from_unique_stmt(select_stmt,
|
||||
ctx->expr_factory_,
|
||||
*unique_keys,
|
||||
@ -9329,6 +9333,8 @@ int ObTransformUtils::recursive_set_stmt_unique(ObSelectStmt *select_stmt,
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected empty unique keys", K(ret), KPC(select_stmt));
|
||||
} else {
|
||||
sel_item_count = select_stmt->get_select_item_size();
|
||||
col_item_count = select_stmt->get_column_size();
|
||||
ObIArray<TableItem *> &table_items = select_stmt->get_table_items();
|
||||
for (int64_t i = 0; OB_SUCC(ret) && i < table_items.count(); ++i) {
|
||||
TableItem *cur_table = table_items.at(i);
|
||||
@ -9343,6 +9349,7 @@ int ObTransformUtils::recursive_set_stmt_unique(ObSelectStmt *select_stmt,
|
||||
} else if (!origin_output_rel_ids.has_member(bit_id)) {
|
||||
// semi join 中的表, 不会输出
|
||||
} else if (cur_table->is_generated_table() || cur_table->is_temp_table()) {
|
||||
in_temp_table_ = in_temp_table || cur_table->is_temp_table();
|
||||
ObSelectStmt *view_stmt = NULL;
|
||||
ObSEArray<ObRawExpr*, 4> stmt_unique_keys;
|
||||
ObSEArray<ObRawExpr*, 4> column_exprs;
|
||||
@ -9354,24 +9361,26 @@ int ObTransformUtils::recursive_set_stmt_unique(ObSelectStmt *select_stmt,
|
||||
false,
|
||||
&stmt_unique_keys)))) {
|
||||
LOG_WARN("recursive set stmt unique failed", K(ret));
|
||||
} else if (OB_FAIL(create_columns_for_view(ctx,
|
||||
*cur_table,
|
||||
select_stmt,
|
||||
column_exprs))) {
|
||||
} else if (OB_FAIL(ObTransformUtils::create_columns_for_view(ctx,
|
||||
*cur_table,
|
||||
select_stmt,
|
||||
column_exprs))) {
|
||||
//为view生成column exprs
|
||||
LOG_WARN("failed to create columns for view", K(ret));
|
||||
} else if (OB_FAIL(convert_select_expr_to_column_expr(stmt_unique_keys,
|
||||
*view_stmt,
|
||||
*select_stmt,
|
||||
cur_table->table_id_,
|
||||
added_unique_keys))) {
|
||||
} else if (OB_FAIL(ObTransformUtils::convert_select_expr_to_column_expr(stmt_unique_keys,
|
||||
*view_stmt,
|
||||
*select_stmt,
|
||||
cur_table->table_id_,
|
||||
added_unique_keys))) {
|
||||
//找到stmt unique keys对应的本层column expr
|
||||
LOG_WARN("failed to get stmt unique keys columns expr", K(ret));
|
||||
}
|
||||
} else if (!cur_table->is_basic_table()) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpect table item type", K(*cur_table), K(ret));
|
||||
} else if (OB_FAIL(generate_unique_key(ctx, select_stmt, cur_table, added_unique_keys))) {
|
||||
} else if (OB_FAIL(ObTransformUtils::generate_unique_key_for_basic_table(ctx, select_stmt,
|
||||
cur_table,
|
||||
added_unique_keys))) {
|
||||
LOG_WARN("failed to generate unique key", K(ret));
|
||||
}
|
||||
}
|
||||
@ -9386,17 +9395,24 @@ int ObTransformUtils::recursive_set_stmt_unique(ObSelectStmt *select_stmt,
|
||||
LOG_WARN("failed to append unique keys", K(ret));
|
||||
} else if (OB_FAIL(add_non_duplicated_select_expr(added_unique_keys, select_exprs))) {
|
||||
LOG_WARN("failed to add non-duplicated select expr", K(ret));
|
||||
} else if (OB_FAIL(create_select_item(*ctx->allocator_, added_unique_keys, select_stmt))) {
|
||||
} else if (OB_FAIL(ObTransformUtils::create_select_item(*ctx->allocator_, added_unique_keys, select_stmt))) {
|
||||
LOG_WARN("failed to get tables primary keys", K(ret));
|
||||
} else if (OB_FAIL(select_stmt->formalize_stmt(ctx->session_info_))) {
|
||||
LOG_WARN("failed to formalize stmt", K(ret));
|
||||
}
|
||||
}
|
||||
|
||||
if (OB_SUCC(ret)) {
|
||||
in_temp_table_ = in_temp_table;
|
||||
if (OB_FAIL(try_push_back_modified_info(select_stmt, sel_item_count, col_item_count))) {
|
||||
LOG_WARN("failed to try push back modified info", K(ret));
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* select_stmt is unique checked by ObTransformUtils::check_stmt_unique */
|
||||
int ObTransformUtils::get_unique_keys_from_unique_stmt(const ObSelectStmt *select_stmt,
|
||||
int StmtUniqueKeyProvider::get_unique_keys_from_unique_stmt(const ObSelectStmt *select_stmt,
|
||||
ObRawExprFactory *expr_factory,
|
||||
ObIArray<ObRawExpr*> &unique_keys,
|
||||
ObIArray<ObRawExpr*> &added_unique_keys)
|
||||
@ -9426,8 +9442,75 @@ int ObTransformUtils::get_unique_keys_from_unique_stmt(const ObSelectStmt *selec
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformUtils::add_non_duplicated_select_expr(ObIArray<ObRawExpr*> &add_select_exprs,
|
||||
ObIArray<ObRawExpr*> &org_select_exprs)
|
||||
int StmtUniqueKeyProvider::recover_useless_unique_for_temp_table()
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (OB_UNLIKELY(sel_stmts_.count() != sel_item_counts_.count()
|
||||
|| sel_stmts_.count() != col_item_counts_.count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected array count", K(ret), K(sel_stmts_.count()),
|
||||
K(sel_item_counts_.count()), K(col_item_counts_.count()));
|
||||
} else if (sel_stmts_.empty()) {
|
||||
/* do nothing */
|
||||
} else {
|
||||
ObSelectStmt *sel_stmt = NULL;
|
||||
// recover select stmt from the end of the array
|
||||
int64_t sel_item_count = 0;
|
||||
int64_t col_item_count = 0;
|
||||
for (int64_t i = sel_stmts_.count() - 1; OB_SUCC(ret) && i >= 0; --i) {
|
||||
sel_item_count = sel_item_counts_.at(i);
|
||||
col_item_count = col_item_counts_.at(i);
|
||||
if (OB_ISNULL(sel_stmt = sel_stmts_.at(i))
|
||||
|| OB_UNLIKELY(sel_item_count <= 0 || col_item_count < 0)) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected params", K(ret), K(sel_stmt), K(sel_item_count), K(col_item_count));
|
||||
} else if (OB_UNLIKELY(sel_item_count >= sel_stmt->get_select_item_size()
|
||||
|| col_item_count > sel_stmt->get_column_size())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected params", K(ret), K(sel_item_count), K(sel_stmt->get_select_item_size()),
|
||||
K(col_item_count), K(sel_stmt->get_column_size()));
|
||||
} else {
|
||||
ObOptimizerUtil::revert_items(sel_stmt->get_select_items(), sel_item_count);
|
||||
ObOptimizerUtil::revert_items(sel_stmt->get_column_items(), col_item_count);
|
||||
}
|
||||
}
|
||||
if (OB_SUCC(ret)) {
|
||||
sel_stmts_.reuse();
|
||||
sel_item_counts_.reuse();
|
||||
col_item_counts_.reuse();
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int StmtUniqueKeyProvider::try_push_back_modified_info(ObSelectStmt *select_stmt,
|
||||
int64_t sel_item_count,
|
||||
int64_t col_item_count)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
if (!for_costed_trans_) {
|
||||
/* do nothing */
|
||||
} else if (OB_ISNULL(select_stmt) ||
|
||||
OB_UNLIKELY(sel_stmts_.count() != sel_item_counts_.count()
|
||||
|| sel_stmts_.count() != col_item_counts_.count())) {
|
||||
ret = OB_ERR_UNEXPECTED;
|
||||
LOG_WARN("unexpected array count", K(ret), K(select_stmt), K(sel_stmts_.count()),
|
||||
K(sel_item_counts_.count()), K(col_item_counts_.count()));
|
||||
} else if (select_stmt->get_select_item_size() == sel_item_count
|
||||
&& select_stmt->get_column_size() == col_item_count) {
|
||||
/* do nothing */
|
||||
} else if (OB_FAIL(sel_stmts_.push_back(select_stmt))) {
|
||||
LOG_WARN("failed to push back array", K(ret), K(select_stmt));
|
||||
} else if (OB_FAIL(sel_item_counts_.push_back(sel_item_count))) {
|
||||
LOG_WARN("failed to push back array", K(ret), K(sel_item_count));
|
||||
} else if (OB_FAIL(col_item_counts_.push_back(col_item_count))) {
|
||||
LOG_WARN("failed to push back array", K(ret), K(col_item_count));
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int StmtUniqueKeyProvider::add_non_duplicated_select_expr(ObIArray<ObRawExpr*> &add_select_exprs,
|
||||
ObIArray<ObRawExpr*> &org_select_exprs)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
ObSEArray<ObRawExpr*, 4> new_select_exprs;
|
||||
@ -9441,8 +9524,8 @@ int ObTransformUtils::add_non_duplicated_select_expr(ObIArray<ObRawExpr*> &add_s
|
||||
return ret;
|
||||
}
|
||||
|
||||
int ObTransformUtils::check_can_set_stmt_unique(ObDMLStmt *stmt,
|
||||
bool &can_set_unique)
|
||||
int StmtUniqueKeyProvider::check_can_set_stmt_unique(ObDMLStmt *stmt,
|
||||
bool &can_set_unique)
|
||||
{
|
||||
int ret = OB_SUCCESS;
|
||||
can_set_unique = false;
|
||||
@ -14235,7 +14318,7 @@ int ObTransformUtils::expand_temp_table(ObTransformerCtx *ctx, ObDMLStmt::TempTa
|
||||
ctx->src_hash_val_,
|
||||
j))) {
|
||||
LOG_WARN("failed to recursive adjust statement id", K(ret));
|
||||
} else if (OB_FAIL(child_stmt->update_stmt_table_id(*temp_table_query))) {
|
||||
} else if (OB_FAIL(child_stmt->update_stmt_table_id(ctx->allocator_, *temp_table_query))) {
|
||||
LOG_WARN("failed to update table id", K(ret));
|
||||
} else if (OB_FAIL(upper_stmt->formalize_stmt_expr_reference(ctx->expr_factory_,
|
||||
ctx->session_info_))) {
|
||||
|
@ -1038,21 +1038,10 @@ public:
|
||||
ObIArray<ObRawExpr *> &targets,
|
||||
ObIArray<ObRawExprPointer> &parents);
|
||||
|
||||
static int generate_unique_key(ObTransformerCtx *ctx,
|
||||
ObDMLStmt *stmt,
|
||||
TableItem *item,
|
||||
ObIArray<ObRawExpr *> &unique_keys);
|
||||
|
||||
/**
|
||||
* @brief generate_unique_key
|
||||
* 可以对stmt生成唯一键,需要调用
|
||||
* check_can_set_stmt_unique
|
||||
* 确认stmt有唯一键
|
||||
*/
|
||||
static int generate_unique_key(ObTransformerCtx *ctx,
|
||||
ObDMLStmt *stmt,
|
||||
ObSqlBitSet<> &ignore_tables,
|
||||
ObIArray<ObRawExpr *> &unique_keys);
|
||||
static int generate_unique_key_for_basic_table(ObTransformerCtx *ctx,
|
||||
ObDMLStmt *stmt,
|
||||
TableItem *item,
|
||||
ObIArray<ObRawExpr *> &unique_keys);
|
||||
|
||||
static int check_loseless_join(ObDMLStmt *stmt,
|
||||
ObTransformerCtx *ctx,
|
||||
@ -1365,17 +1354,6 @@ public:
|
||||
ObRawExpr *limit_offset,
|
||||
ObRawExpr *&pushdown_limit_count);
|
||||
|
||||
static int recursive_set_stmt_unique(ObSelectStmt *select_stmt,
|
||||
ObTransformerCtx *ctx,
|
||||
bool ignore_check_unique = false,
|
||||
common::ObIArray<ObRawExpr *> *unique_keys = NULL);
|
||||
static int get_unique_keys_from_unique_stmt(const ObSelectStmt *select_stmt,
|
||||
ObRawExprFactory *expr_factory,
|
||||
ObIArray<ObRawExpr*> &unique_keys,
|
||||
ObIArray<ObRawExpr*> &added_unique_keys);
|
||||
static int check_can_set_stmt_unique(ObDMLStmt *stmt,
|
||||
bool &can_set_unique);
|
||||
|
||||
static int get_rel_ids_from_tables(const ObDMLStmt *stmt,
|
||||
const ObIArray<TableItem*> &table_items,
|
||||
ObRelIds &rel_ids);
|
||||
@ -1920,9 +1898,6 @@ private:
|
||||
ObIArray<ObRawExpr*> &from_exprs,
|
||||
ObIArray<ObRawExpr*> &view_exprs);
|
||||
|
||||
static int add_non_duplicated_select_expr(ObIArray<ObRawExpr*> &add_select_exprs,
|
||||
ObIArray<ObRawExpr*> &org_select_exprs);
|
||||
|
||||
static int extract_shared_exprs(ObDMLStmt *parent,
|
||||
ObSelectStmt *view_stmt,
|
||||
ObIArray<ObRawExpr *> &common_exprs,
|
||||
@ -1946,6 +1921,51 @@ private:
|
||||
bool &is_safe);
|
||||
};
|
||||
|
||||
class StmtUniqueKeyProvider
|
||||
{
|
||||
public:
|
||||
StmtUniqueKeyProvider(bool for_costed_trans = true) :
|
||||
for_costed_trans_(for_costed_trans),
|
||||
in_temp_table_(false)
|
||||
{}
|
||||
virtual ~StmtUniqueKeyProvider() {}
|
||||
|
||||
static int check_can_set_stmt_unique(ObDMLStmt *stmt,
|
||||
bool &can_set_unique);
|
||||
int recursive_set_stmt_unique(ObSelectStmt *select_stmt,
|
||||
ObTransformerCtx *ctx,
|
||||
bool ignore_check_unique = false,
|
||||
common::ObIArray<ObRawExpr *> *unique_keys = NULL);
|
||||
/**
|
||||
* @brief generate_unique_key
|
||||
* generate unique key for stmt, need call check_can_set_stmt_unique before to ensure unique key can be generated
|
||||
*/
|
||||
int generate_unique_key(ObTransformerCtx *ctx,
|
||||
ObDMLStmt *stmt,
|
||||
ObSqlBitSet<> &ignore_tables,
|
||||
ObIArray<ObRawExpr *> &unique_keys);
|
||||
int recover_useless_unique_for_temp_table();
|
||||
private:
|
||||
int get_unique_keys_from_unique_stmt(const ObSelectStmt *select_stmt,
|
||||
ObRawExprFactory *expr_factory,
|
||||
ObIArray<ObRawExpr*> &unique_keys,
|
||||
ObIArray<ObRawExpr*> &added_unique_keys);
|
||||
int try_push_back_modified_info(ObSelectStmt *select_stmt,
|
||||
int64_t sel_item_count,
|
||||
int64_t col_item_count);
|
||||
int add_non_duplicated_select_expr(ObIArray<ObRawExpr*> &add_select_exprs,
|
||||
ObIArray<ObRawExpr*> &org_select_exprs);
|
||||
|
||||
private:
|
||||
DISALLOW_COPY_AND_ASSIGN(StmtUniqueKeyProvider);
|
||||
const bool for_costed_trans_;
|
||||
bool in_temp_table_;
|
||||
// select items in temp tables may be appended by recursive_set_stmt_unique, store some information to recover them.
|
||||
// ordering in array below must be maintained by this class
|
||||
common::ObSEArray<ObSelectStmt*, 4> sel_stmts_;
|
||||
common::ObSEArray<int64_t, 4> sel_item_counts_;
|
||||
common::ObSEArray<int64_t, 4> col_item_counts_;
|
||||
};
|
||||
|
||||
template <typename T>
|
||||
int ObTransformUtils::replace_exprs(const common::ObIArray<ObRawExpr *> &other_exprs,
|
||||
|
@ -739,7 +739,7 @@ Outputs & filters:
|
||||
0 - output([T_FUN_MAX(skyline_int.v1)], [skyline_int.tenant_id], [skyline_int.v6]), filter(nil), rowset=16
|
||||
sort_keys([skyline_int.v3, ASC], [skyline_int.v4, ASC], [skyline_int.v5, ASC])
|
||||
1 - output([skyline_int.v3], [skyline_int.v4], [skyline_int.v5], [T_FUN_MAX(skyline_int.v1)], [skyline_int.tenant_id], [skyline_int.v6]), filter(nil), rowset=16
|
||||
group([skyline_int.v3], [skyline_int.v5], [skyline_int.v4]), agg_func([T_FUN_MAX(skyline_int.v1)])
|
||||
group([skyline_int.v5], [skyline_int.v4], [skyline_int.v3]), agg_func([T_FUN_MAX(skyline_int.v1)])
|
||||
2 - output([skyline_int.v3], [skyline_int.v4], [skyline_int.v5], [skyline_int.tenant_id], [skyline_int.v6], [skyline_int.v1]), filter(nil), rowset=16
|
||||
equal_conds([skyline_int.v3 = other.c1]), other_conds(nil)
|
||||
merge_directions([ASC])
|
||||
@ -852,7 +852,7 @@ Outputs & filters:
|
||||
0 - output([skyline_int.v5], [skyline_int.v4], [skyline_int.v3]), filter(nil), rowset=16
|
||||
sort_keys([skyline_int.v3, ASC])
|
||||
1 - output([skyline_int.v3], [skyline_int.v5], [skyline_int.v4]), filter(nil), rowset=16
|
||||
distinct([skyline_int.v4], [skyline_int.v5], [skyline_int.v3])
|
||||
distinct([skyline_int.v5], [skyline_int.v4], [skyline_int.v3])
|
||||
2 - output([skyline_int.v3], [skyline_int.v5], [skyline_int.v4]), filter(nil), rowset=16
|
||||
equal_conds([skyline_int.v4 = other.c1]), other_conds(nil)
|
||||
merge_directions([ASC])
|
||||
|
@ -277,15 +277,17 @@ Query Plan
|
||||
============================================
|
||||
Outputs & filters:
|
||||
-------------------------------------
|
||||
0 - output([T_FUN_SUM(.c0)], [T_FUN_SUM(length(.c1))], [T_FUN_COUNT(.c2)], [T_FUN_COUNT(.c3)], [T_FUN_COUNT(.c4)], [T_FUN_COUNT(.c5)], [T_FUN_COUNT(.c6)],
|
||||
[T_FUN_COUNT(.c7)]), filter(nil)
|
||||
0 - output([T_FUN_SUM(ANONYMOUS_VIEW1.c0)], [T_FUN_SUM(length(ANONYMOUS_VIEW1.c1))], [T_FUN_COUNT(ANONYMOUS_VIEW1.c2)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c3)],
|
||||
[T_FUN_COUNT(ANONYMOUS_VIEW1.c4)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c5)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c6)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c7)]), filter(nil)
|
||||
limit(1), offset(nil)
|
||||
1 - output([T_FUN_SUM(.c0)], [T_FUN_SUM(length(.c1))], [T_FUN_COUNT(.c2)], [T_FUN_COUNT(.c3)], [T_FUN_COUNT(.c4)], [T_FUN_COUNT(.c5)], [T_FUN_COUNT(.c6)],
|
||||
[T_FUN_COUNT(.c7)]), filter(nil)
|
||||
group(nil), agg_func([T_FUN_SUM(.c0)], [T_FUN_SUM(length(.c1))], [T_FUN_COUNT(.c2)], [T_FUN_COUNT(.c3)], [T_FUN_COUNT(.c4)], [T_FUN_COUNT(.c5)], [T_FUN_COUNT(.c6)],
|
||||
[T_FUN_COUNT(.c7)])
|
||||
2 - output([.c0], [.c1], [.c2], [.c3], [.c4], [.c5], [.c6], [.c7]), filter(nil)
|
||||
access([.c0], [.c1], [.c2], [.c3], [.c4], [.c5], [.c6], [.c7])
|
||||
1 - output([T_FUN_SUM(ANONYMOUS_VIEW1.c0)], [T_FUN_SUM(length(ANONYMOUS_VIEW1.c1))], [T_FUN_COUNT(ANONYMOUS_VIEW1.c2)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c3)],
|
||||
[T_FUN_COUNT(ANONYMOUS_VIEW1.c4)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c5)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c6)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c7)]), filter(nil)
|
||||
group(nil), agg_func([T_FUN_SUM(ANONYMOUS_VIEW1.c0)], [T_FUN_SUM(length(ANONYMOUS_VIEW1.c1))], [T_FUN_COUNT(ANONYMOUS_VIEW1.c2)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c3)],
|
||||
[T_FUN_COUNT(ANONYMOUS_VIEW1.c4)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c5)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c6)], [T_FUN_COUNT(ANONYMOUS_VIEW1.c7)])
|
||||
2 - output([ANONYMOUS_VIEW1.c0], [ANONYMOUS_VIEW1.c1], [ANONYMOUS_VIEW1.c2], [ANONYMOUS_VIEW1.c3], [ANONYMOUS_VIEW1.c4], [ANONYMOUS_VIEW1.c5], [ANONYMOUS_VIEW1.c6],
|
||||
[ANONYMOUS_VIEW1.c7]), filter(nil)
|
||||
access([ANONYMOUS_VIEW1.c0], [ANONYMOUS_VIEW1.c1], [ANONYMOUS_VIEW1.c2], [ANONYMOUS_VIEW1.c3], [ANONYMOUS_VIEW1.c4], [ANONYMOUS_VIEW1.c5], [ANONYMOUS_VIEW1.c6],
|
||||
[ANONYMOUS_VIEW1.c7])
|
||||
3 - output([t111_var.c0], [t111_var.c1], [t111_var.c2], [t111_var.c3], [t111_var.c4], [t111_var.c5], [t111_var.c6], [t111_var.c7]), filter(nil)
|
||||
distinct([t111_var.c0], [t111_var.c1], [t111_var.c2], [t111_var.c3], [t111_var.c4], [t111_var.c5], [t111_var.c6], [t111_var.c7])
|
||||
4 - output([t111_var.c0], [t111_var.c1], [t111_var.c2], [t111_var.c3], [t111_var.c4], [t111_var.c5], [t111_var.c6], [t111_var.c7]), filter(nil)
|
||||
|
@ -1757,6 +1757,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2") NONE ALL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
USE_DAS(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
@ -1858,6 +1859,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2") NONE ALL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
USE_DAS(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
@ -1959,6 +1961,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2") NONE ALL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
USE_DAS(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
@ -2067,6 +2070,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") LOCAL LOCAL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
FULL(@"SEL$3" "t2"@"SEL$3")
|
||||
@ -2187,6 +2191,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") LOCAL LOCAL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
FULL(@"SEL$3" "t2"@"SEL$3")
|
||||
@ -2307,6 +2312,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") LOCAL LOCAL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
FULL(@"SEL$3" "t2"@"SEL$3")
|
||||
@ -2427,6 +2433,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") LOCAL LOCAL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
FULL(@"SEL$3" "t2"@"SEL$3")
|
||||
@ -2554,6 +2561,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3" "SEL$4") LOCAL LOCAL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
FULL(@"SEL$3" "t2"@"SEL$3")
|
||||
@ -2727,6 +2735,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3" "SEL$4" "SEL$5" "SEL$6" "SEL$7" "SEL$8") NONE ALL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
USE_DAS(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
@ -2953,6 +2962,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3" "SEL$4" "SEL$5" "SEL$6" "SEL$7" "SEL$8") NONE ALL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
USE_DAS(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
@ -3179,6 +3189,7 @@ Outline Data:
|
||||
-------------------------------------
|
||||
/*+
|
||||
BEGIN_OUTLINE_DATA
|
||||
PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3" "SEL$4" "SEL$5" "SEL$6" "SEL$7" "SEL$8") NONE ALL)
|
||||
FULL(@"SEL$1" "test"."t1"@"SEL$1")
|
||||
FULL(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
USE_DAS(@"SEL$2" "test"."t2"@"SEL$2")
|
||||
|
Loading…
x
Reference in New Issue
Block a user