fix some outline/hint bugs

This commit is contained in:
obdev 2024-02-08 13:15:19 +00:00 committed by ob-robot
parent c7b8a188c3
commit b6a15b6111
46 changed files with 1370 additions and 638 deletions

View File

@ -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;

View File

@ -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,

View File

@ -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,

View File

@ -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 *> &params,
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 *> &params,
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 *> &params,
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 *> &params,
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 *> &params,
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));

View File

@ -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 *> &params,
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 *> &params,
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 *> &params,
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,

View File

@ -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;
}

View File

@ -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_;

View File

@ -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));
}

View File

@ -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,

View File

@ -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; }

View File

@ -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 ')'
{

View File

@ -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);

View File

@ -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);

View File

@ -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;

View File

@ -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:
/**

View File

@ -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;

View File

@ -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)

View File

@ -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));

View File

@ -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;

View File

@ -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))) {

View File

@ -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;

View File

@ -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);

View File

@ -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*/ }
}

View File

@ -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(); }

View File

@ -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
{

View File

@ -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); }

View File

@ -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);

View File

@ -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_; }

View File

@ -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) ||

View File

@ -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));
}
}

View File

@ -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));

View File

@ -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);

View File

@ -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));
}

View File

@ -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,

View File

@ -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;

View File

@ -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)
{

View File

@ -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的左右子查询中

View File

@ -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_;

View File

@ -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

View File

@ -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;

View File

@ -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_,

View File

@ -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_))) {

View File

@ -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,

View File

@ -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])

View File

@ -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)

View File

@ -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")