diff --git a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h index cb2a87c529..97ea72a3ab 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h +++ b/deps/oblib/src/lib/mysqlclient/ob_isql_connection.h @@ -178,6 +178,7 @@ public: // session environment virtual int get_session_variable(const ObString &name, int64_t &val) = 0; virtual int set_session_variable(const ObString &name, int64_t val) = 0; + virtual int set_session_variable(const ObString &name, const ObString &val) = 0; virtual int execute(const uint64_t tenant_id, ObIExecutor &executor) { diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.h b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.h index b1e9e075d6..e77502a796 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.h +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_connection.h @@ -98,7 +98,7 @@ public: // session environment virtual int get_session_variable(const ObString &name, int64_t &val) override; virtual int set_session_variable(const ObString &name, int64_t val) override; - int set_session_variable(const ObString &name, const ObString &val); + virtual int set_session_variable(const ObString &name, const ObString &val) override; virtual int ping() override; int set_trace_id(); diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp index abbdd6c8ea..83c33eb45a 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.cpp @@ -222,6 +222,9 @@ int ObCommonSqlProxy::write(const uint64_t tenant_id, const ObString sql, conn->set_force_remote_exec(true); conn->set_nls_formats(param->nls_formats_); } + if (!param->secure_file_priv_.empty()) { + conn->set_session_variable("secure_file_priv", param->secure_file_priv_); + } } if (OB_SUCC(ret) && nullptr != param && nullptr != param->sql_mode_) { // TODO(cangdi): fix get_session_variable not working diff --git a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h index f8fa38d442..3fa78688a2 100644 --- a/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h +++ b/deps/oblib/src/lib/mysqlclient/ob_mysql_proxy.h @@ -105,7 +105,8 @@ struct ObSessionParam final public: ObSessionParam() : sql_mode_(nullptr), tz_info_wrap_(nullptr), ddl_info_(), is_load_data_exec_(false), - use_external_session_(false), consumer_group_id_(0), nls_formats_{}, enable_pl_cache_(true) {} + use_external_session_(false), consumer_group_id_(0), nls_formats_{}, enable_pl_cache_(true), + secure_file_priv_() {} ~ObSessionParam() = default; public: int64_t *sql_mode_; @@ -116,6 +117,7 @@ public: int64_t consumer_group_id_; common::ObString nls_formats_[common::ObNLSFormatEnum::NLS_MAX]; bool enable_pl_cache_; + common::ObString secure_file_priv_; }; // thread safe sql proxy diff --git a/deps/oblib/src/lib/utility/ob_tracepoint_def.h b/deps/oblib/src/lib/utility/ob_tracepoint_def.h index 4f78aed10e..e655fc41ec 100644 --- a/deps/oblib/src/lib/utility/ob_tracepoint_def.h +++ b/deps/oblib/src/lib/utility/ob_tracepoint_def.h @@ -376,7 +376,8 @@ GLOBAL_ERRSIM_POINT_DEF(556, EN_GENERATE_RANDOM_PLAN, "Whether the optimizer gen GLOBAL_ERRSIM_POINT_DEF(557, EN_COALESCE_AGGR_IGNORE_COST, ""); GLOBAL_ERRSIM_POINT_DEF(558, EN_CHECK_REWRITE_ITER_CONVERGE, "Reporting error when rewrite iter nonconvergent"); GLOBAL_ERRSIM_POINT_DEF(559, EN_PRINT_CONSTRAINTS_INFO, "show constraints info when explain query plan"); -GLOBAL_ERRSIM_POINT_DEF(560, EN_PX_RANDOM_SHUFFLE_WITHOUT_STATISTIC_INFORMATION, "Use px random shuffle even statistical information do not exist."); +GLOBAL_ERRSIM_POINT_DEF(560, EN_CBQT_IGNORE_COST, "Whether ignore the cost when do cost based transformation"); +GLOBAL_ERRSIM_POINT_DEF(561, EN_PX_RANDOM_SHUFFLE_WITHOUT_STATISTIC_INFORMATION, "Use px random shuffle even statistical information do not exist."); // 600-700 For PX use GLOBAL_ERRSIM_POINT_DEF(600, EN_PX_SQC_EXECUTE_FAILED, ""); diff --git a/src/observer/ob_inner_sql_connection.cpp b/src/observer/ob_inner_sql_connection.cpp index fa642ec6bd..7b3191b5c8 100644 --- a/src/observer/ob_inner_sql_connection.cpp +++ b/src/observer/ob_inner_sql_connection.cpp @@ -2081,6 +2081,18 @@ int ObInnerSQLConnection::set_session_variable(const ObString &name, int64_t val return ret; } +int ObInnerSQLConnection::set_session_variable(const ObString &name, const ObString &val) +{ + int ret = OB_SUCCESS; + if (!inited_) { + ret = OB_NOT_INIT; + LOG_WARN("not init", K(ret)); + } else if (OB_FAIL(get_session().update_sys_variable(name, val))) { + LOG_WARN("failed to update sys variable", K(ret), K(name), K(val)); + } + return ret; +} + lib::Worker::CompatMode ObInnerSQLConnection::get_compat_mode() const { lib::Worker::CompatMode mode; diff --git a/src/observer/ob_inner_sql_connection.h b/src/observer/ob_inner_sql_connection.h index 6e99bac580..ad6306c504 100644 --- a/src/observer/ob_inner_sql_connection.h +++ b/src/observer/ob_inner_sql_connection.h @@ -178,6 +178,7 @@ public: // session environment virtual int get_session_variable(const ObString &name, int64_t &val) override; virtual int set_session_variable(const ObString &name, int64_t val) override; + virtual int set_session_variable(const ObString &name, const ObString &val) override; inline void set_spi_connection(bool is_spi_conn) { is_spi_conn_ = is_spi_conn; } int set_primary_schema_version(const common::ObIArray &primary_schema_versions); diff --git a/src/observer/virtual_table/ob_all_virtual_proxy_schema.cpp b/src/observer/virtual_table/ob_all_virtual_proxy_schema.cpp index d01f94b1bf..808027d366 100644 --- a/src/observer/virtual_table/ob_all_virtual_proxy_schema.cpp +++ b/src/observer/virtual_table/ob_all_virtual_proxy_schema.cpp @@ -693,7 +693,7 @@ int ObAllVirtualProxySchema::get_view_decoded_schema_( LOG_WARN("create query context failed", KR(ret)); } else { // set # of question marks - resolver_ctx.query_ctx_->question_marks_count_ = static_cast (parse_result.question_mark_ctx_.count_); + resolver_ctx.query_ctx_->set_questionmark_count(static_cast (parse_result.question_mark_ctx_.count_)); } if (OB_SUCC(ret) && OB_NOT_NULL(parse_result.result_tree_) diff --git a/src/observer/virtual_table/ob_table_columns.cpp b/src/observer/virtual_table/ob_table_columns.cpp index efe63da71c..e11bb13136 100644 --- a/src/observer/virtual_table/ob_table_columns.cpp +++ b/src/observer/virtual_table/ob_table_columns.cpp @@ -1223,7 +1223,7 @@ int ObTableColumns::resolve_view_definition( LOG_WARN("create query context failed", K(ret)); } else { // set # of question marks - resolver_ctx.query_ctx_->question_marks_count_ = static_cast (parse_result.question_mark_ctx_.count_); + resolver_ctx.query_ctx_->set_questionmark_count(static_cast (parse_result.question_mark_ctx_.count_)); resolver_ctx.query_ctx_->sql_schema_guard_.set_schema_guard(schema_guard); uint64_t session_id = 0; if (session->get_session_type() != ObSQLSessionInfo::INNER_SESSION) { diff --git a/src/pl/ob_pl_interface_pragma.h b/src/pl/ob_pl_interface_pragma.h index 83c123edf8..9450bffd2c 100644 --- a/src/pl/ob_pl_interface_pragma.h +++ b/src/pl/ob_pl_interface_pragma.h @@ -599,6 +599,10 @@ INTERFACE_DEF(INTERFACE_DBMS_SPM_LOAD_PLANS_FROM_CURSOR_CACHE, "LOAD_PLANS_FROM_CURSOR_CACHE", (ObDBMSSpm::load_plans_from_cursor_cache)) INTERFACE_DEF(INTERFACE_DBMS_SPM_BATCH_LOAD_PLANS_FROM_CURSOR_CACHE, "BATCH_LOAD_PLANS_FROM_CURSOR_CACHE", (ObDBMSSpm::batch_load_plans_from_cursor_cache)) INTERFACE_DEF(INTERFACE_DBMS_SPM_AUTO_PURGE_SQL_PLAN_BASELINE, "AUTO_PURGE_SQL_PLAN_BASELINE", (ObDBMSSpm::auto_purge_sql_plan_baseline)) + INTERFACE_DEF(INTERFACE_DBMS_SPM_UNPACK_STGTAB_BASELINE, "UNPACK_STGTAB_BASELINE", (ObDBMSSpm::unpack_table_baseline)) + INTERFACE_DEF(INTERFACE_DBMS_SPM_PACK_CSV_BASELINE, "PACK_CSV_BASELINE", (ObDBMSSpm::pack_csv_baseline)) + INTERFACE_DEF(INTERFACE_DBMS_SPM_UNPACK_CSV_BASELINE, "UNPACK_CSV_BASELINE", (ObDBMSSpm::unpack_csv_baseline)) + INTERFACE_DEF(INTERFACE_DBMS_SPM_HANDLE_SPM_STATS_JOB_PROC, "HANDLE_SPM_STATS_JOB_PROC", (ObDBMSSpm::handle_spm_stats_job_proc)) // end of dbms_spm #endif diff --git a/src/pl/ob_pl_resolver.cpp b/src/pl/ob_pl_resolver.cpp index fea164da1d..e1d7bb91a6 100644 --- a/src/pl/ob_pl_resolver.cpp +++ b/src/pl/ob_pl_resolver.cpp @@ -2430,8 +2430,7 @@ int ObPLResolver::get_view_select_stmt( OX (resolver_ctx.expr_factory_ = &expr_factory); OX (resolver_ctx.stmt_factory_ = &stmt_factory); CK (OB_NOT_NULL(resolver_ctx.query_ctx_ = stmt_factory.get_query_ctx())); - OX (resolver_ctx.query_ctx_->question_marks_count_ - = static_cast(parse_result.question_mark_ctx_.count_)); + OX (resolver_ctx.query_ctx_->set_questionmark_count(static_cast(parse_result.question_mark_ctx_.count_))); CK (OB_NOT_NULL(select_stmt_node = parse_result.result_tree_->children_[0])); CK (T_SELECT == select_stmt_node->type_); @@ -2521,8 +2520,7 @@ int ObPLResolver::fill_record_type( OX (resolver_ctx.sql_proxy_ = &(ctx.sql_proxy_)); \ CK (OB_NOT_NULL(resolver_ctx.query_ctx_ = stmt_factory.get_query_ctx())); \ OX (resolver_ctx.query_ctx_->sql_schema_guard_.set_schema_guard(&ctx.schema_guard_)); \ - OX (resolver_ctx.query_ctx_->question_marks_count_ \ - = static_cast(parse_result.question_mark_ctx_.count_)); \ + OX (resolver_ctx.query_ctx_->set_questionmark_count(static_cast(parse_result.question_mark_ctx_.count_))); \ OZ (resolver_ctx.schema_checker_->init(resolver_ctx.query_ctx_->sql_schema_guard_, \ ctx.session_info_.get_sessid())); \ CK (OB_NOT_NULL(select_stmt_node = parse_result.result_tree_->children_[0]));\ diff --git a/src/pl/sys_package/ob_dbms_stats.cpp b/src/pl/sys_package/ob_dbms_stats.cpp index a949ee82ea..f3c15a8bf4 100644 --- a/src/pl/sys_package/ob_dbms_stats.cpp +++ b/src/pl/sys_package/ob_dbms_stats.cpp @@ -178,10 +178,10 @@ int ObDbmsStats::gather_schema_stats(ObExecContext &ctx, ParamStore ¶ms, ObO { int ret = OB_SUCCESS; UNUSED(result); - ObTableStatParam global_param; - global_param.allocator_ = &ctx.get_allocator(); ObSEArray table_ids; ObOptStatTaskInfo task_info; + SMART_VAR(ObTableStatParam, global_param){ + global_param.allocator_ = &ctx.get_allocator(); int64_t start_time = ObTimeUtility::current_time(); if (OB_FAIL(check_statistic_table_writeable(ctx))) { LOG_WARN("failed to check tenant is restore", K(ret)); @@ -287,6 +287,7 @@ int ObDbmsStats::gather_schema_stats(ObExecContext &ctx, ParamStore ¶ms, ObO task_info.failed_count_ = ret == OB_SUCCESS ? 0 : table_ids.count() - i + 1; update_optimizer_gather_stat_info(&task_info, NULL); } + } return ret; } @@ -3636,6 +3637,7 @@ int ObDbmsStats::init_column_stat_params(ObIAllocator &allocator, col_param.bucket_num_ = -1; col_param.column_attribute_ = 0; col_param.column_usage_flag_ = 0; + col_param.column_type_ = col->get_data_type(); if (lib::is_oracle_mode() && col->get_meta_type().is_varbinary_or_binary()) { //oracle don't have this type. but agent table will have this type, such as "SYS"."ALL_VIRTUAL_COLUMN_REAL_AGENT" } else { @@ -4442,6 +4444,14 @@ int ObDbmsStats::get_default_stat_options(ObExecContext &ctx, LOG_WARN("failed to push back", K(ret)); } } + if (OB_SUCC(ret) && param.is_auto_gather_ && stat_options & StatOptionFlags::OPT_AUTO_SAMPLE_ROW_COUNT) { + ObAutoSampleRowCountPrefs *tmp_pref = NULL; + if (OB_FAIL(new_stat_prefs(*param.allocator_, ctx.get_my_session(), ObString(), tmp_pref))) { + LOG_WARN("failed to new stat prefs", K(ret)); + } else if (OB_FAIL(stat_prefs.push_back(tmp_pref))) { + LOG_WARN("failed to push back", K(ret)); + } + } if (OB_SUCC(ret)) { if (OB_FAIL(ObDbmsStatsPreferences::get_sys_default_stat_options(ctx, stat_prefs, param))) { LOG_WARN("failed to get sys default stat options", K(ret)); @@ -5982,6 +5992,7 @@ int ObDbmsStats::gather_table_stats_with_default_param(ObExecContext &ctx, stat_param.db_id_ = stat_table.database_id_; stat_param.is_async_gather_ = stat_table.is_async_gather_; stat_param.async_partition_ids_ = &stat_table.async_partition_ids_; + stat_param.is_auto_gather_ = true; bool is_all_fast_gather = false; ObSEArray no_gather_index_ids; ObOptStatGatherStat gather_stat(task_info); @@ -5998,6 +6009,11 @@ int ObDbmsStats::gather_table_stats_with_default_param(ObExecContext &ctx, LOG_WARN("failed to parse owner", K(ret)); } else if (OB_FAIL(use_default_gather_stat_options(ctx, stat_param))) { LOG_WARN("failed to use default gather stat optitions", K(ret)); + } else if (OB_FAIL(determine_auto_sample_table(ctx, stat_param))) { + LOG_WARN("failed to determine auto sample table", K(ret)); + } else if (stat_param.is_auto_sample_size_ && + OB_FAIL(parse_refine_min_max_options(ctx, stat_param))) { + LOG_WARN("failed to parse refine min max options", K(ret)); } else if (!stat_table.is_async_gather_ && OB_FAIL(adjust_auto_gather_stat_option(stat_table.partition_stat_infos_, stat_param))) { LOG_WARN("failed to use default gather stat optitions", K(ret)); @@ -6213,6 +6229,13 @@ int ObDbmsStats::get_new_stat_pref(ObExecContext &ctx, } else { stat_pref = tmp_pref; } + } else if (is_global_prefs && 0 == opt_name.case_compare("AUTO_SAMPLE_ROW_COUNT")) { + ObAutoSampleRowCountPrefs *tmp_pref = NULL; + if (OB_FAIL(new_stat_prefs(allocator, ctx.get_my_session(), opt_value, tmp_pref))) { + LOG_WARN("failed to new stat prefs", K(ret)); + } else { + stat_pref = tmp_pref; + } } else { ret = OB_ERR_DBMS_STATS_PL; LOG_WARN("Invalid input values for pname", K(ret), K(opt_name)); @@ -6222,7 +6245,8 @@ int ObDbmsStats::get_new_stat_pref(ObExecContext &ctx, "STALE_PERCENT | ESTIMATE_BLOCK | ASYNC_GATHER_STALE_RATIO |"\ "ASYNC_GATHER_SAMPLE_SIZE | ASYNC_GATHER_FULL_TABLE_SIZE |"\ "ASYNC_STALE_MAX_TABLE_SIZE | HIST_EST_PERCENT | HIST_BLOCK_SAMPLE |"\ - "APPROXIMATE_NDV(global prefs unique) | ONLINE_ESTIMATE_PERCENT prefs"); + "APPROXIMATE_NDV(global prefs unique) | ONLINE_ESTIMATE_PERCENT prefs |"\ + "AUTO_SAMPLE_ROW_COUNT(global prefs unique) prefs"); } return ret; } @@ -7295,7 +7319,7 @@ int ObDbmsStats::adjust_async_gather_stat_option(ObExecContext &ctx, int ret = OB_SUCCESS; ObSEArray approx_first_part_ids; //If the value of async_full_table_size_ is 0, it means that the table no need to async gather stats. - if (param.async_full_table_size_ == 0) { + if (param.auto_sample_row_cnt_ == 0) { param.subpart_stat_param_.reset_gather_stat(); param.part_stat_param_.reset_gather_stat(); param.global_stat_param_.reset_gather_stat(); @@ -7428,5 +7452,115 @@ int ObDbmsStats::adjust_text_column_basic_stats(ObExecContext &ctx, return ret; } +int ObDbmsStats::parse_refine_min_max_options(ObExecContext &ctx, + ObTableStatParam ¶m) +{ + int ret = OB_SUCCESS; + uint64_t index_tids[OB_MAX_INDEX_PER_TABLE + 2]; + int64_t index_count = OB_MAX_INDEX_PER_TABLE + 1; + share::schema::ObSchemaGetterGuard *schema_guard = ctx.get_virtual_table_ctx().schema_guard_; + const share::schema::ObTableSchema *table_schema = NULL; + ObSEArray refine_columns; + ObSEArray refine_index_names; + uint64_t first_column_id = OB_INVALID_ID; + ObSEArray rowkey_ids; + if (OB_ISNULL(schema_guard) || + OB_ISNULL(ctx.get_my_session()) || + OB_ISNULL(param.allocator_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(schema_guard->get_table_schema(ctx.get_my_session()->get_effective_tenant_id(), + param.table_id_, + table_schema))) { + LOG_WARN("failed to get index schema", K(ret)); + } else if (OB_ISNULL(table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(get_table_index_infos(schema_guard, + ctx.get_my_session()->get_effective_tenant_id(), + param.table_id_, + index_tids, + index_count))) { + LOG_WARN("failed to get table index infos", K(ret)); + } else { + index_tids[index_count++] = param.table_id_; + for (int64_t i = 0; OB_SUCC(ret) && i < index_count; ++i) { + const share::schema::ObTableSchema *index_schema = NULL; + ObString index_name; + rowkey_ids.reuse(); + if (OB_FAIL(schema_guard->get_table_schema(ctx.get_my_session()->get_effective_tenant_id(), + index_tids[i], + index_schema))) { + LOG_WARN("failed to get index schema", K(ret)); + } else if (OB_ISNULL(index_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(index_schema->get_rowkey_column_ids(rowkey_ids))) { + LOG_WARN("failed to get rowkey column ids", K(ret)); + } else if (rowkey_ids.empty()) { + // do nothing + } else if (OB_FALSE_IT(first_column_id = rowkey_ids.at(0))) { + } else if (index_schema->is_global_index_table() && + table_schema->get_part_level() != ObPartitionLevel::PARTITION_LEVEL_ONE) { + // do nothing + } else if (ObOptimizerUtil::find_item(refine_columns, first_column_id)) { + // do nothing + } else if (index_tids[i] != param.table_id_ && + OB_FAIL(index_schema->get_index_name(index_name))) { + LOG_WARN("failed to get index name", K(ret)); + } else if (OB_FAIL(refine_columns.push_back(first_column_id))) { + LOG_WARN("failed to push back array", K(ret)); + } else if (OB_FAIL(refine_index_names.push_back(index_name))) { + LOG_WARN("failed to push back array", K(ret)); + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < param.column_params_.count(); ++i) { + int64_t index = -1; + if (!param.column_params_.at(i).need_basic_stat()) { + // do nothing + } else if (!ObOptimizerUtil::find_item(refine_columns, + param.column_params_.at(i).column_id_, + &index)) { + // do nothing + } else if (OB_FAIL(ob_write_string(*param.allocator_, + refine_index_names.at(index), + param.column_params_.at(i).index_name_))) { + LOG_WARN("failed to write string", K(ret)); + } else { + param.column_params_.at(i).set_need_refine_min_max(); + param.need_refine_min_max_ = true; + } + } + } + return ret; +} + +int ObDbmsStats::determine_auto_sample_table(ObExecContext &ctx, + ObTableStatParam ¶m) +{ + int ret = OB_SUCCESS; + share::schema::ObSchemaGetterGuard *schema_guard = ctx.get_virtual_table_ctx().schema_guard_; + const share::schema::ObTableSchema *table_schema = NULL; + if (param.auto_sample_row_cnt_ == 0) { + param.is_auto_sample_size_ = false; + } else if (!param.is_auto_sample_size_) { + // do nothing + } else if (OB_ISNULL(schema_guard) || + OB_ISNULL(ctx.get_my_session())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(schema_guard->get_table_schema(ctx.get_my_session()->get_effective_tenant_id(), + param.table_id_, + table_schema))) { + LOG_WARN("failed to get index schema", K(ret)); + } else if (OB_ISNULL(table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else { + param.is_auto_sample_size_ = !table_schema->is_vir_table(); + } + return ret; +} + } } diff --git a/src/pl/sys_package/ob_dbms_stats.h b/src/pl/sys_package/ob_dbms_stats.h index 0a6f64e398..b81f9eb673 100644 --- a/src/pl/sys_package/ob_dbms_stats.h +++ b/src/pl/sys_package/ob_dbms_stats.h @@ -545,6 +545,13 @@ public: static void update_optimizer_gather_stat_info(const ObOptStatTaskInfo *task_info, const ObOptStatGatherStat *gather_stat); + static int convert_vaild_ident_name(common::ObIAllocator &allocator, + const common::ObDataTypeCastParams &dtc_params, + ObString &ident_name, + bool need_extra_conv = false); + static int parse_refine_min_max_options(ObExecContext &ctx, + ObTableStatParam ¶m); + private: static int check_statistic_table_writeable(sql::ObExecContext &ctx); @@ -568,12 +575,6 @@ private: bool is_global_prefs, ObStatPrefs *&stat_pref); - static int convert_vaild_ident_name(common::ObIAllocator &allocator, - const common::ObDataTypeCastParams &dtc_params, - ObString &ident_name, - bool need_extra_conv = false); - - static int get_common_table_stale_percent(sql::ObExecContext &ctx, const uint64_t tenant_id, const share::schema::ObTableSchema &table_schema, @@ -667,6 +668,9 @@ private: const share::schema::ObTableSchema &schema, ObTableStatParam ¶m); + static int determine_auto_sample_table(ObExecContext &ctx, + ObTableStatParam ¶m); + }; } diff --git a/src/share/CMakeLists.txt b/src/share/CMakeLists.txt index fe8a3005b6..bcfe654ef1 100644 --- a/src/share/CMakeLists.txt +++ b/src/share/CMakeLists.txt @@ -548,6 +548,7 @@ ob_set_subtarget(ob_share stat stat/ob_dbms_stats_gather.cpp stat/ob_opt_system_stat.cpp stat/ob_opt_system_stat_cache.cpp + stat/ob_min_max_estimator.cpp ) ob_set_subtarget(ob_share external_table diff --git a/src/share/config/ob_config_helper.cpp b/src/share/config/ob_config_helper.cpp index 2e2bc0af60..1ef200edb8 100644 --- a/src/share/config/ob_config_helper.cpp +++ b/src/share/config/ob_config_helper.cpp @@ -1151,6 +1151,14 @@ int64_t ObSqlPlanManagementModeChecker::get_spm_mode_by_string(const common::ObS spm_mode = 0; } else if (0 == string.case_compare("OnlineEvolve")) { spm_mode = 1; + } else if (0 == string.case_compare("BaselineFirst")) { + uint64_t cluster_version = GET_MIN_CLUSTER_VERSION(); + if (cluster_version >= CLUSTER_VERSION_4_3_5_0 || + (cluster_version >= MOCK_CLUSTER_VERSION_4_2_5_0 && cluster_version < CLUSTER_VERSION_4_3_0_0)) { + spm_mode = 2; + } else { + spm_mode = -1; + } } return spm_mode; } diff --git a/src/share/inner_table/ob_inner_table_schema.12451_12500.cpp b/src/share/inner_table/ob_inner_table_schema.12451_12500.cpp index 15c66c2381..d777841cf8 100644 --- a/src/share/inner_table/ob_inner_table_schema.12451_12500.cpp +++ b/src/share/inner_table/ob_inner_table_schema.12451_12500.cpp @@ -8138,6 +8138,279 @@ int ObInnerTableSchema::all_virtual_kv_group_commit_status_schema(ObTableSchema return ret; } +int ObInnerTableSchema::all_virtual_spm_evo_result_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_SYS_DATABASE_ID); + table_schema.set_table_id(OB_ALL_VIRTUAL_SPM_EVO_RESULT_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(4); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(VIRTUAL_TABLE); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_ALL_VIRTUAL_SPM_EVO_RESULT_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("tenant_id", //column_name + ++column_id, //column_id + 1, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA_TS("record_time", //column_name + ++column_id, //column_id + 2, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTimestampType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(ObPreciseDateTime), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false, //is_autoincrement + false); //is_on_update_for_timestamp + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("svr_ip", //column_name + ++column_id, //column_id + 3, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + MAX_IP_ADDR_LENGTH, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("svr_port", //column_name + ++column_id, //column_id + 4, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("database_id", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("sql_id", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + OB_MAX_SQL_ID_LENGTH, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("type", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA_TS("start_time", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTimestampType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(ObPreciseDateTime), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false, //is_autoincrement + false); //is_on_update_for_timestamp + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA_TS("end_time", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTimestampType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(ObPreciseDateTime), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false, //is_autoincrement + false); //is_on_update_for_timestamp + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("status", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + 7, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("new_plan_better", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTinyIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + 1, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("evo_plan_exec_count", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("evo_plan_cpu_time", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("baseline_exec_count", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("baseline_cpu_time", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + table_schema.set_micro_index_clustered(false); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + int ObInnerTableSchema::all_virtual_vector_index_info_schema(ObTableSchema &table_schema) { int ret = OB_SUCCESS; diff --git a/src/share/inner_table/ob_inner_table_schema.15451_15500.cpp b/src/share/inner_table/ob_inner_table_schema.15451_15500.cpp index 3a61a90763..7ed1cf7ad7 100644 --- a/src/share/inner_table/ob_inner_table_schema.15451_15500.cpp +++ b/src/share/inner_table/ob_inner_table_schema.15451_15500.cpp @@ -2515,6 +2515,276 @@ int ObInnerTableSchema::all_virtual_ss_local_cache_info_ora_schema(ObTableSchema return ret; } +int ObInnerTableSchema::all_virtual_spm_evo_result_ora_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_ORA_SYS_DATABASE_ID); + table_schema.set_table_id(OB_ALL_VIRTUAL_SPM_EVO_RESULT_ORA_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(4); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(VIRTUAL_TABLE); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_ALL_VIRTUAL_SPM_EVO_RESULT_ORA_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCollationType::CS_TYPE_UTF8MB4_BIN); + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("TENANT_ID", //column_name + ++column_id, //column_id + 1, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObNumberType, //column_type + CS_TYPE_INVALID, //column_collation_type + 38, //column_length + 38, //column_precision + 0, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("RECORD_TIME", //column_name + ++column_id, //column_id + 2, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTimestampLTZType, //column_type + CS_TYPE_INVALID, //column_collation_type + 0, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("SVR_IP", //column_name + ++column_id, //column_id + 3, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_UTF8MB4_BIN, //column_collation_type + MAX_IP_ADDR_LENGTH, //column_length + 2, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("SVR_PORT", //column_name + ++column_id, //column_id + 4, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObNumberType, //column_type + CS_TYPE_INVALID, //column_collation_type + 38, //column_length + 38, //column_precision + 0, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("DATABASE_ID", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObNumberType, //column_type + CS_TYPE_INVALID, //column_collation_type + 38, //column_length + 38, //column_precision + 0, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("SQL_ID", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_UTF8MB4_BIN, //column_collation_type + OB_MAX_SQL_ID_LENGTH, //column_length + 2, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("TYPE", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObNumberType, //column_type + CS_TYPE_INVALID, //column_collation_type + 38, //column_length + 38, //column_precision + 0, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("START_TIME", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTimestampLTZType, //column_type + CS_TYPE_INVALID, //column_collation_type + 0, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("END_TIME", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTimestampLTZType, //column_type + CS_TYPE_INVALID, //column_collation_type + 0, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("STATUS", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_UTF8MB4_BIN, //column_collation_type + 7, //column_length + 2, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("NEW_PLAN_BETTER", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObNumberType, //column_type + CS_TYPE_INVALID, //column_collation_type + 38, //column_length + 38, //column_precision + 0, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("EVO_PLAN_EXEC_COUNT", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObNumberType, //column_type + CS_TYPE_INVALID, //column_collation_type + 38, //column_length + 38, //column_precision + 0, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("EVO_PLAN_CPU_TIME", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObNumberType, //column_type + CS_TYPE_INVALID, //column_collation_type + 38, //column_length + 38, //column_precision + 0, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("BASELINE_EXEC_COUNT", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObNumberType, //column_type + CS_TYPE_INVALID, //column_collation_type + 38, //column_length + 38, //column_precision + 0, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("BASELINE_CPU_TIME", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObNumberType, //column_type + CS_TYPE_INVALID, //column_collation_type + 38, //column_length + 38, //column_precision + 0, //column_scale + true, //is_nullable + false); //is_autoincrement + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + table_schema.set_micro_index_clustered(false); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + int ObInnerTableSchema::all_virtual_vector_index_info_ora_schema(ObTableSchema &table_schema) { int ret = OB_SUCCESS; diff --git a/src/share/inner_table/ob_inner_table_schema.21251_21300.cpp b/src/share/inner_table/ob_inner_table_schema.21251_21300.cpp index ac4f55b092..0042e07ab8 100644 --- a/src/share/inner_table/ob_inner_table_schema.21251_21300.cpp +++ b/src/share/inner_table/ob_inner_table_schema.21251_21300.cpp @@ -111,7 +111,7 @@ int ObInnerTableSchema::dba_tab_statistics_schema(ObTableSchema &table_schema) table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); if (OB_SUCC(ret)) { - if (OB_FAIL(table_schema.set_view_definition(R"__(SELECT CAST(DB.DATABASE_NAME AS CHAR(128)) AS OWNER, CAST(V.TABLE_NAME AS CHAR(128)) AS TABLE_NAME, CAST(V.PARTITION_NAME AS CHAR(128)) AS PARTITION_NAME, CAST(V.PARTITION_POSITION AS NUMBER) AS PARTITION_POSITION, CAST(V.SUBPARTITION_NAME AS CHAR(128)) AS SUBPARTITION_NAME, CAST(V.SUBPARTITION_POSITION AS NUMBER) AS SUBPARTITION_POSITION, CAST(V.OBJECT_TYPE AS CHAR(12)) AS OBJECT_TYPE, CAST(STAT.ROW_CNT AS NUMBER) AS NUM_ROWS, CAST(NULL AS NUMBER) AS BLOCKS, CAST(NULL AS NUMBER) AS EMPTY_BLOCKS, CAST(NULL AS NUMBER) AS AVG_SPACE, CAST(NULL AS NUMBER) AS CHAIN_CNT, CAST(STAT.AVG_ROW_LEN AS NUMBER) AS AVG_ROW_LEN, CAST(NULL AS NUMBER) AS AVG_SPACE_FREELIST_BLOCKS, CAST(NULL AS NUMBER) AS NUM_FREELIST_BLOCKS, CAST(NULL AS NUMBER) AS AVG_CACHED_BLOCKS, CAST(NULL AS NUMBER) AS AVG_CACHE_HIT_RATIO, CAST(NULL AS NUMBER) AS IM_IMCU_COUNT, CAST(NULL AS NUMBER) AS IM_BLOCK_COUNT, CAST(NULL AS DATETIME) AS IM_STAT_UPDATE_TIME, CAST(NULL AS NUMBER) AS SCAN_RATE, CAST(STAT.SPARE1 AS NUMBER) AS SAMPLE_SIZE, CAST(STAT.LAST_ANALYZED AS DATETIME(6)) AS LAST_ANALYZED, CAST((CASE STAT.GLOBAL_STATS WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' ELSE NULL END) AS CHAR(3)) AS GLOBAL_STATS, CAST((CASE STAT.USER_STATS WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' ELSE NULL END) AS CHAR(3)) AS USER_STATS, CAST((CASE WHEN STAT.STATTYPE_LOCKED & 15 IS NULL THEN NULL ELSE (CASE STAT.STATTYPE_LOCKED & 15 WHEN 0 THEN NULL WHEN 1 THEN 'DATA' WHEN 2 THEN 'CACHE' ELSE 'ALL' END) END) AS CHAR(5)) AS STATTYPE_LOCKED, CAST((CASE STAT.STALE_STATS WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' ELSE NULL END) AS CHAR(3)) AS STALE_STATS, CAST(NULL AS CHAR(7)) AS SCOPE FROM ( (SELECT CAST(0 AS SIGNED) AS TENANT_ID, DATABASE_ID, TABLE_ID, -2 AS PARTITION_ID, TABLE_NAME, NULL AS PARTITION_NAME, NULL AS SUBPARTITION_NAME, NULL AS PARTITION_POSITION, NULL AS SUBPARTITION_POSITION, 'TABLE' AS OBJECT_TYPE FROM OCEANBASE.__ALL_VIRTUAL_CORE_ALL_TABLE WHERE TENANT_ID = EFFECTIVE_TENANT_ID() AND TABLE_TYPE IN (0,2,3,6,14,15) UNION ALL SELECT TENANT_ID, DATABASE_ID, TABLE_ID, CASE WHEN PART_LEVEL = 0 THEN -2 ELSE -1 END AS PARTITION_ID, TABLE_NAME, NULL AS PARTITION_NAME, NULL AS SUBPARTITION_NAME, NULL AS PARTITION_POSITION, NULL AS SUBPARTITION_POSITION, 'TABLE' AS OBJECT_TYPE FROM oceanbase.__all_table T WHERE T.TABLE_TYPE IN (0,2,3,6,14,15) AND T.TABLE_MODE >> 12 & 15 in (0,1)) UNION ALL SELECT T.TENANT_ID, T.DATABASE_ID, T.TABLE_ID, P.PART_ID, T.TABLE_NAME, P.PART_NAME, NULL, P.PART_IDX + 1, NULL, 'PARTITION' FROM oceanbase.__all_table T JOIN oceanbase.__all_part P ON T.TENANT_ID = P.TENANT_ID AND T.TABLE_ID = P.TABLE_ID WHERE T.TABLE_TYPE IN (0,2,3,6,14,15) AND T.TABLE_MODE >> 12 & 15 in (0,1) AND (P.PARTITION_TYPE = 0 OR P.PARTITION_TYPE IS NULL) UNION ALL SELECT T.TENANT_ID, T.DATABASE_ID, T.TABLE_ID, SP.SUB_PART_ID AS PARTITION_ID, T.TABLE_NAME, P.PART_NAME, SP.SUB_PART_NAME, P.PART_IDX + 1, SP.SUB_PART_IDX + 1, 'SUBPARTITION' FROM oceanbase.__all_table T JOIN oceanbase.__all_part P ON T.TENANT_ID = P.TENANT_ID AND T.TABLE_ID = P.TABLE_ID JOIN oceanbase.__all_sub_part SP ON T.TENANT_ID = SP.TENANT_ID AND T.TABLE_ID = SP.TABLE_ID AND P.PART_ID = SP.PART_ID WHERE T.TABLE_TYPE IN (0,2,3,6,14,15) AND T.TABLE_MODE >> 12 & 15 in (0,1) AND (P.PARTITION_TYPE = 0 OR P.PARTITION_TYPE IS NULL) AND (SP.PARTITION_TYPE = 0 OR SP.PARTITION_TYPE IS NULL) ) V JOIN oceanbase.__all_database DB ON DB.TENANT_ID = V.TENANT_ID AND DB.DATABASE_ID = V.DATABASE_ID AND V.TENANT_ID = 0 LEFT JOIN oceanbase.__all_table_stat STAT ON V.TENANT_ID = STAT.TENANT_ID AND V.TABLE_ID = STAT.TABLE_ID AND (V.PARTITION_ID = STAT.PARTITION_ID OR V.PARTITION_ID = -2) AND STAT.INDEX_TYPE = 0 )__"))) { + if (OB_FAIL(table_schema.set_view_definition(R"__(SELECT CAST(DB.DATABASE_NAME AS CHAR(128)) AS OWNER, CAST(V.TABLE_NAME AS CHAR(128)) AS TABLE_NAME, CAST(V.PARTITION_NAME AS CHAR(128)) AS PARTITION_NAME, CAST(V.PARTITION_POSITION AS NUMBER) AS PARTITION_POSITION, CAST(V.SUBPARTITION_NAME AS CHAR(128)) AS SUBPARTITION_NAME, CAST(V.SUBPARTITION_POSITION AS NUMBER) AS SUBPARTITION_POSITION, CAST(V.OBJECT_TYPE AS CHAR(12)) AS OBJECT_TYPE, CAST(STAT.ROW_CNT AS NUMBER) AS NUM_ROWS, CAST(NULL AS NUMBER) AS BLOCKS, CAST(NULL AS NUMBER) AS EMPTY_BLOCKS, CAST(NULL AS NUMBER) AS AVG_SPACE, CAST(NULL AS NUMBER) AS CHAIN_CNT, CAST(STAT.AVG_ROW_LEN AS NUMBER) AS AVG_ROW_LEN, CAST(NULL AS NUMBER) AS AVG_SPACE_FREELIST_BLOCKS, CAST(NULL AS NUMBER) AS NUM_FREELIST_BLOCKS, CAST(NULL AS NUMBER) AS AVG_CACHED_BLOCKS, CAST(NULL AS NUMBER) AS AVG_CACHE_HIT_RATIO, CAST(NULL AS NUMBER) AS IM_IMCU_COUNT, CAST(NULL AS NUMBER) AS IM_BLOCK_COUNT, CAST(NULL AS DATETIME) AS IM_STAT_UPDATE_TIME, CAST(NULL AS NUMBER) AS SCAN_RATE, CAST(STAT.SPARE1 AS DECIMAL(20, 0)) AS SAMPLE_SIZE, CAST(STAT.LAST_ANALYZED AS DATETIME(6)) AS LAST_ANALYZED, CAST((CASE STAT.GLOBAL_STATS WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' ELSE NULL END) AS CHAR(3)) AS GLOBAL_STATS, CAST((CASE STAT.USER_STATS WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' ELSE NULL END) AS CHAR(3)) AS USER_STATS, CAST((CASE WHEN STAT.STATTYPE_LOCKED & 15 IS NULL THEN NULL ELSE (CASE STAT.STATTYPE_LOCKED & 15 WHEN 0 THEN NULL WHEN 1 THEN 'DATA' WHEN 2 THEN 'CACHE' ELSE 'ALL' END) END) AS CHAR(5)) AS STATTYPE_LOCKED, CAST((CASE STAT.STALE_STATS WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' ELSE NULL END) AS CHAR(3)) AS STALE_STATS, CAST(NULL AS CHAR(7)) AS SCOPE FROM ( (SELECT CAST(0 AS SIGNED) AS TENANT_ID, DATABASE_ID, TABLE_ID, -2 AS PARTITION_ID, TABLE_NAME, NULL AS PARTITION_NAME, NULL AS SUBPARTITION_NAME, NULL AS PARTITION_POSITION, NULL AS SUBPARTITION_POSITION, 'TABLE' AS OBJECT_TYPE FROM OCEANBASE.__ALL_VIRTUAL_CORE_ALL_TABLE WHERE TENANT_ID = EFFECTIVE_TENANT_ID() AND TABLE_TYPE IN (0,2,3,6,14,15) UNION ALL SELECT TENANT_ID, DATABASE_ID, TABLE_ID, CASE WHEN PART_LEVEL = 0 THEN -2 ELSE -1 END AS PARTITION_ID, TABLE_NAME, NULL AS PARTITION_NAME, NULL AS SUBPARTITION_NAME, NULL AS PARTITION_POSITION, NULL AS SUBPARTITION_POSITION, 'TABLE' AS OBJECT_TYPE FROM oceanbase.__all_table T WHERE T.TABLE_TYPE IN (0,2,3,6,14,15) AND T.TABLE_MODE >> 12 & 15 in (0,1)) UNION ALL SELECT T.TENANT_ID, T.DATABASE_ID, T.TABLE_ID, P.PART_ID, T.TABLE_NAME, P.PART_NAME, NULL, P.PART_IDX + 1, NULL, 'PARTITION' FROM oceanbase.__all_table T JOIN oceanbase.__all_part P ON T.TENANT_ID = P.TENANT_ID AND T.TABLE_ID = P.TABLE_ID WHERE T.TABLE_TYPE IN (0,2,3,6,14,15) AND T.TABLE_MODE >> 12 & 15 in (0,1) AND (P.PARTITION_TYPE = 0 OR P.PARTITION_TYPE IS NULL) UNION ALL SELECT T.TENANT_ID, T.DATABASE_ID, T.TABLE_ID, SP.SUB_PART_ID AS PARTITION_ID, T.TABLE_NAME, P.PART_NAME, SP.SUB_PART_NAME, P.PART_IDX + 1, SP.SUB_PART_IDX + 1, 'SUBPARTITION' FROM oceanbase.__all_table T JOIN oceanbase.__all_part P ON T.TENANT_ID = P.TENANT_ID AND T.TABLE_ID = P.TABLE_ID JOIN oceanbase.__all_sub_part SP ON T.TENANT_ID = SP.TENANT_ID AND T.TABLE_ID = SP.TABLE_ID AND P.PART_ID = SP.PART_ID WHERE T.TABLE_TYPE IN (0,2,3,6,14,15) AND T.TABLE_MODE >> 12 & 15 in (0,1) AND (P.PARTITION_TYPE = 0 OR P.PARTITION_TYPE IS NULL) AND (SP.PARTITION_TYPE = 0 OR SP.PARTITION_TYPE IS NULL) ) V JOIN oceanbase.__all_database DB ON DB.TENANT_ID = V.TENANT_ID AND DB.DATABASE_ID = V.DATABASE_ID AND V.TENANT_ID = 0 LEFT JOIN oceanbase.__all_table_stat STAT ON V.TENANT_ID = STAT.TENANT_ID AND V.TABLE_ID = STAT.TABLE_ID AND (V.PARTITION_ID = STAT.PARTITION_ID OR V.PARTITION_ID = -2) AND STAT.INDEX_TYPE = 0 )__"))) { LOG_ERROR("fail to set view_definition", K(ret)); } } diff --git a/src/share/inner_table/ob_inner_table_schema.21601_21650.cpp b/src/share/inner_table/ob_inner_table_schema.21601_21650.cpp index 8d447c66af..7d38ae8ecc 100644 --- a/src/share/inner_table/ob_inner_table_schema.21601_21650.cpp +++ b/src/share/inner_table/ob_inner_table_schema.21601_21650.cpp @@ -433,6 +433,108 @@ int ObInnerTableSchema::v_ob_kv_client_info_schema(ObTableSchema &table_schema) return ret; } +int ObInnerTableSchema::dba_ob_spm_evo_result_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_SYS_DATABASE_ID); + table_schema.set_table_id(OB_DBA_OB_SPM_EVO_RESULT_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(0); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(SYSTEM_VIEW); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_DBA_OB_SPM_EVO_RESULT_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT D.DATABASE_NAME AS OWNER, RECORD_TIME, SVR_IP, SVR_PORT, SQL_ID, CAST(CASE WHEN TYPE = 0 THEN 'OnlineEvolve' WHEN TYPE = 1 THEN 'FirstBaseline' WHEN TYPE = 2 THEN 'UnReproducible' WHEN TYPE = 3 THEN 'BaselineFirst' ELSE NULL END AS CHAR(32)) AS TYPE, START_TIME, END_TIME, STATUS, NEW_PLAN_BETTER, EVO_PLAN_EXEC_COUNT, EVO_PLAN_CPU_TIME, BASELINE_EXEC_COUNT, BASELINE_CPU_TIME FROM OCEANBASE.__ALL_VIRTUAL_SPM_EVO_RESULT R, OCEANBASE.__ALL_DATABASE D WHERE R.TENANT_ID = EFFECTIVE_TENANT_ID() AND D.TENANT_ID = 0 AND R.DATABASE_ID = D.DATABASE_ID )__"))) { + LOG_ERROR("fail to set view_definition", K(ret)); + } + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + table_schema.set_micro_index_clustered(false); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + +int ObInnerTableSchema::cdb_ob_spm_evo_result_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_SYS_DATABASE_ID); + table_schema.set_table_id(OB_CDB_OB_SPM_EVO_RESULT_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(0); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(SYSTEM_VIEW); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_CDB_OB_SPM_EVO_RESULT_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT R.TENANT_ID, D.DATABASE_NAME AS OWNER, RECORD_TIME, SVR_IP, SVR_PORT, SQL_ID, CAST(CASE WHEN TYPE = 0 THEN 'OnlineEvolve' WHEN TYPE = 1 THEN 'FirstBaseline' WHEN TYPE = 2 THEN 'UnReproducible' WHEN TYPE = 3 THEN 'BaselineFirst' ELSE NULL END AS CHAR(32)) AS TYPE, START_TIME, END_TIME, STATUS, NEW_PLAN_BETTER, EVO_PLAN_EXEC_COUNT, EVO_PLAN_CPU_TIME, BASELINE_EXEC_COUNT, BASELINE_CPU_TIME FROM OCEANBASE.__ALL_VIRTUAL_SPM_EVO_RESULT R, OCEANBASE.__ALL_VIRTUAL_DATABASE D WHERE R.TENANT_ID = D.TENANT_ID AND R.DATABASE_ID = D.DATABASE_ID )__"))) { + LOG_ERROR("fail to set view_definition", K(ret)); + } + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + table_schema.set_micro_index_clustered(false); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + int ObInnerTableSchema::gv_ob_function_io_stat_schema(ObTableSchema &table_schema) { int ret = OB_SUCCESS; diff --git a/src/share/inner_table/ob_inner_table_schema.28251_28300.cpp b/src/share/inner_table/ob_inner_table_schema.28251_28300.cpp index b11d58b44b..2561115b50 100644 --- a/src/share/inner_table/ob_inner_table_schema.28251_28300.cpp +++ b/src/share/inner_table/ob_inner_table_schema.28251_28300.cpp @@ -25,6 +25,57 @@ using namespace common; namespace share { +int ObInnerTableSchema::dba_ob_spm_evo_result_ora_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_INVALID_ID); + table_schema.set_database_id(OB_ORA_SYS_DATABASE_ID); + table_schema.set_table_id(OB_DBA_OB_SPM_EVO_RESULT_ORA_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(0); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(SYSTEM_VIEW); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_DBA_OB_SPM_EVO_RESULT_ORA_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_view_definition(R"__( SELECT D.DATABASE_NAME AS OWNER, RECORD_TIME, SVR_IP, SVR_PORT, SQL_ID, CAST(CASE WHEN TYPE = 0 THEN 'OnlineEvolve' WHEN TYPE = 1 THEN 'FirstBaseline' WHEN TYPE = 2 THEN 'UnReproducible' WHEN TYPE = 3 THEN 'BaselineFirst' ELSE NULL END AS VARCHAR(32)) AS TYPE, START_TIME, END_TIME, STATUS, NEW_PLAN_BETTER, EVO_PLAN_EXEC_COUNT, EVO_PLAN_CPU_TIME, BASELINE_EXEC_COUNT, BASELINE_CPU_TIME FROM SYS.ALL_VIRTUAL_SPM_EVO_RESULT R, SYS.ALL_VIRTUAL_DATABASE_REAL_AGENT D WHERE R.TENANT_ID = EFFECTIVE_TENANT_ID() AND D.TENANT_ID = EFFECTIVE_TENANT_ID() AND R.DATABASE_ID = D.DATABASE_ID )__"))) { + LOG_ERROR("fail to set view_definition", K(ret)); + } + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(0); + table_schema.set_micro_index_clustered(false); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + int ObInnerTableSchema::gv_ob_function_io_stat_ora_schema(ObTableSchema &table_schema) { int ret = OB_SUCCESS; diff --git a/src/share/inner_table/ob_inner_table_schema.501_550.cpp b/src/share/inner_table/ob_inner_table_schema.501_550.cpp index f84a9eb994..4b3be46531 100644 --- a/src/share/inner_table/ob_inner_table_schema.501_550.cpp +++ b/src/share/inner_table/ob_inner_table_schema.501_550.cpp @@ -3795,6 +3795,281 @@ int ObInnerTableSchema::all_scheduler_job_run_detail_v2_schema(ObTableSchema &ta return ret; } +int ObInnerTableSchema::all_spm_evo_result_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_SYS_TABLEGROUP_ID); + table_schema.set_database_id(OB_SYS_DATABASE_ID); + table_schema.set_table_id(OB_ALL_SPM_EVO_RESULT_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(4); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(SYSTEM_TABLE); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_ALL_SPM_EVO_RESULT_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("tenant_id", //column_name + ++column_id, //column_id + 1, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA_TS("record_time", //column_name + ++column_id, //column_id + 2, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTimestampType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(ObPreciseDateTime), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false, //is_autoincrement + false); //is_on_update_for_timestamp + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("svr_ip", //column_name + ++column_id, //column_id + 3, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + MAX_IP_ADDR_LENGTH, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("svr_port", //column_name + ++column_id, //column_id + 4, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("database_id", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("sql_id", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + OB_MAX_SQL_ID_LENGTH, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("type", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA_TS("start_time", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTimestampType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(ObPreciseDateTime), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false, //is_autoincrement + false); //is_on_update_for_timestamp + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA_TS("end_time", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTimestampType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(ObPreciseDateTime), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false, //is_autoincrement + false); //is_on_update_for_timestamp + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("status", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_INVALID, //column_collation_type + 7, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("new_plan_better", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObTinyIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + 1, //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("evo_plan_exec_count", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("evo_plan_cpu_time", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("baseline_exec_count", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("baseline_cpu_time", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObIntType, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(int64_t), //column_length + -1, //column_precision + -1, //column_scale + true, //is_nullable + false); //is_autoincrement + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(OB_ALL_SPM_EVO_RESULT_TID); + table_schema.set_micro_index_clustered(false); + table_schema.set_aux_lob_meta_tid(OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TID); + table_schema.set_aux_lob_piece_tid(OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TID); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + int ObInnerTableSchema::all_ncomp_dll_v2_schema(ObTableSchema &table_schema) { int ret = OB_SUCCESS; diff --git a/src/share/inner_table/ob_inner_table_schema.50501_50550.cpp b/src/share/inner_table/ob_inner_table_schema.50501_50550.cpp index dd05cba5f9..38acc2d4d4 100644 --- a/src/share/inner_table/ob_inner_table_schema.50501_50550.cpp +++ b/src/share/inner_table/ob_inner_table_schema.50501_50550.cpp @@ -2337,6 +2337,142 @@ int ObInnerTableSchema::all_scheduler_job_run_detail_v2_aux_lob_meta_schema(ObTa return ret; } +int ObInnerTableSchema::all_spm_evo_result_aux_lob_meta_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_SYS_TABLEGROUP_ID); + table_schema.set_database_id(OB_SYS_DATABASE_ID); + table_schema.set_table_id(OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(2); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(AUX_LOB_META); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("lob_id", //column_name + ++column_id, //column_id + 1, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_BINARY, //column_collation_type + 16, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("seq_id", //column_name + ++column_id, //column_id + 2, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_BINARY, //column_collation_type + 8192, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("binary_len", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObUInt32Type, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(uint32_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("char_len", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObUInt32Type, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(uint32_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("piece_id", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObUInt64Type, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(uint64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("lob_data", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_BINARY, //column_collation_type + 262144, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TID); + table_schema.set_micro_index_clustered(false); + table_schema.set_data_table_id(OB_ALL_SPM_EVO_RESULT_TID); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + int ObInnerTableSchema::all_ncomp_dll_v2_aux_lob_meta_schema(ObTableSchema &table_schema) { int ret = OB_SUCCESS; diff --git a/src/share/inner_table/ob_inner_table_schema.60501_60550.cpp b/src/share/inner_table/ob_inner_table_schema.60501_60550.cpp index 7f283dd6f1..4a46ee4e20 100644 --- a/src/share/inner_table/ob_inner_table_schema.60501_60550.cpp +++ b/src/share/inner_table/ob_inner_table_schema.60501_60550.cpp @@ -1572,6 +1572,97 @@ int ObInnerTableSchema::all_scheduler_job_run_detail_v2_aux_lob_piece_schema(ObT return ret; } +int ObInnerTableSchema::all_spm_evo_result_aux_lob_piece_schema(ObTableSchema &table_schema) +{ + int ret = OB_SUCCESS; + uint64_t column_id = OB_APP_MIN_COLUMN_ID - 1; + + //generated fields: + table_schema.set_tenant_id(OB_SYS_TENANT_ID); + table_schema.set_tablegroup_id(OB_SYS_TABLEGROUP_ID); + table_schema.set_database_id(OB_SYS_DATABASE_ID); + table_schema.set_table_id(OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TID); + table_schema.set_rowkey_split_pos(0); + table_schema.set_is_use_bloomfilter(false); + table_schema.set_progressive_merge_num(0); + table_schema.set_rowkey_column_num(1); + table_schema.set_load_type(TABLE_LOAD_TYPE_IN_DISK); + table_schema.set_table_type(AUX_LOB_PIECE); + table_schema.set_index_type(INDEX_TYPE_IS_NOT); + table_schema.set_def_type(TABLE_DEF_TYPE_INTERNAL); + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_table_name(OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TNAME))) { + LOG_ERROR("fail to set table_name", K(ret)); + } + } + + if (OB_SUCC(ret)) { + if (OB_FAIL(table_schema.set_compress_func_name(OB_DEFAULT_COMPRESS_FUNC_NAME))) { + LOG_ERROR("fail to set compress_func_name", K(ret)); + } + } + table_schema.set_part_level(PARTITION_LEVEL_ZERO); + table_schema.set_charset_type(ObCharset::get_default_charset()); + table_schema.set_collation_type(ObCharset::get_default_collation(ObCharset::get_default_charset())); + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("piece_id", //column_name + ++column_id, //column_id + 1, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObUInt64Type, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(uint64_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("data_len", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObUInt32Type, //column_type + CS_TYPE_INVALID, //column_collation_type + sizeof(uint32_t), //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + + if (OB_SUCC(ret)) { + ADD_COLUMN_SCHEMA("lob_data", //column_name + ++column_id, //column_id + 0, //rowkey_id + 0, //index_id + 0, //part_key_pos + ObVarcharType, //column_type + CS_TYPE_BINARY, //column_collation_type + 32, //column_length + -1, //column_precision + -1, //column_scale + false, //is_nullable + false); //is_autoincrement + } + table_schema.set_index_using_type(USING_BTREE); + table_schema.set_row_store_type(ENCODING_ROW_STORE); + table_schema.set_store_format(OB_STORE_FORMAT_DYNAMIC_MYSQL); + table_schema.set_progressive_merge_round(1); + table_schema.set_storage_format_version(3); + table_schema.set_tablet_id(OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TID); + table_schema.set_micro_index_clustered(false); + table_schema.set_data_table_id(OB_ALL_SPM_EVO_RESULT_TID); + + table_schema.set_max_used_column_id(column_id); + return ret; +} + int ObInnerTableSchema::all_ncomp_dll_v2_aux_lob_piece_schema(ObTableSchema &table_schema) { int ret = OB_SUCCESS; diff --git a/src/share/inner_table/ob_inner_table_schema.h b/src/share/inner_table/ob_inner_table_schema.h index d1c5e7fb3a..4a6c085be9 100644 --- a/src/share/inner_table/ob_inner_table_schema.h +++ b/src/share/inner_table/ob_inner_table_schema.h @@ -636,6 +636,7 @@ public: static int all_storage_io_usage_schema(share::schema::ObTableSchema &table_schema); static int all_mview_dep_schema(share::schema::ObTableSchema &table_schema); static int all_scheduler_job_run_detail_v2_schema(share::schema::ObTableSchema &table_schema); + static int all_spm_evo_result_schema(share::schema::ObTableSchema &table_schema); static int all_ncomp_dll_v2_schema(share::schema::ObTableSchema &table_schema); static int tenant_virtual_all_table_schema(share::schema::ObTableSchema &table_schema); static int tenant_virtual_table_column_schema(share::schema::ObTableSchema &table_schema); @@ -1108,6 +1109,7 @@ public: static int all_virtual_log_transport_dest_stat_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_ss_local_cache_info_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_kv_group_commit_status_schema(share::schema::ObTableSchema &table_schema); + static int all_virtual_spm_evo_result_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_vector_index_info_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_kv_client_info_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_function_io_stat_schema(share::schema::ObTableSchema &table_schema); @@ -1395,6 +1397,7 @@ public: static int all_virtual_spatial_reference_systems_real_agent_ora_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_log_transport_dest_stat_ora_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_ss_local_cache_info_ora_schema(share::schema::ObTableSchema &table_schema); + static int all_virtual_spm_evo_result_ora_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_vector_index_info_ora_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_function_io_stat_ora_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_temp_file_ora_schema(share::schema::ObTableSchema &table_schema); @@ -1888,6 +1891,8 @@ public: static int innodb_sys_foreign_cols_schema(share::schema::ObTableSchema &table_schema); static int gv_ob_kv_client_info_schema(share::schema::ObTableSchema &table_schema); static int v_ob_kv_client_info_schema(share::schema::ObTableSchema &table_schema); + static int dba_ob_spm_evo_result_schema(share::schema::ObTableSchema &table_schema); + static int cdb_ob_spm_evo_result_schema(share::schema::ObTableSchema &table_schema); static int gv_ob_function_io_stat_schema(share::schema::ObTableSchema &table_schema); static int v_ob_function_io_stat_schema(share::schema::ObTableSchema &table_schema); static int dba_ob_temp_files_schema(share::schema::ObTableSchema &table_schema); @@ -2372,6 +2377,7 @@ public: static int v_ob_log_transport_dest_stat_ora_schema(share::schema::ObTableSchema &table_schema); static int gv_ob_ss_local_cache_ora_schema(share::schema::ObTableSchema &table_schema); static int v_ob_ss_local_cache_ora_schema(share::schema::ObTableSchema &table_schema); + static int dba_ob_spm_evo_result_ora_schema(share::schema::ObTableSchema &table_schema); static int gv_ob_function_io_stat_ora_schema(share::schema::ObTableSchema &table_schema); static int v_ob_function_io_stat_ora_schema(share::schema::ObTableSchema &table_schema); static int dba_ob_temp_files_ora_schema(share::schema::ObTableSchema &table_schema); @@ -2683,6 +2689,7 @@ public: static int all_storage_io_usage_aux_lob_meta_schema(share::schema::ObTableSchema &table_schema); static int all_mview_dep_aux_lob_meta_schema(share::schema::ObTableSchema &table_schema); static int all_scheduler_job_run_detail_v2_aux_lob_meta_schema(share::schema::ObTableSchema &table_schema); + static int all_spm_evo_result_aux_lob_meta_schema(share::schema::ObTableSchema &table_schema); static int all_ncomp_dll_v2_aux_lob_meta_schema(share::schema::ObTableSchema &table_schema); static int all_table_aux_lob_piece_schema(share::schema::ObTableSchema &table_schema); static int all_column_aux_lob_piece_schema(share::schema::ObTableSchema &table_schema); @@ -2992,6 +2999,7 @@ public: static int all_storage_io_usage_aux_lob_piece_schema(share::schema::ObTableSchema &table_schema); static int all_mview_dep_aux_lob_piece_schema(share::schema::ObTableSchema &table_schema); static int all_scheduler_job_run_detail_v2_aux_lob_piece_schema(share::schema::ObTableSchema &table_schema); + static int all_spm_evo_result_aux_lob_piece_schema(share::schema::ObTableSchema &table_schema); static int all_ncomp_dll_v2_aux_lob_piece_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_ash_all_virtual_ash_i1_schema(share::schema::ObTableSchema &table_schema); static int all_virtual_sql_plan_monitor_all_virtual_sql_plan_monitor_i1_schema(share::schema::ObTableSchema &table_schema); @@ -3522,6 +3530,7 @@ const schema_create_func sys_table_schema_creators [] = { ObInnerTableSchema::all_storage_io_usage_schema, ObInnerTableSchema::all_mview_dep_schema, ObInnerTableSchema::all_scheduler_job_run_detail_v2_schema, + ObInnerTableSchema::all_spm_evo_result_schema, ObInnerTableSchema::all_ncomp_dll_v2_schema, NULL,}; @@ -3997,6 +4006,7 @@ const schema_create_func virtual_table_schema_creators [] = { ObInnerTableSchema::all_virtual_log_transport_dest_stat_schema, ObInnerTableSchema::all_virtual_ss_local_cache_info_schema, ObInnerTableSchema::all_virtual_kv_group_commit_status_schema, + ObInnerTableSchema::all_virtual_spm_evo_result_schema, ObInnerTableSchema::all_virtual_vector_index_info_schema, ObInnerTableSchema::all_virtual_kv_client_info_schema, ObInnerTableSchema::all_virtual_function_io_stat_schema, @@ -4294,6 +4304,7 @@ const schema_create_func virtual_table_schema_creators [] = { ObInnerTableSchema::all_virtual_spatial_reference_systems_real_agent_ora_schema, ObInnerTableSchema::all_virtual_log_transport_dest_stat_ora_schema, ObInnerTableSchema::all_virtual_ss_local_cache_info_ora_schema, + ObInnerTableSchema::all_virtual_spm_evo_result_ora_schema, ObInnerTableSchema::all_virtual_vector_index_info_ora_schema, ObInnerTableSchema::all_virtual_function_io_stat_ora_schema, ObInnerTableSchema::all_virtual_temp_file_ora_schema, @@ -4874,6 +4885,8 @@ const schema_create_func sys_view_schema_creators [] = { ObInnerTableSchema::innodb_sys_foreign_cols_schema, ObInnerTableSchema::gv_ob_kv_client_info_schema, ObInnerTableSchema::v_ob_kv_client_info_schema, + ObInnerTableSchema::dba_ob_spm_evo_result_schema, + ObInnerTableSchema::cdb_ob_spm_evo_result_schema, ObInnerTableSchema::gv_ob_function_io_stat_schema, ObInnerTableSchema::v_ob_function_io_stat_schema, ObInnerTableSchema::dba_ob_temp_files_schema, @@ -5358,6 +5371,7 @@ const schema_create_func sys_view_schema_creators [] = { ObInnerTableSchema::v_ob_log_transport_dest_stat_ora_schema, ObInnerTableSchema::gv_ob_ss_local_cache_ora_schema, ObInnerTableSchema::v_ob_ss_local_cache_ora_schema, + ObInnerTableSchema::dba_ob_spm_evo_result_ora_schema, ObInnerTableSchema::gv_ob_function_io_stat_ora_schema, ObInnerTableSchema::v_ob_function_io_stat_ora_schema, ObInnerTableSchema::dba_ob_temp_files_ora_schema, @@ -5771,6 +5785,7 @@ const uint64_t tenant_space_tables [] = { OB_ALL_STORAGE_IO_USAGE_TID, OB_ALL_MVIEW_DEP_TID, OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_TID, + OB_ALL_SPM_EVO_RESULT_TID, OB_ALL_NCOMP_DLL_V2_TID, OB_TENANT_VIRTUAL_ALL_TABLE_TID, OB_TENANT_VIRTUAL_TABLE_COLUMN_TID, @@ -6017,6 +6032,7 @@ const uint64_t tenant_space_tables [] = { OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_TID, OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_TID, OB_ALL_VIRTUAL_KV_GROUP_COMMIT_STATUS_TID, + OB_ALL_VIRTUAL_SPM_EVO_RESULT_TID, OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_TID, OB_ALL_VIRTUAL_KV_CLIENT_INFO_TID, OB_ALL_VIRTUAL_FUNCTION_IO_STAT_TID, @@ -6312,6 +6328,7 @@ const uint64_t tenant_space_tables [] = { OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TID, OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_ORA_TID, OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_ORA_TID, + OB_ALL_VIRTUAL_SPM_EVO_RESULT_ORA_TID, OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_ORA_TID, OB_ALL_VIRTUAL_FUNCTION_IO_STAT_ORA_TID, OB_ALL_VIRTUAL_TEMP_FILE_ORA_TID, @@ -6675,6 +6692,7 @@ const uint64_t tenant_space_tables [] = { OB_INNODB_SYS_FOREIGN_COLS_TID, OB_GV_OB_KV_CLIENT_INFO_TID, OB_V_OB_KV_CLIENT_INFO_TID, + OB_DBA_OB_SPM_EVO_RESULT_TID, OB_GV_OB_FUNCTION_IO_STAT_TID, OB_V_OB_FUNCTION_IO_STAT_TID, OB_DBA_OB_TEMP_FILES_TID, @@ -7158,6 +7176,7 @@ const uint64_t tenant_space_tables [] = { OB_V_OB_LOG_TRANSPORT_DEST_STAT_ORA_TID, OB_GV_OB_SS_LOCAL_CACHE_ORA_TID, OB_V_OB_SS_LOCAL_CACHE_ORA_TID, + OB_DBA_OB_SPM_EVO_RESULT_ORA_TID, OB_GV_OB_FUNCTION_IO_STAT_ORA_TID, OB_V_OB_FUNCTION_IO_STAT_ORA_TID, OB_DBA_OB_TEMP_FILES_ORA_TID, @@ -7624,6 +7643,7 @@ const uint64_t tenant_space_tables [] = { OB_ALL_STORAGE_IO_USAGE_AUX_LOB_META_TID, OB_ALL_MVIEW_DEP_AUX_LOB_META_TID, OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_AUX_LOB_META_TID, + OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TID, OB_ALL_NCOMP_DLL_V2_AUX_LOB_META_TID, OB_ALL_TABLE_AUX_LOB_PIECE_TID, OB_ALL_COLUMN_AUX_LOB_PIECE_TID, @@ -7907,6 +7927,7 @@ const uint64_t tenant_space_tables [] = { OB_ALL_STORAGE_IO_USAGE_AUX_LOB_PIECE_TID, OB_ALL_MVIEW_DEP_AUX_LOB_PIECE_TID, OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_AUX_LOB_PIECE_TID, + OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TID, OB_ALL_NCOMP_DLL_V2_AUX_LOB_PIECE_TID, }; const uint64_t all_ora_mapping_virtual_table_org_tables [] = { @@ -8063,6 +8084,7 @@ const uint64_t all_ora_mapping_virtual_table_org_tables [] = { OB_ALL_VIRTUAL_NIC_INFO_TID, OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_TID, OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_TID, + OB_ALL_VIRTUAL_SPM_EVO_RESULT_TID, OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_TID, OB_ALL_VIRTUAL_FUNCTION_IO_STAT_TID, OB_ALL_VIRTUAL_TEMP_FILE_TID, @@ -8221,6 +8243,7 @@ const uint64_t all_ora_mapping_virtual_tables [] = { OB_ALL_VIRTUAL_SQL_AUDIT_O , OB_ALL_VIRTUAL_NIC_INFO_ORA_TID , OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_ORA_TID , OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_ORA_TID +, OB_ALL_VIRTUAL_SPM_EVO_RESULT_ORA_TID , OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_ORA_TID , OB_ALL_VIRTUAL_FUNCTION_IO_STAT_ORA_TID , OB_ALL_VIRTUAL_TEMP_FILE_ORA_TID @@ -8522,6 +8545,7 @@ const char* const tenant_space_table_names [] = { OB_ALL_STORAGE_IO_USAGE_TNAME, OB_ALL_MVIEW_DEP_TNAME, OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_TNAME, + OB_ALL_SPM_EVO_RESULT_TNAME, OB_ALL_NCOMP_DLL_V2_TNAME, OB_TENANT_VIRTUAL_ALL_TABLE_TNAME, OB_TENANT_VIRTUAL_TABLE_COLUMN_TNAME, @@ -8768,6 +8792,7 @@ const char* const tenant_space_table_names [] = { OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_TNAME, OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_TNAME, OB_ALL_VIRTUAL_KV_GROUP_COMMIT_STATUS_TNAME, + OB_ALL_VIRTUAL_SPM_EVO_RESULT_TNAME, OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_TNAME, OB_ALL_VIRTUAL_KV_CLIENT_INFO_TNAME, OB_ALL_VIRTUAL_FUNCTION_IO_STAT_TNAME, @@ -9063,6 +9088,7 @@ const char* const tenant_space_table_names [] = { OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TNAME, OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_ORA_TNAME, OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_ORA_TNAME, + OB_ALL_VIRTUAL_SPM_EVO_RESULT_ORA_TNAME, OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_ORA_TNAME, OB_ALL_VIRTUAL_FUNCTION_IO_STAT_ORA_TNAME, OB_ALL_VIRTUAL_TEMP_FILE_ORA_TNAME, @@ -9426,6 +9452,7 @@ const char* const tenant_space_table_names [] = { OB_INNODB_SYS_FOREIGN_COLS_TNAME, OB_GV_OB_KV_CLIENT_INFO_TNAME, OB_V_OB_KV_CLIENT_INFO_TNAME, + OB_DBA_OB_SPM_EVO_RESULT_TNAME, OB_GV_OB_FUNCTION_IO_STAT_TNAME, OB_V_OB_FUNCTION_IO_STAT_TNAME, OB_DBA_OB_TEMP_FILES_TNAME, @@ -9909,6 +9936,7 @@ const char* const tenant_space_table_names [] = { OB_V_OB_LOG_TRANSPORT_DEST_STAT_ORA_TNAME, OB_GV_OB_SS_LOCAL_CACHE_ORA_TNAME, OB_V_OB_SS_LOCAL_CACHE_ORA_TNAME, + OB_DBA_OB_SPM_EVO_RESULT_ORA_TNAME, OB_GV_OB_FUNCTION_IO_STAT_ORA_TNAME, OB_V_OB_FUNCTION_IO_STAT_ORA_TNAME, OB_DBA_OB_TEMP_FILES_ORA_TNAME, @@ -10375,6 +10403,7 @@ const char* const tenant_space_table_names [] = { OB_ALL_STORAGE_IO_USAGE_AUX_LOB_META_TNAME, OB_ALL_MVIEW_DEP_AUX_LOB_META_TNAME, OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_AUX_LOB_META_TNAME, + OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TNAME, OB_ALL_NCOMP_DLL_V2_AUX_LOB_META_TNAME, OB_ALL_TABLE_AUX_LOB_PIECE_TNAME, OB_ALL_COLUMN_AUX_LOB_PIECE_TNAME, @@ -10658,6 +10687,7 @@ const char* const tenant_space_table_names [] = { OB_ALL_STORAGE_IO_USAGE_AUX_LOB_PIECE_TNAME, OB_ALL_MVIEW_DEP_AUX_LOB_PIECE_TNAME, OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_AUX_LOB_PIECE_TNAME, + OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TNAME, OB_ALL_NCOMP_DLL_V2_AUX_LOB_PIECE_TNAME, }; const uint64_t only_rs_vtables [] = { @@ -13663,6 +13693,14 @@ LOBMapping const lob_aux_table_mappings [] = { ObInnerTableSchema::all_scheduler_job_run_detail_v2_aux_lob_piece_schema }, + { + OB_ALL_SPM_EVO_RESULT_TID, + OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TID, + OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TID, + ObInnerTableSchema::all_spm_evo_result_aux_lob_meta_schema, + ObInnerTableSchema::all_spm_evo_result_aux_lob_piece_schema + }, + { OB_ALL_NCOMP_DLL_V2_TID, OB_ALL_NCOMP_DLL_V2_AUX_LOB_META_TID, @@ -13708,12 +13746,12 @@ static inline int get_sys_table_lob_aux_schema(const uint64_t tid, } const int64_t OB_CORE_TABLE_COUNT = 4; -const int64_t OB_SYS_TABLE_COUNT = 306; -const int64_t OB_VIRTUAL_TABLE_COUNT = 857; -const int64_t OB_SYS_VIEW_COUNT = 975; -const int64_t OB_SYS_TENANT_TABLE_COUNT = 2143; +const int64_t OB_SYS_TABLE_COUNT = 307; +const int64_t OB_VIRTUAL_TABLE_COUNT = 859; +const int64_t OB_SYS_VIEW_COUNT = 978; +const int64_t OB_SYS_TENANT_TABLE_COUNT = 2149; const int64_t OB_CORE_SCHEMA_VERSION = 1; -const int64_t OB_BOOTSTRAP_SCHEMA_VERSION = 2146; +const int64_t OB_BOOTSTRAP_SCHEMA_VERSION = 2152; } // end namespace share } // end namespace oceanbase diff --git a/src/share/inner_table/ob_inner_table_schema.lob.cpp b/src/share/inner_table/ob_inner_table_schema.lob.cpp index 3e53e16bc9..fa8d5b6c79 100644 --- a/src/share/inner_table/ob_inner_table_schema.lob.cpp +++ b/src/share/inner_table/ob_inner_table_schema.lob.cpp @@ -21,7 +21,7 @@ inner_lob_map_t inner_lob_map; bool lob_mapping_init() { int ret = OB_SUCCESS; - if (OB_FAIL(inner_lob_map.create(309, ObModIds::OB_INNER_LOB_HASH_SET))) { + if (OB_FAIL(inner_lob_map.create(310, ObModIds::OB_INNER_LOB_HASH_SET))) { SERVER_LOG(WARN, "fail to create inner lob map", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < ARRAYSIZEOF(lob_aux_table_mappings); ++i) { diff --git a/src/share/inner_table/ob_inner_table_schema_constants.h b/src/share/inner_table/ob_inner_table_schema_constants.h index 760a3820dc..8f3ad0808e 100644 --- a/src/share/inner_table/ob_inner_table_schema_constants.h +++ b/src/share/inner_table/ob_inner_table_schema_constants.h @@ -336,6 +336,7 @@ const uint64_t OB_ALL_SERVICE_TID = 516; // "__all_service" const uint64_t OB_ALL_STORAGE_IO_USAGE_TID = 517; // "__all_storage_io_usage" const uint64_t OB_ALL_MVIEW_DEP_TID = 518; // "__all_mview_dep" const uint64_t OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_TID = 519; // "__all_scheduler_job_run_detail_v2" +const uint64_t OB_ALL_SPM_EVO_RESULT_TID = 520; // "__all_spm_evo_result" const uint64_t OB_ALL_NCOMP_DLL_V2_TID = 528; // "__all_ncomp_dll_v2" const uint64_t OB_TENANT_VIRTUAL_ALL_TABLE_TID = 10001; // "__tenant_virtual_all_table" const uint64_t OB_TENANT_VIRTUAL_TABLE_COLUMN_TID = 10002; // "__tenant_virtual_table_column" @@ -808,6 +809,7 @@ const uint64_t OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_TID = 12490; // "__all_v const uint64_t OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_TID = 12491; // "__all_virtual_log_transport_dest_stat" const uint64_t OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_TID = 12492; // "__all_virtual_ss_local_cache_info" const uint64_t OB_ALL_VIRTUAL_KV_GROUP_COMMIT_STATUS_TID = 12493; // "__all_virtual_kv_group_commit_status" +const uint64_t OB_ALL_VIRTUAL_SPM_EVO_RESULT_TID = 12495; // "__all_virtual_spm_evo_result" const uint64_t OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_TID = 12496; // "__all_virtual_vector_index_info" const uint64_t OB_ALL_VIRTUAL_KV_CLIENT_INFO_TID = 12500; // "__all_virtual_kv_client_info" const uint64_t OB_ALL_VIRTUAL_FUNCTION_IO_STAT_TID = 12504; // "__all_virtual_function_io_stat" @@ -1095,6 +1097,7 @@ const uint64_t OB_ALL_VIRTUAL_SCHEDULER_JOB_RUN_DETAIL_V2_REAL_AGENT_ORA_TID = 1 const uint64_t OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TID = 15459; // "ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA" const uint64_t OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_ORA_TID = 15461; // "ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_ORA" const uint64_t OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_ORA_TID = 15462; // "ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_ORA" +const uint64_t OB_ALL_VIRTUAL_SPM_EVO_RESULT_ORA_TID = 15466; // "ALL_VIRTUAL_SPM_EVO_RESULT_ORA" const uint64_t OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_ORA_TID = 15467; // "ALL_VIRTUAL_VECTOR_INDEX_INFO_ORA" const uint64_t OB_ALL_VIRTUAL_FUNCTION_IO_STAT_ORA_TID = 15484; // "ALL_VIRTUAL_FUNCTION_IO_STAT_ORA" const uint64_t OB_ALL_VIRTUAL_TEMP_FILE_ORA_TID = 15485; // "ALL_VIRTUAL_TEMP_FILE_ORA" @@ -1588,6 +1591,8 @@ const uint64_t OB_INNODB_SYS_FOREIGN_TID = 21604; // "INNODB_SYS_FOREIGN" const uint64_t OB_INNODB_SYS_FOREIGN_COLS_TID = 21605; // "INNODB_SYS_FOREIGN_COLS" const uint64_t OB_GV_OB_KV_CLIENT_INFO_TID = 21607; // "GV$OB_KV_CLIENT_INFO" const uint64_t OB_V_OB_KV_CLIENT_INFO_TID = 21608; // "V$OB_KV_CLIENT_INFO" +const uint64_t OB_DBA_OB_SPM_EVO_RESULT_TID = 21616; // "DBA_OB_SPM_EVO_RESULT" +const uint64_t OB_CDB_OB_SPM_EVO_RESULT_TID = 21617; // "CDB_OB_SPM_EVO_RESULT" const uint64_t OB_GV_OB_FUNCTION_IO_STAT_TID = 21620; // "GV$OB_FUNCTION_IO_STAT" const uint64_t OB_V_OB_FUNCTION_IO_STAT_TID = 21621; // "V$OB_FUNCTION_IO_STAT" const uint64_t OB_DBA_OB_TEMP_FILES_TID = 21622; // "DBA_OB_TEMP_FILES" @@ -2072,6 +2077,7 @@ const uint64_t OB_GV_OB_LOG_TRANSPORT_DEST_STAT_ORA_TID = 28238; // "GV$OB_LOG_T const uint64_t OB_V_OB_LOG_TRANSPORT_DEST_STAT_ORA_TID = 28239; // "V$OB_LOG_TRANSPORT_DEST_STAT_ORA" const uint64_t OB_GV_OB_SS_LOCAL_CACHE_ORA_TID = 28240; // "GV$OB_SS_LOCAL_CACHE_ORA" const uint64_t OB_V_OB_SS_LOCAL_CACHE_ORA_TID = 28241; // "V$OB_SS_LOCAL_CACHE_ORA" +const uint64_t OB_DBA_OB_SPM_EVO_RESULT_ORA_TID = 28261; // "DBA_OB_SPM_EVO_RESULT_ORA" const uint64_t OB_GV_OB_FUNCTION_IO_STAT_ORA_TID = 28262; // "GV$OB_FUNCTION_IO_STAT_ORA" const uint64_t OB_V_OB_FUNCTION_IO_STAT_ORA_TID = 28263; // "V$OB_FUNCTION_IO_STAT_ORA" const uint64_t OB_DBA_OB_TEMP_FILES_ORA_TID = 28264; // "DBA_OB_TEMP_FILES_ORA" @@ -2383,6 +2389,7 @@ const uint64_t OB_ALL_SERVICE_AUX_LOB_META_TID = 50516; // "__all_service_aux_lo const uint64_t OB_ALL_STORAGE_IO_USAGE_AUX_LOB_META_TID = 50517; // "__all_storage_io_usage_aux_lob_meta" const uint64_t OB_ALL_MVIEW_DEP_AUX_LOB_META_TID = 50518; // "__all_mview_dep_aux_lob_meta" const uint64_t OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_AUX_LOB_META_TID = 50519; // "__all_scheduler_job_run_detail_v2_aux_lob_meta" +const uint64_t OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TID = 50520; // "__all_spm_evo_result_aux_lob_meta" const uint64_t OB_ALL_NCOMP_DLL_V2_AUX_LOB_META_TID = 50528; // "__all_ncomp_dll_v2_aux_lob_meta" const uint64_t OB_ALL_TABLE_AUX_LOB_PIECE_TID = 60003; // "__all_table_aux_lob_piece" const uint64_t OB_ALL_COLUMN_AUX_LOB_PIECE_TID = 60004; // "__all_column_aux_lob_piece" @@ -2692,6 +2699,7 @@ const uint64_t OB_ALL_SERVICE_AUX_LOB_PIECE_TID = 60516; // "__all_service_aux_l const uint64_t OB_ALL_STORAGE_IO_USAGE_AUX_LOB_PIECE_TID = 60517; // "__all_storage_io_usage_aux_lob_piece" const uint64_t OB_ALL_MVIEW_DEP_AUX_LOB_PIECE_TID = 60518; // "__all_mview_dep_aux_lob_piece" const uint64_t OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_AUX_LOB_PIECE_TID = 60519; // "__all_scheduler_job_run_detail_v2_aux_lob_piece" +const uint64_t OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TID = 60520; // "__all_spm_evo_result_aux_lob_piece" const uint64_t OB_ALL_NCOMP_DLL_V2_AUX_LOB_PIECE_TID = 60528; // "__all_ncomp_dll_v2_aux_lob_piece" const uint64_t OB_ALL_VIRTUAL_PLAN_CACHE_STAT_ALL_VIRTUAL_PLAN_CACHE_STAT_I1_TID = 14999; // "__all_virtual_plan_cache_stat" const uint64_t OB_ALL_VIRTUAL_SESSION_EVENT_ALL_VIRTUAL_SESSION_EVENT_I1_TID = 14998; // "__all_virtual_session_event" @@ -3209,6 +3217,7 @@ const char *const OB_ALL_SERVICE_TNAME = "__all_service"; const char *const OB_ALL_STORAGE_IO_USAGE_TNAME = "__all_storage_io_usage"; const char *const OB_ALL_MVIEW_DEP_TNAME = "__all_mview_dep"; const char *const OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_TNAME = "__all_scheduler_job_run_detail_v2"; +const char *const OB_ALL_SPM_EVO_RESULT_TNAME = "__all_spm_evo_result"; const char *const OB_ALL_NCOMP_DLL_V2_TNAME = "__all_ncomp_dll_v2"; const char *const OB_TENANT_VIRTUAL_ALL_TABLE_TNAME = "__tenant_virtual_all_table"; const char *const OB_TENANT_VIRTUAL_TABLE_COLUMN_TNAME = "__tenant_virtual_table_column"; @@ -3681,6 +3690,7 @@ const char *const OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_TNAME = "__all_virtua const char *const OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_TNAME = "__all_virtual_log_transport_dest_stat"; const char *const OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_TNAME = "__all_virtual_ss_local_cache_info"; const char *const OB_ALL_VIRTUAL_KV_GROUP_COMMIT_STATUS_TNAME = "__all_virtual_kv_group_commit_status"; +const char *const OB_ALL_VIRTUAL_SPM_EVO_RESULT_TNAME = "__all_virtual_spm_evo_result"; const char *const OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_TNAME = "__all_virtual_vector_index_info"; const char *const OB_ALL_VIRTUAL_KV_CLIENT_INFO_TNAME = "__all_virtual_kv_client_info"; const char *const OB_ALL_VIRTUAL_FUNCTION_IO_STAT_TNAME = "__all_virtual_function_io_stat"; @@ -3968,6 +3978,7 @@ const char *const OB_ALL_VIRTUAL_SCHEDULER_JOB_RUN_DETAIL_V2_REAL_AGENT_ORA_TNAM const char *const OB_ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT_ORA_TNAME = "ALL_VIRTUAL_SPATIAL_REFERENCE_SYSTEMS_REAL_AGENT"; const char *const OB_ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT_ORA_TNAME = "ALL_VIRTUAL_LOG_TRANSPORT_DEST_STAT"; const char *const OB_ALL_VIRTUAL_SS_LOCAL_CACHE_INFO_ORA_TNAME = "ALL_VIRTUAL_SS_LOCAL_CACHE_INFO"; +const char *const OB_ALL_VIRTUAL_SPM_EVO_RESULT_ORA_TNAME = "ALL_VIRTUAL_SPM_EVO_RESULT"; const char *const OB_ALL_VIRTUAL_VECTOR_INDEX_INFO_ORA_TNAME = "ALL_VIRTUAL_VECTOR_INDEX_INFO"; const char *const OB_ALL_VIRTUAL_FUNCTION_IO_STAT_ORA_TNAME = "ALL_VIRTUAL_FUNCTION_IO_STAT"; const char *const OB_ALL_VIRTUAL_TEMP_FILE_ORA_TNAME = "ALL_VIRTUAL_TEMP_FILE"; @@ -4461,6 +4472,8 @@ const char *const OB_INNODB_SYS_FOREIGN_TNAME = "INNODB_SYS_FOREIGN"; const char *const OB_INNODB_SYS_FOREIGN_COLS_TNAME = "INNODB_SYS_FOREIGN_COLS"; const char *const OB_GV_OB_KV_CLIENT_INFO_TNAME = "GV$OB_KV_CLIENT_INFO"; const char *const OB_V_OB_KV_CLIENT_INFO_TNAME = "V$OB_KV_CLIENT_INFO"; +const char *const OB_DBA_OB_SPM_EVO_RESULT_TNAME = "DBA_OB_SPM_EVO_RESULT"; +const char *const OB_CDB_OB_SPM_EVO_RESULT_TNAME = "CDB_OB_SPM_EVO_RESULT"; const char *const OB_GV_OB_FUNCTION_IO_STAT_TNAME = "GV$OB_FUNCTION_IO_STAT"; const char *const OB_V_OB_FUNCTION_IO_STAT_TNAME = "V$OB_FUNCTION_IO_STAT"; const char *const OB_DBA_OB_TEMP_FILES_TNAME = "DBA_OB_TEMP_FILES"; @@ -4945,6 +4958,7 @@ const char *const OB_GV_OB_LOG_TRANSPORT_DEST_STAT_ORA_TNAME = "GV$OB_LOG_TRANSP const char *const OB_V_OB_LOG_TRANSPORT_DEST_STAT_ORA_TNAME = "V$OB_LOG_TRANSPORT_DEST_STAT"; const char *const OB_GV_OB_SS_LOCAL_CACHE_ORA_TNAME = "GV$OB_SS_LOCAL_CACHE"; const char *const OB_V_OB_SS_LOCAL_CACHE_ORA_TNAME = "V$OB_SS_LOCAL_CACHE"; +const char *const OB_DBA_OB_SPM_EVO_RESULT_ORA_TNAME = "DBA_OB_SPM_EVO_RESULT"; const char *const OB_GV_OB_FUNCTION_IO_STAT_ORA_TNAME = "GV$OB_FUNCTION_IO_STAT"; const char *const OB_V_OB_FUNCTION_IO_STAT_ORA_TNAME = "V$OB_FUNCTION_IO_STAT"; const char *const OB_DBA_OB_TEMP_FILES_ORA_TNAME = "DBA_OB_TEMP_FILES"; @@ -5256,6 +5270,7 @@ const char *const OB_ALL_SERVICE_AUX_LOB_META_TNAME = "__all_service_aux_lob_met const char *const OB_ALL_STORAGE_IO_USAGE_AUX_LOB_META_TNAME = "__all_storage_io_usage_aux_lob_meta"; const char *const OB_ALL_MVIEW_DEP_AUX_LOB_META_TNAME = "__all_mview_dep_aux_lob_meta"; const char *const OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_AUX_LOB_META_TNAME = "__all_scheduler_job_run_detail_v2_aux_lob_meta"; +const char *const OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TNAME = "__all_spm_evo_result_aux_lob_meta"; const char *const OB_ALL_NCOMP_DLL_V2_AUX_LOB_META_TNAME = "__all_ncomp_dll_v2_aux_lob_meta"; const char *const OB_ALL_TABLE_AUX_LOB_PIECE_TNAME = "__all_table_aux_lob_piece"; const char *const OB_ALL_COLUMN_AUX_LOB_PIECE_TNAME = "__all_column_aux_lob_piece"; @@ -5565,6 +5580,7 @@ const char *const OB_ALL_SERVICE_AUX_LOB_PIECE_TNAME = "__all_service_aux_lob_pi const char *const OB_ALL_STORAGE_IO_USAGE_AUX_LOB_PIECE_TNAME = "__all_storage_io_usage_aux_lob_piece"; const char *const OB_ALL_MVIEW_DEP_AUX_LOB_PIECE_TNAME = "__all_mview_dep_aux_lob_piece"; const char *const OB_ALL_SCHEDULER_JOB_RUN_DETAIL_V2_AUX_LOB_PIECE_TNAME = "__all_scheduler_job_run_detail_v2_aux_lob_piece"; +const char *const OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TNAME = "__all_spm_evo_result_aux_lob_piece"; const char *const OB_ALL_NCOMP_DLL_V2_AUX_LOB_PIECE_TNAME = "__all_ncomp_dll_v2_aux_lob_piece"; const char *const OB_ALL_VIRTUAL_PLAN_CACHE_STAT_ALL_VIRTUAL_PLAN_CACHE_STAT_I1_TNAME = "__idx_11003_all_virtual_plan_cache_stat_i1"; const char *const OB_ALL_VIRTUAL_SESSION_EVENT_ALL_VIRTUAL_SESSION_EVENT_I1_TNAME = "__idx_11013_all_virtual_session_event_i1"; diff --git a/src/share/inner_table/ob_inner_table_schema_def.py b/src/share/inner_table/ob_inner_table_schema_def.py index 281c6841ec..6ac355582e 100755 --- a/src/share/inner_table/ob_inner_table_schema_def.py +++ b/src/share/inner_table/ob_inner_table_schema_def.py @@ -7513,7 +7513,36 @@ def_table_schema( ], ) -# 520 : __all_spm_evo_result +def_table_schema( + owner = 'yibo.tyf', + table_id = '520', + table_name = '__all_spm_evo_result', + table_type = 'SYSTEM_TABLE', + gm_columns = [], + rowkey_columns = [ + ('tenant_id', 'int'), + ('record_time', 'timestamp'), + ('svr_ip', 'varchar:MAX_IP_ADDR_LENGTH'), + ('svr_port', 'int'), + ], + in_tenant_space=True, + is_cluster_private=True, + meta_record_in_sys = False, + normal_columns = [ + ('database_id', 'int'), + ('sql_id', 'varchar:OB_MAX_SQL_ID_LENGTH'), + ('type', 'int'), + ('start_time', 'timestamp', 'true'), + ('end_time', 'timestamp', 'true'), + ('status', 'varchar:7', 'true'), + ('new_plan_better', 'bool', 'true'), + ('evo_plan_exec_count', 'int', 'true'), + ('evo_plan_cpu_time', 'int', 'true'), + ('baseline_exec_count', 'int', 'true'), + ('baseline_cpu_time', 'int', 'true'), + ], +) + # 521 : __all_detect_lock_info_v2 # 522 : __all_pkg_type # 523 : __all_pkg_type_attr @@ -15091,7 +15120,12 @@ def_table_schema( vtable_route_policy = 'distributed', ) # 12494: __all_virtual_session_sys_variable -# 12495: __all_virtual_spm_evo_result +def_table_schema(**gen_iterate_private_virtual_table_def( + table_id = '12495', + table_name = '__all_virtual_spm_evo_result', + in_tenant_space = True, + keywords = all_def_keywords['__all_spm_evo_result'])) + def_table_schema( owner = 'huhaosheng.hhs', table_name = '__all_virtual_vector_index_info', @@ -15733,7 +15767,7 @@ def_table_schema(**no_direct_access(gen_oracle_mapping_virtual_table_def('15462' # 15464: __all_virtual_kv_group_commit_status # 15465: __all_virtual_session_sys_variable -# 15466: __all_spm_evo_result +def_table_schema(**gen_oracle_mapping_virtual_table_def('15466', all_def_keywords['__all_virtual_spm_evo_result'])) # 15467: __all_virtual_vector_index_info # 15468: __all_pkg_type @@ -25811,7 +25845,7 @@ def_table_schema( CAST(NULL AS NUMBER) AS IM_BLOCK_COUNT, CAST(NULL AS DATETIME) AS IM_STAT_UPDATE_TIME, CAST(NULL AS NUMBER) AS SCAN_RATE, - CAST(STAT.SPARE1 AS NUMBER) AS SAMPLE_SIZE, + CAST(STAT.SPARE1 AS DECIMAL(20, 0)) AS SAMPLE_SIZE, CAST(STAT.LAST_ANALYZED AS DATETIME(6)) AS LAST_ANALYZED, CAST((CASE STAT.GLOBAL_STATS WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' ELSE NULL END) AS CHAR(3)) AS GLOBAL_STATS, CAST((CASE STAT.USER_STATS WHEN 0 THEN 'NO' WHEN 1 THEN 'YES' ELSE NULL END) AS CHAR(3)) AS USER_STATS, @@ -38156,8 +38190,78 @@ def_table_schema( # 21613: CDB_WR_SQL_PLAN # 21614: DBA_WR_RES_MGR_SYSSTAT # 21615: CDB_WR_RES_MGR_SYSSTAT -# 21616: DBA_OB_SPM_EVO_RESULT -# 21617: CDB_OB_SPM_EVO_RESULT + +def_table_schema( + owner = 'yibo.tyf', + table_name = 'DBA_OB_SPM_EVO_RESULT', + table_id = '21616', + table_type = 'SYSTEM_VIEW', + rowkey_columns = [], + normal_columns = [], + gm_columns = [], + in_tenant_space = True, + view_definition = """ + SELECT D.DATABASE_NAME AS OWNER, + RECORD_TIME, + SVR_IP, + SVR_PORT, + SQL_ID, + CAST(CASE WHEN TYPE = 0 THEN 'OnlineEvolve' + WHEN TYPE = 1 THEN 'FirstBaseline' + WHEN TYPE = 2 THEN 'UnReproducible' + WHEN TYPE = 3 THEN 'BaselineFirst' + ELSE NULL END AS CHAR(32)) AS TYPE, + START_TIME, + END_TIME, + STATUS, + NEW_PLAN_BETTER, + EVO_PLAN_EXEC_COUNT, + EVO_PLAN_CPU_TIME, + BASELINE_EXEC_COUNT, + BASELINE_CPU_TIME + FROM OCEANBASE.__ALL_VIRTUAL_SPM_EVO_RESULT R, + OCEANBASE.__ALL_DATABASE D + WHERE R.TENANT_ID = EFFECTIVE_TENANT_ID() + AND D.TENANT_ID = 0 + AND R.DATABASE_ID = D.DATABASE_ID +""".replace("\n", " ") +) + +def_table_schema( + owner = 'yibo.tyf', + table_name = 'CDB_OB_SPM_EVO_RESULT', + table_id = '21617', + table_type = 'SYSTEM_VIEW', + rowkey_columns = [], + normal_columns = [], + gm_columns = [], + view_definition = """ + SELECT R.TENANT_ID, + D.DATABASE_NAME AS OWNER, + RECORD_TIME, + SVR_IP, + SVR_PORT, + SQL_ID, + CAST(CASE WHEN TYPE = 0 THEN 'OnlineEvolve' + WHEN TYPE = 1 THEN 'FirstBaseline' + WHEN TYPE = 2 THEN 'UnReproducible' + WHEN TYPE = 3 THEN 'BaselineFirst' + ELSE NULL END AS CHAR(32)) AS TYPE, + START_TIME, + END_TIME, + STATUS, + NEW_PLAN_BETTER, + EVO_PLAN_EXEC_COUNT, + EVO_PLAN_CPU_TIME, + BASELINE_EXEC_COUNT, + BASELINE_CPU_TIME + FROM OCEANBASE.__ALL_VIRTUAL_SPM_EVO_RESULT R, + OCEANBASE.__ALL_VIRTUAL_DATABASE D + WHERE R.TENANT_ID = D.TENANT_ID + AND R.DATABASE_ID = D.DATABASE_ID +""".replace("\n", " ") +) + # 21618: DBA_OB_KV_REDIS_TABLE # 21619: CDB_OB_KV_REDIS_TABLE @@ -67081,7 +67185,44 @@ def_table_schema( # 28258: V$OB_RES_MGR_SYSSTAT # 28259: DBA_WR_SQL_PLAN # 28260: DBA_WR_RES_MGR_SYSSTAT -# 28261: DBA_OB_SPM_EVO_RESULT + +def_table_schema( + owner = 'yibo.tyf', + table_name = 'DBA_OB_SPM_EVO_RESULT', + name_postfix = '_ORA', + database_id = 'OB_ORA_SYS_DATABASE_ID', + table_id = '28261', + table_type = 'SYSTEM_VIEW', + rowkey_columns = [], + normal_columns = [], + gm_columns = [], + in_tenant_space = True, + view_definition = """ + SELECT D.DATABASE_NAME AS OWNER, + RECORD_TIME, + SVR_IP, + SVR_PORT, + SQL_ID, + CAST(CASE WHEN TYPE = 0 THEN 'OnlineEvolve' + WHEN TYPE = 1 THEN 'FirstBaseline' + WHEN TYPE = 2 THEN 'UnReproducible' + WHEN TYPE = 3 THEN 'BaselineFirst' + ELSE NULL END AS VARCHAR(32)) AS TYPE, + START_TIME, + END_TIME, + STATUS, + NEW_PLAN_BETTER, + EVO_PLAN_EXEC_COUNT, + EVO_PLAN_CPU_TIME, + BASELINE_EXEC_COUNT, + BASELINE_CPU_TIME + FROM SYS.ALL_VIRTUAL_SPM_EVO_RESULT R, + SYS.ALL_VIRTUAL_DATABASE_REAL_AGENT D + WHERE R.TENANT_ID = EFFECTIVE_TENANT_ID() + AND D.TENANT_ID = EFFECTIVE_TENANT_ID() + AND R.DATABASE_ID = D.DATABASE_ID +""".replace("\n", " ") +) def_table_schema( owner = 'zz412656', diff --git a/src/share/inner_table/ob_inner_table_schema_misc.ipp b/src/share/inner_table/ob_inner_table_schema_misc.ipp index 4e33e8d047..a5df1e6e03 100644 --- a/src/share/inner_table/ob_inner_table_schema_misc.ipp +++ b/src/share/inner_table/ob_inner_table_schema_misc.ipp @@ -525,6 +525,7 @@ case OB_ALL_VIRTUAL_RESTORE_JOB_TID: case OB_ALL_VIRTUAL_RESTORE_JOB_HISTORY_TID: case OB_ALL_VIRTUAL_RESTORE_PROGRESS_TID: case OB_ALL_VIRTUAL_SERVICE_TID: +case OB_ALL_VIRTUAL_SPM_EVO_RESULT_TID: case OB_ALL_VIRTUAL_STORAGE_IO_USAGE_TID: case OB_ALL_VIRTUAL_TABLE_OPT_STAT_GATHER_HISTORY_TID: case OB_ALL_VIRTUAL_TABLET_CHECKSUM_ERROR_INFO_TID: @@ -1519,6 +1520,22 @@ case OB_ALL_VIRTUAL_ZONE_MERGE_INFO_TID: END_CREATE_VT_ITER_SWITCH_LAMBDA BEGIN_CREATE_VT_ITER_SWITCH_LAMBDA + case OB_ALL_VIRTUAL_SPM_EVO_RESULT_TID: { + ObIteratePrivateVirtualTable *iter = NULL; + const bool meta_record_in_sys = false; + if (OB_FAIL(NEW_VIRTUAL_TABLE(ObIteratePrivateVirtualTable, iter))) { + SERVER_LOG(WARN, "create iterate private virtual table iterator failed", KR(ret)); + } else if (OB_FAIL(iter->init(OB_ALL_SPM_EVO_RESULT_TID, meta_record_in_sys, index_schema, params))) { + SERVER_LOG(WARN, "iterate private virtual table iter init failed", KR(ret)); + iter->~ObIteratePrivateVirtualTable(); + allocator.free(iter); + iter = NULL; + } else { + vt_iter = iter; + } + break; + } + case OB_ALL_VIRTUAL_STORAGE_IO_USAGE_TID: { ObIteratePrivateVirtualTable *iter = NULL; const bool meta_record_in_sys = false; @@ -1822,7 +1839,9 @@ case OB_ALL_VIRTUAL_ZONE_MERGE_INFO_TID: } break; } + END_CREATE_VT_ITER_SWITCH_LAMBDA + BEGIN_CREATE_VT_ITER_SWITCH_LAMBDA case OB_ALL_VIRTUAL_WR_SYSSTAT_TID: { ObIteratePrivateVirtualTable *iter = NULL; const bool meta_record_in_sys = false; @@ -1838,9 +1857,7 @@ case OB_ALL_VIRTUAL_ZONE_MERGE_INFO_TID: } break; } - END_CREATE_VT_ITER_SWITCH_LAMBDA - BEGIN_CREATE_VT_ITER_SWITCH_LAMBDA case OB_ALL_VIRTUAL_ZONE_MERGE_INFO_TID: { ObIteratePrivateVirtualTable *iter = NULL; const bool meta_record_in_sys = false; @@ -5028,6 +5045,9 @@ case OB_ALL_SERVICE_AUX_LOB_PIECE_TID: case OB_ALL_SERVICE_EPOCH_TID: case OB_ALL_SERVICE_EPOCH_AUX_LOB_META_TID: case OB_ALL_SERVICE_EPOCH_AUX_LOB_PIECE_TID: +case OB_ALL_SPM_EVO_RESULT_TID: +case OB_ALL_SPM_EVO_RESULT_AUX_LOB_META_TID: +case OB_ALL_SPM_EVO_RESULT_AUX_LOB_PIECE_TID: case OB_ALL_STORAGE_IO_USAGE_TID: case OB_ALL_STORAGE_IO_USAGE_AUX_LOB_META_TID: case OB_ALL_STORAGE_IO_USAGE_AUX_LOB_PIECE_TID: diff --git a/src/share/inner_table/table_id_to_name b/src/share/inner_table/table_id_to_name index b05435aed5..e8035b993f 100644 --- a/src/share/inner_table/table_id_to_name +++ b/src/share/inner_table/table_id_to_name @@ -365,6 +365,7 @@ # 517: __all_storage_io_usage # 518: __all_mview_dep # 519: __all_scheduler_job_run_detail_v2 +# 520: __all_spm_evo_result # 528: __all_ncomp_dll_v2 # 10001: __tenant_virtual_all_table # 10002: __tenant_virtual_table_column @@ -1160,6 +1161,8 @@ # 12491: __all_virtual_log_transport_dest_stat # 12492: __all_virtual_ss_local_cache_info # 12493: __all_virtual_kv_group_commit_status +# 12495: __all_virtual_spm_evo_result +# 12495: __all_spm_evo_result # BASE_TABLE_NAME # 12496: __all_virtual_vector_index_info # 12500: __all_virtual_kv_client_info # 12504: __all_virtual_function_io_stat @@ -1790,6 +1793,9 @@ # 15461: __all_virtual_log_transport_dest_stat # BASE_TABLE_NAME # 15462: ALL_VIRTUAL_SS_LOCAL_CACHE_INFO # 15462: __all_virtual_ss_local_cache_info # BASE_TABLE_NAME +# 15466: ALL_VIRTUAL_SPM_EVO_RESULT +# 15466: __all_spm_evo_result # BASE_TABLE_NAME +# 15466: __all_virtual_spm_evo_result # BASE_TABLE_NAME1 # 15467: ALL_VIRTUAL_VECTOR_INDEX_INFO # 15467: __all_virtual_vector_index_info # BASE_TABLE_NAME # 15484: ALL_VIRTUAL_FUNCTION_IO_STAT @@ -2288,6 +2294,8 @@ # 21605: INNODB_SYS_FOREIGN_COLS # 21607: GV$OB_KV_CLIENT_INFO # 21608: V$OB_KV_CLIENT_INFO +# 21616: DBA_OB_SPM_EVO_RESULT +# 21617: CDB_OB_SPM_EVO_RESULT # 21620: GV$OB_FUNCTION_IO_STAT # 21621: V$OB_FUNCTION_IO_STAT # 21622: DBA_OB_TEMP_FILES @@ -2772,6 +2780,7 @@ # 28239: V$OB_LOG_TRANSPORT_DEST_STAT # 28240: GV$OB_SS_LOCAL_CACHE # 28241: V$OB_SS_LOCAL_CACHE +# 28261: DBA_OB_SPM_EVO_RESULT # 28262: GV$OB_FUNCTION_IO_STAT # 28263: V$OB_FUNCTION_IO_STAT # 28264: DBA_OB_TEMP_FILES diff --git a/src/share/ob_upgrade_utils.cpp b/src/share/ob_upgrade_utils.cpp index e48866b053..7aba7aff07 100755 --- a/src/share/ob_upgrade_utils.cpp +++ b/src/share/ob_upgrade_utils.cpp @@ -1630,6 +1630,11 @@ int ObUpgradeFor4330Processor::post_upgrade_for_optimizer_stats() return ret; } +/* =========== 4250 upgrade processor end ============= */ + +/* =========== 4330 upgrade processor end ============= */ + +/* =========== 4340 upgrade processor start ============= */ int ObUpgradeFor4340Processor::post_upgrade() { int ret = OB_SUCCESS; @@ -1679,10 +1684,92 @@ int ObUpgradeFor4340Processor::post_upgrade_for_persitent_routine() return ret; } +/* =========== 4340 upgrade processor end ============= */ -/* =========== 4250 upgrade processor end ============= */ +/* =========== 4350 upgrade processor start ============= */ +int ObUpgradeFor4350Processor::post_upgrade() +{ + int ret = OB_SUCCESS; + if (OB_FAIL(check_inner_stat())) { + LOG_WARN("fail to check inner stat", KR(ret)); + } else if (OB_FAIL(add_spm_stats_scheduler_job())) { + LOG_WARN("fail to create standby replication role in oracle", KR(ret)); + } else if (OB_FAIL(post_upgrade_for_optimizer_stats())) { + LOG_WARN("fail to post upgrade for optimizer stats", KR(ret)); + } + return ret; +} -/* =========== 4330 upgrade processor end ============= */ +int ObUpgradeFor4350Processor::add_spm_stats_scheduler_job() +{ + int ret = OB_SUCCESS; + lib::Worker::CompatMode compat_mode = lib::Worker::CompatMode::INVALID; + bool is_primary_tenant = false; + bool job_exists = false; + ObSchemaGetterGuard schema_guard; + const ObSysVariableSchema *var_schema = NULL; + ObSqlString insert_sql; + int64_t affected_rows = 0; + if (OB_ISNULL(sql_proxy_) || OB_ISNULL(schema_service_) || !is_valid_tenant_id(tenant_id_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected error", KR(ret), KP_(sql_proxy), KP_(schema_service), K_(tenant_id)); + } else if (OB_FAIL(ObAllTenantInfoProxy::is_primary_tenant(sql_proxy_, tenant_id_, is_primary_tenant))) { + LOG_WARN("check is standby tenant failed", K(ret), K(tenant_id_)); + } else if (!is_primary_tenant) { + LOG_INFO("tenant isn't primary tenant", K(tenant_id_)); + } else if (OB_FAIL(ObDbmsStatsMaintenanceWindow::check_job_exists(sql_proxy_, + tenant_id_, + "SPM_STATS_MANAGER", + job_exists))) { + LOG_WARN("failed to check job exists"); + } else if (job_exists) { + LOG_INFO("spm schedular job already exists", K(tenant_id_), "job_name", "SPM_STATS_MANAGER"); + } else if (OB_FAIL(schema_service_->get_tenant_schema_guard(tenant_id_, schema_guard))) { + LOG_WARN("failed to get schema guard", K(ret)); + } else if (OB_FAIL(schema_guard.get_sys_variable_schema(tenant_id_, var_schema))) { + LOG_WARN("fail to get sys variable schema", KR(ret), K_(tenant_id)); + } else if (OB_FAIL(ObCompatModeGetter::get_tenant_mode(tenant_id_, compat_mode))) { + LOG_WARN("failed to get tenant compat mode", KR(ret), K_(tenant_id)); + } else if (OB_FAIL(ObDbmsStatsMaintenanceWindow::get_spm_stats_upgrade_jobs_sql(sql_proxy_, + *var_schema, + tenant_id_, + lib::Worker::CompatMode::ORACLE == compat_mode, + insert_sql))) { + LOG_WARN("failed to get spm stats upgrade jobs sql"); + } else if (OB_FAIL(sql_proxy_->write(tenant_id_, insert_sql.ptr(), affected_rows))) { + LOG_WARN("failed to write spm stats job", K(ret), K(tenant_id_), K(affected_rows), K(insert_sql)); + } + + return ret; +} + +int ObUpgradeFor4350Processor::post_upgrade_for_optimizer_stats() +{ + int ret = OB_SUCCESS; + ObSqlString extra_stats_perfs_sql; + int64_t affected_rows = 0; + bool is_primary_tenant = false; + if (sql_proxy_ == NULL) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("sql_proxy is null", K(ret), K(tenant_id_)); + } else if (OB_FAIL(ObAllTenantInfoProxy::is_primary_tenant(sql_proxy_, tenant_id_, is_primary_tenant))) { + LOG_WARN("check is standby tenant failed", K(ret), K(tenant_id_)); + } else if (!is_primary_tenant) { + LOG_INFO("tenant isn't primary standby, no refer to gather stats, skip", K(tenant_id_)); + } else if (OB_FAIL(ObDbmsStatsPreferences::get_extra_stats_perfs_for_upgrade_425(extra_stats_perfs_sql))) { + LOG_WARN("failed to get extra stats perfs for upgrade", K(ret)); + } else if (OB_FAIL(sql_proxy_->write(tenant_id_, extra_stats_perfs_sql.ptr(), affected_rows))) { + LOG_WARN("failed to write", K(ret)); + } + if (OB_FAIL(ret)) { + LOG_WARN("[UPGRADE] post upgrade for optimizer stats failed", KR(ret), K_(tenant_id)); + } else { + LOG_INFO("[UPGRADE] post upgrade for optimizer stats succeed", K_(tenant_id)); + } + return ret; +} + +/* =========== 4350 upgrade processor end ============= */ } // end share } // end oceanbase diff --git a/src/share/ob_upgrade_utils.h b/src/share/ob_upgrade_utils.h index 72c6429e5f..b17ba0ddba 100755 --- a/src/share/ob_upgrade_utils.h +++ b/src/share/ob_upgrade_utils.h @@ -286,6 +286,7 @@ private: int post_upgrade_for_external_table_flag(); int post_upgrade_for_service_name(); int post_upgrade_for_optimizer_stats(); + int add_spm_stats_scheduler_job(); }; DEF_SIMPLE_UPGRARD_PROCESSER(4, 3, 3, 1) @@ -300,7 +301,17 @@ private: int post_upgrade_for_persitent_routine(); }; -DEF_SIMPLE_UPGRARD_PROCESSER(4, 3, 5, 0) +class ObUpgradeFor4350Processor : public ObBaseUpgradeProcessor +{ +public: + ObUpgradeFor4350Processor() : ObBaseUpgradeProcessor() {} + virtual ~ObUpgradeFor4350Processor() {} + virtual int pre_upgrade() override { return common::OB_SUCCESS; } + virtual int post_upgrade() override; +private: + int add_spm_stats_scheduler_job(); + int post_upgrade_for_optimizer_stats(); +}; /* =========== special upgrade processor end ============= */ diff --git a/src/share/parameter/ob_parameter_seed.ipp b/src/share/parameter/ob_parameter_seed.ipp index 54264a0448..600aa70322 100644 --- a/src/share/parameter/ob_parameter_seed.ipp +++ b/src/share/parameter/ob_parameter_seed.ipp @@ -1907,6 +1907,9 @@ DEF_BOOL(_xsolapi_generate_with_clause, OB_TENANT_PARAMETER, "True", DEF_BOOL(_optimizer_group_by_placement, OB_TENANT_PARAMETER, "True", "enable group by placement transform rule", ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); +DEF_INT(_complex_cbqt_table_num, OB_TENANT_PARAMETER, "10", "[0,)", + "cost-based transform will be disabled when table count in a single stmt exceeds threshold", + ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); DEF_TIME(_wait_interval_after_parallel_ddl, OB_TENANT_PARAMETER, "30s", "[0s,)", "time interval for waiting other servers to refresh schema after parallel ddl is done", ObParameterAttr(Section::OBSERVER, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); @@ -2001,7 +2004,7 @@ DEF_CAP(auto_split_tablet_size, OB_TENANT_PARAMETER, "128M", "[128M,)", "Note that the modification of this config will not affect the created auto-partitioned table." "Range: [128M, +∞)", ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); -DEF_INT(_inlist_rewrite_threshold, OB_TENANT_PARAMETER, "2147483647", "[1, 2147483647]" +DEF_INT(_inlist_rewrite_threshold, OB_TENANT_PARAMETER, "1000", "[1, 2147483647]" "specifies transform how much const params in IN list to values table", ObParameterAttr(Section::TENANT, Source::DEFAULT, EditLevel::DYNAMIC_EFFECTIVE)); diff --git a/src/share/stat/ob_dbms_stats_executor.cpp b/src/share/stat/ob_dbms_stats_executor.cpp index 026318e17d..b0a9dd9e09 100644 --- a/src/share/stat/ob_dbms_stats_executor.cpp +++ b/src/share/stat/ob_dbms_stats_executor.cpp @@ -300,6 +300,10 @@ int ObDbmsStatsExecutor::prepare_gather_stats(ObExecContext &ctx, const_cast(param), gather_helper.use_split_part_))) { LOG_WARN("failed to adjsut async gather param", K(ret)); + } else if (!gather_helper.use_split_part_ && param.is_auto_sample_size_ && + OB_FAIL(adjust_auto_gather_param(partition_id_block_map, + param, gather_helper.use_split_part_))) { + LOG_WARN("failed to adjust auto gather param", K(ret)); } else if (OB_FAIL(check_need_split_gather(param, gather_helper))) { LOG_WARN("failed to check need split gather", K(ret)); } else { @@ -1904,7 +1908,7 @@ int ObDbmsStatsExecutor::adjsut_async_gather_param(const PartitionIdBlockMap &pa LOG_WARN("get unexpected error", K(ret), K(block_num_stat)); } else { int64_t total_row_cnt = block_num_stat->sstable_row_cnt_ + block_num_stat->memtable_row_cnt_; - if (total_row_cnt < param.async_full_table_size_) { + if (total_row_cnt < param.auto_sample_row_cnt_) { //do nothing } else if (param.part_level_ == share::schema::ObPartitionLevel::PARTITION_LEVEL_ONE || param.part_level_ == share::schema::ObPartitionLevel::PARTITION_LEVEL_TWO) { @@ -1928,7 +1932,7 @@ int ObDbmsStatsExecutor::adjsut_async_gather_param(const PartitionIdBlockMap &pa } else { int64_t row_cnt = block_num_stat->sstable_row_cnt_ + block_num_stat->memtable_row_cnt_; gather_scan_row_cnt += row_cnt; - if (row_cnt > param.async_full_table_size_) { + if (row_cnt > param.auto_sample_row_cnt_) { need_split_part = true; if (OB_FAIL(add_var_to_array_no_dup(no_derive_part_ids, param.subpart_infos_.at(i).first_part_id_))) { @@ -1994,7 +1998,7 @@ int ObDbmsStatsExecutor::adjsut_async_gather_param(const PartitionIdBlockMap &pa } else { int64_t row_cnt = block_num_stat->sstable_row_cnt_ + block_num_stat->memtable_row_cnt_; gather_scan_row_cnt += row_cnt; - if (row_cnt > param.async_full_table_size_) { + if (row_cnt > param.auto_sample_row_cnt_) { need_split_part = true; can_derive = false; } @@ -2038,6 +2042,75 @@ bool ObDbmsStatsExecutor::is_async_gather_partition_id(const int64_t partition_i return is_found; } +int ObDbmsStatsExecutor::adjust_auto_gather_param(const PartitionIdBlockMap &partition_id_block_map, + const ObTableStatParam ¶m, + bool &need_split_part) +{ + int ret = OB_SUCCESS; + if (param.is_auto_gather_) { + LOG_TRACE("begin to adjsut auto gather param", K(param)); + if (param.part_level_ == share::schema::ObPartitionLevel::PARTITION_LEVEL_ZERO) { + //do nohting + } else { + BlockNumStat *block_num_stat = NULL; + int64_t row_cnt = 0; + if (OB_FAIL(partition_id_block_map.get_refactored(param.global_part_id_, block_num_stat))) { + if (OB_LIKELY(OB_HASH_NOT_EXIST == ret)) { + ret = OB_SUCCESS; + } else { + LOG_WARN("failed to get refactored", K(ret)); + } + } else if (OB_ISNULL(block_num_stat)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(block_num_stat)); + } else if (OB_FALSE_IT(row_cnt = block_num_stat->sstable_row_cnt_ + block_num_stat->memtable_row_cnt_)) { + } else if (row_cnt < param.auto_sample_row_cnt_) { + // do nothing + } else { + for (int64_t i = 0; OB_SUCC(ret) && !need_split_part && i < param.subpart_infos_.count(); ++i) { + if (OB_FAIL(partition_id_block_map.get_refactored(param.subpart_infos_.at(i).part_id_, block_num_stat))) { + if (OB_LIKELY(OB_HASH_NOT_EXIST == ret)) { + ret = OB_SUCCESS; + } else { + LOG_WARN("failed to get refactored", K(ret)); + } + } else if (OB_ISNULL(block_num_stat)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(block_num_stat)); + } else if (OB_FALSE_IT(row_cnt = block_num_stat->sstable_row_cnt_ + block_num_stat->memtable_row_cnt_)) { + } else if (row_cnt < param.auto_sample_row_cnt_) { + //do nothing + } else { + need_split_part = true; + } + } + if (OB_SUCC(ret) && !need_split_part && param.part_stat_param_.need_modify_) { + for (int64_t i = 0; OB_SUCC(ret) && !need_split_part && i < param.part_infos_.count(); ++i) { + if (OB_FAIL(partition_id_block_map.get_refactored(param.part_infos_.at(i).part_id_, block_num_stat))) { + if (OB_LIKELY(OB_HASH_NOT_EXIST == ret)) { + ret = OB_SUCCESS; + } else { + LOG_WARN("failed to get refactored", K(ret)); + } + } else if (OB_ISNULL(block_num_stat)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(block_num_stat)); + } else if (OB_FALSE_IT(row_cnt = block_num_stat->sstable_row_cnt_ + block_num_stat->memtable_row_cnt_)) { + } else if (row_cnt < param.auto_sample_row_cnt_) { + //do nothing + } else { + need_split_part = true; + } + } + } + } + + } + LOG_TRACE("end to adjsut auto gather param", K(param), K(need_split_part)); + } + return ret; +} + } // namespace common } // namespace oceanbase diff --git a/src/share/stat/ob_dbms_stats_executor.h b/src/share/stat/ob_dbms_stats_executor.h index 0eb7f2431f..7763e97c8f 100644 --- a/src/share/stat/ob_dbms_stats_executor.h +++ b/src/share/stat/ob_dbms_stats_executor.h @@ -209,6 +209,10 @@ private: static bool is_async_gather_partition_id(const int64_t partition_id, const ObIArray *async_partition_ids); + static int adjust_auto_gather_param(const PartitionIdBlockMap &partition_id_block_map, + const ObTableStatParam ¶m, + bool &need_split_part); + }; diff --git a/src/share/stat/ob_dbms_stats_gather.cpp b/src/share/stat/ob_dbms_stats_gather.cpp index 34883a4003..f40b684314 100644 --- a/src/share/stat/ob_dbms_stats_gather.cpp +++ b/src/share/stat/ob_dbms_stats_gather.cpp @@ -23,6 +23,7 @@ #include "share/stat/ob_index_stats_estimator.h" #include "pl/sys_package/ob_dbms_stats.h" #include "share/stat/ob_opt_stat_gather_stat.h" +#include "share/stat/ob_min_max_estimator.h" namespace oceanbase { using namespace pl; namespace common { @@ -76,6 +77,30 @@ int ObDbmsStatsGather::gather_stats(ObExecContext &ctx, } } } else {/*do nothing*/} + + if (OB_SUCC(ret) && + param.sample_info_.is_specify_sample() && param.need_refine_min_max_) { + for (int64_t i = 0; OB_SUCC(ret) && i < opt_stats.count(); ++i) { + ObOptStatGatherParam new_param; + ObMinMaxEstimator min_max_est(ctx, *param.allocator_); + if (OB_ISNULL(opt_stats.at(i).table_stat_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(opt_stats.at(i).table_stat_)); + } else if (OB_FAIL(THIS_WORKER.check_status())) { + LOG_WARN("check status failed", KR(ret)); + } else if (opt_stats.at(i).table_stat_->get_row_count() <= 0) { + //empty table or empty partition, no need gather histogram, just skip. + } else if (OB_FAIL(new_param.assign(param))) { + LOG_WARN("failed to assign", K(ret)); + } else if (new_param.stat_level_ != TABLE_LEVEL && + OB_FAIL(ObDbmsStatsUtils::remove_stat_gather_param_partition_info(opt_stats.at(i).table_stat_->get_partition_id(), + new_param))) { + LOG_WARN("failed to remove stat gather param partition info", K(ret)); + } else if (OB_FAIL(min_max_est.estimate(new_param, opt_stats.at(i)))) { + LOG_WARN("failed to estimate hybrid histogram", K(ret)); + } + } + } } return ret; } @@ -268,16 +293,22 @@ int ObDbmsStatsGather::refine_sample_block_for_async_gather(const ObIArray DEFAULT_ASYNC_MAX_SCAN_ROWCOUNT)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected error", K(sstable_row_cnt), K(memtable_row_cnt), K(opt_stats), K(param)); - } else if (opt_stats.count() == 1) { - if (param.async_full_table_size_ < sstable_row_cnt + memtable_row_cnt) { - double sample_ratio = 100.0; - sample_ratio = 1.0 * param.async_gather_sample_size_ / (sstable_row_cnt + memtable_row_cnt) * 100.0; - if (sample_ratio > 0.0 && sample_ratio < 100.0) { - param.sample_info_.set_percent(sample_ratio); - param.sample_info_.set_is_block_sample(true); - } - LOG_INFO("decide async gather stats need sample", K(param), K(opt_stats)); + } + } + + if (OB_SUCC(ret) && + (param.is_async_gather_ || param.is_auto_sample_size_) && + !param.sample_info_.is_specify_sample() && opt_stats.count() == 1) { + int64_t sstable_row_cnt = opt_stats.at(0).table_stat_->get_sstable_row_count(); + int64_t memtable_row_cnt = opt_stats.at(0).table_stat_->get_memtable_row_count(); + if (param.auto_sample_row_cnt_ < sstable_row_cnt + memtable_row_cnt) { + double sample_ratio = 100.0; + sample_ratio = 1.0 * param.auto_sample_row_cnt_ / (sstable_row_cnt + memtable_row_cnt) * 100.0; + if (sample_ratio > 0.0 && sample_ratio < 100.0) { + param.sample_info_.set_percent(sample_ratio); + param.sample_info_.set_is_block_sample(true); } + LOG_INFO("decide auto gather stats need sample", K(param), K(opt_stats)); } } return ret; diff --git a/src/share/stat/ob_dbms_stats_maintenance_window.cpp b/src/share/stat/ob_dbms_stats_maintenance_window.cpp index 3d6e62a26d..6f43498420 100644 --- a/src/share/stat/ob_dbms_stats_maintenance_window.cpp +++ b/src/share/stat/ob_dbms_stats_maintenance_window.cpp @@ -67,6 +67,7 @@ const char *windows_name[DAY_OF_WEEK] = {"MONDAY_WINDOW", const char *opt_stats_history_manager = "OPT_STATS_HISTORY_MANAGER"; const char *async_gather_stats_job_proc = "ASYNC_GATHER_STATS_JOB_PROC"; const int64_t OPT_STATS_HISTORY_MANAGER_JOB_ID = 8; +const char *spm_stats_manager = "SPM_STATS_MANAGER"; int ObDbmsStatsMaintenanceWindow::get_stats_maintenance_window_jobs_sql(const ObSysVariableSchema &sys_variable, const uint64_t tenant_id, @@ -180,6 +181,26 @@ int ObDbmsStatsMaintenanceWindow::get_stats_maintenance_window_jobs_sql(const Ob } } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(get_spm_stats_job_sql(is_oracle_mode, tenant_id, job_id++, + offset_sec, exec_env, tmp_sql))) { + LOG_WARN("failed to get stats history manager job sql", K(ret)); + } else if (OB_FAIL(raw_sql.append_fmt(", (%s)", tmp_sql.ptr()))) { + LOG_WARN("failed to append sql", K(ret)); + } else { + ++ expected_affected_rows; + tmp_sql.reset(); + if (OB_FAIL(get_spm_stats_job_sql(is_oracle_mode, tenant_id, 0, + offset_sec, exec_env, tmp_sql))) { + LOG_WARN("failed to get stats history manager job sql", K(ret)); + } else if (OB_FAIL(raw_sql.append_fmt(", (%s)", tmp_sql.ptr()))) { + LOG_WARN("failed to append sql", K(ret)); + } else { + ++ expected_affected_rows; + tmp_sql.reset(); + } + } + //set dummy guard job if (OB_FAIL(ret)) { } else if (OB_FAIL(get_dummy_guard_job_sql(tenant_id, job_id, tmp_sql))) { @@ -364,6 +385,70 @@ int ObDbmsStatsMaintenanceWindow::get_dummy_guard_job_sql(const uint64_t tenant_ return ret; } +int ObDbmsStatsMaintenanceWindow::get_spm_stats_job_sql(const bool is_oracle_mode, + const uint64_t tenant_id, + const int64_t job_id, + const int64_t offset_sec, + const ObString &exec_env, + ObSqlString &raw_sql) +{ + int ret = OB_SUCCESS; + + ObTime ob_time; + int64_t current_time = ObTimeUtility::current_time(); + if (OB_UNLIKELY(current_time <= 0)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(current_time)); + } else if (OB_FAIL(ObTimeConverter::usec_to_ob_time(current_time + offset_sec * 1000000, ob_time))) { + LOG_WARN("failed to usec to ob time", K(ret), K(current_time)); + } else { + // handle spm stats at 1:00 every day + int64_t default_start_hour = 1; + int64_t total_hour_with_trunc = current_time / USEC_OF_HOUR; + int64_t current_hour = ob_time.parts_[DT_HOUR]; + int64_t offset_hour = 1 * HOUR_OF_DAY + default_start_hour - current_hour; + int64_t start_usec = (total_hour_with_trunc + offset_hour) * USEC_OF_HOUR; + LOG_INFO("succeed to get spm job info", K(ob_time), K(start_usec), K(offset_hour), K(current_time), + K(total_hour_with_trunc), K(current_hour), + K(default_start_hour)); + int64_t interval_ts = DEFAULT_DAY_INTERVAL_USEC; + int64_t end_date = 64060560000000000;//4000-01-01 00:00:00.000000 + share::ObDMLSqlSplicer dml; + OZ (dml.add_pk_column("tenant_id", share::schema::ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id))); + OZ (dml.add_column("job_name", ObHexEscapeSqlStr(ObString(spm_stats_manager)))); + OZ (dml.add_pk_column("job", job_id)); + OZ (dml.add_column("lowner", is_oracle_mode ? ObHexEscapeSqlStr("SYS") : ObHexEscapeSqlStr("root@%"))); + OZ (dml.add_column("powner", is_oracle_mode ? ObHexEscapeSqlStr("SYS") : ObHexEscapeSqlStr("root@%"))); + OZ (dml.add_column("cowner", is_oracle_mode ? ObHexEscapeSqlStr("SYS") : ObHexEscapeSqlStr("oceanbase"))); + OZ (dml.add_time_column("next_date", start_usec)); + OZ (dml.add_column("total", 0)); + OZ (dml.add_column("`interval#`", ObHexEscapeSqlStr(ObString("FREQ=DAYLY; INTERVAL=1")))); + OZ (dml.add_column("flag", 0)); + OZ (dml.add_column("what", ObHexEscapeSqlStr("DBMS_SPM.HANDLE_SPM_STATS_JOB_PROC()"))); + OZ (dml.add_column("nlsenv", ObHexEscapeSqlStr(ObString("")))); + OZ (dml.add_column("field1", ObHexEscapeSqlStr(ObString("")))); + OZ (dml.add_column("exec_env", ObHexEscapeSqlStr(exec_env))); + OZ (dml.add_column("job_style", ObHexEscapeSqlStr(ObString("REGULER")))); + OZ (dml.add_column("program_name", ObHexEscapeSqlStr(ObString("")))); + OZ (dml.add_column("job_type", ObHexEscapeSqlStr(ObString("STORED_PROCEDURE")))); + OZ (dml.add_column("job_action", ObHexEscapeSqlStr("DBMS_SPM.HANDLE_SPM_STATS_JOB_PROC()"))); + OZ (dml.add_column("number_of_argument", 0)); + OZ (dml.add_raw_time_column("start_date", start_usec)); + OZ (dml.add_column("repeat_interval", ObHexEscapeSqlStr(ObString("FREQ=DAYLY; INTERVAL=1")))); + OZ (dml.add_raw_time_column("end_date", end_date)); + OZ (dml.add_column("job_class", ObHexEscapeSqlStr(ObString("DEFAULT_JOB_CLASS")))); + OZ (dml.add_column("enabled", true)); + OZ (dml.add_column("auto_drop", false)); + OZ (dml.add_column("comments", ObHexEscapeSqlStr(ObString("used to handle spm stats")))); + OZ (dml.add_column("credential_name", ObHexEscapeSqlStr(ObString("")))); + OZ (dml.add_column("destination_name", ObHexEscapeSqlStr(ObString("")))); + OZ (dml.add_column("interval_ts", interval_ts)); + OZ (dml.add_column("max_run_duration", 10 * 60)); // 10 min + OZ (dml.splice_values(raw_sql)); + } + return ret; +} + /* like Oracle, we set 7 windows: * WINDOW_NAME REPEAT_INTERVAL DURATION * MONDAY_WINDOW freq=daily;byday=MON;byhour=22; 4 hours @@ -653,11 +738,11 @@ int ObDbmsStatsMaintenanceWindow::get_async_gather_stats_job_for_upgrade(common: bool is_join_exists = false; //bug: ObArenaAllocator allocator("AsyncStatsJob"); - if (OB_FAIL(check_async_gather_job_exists(sql_proxy, tenant_id, is_join_exists))) { + if (OB_FAIL(check_job_exists(sql_proxy, tenant_id, async_gather_stats_job_proc, is_join_exists))) { LOG_WARN("failed to check async gather job exists", K(ret)); } else if (is_join_exists) { //do nothing - } else if (OB_FAIL(get_async_gather_stats_job_id_and_exec_env(sql_proxy, allocator, tenant_id, job_id, exec_env))) { + } else if (OB_FAIL(get_next_job_id_and_exec_env(sql_proxy, allocator, tenant_id, job_id, exec_env))) { LOG_WARN("failed to get async gather stats job id and exec env", K(ret)); } else if (OB_UNLIKELY(job_id > dbms_scheduler::ObDBMSSchedTableOperator::JOB_ID_OFFSET || exec_env.empty())) { @@ -684,11 +769,11 @@ int ObDbmsStatsMaintenanceWindow::get_async_gather_stats_job_for_upgrade(common: return ret; } -int ObDbmsStatsMaintenanceWindow::get_async_gather_stats_job_id_and_exec_env(common::ObMySQLProxy *sql_proxy, - ObIAllocator &allocator, - const uint64_t tenant_id, - int64_t &job_id, - ObString &exec_env) +int ObDbmsStatsMaintenanceWindow::get_next_job_id_and_exec_env(common::ObMySQLProxy *sql_proxy, + ObIAllocator &allocator, + const uint64_t tenant_id, + int64_t &job_id, + ObString &exec_env) { int ret = OB_SUCCESS; ObSqlString select_sql; @@ -748,14 +833,15 @@ int ObDbmsStatsMaintenanceWindow::get_async_gather_stats_job_id_and_exec_env(com } } } - LOG_INFO("succeed to get async gather stats job id and exec env", K(ret), K(select_sql), K(job_id), K(exec_env)); + LOG_INFO("succeed to get next job id and exec env", K(ret), K(select_sql), K(job_id), K(exec_env)); } return ret; } -int ObDbmsStatsMaintenanceWindow::check_async_gather_job_exists(common::ObMySQLProxy *sql_proxy, - const uint64_t tenant_id, - bool &is_join_exists) +int ObDbmsStatsMaintenanceWindow::check_job_exists(common::ObMySQLProxy *sql_proxy, + const uint64_t tenant_id, + const char* job_name, + bool &is_join_exists) { int ret = OB_SUCCESS; is_join_exists = false; @@ -764,7 +850,7 @@ int ObDbmsStatsMaintenanceWindow::check_async_gather_job_exists(common::ObMySQLP if (OB_FAIL(select_sql.append_fmt("SELECT count(*) FROM %s WHERE tenant_id = %ld and job_name = '%s';", share::OB_ALL_TENANT_SCHEDULER_JOB_TNAME, share::schema::ObSchemaUtils::get_extract_tenant_id(tenant_id, tenant_id), - async_gather_stats_job_proc))) { + job_name))) { LOG_WARN("failed to append fmt", K(ret)); } else { SMART_VAR(ObMySQLProxy::MySQLResult, proxy_result) { @@ -801,7 +887,52 @@ int ObDbmsStatsMaintenanceWindow::check_async_gather_job_exists(common::ObMySQLP } } } - LOG_INFO("succeed to check async gather job exists", K(ret), K(select_sql), K(is_join_exists), K(row_count)); + LOG_INFO("succeed to check job exists", K(ret), K(select_sql), K(is_join_exists), K(row_count)); + } + return ret; +} + +int ObDbmsStatsMaintenanceWindow::get_spm_stats_upgrade_jobs_sql(common::ObMySQLProxy *sql_proxy, + const ObSysVariableSchema &sys_variable, + const uint64_t tenant_id, + const bool is_oracle_mode, + ObSqlString &raw_sql) +{ + int ret = OB_SUCCESS; + char buf[OB_MAX_PROC_ENV_LENGTH]; + ObSqlString tmp_sql; + int64_t pos = 0; + int32_t offset_sec = 0; + int64_t job_id = 0; + ObString tmp_exec_env; + ObArenaAllocator allocator("SpmSchedularJob"); + if (OB_FAIL(get_next_job_id_and_exec_env(sql_proxy, allocator, tenant_id, job_id, tmp_exec_env))) { + LOG_WARN("failed to get async gather stats job id and exec env", K(ret)); + } else if (OB_UNLIKELY(job_id > dbms_scheduler::ObDBMSSchedTableOperator::JOB_ID_OFFSET || + tmp_exec_env.empty())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(job_id), K(tmp_exec_env)); + } else if (OB_FAIL(raw_sql.assign_fmt("INSERT INTO %s( "ALL_TENANT_SCHEDULER_JOB_COLUMN_NAME") VALUES ", + share::OB_ALL_TENANT_SCHEDULER_JOB_TNAME))) { + LOG_WARN("failed to assign fmt", K(ret)); + } else if (OB_FAIL(sql::ObExecEnv::gen_exec_env(sys_variable, buf, OB_MAX_PROC_ENV_LENGTH, pos))) { + LOG_WARN("failed to gen exec env", K(ret)); + } else if (OB_FAIL(get_time_zone_offset(sys_variable, tenant_id, offset_sec))) { + LOG_WARN("failed to get time zone offset", K(ret)); + } else { + ObString exec_env(pos, buf); + if (OB_FAIL(get_spm_stats_job_sql(is_oracle_mode, tenant_id, job_id, + offset_sec, exec_env, tmp_sql))) { + LOG_WARN("failed to get stats history manager job sql", K(ret)); + } else if (OB_FAIL(raw_sql.append_fmt(" (%s)", tmp_sql.ptr()))) { + LOG_WARN("failed to append sql", K(ret)); + } else if (OB_FALSE_IT(tmp_sql.reset())) { + } else if (OB_FAIL(get_spm_stats_job_sql(is_oracle_mode, tenant_id, 0, + offset_sec, exec_env, tmp_sql))) { + LOG_WARN("failed to get stats history manager job sql", K(ret)); + } else if (OB_FAIL(raw_sql.append_fmt(", (%s)", tmp_sql.ptr()))) { + LOG_WARN("failed to append sql", K(ret)); + } } return ret; } diff --git a/src/share/stat/ob_dbms_stats_maintenance_window.h b/src/share/stat/ob_dbms_stats_maintenance_window.h index 8753ca57f8..d2d326cc55 100644 --- a/src/share/stat/ob_dbms_stats_maintenance_window.h +++ b/src/share/stat/ob_dbms_stats_maintenance_window.h @@ -61,6 +61,18 @@ public: static int get_async_gather_stats_job_for_upgrade(common::ObMySQLProxy *sql_proxy, const uint64_t tenant_id, ObSqlString &sql); + + static int check_job_exists(common::ObMySQLProxy *sql_proxy, + const uint64_t tenant_id, + const char* job_name, + bool &is_join_exists); + + static int get_spm_stats_upgrade_jobs_sql(common::ObMySQLProxy *sql_proxy, + const ObSysVariableSchema &sys_variable, + const uint64_t tenant_id, + const bool is_oracle_mode, + ObSqlString &raw_sql); + static int get_time_zone_offset(const share::schema::ObSysVariableSchema &sys_variable, const uint64_t tenant_id, int32_t &offset_sec); @@ -86,6 +98,12 @@ private: const int64_t job_id, const ObString &exec_env, ObSqlString &raw_sql); + static int get_spm_stats_job_sql(const bool is_oracle_mode, + const uint64_t tenant_id, + const int64_t job_id, + const int64_t offset_sec, + const ObString &exec_env, + ObSqlString &raw_sql); static int get_dummy_guard_job_sql(const uint64_t tenant_id, const int64_t job_id, @@ -102,14 +120,11 @@ private: const int64_t job_id, const ObString &exec_env, ObSqlString &raw_sql); - static int get_async_gather_stats_job_id_and_exec_env(common::ObMySQLProxy *sql_proxy, - ObIAllocator &allocator, - const uint64_t tenant_id, - int64_t &job_id, - ObString &exec_env); - static int check_async_gather_job_exists(common::ObMySQLProxy *sql_proxy, - const uint64_t tenant_id, - bool &is_join_exists); + static int get_next_job_id_and_exec_env(common::ObMySQLProxy *sql_proxy, + ObIAllocator &allocator, + const uint64_t tenant_id, + int64_t &job_id, + ObString &exec_env); }; diff --git a/src/share/stat/ob_dbms_stats_preferences.cpp b/src/share/stat/ob_dbms_stats_preferences.cpp index abbb5cab77..9b4b70a9e2 100644 --- a/src/share/stat/ob_dbms_stats_preferences.cpp +++ b/src/share/stat/ob_dbms_stats_preferences.cpp @@ -415,7 +415,8 @@ int ObDbmsStatsPreferences::gen_init_global_prefs_sql(ObSqlString &raw_sql, init_perfs_value(ObAsyncGatherFullTableSizePrefs, false/*last value*/);//init async gather full table size init_perfs_value(ObAsyncStaleMaxTableSizePrefs, false/*last value*/);//init async stale max table size init_perfs_value(ObHistEstPercentPrefs, false/*last value*/);//init hist_est_percent - init_perfs_value(ObHistBlockSamplePrefs, true/*last value*/);//init hist_block_sample + init_perfs_value(ObHistBlockSamplePrefs, false/*last value*/);//init hist_block_sample + init_perfs_value(ObAutoSampleRowCountPrefs, true/*last value*/);//init auto_sample_row_count if (OB_SUCC(ret)) { if (OB_FAIL(raw_sql.append_fmt(INIT_GLOBAL_PREFS, share::OB_ALL_OPTSTAT_GLOBAL_PREFS_TNAME, @@ -678,7 +679,9 @@ int ObEstimatePercentPrefs::check_pref_value_validity(ObTableStatParam *param/*d int ret = OB_SUCCESS; if (!pvalue_.empty()) { if (0 == pvalue_.case_compare("DBMS_STATS.AUTO_SAMPLE_SIZE")) { - /*do nothing*/ + if (param != NULL && param->is_auto_gather_) { + param->is_auto_sample_size_ = true; + } } else { ObObj src_obj; ObObj dest_obj; @@ -995,7 +998,7 @@ int ObAsyncGatherSampleSizePrefs::check_pref_value_validity(ObTableStatParam *pa ret = OB_ERR_DBMS_STATS_PL; LOG_WARN("Illegal async gather sample size", K(ret), K(sample_size)); } else if (param != NULL) { - param->async_gather_sample_size_ = sample_size; + } else {/*do nothing*/} if (OB_FAIL(ret)) { ret = OB_ERR_DBMS_STATS_PL; @@ -1113,6 +1116,38 @@ int ObHistBlockSamplePrefs::check_pref_value_validity(ObTableStatParam *param/*d return ret; } +int ObAutoSampleRowCountPrefs::check_pref_value_validity(ObTableStatParam *param) +{ + int ret = OB_SUCCESS; + if (!pvalue_.empty()) { + ObObj src_obj; + ObObj dest_obj; + src_obj.set_string(ObVarcharType, pvalue_); + ObArenaAllocator calc_buf("AutoRowCnt"); + ObCastCtx cast_ctx(&calc_buf, NULL, CM_NONE, ObCharset::get_system_collation()); + int64_t row_count = 0; + int64_t int_part = 0; + if (OB_FAIL(ObObjCaster::to_type(ObNumberType, cast_ctx, src_obj, dest_obj))) { + LOG_WARN("failed to type", K(ret), K(src_obj)); + } else if (!dest_obj.get_number().is_valid_int64(int_part)) { + ret = OB_ERR_DBMS_STATS_PL; + LOG_WARN("Illegal auto sample row count must interger", K(ret)); + } else if (OB_FAIL(dest_obj.get_number().extract_valid_int64_with_trunc(row_count))) { + LOG_WARN("failed to extract valid int64 with trunc", K(ret), K(src_obj)); + } else if (row_count < -1 || (row_count > 0 && row_count < MAGIC_MIN_SAMPLE_SIZE)) { + ret = OB_ERR_DBMS_STATS_PL; + LOG_WARN("Illegal auto sample row count must greater than 2500", K(ret), K(row_count)); + } else if (NULL != param) { + param->auto_sample_row_cnt_ = row_count; + } + if (OB_FAIL(ret)) { + ret = OB_ERR_DBMS_STATS_PL; + LOG_WARN("Illegal auto sample row count", K(ret), K(pvalue_)); + LOG_USER_ERROR(OB_ERR_DBMS_STATS_PL, "Illegal auto sample row count."); + } + } + return ret; +} #define ISSPACE(c) ((c) == ' ' || (c) == '\n' || (c) == '\r' || (c) == '\t' || (c) == '\f' || (c) == '\v') //compatible oracle, global prefs/schema prefs just only can set "for all columns...." @@ -1274,5 +1309,30 @@ int ObDbmsStatsPreferences::get_online_estimate_percent_for_upgrade(ObSqlString return ret; } +int ObDbmsStatsPreferences::get_extra_stats_perfs_for_upgrade_425(ObSqlString &raw_sql) +{ + int ret = OB_SUCCESS; + const char *null_str = "NULL"; + const char *time_str = "CURRENT_TIMESTAMP"; + ObSqlString value_str; + ObAutoSampleRowCountPrefs prefs; + if (OB_ISNULL(prefs.get_stat_pref_name()) || OB_ISNULL(prefs.get_stat_pref_default_value())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(prefs.get_stat_pref_name()), + K(prefs.get_stat_pref_default_value())); + } else if (OB_FAIL(value_str.append_fmt("('%s', %s, %s, '%s');", + prefs.get_stat_pref_name(), + null_str, + time_str, + "0"))) { + LOG_WARN("failed to append", K(ret)); + } else if (OB_FAIL(raw_sql.append_fmt(INIT_GLOBAL_PREFS, + share::OB_ALL_OPTSTAT_GLOBAL_PREFS_TNAME, + value_str.ptr()))) { + LOG_WARN("failed to append fmt", K(ret)); + } + return ret; +} + } // namespace common } // namespace oceanbase diff --git a/src/share/stat/ob_dbms_stats_preferences.h b/src/share/stat/ob_dbms_stats_preferences.h index 4dd94d3383..8dbe8cb4fc 100644 --- a/src/share/stat/ob_dbms_stats_preferences.h +++ b/src/share/stat/ob_dbms_stats_preferences.h @@ -319,6 +319,19 @@ class ObHistBlockSamplePrefs : public ObStatPrefs virtual const char* get_stat_pref_default_value() const { return "FALSE"; } }; +class ObAutoSampleRowCountPrefs : public ObStatPrefs +{ + public: + ObAutoSampleRowCountPrefs() : ObStatPrefs() {} + ObAutoSampleRowCountPrefs(ObIAllocator *alloc, + ObSQLSessionInfo *session_info, + const ObString &pvalue): + ObStatPrefs(alloc, session_info, pvalue) {} + virtual int check_pref_value_validity(ObTableStatParam *param = NULL) override; + virtual const char* get_stat_pref_name() const { return "AUTO_SAMPLE_ROW_COUNT"; } + virtual const char* get_stat_pref_default_value() const { return "5000000"; } +}; + template static int new_stat_prefs(ObIAllocator &allocator, ObSQLSessionInfo *session_info, const ObString &opt_value, T *&src) @@ -369,6 +382,8 @@ public: static int get_extra_stats_perfs_for_upgrade(ObSqlString &sql); + static int get_extra_stats_perfs_for_upgrade_425(ObSqlString &sql); + private: static int do_get_prefs(ObMySQLProxy *mysql_proxy, ObIAllocator &allocator, diff --git a/src/share/stat/ob_dbms_stats_utils.cpp b/src/share/stat/ob_dbms_stats_utils.cpp index 0a132f2284..88ded466a7 100644 --- a/src/share/stat/ob_dbms_stats_utils.cpp +++ b/src/share/stat/ob_dbms_stats_utils.cpp @@ -1106,12 +1106,14 @@ int ObDbmsStatsUtils::prepare_gather_stat_param(const ObTableStatParam ¶m, gather_param.gather_vectorize_ = gather_vectorize; gather_param.use_column_store_ = use_column_store; gather_param.is_async_gather_ = param.is_async_gather_; - gather_param.async_gather_sample_size_ = param.async_gather_sample_size_; gather_param.async_full_table_size_ = param.async_full_table_size_; gather_param.hist_sample_info_.is_sample_ = param.hist_sample_info_.is_sample_; gather_param.hist_sample_info_.is_block_sample_ = param.hist_sample_info_.is_block_sample_; gather_param.hist_sample_info_.sample_type_ = param.hist_sample_info_.sample_type_; gather_param.hist_sample_info_.sample_value_ = param.hist_sample_info_.sample_value_; + gather_param.is_auto_sample_size_ = param.is_auto_sample_size_; + gather_param.auto_sample_row_cnt_ = param.auto_sample_row_cnt_; + gather_param.need_refine_min_max_ = param.need_refine_min_max_; gather_param.is_global_index_ = param.is_global_index_; gather_param.data_table_id_ = param.data_table_id_; gather_param.part_level_ = param.part_level_; diff --git a/src/share/stat/ob_incremental_stat_estimator.cpp b/src/share/stat/ob_incremental_stat_estimator.cpp index b818f5d758..be5fe5ab18 100644 --- a/src/share/stat/ob_incremental_stat_estimator.cpp +++ b/src/share/stat/ob_incremental_stat_estimator.cpp @@ -22,6 +22,7 @@ #include "pl/sys_package/ob_dbms_stats.h" #include "share/stat/ob_dbms_stats_history_manager.h" #include "share/rc/ob_tenant_base.h" +#include "sql/optimizer/ob_opt_selectivity.h" namespace oceanbase { using namespace pl; @@ -536,6 +537,7 @@ int ObIncrementalStatEstimator::derive_global_tbl_stat(ObIAllocator &alloc, } else { table_stat = new (ptr) ObOptTableStat(); ObGlobalTableStat global_tstat; + int64_t sample_size = 0; for (int64_t i = 0; OB_SUCC(ret) && i < part_opt_stats.count(); ++i) { ObOptTableStat *opt_tbl_stat = part_opt_stats.at(i).table_stat_; if (OB_ISNULL(opt_tbl_stat)) { @@ -547,6 +549,7 @@ int ObIncrementalStatEstimator::derive_global_tbl_stat(ObIAllocator &alloc, opt_tbl_stat->get_data_size(), opt_tbl_stat->get_macro_block_num(), opt_tbl_stat->get_micro_block_num()); + sample_size += opt_tbl_stat->get_sample_size(); } } if (OB_SUCC(ret)) { @@ -555,7 +558,7 @@ int ObIncrementalStatEstimator::derive_global_tbl_stat(ObIAllocator &alloc, table_stat->set_partition_id(partition_id); table_stat->set_object_type(approx_level); table_stat->set_row_count(global_tstat.get_row_count()); - table_stat->set_sample_size(global_tstat.get_row_count()); + table_stat->set_sample_size(sample_size); table_stat->set_avg_row_size(global_tstat.get_avg_row_size()); table_stat->set_data_size(global_tstat.get_avg_data_size()); table_stat->set_macro_block_num(global_tstat.get_macro_block_count()); @@ -603,6 +606,8 @@ int ObIncrementalStatEstimator::derive_global_col_stat(ObExecContext &ctx, ObGlobalNdvEval ndv_eval; ObGlobalAvglenEval avglen_eval; ObSEArray all_part_histograms; + int64_t sample_size = 0; + int64_t total_row_cnt = 0; int64_t max_bucket_num = param.column_params_.at(i).bucket_num_; for (int64_t j = 0; OB_SUCC(ret) && j < part_cnt; ++j) { ObOptColumnStat *opt_col_stat = NULL; @@ -623,6 +628,8 @@ int ObIncrementalStatEstimator::derive_global_col_stat(ObExecContext &ctx, ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(part_opt_stats.at(j).column_stats_), K(param.column_params_.at(i))); + } else if (OB_FALSE_IT(sample_size += opt_tab_stat->get_sample_size())) { + } else if (OB_FALSE_IT(total_row_cnt += opt_tab_stat->get_row_count())) { } else if (opt_col_stat->get_num_distinct() == 0 && opt_col_stat->get_num_null() == 0) { /*do nothing*/ } else if (need_derive_hist && opt_col_stat->get_histogram().is_valid() && @@ -642,6 +649,7 @@ int ObIncrementalStatEstimator::derive_global_col_stat(ObExecContext &ctx, } } if (OB_SUCC(ret)) { + int64_t num_distinct = ObOptSelectivity::scale_distinct(total_row_cnt, sample_size, ndv_eval.get()); col_stat->set_table_id(param.column_params_.at(i).need_basic_stat() ? param.table_id_ : OB_INVALID_ID); col_stat->set_partition_id(partition_id); col_stat->set_column_id(param.column_params_.at(i).column_id_); @@ -649,7 +657,7 @@ int ObIncrementalStatEstimator::derive_global_col_stat(ObExecContext &ctx, col_stat->set_num_null(null_eval.get()); col_stat->set_num_not_null(not_null_eval.get()); col_stat->get_histogram().set_sample_size(not_null_eval.get()); - col_stat->set_num_distinct(ndv_eval.get()); + col_stat->set_num_distinct(num_distinct); col_stat->set_avg_len(avglen_eval.get()); ndv_eval.get_llc_bitmap(col_stat->get_llc_bitmap(), col_stat->get_llc_bitmap_size()); col_stat->set_llc_bitmap_size(ObOptColumnStat::NUM_LLC_BUCKET); diff --git a/src/share/stat/ob_min_max_estimator.cpp b/src/share/stat/ob_min_max_estimator.cpp new file mode 100644 index 0000000000..3a1175e2be --- /dev/null +++ b/src/share/stat/ob_min_max_estimator.cpp @@ -0,0 +1,194 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ +#define USING_LOG_PREFIX SQL_ENG +#include "share/stat/ob_min_max_estimator.h" +#include "share/stat/ob_dbms_stats_utils.h" +namespace oceanbase +{ +namespace common +{ + +int ObStatMinMaxSubquery::gen_expr(char *buf, const int64_t buf_len, int64_t &pos) +{ + int ret = OB_SUCCESS; + char hint[OB_MAX_TABLE_NAME_LENGTH + 10]; + int64_t hint_pos = 0; + if (OB_ISNULL(col_param_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (col_param_->index_name_.empty() && + OB_FAIL(databuff_printf(hint, sizeof(hint), hint_pos, "FULL(T)"))) { + LOG_WARN("failed to print buf", K(ret)); + } else if (!col_param_->index_name_.empty() && + OB_FAIL(databuff_printf(hint, sizeof(hint), hint_pos, "INDEX(T %.*s)", + col_param_->index_name_.length(), + col_param_->index_name_.ptr()))) { + LOG_WARN("failed to print buf", K(ret)); + } else if (OB_FAIL(databuff_printf(buf, buf_len, pos, + lib::is_oracle_mode() ? + " (SELECT /*+ %.*s */ %.*s FROM \"%.*s\".\"%.*s\" %.*s T WHERE %.*s IS NOT NULL ORDER BY 1 %s FETCH FIRST 1 ROWS ONLY)" : + " (SELECT /*+ %.*s */ %.*s FROM `%.*s`.`%.*s` %.*s T WHERE %.*s IS NOT NULL ORDER BY 1 %s LIMIT 1)", + (int)hint_pos, + hint, + col_param_->column_name_.length(), + col_param_->column_name_.ptr(), + db_name_.length(), + db_name_.ptr(), + from_table_.length(), + from_table_.ptr(), + partition_string_.length(), + partition_string_.ptr(), + col_param_->column_name_.length(), + col_param_->column_name_.ptr(), + is_min_ ? "ASC" : "DESC"))) { + LOG_WARN("failed to print buf", K(ret)); + } + return ret; +} + +int ObStatMinMaxSubquery::decode(ObObj &obj, ObIAllocator &allocator) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(col_stat_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("col stat is not given", K(ret), K(col_stat_)); + } else if (OB_FAIL(ObDbmsStatsUtils::truncate_string_for_opt_stats(obj, allocator))) { + LOG_WARN("fail to truncate string", K(ret)); + } else if (is_min_) { + col_stat_->set_min_value(obj); + } else { + col_stat_->set_max_value(obj); + } + return ret; +} + +ObMinMaxEstimator::ObMinMaxEstimator(ObExecContext &ctx, ObIAllocator &allocator) + : ObBasicStatsEstimator(ctx, allocator) +{} + +int ObMinMaxEstimator::add_min_max_stat_items(ObIAllocator &allocator, + const ObOptStatGatherParam ¶m, + const ObIArray &column_params, + ObOptStat &opt_stat) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(opt_stat.table_stat_) || + OB_UNLIKELY(opt_stat.column_stats_.count() != column_params.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(opt_stat), K(column_params)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < column_params.count(); ++i) { + const ObColumnStatParam *col_param = &column_params.at(i); + if (OB_ISNULL(opt_stat.column_stats_.at(i)) || + OB_UNLIKELY(col_param->column_id_ != opt_stat.column_stats_.at(i)->get_column_id())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), KPC(opt_stat.column_stats_.at(i)), KPC(col_param)); + } else if (!col_param->need_refine_min_max()) { + //do nothing + } else { + void *p = NULL; + ObStatMinMaxSubquery *min_subquery = NULL; + ObStatMinMaxSubquery *max_subquery = NULL; + if (OB_ISNULL(p = allocator.alloc(sizeof(ObStatMinMaxSubquery)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate memory failed", K(ret)); + } else if (OB_FALSE_IT(min_subquery = new(p) ObStatMinMaxSubquery(col_param, + opt_stat.column_stats_.at(i), + db_name_, + from_table_, + partition_string_, + true))) { + } else if (OB_FAIL(stat_items_.push_back(min_subquery))) { + LOG_WARN("failed to push back array", K(ret)); + } else if (OB_ISNULL(p = allocator.alloc(sizeof(ObStatMinMaxSubquery)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("allocate memory failed", K(ret)); + } else if (OB_FALSE_IT(max_subquery = new(p) ObStatMinMaxSubquery(col_param, + opt_stat.column_stats_.at(i), + db_name_, + from_table_, + partition_string_, + false))) { + } else if (OB_FAIL(stat_items_.push_back(max_subquery))) { + LOG_WARN("failed to push back array", K(ret)); + } + } + } + } + return ret; +} + +int ObMinMaxEstimator::estimate(const ObOptStatGatherParam ¶m, + ObOptStat &opt_stat) +{ + int ret = OB_SUCCESS; + ObArenaAllocator allocator("ObMinMaxEst", OB_MALLOC_NORMAL_BLOCK_SIZE, param.tenant_id_); + ObString no_rewrite("NO_REWRITE USE_PLAN_CACHE(NONE) DBMS_STATS OPT_PARAM('ROWSETS_MAX_ROWS', 256)"); + ObSqlString raw_sql; + int64_t duration_time = -1; + ObSEArray tmp_opt_stats; + if (OB_FAIL(add_from_table(param.db_name_, param.tab_name_))) { + LOG_WARN("failed to add from table", K(ret)); + } else if (OB_UNLIKELY(param.partition_infos_.count() > 1)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected error", K(ret), K(param)); + } else if (!param.partition_infos_.empty() && + OB_FAIL(fill_partition_info(allocator, param.partition_infos_.at(0).part_name_))) { + LOG_WARN("failed to add partition info", K(ret)); + } else if (OB_FAIL(add_min_max_stat_items(allocator, + param, + param.column_params_, + opt_stat))) { + LOG_WARN("failed to add min max stat items", K(ret)); + } else if (get_item_size() <= 0) { + // do nothing + } else if (OB_FAIL(add_hint(no_rewrite, allocator))) { + LOG_WARN("failed to add no_rewrite", K(ret)); + } else if (OB_FAIL(ObDbmsStatsUtils::get_valid_duration_time(param.gather_start_time_, + param.max_duration_time_, + duration_time))) { + LOG_WARN("failed to get valid duration time", K(ret)); + } else if (OB_FAIL(fill_query_timeout_info(allocator, duration_time))) { + LOG_WARN("failed to fill query timeout info", K(ret)); + } else if (OB_FAIL(pack_sql(raw_sql))) { + LOG_WARN("failed to pack raw sql", K(ret)); + } else if (OB_FAIL(tmp_opt_stats.push_back(opt_stat))) { + LOG_WARN("failed to push back", K(ret)); + } else if (OB_FAIL(do_estimate(param.tenant_id_, raw_sql.string(), false, + opt_stat, tmp_opt_stats))) { + LOG_WARN("failed to evaluate basic stats", K(ret)); + } else { + LOG_TRACE("succeed to gather min max value from index", K(opt_stat.column_stats_)); + } + stat_items_.reuse(); + return ret; +} + +int ObMinMaxEstimator::pack_sql(ObSqlString &raw_sql_str) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(gen_select_filed())) { + LOG_WARN("failed to generate select filed", K(ret)); + } else if (OB_FAIL(raw_sql_str.append_fmt("SELECT %.*s %.*s FROM DUAL", + other_hints_.length(), + other_hints_.ptr(), + static_cast(select_fields_.length()), + select_fields_.ptr()))) { + LOG_WARN("failed to build query sql stmt", K(ret)); + } else { + LOG_TRACE("OptStat: min max stat query sql", K(raw_sql_str)); + } + return ret; +} + +} // end of namespace common +} // end of namespace oceanbase diff --git a/src/share/stat/ob_min_max_estimator.h b/src/share/stat/ob_min_max_estimator.h new file mode 100644 index 0000000000..2b434480c5 --- /dev/null +++ b/src/share/stat/ob_min_max_estimator.h @@ -0,0 +1,72 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef OB_MIN_MAX_ESTIMATOR_H +#define OB_MIN_MAX_ESTIMATOR_H + +#include "share/stat/ob_stat_define.h" +#include "share/rc/ob_tenant_base.h" +#include "share/stat/ob_basic_stats_estimator.h" + +namespace oceanbase +{ +namespace common +{ + +class ObStatMinMaxSubquery : public ObStatColItem +{ +public: + ObStatMinMaxSubquery() {} + ObStatMinMaxSubquery(const ObColumnStatParam *param, + ObOptColumnStat *stat, + const ObString &db_name, + const ObString &from_table, + const ObString &partition, + bool is_min) : + ObStatColItem(param, stat), + db_name_(db_name), + from_table_(from_table), + partition_string_(partition), + is_min_(is_min) + {} + virtual ~ObStatMinMaxSubquery() {} + virtual int gen_expr(char *buf, const int64_t buf_len, int64_t &pos) override; + virtual int decode(ObObj &obj, ObIAllocator &allocator) override; + virtual bool is_needed() const override { return col_param_ != NULL && col_param_->need_refine_min_max(); } +private: + ObString db_name_; + ObString from_table_; + ObString partition_string_; + bool is_min_; +}; + +class ObMinMaxEstimator : public ObBasicStatsEstimator +{ +public: + explicit ObMinMaxEstimator(ObExecContext &ctx, ObIAllocator &allocator); + + int estimate(const ObOptStatGatherParam ¶m, + ObOptStat &opt_stat); + +private: + int add_min_max_stat_items(ObIAllocator &allocator, + const ObOptStatGatherParam ¶m, + const ObIArray &column_params, + ObOptStat &opt_stat); + + int pack_sql(ObSqlString &raw_sql_str); +}; + +} // end of namespace common +} // end of namespace oceanbase + +#endif /*#endif OB_MIN_MAX_ESTIMATOR_H */ diff --git a/src/share/stat/ob_opt_table_stat.h b/src/share/stat/ob_opt_table_stat.h index a3e3fec7cc..7e883a8660 100644 --- a/src/share/stat/ob_opt_table_stat.h +++ b/src/share/stat/ob_opt_table_stat.h @@ -241,13 +241,11 @@ public: bool is_stat_expired() const { return stale_stats_; } void set_stale_stats(int64_t stale_stats) { stale_stats_ = stale_stats > 0; } - + void add_sample_size(int64_t rc) { sample_size_ += rc; } bool is_locked() const { return stattype_locked_ > 0; } void add_row_count(int64_t rc) { row_count_ += rc; } - void add_sample_size(int64_t rc) { sample_size_ += rc; } - // for multi rows void add_avg_row_size(double avg_row_size, int64_t rc) { SQL_LOG(DEBUG, "INFO", K(partition_id_)); diff --git a/src/share/stat/ob_stat_define.cpp b/src/share/stat/ob_stat_define.cpp index d98bcee350..3a8ebea770 100644 --- a/src/share/stat/ob_stat_define.cpp +++ b/src/share/stat/ob_stat_define.cpp @@ -183,13 +183,16 @@ int ObTableStatParam::assign(const ObTableStatParam &other) allocator_ = other.allocator_; ref_table_type_ = other.ref_table_type_; is_async_gather_ = other.is_async_gather_; - async_gather_sample_size_ = other.async_gather_sample_size_; async_full_table_size_ = other.async_full_table_size_; async_partition_ids_ = other.async_partition_ids_; hist_sample_info_.is_sample_ = other.hist_sample_info_.is_sample_; hist_sample_info_.is_block_sample_ = other.hist_sample_info_.is_block_sample_; hist_sample_info_.sample_type_ = other.hist_sample_info_.sample_type_; hist_sample_info_.sample_value_ = other.hist_sample_info_.sample_value_; + is_auto_gather_ = other.is_auto_gather_; + is_auto_sample_size_ = other.is_auto_sample_size_; + need_refine_min_max_ = other.need_refine_min_max_; + auto_sample_row_cnt_ = other.auto_sample_row_cnt_; if (OB_FAIL(part_infos_.assign(other.part_infos_))) { LOG_WARN("failed to assign", K(ret)); } else if (OB_FAIL(subpart_infos_.assign(other.subpart_infos_))) { @@ -239,6 +242,10 @@ int ObTableStatParam::assign_common_property(const ObTableStatParam &other) hist_sample_info_.is_block_sample_ = other.hist_sample_info_.is_block_sample_; hist_sample_info_.sample_type_ = other.hist_sample_info_.sample_type_; hist_sample_info_.sample_value_ = other.hist_sample_info_.sample_value_; + is_auto_gather_ = other.is_auto_gather_; + is_auto_sample_size_ = other.is_auto_sample_size_; + need_refine_min_max_ = other.need_refine_min_max_; + auto_sample_row_cnt_ = other.auto_sample_row_cnt_; return ret; } @@ -271,6 +278,9 @@ int ObOptStatGatherParam::assign(const ObOptStatGatherParam &other) hist_sample_info_.is_block_sample_ = other.hist_sample_info_.is_block_sample_; hist_sample_info_.sample_type_ = other.hist_sample_info_.sample_type_; hist_sample_info_.sample_value_ = other.hist_sample_info_.sample_value_; + is_auto_sample_size_ = other.is_auto_sample_size_; + need_refine_min_max_ = other.need_refine_min_max_; + auto_sample_row_cnt_ = other.auto_sample_row_cnt_; data_table_id_ = other.data_table_id_; is_global_index_ = other.is_global_index_; part_level_ = other.part_level_; diff --git a/src/share/stat/ob_stat_define.h b/src/share/stat/ob_stat_define.h index 73e003a82e..96615d6f5a 100644 --- a/src/share/stat/ob_stat_define.h +++ b/src/share/stat/ob_stat_define.h @@ -81,6 +81,7 @@ const static int64_t MINIMUM_OF_ASYNC_GATHER_STALE_RATIO = 2; const int64_t MAXIMUM_BLOCK_CNT_OF_ROW_SAMPLE_GATHER_HYBRID_HIST = 100000; const int64_t MAXIMUM_ROWS_OF_ROW_SAMPLE_GATHER_HYBRID_HIST = 10000000; const int64_t MINIMUM_BLOCK_CNT_OF_BLOCK_SAMPLE_HYBRID_HIST = 16; +const static int64_t DEFAULT_AUTO_SAMPLE_ROW_COUNT = 0; enum StatLevel { @@ -425,11 +426,13 @@ struct ObColumnStatParam { inline void set_valid_opt_col() { gather_flag_ |= ColumnGatherFlag::VALID_OPT_COL; } inline void set_need_basic_stat() { gather_flag_ |= ColumnGatherFlag::NEED_BASIC_STAT; } inline void set_need_avg_len() { gather_flag_ |= ColumnGatherFlag::NEED_AVG_LEN; } + inline void set_need_refine_min_max() { gather_flag_ |= ColumnGatherFlag::NEED_REFINE_MIN_MAX; } inline bool is_valid_opt_col() const { return gather_flag_ & ColumnGatherFlag::VALID_OPT_COL; } inline bool need_basic_stat() const { return gather_flag_ & ColumnGatherFlag::NEED_BASIC_STAT; } inline bool need_avg_len() const { return gather_flag_ & ColumnGatherFlag::NEED_AVG_LEN; } inline bool need_col_stat() const { return gather_flag_ != ColumnGatherFlag::NO_NEED_STAT; } inline void unset_need_basic_stat() { gather_flag_ &= ~ColumnGatherFlag::NEED_BASIC_STAT; } + inline bool need_refine_min_max() const { return gather_flag_ & ColumnGatherFlag::NEED_REFINE_MIN_MAX; } ObString column_name_; uint64_t column_id_; @@ -440,6 +443,8 @@ struct ObColumnStatParam { int64_t column_attribute_; int64_t column_usage_flag_; int64_t gather_flag_; + ObString index_name_; + ObObjType column_type_; static bool is_valid_opt_col_type(const ObObjType type, bool is_online_stat = false); static bool is_valid_avglen_type(const ObObjType type); @@ -452,7 +457,8 @@ struct ObColumnStatParam { K_(bucket_num), K_(column_attribute), K_(column_usage_flag), - K_(gather_flag)); + K_(gather_flag), + K_(index_name)); }; struct ObColumnGroupStatParam { @@ -540,10 +546,13 @@ struct ObTableStatParam { column_group_params_(), online_sample_percent_(1.), is_async_gather_(false), - async_gather_sample_size_(DEFAULT_ASYNC_SAMPLE_SIZE), async_full_table_size_(DEFAULT_ASYNC_FULL_TABLE_SIZE), async_partition_ids_(NULL), - hist_sample_info_() + hist_sample_info_(), + is_auto_gather_(false), + is_auto_sample_size_(false), + need_refine_min_max_(false), + auto_sample_row_cnt_(DEFAULT_AUTO_SAMPLE_ROW_COUNT) {} int assign(const ObTableStatParam &other); @@ -627,10 +636,13 @@ struct ObTableStatParam { ObArray column_group_params_; double online_sample_percent_; bool is_async_gather_; - int64_t async_gather_sample_size_; int64_t async_full_table_size_; const ObIArray *async_partition_ids_; ObAnalyzeSampleInfo hist_sample_info_; + bool is_auto_gather_; + bool is_auto_sample_size_; + bool need_refine_min_max_; + int64_t auto_sample_row_cnt_; ObSEArray prefix_column_pairs_; TO_STRING_KV(K(tenant_id_), @@ -678,10 +690,12 @@ struct ObTableStatParam { K(column_group_params_), K(online_sample_percent_), K(is_async_gather_), - K(async_gather_sample_size_), K(async_full_table_size_), KPC(async_partition_ids_), K(hist_sample_info_), + K(is_auto_gather_), + K(need_refine_min_max_), + K(is_auto_sample_size_), K(prefix_column_pairs_)); }; @@ -712,9 +726,11 @@ struct ObOptStatGatherParam { use_column_store_(false), is_specify_partition_(false), is_async_gather_(false), - async_gather_sample_size_(DEFAULT_ASYNC_SAMPLE_SIZE), async_full_table_size_(DEFAULT_ASYNC_FULL_TABLE_SIZE), hist_sample_info_(), + is_auto_sample_size_(false), + need_refine_min_max_(false), + auto_sample_row_cnt_(DEFAULT_AUTO_SAMPLE_ROW_COUNT), data_table_id_(OB_INVALID_ID), is_global_index_(false), part_level_(share::schema::ObPartitionLevel::PARTITION_LEVEL_ZERO) @@ -746,9 +762,11 @@ struct ObOptStatGatherParam { bool use_column_store_; bool is_specify_partition_; int64_t is_async_gather_; - int64_t async_gather_sample_size_; int64_t async_full_table_size_; ObAnalyzeSampleInfo hist_sample_info_; + bool is_auto_sample_size_; + bool need_refine_min_max_; + int64_t auto_sample_row_cnt_; uint64_t data_table_id_; bool is_global_index_; share::schema::ObPartitionLevel part_level_; @@ -776,9 +794,11 @@ struct ObOptStatGatherParam { K(use_column_store_), K(is_specify_partition_), K(is_async_gather_), - K(async_gather_sample_size_), K(async_full_table_size_), K(hist_sample_info_), + K(is_auto_sample_size_), + K(need_refine_min_max_), + K(auto_sample_row_cnt_), K(data_table_id_), K(is_global_index_)); }; diff --git a/src/share/stat/ob_stat_item.cpp b/src/share/stat/ob_stat_item.cpp index 94d95caf42..054bfcd8ea 100644 --- a/src/share/stat/ob_stat_item.cpp +++ b/src/share/stat/ob_stat_item.cpp @@ -753,5 +753,97 @@ int ObStatHybridHist::decode(ObObj &obj, ObIAllocator &allocator) return ret; } +static const int32_t DEFAULT_DATA_TYPE_LEGNTH[] = +{ + /*ObNullType = 0*/ 12, + /*ObTinyIntType = 1*/ 20, + /*ObSmallIntType = 2*/ 20, + /*ObMediumIntType = 3*/ 20, + /*ObInt32Type = 4*/ 20, + /*ObIntType = 5*/ 20, + + /*ObUTinyIntType = 6*/ 20, + /*ObUSmallIntType = 7*/ 20, + /*ObUMediumIntType = 8*/ 20, + /*ObUInt32Type = 9*/ 20, + /*ObUInt64Type = 10*/ 20, + + /*ObFloatType = 11*/ 16, + /*ObDoubleType = 12*/ 20, + + /*ObUFloatType = 13*/ 16, + /*ObUDoubleType = 14*/ 20, + + /*ObNumberType = 15*/ -1, + /*ObUNumberType = 16*/ -1, + + /*ObDateTimeType = 17*/ 20, + /*ObTimestampType = 18*/ 20, + /*ObDateType = 19*/ 16, + /*ObTimeType = 20*/ 20, + /*ObYearType = 21*/ 13, + + /*ObVarcharType = 22*/ -1, + /*ObCharType = 23*/ -1, + + /*ObHexStringType = 24*/ -1, + + /*ObExtendType = 25*/ -1, + /*ObUnknownType = 26*/ -1, + + /*ObTinyTextType = 27*/ -1, + /*ObTextType = 28*/ -1, + /*ObMediumTextType = 29*/ -1, + /*ObLongTextType = 30*/ -1, + + /*ObBitType = 31*/ 20, + /*ObEnumType = 32*/ 20, + /*ObSetType = 33*/ 20, + /*ObEnumInnerType = 34*/ -1, + /*ObSetInnerType = 35*/ -1, + + /*ObTimestampTZType = 36*/ 24, + /*ObTimestampLTZType = 37*/ 22, + /*ObTimestampNanoType = 38*/ 22, + /*ObRawType = 39*/ -1, + /*ObIntervalYMType = 40*/ -1, + /*ObIntervalDSType = 41*/ -1, + /*ObNumberFloatType = 42*/ -1, + /*ObNVarchar2Type = 43*/ -1, + /*ObNCharType = 44*/ -1, + /*ObURowIDType = 45*/ -1, + /*ObLobType = 46*/ -1, + /*ObJsonType = 47*/ -1, + /*ObGeometryType = 48*/ -1, + + /*ObUserDefinedSQLType = 49*/ -1, + /*ObDecimalIntType = 50*/ -1, + /*ObCollectionSQLType = 51*/ -1, + /*ObMySQLDateType = 52*/ 16, + /*ObMySQLDateTimeType = 53*/ 20, + /*ObMaxType */ -1 +}; + +int ObStatAvgLen::gen_expr(char *buf, const int64_t buf_len, int64_t &pos) +{ + int ret = OB_SUCCESS; + int64_t type_count = sizeof(DEFAULT_DATA_TYPE_LEGNTH) / sizeof(int32_t); + if (OB_ISNULL(col_param_) || OB_ISNULL(get_fmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column param is null", K(ret)); + } else if (col_param_->column_type_ < type_count && + DEFAULT_DATA_TYPE_LEGNTH[col_param_->column_type_] > 0) { + if (OB_FAIL(databuff_printf(buf, buf_len, pos, "%d", + DEFAULT_DATA_TYPE_LEGNTH[col_param_->column_type_]))) { + LOG_WARN("failed to print avg column size", K(ret)); + } + } else if (OB_FAIL(databuff_printf(buf, buf_len, pos, get_fmt(), + col_param_->column_name_.length(), + col_param_->column_name_.ptr()))) { + LOG_WARN("failed to print AVG(SYS_OP_OPNSIZE(c2)) expr", K(ret)); + } + return ret; +} + } // end of common } // end of oceanbase diff --git a/src/share/stat/ob_stat_item.h b/src/share/stat/ob_stat_item.h index b6179ccd96..72db06a3fa 100644 --- a/src/share/stat/ob_stat_item.h +++ b/src/share/stat/ob_stat_item.h @@ -202,6 +202,7 @@ public: return lib::is_oracle_mode() ? " SUM_OPNSIZE(\"%.*s\")/decode(COUNT(*),0,1,COUNT(*))" : " SUM_OPNSIZE(`%.*s`)/(case when COUNT(*) = 0 then 1 else COUNT(*) end)"; } virtual int decode(ObObj &obj) override; + virtual int gen_expr(char *buf, const int64_t buf_len, int64_t &pos) override; }; class ObStatLlcBitmap : public ObStatColItem diff --git a/src/share/system_variable/ob_sys_var_class_type.h b/src/share/system_variable/ob_sys_var_class_type.h index a2d51005df..b484c49f10 100644 --- a/src/share/system_variable/ob_sys_var_class_type.h +++ b/src/share/system_variable/ob_sys_var_class_type.h @@ -627,6 +627,7 @@ enum ObSysVarClassType SYS_VAR_DELAYED_INSERT_LIMIT = 10736, SYS_VAR_NDB_VERSION = 10737, SYS_VAR_AUTO_GENERATE_CERTS = 10738, + SYS_VAR__OPTIMIZER_COST_BASED_TRANSFORMATION = 10739, SYS_VAR_RANGE_INDEX_DIVE_LIMIT = 10740, SYS_VAR_PARTITION_INDEX_DIVE_LIMIT = 10741, SYS_VAR_OB_TABLE_ACCESS_POLICY = 10742, diff --git a/src/share/system_variable/ob_system_variable_alias.h b/src/share/system_variable/ob_system_variable_alias.h index 4091cb8b90..8243ee4ea6 100644 --- a/src/share/system_variable/ob_system_variable_alias.h +++ b/src/share/system_variable/ob_system_variable_alias.h @@ -622,6 +622,7 @@ namespace share static const char* const OB_SV_DELAYED_INSERT_LIMIT = "delayed_insert_limit"; static const char* const OB_SV_NDB_VERSION = "ndb_version"; static const char* const OB_SV_AUTO_GENERATE_CERTS = "auto_generate_certs"; + static const char* const OB_SV__OPTIMIZER_COST_BASED_TRANSFORMATION = "_optimizer_cost_based_transformation"; static const char* const OB_SV_RANGE_INDEX_DIVE_LIMIT = "range_index_dive_limit"; static const char* const OB_SV_PARTITION_INDEX_DIVE_LIMIT = "partition_index_dive_limit"; static const char* const OB_SV_TABLE_ACCESS_POLICY = "ob_table_access_policy"; diff --git a/src/share/system_variable/ob_system_variable_factory.cpp b/src/share/system_variable/ob_system_variable_factory.cpp index 4715abd417..4a113d6501 100644 --- a/src/share/system_variable/ob_system_variable_factory.cpp +++ b/src/share/system_variable/ob_system_variable_factory.cpp @@ -539,6 +539,7 @@ const char *ObSysVarFactory::SYS_VAR_NAMES_SORTED_BY_NAME[] = { "_ob_proxy_weakread_feedback", "_ob_px_bcast_optimization", "_ob_px_slave_mapping_threshold", + "_optimizer_cost_based_transformation", "_optimizer_gather_stats_on_load", "_optimizer_null_aware_antijoin", "_oracle_sql_select_limit", @@ -1151,6 +1152,7 @@ const ObSysVarClassType ObSysVarFactory::SYS_VAR_IDS_SORTED_BY_NAME[] = { SYS_VAR__OB_PROXY_WEAKREAD_FEEDBACK, SYS_VAR__OB_PX_BCAST_OPTIMIZATION, SYS_VAR__OB_PX_SLAVE_MAPPING_THRESHOLD, + SYS_VAR__OPTIMIZER_COST_BASED_TRANSFORMATION, SYS_VAR__OPTIMIZER_GATHER_STATS_ON_LOAD, SYS_VAR__OPTIMIZER_NULL_AWARE_ANTIJOIN, SYS_VAR__ORACLE_SQL_SELECT_LIMIT, @@ -2346,6 +2348,7 @@ const char *ObSysVarFactory::SYS_VAR_NAMES_SORTED_BY_ID[] = { "delayed_insert_limit", "ndb_version", "auto_generate_certs", + "_optimizer_cost_based_transformation", "range_index_dive_limit", "partition_index_dive_limit", "ob_table_access_policy" @@ -3159,6 +3162,7 @@ int ObSysVarFactory::create_all_sys_vars() + sizeof(ObSysVarDelayedInsertLimit) + sizeof(ObSysVarNdbVersion) + sizeof(ObSysVarAutoGenerateCerts) + + sizeof(ObSysVarOptimizerCostBasedTransformation) + sizeof(ObSysVarRangeIndexDiveLimit) + sizeof(ObSysVarPartitionIndexDiveLimit) + sizeof(ObSysVarObTableAccessPolicy) @@ -8624,6 +8628,15 @@ int ObSysVarFactory::create_all_sys_vars() ptr = (void *)((char *)ptr + sizeof(ObSysVarAutoGenerateCerts)); } } + if (OB_SUCC(ret)) { + if (OB_ISNULL(sys_var_ptr = new (ptr)ObSysVarOptimizerCostBasedTransformation())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("fail to new ObSysVarOptimizerCostBasedTransformation", K(ret)); + } else { + store_buf_[ObSysVarsToIdxMap::get_store_idx(static_cast(SYS_VAR__OPTIMIZER_COST_BASED_TRANSFORMATION))] = sys_var_ptr; + ptr = (void *)((char *)ptr + sizeof(ObSysVarOptimizerCostBasedTransformation)); + } + } if (OB_SUCC(ret)) { if (OB_ISNULL(sys_var_ptr = new (ptr)ObSysVarRangeIndexDiveLimit())) { ret = OB_ALLOCATE_MEMORY_FAILED; @@ -15327,6 +15340,17 @@ int ObSysVarFactory::create_sys_var(ObIAllocator &allocator_, ObSysVarClassType } break; } + case SYS_VAR__OPTIMIZER_COST_BASED_TRANSFORMATION: { + void *ptr = NULL; + if (OB_ISNULL(ptr = allocator_.alloc(sizeof(ObSysVarOptimizerCostBasedTransformation)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("fail to alloc memory", K(ret), K(sizeof(ObSysVarOptimizerCostBasedTransformation))); + } else if (OB_ISNULL(sys_var_ptr = new (ptr)ObSysVarOptimizerCostBasedTransformation())) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("fail to new ObSysVarOptimizerCostBasedTransformation", K(ret)); + } + break; + } case SYS_VAR_RANGE_INDEX_DIVE_LIMIT: { void *ptr = NULL; if (OB_ISNULL(ptr = allocator_.alloc(sizeof(ObSysVarRangeIndexDiveLimit)))) { diff --git a/src/share/system_variable/ob_system_variable_factory.h b/src/share/system_variable/ob_system_variable_factory.h index c8b29595c3..cf0c89ef9d 100644 --- a/src/share/system_variable/ob_system_variable_factory.h +++ b/src/share/system_variable/ob_system_variable_factory.h @@ -4421,19 +4421,26 @@ public: inline virtual ObSysVarClassType get_type() const { return SYS_VAR_AUTO_GENERATE_CERTS; } inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(605); } }; +class ObSysVarOptimizerCostBasedTransformation : public ObIntSysVar +{ +public: + ObSysVarOptimizerCostBasedTransformation() : ObIntSysVar(NULL, NULL, NULL, NULL, NULL) {} + inline virtual ObSysVarClassType get_type() const { return SYS_VAR__OPTIMIZER_COST_BASED_TRANSFORMATION; } + inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(606); } +}; class ObSysVarRangeIndexDiveLimit : public ObIntSysVar { public: ObSysVarRangeIndexDiveLimit() : ObIntSysVar(NULL, NULL, NULL, NULL, NULL) {} inline virtual ObSysVarClassType get_type() const { return SYS_VAR_RANGE_INDEX_DIVE_LIMIT; } - inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(606); } + inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(607); } }; class ObSysVarPartitionIndexDiveLimit : public ObIntSysVar { public: ObSysVarPartitionIndexDiveLimit() : ObIntSysVar(NULL, NULL, NULL, NULL, NULL) {} inline virtual ObSysVarClassType get_type() const { return SYS_VAR_PARTITION_INDEX_DIVE_LIMIT; } - inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(607); } + inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(608); } }; class ObSysVarObTableAccessPolicy : public ObEnumSysVar { @@ -4442,7 +4449,7 @@ public: public: ObSysVarObTableAccessPolicy() : ObEnumSysVar(OB_TABLE_ACCESS_POLICY_NAMES, NULL, NULL, NULL, NULL, NULL) {} inline virtual ObSysVarClassType get_type() const { return SYS_VAR_OB_TABLE_ACCESS_POLICY; } - inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(608); } + inline virtual const common::ObObj &get_global_default_value() const { return ObSysVariables::get_default_value(609); } }; @@ -4467,7 +4474,7 @@ private: public: const static int64_t MYSQL_SYS_VARS_COUNT = 99; - const static int64_t OB_SYS_VARS_COUNT = 510; + const static int64_t OB_SYS_VARS_COUNT = 511; const static int64_t ALL_SYS_VARS_COUNT = MYSQL_SYS_VARS_COUNT + OB_SYS_VARS_COUNT; const static int64_t INVALID_MAX_READ_STALE_TIME = -1; diff --git a/src/share/system_variable/ob_system_variable_init.cpp b/src/share/system_variable/ob_system_variable_init.cpp index 5f771123e1..a143c8c3e3 100644 --- a/src/share/system_variable/ob_system_variable_init.cpp +++ b/src/share/system_variable/ob_system_variable_init.cpp @@ -3308,7 +3308,7 @@ static struct VarsInit{ }(); [&] (){ - ObSysVars[234].default_value_ = "4.3.4.0" ; + ObSysVars[234].default_value_ = "4.3.5.0" ; ObSysVars[234].info_ = "enabling a series of optimizer features based on an OceanBase release number" ; ObSysVars[234].name_ = "optimizer_features_enable" ; ObSysVars[234].data_type_ = ObVarcharType ; @@ -8441,43 +8441,58 @@ static struct VarsInit{ }(); [&] (){ - ObSysVars[606].default_value_ = "10" ; - ObSysVars[606].info_ = "Indicate the limit on the number of ranges when optimizer use storage cardinality estimation" ; - ObSysVars[606].name_ = "range_index_dive_limit" ; + ObSysVars[606].default_value_ = "1" ; + ObSysVars[606].info_ = "control cost-based transformation search policy" ; + ObSysVars[606].name_ = "_optimizer_cost_based_transformation" ; ObSysVars[606].data_type_ = ObIntType ; - ObSysVars[606].flags_ = ObSysVarFlag::SESSION_SCOPE | ObSysVarFlag::GLOBAL_SCOPE ; - ObSysVars[606].id_ = SYS_VAR_RANGE_INDEX_DIVE_LIMIT ; - cur_max_var_id = MAX(cur_max_var_id, static_cast(SYS_VAR_RANGE_INDEX_DIVE_LIMIT)) ; - ObSysVarsIdToArrayIdx[SYS_VAR_RANGE_INDEX_DIVE_LIMIT] = 606 ; - ObSysVars[606].base_value_ = "10" ; - ObSysVars[606].alias_ = "OB_SV_RANGE_INDEX_DIVE_LIMIT" ; + ObSysVars[606].min_val_ = "0" ; + ObSysVars[606].max_val_ = "2" ; + ObSysVars[606].flags_ = ObSysVarFlag::GLOBAL_SCOPE | ObSysVarFlag::SESSION_SCOPE ; + ObSysVars[606].id_ = SYS_VAR__OPTIMIZER_COST_BASED_TRANSFORMATION ; + cur_max_var_id = MAX(cur_max_var_id, static_cast(SYS_VAR__OPTIMIZER_COST_BASED_TRANSFORMATION)) ; + ObSysVarsIdToArrayIdx[SYS_VAR__OPTIMIZER_COST_BASED_TRANSFORMATION] = 606 ; + ObSysVars[606].base_value_ = "1" ; + ObSysVars[606].alias_ = "OB_SV__OPTIMIZER_COST_BASED_TRANSFORMATION" ; }(); [&] (){ ObSysVars[607].default_value_ = "10" ; - ObSysVars[607].info_ = "Indicate the limit on the number of partitions when optimizer use storage cardinality estimation" ; - ObSysVars[607].name_ = "partition_index_dive_limit" ; + ObSysVars[607].info_ = "Indicate the limit on the number of ranges when optimizer use storage cardinality estimation" ; + ObSysVars[607].name_ = "range_index_dive_limit" ; ObSysVars[607].data_type_ = ObIntType ; ObSysVars[607].flags_ = ObSysVarFlag::SESSION_SCOPE | ObSysVarFlag::GLOBAL_SCOPE ; - ObSysVars[607].id_ = SYS_VAR_PARTITION_INDEX_DIVE_LIMIT ; - cur_max_var_id = MAX(cur_max_var_id, static_cast(SYS_VAR_PARTITION_INDEX_DIVE_LIMIT)) ; - ObSysVarsIdToArrayIdx[SYS_VAR_PARTITION_INDEX_DIVE_LIMIT] = 607 ; + ObSysVars[607].id_ = SYS_VAR_RANGE_INDEX_DIVE_LIMIT ; + cur_max_var_id = MAX(cur_max_var_id, static_cast(SYS_VAR_RANGE_INDEX_DIVE_LIMIT)) ; + ObSysVarsIdToArrayIdx[SYS_VAR_RANGE_INDEX_DIVE_LIMIT] = 607 ; ObSysVars[607].base_value_ = "10" ; - ObSysVars[607].alias_ = "OB_SV_PARTITION_INDEX_DIVE_LIMIT" ; + ObSysVars[607].alias_ = "OB_SV_RANGE_INDEX_DIVE_LIMIT" ; }(); [&] (){ - ObSysVars[608].default_value_ = "2" ; - ObSysVars[608].info_ = "Control the optimizer to generate a table access plan that prefers a specific storage format." ; - ObSysVars[608].name_ = "ob_table_access_policy" ; + ObSysVars[608].default_value_ = "10" ; + ObSysVars[608].info_ = "Indicate the limit on the number of partitions when optimizer use storage cardinality estimation" ; + ObSysVars[608].name_ = "partition_index_dive_limit" ; ObSysVars[608].data_type_ = ObIntType ; - ObSysVars[608].enum_names_ = "[u'ROW_STORE', u'COLUMN_STORE', u'AUTO']" ; - ObSysVars[608].flags_ = ObSysVarFlag::GLOBAL_SCOPE | ObSysVarFlag::SESSION_SCOPE | ObSysVarFlag::INFLUENCE_PLAN | ObSysVarFlag::NEED_SERIALIZE ; - ObSysVars[608].id_ = SYS_VAR_OB_TABLE_ACCESS_POLICY ; + ObSysVars[608].flags_ = ObSysVarFlag::SESSION_SCOPE | ObSysVarFlag::GLOBAL_SCOPE ; + ObSysVars[608].id_ = SYS_VAR_PARTITION_INDEX_DIVE_LIMIT ; + cur_max_var_id = MAX(cur_max_var_id, static_cast(SYS_VAR_PARTITION_INDEX_DIVE_LIMIT)) ; + ObSysVarsIdToArrayIdx[SYS_VAR_PARTITION_INDEX_DIVE_LIMIT] = 608 ; + ObSysVars[608].base_value_ = "10" ; + ObSysVars[608].alias_ = "OB_SV_PARTITION_INDEX_DIVE_LIMIT" ; + }(); + + [&] (){ + ObSysVars[609].default_value_ = "2" ; + ObSysVars[609].info_ = "Control the optimizer to generate a table access plan that prefers a specific storage format." ; + ObSysVars[609].name_ = "ob_table_access_policy" ; + ObSysVars[609].data_type_ = ObIntType ; + ObSysVars[609].enum_names_ = "[u'ROW_STORE', u'COLUMN_STORE', u'AUTO']" ; + ObSysVars[609].flags_ = ObSysVarFlag::GLOBAL_SCOPE | ObSysVarFlag::SESSION_SCOPE | ObSysVarFlag::INFLUENCE_PLAN | ObSysVarFlag::NEED_SERIALIZE ; + ObSysVars[609].id_ = SYS_VAR_OB_TABLE_ACCESS_POLICY ; cur_max_var_id = MAX(cur_max_var_id, static_cast(SYS_VAR_OB_TABLE_ACCESS_POLICY)) ; - ObSysVarsIdToArrayIdx[SYS_VAR_OB_TABLE_ACCESS_POLICY] = 608 ; - ObSysVars[608].base_value_ = "2" ; - ObSysVars[608].alias_ = "OB_SV_TABLE_ACCESS_POLICY" ; + ObSysVarsIdToArrayIdx[SYS_VAR_OB_TABLE_ACCESS_POLICY] = 609 ; + ObSysVars[609].base_value_ = "2" ; + ObSysVars[609].alias_ = "OB_SV_TABLE_ACCESS_POLICY" ; }(); if (cur_max_var_id >= ObSysVarFactory::OB_MAX_SYS_VAR_ID) { @@ -8486,7 +8501,7 @@ static struct VarsInit{ } }vars_init; -static int64_t var_amount = 609; +static int64_t var_amount = 610; int64_t ObSysVariables::get_all_sys_var_count(){ return ObSysVarFactory::ALL_SYS_VARS_COUNT;} ObSysVarClassType ObSysVariables::get_sys_var_id(int64_t i){ return ObSysVars[i].id_;} diff --git a/src/share/system_variable/ob_system_variable_init.json b/src/share/system_variable/ob_system_variable_init.json index b853d9d18d..bcbeec5c06 100644 --- a/src/share/system_variable/ob_system_variable_init.json +++ b/src/share/system_variable/ob_system_variable_init.json @@ -3349,7 +3349,7 @@ "optimizer_features_enable": { "id": 10150, "name": "optimizer_features_enable", - "default_value": "4.3.4.0", + "default_value": "4.3.5.0", "base_value": "", "data_type": "varchar", "info": "enabling a series of optimizer features based on an OceanBase release number", @@ -11825,8 +11825,7 @@ "publish_version": "425", "info_cn": "", "background_cn": "", - "ref_url": "", - "placeholder": true + "ref_url": "" }, "range_index_dive_limit": { "id": 10740, diff --git a/src/sql/CMakeLists.txt b/src/sql/CMakeLists.txt index 0054728ac6..25db98ee80 100644 --- a/src/sql/CMakeLists.txt +++ b/src/sql/CMakeLists.txt @@ -1380,7 +1380,6 @@ ob_set_subtarget(ob_sql resolver_prepare ob_set_subtarget(ob_sql rewrite rewrite/ob_equal_analysis.cpp - rewrite/ob_equal_set.ipp rewrite/ob_expand_aggregate_utils.cpp rewrite/ob_key_part.cpp rewrite/ob_predicate_deduce.cpp @@ -1427,6 +1426,7 @@ ob_set_subtarget(ob_sql rewrite rewrite/ob_transform_decorrelate.cpp rewrite/ob_transform_late_materialization.cpp rewrite/ob_transform_mv_rewrite_prepare.cpp + rewrite/ob_transform_distinct_aggregate.cpp ) ob_set_subtarget(ob_sql session diff --git a/src/sql/code_generator/ob_static_engine_cg.cpp b/src/sql/code_generator/ob_static_engine_cg.cpp index c739e8db53..f71c860069 100644 --- a/src/sql/code_generator/ob_static_engine_cg.cpp +++ b/src/sql/code_generator/ob_static_engine_cg.cpp @@ -4797,7 +4797,7 @@ int ObStaticEngineCG::generate_spec(ObLogGroupBy &op, ObMergeGroupBySpec &spec, } if ((!op.get_group_by_exprs().empty() || !op.get_rollup_exprs().empty()) && SCALAR_AGGREGATE != op.get_algo()) { - double distinct_card = MAX(1.0, op.get_distinct_card()); + double distinct_card = MAX(1.0, op.get_total_ndv()); spec.est_rows_per_group_ = ceil(op.get_origin_child_card() / distinct_card); } spec.set_rollup(op.has_rollup()); @@ -5066,7 +5066,7 @@ int ObStaticEngineCG::generate_spec(ObLogGroupBy &op, ObHashGroupBySpec &spec, ret = OB_ERR_UNEXPECTED; LOG_ERROR("wrong number of children", K(ret), K(op.get_num_of_child())); } else { - spec.set_est_group_cnt(op.get_distinct_card()); + spec.set_est_group_cnt(op.get_total_ndv()); OZ(set_3stage_info(op, spec)); spec.by_pass_enabled_ = op.is_adaptive_aggregate(); int64_t tenant_id = op.get_plan()->get_optimizer_context().get_session_info()->get_effective_tenant_id(); diff --git a/src/sql/engine/cmd/ob_load_data_impl.cpp b/src/sql/engine/cmd/ob_load_data_impl.cpp index b4babd8969..e675b2aba8 100644 --- a/src/sql/engine/cmd/ob_load_data_impl.cpp +++ b/src/sql/engine/cmd/ob_load_data_impl.cpp @@ -211,7 +211,7 @@ int ObLoadDataBase::make_parameterize_stmt(ObExecContext &ctx, LOG_WARN("invalid argument", K(ret), KP(ctx.get_stmt_factory()->get_query_ctx())); } else { resolver_ctx.query_ctx_ = ctx.get_stmt_factory()->get_query_ctx(); - resolver_ctx.query_ctx_->question_marks_count_ = param_store.count(); + resolver_ctx.query_ctx_->set_questionmark_count(param_store.count()); resolver_ctx.query_ctx_->sql_schema_guard_.set_schema_guard(ctx.get_sql_ctx()->schema_guard_); ObResolver resolver(resolver_ctx); ObStmt *astmt = NULL; diff --git a/src/sql/engine/expr/ob_expr_operator.cpp b/src/sql/engine/expr/ob_expr_operator.cpp index cede1f2a92..5fddf3bf17 100644 --- a/src/sql/engine/expr/ob_expr_operator.cpp +++ b/src/sql/engine/expr/ob_expr_operator.cpp @@ -2254,43 +2254,30 @@ bool ObRelationalExprOperator::can_cmp_without_cast(ObExprResType type1, /* * Note that, the original motivation of this function is that, * - * Provided that we have a = b and b = c in which a , b and c - * are of metainfo meta1, meta2, meta3, respectively + * Provided that we have a = b and b = c, can we deduce that a = c holds actually? * - * So, can we deduce that a = c holds actually? + * The return value of result is true represents equal comparison a = b is transitive, which means + * for any a = b and b = c, if both of them are transitive, then we can always deduce a = c * - * this func tells you this via result when and only when the ret is OB_SUCCESS + * For example, we have the table definition like this + * create table t1(c1 int, c2 tinyint, c3 int unsigned, c4 enum('a', 'b'), c5 enum('c', 'd')) + * Then there is no need to add any implicit cast in c1 = c2, c1 = c3, c1 = c4, c1 = c5. + * c1 = c2 and c1 = c3 is equal transitive, then we can deduce c2 = c3. + * For comparison between enum types, they need cast to varchar implicitly, so we define comparison + * between enum and int type class is not transitive. + * Then we can not deduce c4 = c5 via c1 = c4 and c1 = c5, because they are not equal transitive. */ - -int ObRelationalExprOperator::is_equivalent(const ObObjMeta &meta1, - const ObObjMeta &meta2, - const ObObjMeta &meta3, - bool &result) +int ObRelationalExprOperator::is_equal_transitive(const common::ObObjMeta &meta1, + const common::ObObjMeta &meta2, + bool &result) { int ret = OB_SUCCESS; result = false; - ObObjMeta equal_meta12; - ObObjMeta equal_meta23; - ObObjMeta equal_meta13; - if (OB_FAIL(get_equal_meta(equal_meta12, meta1, meta2))) { + ObObjMeta equal_meta; + if (OB_FAIL(get_equal_meta(equal_meta, meta1, meta2))) { LOG_WARN("get equal meta failed", K(ret), K(meta1), K(meta2)); - } else if (OB_FAIL(get_equal_meta(equal_meta13, meta1, meta3))) { - LOG_WARN("get equal meta failed", K(ret), K(meta1), K(meta3)); - } else if (OB_FAIL(get_equal_meta(equal_meta23, meta2, meta3))) { - LOG_WARN("get equal meta failed", K(ret), K(meta2), K(meta3)); - } else if (OB_UNLIKELY(equal_meta12.get_type() == ObMaxType - || equal_meta13.get_type() == ObMaxType /* no need to check ObNullType here*/ - || equal_meta23.get_type() == ObMaxType)) { - /*result = false;*/ - } else if (equal_meta12.get_type() == equal_meta13.get_type() - && equal_meta13.get_type() == equal_meta23.get_type()) { - if (OB_UNLIKELY(ob_is_string_or_lob_type(equal_meta12.get_type()))) { - //all are string type - result = equal_meta12.get_collation_type() == equal_meta13.get_collation_type() - && equal_meta13.get_collation_type() == equal_meta23.get_collation_type(); - } else { - result = true; - } + } else { + result = equal_meta.get_type() != ObMaxType; } return ret; } @@ -2307,8 +2294,11 @@ int ObRelationalExprOperator::get_equal_meta(ObObjMeta &meta, meta2.get_type()))) { LOG_WARN("get equal type failed", K(ret), K(meta1), K(meta2)); } else if (ob_is_string_or_lob_type(type)) { - ObObjMeta coll_types[2] = {meta1, meta2}; - ret = aggregate_charsets_for_comparison(meta, coll_types, 2, type_ctx); + if (meta1.get_collation_type() != meta2.get_collation_type()) { + type = ObMaxType; + } else { + meta.set_collation_type(meta1.get_collation_type()); + } } if (OB_SUCC(ret)) { meta.set_type(type); diff --git a/src/sql/engine/expr/ob_expr_operator.h b/src/sql/engine/expr/ob_expr_operator.h index 46fc33293a..b9b8bd2ebd 100644 --- a/src/sql/engine/expr/ob_expr_operator.h +++ b/src/sql/engine/expr/ob_expr_operator.h @@ -1258,10 +1258,9 @@ public: bool is_null_safe, common::ObCmpOp cmp_op) const; - static int is_equivalent(const common::ObObjMeta &meta1, - const common::ObObjMeta &meta2, - const common::ObObjMeta &meta3, - bool &result); + static int is_equal_transitive(const common::ObObjMeta &meta1, + const common::ObObjMeta &meta2, + bool &result); int assign(const ObExprOperator &other); int set_cmp_func(const common::ObObjType type1, const common::ObObjType type2); diff --git a/src/sql/engine/expr/ob_expr_relational_equal_type.map b/src/sql/engine/expr/ob_expr_relational_equal_type.map index 0a8c1700e0..47f3dfb2be 100644 --- a/src/sql/engine/expr/ob_expr_relational_equal_type.map +++ b/src/sql/engine/expr/ob_expr_relational_equal_type.map @@ -1,3226 +1,123 @@ -static constexpr ObObjType RELATIONAL_EQUAL_TYPE[ObMaxType][ObMaxType] = +/* + * the following array is used to determine whether the equal compare is transitive in optimizer + */ +static constexpr ObObjType RELATIONAL_EQUAL_TYPE[ObMaxType] = { - /*NullType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObMaxType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*TinyIntType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*SmallIntType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*MediumIntType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*Int32Type*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*IntType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*UTinyIntType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*USmallIntType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*UMediumIntType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*UInt32Type*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*UInt64Type*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*FloatType*/ - { - ObMaxType, /* NullType */ - ObDoubleType, /* TinyIntType */ - ObDoubleType, /* SmallIntType */ - ObDoubleType, /* MediumIntType */ - ObDoubleType, /* Int32Type */ - ObDoubleType, /* IntType */ - ObDoubleType, /* UTinyIntType */ - ObDoubleType, /* USmallIntType */ - ObDoubleType, /* UMediumIntType */ - ObDoubleType, /* UInt32Type */ - ObDoubleType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObDoubleType, /* NumberType */ - ObDoubleType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObDoubleType, /* YearType */ - ObDoubleType, /* VarcharType */ - ObDoubleType, /* CharType */ - ObDoubleType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObDoubleType, /*TinyTextType*/ - ObDoubleType, /*TextType*/ - ObDoubleType, /*MediumTextType*/ - ObDoubleType, /*LongTextType*/ - ObDoubleType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObDoubleType, /* ObNumberFloatType */ - ObNVarchar2Type, /* ObNVarchar2Type */ - ObNCharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDoubleType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*DoubleType*/ - { - ObMaxType, /* NullType */ - ObDoubleType, /* TinyIntType */ - ObDoubleType, /* SmallIntType */ - ObDoubleType, /* MediumIntType */ - ObDoubleType, /* Int32Type */ - ObDoubleType, /* IntType */ - ObDoubleType, /* UTinyIntType */ - ObDoubleType, /* USmallIntType */ - ObDoubleType, /* UMediumIntType */ - ObDoubleType, /* UInt32Type */ - ObDoubleType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObDoubleType, /* NumberType */ - ObDoubleType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObDoubleType, /* YearType */ - ObDoubleType, /* VarcharType */ - ObDoubleType, /* CharType */ - ObDoubleType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObDoubleType, /*TinyTextType*/ - ObDoubleType, /*TextType*/ - ObDoubleType, /*MediumTextType*/ - ObDoubleType, /*LongTextType*/ - ObDoubleType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObDoubleType, /* ObNumberFloatType */ - ObDoubleType, /* ObNVarchar2Type */ - ObDoubleType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDoubleType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*UFloatType*/ - { - ObMaxType, /* NullType */ - ObDoubleType, /* TinyIntType */ - ObDoubleType, /* SmallIntType */ - ObDoubleType, /* MediumIntType */ - ObDoubleType, /* Int32Type */ - ObDoubleType, /* IntType */ - ObDoubleType, /* UTinyIntType */ - ObDoubleType, /* USmallIntType */ - ObDoubleType, /* UMediumIntType */ - ObDoubleType, /* UInt32Type */ - ObDoubleType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObDoubleType, /* NumberType */ - ObDoubleType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObDoubleType, /* YearType */ - ObDoubleType, /* VarcharType */ - ObDoubleType, /* CharType */ - ObDoubleType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObDoubleType, /*TinyTextType*/ - ObDoubleType, /*TextType*/ - ObDoubleType, /*MediumTextType*/ - ObDoubleType, /*LongTextType*/ - ObDoubleType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObDoubleType, /* ObNumberFloatType */ - ObDoubleType, /* ObNVarchar2Type */ - ObDoubleType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDoubleType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*UDoubleType*/ - { - ObMaxType, /* NullType */ - ObDoubleType, /* TinyIntType */ - ObDoubleType, /* SmallIntType */ - ObDoubleType, /* MediumIntType */ - ObDoubleType, /* Int32Type */ - ObDoubleType, /* IntType */ - ObDoubleType, /* UTinyIntType */ - ObDoubleType, /* USmallIntType */ - ObDoubleType, /* UMediumIntType */ - ObDoubleType, /* UInt32Type */ - ObDoubleType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObDoubleType, /* NumberType */ - ObDoubleType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObDoubleType, /* YearType */ - ObDoubleType, /* VarcharType */ - ObDoubleType, /* CharType */ - ObDoubleType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObDoubleType, /*TinyTextType*/ - ObDoubleType, /*TextType*/ - ObDoubleType, /*MediumTextType*/ - ObDoubleType, /*LongTextType*/ - ObDoubleType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObDoubleType, /* ObNumberFloatType */ - ObDoubleType, /* ObNVarchar2Type */ - ObDoubleType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDoubleType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*NumberType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObNumberType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObNumberType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*UNumberType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObNumberType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObNumberType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*DateTimeType*/ - { - ObMaxType, /* NullType */ - ObDateTimeType, /* TinyIntType */ - ObDateTimeType, /* SmallIntType */ - ObDateTimeType, /* MediumIntType */ - ObDateTimeType, /* Int32Type */ - ObDateTimeType, /* IntType */ - ObDateTimeType, /* UTinyIntType */ - ObDateTimeType, /* USmallIntType */ - ObDateTimeType, /* UMediumIntType */ - ObDateTimeType, /* UInt32Type */ - ObDateTimeType, /* UIntType */ - ObDateTimeType, /* FloatType */ - ObDateTimeType, /* DoubleType */ - ObDateTimeType, /* UFloatType */ - ObDateTimeType, /* UDoubleType */ - ObDateTimeType, /* NumberType */ - ObDateTimeType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObDateTimeType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObDateTimeType, /* TimeType */ - ObVarcharType, /* YearType */ - ObDateTimeType, /* VarcharType */ - ObDateTimeType, /* CharType */ - ObDateTimeType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObDateTimeType, /*TinyTextType*/ - ObDateTimeType, /*TextType*/ - ObDateTimeType, /*MediumTextType*/ - ObDateTimeType, /*LongTextType*/ - ObDateTimeType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObDateTimeType, /* ObNumberFloatType */ - ObDateTimeType, /* ObNVarchar2Type */ - ObDateTimeType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDateTimeType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*TimestampType*/ - { - ObMaxType, /* NullType */ - ObTimestampType, /* TinyIntType */ - ObTimestampType, /* SmallIntType */ - ObTimestampType, /* MediumIntType */ - ObTimestampType, /* Int32Type */ - ObTimestampType, /* IntType */ - ObTimestampType, /* UTinyIntType */ - ObTimestampType, /* USmallIntType */ - ObTimestampType, /* UMediumIntType */ - ObTimestampType, /* UInt32Type */ - ObTimestampType, /* UIntType */ - ObTimestampType, /* FloatType */ - ObTimestampType, /* DoubleType */ - ObTimestampType, /* UFloatType */ - ObTimestampType, /* UDoubleType */ - ObTimestampType, /* NumberType */ - ObTimestampType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObTimestampType, /* DateType */ - ObTimestampType, /* TimeType */ - ObVarcharType, /* YearType */ - ObTimestampType, /* VarcharType */ - ObTimestampType, /* CharType */ - ObTimestampType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObTimestampType, /*TinyTextType*/ - ObTimestampType, /*TextType*/ - ObTimestampType, /*MediumTextType*/ - ObTimestampType, /*LongTextType*/ - ObTimestampType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObTimestampType, /* ObNumberFloatType */ - ObTimestampType, /* ObNVarchar2Type */ - ObTimestampType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObTimestampType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObTimestampType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*DateType*/ - { - ObMaxType, /* NullType */ - ObDateType, /* TinyIntType */ - ObDateType, /* SmallIntType */ - ObDateType, /* MediumIntType */ - ObDateType, /* Int32Type */ - ObDateType, /* IntType */ - ObDateType, /* UTinyIntType */ - ObDateType, /* USmallIntType */ - ObDateType, /* UMediumIntType */ - ObDateType, /* UInt32Type */ - ObDateType, /* UIntType */ - ObDateType, /* FloatType */ - ObDateType, /* DoubleType */ - ObDateType, /* UFloatType */ - ObDateType, /* UDoubleType */ - ObDateType, /* NumberType */ - ObDateType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObDateTimeType, /* TimeType */ - ObVarcharType, /* YearType */ - ObDateTimeType, /* VarcharType */ - ObDateTimeType, /* CharType */ - ObDateTimeType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObDateTimeType, /*TinyTextType*/ - ObDateTimeType, /*TextType*/ - ObDateTimeType, /*MediumTextType*/ - ObDateTimeType, /*LongTextType*/ - ObDateType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObDateType, /* ObNumberFloatType */ - ObDateTimeType, /* ObNVarchar2Type */ - ObDateTimeType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDateType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*TimeType*/ - { - ObMaxType, /* NullType */ - ObTimeType, /* TinyIntType */ - ObTimeType, /* SmallIntType */ - ObTimeType, /* MediumIntType */ - ObTimeType, /* Int32Type */ - ObTimeType, /* IntType */ - ObTimeType, /* UTinyIntType */ - ObTimeType, /* USmallIntType */ - ObTimeType, /* UMediumIntType */ - ObTimeType, /* UInt32Type */ - ObTimeType, /* UIntType */ - ObTimeType, /* FloatType */ - ObTimeType, /* DoubleType */ - ObTimeType, /* UFloatType */ - ObTimeType, /* UDoubleType */ - ObTimeType, /* NumberType */ - ObTimeType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObTimeType, /* VarcharType */ - ObTimeType, /* CharType */ - ObTimeType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObTimeType, /*TinyTextType*/ - ObTimeType, /*TextType*/ - ObTimeType, /*MediumTextType*/ - ObTimeType, /*LongTextType*/ - ObTimeType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObTimeType, /* ObNumberFloatType */ - ObTimeType, /* ObNVarchar2Type */ - ObTimeType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObHexStringType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObTimeType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*YearType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObVarcharType, /* DateTimeType */ - ObVarcharType, /* TimestampType */ - ObVarcharType, /* DateType */ - ObNumberType, /* TimeType */ - ObYearType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObVarcharType, /* ObTimestampTZType */ - ObVarcharType, /* ObTimestampLTZType */ - ObVarcharType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType*/ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObVarcharType, /* ObMySQLDateType */ - ObVarcharType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*VarcharType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObVarcharType, /* VarcharType */ - ObVarcharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMediumTextType, /*TinyTextType*/ - ObMediumTextType, /*TextType*/ - ObMediumTextType, /*MediumTextType*/ - ObMediumTextType, /*LongTextType*/ - ObNumberType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObVarcharType, /* ObNVarchar2Type */ - ObVarcharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObHexStringType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*CharType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObVarcharType, /* VarcharType */ - ObVarcharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMediumTextType, /*TinyTextType*/ - ObMediumTextType, /*TextType*/ - ObMediumTextType, /*MediumTextType*/ - ObMediumTextType, /*LongTextType*/ - ObNumberType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObVarcharType, /* ObNVarchar2Type */ - ObVarcharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObHexStringType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*HexStringType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObVarcharType, /* VarcharType */ - ObVarcharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMediumTextType, /*TinyTextType*/ - ObMediumTextType, /*TextType*/ - ObMediumTextType, /*MediumTextType*/ - ObMediumTextType, /*LongTextType*/ - ObNumberType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObVarcharType, /* ObNVarchar2Type */ - ObVarcharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObHexStringType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*ExtendType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObMaxType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*UnknownType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObMaxType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*TinyTextType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObVarcharType, /* VarcharType */ - ObVarcharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObVarcharType, /*TinyTextType*/ - ObVarcharType, /*TextType*/ - ObVarcharType, /*MediumTextType*/ - ObVarcharType, /*LongTextType*/ - ObNumberType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObVarcharType, /* ObNVarchar2Type */ - ObVarcharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*TextType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObVarcharType, /* VarcharType */ - ObVarcharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObVarcharType, /*TinyTextType*/ - ObVarcharType, /*TextType*/ - ObVarcharType, /*MediumTextType*/ - ObVarcharType, /*LongTextType*/ - ObNumberType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObVarcharType, /* ObNVarchar2Type */ - ObVarcharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*MediumTextType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObVarcharType, /* VarcharType */ - ObVarcharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObVarcharType, /*TinyTextType*/ - ObVarcharType, /*TextType*/ - ObVarcharType, /*MediumTextType*/ - ObVarcharType, /*LongTextType*/ - ObNumberType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObVarcharType, /* ObNVarchar2Type */ - ObVarcharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*LongTextType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObVarcharType, /* VarcharType */ - ObVarcharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObVarcharType, /*TinyTextType*/ - ObVarcharType, /*TextType*/ - ObVarcharType, /*MediumTextType*/ - ObVarcharType, /*LongTextType*/ - ObNumberType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObVarcharType, /* ObNVarchar2Type */ - ObVarcharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*BitType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*EnumType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObVarcharType, /* VarcharType */ - ObVarcharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObVarcharType, /*TinyTextType*/ - ObVarcharType, /*TextType*/ - ObVarcharType, /*MediumTextType*/ - ObVarcharType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObVarcharType, /* ObNVarchar2Type */ - ObVarcharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObNumberType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*SetType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObVarcharType, /* VarcharType */ - ObVarcharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObVarcharType, /*TinyTextType*/ - ObVarcharType, /*TextType*/ - ObVarcharType, /*MediumTextType*/ - ObVarcharType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObVarcharType, /* ObNVarchar2Type */ - ObVarcharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObNumberType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*EnumInnerType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObMaxType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObNumberType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*SetInnerType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObMaxType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObNumberType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObTimestampTZType*/ - { - ObMaxType, /* NullType */ - ObTimestampTZType, /* TinyIntType */ - ObTimestampTZType, /* SmallIntType */ - ObTimestampTZType, /* MediumIntType */ - ObTimestampTZType, /* Int32Type */ - ObTimestampTZType, /* IntType */ - ObTimestampTZType, /* UTinyIntType */ - ObTimestampTZType, /* USmallIntType */ - ObTimestampTZType, /* UMediumIntType */ - ObTimestampTZType, /* UInt32Type */ - ObTimestampTZType, /* UIntType */ - ObTimestampTZType, /* FloatType */ - ObTimestampTZType, /* DoubleType */ - ObTimestampTZType, /* UFloatType */ - ObTimestampTZType, /* UDoubleType */ - ObTimestampTZType, /* NumberType */ - ObTimestampTZType, /* UNumberType */ - ObTimestampTZType, /* DateTimeType */ - ObTimestampTZType, /* TimestampType */ - ObTimestampTZType, /* DateType */ - ObTimestampTZType, /* TimeType */ - ObVarcharType, /* YearType */ - ObTimestampTZType, /* VarcharType */ - ObTimestampTZType, /* CharType */ - ObTimestampTZType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObTimestampTZType, /*TinyTextType*/ - ObTimestampTZType, /*TextType*/ - ObTimestampTZType, /*MediumTextType*/ - ObTimestampTZType, /*LongTextType*/ - ObTimestampTZType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObTimestampTZType, /* ObNumberFloatType */ - ObTimestampTZType, /* ObNVarchar2Type */ - ObTimestampTZType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObTimestampTZType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObTimestampTZType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObTimestampTZType, /* ObMySQLDateType */ - ObTimestampTZType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObTimestampLTZType*/ - { - ObMaxType, /* NullType */ - ObTimestampLTZType, /* TinyIntType */ - ObTimestampLTZType, /* SmallIntType */ - ObTimestampLTZType, /* MediumIntType */ - ObTimestampLTZType, /* Int32Type */ - ObTimestampLTZType, /* IntType */ - ObTimestampLTZType, /* UTinyIntType */ - ObTimestampLTZType, /* USmallIntType */ - ObTimestampLTZType, /* UMediumIntType */ - ObTimestampLTZType, /* UInt32Type */ - ObTimestampLTZType, /* UIntType */ - ObTimestampLTZType, /* FloatType */ - ObTimestampLTZType, /* DoubleType */ - ObTimestampLTZType, /* UFloatType */ - ObTimestampLTZType, /* UDoubleType */ - ObTimestampLTZType, /* NumberType */ - ObTimestampLTZType, /* UNumberType */ - ObTimestampLTZType, /* DateTimeType */ - ObTimestampLTZType, /* TimestampType */ - ObTimestampLTZType, /* DateType */ - ObTimestampLTZType, /* TimeType */ - ObVarcharType, /* YearType */ - ObTimestampLTZType, /* VarcharType */ - ObTimestampLTZType, /* CharType */ - ObTimestampLTZType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObTimestampLTZType, /*TinyTextType*/ - ObTimestampLTZType, /*TextType*/ - ObTimestampLTZType, /*MediumTextType*/ - ObTimestampLTZType, /*LongTextType*/ - ObTimestampLTZType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampTZType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObTimestampLTZType, /* ObNumberFloatType */ - ObTimestampLTZType, /* ObNVarchar2Type */ - ObTimestampLTZType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObTimestampLTZType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObTimestampLTZType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObTimestampLTZType, /* ObMySQLDateType */ - ObTimestampLTZType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObTimestampNanoType*/ - { - ObMaxType, /* NullType */ - ObTimestampNanoType, /* TinyIntType */ - ObTimestampNanoType, /* SmallIntType */ - ObTimestampNanoType, /* MediumIntType */ - ObTimestampNanoType, /* Int32Type */ - ObTimestampNanoType, /* IntType */ - ObTimestampNanoType, /* UTinyIntType */ - ObTimestampNanoType, /* USmallIntType */ - ObTimestampNanoType, /* UMediumIntType */ - ObTimestampNanoType, /* UInt32Type */ - ObTimestampNanoType, /* UIntType */ - ObTimestampNanoType, /* FloatType */ - ObTimestampNanoType, /* DoubleType */ - ObTimestampNanoType, /* UFloatType */ - ObTimestampNanoType, /* UDoubleType */ - ObTimestampNanoType, /* NumberType */ - ObTimestampNanoType, /* UNumberType */ - ObTimestampNanoType, /* DateTimeType */ - ObTimestampNanoType, /* TimestampType */ - ObTimestampNanoType, /* DateType */ - ObTimestampNanoType, /* TimeType */ - ObVarcharType, /* YearType */ - ObTimestampNanoType, /* VarcharType */ - ObTimestampNanoType, /* CharType */ - ObTimestampNanoType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObTimestampNanoType, /*TinyTextType*/ - ObTimestampNanoType, /*TextType*/ - ObTimestampNanoType, /*MediumTextType*/ - ObTimestampNanoType, /*LongTextType*/ - ObTimestampNanoType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObTimestampNanoType, /* ObNumberFloatType */ - ObTimestampNanoType, /* ObNVarchar2Type */ - ObTimestampNanoType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObTimestampNanoType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObTimestampNanoType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObTimestampNanoType, /* ObMySQLDateType */ - ObTimestampNanoType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObRawType*/ - { - ObMaxType, /* NullType */ - ObRawType, /* TinyIntType */ - ObRawType, /* SmallIntType */ - ObRawType, /* MediumIntType */ - ObRawType, /* Int32Type */ - ObRawType, /* IntType */ - ObRawType, /* UTinyIntType */ - ObRawType, /* USmallIntType */ - ObRawType, /* UMediumIntType */ - ObRawType, /* UInt32Type */ - ObRawType, /* UIntType */ - ObRawType, /* FloatType */ - ObRawType, /* DoubleType */ - ObRawType, /* UFloatType */ - ObRawType, /* UDoubleType */ - ObRawType, /* NumberType */ - ObRawType, /* UNumberType */ - ObRawType, /* DateTimeType */ - ObRawType, /* TimestampType */ - ObRawType, /* DateType */ - ObRawType, /* TimeType */ - ObRawType, /* YearType */ - ObRawType, /* VarcharType */ - ObRawType, /* CharType */ - ObRawType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObRawType, /* TinyTextType*/ - ObRawType, /* TextType*/ - ObRawType, /* MediumTextType*/ - ObRawType, /* LongTextType*/ - ObRawType, /* BitType*/ - ObMaxType, /* EnumType*/ - ObMaxType, /* SetType*/ - ObMaxType, /* EnumInnerType*/ - ObMaxType, /* SetInnerType*/ - ObRawType, /* ObTimestampTZType */ - ObRawType, /* ObTimestampLTZType */ - ObRawType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObRawType, /* ObNumberFloatType */ - ObRawType, /* ObNVarchar2Type */ - ObRawType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObVarcharType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObRawType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObRawType, /* ObMySQLDateType */ - ObRawType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObIntervalYMType*/ - { - ObMaxType, /* NullType */ - ObIntervalYMType, /* TinyIntType */ - ObIntervalYMType, /* SmallIntType */ - ObIntervalYMType, /* MediumIntType */ - ObIntervalYMType, /* Int32Type */ - ObIntervalYMType, /* IntType */ - ObIntervalYMType, /* UTinyIntType */ - ObIntervalYMType, /* USmallIntType */ - ObIntervalYMType, /* UMediumIntType */ - ObIntervalYMType, /* UInt32Type */ - ObIntervalYMType, /* UIntType */ - ObIntervalYMType, /* FloatType */ - ObIntervalYMType, /* DoubleType */ - ObIntervalYMType, /* UFloatType */ - ObIntervalYMType, /* UDoubleType */ - ObIntervalYMType, /* NumberType */ - ObIntervalYMType, /* UNumberType */ - ObIntervalYMType, /* DateTimeType */ - ObIntervalYMType, /* TimestampType */ - ObIntervalYMType, /* DateType */ - ObIntervalYMType, /* TimeType */ - ObIntervalYMType, /* YearType */ - ObIntervalYMType, /* VarcharType */ - ObIntervalYMType, /* CharType */ - ObIntervalYMType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObIntervalYMType, /* TinyTextType*/ - ObIntervalYMType, /* TextType*/ - ObIntervalYMType, /* MediumTextType*/ - ObIntervalYMType, /* LongTextType*/ - ObIntervalYMType, /* BitType*/ - ObMaxType, /* EnumType*/ - ObMaxType, /* SetType*/ - ObMaxType, /* EnumInnerType*/ - ObMaxType, /* SetInnerType*/ - ObIntervalYMType, /* ObTimestampTZType */ - ObIntervalYMType, /* ObTimestampLTZType */ - ObIntervalYMType, /* ObTimestampNanoType */ - ObIntervalYMType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalYMType, /* ObIntervalDSType */ - ObIntervalYMType, /* ObNumberFloatType */ - ObIntervalYMType, /* ObNVarchar2Type */ - ObIntervalYMType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObIntervalYMType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObIntervalYMType, /* ObMySQLDateType */ - ObIntervalYMType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObIntervalDSType*/ - { - ObMaxType, /* NullType */ - ObIntervalDSType, /* TinyIntType */ - ObIntervalDSType, /* SmallIntType */ - ObIntervalDSType, /* MediumIntType */ - ObIntervalDSType, /* Int32Type */ - ObIntervalDSType, /* IntType */ - ObIntervalDSType, /* UTinyIntType */ - ObIntervalDSType, /* USmallIntType */ - ObIntervalDSType, /* UMediumIntType */ - ObIntervalDSType, /* UInt32Type */ - ObIntervalDSType, /* UIntType */ - ObIntervalDSType, /* FloatType */ - ObIntervalDSType, /* DoubleType */ - ObIntervalDSType, /* UFloatType */ - ObIntervalDSType, /* UDoubleType */ - ObIntervalDSType, /* NumberType */ - ObIntervalDSType, /* UNumberType */ - ObIntervalDSType, /* DateTimeType */ - ObIntervalDSType, /* TimestampType */ - ObIntervalDSType, /* DateType */ - ObIntervalDSType, /* TimeType */ - ObIntervalDSType, /* YearType */ - ObIntervalDSType, /* VarcharType */ - ObIntervalDSType, /* CharType */ - ObIntervalDSType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObIntervalDSType, /* TinyTextType*/ - ObIntervalDSType, /* TextType*/ - ObIntervalDSType, /* MediumTextType*/ - ObIntervalDSType, /* LongTextType*/ - ObIntervalDSType, /* BitType*/ - ObMaxType, /* EnumType*/ - ObMaxType, /* SetType*/ - ObMaxType, /* EnumInnerType*/ - ObMaxType, /* SetInnerType*/ - ObIntervalDSType, /* ObTimestampTZType */ - ObIntervalDSType, /* ObTimestampLTZType */ - ObIntervalDSType, /* ObTimestampNanoType */ - ObIntervalDSType, /* ObRawType */ - ObIntervalDSType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObIntervalDSType, /* ObNumberFloatType */ - ObIntervalDSType, /* ObNVarchar2Type */ - ObIntervalDSType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObIntervalDSType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObIntervalDSType, /* ObMySQLDateType */ - ObIntervalDSType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*NumberFloatType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNumberType, /* VarcharType */ - ObNumberType, /* CharType */ - ObNumberType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObNumberType, /*TinyTextType*/ - ObNumberType, /*TextType*/ - ObNumberType, /*MediumTextType*/ - ObNumberType, /*LongTextType*/ - ObNumberType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNumberType, /* ObNVarchar2Type */ - ObNumberType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObDoubleType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObNumberType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*NVarchar2Type*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNVarchar2Type, /* VarcharType */ - ObNVarchar2Type, /* CharType */ - ObNVarchar2Type, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMediumTextType, /*TinyTextType*/ - ObMediumTextType, /*TextType*/ - ObMediumTextType, /*MediumTextType*/ - ObMediumTextType, /*LongTextType*/ - ObNumberType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNVarchar2Type, /* ObNVarchar2Type */ - ObNVarchar2Type, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*NCharType*/ - { - ObMaxType, /* NullType */ - ObNumberType, /* TinyIntType */ - ObNumberType, /* SmallIntType */ - ObNumberType, /* MediumIntType */ - ObNumberType, /* Int32Type */ - ObNumberType, /* IntType */ - ObNumberType, /* UTinyIntType */ - ObNumberType, /* USmallIntType */ - ObNumberType, /* UMediumIntType */ - ObNumberType, /* UInt32Type */ - ObNumberType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateTimeType, /* DateType */ - ObTimeType, /* TimeType */ - ObNumberType, /* YearType */ - ObNVarchar2Type, /* VarcharType */ - ObNCharType, /* CharType */ - ObVarcharType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMediumTextType, /*TinyTextType*/ - ObMediumTextType, /*TextType*/ - ObMediumTextType, /*MediumTextType*/ - ObMediumTextType, /*LongTextType*/ - ObNumberType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObNVarchar2Type, /* ObNVarchar2Type */ - ObNCharType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObURowIDType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObMaxType, /*BitType*/ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObLobType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObMaxType, /*BitType*/ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObJsonType*/ - { - ObMaxType, /* NullType */ - ObJsonType, /* TinyIntType */ - ObJsonType, /* SmallIntType */ - ObJsonType, /* MediumIntType */ - ObJsonType, /* Int32Type */ - ObJsonType, /* IntType */ - ObJsonType, /* UTinyIntType */ - ObJsonType, /* USmallIntType */ - ObJsonType, /* UMediumIntType */ - ObJsonType, /* UInt32Type */ - ObJsonType, /* UIntType */ - ObJsonType, /* FloatType */ - ObJsonType, /* DoubleType */ - ObJsonType, /* UFloatType */ - ObJsonType, /* UDoubleType */ - ObJsonType, /* NumberType */ - ObJsonType, /* UNumberType */ - ObJsonType, /* DateTimeType */ - ObJsonType, /* TimestampType */ - ObJsonType, /* DateType */ - ObJsonType, /* TimeType */ - ObJsonType, /* YearType */ - ObJsonType, /* VarcharType */ - ObJsonType, /* CharType */ - ObJsonType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObJsonType, /* UnknownType */ - ObJsonType, /*TinyTextType*/ - ObJsonType, /*TextType*/ - ObJsonType, /*MediumTextType*/ - ObJsonType, /*LongTextType*/ - ObJsonType, /*BitType*/ - ObNumberType, /* EnumType */ - ObNumberType, /* SetType */ - ObNumberType, /* EnumInnerType */ - ObNumberType, /* SetInnerType */ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObVarcharType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObJsonType, /* ObGeometryType*/ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObJsonType, /* ObMySQLDateType */ - ObJsonType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObGeometryType*/ - { - ObMaxType, /* NullType */ - ObDoubleType, /* TinyIntType */ - ObDoubleType, /* SmallIntType */ - ObDoubleType, /* MediumIntType */ - ObDoubleType, /* Int32Type */ - ObDoubleType, /* IntType */ - ObDoubleType, /* UTinyIntType */ - ObDoubleType, /* USmallIntType */ - ObDoubleType, /* UMediumIntType */ - ObDoubleType, /* UInt32Type */ - ObDoubleType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObHexStringType, /* TimeType */ - ObDoubleType, /* YearType */ - ObHexStringType, /* VarcharType */ - ObHexStringType, /* CharType */ - ObHexStringType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObDoubleType, /*BitType*/ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /* EnumInnerType */ - ObMaxType, /* SetInnerType */ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObDoubleType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObHexStringType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObUserDefinedSQLType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObMaxType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*DecimalIntType*/ - { - ObMaxType, /* NullType */ - ObDecimalIntType, /* TinyIntType */ - ObDecimalIntType, /* SmallIntType */ - ObDecimalIntType, /* MediumIntType */ - ObDecimalIntType, /* Int32Type */ - ObDecimalIntType, /* IntType */ - ObDecimalIntType, /* UTinyIntType */ - ObDecimalIntType, /* USmallIntType */ - ObDecimalIntType, /* UMediumIntType */ - ObDecimalIntType, /* UInt32Type */ - ObDecimalIntType, /* UIntType */ - ObDoubleType, /* FloatType */ - ObDoubleType, /* DoubleType */ - ObDoubleType, /* UFloatType */ - ObDoubleType, /* UDoubleType */ - ObNumberType, /* NumberType */ - ObNumberType, /* UNumberType */ - ObDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObDateType, /* DateType */ - ObTimeType, /* TimeType */ - ObDecimalIntType, /* YearType */ - ObDecimalIntType, /* VarcharType */ - ObDecimalIntType, /* CharType */ - ObDecimalIntType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObDecimalIntType, /*TinyTextType*/ - ObDecimalIntType, /*TextType*/ - ObDecimalIntType, /*MediumTextType*/ - ObDecimalIntType, /*LongTextType*/ - ObDecimalIntType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObNumberType, /* ObNumberFloatType */ - ObDecimalIntType, /* ObNVarchar2Type */ - ObDecimalIntType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObDecimalIntType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObCollectionSQLType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /*TinyTextType*/ - ObMaxType, /*TextType*/ - ObMaxType, /*MediumTextType*/ - ObMaxType, /*LongTextType*/ - ObMaxType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - - /*MySQLDateType*/ - { - ObMaxType, /* NullType */ - ObMySQLDateType, /* TinyIntType */ - ObMySQLDateType, /* SmallIntType */ - ObMySQLDateType, /* MediumIntType */ - ObMySQLDateType, /* Int32Type */ - ObMySQLDateType, /* IntType */ - ObMySQLDateType, /* UTinyIntType */ - ObMySQLDateType, /* USmallIntType */ - ObMySQLDateType, /* UMediumIntType */ - ObMySQLDateType, /* UInt32Type */ - ObMySQLDateType, /* UIntType */ - ObMySQLDateType, /* FloatType */ - ObMySQLDateType, /* DoubleType */ - ObMySQLDateType, /* UFloatType */ - ObMySQLDateType, /* UDoubleType */ - ObMySQLDateType, /* NumberType */ - ObMySQLDateType, /* UNumberType */ - ObMySQLDateTimeType, /* DateTimeType */ - ObTimestampType, /* TimestampType */ - ObMySQLDateType, /* DateType */ - ObMySQLDateTimeType, /* TimeType */ - ObVarcharType, /* YearType */ - ObMySQLDateTimeType, /* VarcharType */ - ObMySQLDateTimeType, /* CharType */ - ObMySQLDateTimeType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMySQLDateTimeType, /*TinyTextType*/ - ObMySQLDateTimeType, /*TextType*/ - ObMySQLDateTimeType, /*MediumTextType*/ - ObMySQLDateTimeType, /*LongTextType*/ - ObMySQLDateType, /* BitType */ - ObMaxType, /* EnumType */ - ObMaxType, /* SetType */ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObMySQLDateType, /* ObNumberFloatType */ - ObMySQLDateTimeType, /* ObNVarchar2Type */ - ObMySQLDateTimeType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMySQLDateType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*MySQLDateTimeType*/ - { - ObMaxType, /* NullType */ - ObMySQLDateTimeType, /* TinyIntType */ - ObMySQLDateTimeType, /* SmallIntType */ - ObMySQLDateTimeType, /* MediumIntType */ - ObMySQLDateTimeType, /* Int32Type */ - ObMySQLDateTimeType, /* IntType */ - ObMySQLDateTimeType, /* UTinyIntType */ - ObMySQLDateTimeType, /* USmallIntType */ - ObMySQLDateTimeType, /* UMediumIntType */ - ObMySQLDateTimeType, /* UInt32Type */ - ObMySQLDateTimeType, /* UIntType */ - ObMySQLDateTimeType, /* FloatType */ - ObMySQLDateTimeType, /* DoubleType */ - ObMySQLDateTimeType, /* UFloatType */ - ObMySQLDateTimeType, /* UDoubleType */ - ObMySQLDateTimeType, /* NumberType */ - ObMySQLDateTimeType, /* UNumberType */ - ObMySQLDateTimeType, /* DateTimeType */ - ObMySQLDateTimeType, /* TimestampType */ - ObMySQLDateTimeType, /* DateType */ - ObMySQLDateTimeType, /* TimeType */ - ObVarcharType, /* YearType */ - ObMySQLDateTimeType, /* VarcharType */ - ObMySQLDateTimeType, /* CharType */ - ObMySQLDateTimeType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMySQLDateTimeType, /*TinyTextType*/ - ObMySQLDateTimeType, /*TextType*/ - ObMySQLDateTimeType, /*MediumTextType*/ - ObMySQLDateTimeType, /*LongTextType*/ - ObMySQLDateTimeType, /*BitType*/ - ObMaxType, /*EnumType*/ - ObMaxType, /*SetType*/ - ObMaxType, /*EnumInnerType*/ - ObMaxType, /*SetInnerType*/ - ObTimestampTZType, /* ObTimestampTZType */ - ObTimestampLTZType, /* ObTimestampLTZType */ - ObTimestampNanoType, /* ObTimestampNanoType */ - ObRawType, /* ObRawType */ - ObIntervalYMType, /* ObIntervalYMType */ - ObIntervalDSType, /* ObIntervalDSType */ - ObMySQLDateTimeType, /* ObNumberFloatType */ - ObMySQLDateTimeType, /* ObNVarchar2Type */ - ObMySQLDateTimeType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObJsonType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMySQLDateTimeType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMySQLDateTimeType, /* ObMySQLDateType */ - ObMySQLDateTimeType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - }, - /*ObRoaringBitmapType*/ - { - ObMaxType, /* NullType */ - ObMaxType, /* TinyIntType */ - ObMaxType, /* SmallIntType */ - ObMaxType, /* MediumIntType */ - ObMaxType, /* Int32Type */ - ObMaxType, /* IntType */ - ObMaxType, /* UTinyIntType */ - ObMaxType, /* USmallIntType */ - ObMaxType, /* UMediumIntType */ - ObMaxType, /* UInt32Type */ - ObMaxType, /* UIntType */ - ObMaxType, /* FloatType */ - ObMaxType, /* DoubleType */ - ObMaxType, /* UFloatType */ - ObMaxType, /* UDoubleType */ - ObMaxType, /* NumberType */ - ObMaxType, /* UNumberType */ - ObMaxType, /* DateTimeType */ - ObMaxType, /* TimestampType */ - ObMaxType, /* DateType */ - ObMaxType, /* TimeType */ - ObMaxType, /* YearType */ - ObMaxType, /* VarcharType */ - ObMaxType, /* CharType */ - ObMaxType, /* HexStringType */ - ObMaxType, /* ExtendType */ - ObMaxType, /* UnknownType */ - ObMaxType, /* TinyTextType*/ - ObMaxType, /* TextType*/ - ObMaxType, /* MediumTextType*/ - ObMaxType, /* LongTextType*/ - ObMaxType, /* BitType*/ - ObMaxType, /* EnumType*/ - ObMaxType, /* SetType*/ - ObMaxType, /* EnumInnerType*/ - ObMaxType, /* SetInnerType*/ - ObMaxType, /* ObTimestampTZType */ - ObMaxType, /* ObTimestampLTZType */ - ObMaxType, /* ObTimestampNanoType */ - ObMaxType, /* ObRawType */ - ObMaxType, /* ObIntervalYMType */ - ObMaxType, /* ObIntervalDSType */ - ObMaxType, /* ObNumberFloatType */ - ObMaxType, /* ObNVarchar2Type */ - ObMaxType, /* ObNCharType */ - ObMaxType, /* ObURowIDType */ - ObMaxType, /* ObLobType */ - ObMaxType, /* ObJsonType */ - ObMaxType, /* ObGeometryType */ - ObMaxType, /* ObUserDefinedSQLType */ - ObMaxType, /* ObDecimalIntType */ - ObMaxType, /* ObCollectionSQLType */ - ObMaxType, /* ObMySQLDateType */ - ObMaxType, /* ObMySQLDateTimeType */ - ObMaxType, /* ObRoaringBitmapType */ - } + ObMaxType, /* NullType */ + ObIntType, /* TinyIntType */ + ObIntType, /* SmallIntType */ + ObIntType, /* MediumIntType */ + ObIntType, /* Int32Type */ + ObIntType, /* IntType */ + ObIntType, /* UTinyIntType */ + ObIntType, /* USmallIntType */ + ObIntType, /* UMediumIntType */ + ObIntType, /* UInt32Type */ + ObIntType, /* UIntType */ + ObFloatType, /* FloatType */ + ObDoubleType, /* DoubleType */ + ObFloatType, /* UFloatType */ + ObDoubleType, /* UDoubleType */ + ObNumberType, /* NumberType */ + ObNumberType, /* UNumberType */ + ObDateTimeType, /* DateTimeType */ + ObTimestampType, /* TimestampType */ + ObDateType, /* DateType */ + ObTimeType, /* TimeType */ + ObYearType, /* YearType */ + ObVarcharType, /* VarcharType */ + ObVarcharType, /* CharType */ + ObHexStringType, /* HexStringType */ + ObMaxType, /* ExtendType */ + ObMaxType, /* UnknownType */ + ObVarcharType, /* TinyTextType */ + ObVarcharType, /* TextType */ + ObVarcharType, /* MediumTextType */ + ObVarcharType, /* LongTextType */ + ObBitType, /* BitType */ + ObMaxType, /* ObEnumType */ + ObMaxType, /* ObSetType */ + ObMaxType, /* ObEnumInnerType */ + ObMaxType, /* ObSetInnerType */ + ObMaxType, /* ObTimestampTZType */ + ObMaxType, /* ObTimestampLTZType */ + ObMaxType, /* ObTimestampNanoType */ + ObMaxType, /* ObRawType */ + ObMaxType, /* ObIntervalYMType */ + ObMaxType, /* ObIntervalDSType */ + ObMaxType, /* ObNumberFloatType */ + ObMaxType, /* ObNVarchar2Type */ + ObMaxType, /* ObNCharType */ + ObMaxType, /* ObURowIDType */ + ObMaxType, /* ObLobType */ + ObJsonType, /* ObJsonType */ + ObGeometryType, /* ObGeometryType */ + ObMaxType, /* ObUserDefinedSqlType */ + ObDecimalIntType, /* ObDecimalIntType */ + ObMaxType, /* ObCollectionSQLType */ + ObMaxType, /* ObMySQLDateType */ + ObMaxType, /* ObMySQLDateTimeType */ + ObMaxType, /* ObRoaringBitmapType */ }; -static_assert(is_array_fully_initialized(RELATIONAL_EQUAL_TYPE, ObMaxType), "RELATIONAL_EQUAL_TYPE is partially initlized"); - +static constexpr ObObjType ORACLE_RELATIONAL_EQUAL_TYPE[ObMaxType] = +{ + ObMaxType, /* NullType */ + ObMaxType, /* TinyIntType */ + ObMaxType, /* SmallIntType */ + ObMaxType, /* MediumIntType */ + ObMaxType, /* Int32Type */ + ObMaxType, /* IntType */ + ObMaxType, /* UTinyIntType */ + ObMaxType, /* USmallIntType */ + ObMaxType, /* UMediumIntType */ + ObMaxType, /* UInt32Type */ + ObMaxType, /* UIntType */ + ObFloatType, /* FloatType */ + ObDoubleType, /* DoubleType */ + ObMaxType, /* UFloatType */ + ObMaxType, /* UDoubleType */ + ObNumberType, /* NumberType */ + ObMaxType, /* UNumberType */ + ObDateTimeType, /* DateTimeType */ + ObMaxType, /* TimestampType */ + ObMaxType, /* DateType */ + ObMaxType, /* TimeType */ + ObMaxType, /* YearType */ + ObVarcharType, /* VarcharType */ + ObCharType, /* CharType */ + ObMaxType, /* HexStringType */ + ObMaxType, /* ExtendType */ + ObMaxType, /* UnknownType */ + ObMaxType, /* TinyTextType */ + ObMaxType, /* TextType */ + ObMaxType, /* MediumTextType */ + ObLongTextType, /* LongTextType */ + ObMaxType, /* BitType */ + ObMaxType, /* ObEnumType */ + ObMaxType, /* ObSetType */ + ObMaxType, /* ObEnumInnerType */ + ObMaxType, /* ObSetInnerType */ + ObTimestampTZType, /* ObTimestampTZType */ + ObTimestampLTZType, /* ObTimestampLTZType */ + ObTimestampNanoType, /* ObTimestampNanoType */ + ObRawType, /* ObRawType */ + ObIntervalYMType, /* ObIntervalYMType */ + ObIntervalDSType, /* ObIntervalDSType */ + ObNumberFloatType, /* ObNumberFloatType */ + ObNVarchar2Type, /* ObNVarchar2Type */ + ObNCharType, /* ObNCharType */ + ObURowIDType, /* ObURowIDType */ + ObMaxType, /* ObLobType */ + ObJsonType, /* ObJsonType */ + ObGeometryType, /* ObGeometryType */ + ObMaxType, /* ObUserDefinedSqlType */ + ObDecimalIntType, /* ObDecimalIntType */ + ObMaxType, /* ObCollectionSQLType */ + ObMaxType, /* ObMySQLDateType */ + ObMaxType, /* ObMySQLDateTimeType */ + ObMaxType, /* ObRoaringBitmapType */ +}; +static_assert(is_array_fully_initialized(RELATIONAL_EQUAL_TYPE), "RELATIONAL_EQUAL_TYPE is partially initlized"); +static_assert(is_array_fully_initialized(ORACLE_RELATIONAL_EQUAL_TYPE), "ORACLE_RELATIONAL_EQUAL_TYPE is partially initlized"); diff --git a/src/sql/engine/expr/ob_expr_res_type.h b/src/sql/engine/expr/ob_expr_res_type.h index f01f7f1afe..9d18ab3681 100644 --- a/src/sql/engine/expr/ob_expr_res_type.h +++ b/src/sql/engine/expr/ob_expr_res_type.h @@ -365,6 +365,11 @@ public: // } return seed; } + int hash(uint64_t &hash_val, uint64_t seed) const + { + hash_val = hash(seed); + return OB_SUCCESS; + } // others. INHERIT_TO_STRING_KV(N_META, ObObjMeta, diff --git a/src/sql/engine/expr/ob_expr_result_type_util.cpp b/src/sql/engine/expr/ob_expr_result_type_util.cpp index e8d17dbc7b..ce903e859c 100644 --- a/src/sql/engine/expr/ob_expr_result_type_util.cpp +++ b/src/sql/engine/expr/ob_expr_result_type_util.cpp @@ -118,10 +118,10 @@ int ObExprResultTypeUtil::get_relational_equal_type(ObObjType &type, ret = OB_ERR_UNEXPECTED; LOG_ERROR("the wrong type", K(type1), K(type2), K(ret)); } else { - // we donot have ORACLE_RELATIONAL_EQUAL_TYPE, just use ORACLE_RELATIONAL_CMP_TYPE instead. - type = (lib::is_oracle_mode() - ? ORACLE_RELATIONAL_CMP_TYPE[type1][type2] - : RELATIONAL_EQUAL_TYPE[type1][type2]); + const ObObjType *equal_type_array = lib::is_oracle_mode() + ? ORACLE_RELATIONAL_EQUAL_TYPE + : RELATIONAL_EQUAL_TYPE; + type = equal_type_array[type1] == equal_type_array[type2] ? equal_type_array[type1] : ObMaxType; } return ret; } diff --git a/src/sql/engine/table/ob_table_scan_op.cpp b/src/sql/engine/table/ob_table_scan_op.cpp index 8a03d742db..89323b1c40 100644 --- a/src/sql/engine/table/ob_table_scan_op.cpp +++ b/src/sql/engine/table/ob_table_scan_op.cpp @@ -1333,11 +1333,6 @@ int ObTableScanOp::build_bnlj_params() OZ(tsc_rtdef_.bnlj_params_.push_back(GroupRescanParamInfo(param_idx, group_param.gr_param_))); } } - if (OB_SUCC(ret) && tsc_rtdef_.bnlj_params_.empty()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("batch param is empty in batch rescan", K(ret), - K(MY_CTDEF.bnlj_param_idxs_), KPC(group_params_above)); - } if (OB_SUCC(ret) && (OB_ISNULL(fold_iter_))) { if (OB_FAIL(ObDASIterUtils::create_group_fold_iter(MY_CTDEF, tsc_rtdef_, diff --git a/src/sql/monitor/ob_sql_plan.cpp b/src/sql/monitor/ob_sql_plan.cpp index 7de83570f1..fcc7e312ae 100644 --- a/src/sql/monitor/ob_sql_plan.cpp +++ b/src/sql/monitor/ob_sql_plan.cpp @@ -864,57 +864,60 @@ int ObSqlPlan::get_plan_other_info(PlanText &plan_text, LOG_WARN("unexpect null param", K(ret)); } else { ObObjPrintParams print_params(query_ctx->get_timezone_info()); - BEGIN_BUF_PRINT ObPhyPlanType plan_type = plan->get_optimizer_context().get_phy_plan_type(); - if (OB_FAIL(BUF_PRINTF(" Plan Type:"))) { - } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { - } else if (OB_FAIL(BUF_PRINTF(OUTPUT_PREFIX))) { - } else if (OB_FAIL(BUF_PRINTF("%.*s", - ob_plan_type_str(plan_type).length(), - ob_plan_type_str(plan_type).ptr()))) { - } else { - ret = BUF_PRINTF(NEW_LINE); - } - - const ParamStore *params = NULL; - if (OB_FAIL(ret)) { - } else if (OB_ISNULL(params = plan->get_optimizer_context().get_params())) { - ret = OB_ERR_UNEXPECTED; - } else if (params->count() <= 0) { - //do nothing - } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { - } else if (OB_FAIL(BUF_PRINTF(" Parameters:"))) { - } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { - } else { /* Do nothing */ } - for (int64_t i = 0; OB_SUCC(ret) && NULL != params && i < params->count() && i < 100; i++) { - if (OB_FAIL(BUF_PRINTF(OUTPUT_PREFIX))) { - } else if (OB_FAIL(BUF_PRINTF(":%ld => ", i))) { + ret = OB_E(EventTable::EN_PRINT_CONSTRAINTS_INFO) OB_SUCCESS; + bool only_show_constraint = OB_SUCCESS != ret && EXPLAIN_UNINITIALIZED == plan_text.type_; + ret = OB_SUCCESS; + BEGIN_BUF_PRINT + if (OB_SUCC(ret) && !only_show_constraint) { + if (OB_FAIL(BUF_PRINTF(" Plan Type:"))) { + } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { + } else if (OB_FAIL(BUF_PRINTF(OUTPUT_PREFIX))) { + } else if (OB_FAIL(BUF_PRINTF("%.*s", + ob_plan_type_str(plan_type).length(), + ob_plan_type_str(plan_type).ptr()))) { } else { - int64_t save_pos = pos; - if (OB_FAIL(params->at(i).print_sql_literal(buf, - buf_len, - pos, - print_params))) { - //ignore size overflow error - pos = save_pos; - } - if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { - } else { /* Do nothing */ } - } - } - - const ObPlanNotes ¬es = plan->get_optimizer_context().get_plan_notes(); - if (notes.count() <= 0 || OB_FAIL(ret)) { - } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { /* Do nothing */ - } else if (OB_FAIL(BUF_PRINTF(" Note:"))) { /* Do nothing */ - } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { /* Do nothing */ - } - for (int64_t i = 0; OB_SUCC(ret) && i < notes.count(); i++) { - if (OB_FAIL(BUF_PRINTF(OUTPUT_PREFIX))) { - } else { - pos += notes.at(i).to_string(buf + pos, buf_len - pos); ret = BUF_PRINTF(NEW_LINE); } + const ParamStore *params = NULL; + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(params = plan->get_optimizer_context().get_params())) { + ret = OB_ERR_UNEXPECTED; + } else if (params->count() <= 0) { + //do nothing + } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { + } else if (OB_FAIL(BUF_PRINTF(" Parameters:"))) { + } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { + } else { /* Do nothing */ } + for (int64_t i = 0; OB_SUCC(ret) && NULL != params && i < params->count() && i < 100; i++) { + if (OB_FAIL(BUF_PRINTF(OUTPUT_PREFIX))) { + } else if (OB_FAIL(BUF_PRINTF(":%ld => ", i))) { + } else { + int64_t save_pos = pos; + if (OB_FAIL(params->at(i).print_sql_literal(buf, + buf_len, + pos, + print_params))) { + //ignore size overflow error + pos = save_pos; + } + if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { + } else { /* Do nothing */ } + } + } + const ObPlanNotes ¬es = plan->get_optimizer_context().get_plan_notes(); + if (notes.count() <= 0 || OB_FAIL(ret)) { + } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { /* Do nothing */ + } else if (OB_FAIL(BUF_PRINTF(" Note:"))) { /* Do nothing */ + } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { /* Do nothing */ + } + for (int64_t i = 0; OB_SUCC(ret) && i < notes.count(); i++) { + if (OB_FAIL(BUF_PRINTF(OUTPUT_PREFIX))) { + } else { + pos += notes.at(i).to_string(buf + pos, buf_len - pos); + ret = BUF_PRINTF(NEW_LINE); + } + } } if (OB_SUCC(ret)) { if (OB_FAIL(get_constraint_info(buf, buf_len, pos, *query_ctx))) { @@ -1100,6 +1103,19 @@ int ObSqlPlan::format_sql_plan(ObIArray &sql_plan_infos, } else if (OB_FAIL(format_plan_output(sql_plan_infos, plan_text))) { LOG_WARN("failed to print plan output", K(ret)); } + } else if (EXPLAIN_UNINITIALIZED == type) { + if (OB_FAIL(format_plan_table(sql_plan_infos, option, plan_text))) { + LOG_WARN("failed to print plan", K(ret)); + } else if (OB_FAIL(format_plan_output(sql_plan_infos, plan_text))) { + LOG_WARN("failed to print plan output", K(ret)); + } else { + ret = OB_E(EventTable::EN_PRINT_CONSTRAINTS_INFO) OB_SUCCESS; + bool only_show_constraint = OB_SUCCESS != ret; + ret = OB_SUCCESS; + if (only_show_constraint && OB_FAIL(format_other_info(sql_plan_infos, plan_text))) { + LOG_WARN("failed to print other info", K(ret)); + } + } } else if (EXPLAIN_OUTLINE == type) { if (OB_FAIL(format_plan_table(sql_plan_infos, option, plan_text))) { LOG_WARN("failed to print plan", K(ret)); diff --git a/src/sql/ob_optimizer_trace_impl.cpp b/src/sql/ob_optimizer_trace_impl.cpp index e6f3762183..61ede4af78 100644 --- a/src/sql/ob_optimizer_trace_impl.cpp +++ b/src/sql/ob_optimizer_trace_impl.cpp @@ -682,8 +682,8 @@ int ObOptimizerTraceImpl::append(const JoinPath* join_path) new_line(); append("tables:", join_path->right_path_->parent_); new_line(); - new_line(); append_ptr(join_path->right_path_); + new_line(); append("cost:", join_path->right_path_->cost_, ",card:", join_path->right_path_->parent_->get_output_rows(), ",width:", join_path->right_path_->parent_->get_output_row_size()); new_line(); @@ -1082,6 +1082,8 @@ int ObOptimizerTraceImpl::trace_static(const ObDMLStmt *stmt, OptTableMetas &tab LOG_WARN("failed to append msg", K(ret)); } else if (OB_FAIL(append("rows:", table_meta->get_rows(), + "base rows:", + table_meta->get_base_rows(), "statis type:", table_meta->use_default_stat() ? "DEFAULT" : "OPTIMIZER", "version:", @@ -1110,6 +1112,10 @@ int ObOptimizerTraceImpl::trace_static(const ObDMLStmt *stmt, OptTableMetas &tab LOG_WARN("failed to append msg", K(ret)); } else if (OB_FAIL(new_line())) { LOG_WARN("failed to append msg", K(ret)); + } else if (OB_FAIL(append("BASE NDV:", col_meta->get_base_ndv()))) { + LOG_WARN("failed to append msg", K(ret)); + } else if (OB_FAIL(new_line())) { + LOG_WARN("failed to append msg", K(ret)); } else if (OB_FAIL(append("Null:", col_meta->get_num_null()))) { LOG_WARN("failed to append msg", K(ret)); } else if (OB_FAIL(new_line())) { diff --git a/src/sql/ob_sql.cpp b/src/sql/ob_sql.cpp index 58b8070aac..3ea8a64eec 100644 --- a/src/sql/ob_sql.cpp +++ b/src/sql/ob_sql.cpp @@ -3023,10 +3023,10 @@ int ObSql::generate_stmt(ParseResult &parse_result, if (OB_SUCC(ret)) { // set # of question marks if (context.is_prepare_protocol_ && !context.is_prepare_stage_) { - resolver_ctx.query_ctx_->question_marks_count_ = plan_ctx->get_param_store().count(); + resolver_ctx.query_ctx_->set_questionmark_count(plan_ctx->get_param_store().count()); LOG_DEBUG("question mark size is ", K(plan_ctx->get_param_store())); } else { - resolver_ctx.query_ctx_->question_marks_count_ = static_cast (parse_result.question_mark_ctx_.count_); + resolver_ctx.query_ctx_->set_questionmark_count(static_cast(parse_result.question_mark_ctx_.count_)); LOG_DEBUG("question mark size is ", K(parse_result.question_mark_ctx_.count_)); } @@ -4420,6 +4420,8 @@ int ObSql::parser_and_check(const ObString &outlined_stmt, ObPhysicalPlanCtx *pctx = exec_ctx.get_physical_plan_ctx(); bool is_stack_overflow = false; bool is_show_variables = false; + bool is_explain_parameterize = false; + stmt::StmtType stmt_type = stmt::T_NONE; if (OB_ISNULL(session)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("session is null", K(ret)); @@ -4530,6 +4532,17 @@ int ObSql::parser_and_check(const ObString &outlined_stmt, } } } + if (OB_SUCC(ret) && stmt::T_EXPLAIN == stmt_type) { +#ifndef OB_BUILD_SPM + if (OB_SQL_PC_NOT_EXIST == get_plan_err) { +#else + if (OB_SQL_PC_NOT_EXIST == get_plan_err || pc_ctx.sql_ctx_.spm_ctx_.is_retry_for_spm_) { +#endif + is_explain_parameterize = true; + } else { + is_explain_parameterize = false; + } + } } } } @@ -4567,10 +4580,11 @@ int ObSql::parser_and_check(const ObString &outlined_stmt, //对于create outline限流语句,可能会带有问题。我们需要对?做特殊处理, //所以也需要经过transform_systax_tree bool flag = false; - if ((add_plan_to_pc && !is_show_variables) - || ((T_CREATE_OUTLINE == parse_result.result_tree_->children_[0]->type_ - || T_ALTER_OUTLINE == parse_result.result_tree_->children_[0]->type_) - && (INT64_MAX != parse_result.result_tree_->children_[0]->value_))) { + if ((add_plan_to_pc && !is_show_variables) || + is_explain_parameterize || + ((T_CREATE_OUTLINE == parse_result.result_tree_->children_[0]->type_ || + T_ALTER_OUTLINE == parse_result.result_tree_->children_[0]->type_) && + (INT64_MAX != parse_result.result_tree_->children_[0]->value_))) { flag = true; if (T_CREATE_OUTLINE == parse_result.result_tree_->children_[0]->type_) { if (1 != parse_result.result_tree_->children_[0]->children_[2]->value_) { @@ -5232,9 +5246,10 @@ OB_NOINLINE int ObSql::handle_physical_plan(const ObString &trimed_stmt, (void) ObSpmController::deny_new_plan_as_baseline(spm_ctx); } } else if (plan_added && ObSpmCacheCtx::SpmStat::STAT_ADD_BASELINE_PLAN == spm_ctx.spm_stat_) { - if (nullptr != spm_ctx.baseline_guard_.get_cache_obj() && - static_cast(spm_ctx.baseline_guard_.get_cache_obj())->get_fixed()) { - // fixed baseline plan, use is directly + if ((nullptr != spm_ctx.baseline_guard_.get_cache_obj() && + static_cast(spm_ctx.baseline_guard_.get_cache_obj())->get_fixed()) || + SPM_MODE_BASELINE_FIRST == spm_ctx.spm_mode_) { + // fixed baseline plan or baseline first mode, use is directly } else { spm_ctx.spm_force_disable_ = true; spm_ctx.spm_stat_ = ObSpmCacheCtx::STAT_FIRST_EXECUTE_PLAN; diff --git a/src/sql/ob_sql_context.h b/src/sql/ob_sql_context.h index 3f9e7ed213..d5752fd4c0 100644 --- a/src/sql/ob_sql_context.h +++ b/src/sql/ob_sql_context.h @@ -778,7 +778,8 @@ public: optimizer_features_enable_version_(0), udf_flag_(0), has_dblink_(false), - injected_random_status_(false) + injected_random_status_(false), + ori_question_marks_count_(0) { } TO_STRING_KV(N_PARAM_NUM, question_marks_count_, @@ -822,6 +823,7 @@ public: root_stmt_ = NULL; udf_flag_ = 0; optimizer_features_enable_version_ = 0; + ori_question_marks_count_ = 0; } int64_t get_new_stmt_id() { return stmt_count_++; } @@ -862,7 +864,10 @@ public: bool check_opt_compat_version(uint64_t v1, uint64_t v2) const { return optimizer_features_enable_version_ >= v1 && optimizer_features_enable_version_ < v2; } - + void set_questionmark_count(int64_t count) { + ori_question_marks_count_ = count; + question_marks_count_ = count; + }; public: @@ -930,6 +935,7 @@ public: bool has_dblink_; bool injected_random_status_; ObRandom rand_gen_; + int64_t ori_question_marks_count_; }; template diff --git a/src/sql/ob_sql_define.h b/src/sql/ob_sql_define.h index ab7856b865..3cce3c6e3d 100644 --- a/src/sql/ob_sql_define.h +++ b/src/sql/ob_sql_define.h @@ -762,6 +762,10 @@ static int16_t get_type_fixed_length(ObObjType type) { return len; } +#define SPM_MODE_DISABLE 0 +#define SPM_MODE_ONLINE_EVOLVE 1 +#define SPM_MODE_BASELINE_FIRST 2 + } // namespace sql } // namespace oceanbase #endif /* OCEANBASE_SQL_OB_SQL_DEFINE_H_ */ diff --git a/src/sql/optimizer/ob_access_path_estimation.cpp b/src/sql/optimizer/ob_access_path_estimation.cpp index 931f6516da..486a19e2b0 100644 --- a/src/sql/optimizer/ob_access_path_estimation.cpp +++ b/src/sql/optimizer/ob_access_path_estimation.cpp @@ -354,7 +354,7 @@ int ObAccessPathEstimation::choose_best_est_method(ObOptimizerContext &ctx, ObSelEstimator *estimator = NULL; if (OB_FAIL(factory.create_estimator(*sel_ctx, filter, estimator))) { LOG_WARN("failed to create estimator", KPC(filter)); - } else if (estimator->tend_to_use_ds()) { + } else if (estimator->is_complex_filter_qual()) { is_complex_scene = true; // path which contains complex filters is complex LOG_PRINT_EXPR(TRACE, "Try to use dynamic sampling because of complex filter:", filter); @@ -2505,6 +2505,7 @@ int ObAccessPathEstimation::update_table_stat_info_by_dynamic_sampling(AccessPat LOG_WARN("failed to fill ds col stat", K(ret)); } else { table_meta->set_rows(row_count); + table_meta->set_base_rows(row_count); table_meta->set_use_ds_stat(); } } @@ -2524,6 +2525,7 @@ int ObAccessPathEstimation::update_table_stat_info_by_default(AccessPath *path) OptTableMeta *table_meta = table_metas.get_table_meta_by_table_id(path->table_id_); if (OB_NOT_NULL(table_meta)) { table_meta->set_rows(path->get_output_row_count()); + table_meta->set_base_rows(path->get_output_row_count()); for (int64_t i = 0; i < table_meta->get_column_metas().count(); ++i) { table_meta->get_column_metas().at(i).set_default_meta(path->get_output_row_count()); } @@ -2666,6 +2668,7 @@ int ObAccessPathEstimation::update_column_metas_by_ds_col_stat(const int64_t row if (!found_it) { col_metas.at(i).set_ndv(rowcount); } + col_metas.at(i).set_base_ndv(col_metas.at(i).get_ndv()); } LOG_TRACE("update column metas by ds col stat", K(ds_col_stats), K(col_metas), K(rowcount)); return ret; diff --git a/src/sql/optimizer/ob_join_order.cpp b/src/sql/optimizer/ob_join_order.cpp old mode 100644 new mode 100755 index 970d528248..dacfc6e707 --- a/src/sql/optimizer/ob_join_order.cpp +++ b/src/sql/optimizer/ob_join_order.cpp @@ -114,41 +114,6 @@ int ObJoinOrder::fill_query_range_info(const QueryRangeInfo &range_info, return ret; } -int ObJoinOrder::set_table_location_for_paths(ObIArray &access_paths, - ObIndexInfoCache &index_info_cache) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(get_plan()) || OB_ISNULL(allocator_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(get_plan()), K(allocator_), K(ret)); - } - // compute table location for global index - for (int64_t i = 0; OB_SUCC(ret) && i < access_paths.count(); ++i) { - AccessPath *path = NULL; - IndexInfoEntry *index_info_entry = NULL; - ObTablePartitionInfo *table_partition_info = NULL; - if (OB_ISNULL(path = access_paths.at(i))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(path), K(ret)); - } else if (OB_FAIL(index_info_cache.get_index_info_entry(path->table_id_, - path->index_id_, - index_info_entry))) { - LOG_WARN("get index info entry failed"); - } else if (OB_ISNULL(index_info_entry)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("index entry not found", K(ret)); - } else { - path->table_partition_info_ = index_info_entry->get_partition_info(); - } - if (OB_FAIL(ret)) { - } else if (OB_ISNULL(path->table_partition_info_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(i)); - } - } - return ret; -} - int ObJoinOrder::compute_table_location_for_index_info_entry(const uint64_t table_id, const uint64_t base_table_id, IndexInfoEntry *index_info_entry) { @@ -355,14 +320,13 @@ int ObJoinOrder::compute_sharding_info_for_base_paths(ObIArray &ac int ObJoinOrder::prune_paths_due_to_parallel(ObIArray &access_paths) { int ret = OB_SUCCESS; + AccessPath *path = NULL; if (access_paths.count() < 2) { /* do nothing */ - } else if (OB_ISNULL(access_paths.at(0)) || OB_ISNULL(get_plan())) { + } else if (OB_ISNULL(path = access_paths.at(0))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected params", K(ret), K(access_paths.empty()), K(get_plan())); - } else if (!is_virtual_table(access_paths.at(0)->ref_table_id_) - && (get_tables().is_subset(get_plan()->get_subq_pdfilter_tset()) - || access_paths.at(0)->is_inner_path_)) { + LOG_WARN("get unexpected null", K(ret), K(path)); + } else if (path->is_rescan_path()) { /* do nothing */ } else { ObSEArray tmp_paths; @@ -882,21 +846,23 @@ int ObJoinOrder::compute_base_table_parallel_and_server_info(const OpParallelRul int64_t final_parallel = parallel; ObSqlSchemaGuard *schema_guard = NULL; const ObTableSchema *index_schema = NULL; - if (OB_ISNULL(get_plan()) || OB_ISNULL(path) || + if (OB_ISNULL(get_plan()) || OB_ISNULL(path) || OB_ISNULL(path->table_partition_info_) || OB_ISNULL(schema_guard = get_plan()->get_optimizer_context().get_sql_schema_guard())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null param", K(ret), K(get_plan()), K(path)); + } else if (OB_FAIL(path->table_partition_info_->get_all_servers(path->server_list_))) { + LOG_WARN("failed to get all servers", K(ret)); } else if (path->use_das_) { - if (OB_FAIL(path->set_parallel_and_server_info_for_match_all())) { - LOG_WARN("failed set parallel and server info for match all", K(ret)); - } + // for das access path, fill server_list_ + path->op_parallel_rule_ = OpParallelRule::OP_DAS_DOP; + path->parallel_ = ObGlobalHint::DEFAULT_PARALLEL; + path->server_cnt_ = path->server_list_.count(); + path->available_parallel_ = ObGlobalHint::DEFAULT_PARALLEL; } else if (OB_FAIL(schema_guard->get_table_schema(path->index_id_, index_schema))) { LOG_WARN("failed to get table schema", K(ret)); } else if (OB_ISNULL(index_schema)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); - } else if (OB_FAIL(path->table_partition_info_->get_all_servers(path->server_list_))) { - LOG_WARN("failed to get all servers", K(ret)); } else { if (OpParallelRule::OP_TABLE_DOP == op_parallel_rule) { final_parallel = index_schema->get_dop(); @@ -1592,7 +1558,6 @@ int ObJoinOrder::check_index_subset(const OrderingInfo *first_ordering_info, } int ObJoinOrder::will_use_das(const uint64_t table_id, - const uint64_t ref_id, const uint64_t index_id, const ObIndexInfoCache &index_info_cache, PathHelper &helper, @@ -1602,117 +1567,115 @@ int ObJoinOrder::will_use_das(const uint64_t table_id, int ret = OB_SUCCESS; create_das_path = false; create_basic_path = false; - IndexInfoEntry *index_info_entry; - bool force_das_tsc = false; - bool is_batch_update_table = false; + if (OB_ISNULL(get_plan())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(get_plan())); + } else if (OB_FAIL(check_exec_force_use_das(table_id, create_das_path, create_basic_path))) { + LOG_WARN("failed to check exec force use das", K(ret)); + } else if (create_das_path || create_basic_path) { + LOG_TRACE("will use das by execution", K(create_das_path), K(create_basic_path)); + } else if (OB_FAIL(get_plan()->get_log_plan_hint().check_use_das(table_id, create_das_path, create_basic_path))) { + LOG_WARN("failed to check hint use das", K(ret)); + } else if (create_das_path || create_basic_path) { + LOG_TRACE("will use das by hint", K(create_das_path), K(create_basic_path)); + } else if (OB_FAIL(check_opt_rule_use_das(table_id, + index_id, + index_info_cache, + helper.filters_, + (get_plan()->get_is_rescan_subplan() || helper.is_inner_path_), + create_das_path, + create_basic_path))) { + LOG_WARN("failed to check opt rule use das", K(ret)); + } else { + LOG_TRACE("will use das by opt rule", K(create_das_path), K(create_basic_path)); + } + return ret; +} + +int ObJoinOrder::check_exec_force_use_das(const uint64_t table_id, + bool &create_das_path, + bool &create_basic_path) +{ + int ret = OB_SUCCESS; + create_das_path = false; + create_basic_path = false; const TableItem *table_item = nullptr; - bool is_sample_stmt = false; - bool is_online_ddl_insert = false; - if (OB_UNLIKELY(OB_INVALID_ID == ref_id) || OB_UNLIKELY(OB_INVALID_ID == index_id) || - OB_ISNULL(get_plan()) || OB_ISNULL(get_plan()->get_stmt())) { + ObSQLSessionInfo *session_info = NULL; + if (OB_ISNULL(get_plan()) || OB_ISNULL(get_plan()->get_stmt()) || + OB_ISNULL(session_info = get_plan()->get_optimizer_context().get_session_info())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ref_id), K(index_id), K(get_plan()), - K(table_item), K(ret)); - } else if (OB_FAIL(index_info_cache.get_index_info_entry(table_id, index_id, - index_info_entry))) { - LOG_WARN("failed to get index info entry", K(table_id), K(index_id), K(ret)); - } else if (OB_ISNULL(index_info_entry)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("index info entry should not be null", K(ret)); + LOG_WARN("get unexpected null", K(get_plan()), K(session_info), K(ret)); } else if (OB_ISNULL(table_item = get_plan()->get_stmt()->get_table_item_by_id(table_id))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("table_item is null", K(ret), K(table_id)); - } else if (get_plan()->get_optimizer_context().is_batched_multi_stmt()) { - if (table_item->is_basic_table()) { - is_batch_update_table = true; - } - } - if (OB_SUCC(ret) && OB_NOT_NULL(get_plan()->get_optimizer_context().get_root_stmt())) { - if (get_plan()->get_optimizer_context().is_online_ddl() && - get_plan()->get_optimizer_context().get_root_stmt()->is_insert_stmt()) { - is_online_ddl_insert = true; - } - } - if (OB_SUCC(ret) && get_plan()->get_stmt()->is_select_stmt()) { - const ObSelectStmt *stmt = static_cast(get_plan()->get_stmt()); - const SampleInfo *sample_info = table_item->sample_info_; - if (sample_info != NULL && !sample_info->is_no_sample()) { - is_sample_stmt = true; - } - } - bool enable_var_assign_use_das = false; - if (OB_SUCC(ret)) { - ObSQLSessionInfo *session_info = NULL; - if (OB_NOT_NULL(session_info = get_plan()->get_optimizer_context().get_session_info())) { - enable_var_assign_use_das = session_info->is_var_assign_use_das_enabled(); - } else { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("session info is null", K(ret)); - } - } - if(OB_SUCC(ret)) { - bool hint_force_das = false; - bool hint_force_no_das = false; - int64_t explicit_dop = ObGlobalHint::UNSET_PARALLEL; + } else { + ObOptimizerContext &opt_ctx = get_plan()->get_optimizer_context(); // TODO: access virtual table by remote das task is not supported, it will report 4016 error in execute server // Ensure that the following scenarios will not combined with virtual table - force_das_tsc = get_plan()->get_optimizer_context().in_nested_sql() || - get_plan()->get_optimizer_context().has_pl_udf() || - get_plan()->get_optimizer_context().has_dblink() || - get_plan()->get_optimizer_context().has_subquery_in_function_table() || - get_plan()->get_optimizer_context().has_cursor_expression() || - (get_plan()->get_optimizer_context().has_var_assign() && enable_var_assign_use_das && !is_virtual_table(ref_id)) || - is_batch_update_table; - if (!force_das_tsc - && table_item->for_update_ - && table_item->skip_locked_ - && NULL != get_plan()->get_optimizer_context().get_session_info() - && NULL != get_plan()->get_optimizer_context().get_session_info()->get_pl_context()) { - // select for update skip locked stmt in PL use das force - force_das_tsc = true; + bool force_das_tsc = opt_ctx.in_nested_sql() || //contain nested sql(pl udf or in nested sql), trigger or foreign key in the top sql not force to use DAS TSC + opt_ctx.has_pl_udf() || + opt_ctx.has_dblink() || + opt_ctx.has_subquery_in_function_table() || //has function table + opt_ctx.has_cursor_expression() || + (opt_ctx.has_var_assign() && session_info->is_var_assign_use_das_enabled()) || + (opt_ctx.is_batched_multi_stmt() && table_item->is_basic_table()) || //batch update table(multi queries or arraybinding) + (table_item->for_update_ && table_item->skip_locked_ && session_info->get_pl_context()) // select for update skip locked stmt in PL use das force + ; + bool is_select_sample_scan = get_plan()->get_stmt()->is_select_stmt() + && ((NULL != table_item->sample_info_ && !table_item->sample_info_->is_no_sample()) //block(row) sample scan do not support DAS TSC + || (opt_ctx.is_online_ddl() && opt_ctx.get_root_stmt()->is_insert_stmt()) // online ddl plan use sample table scan, create index not support DAS TSC + ); + + if (EXTERNAL_TABLE == table_item->table_type_ + || is_select_sample_scan + || is_virtual_table(table_item->ref_id_)) { + create_das_path = false; + create_basic_path = true; + } else if (force_das_tsc) { //this sql force to use DAS TSC + create_das_path = true; + create_basic_path = false; } - if (EXTERNAL_TABLE == table_item->table_type_) { - create_das_path = false; - create_basic_path = true; - } else - //this sql force to use DAS TSC: - //batch update table(multi queries or arraybinding) - //contain nested sql(pl udf or in nested sql) - //trigger or foreign key in the top sql not force to use DAS TSC - //has function table - if (is_sample_stmt || is_online_ddl_insert) { - create_das_path = false; - create_basic_path = true; - } else if (force_das_tsc) { - create_das_path = true; - create_basic_path = false; - } else if (OB_FAIL(get_plan()->get_log_plan_hint().check_use_das(table_id, hint_force_das, - hint_force_no_das))) { - LOG_WARN("table_item is null", K(ret), K(table_id)); - } else if (hint_force_das || hint_force_no_das) { - create_das_path = hint_force_das; - create_basic_path = hint_force_no_das; - } else if (index_info_entry->is_index_global() && OB_FAIL(get_explicit_dop_for_path(index_id, explicit_dop))) { + } + return ret; +} + +int ObJoinOrder::check_opt_rule_use_das(const uint64_t table_id, + const uint64_t index_id, + const ObIndexInfoCache &index_info_cache, + const ObIArray &filters, + const bool is_rescan, + bool &create_das_path, + bool &create_basic_path) +{ + int ret = OB_SUCCESS; + create_das_path = false; + create_basic_path = false; + IndexInfoEntry *index_info_entry = NULL; + if (is_rescan) { + create_das_path = true; + create_basic_path = (table_meta_info_.is_broadcast_table_ + || (OB_SUCCESS != (OB_E(EventTable::EN_GENERATE_PLAN_WITH_NLJ) OB_SUCCESS))) + ? false : true; + } else if (OB_FAIL(index_info_cache.get_index_info_entry(table_id, index_id, index_info_entry))) { + LOG_WARN("failed to get index info entry", K(table_id), K(index_id), K(ret)); + } else if (OB_ISNULL(index_info_entry)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(index_info_entry)); + } else if (index_info_entry->is_index_global() && index_info_entry->is_index_back()) { + int64_t explicit_dop = ObGlobalHint::UNSET_PARALLEL; + if (OB_FAIL(get_explicit_dop_for_path(index_id, explicit_dop))) { LOG_WARN("failed to get explicit dop", K(ret)); - } else if (ObGlobalHint::DEFAULT_PARALLEL == explicit_dop) { - create_das_path = true; - create_basic_path = false; - } else if ((helper.is_inner_path_ || get_tables().is_subset(get_plan()->get_subq_pdfilter_tset())) && - !is_virtual_table(ref_id)) { - bool force_use_nlj = false; - force_use_nlj = (OB_SUCCESS != (OB_E(EventTable::EN_GENERATE_PLAN_WITH_NLJ) OB_SUCCESS)); - create_das_path = true; - create_basic_path = (force_use_nlj || table_meta_info_.is_broadcast_table_) ? false : true; - } else if (index_info_entry->is_index_global() && ObGlobalHint::UNSET_PARALLEL == explicit_dop) { + } else if (ObGlobalHint::UNSET_PARALLEL == explicit_dop) { // for global index use auto dop, create das path and basic path, after get auto dop result, prune unnecessary path create_das_path = true; create_basic_path = true; + } else if (ObGlobalHint::DEFAULT_PARALLEL == explicit_dop) { + create_das_path = true; } else { - create_das_path = false; create_basic_path = true; } - LOG_TRACE("will use das", K(force_das_tsc), K(hint_force_das), K(hint_force_no_das), - K(helper.is_inner_path_), K(create_das_path), K(create_basic_path)); + } else { + create_basic_path = true; } return ret; } @@ -1742,9 +1705,9 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id, } else if (OB_FAIL(index_info_cache.get_index_info_entry(table_id, index_id, index_info_entry))) { LOG_WARN("failed to get index info entry", K(table_id), K(index_id), K(ret)); - } else if (OB_ISNULL(index_info_entry)) { + } else if (OB_ISNULL(index_info_entry) || OB_ISNULL(index_info_entry->get_partition_info())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("index info entry should not be null", K(ret)); + LOG_WARN("index info entry should not be null", K(ret), KPC(index_info_entry)); } else if (!helper.force_inner_nl_ && helper.is_inner_path_ && (index_info_entry->get_ordering_info().get_index_keys().count() <= 0)) { LOG_TRACE("skip adding inner access path due to wrong index key count", @@ -1760,7 +1723,10 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id, ap = new(ap) AccessPath(table_id, ref_id, index_id, this, ordering_info.get_scan_direction()); ap->is_get_ = range_info.is_get(); ap->is_global_index_ = index_info_entry->is_index_global(); + ap->table_partition_info_ = index_info_entry->get_partition_info(); ap->use_das_ = use_das; + ap->contain_das_op_ = ap->use_das_; + ap->est_cost_info_.is_das_scan_ = ap->use_das_; ap->is_hash_index_ = is_virtual_table(ref_id) && ref_id != index_id; ap->est_cost_info_.index_meta_info_.is_index_back_ = index_info_entry->is_index_back(); ap->est_cost_info_.index_meta_info_.is_unique_index_ = index_info_entry->is_unique_index(); @@ -1776,9 +1742,10 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id, (index_info_entry->is_unique_index() && range_info.is_index_column_get() && index_info_entry->is_valid_unique_index()); + ap->est_cost_info_.rescan_server_list_ = &ap->server_list_; ap->table_opt_info_ = helper.table_opt_info_; ap->is_inner_path_ = helper.is_inner_path_; - ap->est_cost_info_.is_inner_path_ = helper.is_inner_path_; + ap->est_cost_info_.is_rescan_ = helper.is_inner_path_ || get_plan()->get_is_rescan_subplan(); ap->range_prefix_count_ = index_info_entry->get_range_info().get_range_prefix_count(); ap->interesting_order_info_ = index_info_entry->get_interesting_order_info(); ap->for_update_ = table_item->for_update_; @@ -1851,6 +1818,8 @@ int ObJoinOrder::create_one_access_path(const uint64_t table_id, LOG_WARN("append expr constraints failed", K(ret)); } else if (OB_FAIL(init_column_store_est_info(table_id, ref_id, ap->est_cost_info_))) { LOG_WARN("failed to init column store est cost info", K(ret)); + } else if (OB_FAIL(ap->compute_access_path_batch_rescan())) { + LOG_WARN("failed to compute access path batch rescan", K(ret)); } else { access_path = ap; } @@ -2822,7 +2791,6 @@ int ObJoinOrder::create_access_paths(const uint64_t table_id, AccessPath *basic_column_store_access_path = NULL; OptSkipScanState use_skip_scan = OptSkipScanState::SS_UNSET; if (OB_FAIL(will_use_das(table_id, - ref_table_id, valid_index_ids.at(i), index_info_cache, helper, @@ -3179,7 +3147,7 @@ int ObJoinOrder::will_use_skip_scan(const uint64_t table_id, use_skip_scan = OptSkipScanState::SS_DISABLE; } else if (!OPT_CTX.get_is_skip_scan_enabled()) { use_skip_scan = OptSkipScanState::SS_DISABLE; - } else if (helper.is_inner_path_ || get_tables().is_subset(get_plan()->get_subq_pdfilter_tset())) { + } else if (get_plan()->get_is_rescan_subplan() || helper.is_inner_path_) { use_skip_scan = OptSkipScanState::SS_DISABLE; } else { // may use skip scan for SS_NDV_SEL_ENABLE after calculate ndv and selectivity @@ -3490,7 +3458,7 @@ int ObJoinOrder::compute_cost_and_prune_access_path(PathHelper &helper, LOG_WARN("failed to compute pipelined path", K(ret)); } else if (OB_FAIL(ap->compute_valid_inner_path())) { LOG_WARN("failed to compute inner path with pushdown filters", K(ret)); - } else if (!ap->is_inner_path()) { + } else if (!helper.is_inner_path_) { if (OB_FAIL(add_path(ap))) { LOG_WARN("failed to add the interesting order"); } else { @@ -4721,6 +4689,9 @@ int ObJoinOrder::estimate_size_and_width_for_join(const ObJoinOrder* left_tree, LOG_WARN("get unexpected null", K(left_tree), K(right_tree), K(ret)); } else if (OB_FAIL(est_join_width())) { LOG_WARN("failed to estimate join width", K(ret)); + } else if (OPT_CTX.get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, + COMPAT_VERSION_4_3_5)) { + // do nothing } else if (OB_FAIL(append(equal_sets, left_tree->get_output_equal_sets())) || OB_FAIL(append(equal_sets, right_tree->get_output_equal_sets()))) { LOG_WARN("failed to append equal sets", K(ret)); @@ -4734,9 +4705,7 @@ int ObJoinOrder::estimate_size_and_width_for_join(const ObJoinOrder* left_tree, LOG_WARN("failed to calc join output rows", K(ret)); } else { set_output_rows(new_rows); - if (IS_SEMI_ANTI_JOIN(join_type)) { - anti_or_semi_match_sel_ = sel; - } + current_join_output_rows_ = new_rows; LOG_TRACE("estimate rows for join path", K(output_rows_), K(get_plan()->get_update_table_metas())); } return ret; @@ -5447,30 +5416,13 @@ int ObJoinOrder::compute_path_relationship(const Path &first_path, first_path.contain_match_all_fake_cte() != second_path.contain_match_all_fake_cte()) { relation = DominateRelation::OBJ_UNCOMPARABLE; OPT_TRACE("sharding can not compare for fake cte"); - } else if (first_path.is_join_path() && - second_path.is_join_path() && - static_cast(first_path).contain_normal_nl() && - !static_cast(second_path).contain_normal_nl()) { - relation = DominateRelation::OBJ_RIGHT_DOMINATE; - OPT_TRACE("right path dominate left path because of normal nl"); - } else if (first_path.is_join_path() && - second_path.is_join_path() && - !static_cast(first_path).contain_normal_nl() && - static_cast(second_path).contain_normal_nl()) { - relation = DominateRelation::OBJ_LEFT_DOMINATE; - OPT_TRACE("left path dominate right path because of normal nl"); - } else if (first_path.is_join_path() && - second_path.is_join_path() && - static_cast(first_path).has_none_equal_join() && - !static_cast(second_path).has_none_equal_join()) { - relation = DominateRelation::OBJ_RIGHT_DOMINATE; - OPT_TRACE("right path dominate left path because of none equal join"); - } else if (first_path.is_join_path() && - second_path.is_join_path() && - !static_cast(first_path).has_none_equal_join() && - static_cast(second_path).has_none_equal_join()) { - relation = DominateRelation::OBJ_LEFT_DOMINATE; - OPT_TRACE("left path dominate right path because of none equal join"); + } else if (first_path.is_join_path() && second_path.is_join_path() && + OB_FAIL(compute_join_path_relationship(static_cast(first_path), + static_cast(second_path), + relation))) { + LOG_WARN("failed to compute join path relationship", K(ret)); + } else if (DominateRelation::OBJ_EQUAL != relation) { + /* do nothing */ } else if (first_path.is_access_path() && second_path.is_access_path() && !static_cast(first_path).is_valid_inner_path_ && static_cast(second_path).is_valid_inner_path_) { @@ -5634,6 +5586,98 @@ int ObJoinOrder::compute_path_relationship(const Path &first_path, return ret; } +int ObJoinOrder::compute_join_path_relationship(const JoinPath &first_path, + const JoinPath &second_path, + DominateRelation &relation) +{ + int ret = OB_SUCCESS; + relation = DominateRelation::OBJ_EQUAL; + if (OB_ISNULL(get_plan()) || OB_ISNULL(first_path.right_path_) || OB_ISNULL(second_path.right_path_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(first_path.right_path_), K(second_path.right_path_)); + } + + if (OB_SUCC(ret) && DominateRelation::OBJ_EQUAL == relation && get_plan()->get_is_rescan_subplan()) { + bool first_is_px_with_das = !first_path.is_match_all() && first_path.contain_das_op(); + bool second_is_px_with_das = !second_path.is_match_all() && second_path.contain_das_op(); + if (first_is_px_with_das && !second_is_px_with_das) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right path dominate left path because of px rescan plan use das op"); + } else if (!first_is_px_with_das && second_is_px_with_das) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left path dominate right path because of px rescan plan use das op"); + } + } + + if (OB_SUCC(ret) && DominateRelation::OBJ_EQUAL == relation) { + if (first_path.contain_normal_nl() && !second_path.contain_normal_nl()) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right path dominate left path because of normal nl"); + } else if (!first_path.contain_normal_nl() && second_path.contain_normal_nl()) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left path dominate right path because of normal nl"); + } else if (first_path.has_none_equal_join() && !second_path.has_none_equal_join()) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right path dominate left path because of none equal join"); + } else if (!first_path.has_none_equal_join() && second_path.has_none_equal_join()) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left path dominate right path because of none equal join"); + } + } + + if (OB_SUCC(ret) && DominateRelation::OBJ_EQUAL == relation + && first_path.is_nlj_with_param_down() && second_path.is_nlj_with_param_down()) { + bool first_right_local_rescan = false; + bool second_right_local_rescan = false; + bool first_can_px_batch_rescan = false; + bool second_can_px_batch_rescan = false; + if (!first_path.can_use_batch_nlj_ && second_path.can_use_batch_nlj_) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right path dominate left path because of batch nl"); + } else if (first_path.can_use_batch_nlj_ && !second_path.can_use_batch_nlj_) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left path dominate right path because of batch nl"); + } else if (OB_FAIL(first_path.check_right_is_local_scan(first_right_local_rescan)) + || OB_FAIL(second_path.check_right_is_local_scan(second_right_local_rescan))) { + LOG_WARN("failed to check right is lcoal rescan", K(ret)); + } else if (first_path.can_use_batch_nlj_ && second_path.can_use_batch_nlj_) { + if (first_path.parallel_ != second_path.parallel_) { + /* do nothing */ + } else if (!first_right_local_rescan && second_right_local_rescan) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right path dominate left path because of batch nl local rescan"); + } else if (first_right_local_rescan && !second_right_local_rescan) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left path dominate right path because of batch nl local rescan"); + } + } else if (!first_right_local_rescan && second_right_local_rescan) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right path dominate left path because of nl local rescan"); + } else if (first_right_local_rescan && !second_right_local_rescan) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left path dominate right path because of nl local rescan"); + } else if (first_right_local_rescan && second_right_local_rescan) { + /* do nothing */ + } else if (OB_FAIL(first_path.pre_check_nlj_can_px_batch_rescan(first_can_px_batch_rescan)) + || OB_FAIL(second_path.pre_check_nlj_can_px_batch_rescan(second_can_px_batch_rescan))) { + LOG_WARN("failed to pre check spf can px batch rescan", K(ret)); + } else if (!first_can_px_batch_rescan && second_can_px_batch_rescan) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right plan dominate left plan because of nl px batch rescan"); + } else if (first_can_px_batch_rescan && !second_can_px_batch_rescan) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left plan dominate right plan because of nl px batch rescan"); + } else { + /* do nothing */ + } + LOG_TRACE("finish compute nlj rescan join path relationship", + K(first_path.can_use_batch_nlj_), K(second_path.can_use_batch_nlj_), + K(first_right_local_rescan), K(second_right_local_rescan), + K(first_can_px_batch_rescan), K(second_can_px_batch_rescan)); + } + return ret; +} + int ObJoinOrder::compute_pipeline_relationship(const Path &first_path, const Path &second_path, DominateRelation &relation) @@ -5915,6 +5959,8 @@ int AccessPath::assign(const AccessPath &other, common::ObIAllocator *allocator) use_skip_scan_ = other.use_skip_scan_; use_column_store_ = other.use_column_store_; is_valid_inner_path_ = other.is_valid_inner_path_; + can_batch_rescan_ = other.can_batch_rescan_; + can_das_dynamic_part_pruning_ = other.can_das_dynamic_part_pruning_; if (OB_ISNULL(allocator)) { ret = OB_INVALID_ARGUMENT; @@ -6260,6 +6306,7 @@ int AccessPath::re_estimate_cost(EstimateCostInfo ¶m, double &card, double & double opt_logical_query_range_row_count = est_cost_info_.logical_query_range_row_count_; param.need_parallel_ = (ObGlobalHint::UNSET_PARALLEL == param.need_parallel_ || is_match_all()) ? parallel_ : param.need_parallel_; + est_cost_info_.rescan_left_server_list_ = param.rescan_left_server_list_; if (OB_ISNULL(parent_) || OB_ISNULL(parent_->get_plan()) || OB_ISNULL(opt_ctx = &parent_->get_plan()->get_optimizer_context())) { ret = OB_ERR_UNEXPECTED; @@ -6271,10 +6318,12 @@ int AccessPath::re_estimate_cost(EstimateCostInfo ¶m, double &card, double & LOG_WARN("failed to check adj index cost valid", K(ret)); } else if (OB_FAIL(re_estimate_cost(param, est_cost_info_, sample_info_, *opt_ctx, + can_batch_rescan_, storage_est_card, storage_est_cost))) { LOG_WARN("failed to re estimate cost", K(ret)); } else if (!adj_cost_is_valid) { + est_cost_info_.rescan_left_server_list_ = NULL; cost = storage_est_cost; card = storage_est_card; if (param.override_) { @@ -6284,10 +6333,12 @@ int AccessPath::re_estimate_cost(EstimateCostInfo ¶m, double &card, double & } else if (OB_FALSE_IT(est_cost_info_.logical_query_range_row_count_ = stats_logical_query_range_row_count)) { } else if (OB_FAIL(re_estimate_cost(param, est_cost_info_, sample_info_, *opt_ctx, + can_batch_rescan_, stats_est_card, stats_est_cost))) { LOG_WARN("failed to re estimate cost", K(ret)); } else { + est_cost_info_.rescan_left_server_list_ = NULL; double rate = opt_stats_cost_percent * 1.0 / 100.0; cost = storage_est_cost * (1-rate) + stats_est_cost * rate; card = storage_est_card * (1-rate) + stats_est_card * rate; @@ -6304,6 +6355,7 @@ int AccessPath::re_estimate_cost(const EstimateCostInfo ¶m, ObCostTableScanInfo &est_cost_info, const SampleInfo &sample_info, const ObOptimizerContext &opt_ctx, + const bool can_batch_rescan, double &card, double &cost) { @@ -6312,10 +6364,13 @@ int AccessPath::re_estimate_cost(const EstimateCostInfo ¶m, cost = 0; est_cost_info.join_filter_sel_ = 1.0; double table_filter_sel = est_cost_info.table_filter_sel_; - if (OB_UNLIKELY(param.need_parallel_ < ObGlobalHint::DEFAULT_PARALLEL || orign_card < 0)) { + if (OB_UNLIKELY(param.need_parallel_ < ObGlobalHint::DEFAULT_PARALLEL + || (!can_batch_rescan && param.need_batch_rescan_) + || orign_card < 0)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected params", K(ret), K(param), K(orign_card)); + LOG_WARN("get unexpected params", K(ret), K(param), K(orign_card), K(can_batch_rescan)); } else { + est_cost_info.is_batch_rescan_ = param.need_batch_rescan_; //bloom filter selectivity for (int64_t i = 0; i < param.join_filter_infos_.count(); ++i) { const JoinFilterInfo &info = param.join_filter_infos_.at(i); @@ -6368,6 +6423,7 @@ int AccessPath::re_estimate_cost(const EstimateCostInfo ¶m, //restore query range row count est_cost_info.phy_query_range_row_count_ = orign_phy_query_range_row_count; est_cost_info.logical_query_range_row_count_ = orign_logical_query_range_row_count; + est_cost_info.is_batch_rescan_ = false; } } return ret; @@ -6449,6 +6505,58 @@ int AccessPath::compute_valid_inner_path() return ret; } +int AccessPath::compute_access_path_batch_rescan() +{ + int ret = OB_SUCCESS; + can_batch_rescan_ = false; + ObLogPlan *plan = NULL; + const TableItem *table_item = NULL; + bool has_index_scan_filter = false; + bool has_index_lookup_filter = false; + bool can_batch_rescan = false; + ObSEArray non_match_filters; + ObSEArray match_filters; + if (OB_ISNULL(parent_) || OB_ISNULL(plan = parent_->get_plan()) || OB_ISNULL(plan->get_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null log op", K(ret)); + } else if (OB_ISNULL(table_item = plan->get_stmt()->get_table_item_by_id(table_id_))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("Failed to get table item", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::extract_match_against_filters(filter_, + non_match_filters, + match_filters))) { + LOG_WARN("failed to extract ir fitler from filters", K(ret), K(filter_)); + } else if (is_virtual_table(ref_table_id_) + || est_cost_info_.index_meta_info_.is_geo_index_ + || for_update_ + || !subquery_exprs_.empty() + || table_item->is_link_table() + || match_filters.count() > 0 + || EXTERNAL_TABLE == table_item->table_type_) { + can_batch_rescan = false; + } else if (order_direction_ != default_asc_direction() && order_direction_ != ObOrderDirection::UNORDERED) { + can_batch_rescan = false; + } else if (plan->get_optimizer_context().enable_experimental_batch_rescan()) { + can_batch_rescan = true; + } else if (est_cost_info_.index_meta_info_.is_global_index_ && + est_cost_info_.index_meta_info_.is_index_back_ && + OB_FAIL(ObOptimizerUtil::get_has_global_index_filters(plan->get_optimizer_context().get_sql_schema_guard(), + index_id_, + est_cost_info_.postfix_filters_, + has_index_scan_filter, + has_index_lookup_filter))) { + LOG_WARN("failed to get has global index filters", K(ret)); + } else { + // For the global index lookup, if there is a pushdown filter when scanning the index, batch cannot be used. + can_batch_rescan = !has_index_scan_filter; + } + + if (OB_SUCC(ret)) { + can_batch_rescan_ = can_batch_rescan; + } + return ret; +} + bool ObIndexMergeNode::is_valid() const { return is_leaf_node_ ? @@ -6543,6 +6651,46 @@ int IndexMergePath::add_index_scan_node(const ObIndexMergeType merge_type, return ret; } +int AccessPath::compute_is_das_dynamic_part_pruning(const EqualSets &equal_sets, + const ObIArray &src_keys, + const ObIArray &target_keys) +{ + int ret = OB_SUCCESS; + if (-1 != can_das_dynamic_part_pruning_ || !use_das_) { + /* do nothing */ + } else if (OB_ISNULL(parent_) || OB_ISNULL(parent_->get_plan()) + || OB_ISNULL(parent_->get_plan()->get_stmt()) + || OB_ISNULL(table_partition_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected params", K(ret), K(parent_), K(table_partition_info_)); + } else if (!parent_->get_plan()->get_optimizer_context().enable_425_batch_rescan()) { + can_das_dynamic_part_pruning_ = false; + } else if (table_partition_info_->get_phy_tbl_location_info().get_partition_cnt() <= 1) { + can_das_dynamic_part_pruning_ = false; + } else { + ObSEArray part_keys; + bool is_match = false; + if (OB_FAIL(ObShardingInfo::get_all_partition_key(parent_->get_plan()->get_optimizer_context(), + *parent_->get_plan()->get_stmt(), + table_id_, + index_id_, + part_keys))) { + LOG_WARN("failed to get all partition key", K(ret)); + } else if (OB_FAIL(ObShardingInfo::check_if_match_repart_or_rehash(equal_sets, + src_keys, + target_keys, + part_keys, + is_match))) { + LOG_WARN("failed to check if match repartition", K(ret)); + } else { + LOG_DEBUG("finish check is das dynamic part pruning", K(is_match), K(part_keys), + K(src_keys), K(target_keys)); + can_das_dynamic_part_pruning_ = is_match; + } + } + return ret; +} + int IndexMergePath::set_scan_direction(const ObOrderDirection &direction) { int ret = OB_SUCCESS; @@ -6832,6 +6980,7 @@ int JoinPath::assign(const JoinPath &other, common::ObIAllocator *allocator) is_naaj_ = other.is_naaj_; is_sna_ = other.is_sna_; inherit_sharding_index_ = other.inherit_sharding_index_; + join_output_rows_ = other.join_output_rows_; if (OB_FAIL(Path::assign(other, allocator))) { LOG_WARN("failed to deep copy path", K(ret)); @@ -7040,8 +7189,8 @@ int JoinPath::compute_join_path_property() LOG_WARN("failed to compute op ordering", K(ret)); } else if (OB_FAIL(compute_join_path_parallel_and_server_info())) { LOG_WARN("failed to compute server info", K(ret)); - } else if OB_FAIL(can_use_batch_nlj(can_use_batch_nlj_)) { - LOG_WARN("failed to check can use batch nlj", K(ret)); + } else if OB_FAIL(compute_nlj_batch_rescan()) { + LOG_WARN("failed to compute nlj batch rescan", K(ret)); } else if (OB_FAIL(estimate_cost())) { LOG_WARN("failed to calculate cost in create_ml_path", K(ret)); } else if (OB_FAIL(compute_pipeline_info())) { @@ -7448,153 +7597,157 @@ int JoinPath::compute_join_path_parallel_and_server_info(ObOptimizerContext *opt return ret; } -int JoinPath::can_use_batch_nlj(ObLogPlan *plan, - const AccessPath *access_path, - bool &use_batch_nlj) +int JoinPath::compute_nlj_batch_rescan() { int ret = OB_SUCCESS; - const TableItem *table_item = NULL; - use_batch_nlj = false; - if (OB_ISNULL(access_path) || OB_ISNULL(plan) || - OB_ISNULL(plan->get_stmt())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid input", K(ret)); - } else if (OB_ISNULL(table_item = plan->get_stmt()->get_table_item_by_id(access_path->table_id_))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("Failed to get table item", K(ret)); - } else { - bool is_global_index_back = access_path->est_cost_info_.index_meta_info_.is_global_index_ - && access_path->est_cost_info_.index_meta_info_.is_index_back_; - use_batch_nlj = !(is_virtual_table(access_path->ref_table_id_) - || table_item->is_link_table() - || access_path->is_cte_path() - || access_path->is_function_table_path() - || access_path->is_temp_table_path() - || access_path->is_json_table_path() - || table_item->for_update_ - || !access_path->subquery_exprs_.empty() - || EXTERNAL_TABLE == table_item->table_type_ - ); - - if (use_batch_nlj) { - bool found_query_range = false; - for (int64_t i = 0; OB_SUCC(ret) && i < access_path->filter_.count() && !found_query_range; ++i) { - const ObRawExpr *expr = access_path->filter_.at(i); - if (OB_ISNULL(expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("table filter is null", K(ret)); - } else if (OB_NOT_NULL(access_path->pre_query_range_) && - ObOptimizerUtil::find_item(access_path->pre_query_range_->get_range_exprs(), expr)) { - found_query_range = true; - } else { - //do nothing - //dynamic filter will keep in tsc operator - //static filter will pushdown to storage - } - } - use_batch_nlj = use_batch_nlj && found_query_range; - } - - } - return ret; -} - -int JoinPath::can_use_batch_nlj(bool &use_batch_nlj) -{ - int ret = OB_SUCCESS; - const ParamStore *params = NULL; - ObSQLSessionInfo *session_info = NULL; - const AccessPath *access_path = NULL; - const SubQueryPath *subq_path = NULL; + can_use_batch_nlj_ = false; ObLogPlan *plan = NULL; - ObQueryCtx *query_ctx = NULL; - use_batch_nlj = false; - if (OB_ISNULL(parent_) || OB_ISNULL(plan = parent_->get_plan()) || OB_ISNULL(right_path_) || - OB_ISNULL(session_info = plan->get_optimizer_context().get_session_info()) || - OB_ISNULL(params = plan->get_optimizer_context().get_params()) || - OB_ISNULL(query_ctx = plan->get_optimizer_context().get_query_ctx())) { + bool use_batch_nlj = false; + bool right_has_gi_or_exchange = false; + if (OB_ISNULL(parent_) || OB_ISNULL(plan = parent_->get_plan()) || OB_ISNULL(right_path_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid argument", K(session_info), K(params), K(query_ctx), K(ret)); - } else if (NESTED_LOOP_JOIN == join_algo_ - && CONNECT_BY_JOIN != join_type_ - && (!IS_SEMI_ANTI_JOIN(join_type_)) - && right_path_->is_inner_path() - && !right_path_->nl_params_.empty()) { - ObLogTableScan *ts = NULL; - bool right_has_gi_or_exchange = false; - if (DistAlgo::DIST_BASIC_METHOD == join_dist_algo_ || - DistAlgo::DIST_NONE_ALL == join_dist_algo_ || - DistAlgo::DIST_RANDOM_ALL == join_dist_algo_ || - (DistAlgo::DIST_PARTITION_WISE == join_dist_algo_ && - !is_slave_mapping_ && - !left_path_->exchange_allocated_ && - !right_path_->exchange_allocated_)) { - right_has_gi_or_exchange = false; - } else if (DistAlgo::DIST_PULL_TO_LOCAL == join_dist_algo_ && - !is_right_need_exchange()) { - right_has_gi_or_exchange = false; - } else { - right_has_gi_or_exchange = true; - } - if (!plan->get_optimizer_context().get_nlj_batching_enabled()) { - //do nothing - } else if ((!right_path_->is_access_path() && !right_path_->is_subquery_path()) || - right_has_gi_or_exchange) { - //do nothing - } else if (right_path_->is_access_path()) { - if (OB_FAIL(can_use_batch_nlj(plan, - static_cast(right_path_), - use_batch_nlj))) { - LOG_WARN("failed to check use batch nlj", K(ret)); - } - } else if (right_path_->is_subquery_path()) { - subq_path = static_cast(right_path_); - ObLogicalOperator *root = subq_path->root_; - if (OB_ISNULL(root)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("root is null", K(ret)); - } else if (OB_FAIL(can_use_das_batch_nlj(root, use_batch_nlj))) { - LOG_WARN("failed to check use batch nlj", K(ret)); - } + LOG_WARN("unexpected null", K(ret), K(parent_), K(plan), K(right_path_)); + } else if (!plan->get_optimizer_context().enable_nlj_batch_rescan()) { + /* do nothing */ + } else if (plan->get_disable_child_batch_rescan()) { + /* disabled by upper log_plan */ + } else if (NESTED_LOOP_JOIN != join_algo_ || !is_nlj_with_param_down() + || CONNECT_BY_JOIN == join_type_) { + /* join type not support */ + } else if (!right_path_->subquery_exprs_.empty()) { + /* subplan filter allocated for on condition subquery, not support */ + } else if (IS_SEMI_ANTI_JOIN(join_type_) && !plan->get_optimizer_context().enable_experimental_batch_rescan()) { + /* semi/anti join not support */ + } else if (OB_FAIL(check_right_has_gi_or_exchange(right_has_gi_or_exchange))) { + LOG_WARN("failed to check right has gi or exchange", K(ret)); + } else if (right_has_gi_or_exchange) { + /* do nothing */ + } else if (right_path_->is_access_path()) { + const AccessPath *ap = static_cast(right_path_); + can_use_batch_nlj_ = ap->can_batch_rescan_; + if (can_use_batch_nlj_ && !plan->get_optimizer_context().enable_experimental_batch_rescan() + && OB_FAIL(ObOptimizerUtil::check_exec_param_filter_exprs(ap->est_cost_info_.pushdown_prefix_filters_, + right_path_->nl_params_, + can_use_batch_nlj_))) { + LOG_WARN("failed to check exec param filter exprs", K(ret)); } + } else if (!right_path_->is_subquery_path()) { + /* do nothing, only access_path and subquery_path may use batch nlj */ + } else if (plan->get_optimizer_context().enable_experimental_batch_rescan() && + OB_FAIL(ObOptimizerUtil::check_can_batch_rescan(static_cast(right_path_)->root_, + false, + can_use_batch_nlj_))) { + LOG_WARN("failed to check plan can batch rescan", K(ret)); + } else if (!plan->get_optimizer_context().enable_experimental_batch_rescan() && + OB_FAIL(ObOptimizerUtil::check_can_batch_rescan_compat(static_cast(right_path_)->root_, + right_path_->nl_params_, + true, + can_use_batch_nlj_))) { + LOG_WARN("failed to check plan can batch rescan", K(ret)); } return ret; } -int JoinPath::can_use_das_batch_nlj(ObLogicalOperator* root, bool &use_batch_nlj) +int JoinPath::check_right_has_gi_or_exchange(bool &right_has_gi_or_exchange) { int ret = OB_SUCCESS; - use_batch_nlj = false; - if (OB_ISNULL(root)) { + right_has_gi_or_exchange = true; + if (OB_ISNULL(left_path_) || OB_ISNULL(right_path_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("root is null", K(ret)); - } else if (root->is_table_scan()) { - ObLogTableScan *ts = static_cast(root); - const AccessPath *access_path = ts->get_access_path(); - if (OB_ISNULL(access_path)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("ap is null", K(ret)); - } else if (!ts->use_das()) { - use_batch_nlj = false; - } else if (OB_FAIL(can_use_batch_nlj(ts->get_plan(), access_path, use_batch_nlj))) { - LOG_WARN("failed to check batch nlj", K(ret)); - } - } else if (root->get_num_of_child() == 1) { - if (OB_FAIL(SMART_CALL(can_use_das_batch_nlj(root->get_child(0), use_batch_nlj)))) { - LOG_WARN("failed to check das batch nlj", K(ret)); - } - } else if (log_op_def::LOG_SET == root->get_type() - || log_op_def::LOG_JOIN == root->get_type()) { - use_batch_nlj = true; - for (int64_t i = 0; OB_SUCC(ret) && use_batch_nlj && i < root->get_num_of_child(); ++i) { - ObLogicalOperator *child = root->get_child(i); - if (OB_ISNULL(child)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid child", K(ret)); - } else if (OB_FAIL(SMART_CALL(can_use_das_batch_nlj(child, use_batch_nlj)))) { - LOG_WARN("failed to check batch nlj", K(ret)); - } else {/* do nothing */} - } + LOG_WARN("unexpected null", K(ret), K(left_path_), K(right_path_)); + } else if (DistAlgo::DIST_BASIC_METHOD == join_dist_algo_ + || DistAlgo::DIST_NONE_ALL == join_dist_algo_ + || DistAlgo::DIST_RANDOM_ALL == join_dist_algo_) { + right_has_gi_or_exchange = false; + } else if (DistAlgo::DIST_PARTITION_WISE == join_dist_algo_ && !is_slave_mapping_ + && !left_path_->exchange_allocated_ + && !right_path_->exchange_allocated_) { + right_has_gi_or_exchange = false; + } else if (DistAlgo::DIST_BC2HOST_NONE == join_dist_algo_ && right_path_->is_single()) { + right_has_gi_or_exchange = false; + } else if (DistAlgo::DIST_PULL_TO_LOCAL == join_dist_algo_ && !is_right_need_exchange()) { + right_has_gi_or_exchange = false; + } else { + right_has_gi_or_exchange = true; + } + return ret; +} + +int JoinPath::check_right_is_local_scan(bool &is_local_scan) const +{ + int ret = OB_SUCCESS; + is_local_scan = true; + if (OB_ISNULL(right_path_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(right_path_)); + } else if (is_right_need_exchange() || right_path_->exchange_allocated_ || right_path_->contain_das_op_) { + is_local_scan = false; + } + return ret; +} + +int JoinPath::pre_check_nlj_can_px_batch_rescan(bool &can_px_batch_rescan) const +{ + int ret = OB_SUCCESS; + can_px_batch_rescan = false; + bool find_nested_rescan = false; + bool find_rescan_px = false; + const ObLogicalOperator *op = NULL; + if (OB_ISNULL(parent_) || OB_ISNULL(parent_->get_plan()) || OB_ISNULL(right_path_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(parent_), K(right_path_)); + } else if (1 < available_parallel_ || 1 < parallel_ + || !parent_->get_plan()->get_optimizer_context().enable_px_batch_rescan() + || NESTED_LOOP_JOIN != join_algo_ || !is_nlj_with_param_down() + || CONNECT_BY_JOIN == join_type_ + || IS_SEMI_ANTI_JOIN(join_type_) + || GCONF._enable_px_ordered_coord) { + /* when _enable_px_ordered_coord is enabled, px batch rescan is disabled due to is_task_order()exchange op */ + } else if (is_right_need_exchange()) { + can_px_batch_rescan = true; + } else if (right_path_->is_join_path() && + OB_FAIL(SMART_CALL(static_cast(right_path_)->pre_check_can_px_batch_rescan(find_nested_rescan, find_rescan_px, false)))) { + LOG_WARN("fail to find px for batch rescan", K(ret)); + } else if (right_path_->is_subquery_path() && + NULL != (op = static_cast(right_path_)->root_) && + OB_FAIL(SMART_CALL(op->pre_check_can_px_batch_rescan(find_nested_rescan, find_rescan_px, false)))) { + LOG_WARN("fail to find px for batch rescan", K(ret)); + } else if (!find_nested_rescan && find_rescan_px) { + can_px_batch_rescan = true; + } + return ret; +} + +int JoinPath::pre_check_can_px_batch_rescan(bool &find_nested_rescan, + bool &find_rescan_px, + bool nested) const +{ + int ret = OB_SUCCESS; + const ObLogicalOperator *op = NULL; + if (find_nested_rescan) { + } else if (NULL != log_op_) { + ret = log_op_->pre_check_can_px_batch_rescan(find_nested_rescan, find_rescan_px, nested); + } else if (OB_FALSE_IT(nested |= NESTED_LOOP_JOIN == join_algo_)) { + } else if (is_left_need_exchange() || is_right_need_exchange()) { + find_nested_rescan = nested; + find_rescan_px |= !nested; + } else if (OB_ISNULL(left_path_) || OB_ISNULL(right_path_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(left_path_), K(right_path_)); + } else if (left_path_->is_join_path() && + OB_FAIL(SMART_CALL(static_cast(left_path_)->pre_check_can_px_batch_rescan(find_nested_rescan, find_rescan_px, nested)))) { + LOG_WARN("fail to find px for batch rescan", K(ret)); + } else if (left_path_->is_subquery_path() && + NULL != (op = static_cast(left_path_)->root_) && + OB_FAIL(SMART_CALL(op->pre_check_can_px_batch_rescan(find_nested_rescan, find_rescan_px, nested)))) { + LOG_WARN("fail to find px for batch rescan", K(ret)); + } else if (right_path_->is_join_path() && + OB_FAIL(SMART_CALL(static_cast(right_path_)->pre_check_can_px_batch_rescan(find_nested_rescan, find_rescan_px, nested)))) { + LOG_WARN("fail to find px for batch rescan", K(ret)); + } else if (right_path_->is_subquery_path() && + NULL != (op = static_cast(right_path_)->root_) && + OB_FAIL(SMART_CALL(op->pre_check_can_px_batch_rescan(find_nested_rescan, find_rescan_px, nested)))) { + LOG_WARN("fail to find px for batch rescan", K(ret)); } return ret; } @@ -7666,17 +7819,15 @@ int JoinPath::do_re_estimate_cost(EstimateCostInfo &info, double &card, double & double right_cost = 0.0; Path *left_path = const_cast(left_path_); Path *right_path = const_cast(right_path_); - if (OB_ISNULL(left_path_) || OB_ISNULL(right_path_)) { + if (OB_ISNULL(left_path_) || OB_ISNULL(right_path_) || OB_UNLIKELY(info.need_batch_rescan_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(left_path_), K(right_path_), K(ret)); + LOG_WARN("get unexpected null", K(left_path_), K(right_path_), K(info), K(ret)); } else if (OB_FAIL(get_re_estimate_param(info, left_param, right_param, false))) { LOG_WARN("failed to get re estimate param", K(ret)); } else if (OB_FAIL(left_path->re_estimate_cost(left_param, left_output_rows, left_cost))) { LOG_WARN("failed to re estimate cost", K(ret)); - } else if (OB_FAIL(try_set_batch_nlj_for_right_access_path(true))) { - LOG_WARN("failed to try set batch nlj for right access path", K(ret)); } else if (NULL != right_path->log_op_ && OB_FAIL(right_path->log_op_->re_est_cost(right_param, right_output_rows, @@ -7687,8 +7838,6 @@ int JoinPath::do_re_estimate_cost(EstimateCostInfo &info, double &card, double & right_output_rows, right_cost))) { LOG_WARN("failed to re estimate cost", K(ret)); - } else if (OB_FAIL(try_set_batch_nlj_for_right_access_path(false))) { - LOG_WARN("failed to try set batch nlj for right access path", K(ret)); } else if (OB_FAIL(re_estimate_rows(info.join_filter_infos_, left_output_rows, right_output_rows, card))) { LOG_WARN("failed to re estimate rows", K(ret)); } else if (NESTED_LOOP_JOIN == join_algo_) { @@ -7736,22 +7885,6 @@ int JoinPath::do_re_estimate_cost(EstimateCostInfo &info, double &card, double & return ret; } -int JoinPath::try_set_batch_nlj_for_right_access_path(bool enable) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(right_path_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(right_path_), K(ret)); - } else if (!can_use_batch_nlj_ || !right_path_->is_inner_path() || !right_path_->is_access_path()) { - /* do nothing */ - } else { - const AccessPath *access = static_cast(right_path_); - AccessPath *ap = const_cast(access); - ap->est_cost_info_.can_use_batch_nlj_ = enable; - } - return ret; -} - int JoinPath::get_re_estimate_param(EstimateCostInfo ¶m, EstimateCostInfo &left_param, EstimateCostInfo &right_param, @@ -7760,6 +7893,7 @@ int JoinPath::get_re_estimate_param(EstimateCostInfo ¶m, int ret = OB_SUCCESS; left_param.override_ = param.override_; right_param.override_ = param.override_; + right_param.need_batch_rescan_ = can_use_batch_nlj_; if (OB_ISNULL(left_path_) || OB_ISNULL(right_path_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(left_path_), K(right_path_), K(ret)); @@ -7767,6 +7901,10 @@ int JoinPath::get_re_estimate_param(EstimateCostInfo ¶m, ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected param", K(param), K(ret)); } else { + left_param.rescan_left_server_list_ = param.rescan_left_server_list_; + right_param.rescan_left_server_list_ = left_path_->is_match_all() + ? param.rescan_left_server_list_ + : &left_path_->get_server_list(); double card = get_path_output_rows(); if (param.need_row_count_ >= card || param.need_row_count_ < 0) { param.need_row_count_ = card; @@ -7887,6 +8025,11 @@ int JoinPath::re_estimate_rows(ObIArray &pushdown_join_filter_in row_count /= join_filter_infos_.at(i).join_filter_selectivity_; } } + // refine the rowcnt based on the first estimated difference between ObJoinOrder and JoinPath + if (join_output_rows_ > OB_DOUBLE_EPSINON) { + row_count *= get_path_output_rows() / join_output_rows_; + } + row_count = std::min(row_count, get_path_output_rows()); } } return ret; @@ -7927,10 +8070,6 @@ int JoinPath::cost_nest_loop_join(int64_t join_parallel, int64_t right_part_cnt = 1; double left_ex_cost = 0.0; double right_ex_cost = 0.0; - if (NULL != right_path_->get_sharding() && - NULL != right_path_->get_sharding()->get_phy_table_location_info()) { - right_part_cnt = right_path_->get_sharding()->get_part_cnt(); - } if (DistAlgo::DIST_BC2HOST_NONE == join_dist_algo_) { left_rows = ObJoinOrder::calc_single_parallel_rows(left_rows, in_parallel/server_cnt_); right_cost = right_cost * right_out_parallel / server_cnt_; @@ -7939,14 +8078,26 @@ int JoinPath::cost_nest_loop_join(int64_t join_parallel, DistAlgo::DIST_ALL_NONE == join_dist_algo_) { right_rows /= in_parallel; left_rows = ObJoinOrder::calc_single_parallel_rows(left_rows, 1); - } else if (DistAlgo::DIST_NONE_BROADCAST == join_dist_algo_ || - DistAlgo::DIST_NONE_ALL == join_dist_algo_ || - DistAlgo::DIST_RANDOM_ALL == join_dist_algo_) { + } else if (DistAlgo::DIST_NONE_ALL == join_dist_algo_ + || DistAlgo::DIST_RANDOM_ALL == join_dist_algo_) { + left_rows = ObJoinOrder::calc_single_parallel_rows(left_rows, in_parallel); + if (right_path_->is_access_path() && + static_cast(right_path_)->can_das_dynamic_part_pruning()) { + // das dynamic partition pruning + right_part_cnt = static_cast(right_path_)->get_part_cnt_before_das_dynamic_part_pruning(); + right_rows /= right_part_cnt; + right_cost = right_cost / right_part_cnt; + } + } else if (DistAlgo::DIST_NONE_BROADCAST == join_dist_algo_) { left_rows = ObJoinOrder::calc_single_parallel_rows(left_rows, in_parallel); } else if (DistAlgo::DIST_PULL_TO_LOCAL == join_dist_algo_) { left_rows = ObJoinOrder::calc_single_parallel_rows(left_rows, in_parallel); } else { left_rows = ObJoinOrder::calc_single_parallel_rows(left_rows, in_parallel); + if (NULL != right_path_->get_sharding() && + NULL != right_path_->get_sharding()->get_phy_table_location_info()) { + right_part_cnt = right_path_->get_sharding()->get_part_cnt(); + } right_rows /= right_part_cnt; const int64_t right_real_parallel = is_partition_wise() ? in_parallel : right_out_parallel; right_cost = right_cost * right_real_parallel / right_part_cnt; @@ -7960,7 +8111,7 @@ int JoinPath::cost_nest_loop_join(int64_t join_parallel, left_join_order->get_tables(), right_join_order->get_tables(), join_type_, - parent_->get_anti_or_semi_match_sel(), + other_cond_sel_, with_nl_param, need_mat_, is_right_need_exchange() || @@ -7987,9 +8138,7 @@ int JoinPath::cost_nest_loop_join(int64_t join_parallel, false, right_sort_keys_, server_cnt_); - if (OB_FAIL(ObOptEstCost::cost_nestloop(est_join_info, op_cost, other_cond_sel_, - plan->get_predicate_selectivities(), - opt_ctx))) { + if (OB_FAIL(ObOptEstCost::cost_nestloop(est_join_info, op_cost, opt_ctx))) { LOG_WARN("failed to estimate nest loop join cost", K(est_join_info), K(ret)); } else if (!re_est_for_op && is_left_need_exchange() && OB_FAIL(ObOptEstCost::cost_exchange(left_exch_info, left_ex_cost, @@ -8305,6 +8454,7 @@ void JoinPath::reuse() is_naaj_ = false; is_sna_ = false; inherit_sharding_index_ = -1; + join_output_rows_ = -1.0; } int JoinPath::compute_pipeline_info() @@ -8392,6 +8542,7 @@ int SubQueryPath::re_estimate_cost(EstimateCostInfo ¶m, double &card, double op_cost = ObOptEstCost::cost_filter_rows(child_card / parallel, filter_, opt_ctx); cost = child_cost + op_cost; + card = child_card < card ? child_card : card; if (param.override_) { op_cost_ = op_cost; cost_ = cost; @@ -8897,9 +9048,6 @@ int ObJoinOrder::generate_base_table_paths(PathHelper &helper) access_paths, index_info_cache))) { LOG_WARN("failed to add table to join order(single)", K(ret)); - } else if (OB_FAIL(set_table_location_for_paths(access_paths, - index_info_cache))) { - 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 (OB_FAIL(pruning_unstable_access_path(table_id, @@ -9291,6 +9439,10 @@ int ObJoinOrder::generate_subquery_paths(PathHelper &helper) get_plan()->get_basic_table_metas(), get_plan()->get_selectivity_ctx()))) { LOG_WARN("failed to prepare opt exec param meta", K(ret)); + } else if (OB_FAIL(log_plan->init_rescan_info_for_subquery_paths(*get_plan(), + helper.is_inner_path_, + helper.is_semi_anti_join_))) { + LOG_WARN("failed to init rescan info", K(ret)); } else { log_plan->set_is_subplan_scan(true); log_plan->set_nonrecursive_plan_for_fake_cte(get_plan()->get_nonrecursive_plan_for_fake_cte()); @@ -10148,6 +10300,7 @@ int ObJoinOrder::generate_nl_paths(const EqualSets &equal_sets, *left_tree, *right_tree, path_info.force_inner_nl_, + path_info.join_type_, best_paths))) { LOG_WARN("failed to generate best inner paths", K(ret)); } else if (!best_paths.empty()) { @@ -10299,6 +10452,12 @@ int ObJoinOrder::generate_inner_nl_paths(const EqualSets &equal_sets, dist_method, can_slave_mapping))) { LOG_WARN("failed to get distributed join method", K(ret)); + } else if (right_path->is_access_path() && + OB_FAIL(static_cast(right_path)->compute_is_das_dynamic_part_pruning( + equal_sets, + left_join_keys, + right_join_keys))) { + LOG_WARN("failed to compute is das dynamic part pruning", K(ret)); } else if (dist_method == 0) { /*do nothing*/ } else { @@ -10564,6 +10723,9 @@ int ObJoinOrder::get_distributed_join_method(Path &left_path, distributed_methods &= ~DIST_BC2HOST_NONE; distributed_methods &= ~DIST_BROADCAST_NONE; } + if (right_sharding->is_match_all()) { + distributed_methods &= ~DIST_NONE_BROADCAST; + } if (left_path.parallel_ <= 1) { distributed_methods &= ~DIST_NONE_BROADCAST; } @@ -11401,6 +11563,7 @@ int ObJoinOrder::create_and_add_hash_path(const Path *left_path, join_path->is_naaj_ = naaj_info.is_naaj_; join_path->is_sna_ = naaj_info.is_sna_; join_path->is_slave_mapping_ &= (!naaj_info.is_naaj_); + join_path->join_output_rows_ = current_join_output_rows_; OPT_TRACE("create new Hash Join path:", join_path); if (OB_FAIL(append(join_path->equal_join_conditions_, equal_join_conditions))) { LOG_WARN("failed to append join conditions", K(ret)); @@ -11477,9 +11640,13 @@ int ObJoinOrder::generate_join_filter_infos(const Path &left_path, LOG_WARN("failed to find possible table scan for bf", K(ret)); } else if (join_filter_infos.empty()) { OPT_TRACE("no valid join filter"); - } else if (OB_FAIL(check_normal_join_filter_valid(left_path, right_path, join_filter_infos))) { + } else if (OB_FAIL(check_normal_join_filter_valid(left_path, + right_path, + join_filter_infos))) { LOG_WARN("fail to check bloom filter gen rule", K(ret)); - } else if (OB_FAIL(check_partition_join_filter_valid(join_dist_algo, join_filter_infos))) { + } else if (OB_FAIL(check_partition_join_filter_valid(join_dist_algo, + right_path, + join_filter_infos))) { LOG_WARN("fail to check hint gen rule", K(ret)); } else if (OB_FAIL(remove_invalid_join_filter_infos(join_filter_infos))) { LOG_WARN("failed to remove invalid join filter info", K(ret)); @@ -11805,6 +11972,64 @@ int ObJoinOrder::get_join_filter_exprs(const ObIArray &left_join_con return ret; } +int ObJoinOrder::check_path_contain_filter(const Path* path, bool &contain) +{ + int ret = OB_SUCCESS; + contain = false; + if (OB_ISNULL(path)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null path", K(ret)); + } else if (path->is_subquery_path()) { + const SubQueryPath* subquery = static_cast(path); + if (0 != path->filter_.count()) { + contain = true; + } else if (OB_FAIL(SMART_CALL(check_path_contain_filter(subquery->root_, contain)))) { + LOG_WARN("failed to check path contain filter", K(ret)); + } + } else if (path->is_join_path()) { + const JoinPath *join_path = static_cast(path); + bool left_contain = false; + bool right_contain = false; + if (OB_FAIL(SMART_CALL(check_path_contain_filter(join_path->left_path_, contain)))) { + LOG_WARN("failed to check path contain filter", K(ret)); + } else if (contain) { + //do nothing + } else if (OB_FAIL(SMART_CALL(check_path_contain_filter(join_path->right_path_, contain)))) { + LOG_WARN("failed to check path contain filter", K(ret)); + } + } else { + contain = 0 != path->filter_.count(); + } + return ret; +} + + +int ObJoinOrder::check_path_contain_filter(const ObLogicalOperator* op, bool &contain) +{ + int ret = OB_SUCCESS; + contain = false; + if (OB_ISNULL(op)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null op", K(ret)); + } else if (0 != op->get_filter_exprs().count()) { + contain = true; + } else if (log_op_def::LOG_TABLE_SCAN == op->get_type()) { + const ObLogTableScan *table_scan = static_cast(op); + contain = 0 != table_scan->get_range_conditions().count(); + } else if (log_op_def::LOG_SUBPLAN_FILTER == op->get_type()) { + if (OB_FAIL(SMART_CALL(check_path_contain_filter(op->get_child(0), contain)))) { + LOG_WARN("failed to check path contain filter", K(ret)); + } + } else { + for (int64_t i = 0; OB_SUCC(ret) && !contain && i < op->get_num_of_child(); ++i) { + if (OB_FAIL(SMART_CALL(check_path_contain_filter(op->get_child(i), contain)))) { + LOG_WARN("failed to check path contain filter", K(ret)); + } + } + } + return ret; +} + int ObJoinOrder::check_normal_join_filter_valid(const Path& left_path, const Path& right_path, ObIArray &join_filter_infos) @@ -11816,12 +12041,15 @@ int ObJoinOrder::check_normal_join_filter_valid(const Path& left_path, bool left_find = false; bool right_find = false; bool cur_dfo_has_shuffle_bf = false; + bool left_path_contain_filter = false; if (OB_ISNULL(plan) || OB_ISNULL(left_tree=left_path.parent_) || OB_ISNULL(stmt = plan->get_stmt()) || OB_ISNULL(OPT_CTX.get_query_ctx())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null plan", K(ret)); + } else if (OB_FAIL(check_path_contain_filter(&left_path, left_path_contain_filter))) { + LOG_WARN("failed to check path contain filter", K(ret)); } for (int i = 0; OB_SUCC(ret) && i < join_filter_infos.count(); ++i) { JoinFilterInfo &info = join_filter_infos.at(i); @@ -11845,7 +12073,18 @@ int ObJoinOrder::check_normal_join_filter_valid(const Path& left_path, 0 <= misjudgment_rate && misjudgment_rate <= 1.0) { info.join_filter_selectivity_ += (1 - join_filter_sel) * misjudgment_rate; } - info.can_use_join_filter_ = rate >= threshold || NULL != info.force_filter_; + if (NULL != info.force_filter_) { + info.can_use_join_filter_ = true; + } else if (!OPT_CTX.get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_3_5)) { + info.can_use_join_filter_ = rate >= threshold; + } else { + info.can_use_join_filter_ = left_path_contain_filter && + info.row_count_ >= 100000 && + left_path.get_path_output_rows() < 64000000; + } + if (!info.can_use_join_filter_) { + info.join_filter_selectivity_ = 1; + } OPT_TRACE("join filter info:"); OPT_TRACE("in current dfo:", info.in_current_dfo_); OPT_TRACE("right distinct card:", info.right_distinct_card_); @@ -11990,6 +12229,7 @@ int ObJoinOrder::find_shuffle_join_filter(const Path& path, bool &find) } int ObJoinOrder::check_partition_join_filter_valid(const DistAlgo join_dist_algo, + const Path &right_path, ObIArray &join_filter_infos) { int ret = OB_SUCCESS; @@ -12011,6 +12251,11 @@ int ObJoinOrder::check_partition_join_filter_valid(const DistAlgo join_dist_algo } else if (OB_ISNULL(info.sharding_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null sharding", K(ret)); + } else if (OPT_CTX.get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_3_5) && + (DIST_PARTITION_NONE != join_dist_algo || right_path.get_strong_sharding() != info.sharding_ ) && + NULL == info.force_part_filter_ && + info.sharding_->get_part_cnt() < 1000) { + info.need_partition_join_filter_ = false; } else if (info.sharding_->is_single()) { info.need_partition_join_filter_ = false; } else if (OB_FAIL(info.sharding_->get_all_partition_keys(target_part_keys))) { @@ -12245,6 +12490,7 @@ int ObJoinOrder::create_and_add_mj_path(const Path *left_path, join_path->right_prefix_pos_ = right_prefix_pos; join_path->equal_cond_sel_ = equal_cond_sel; join_path->other_cond_sel_ = other_cond_sel; + join_path->join_output_rows_ = current_join_output_rows_; OPT_TRACE("create new Merge Join path:", join_path); if (OB_FAIL(append(join_path->equal_join_conditions_, equal_join_conditions))) { LOG_WARN("failed to append join conditions", K(ret)); @@ -12633,7 +12879,8 @@ int ObJoinOrder::create_onetime_expr(const ObRelIds &ignore_relids, ObRawExpr* & const ObDMLStmt* stmt = NULL; bool is_valid = false; if (OB_ISNULL(expr) || OB_ISNULL(get_plan()) || - OB_ISNULL(stmt = get_plan()->get_stmt())) { + OB_ISNULL(stmt = get_plan()->get_stmt()) || + OB_ISNULL(stmt->query_ctx_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null expr", K(ret)); } else if (expr->has_flag(CNT_SUB_QUERY) && @@ -12649,10 +12896,8 @@ int ObJoinOrder::create_onetime_expr(const ObRelIds &ignore_relids, ObRawExpr* & LOG_WARN("new expr is null", K(ret), K(new_expr)); } else { new_expr->set_ref_expr(expr, true); + new_expr->set_param_index(*stmt->query_ctx_); new_expr->set_result_type(expr->get_result_type()); - new_expr->set_param_index(stmt->get_question_marks_count()); - // TODO link.zt - const_cast(stmt)->increase_question_marks_count(); ObSQLSessionInfo *session_info = get_plan()->get_optimizer_context().get_session_info(); if (OB_FAIL(new_expr->formalize(session_info))) { LOG_WARN("failed to extract expr info", K(ret)); @@ -13612,7 +13857,8 @@ int ObJoinOrder::create_and_add_nl_path(const Path *left_path, ObSEArray normal_filters; ObSEArray subquery_filters; if (OB_ISNULL(left_path) || OB_ISNULL(right_path) || - OB_ISNULL(get_plan()) || OB_ISNULL(left_path->get_sharding())) { + OB_ISNULL(get_plan()) || OB_ISNULL(left_path->get_sharding()) || + OB_ISNULL(left_path->parent_) || OB_ISNULL(right_path->parent_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("get unexpected null", K(left_path), K(right_path), K(get_plan()), K(ret)); } else if (IS_OUTER_OR_CONNECT_BY_JOIN(join_type) && @@ -13637,6 +13883,7 @@ int ObJoinOrder::create_and_add_nl_path(const Path *left_path, need_mat); join_path->contain_normal_nl_ = is_normal_nl; join_path->has_none_equal_join_ = !has_equal_cond; + join_path->join_output_rows_ = current_join_output_rows_; OPT_TRACE("create new NL Join path:", join_path); if (OB_FAIL(set_nl_filters(join_path, right_path, @@ -13644,6 +13891,28 @@ int ObJoinOrder::create_and_add_nl_path(const Path *left_path, on_conditions, normal_filters))) { LOG_WARN("failed to remove filters", K(ret)); + } else if (IS_SEMI_ANTI_JOIN(join_type)) { + // nested loop join must be left semi/anti join + double left_rows = left_path->get_path_output_rows(); + join_path->other_cond_sel_ = left_rows > OB_DOUBLE_EPSINON ? + current_join_output_rows_ / left_rows : + 1.0; + } else { + get_plan()->get_selectivity_ctx().init_join_ctx(join_type, + &left_path->parent_->get_tables(), + &right_path->parent_->get_tables(), + left_path->get_path_output_rows(), + right_path->get_path_output_rows()); + if (OB_FAIL(ObOptSelectivity::calculate_join_selectivity( + get_plan()->get_update_table_metas(), + get_plan()->get_selectivity_ctx(), + join_path->other_join_conditions_, + join_path->other_cond_sel_, + get_plan()->get_predicate_selectivities()))) { + LOG_WARN("failed to calculate selectivity", K(ret), K(join_path->other_join_conditions_)); + } + } + if (OB_FAIL(ret)) { } else if (CONNECT_BY_JOIN == join_type && OB_FAIL(push_down_order_siblings(join_path, right_path))) { LOG_WARN("push down order siblings by condition failed", K(ret)); @@ -14247,6 +14516,9 @@ int ObJoinOrder::revise_cardinality(const ObJoinOrder *left_tree, double sel = 1.0; EqualSets equal_sets; ObSEArray cur_join_ambient_card; + current_join_output_rows_ = 0.0; + double new_rows = 0.0; + double selectivity = 0.0; if (OB_ISNULL(left_tree) || OB_ISNULL(right_tree) || OB_ISNULL(get_plan()) || OB_ISNULL(OPT_CTX.get_query_ctx())) { ret = OB_ERR_UNEXPECTED; @@ -14259,10 +14531,18 @@ int ObJoinOrder::revise_cardinality(const ObJoinOrder *left_tree, LOG_WARN("failed to append equal sets", K(ret)); } else if (OB_FAIL(merge_ambient_card(left_tree->get_ambient_card(), right_tree->get_ambient_card(), cur_join_ambient_card))) { LOG_WARN("failed to merge rowcnts", K(ret)); + } else if (OB_FAIL(calc_join_output_rows(get_plan(), + left_tree->get_tables(), + right_tree->get_tables(), + left_tree->get_output_rows(), + right_tree->get_output_rows(), + join_info, current_join_output_rows_, + selectivity, equal_sets))) { + LOG_WARN("failed to calc join output rows", K(ret)); } else if (OB_FAIL(calc_join_ambient_card(get_plan(), *left_tree, *right_tree, - output_rows_, + current_join_output_rows_, join_info, equal_sets, cur_join_ambient_card))) { LOG_WARN("failed to scale base table rowcnts", K(ret)); @@ -14272,13 +14552,18 @@ int ObJoinOrder::revise_cardinality(const ObJoinOrder *left_tree, K(right_tree->get_ambient_card()), K(cur_join_ambient_card), K(ambient_card_)); } else { get_plan()->get_selectivity_ctx().clear(); + + // choose the minimal ambient cardinality and maximum output rowcnt for (int64_t i = 0; i < ambient_card_.count(); i ++) { ambient_card_.at(i) = std::min(ambient_card_.at(i), cur_join_ambient_card.at(i)); } + new_rows = std::max(current_join_output_rows_, get_output_rows()); + set_output_rows(new_rows); OPT_TRACE("left output rows :", left_tree->get_output_rows(), " ambient cardinality :", left_tree->get_ambient_card()); OPT_TRACE("right output rows :", right_tree->get_output_rows(), " ambient cardinality :", right_tree->get_ambient_card()); - OPT_TRACE("output rows of", left_tree, "join", right_tree, ":", get_output_rows(), " ambient cardinality :", cur_join_ambient_card); + OPT_TRACE("output rows of", left_tree, "join", right_tree, ":", current_join_output_rows_, " ambient cardinality :", cur_join_ambient_card); OPT_TRACE("Revised ambient cardinality :", ambient_card_); + OPT_TRACE("Revised output rows :", new_rows); LOG_DEBUG("estimate join ambient card", K(table_set_), K(left_tree->get_tables()), K(right_tree->get_tables()), K(cur_join_ambient_card)); } return ret; @@ -14442,7 +14727,8 @@ int ObJoinOrder::calc_join_ambient_card(ObLogPlan *plan, plan->get_update_table_metas(), plan->get_selectivity_ctx(), join_info.where_conditions_, where_sel_for_oj, - plan->get_predicate_selectivities()))) { + plan->get_predicate_selectivities(), + true/*is_outerjoin_filter*/))) { LOG_WARN("failed to calc filter selectivities", K(join_info.where_conditions_), K(ret)); } } @@ -15277,6 +15563,7 @@ int ObJoinOrder::get_cached_inner_paths(const ObIArray &join_condit ObJoinOrder &left_tree, ObJoinOrder &right_tree, const bool force_inner_nl, + const ObJoinType join_type, ObIArray &inner_paths) { int ret = OB_SUCCESS; @@ -15294,7 +15581,8 @@ int ObJoinOrder::get_cached_inner_paths(const ObIArray &join_condit LOG_WARN("failed to allocate place holder", K(ret)); } else if (OB_FAIL(path_info->join_conditions_.assign(join_conditions))) { LOG_WARN("failed to assign join conditions", K(ret)); - } else if (OB_FALSE_IT(path_info->force_inner_nl_ = force_inner_nl)) { + } else if (OB_FALSE_IT(path_info->force_inner_nl_ = force_inner_nl) + || OB_FALSE_IT(path_info->join_type_ = join_type)) { } else if (OB_FAIL(generate_inner_base_paths(join_conditions, left_tree, right_tree, @@ -15613,6 +15901,7 @@ int ObJoinOrder::generate_inner_subquery_paths(const ObDMLStmt &parent_stmt, ObSelectStmt *child_stmt = NULL; const TableItem *table_item = NULL; helper.is_inner_path_ = true; + helper.is_semi_anti_join_ = IS_SEMI_ANTI_JOIN(inner_path_info.join_type_); if (OB_ISNULL(get_plan()) || OB_ISNULL(session_info = get_plan()->get_optimizer_context().get_session_info()) || OB_ISNULL(expr_factory = &get_plan()->get_optimizer_context().get_expr_factory()) || diff --git a/src/sql/optimizer/ob_join_order.h b/src/sql/optimizer/ob_join_order.h old mode 100644 new mode 100755 index 7ad72db604..99272052da --- a/src/sql/optimizer/ob_join_order.h +++ b/src/sql/optimizer/ob_join_order.h @@ -232,36 +232,47 @@ struct EstimateCostInfo { :join_filter_infos_(), need_row_count_(-1), //no need to refine row count need_parallel_(ObGlobalHint::UNSET_PARALLEL), //no need to refine parallel + need_batch_rescan_(false), + rescan_left_server_list_(NULL), override_(false) {} void reset() { join_filter_infos_.reuse(); need_row_count_ = -1; need_parallel_ = ObGlobalHint::UNSET_PARALLEL; + need_batch_rescan_ = false; + rescan_left_server_list_ = NULL; override_ = false; } int assign(const EstimateCostInfo& other) { need_row_count_ = other.need_row_count_; need_parallel_ = other.need_parallel_; + need_batch_rescan_ = other.need_batch_rescan_; + rescan_left_server_list_ = other.rescan_left_server_list_; override_ = other.override_; return join_filter_infos_.assign(other.join_filter_infos_); } bool need_re_est(int64_t cur_parallel, double cur_row_count) const { return override_ || !join_filter_infos_.empty() || (ObGlobalHint::UNSET_PARALLEL != need_parallel_ && need_parallel_ != cur_parallel) - || (need_row_count_ >= 0 && need_row_count_ < cur_row_count); + || (need_row_count_ >= 0 && need_row_count_ < cur_row_count) + || (need_batch_rescan_ || NULL != rescan_left_server_list_); } TO_STRING_KV( K_(join_filter_infos), K_(need_row_count), K_(need_parallel), + K_(need_batch_rescan), + K_(rescan_left_server_list), K_(override) ); ObSEArray join_filter_infos_; double need_row_count_; int64_t need_parallel_; + bool need_batch_rescan_; + const common::ObIArray *rescan_left_server_list_; bool override_; }; @@ -540,6 +551,8 @@ struct EstimateCostInfo { use_skip_scan_(OptSkipScanState::SS_UNSET), use_column_store_(false), is_valid_inner_path_(false), + can_batch_rescan_(false), + can_das_dynamic_part_pruning_(-1), is_index_merge_(false), is_ror_(false) { @@ -595,6 +608,7 @@ struct EstimateCostInfo { ObCostTableScanInfo &est_cost_info, const SampleInfo &sample_info, const ObOptimizerContext &opt_ctx, + const bool can_batch_rescan, double &card, double &cost); int check_adj_index_cost_valid(double &stats_phy_query_range_row_count, @@ -622,6 +636,16 @@ struct EstimateCostInfo { return 1 == est_cost_info_.ranges_.count() && est_cost_info_.ranges_.at(0).is_false_range(); } + int compute_access_path_batch_rescan(); + bool is_rescan_path() const { return est_cost_info_.is_rescan_; } + int compute_is_das_dynamic_part_pruning(const EqualSets &equal_sets, + const ObIArray &src_keys, + const ObIArray &target_keys); + bool can_das_dynamic_part_pruning() const { return can_das_dynamic_part_pruning_ > 0; } + int64_t get_part_cnt_before_das_dynamic_part_pruning() const { + return can_das_dynamic_part_pruning() && NULL != table_partition_info_ + ? table_partition_info_->get_phy_tbl_location_info().get_partition_cnt() : 1; + } TO_STRING_KV(K_(table_id), K_(ref_table_id), K_(index_id), @@ -640,6 +664,8 @@ struct EstimateCostInfo { K_(use_skip_scan), K_(use_column_store), K_(is_valid_inner_path), + K_(can_batch_rescan), + K_(can_das_dynamic_part_pruning), K_(is_index_merge), K_(is_ror)); public: @@ -666,6 +692,8 @@ struct EstimateCostInfo { bool use_column_store_; // mark this access path is inner path and contribute query range bool is_valid_inner_path_; + bool can_batch_rescan_; + int64_t can_das_dynamic_part_pruning_; bool is_index_merge_; // whether used for index merge bool is_ror_; // indicate whether result from index table scan is ordered by primary key private: @@ -775,7 +803,8 @@ struct EstimateCostInfo { has_none_equal_join_(false), can_use_batch_nlj_(false), is_naaj_(false), - is_sna_(false) + is_sna_(false), + join_output_rows_(-1.0) { } @@ -812,7 +841,8 @@ struct EstimateCostInfo { can_use_batch_nlj_(false), is_naaj_(false), is_sna_(false), - inherit_sharding_index_(-1) + inherit_sharding_index_(-1), + join_output_rows_(-1.0) { } virtual ~JoinPath() {} @@ -825,7 +855,6 @@ struct EstimateCostInfo { EstimateCostInfo &left_param, EstimateCostInfo &right_param, bool re_est_for_op); - int try_set_batch_nlj_for_right_access_path(bool enable); int re_estimate_rows(ObIArray &pushdown_join_filter_infos, double left_output_rows, double right_output_rows, @@ -988,6 +1017,10 @@ struct EstimateCostInfo { int64_t &available_parallel, int64_t &server_cnt, ObIArray &server_list); + inline bool is_nlj_with_param_down() const + { return NULL != right_path_ && right_path_->is_inner_path() && !right_path_->nl_params_.empty(); } + int check_right_is_local_scan(bool &is_local_scan) const; + int pre_check_nlj_can_px_batch_rescan(bool &can_px_batch_rescan) const; private: int compute_hash_hash_sharding_info(); int compute_join_path_ordering(); @@ -996,9 +1029,11 @@ struct EstimateCostInfo { int compute_join_path_plan_type(); int compute_join_path_parallel_and_server_info(); int re_adjust_sharding_ordering_info(); - int can_use_batch_nlj(bool &use_batch_nlj); - int can_use_batch_nlj(ObLogPlan *plan, const AccessPath *access_path, bool &use_batch_nlj); - int can_use_das_batch_nlj(ObLogicalOperator* root, bool &use_batch_nlj); + int compute_nlj_batch_rescan(); + int check_right_has_gi_or_exchange(bool &right_has_gi_or_exchange); + int pre_check_can_px_batch_rescan(bool &find_nested_rescan, + bool &find_rescan_px, + bool nested) const; public: TO_STRING_KV(K_(join_algo), K_(join_dist_algo), @@ -1020,7 +1055,8 @@ struct EstimateCostInfo { K_(can_use_batch_nlj), K_(is_naaj), K_(is_sna), - K_(inherit_sharding_index)); + K_(inherit_sharding_index), + K_(join_output_rows)); public: const Path *left_path_; const Path *right_path_; @@ -1052,6 +1088,11 @@ struct EstimateCostInfo { bool is_sna_; // is single null aware anti join //Used to indicate which child node the current sharding inherits from int64_t inherit_sharding_index_; + /** + * estimated rowcount under the current left and right join order trees, + * might be different with the rowcount of parent_ join order + */ + double join_output_rows_; private: DISALLOW_COPY_AND_ASSIGN(JoinPath); }; @@ -1240,16 +1281,19 @@ struct InnerPathInfo { join_conditions_(), inner_paths_(), table_opt_info_(), - force_inner_nl_(false) {} + force_inner_nl_(false), + join_type_(UNKNOWN_JOIN) {} virtual ~InnerPathInfo() {} TO_STRING_KV(K_(join_conditions), K_(inner_paths), - K_(force_inner_nl)); + K_(force_inner_nl), + K_(join_type)); common::ObSEArray join_conditions_; common::ObSEArray inner_paths_; BaseTableOptInfo table_opt_info_; bool force_inner_nl_; //force generation of inner path, ignoring range check + ObJoinType join_type_; }; typedef common::ObSEArray InnerPathInfos; @@ -1289,6 +1333,7 @@ struct NullAwareAntiJoinInfo { PathHelper() : is_inner_path_(false), force_inner_nl_(false), + is_semi_anti_join_(false), child_stmt_(NULL), pushdown_filters_(), filters_(), @@ -1300,6 +1345,7 @@ struct NullAwareAntiJoinInfo { bool is_inner_path_; bool force_inner_nl_; + bool is_semi_anti_join_; ObSelectStmt *child_stmt_; // when generate inner access path, save all pushdown filters // when generate subquery path, save all pushdown filters after rename @@ -1350,7 +1396,6 @@ struct NullAwareAntiJoinInfo { output_table_set_(), output_rows_(-1.0), output_row_size_(-1.0), - anti_or_semi_match_sel_(1.0), table_partition_info_(NULL), sharding_info_(NULL), table_meta_info_(common::OB_INVALID_ID), @@ -1369,7 +1414,8 @@ struct NullAwareAntiJoinInfo { not_null_columns_(), inner_path_infos_(), cnt_rownum_(false), - total_path_num_(0) + total_path_num_(0), + current_join_output_rows_(-1.0) { } virtual ~ObJoinOrder(); @@ -1479,7 +1525,9 @@ struct NullAwareAntiJoinInfo { int compute_path_relationship(const Path &first_path, const Path &second_path, DominateRelation &relation); - + int compute_join_path_relationship(const JoinPath &first_path, + const JoinPath &second_path, + DominateRelation &relation); int compute_pipeline_relationship(const Path &first_path, const Path &second_path, DominateRelation &relation); @@ -1670,13 +1718,22 @@ struct NullAwareAntiJoinInfo { ObSqlBitSet<> &used_column_ids); int will_use_das(const uint64_t table_id, - const uint64_t ref_id, const uint64_t index_id, const ObIndexInfoCache &index_info_cache, PathHelper &helper, bool &create_das_path, bool &create_basic_path); + int check_exec_force_use_das(const uint64_t table_id, + bool &create_das_path, + bool &create_basic_path); + int check_opt_rule_use_das(const uint64_t table_id, + const uint64_t index_id, + const ObIndexInfoCache &index_info_cache, + const ObIArray &filters, + const bool is_rescan, + bool &create_das_path, + bool &create_basic_path); int will_use_skip_scan(const uint64_t table_id, const uint64_t ref_id, const uint64_t index_id, @@ -2127,7 +2184,8 @@ struct NullAwareAntiJoinInfo { JoinFilterInfo &join_filter_info); int fill_join_filter_info(JoinFilterInfo &join_filter_info); - + int check_path_contain_filter(const Path* path, bool &contain); + int check_path_contain_filter(const ObLogicalOperator* op, bool &contain); int check_normal_join_filter_valid(const Path& left_path, const Path& right_path, ObIArray &join_filter_infos); @@ -2144,6 +2202,7 @@ struct NullAwareAntiJoinInfo { int find_shuffle_join_filter(const Path& path, bool &find); int check_partition_join_filter_valid(const DistAlgo join_dist_algo, + const Path &right_path, ObIArray &join_filter_infos); int build_join_filter_part_expr(const int64_t ref_table_id, @@ -2266,8 +2325,6 @@ struct NullAwareAntiJoinInfo { int64_t get_diverse_path_count() const { return diverse_path_count_; } - inline double get_anti_or_semi_match_sel() const { return anti_or_semi_match_sel_; } - const ObFdItemSet &get_fd_item_set() const { return fd_item_set_; } ObFdItemSet &get_fd_item_set() { return fd_item_set_; } @@ -2320,9 +2377,6 @@ struct NullAwareAntiJoinInfo { ObCostTableScanInfo &est_cost_info, bool use_skip_scan); - int set_table_location_for_paths(ObIArray &access_paths, - ObIndexInfoCache &index_info_cache); - int compute_table_location(const uint64_t table_id, const uint64_t ref_id, const bool is_global_index, @@ -2575,6 +2629,7 @@ struct NullAwareAntiJoinInfo { ObJoinOrder &left_tree, ObJoinOrder &right_tree, const bool force_inner_nl, + const ObJoinType join_type, ObIArray &inner_paths); int generate_inner_base_paths(const ObIArray &join_conditions, @@ -2729,7 +2784,6 @@ struct NullAwareAntiJoinInfo { ObRelIds output_table_set_; //需要输出的table item下表, 经过semi join时只输出左枝 double output_rows_; double output_row_size_; - double anti_or_semi_match_sel_; //for anti/semi join ObTablePartitionInfo *table_partition_info_; // only for base table ObShardingInfo *sharding_info_; // only for base table and local index ObTableMetaInfo table_meta_info_; // only for base table @@ -2752,6 +2806,7 @@ struct NullAwareAntiJoinInfo { bool cnt_rownum_; uint64_t total_path_num_; common::ObSEArray ambient_card_; + double current_join_output_rows_; // 记录对当前连接树估计的输出行数 private: DISALLOW_COPY_AND_ASSIGN(ObJoinOrder); }; diff --git a/src/sql/optimizer/ob_log_distinct.cpp b/src/sql/optimizer/ob_log_distinct.cpp index 2e147f75e3..1dc65a4c71 100644 --- a/src/sql/optimizer/ob_log_distinct.cpp +++ b/src/sql/optimizer/ob_log_distinct.cpp @@ -118,7 +118,8 @@ int ObLogDistinct::get_distinct_output_exprs(ObIArray &output_exprs } else if (OB_FAIL(append_array_no_dup(candi_exprs, plan->get_orderby_exprs_for_width_est()))) { LOG_WARN("failed to add into output exprs", K(ret)); } else if (OB_FAIL(ObRawExprUtils::extract_col_aggr_winfunc_exprs(candi_exprs, - extracted_col_aggr_winfunc_exprs))) { + extracted_col_aggr_winfunc_exprs, + true))) { } else if (OB_FAIL(append_array_no_dup(output_exprs, extracted_col_aggr_winfunc_exprs))) { LOG_WARN("failed to add into output exprs", K(ret)); } else {/*do nothing*/} diff --git a/src/sql/optimizer/ob_log_exchange.cpp b/src/sql/optimizer/ob_log_exchange.cpp index 67d6239f0f..ad115c3ba9 100644 --- a/src/sql/optimizer/ob_log_exchange.cpp +++ b/src/sql/optimizer/ob_log_exchange.cpp @@ -937,7 +937,7 @@ int ObLogExchange::find_need_drop_expr_idxs(ObLogicalOperator *op, if (OB_ISNULL(op->get_child(0))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null op", K(ret)); - } else if (OB_FAIL(op->get_child(0)->check_has_exchange_below(left_has_exchange))) { + } else if (OB_FAIL(op->get_child(0)->check_has_op_below(LOG_EXCHANGE, left_has_exchange))) { LOG_WARN("fail to check has exchange below"); } else if (!left_has_exchange) { if (type == log_op_def::LOG_SUBPLAN_FILTER) { diff --git a/src/sql/optimizer/ob_log_exchange.h b/src/sql/optimizer/ob_log_exchange.h index 07ebca6aa0..725868f309 100644 --- a/src/sql/optimizer/ob_log_exchange.h +++ b/src/sql/optimizer/ob_log_exchange.h @@ -101,7 +101,8 @@ public: const common::ObIArray &get_repart_func_exprs() const {return repartition_func_exprs_;} const common::ObIArray &get_hash_dist_exprs() const {return hash_dist_exprs_;} const common::ObIArray *get_popular_values() const {return &popular_values_;} - const ObRawExpr *get_calc_part_id_expr() { return calc_part_id_expr_; } + const ObRawExpr *get_calc_part_id_expr() const { return calc_part_id_expr_; } + ObRawExpr *get_calc_part_id_expr() { return calc_part_id_expr_; } ObRepartitionType get_repartition_type() const {return repartition_type_;} int64_t get_repartition_ref_table_id() const {return repartition_ref_table_id_;} int64_t get_repartition_table_id() const {return repartition_table_id_;} diff --git a/src/sql/optimizer/ob_log_group_by.cpp b/src/sql/optimizer/ob_log_group_by.cpp index f7ba0678fb..d6c8531350 100644 --- a/src/sql/optimizer/ob_log_group_by.cpp +++ b/src/sql/optimizer/ob_log_group_by.cpp @@ -245,12 +245,10 @@ int ObLogGroupBy::est_cost() } else if (OB_FAIL(inner_est_cost(get_parallel(), child_card, child_ndv, - distinct_per_dop_, group_cost))) { LOG_WARN("failed to est group by cost", K(ret)); } else { - distinct_card_ = child_ndv; - set_card(distinct_card_ * selectivity); + set_card(child_ndv * selectivity); set_cost(child->get_cost() + group_cost); set_op_cost(group_cost); } @@ -310,7 +308,6 @@ int ObLogGroupBy::do_re_est_cost(EstimateCostInfo ¶m, double &card, double & } else if (OB_FAIL(inner_est_cost(parallel, child_card, need_ndv, - distinct_per_dop_, op_cost))) { LOG_WARN("failed to est distinct cost", K(ret)); } else { @@ -324,11 +321,11 @@ int ObLogGroupBy::do_re_est_cost(EstimateCostInfo ¶m, double &card, double & return ret; } -int ObLogGroupBy::inner_est_cost(const int64_t parallel, double child_card, double &child_ndv, double &per_dop_ndv, double &op_cost) +int ObLogGroupBy::inner_est_cost(const int64_t parallel, double child_card, double &child_ndv, double &op_cost) { int ret = OB_SUCCESS; double per_dop_card = 0.0; - per_dop_ndv = 0.0; + double per_dop_ndv = 0.0; common::ObSEArray group_rollup_exprs; ObLogicalOperator *child = get_child(ObLogicalOperator::first_child); if (OB_ISNULL(get_plan()) || @@ -919,7 +916,7 @@ int ObLogGroupBy::compute_sharding_info() int ObLogGroupBy::get_card_without_filter(double &card) { int ret = OB_SUCCESS; - card = get_distinct_card(); + card = get_total_ndv(); return ret; } diff --git a/src/sql/optimizer/ob_log_group_by.h b/src/sql/optimizer/ob_log_group_by.h index 0ac2f8eb49..f75326ae6f 100644 --- a/src/sql/optimizer/ob_log_group_by.h +++ b/src/sql/optimizer/ob_log_group_by.h @@ -86,8 +86,6 @@ public: rollup_exprs_(), aggr_exprs_(), algo_(AGGREGATE_UNINITIALIZED), - distinct_card_(0.0), - distinct_per_dop_(0.0), from_pivot_(false), is_push_down_(false), is_partition_gi_(false), @@ -155,7 +153,6 @@ public: int inner_est_cost(const int64_t parallel, double child_card, double &child_ndv, - double &per_dop_ndv, double &op_cost); int get_child_est_info(const int64_t parallel, double &child_card, double &child_ndv, double &selectivity); int get_gby_output_exprs(ObIArray &output_exprs); @@ -167,8 +164,6 @@ public: virtual int compute_equal_set() override; virtual int compute_fd_item_set() override; virtual int compute_op_ordering() override; - double get_distinct_card() const { return distinct_card_; } - void set_distinct_card(const double distinct_card) { distinct_card_ = distinct_card; } bool from_pivot() const { return from_pivot_; } void set_from_pivot(const bool value) { from_pivot_ = value; } int get_group_rollup_exprs(common::ObIArray &group_rollup_exprs) const; @@ -241,7 +236,7 @@ public: void set_pushdown_scalar_aggr() { is_pushdown_scalar_aggr_ = true; } bool is_pushdown_scalar_aggr() { return is_pushdown_scalar_aggr_; } - VIRTUAL_TO_STRING_KV(K_(group_exprs), K_(rollup_exprs), K_(aggr_exprs), K_(algo), K_(distinct_card), + VIRTUAL_TO_STRING_KV(K_(group_exprs), K_(rollup_exprs), K_(aggr_exprs), K_(algo), K_(is_push_down)); virtual int get_card_without_filter(double &card) override; private: @@ -258,9 +253,6 @@ private: common::ObSEArray rollup_exprs_; common::ObSEArray aggr_exprs_; AggregateAlgo algo_; - // used for the execution engine to set hash bucket size - double distinct_card_; - double distinct_per_dop_; bool from_pivot_; bool is_push_down_; bool is_partition_gi_; diff --git a/src/sql/optimizer/ob_log_join.cpp b/src/sql/optimizer/ob_log_join.cpp index 3f5268a814..e2890f711a 100644 --- a/src/sql/optimizer/ob_log_join.cpp +++ b/src/sql/optimizer/ob_log_join.cpp @@ -416,9 +416,9 @@ int ObLogJoin::do_re_est_cost(EstimateCostInfo ¶m, double &card, double &op_ ObLogicalOperator *left_child = get_child(ObLogicalOperator::first_child); ObLogicalOperator *right_child = get_child(ObLogicalOperator::second_child); const int64_t parallel = param.need_parallel_; - if (OB_ISNULL(left_child) || OB_ISNULL(right_child)) { + if (OB_ISNULL(left_child) || OB_ISNULL(right_child) || OB_UNLIKELY(param.need_batch_rescan_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpect null join path", K(ret)); + LOG_WARN("unexpected params", K(ret), K(left_child), K(right_child), K(param)); } else if (OB_ISNULL(join_path_)) { card = get_card(); op_cost = get_op_cost(); @@ -432,14 +432,10 @@ int ObLogJoin::do_re_est_cost(EstimateCostInfo ¶m, double &card, double &op_ left_output_rows, left_cost)))) { LOG_WARN("failed to re estimate cost", K(ret)); - } else if (OB_FAIL(join_path_->try_set_batch_nlj_for_right_access_path(true))) { - LOG_WARN("failed to try set batch nlj for right access path", K(ret)); } else if (OB_FAIL(SMART_CALL(right_child->re_est_cost(right_param, right_output_rows, right_cost)))) { LOG_WARN("failed to re estimate cost", K(ret)); - } else if (OB_FAIL(join_path_->try_set_batch_nlj_for_right_access_path(false))) { - LOG_WARN("failed to try set batch nlj for right access path", K(ret)); } else if (OB_FAIL(join_path_->re_estimate_rows(param.join_filter_infos_, left_output_rows, right_output_rows, @@ -1277,195 +1273,6 @@ int ObLogJoin::allocate_startup_expr_post() return ret; } -int ObLogJoin::set_use_batch(ObLogicalOperator* root) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(root)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid input", K(ret)); - } else if (root->is_table_scan()) { - ObLogTableScan *ts = static_cast(root); - // dblink can not support batch nlj - bool has_param = false; - ObSEArray idx_array; - if (OB_FAIL(ts->extract_bnlj_param_idxs(idx_array))) { - LOG_WARN("extract param indexes failed", KR(ret)); - } - for (int64_t i = 0; OB_SUCC(ret) && !has_param && i < nl_params_.count(); i++) { - int64_t param_idx = nl_params_.at(i)->get_param_index(); - for (int64_t j = 0; OB_SUCC(ret) && j < idx_array.count(); j++) { - if (param_idx == idx_array.at(j)) { - has_param = true; - } - } - } - if (OB_SUCC(ret)) { - if ((ts->has_index_scan_filter() && ts->get_index_back() && ts->get_is_index_global()) || - ts->is_text_retrieval_scan()) { - // For the global index lookup, if there is a pushdown filter when scanning the index, - // batch cannot be used. - ts->set_use_batch(false); - } else { - ts->set_use_batch(ts->use_batch() || (can_use_batch_nlj_ && has_param)); - } - } - } else if (root->get_num_of_child() == 1) { - if(OB_FAIL(SMART_CALL(set_use_batch(root->get_child(first_child))))) { - LOG_WARN("failed to check use batch nlj", K(ret)); - } - } else if (log_op_def::LOG_SET == root->get_type()) { - for (int64_t i = 0; OB_SUCC(ret) && i < root->get_num_of_child(); ++i) { - ObLogicalOperator *child = root->get_child(i); - if (OB_ISNULL(child)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid child", K(ret)); - } else if (OB_FAIL(SMART_CALL(set_use_batch(child)))) { - LOG_WARN("failed to check use batch nlj", K(ret)); - } - } - } else if (log_op_def::LOG_JOIN == root->get_type()) { - ObLogJoin *join = NULL; - ObLogicalOperator *left_child = NULL; - ObLogicalOperator *rigtht_child = NULL; - if (OB_ISNULL(join = static_cast(root)) - || OB_ISNULL(left_child = join->get_child(0))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid input", K(ret)); - } else if (OB_FAIL(SMART_CALL(set_use_batch(left_child)))) { - LOG_WARN("failed to check use batch nlj", K(ret)); - } else if (!join->can_use_batch_nlj()) { - // do nothing - } else if (OB_ISNULL(rigtht_child = join->get_child(1))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid child", K(ret)); - } else if (OB_FAIL(SMART_CALL(set_use_batch(rigtht_child)))) { - LOG_WARN("failed to check use batch nlj", K(ret)); - } - } else { /*do nothing*/ } - return ret; -} - -int ObLogJoin::check_and_set_use_batch() -{ - int ret = OB_SUCCESS; - ObSQLSessionInfo *session_info = NULL; - ObLogPlan *plan = NULL; - ObQueryCtx *query_ctx = NULL; - if (OB_ISNULL(plan = get_plan()) - || OB_ISNULL(session_info = plan->get_optimizer_context().get_session_info()) - || OB_ISNULL(query_ctx = plan->get_optimizer_context().get_query_ctx())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret), K(plan), K(session_info), K(query_ctx)); - } else if (!can_use_batch_nlj_) { - // do nothing - } else if (OB_FALSE_IT(can_use_batch_nlj_ = plan->get_optimizer_context().get_nlj_batching_enabled())) { - } else if (NESTED_LOOP_JOIN != get_join_algo()) { - can_use_batch_nlj_ = false; - } - // check use batch - if (OB_SUCC(ret) && can_use_batch_nlj_) { - bool contains_invalid_startup = false; - bool contains_limit = false; - bool enable_group_rescan_test_mode = false; - enable_group_rescan_test_mode = (OB_SUCCESS != (OB_E(EventTable::EN_DAS_GROUP_RESCAN_TEST_MODE) OB_SUCCESS)); - if (get_child(1)->get_type() == log_op_def::LOG_GRANULE_ITERATOR && !enable_group_rescan_test_mode) { - can_use_batch_nlj_ = false; - } else if (OB_FAIL(plan->contains_startup_with_exec_param(get_child(1), - contains_invalid_startup))) { - LOG_WARN("failed to check contains invalid startup", K(ret)); - } else if (contains_invalid_startup) { - can_use_batch_nlj_ = false; - } else if (OB_FAIL(plan->contains_limit_or_pushdown_limit(get_child(1), contains_limit))) { - LOG_WARN("failed to check contains limit", K(ret)); - } else if (contains_limit) { - can_use_batch_nlj_ = false; - } else if (OB_FAIL(check_if_disable_batch(get_child(1), can_use_batch_nlj_))) { - LOG_WARN("failed to check if disable batch", K(ret)); - } else if (can_use_batch_nlj_ && OB_FAIL(ObOptimizerUtil::check_ancestor_node_support_skip_scan(this, can_use_batch_nlj_))) { - LOG_WARN("failed to check whether ancestor node support skip read", K(ret)); - } - } - // set use batch - if (OB_SUCC(ret) && can_use_batch_nlj_) { - if (OB_FAIL(set_use_batch(get_child(1)))) { - LOG_WARN("failed to set use batch nlj", K(ret)); - } - } - return ret; -} - - -int ObLogJoin::check_if_disable_batch(ObLogicalOperator* root, bool &can_use_batch_nlj) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(root)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (!can_use_batch_nlj) { - // do nothing - } else if (root->is_table_scan()) { - ObLogTableScan *ts = NULL; - ObLogPlan *plan = NULL; - ObTablePartitionInfo *info = NULL; - if (OB_ISNULL(ts = static_cast(root)) || - OB_ISNULL(plan = get_plan()) || - OB_ISNULL(info = ts->get_table_partition_info())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid input", K(ret)); - } else if (ts->has_index_scan_filter() && ts->get_index_back() && ts->get_is_index_global()) { - // For the global index lookup, if there is a pushdown filter when scanning the index, - // batch cannot be used. - can_use_batch_nlj = false; - } else if (ts->get_scan_direction() != default_asc_direction() && ts->get_scan_direction() != ObOrderDirection::UNORDERED) { - can_use_batch_nlj = false; - } else if (ts->use_index_merge()) { - can_use_batch_nlj = false; - } else { - SMART_VAR(ObTablePartitionInfo, tmp_info) { - ObTablePartitionInfo *tmp_info_ptr = &tmp_info; - if (OB_FAIL(plan->gen_das_table_location_info(ts, tmp_info_ptr))) { - LOG_WARN("failed to gen das table location info", K(ret)); - } else { - if (tmp_info.get_table_location().use_das() && - tmp_info.get_table_location().get_has_dynamic_exec_param()) { - // dynamic partition pruning, no need to check - } else if (10 < info->get_phy_tbl_location_info().get_phy_part_loc_info_list().count()) { - can_use_batch_nlj = false; - } - } - } - } - } else if (1 == root->get_num_of_child()) { - if (OB_FAIL(SMART_CALL(check_if_disable_batch(root->get_child(0), can_use_batch_nlj)))) { - LOG_WARN("failed to check if disable batch", K(ret)); - } - } else if (log_op_def::LOG_SET == root->get_type()) { - ObLogSet *log_set = static_cast(root); - if (log_set->get_set_op() != ObSelectStmt::UNION) { - if (GET_MIN_CLUSTER_VERSION() < CLUSTER_VERSION_4_3_1_0) { - // if the min cluster version is less than 4.3.1.0, don't uses NLJ group-rescan because the old version don't adaptive group-rescan - can_use_batch_nlj = false; - LOG_TRACE("updrade stage don't support group-rescan if the min cluster version is less than 4.3.1.0 for distinct and except operator"); - } - } - for (int64_t i = 0; OB_SUCC(ret) && can_use_batch_nlj && i < root->get_num_of_child(); ++i) { - ObLogicalOperator *child = root->get_child(i); - if (OB_ISNULL(child)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid child", K(ret)); - } else if (OB_FAIL(SMART_CALL(check_if_disable_batch(child, can_use_batch_nlj)))) { - LOG_WARN("failed to check if disable batch", K(ret)); - } - } - } else if (log_op_def::LOG_JOIN == root->get_type()) { - // multi level nlj use batch is disabled - can_use_batch_nlj = false; - } else { - can_use_batch_nlj = false; - } - return ret; -} - bool ObLogJoin::is_my_exec_expr(const ObRawExpr *expr) { return ObOptimizerUtil::find_item(nl_params_, expr); diff --git a/src/sql/optimizer/ob_log_join.h b/src/sql/optimizer/ob_log_join.h index 4df48201d3..ba528383fb 100644 --- a/src/sql/optimizer/ob_log_join.h +++ b/src/sql/optimizer/ob_log_join.h @@ -158,8 +158,6 @@ namespace sql inline bool can_use_batch_nlj() const { return can_use_batch_nlj_; } void set_can_use_batch_nlj(bool can_use) { can_use_batch_nlj_ = can_use; } - int check_and_set_use_batch(); - int check_if_disable_batch(ObLogicalOperator* root, bool &can_use_batch_nlj); void set_join_path(JoinPath *path) { join_path_ = path; } JoinPath *get_join_path() { return join_path_; } bool is_my_exec_expr(const ObRawExpr *expr); @@ -185,7 +183,6 @@ namespace sql } private: - int set_use_batch(ObLogicalOperator* root); inline bool can_enable_gi_partition_pruning() { return (NESTED_LOOP_JOIN == join_algo_) diff --git a/src/sql/optimizer/ob_log_plan.cpp b/src/sql/optimizer/ob_log_plan.cpp index 5c987eeb87..8e80d6412f 100644 --- a/src/sql/optimizer/ob_log_plan.cpp +++ b/src/sql/optimizer/ob_log_plan.cpp @@ -135,6 +135,8 @@ ObLogPlan::ObLogPlan(ObOptimizerContext &ctx, const ObDMLStmt *stmt) max_op_id_(OB_INVALID_ID), is_subplan_scan_(false), is_parent_set_distinct_(false), + is_rescan_subplan_(false), + disable_child_batch_rescan_(false), temp_table_info_(NULL), const_exprs_(), hash_dist_info_(), @@ -296,8 +298,6 @@ int ObLogPlan::generate_join_orders() stmt->get_semi_infos(), quals))) { LOG_WARN("failed to distribute special quals", K(ret)); - } else if (OB_FAIL(collect_subq_pushdown_filter_table_relids(quals))) { - LOG_WARN("failed to compute subplan das table ids", K(ret)); } else if (OB_FAIL(generate_base_level_join_order(base_table_items, base_level))) { LOG_WARN("fail to generate base level join order", K(ret)); @@ -2410,6 +2410,7 @@ int ObLogPlan::inner_remove_redundancy_pred(ObIArray &join_pred, } else if (T_OP_EQ == cur_expr->get_expr_type() && 2 == cur_expr->get_param_count() && cur_expr->get_param_expr(0) != cur_expr->get_param_expr(1)) { + EqualSets tmp_equal_sets; if (OB_ISNULL(left_expr = cur_expr->get_param_expr(0)) || OB_ISNULL(right_expr = cur_expr->get_param_expr(1))) { ret = OB_ERR_UNEXPECTED; @@ -2438,9 +2439,12 @@ int ObLogPlan::inner_remove_redundancy_pred(ObIArray &join_pred, // remove preds which is equation between two exprs in the same equal sets has_checked.at(i) = true; OPT_TRACE("remove redundancy join condition:", cur_expr); + } else if (OB_FAIL(tmp_equal_sets.assign(equal_sets))) { + LOG_WARN("failed to append fd equal set", K(ret)); + } else if (FALSE_IT(equal_sets.reuse())) { } else if (OB_FAIL(ObEqualAnalysis::compute_equal_set(&allocator_, cur_expr, - equal_sets, + tmp_equal_sets, equal_sets))) { LOG_WARN("failed to compute equal sets for inner join", K(ret)); } else if (OB_FAIL(new_join_pred.push_back(cur_expr))) { @@ -2476,9 +2480,13 @@ int ObLogPlan::generate_subplan_for_query_ref(ObQueryRefRawExpr *query_ref, { int ret = OB_SUCCESS; // check if sub plan has been generated + subplan_info = NULL; const ObSelectStmt *subquery = NULL; ObLogPlan *logical_plan = NULL; ObOptimizerContext &opt_ctx = get_optimizer_context(); + bool has_ref_assign_user_var = false; + SubPlanInfo *info = NULL; + bool is_initplan = false; OPT_TRACE_TITLE("start generate subplan for subquery expr"); OPT_TRACE_BEGIN_SECTION; if (OB_ISNULL(subquery = query_ref->get_ref_stmt())) { @@ -2492,6 +2500,11 @@ int ObLogPlan::generate_subplan_for_query_ref(ObQueryRefRawExpr *query_ref, LOG_WARN("failed to create plan", K(ret), K(opt_ctx.get_query_ctx()->get_sql_stmt())); } else if (FALSE_IT(logical_plan->set_nonrecursive_plan_for_fake_cte(get_nonrecursive_plan_for_fake_cte()))) { // never reach + } else if (OB_FAIL(subquery->has_ref_assign_user_var(has_ref_assign_user_var))) { + LOG_WARN("faield to check stmt has assignment ref user var", K(ret)); + } else if (OB_FALSE_IT(is_initplan = !query_ref->has_exec_param() && !has_ref_assign_user_var)) { + } else if (OB_FAIL(logical_plan->init_rescan_info_for_query_ref(*this, !is_initplan))) { + LOG_WARN("failed to init rescan info", K(ret)); } else if (OB_FAIL(logical_plan->add_exec_params_meta(query_ref->get_exec_params(), get_basic_table_metas(), get_selectivity_ctx()))) { @@ -2502,29 +2515,22 @@ int ObLogPlan::generate_subplan_for_query_ref(ObQueryRefRawExpr *query_ref, logical_plan->get_update_table_metas(), logical_plan->get_selectivity_ctx()))) { LOG_WARN("failed to add expr meta", K(ret)); + } else if (OB_ISNULL(info = static_cast(get_allocator().alloc(sizeof(SubPlanInfo))))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_ERROR("failed to alloc semi info", K(ret)); } else { - SubPlanInfo *info = static_cast(get_allocator().alloc(sizeof(SubPlanInfo))); - bool has_ref_assign_user_var = false; - if (OB_ISNULL(info)) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_ERROR("failed to alloc semi info", K(ret)); - } else if (OB_FAIL(subquery->has_ref_assign_user_var(has_ref_assign_user_var))) { - LOG_WARN("faield to check stmt has assignment ref user var", K(ret)); - } else { /** * 作为initplan的条件: * 1. 不含上层变量,如果含上层变量会在本层当作Const * 2. 不含存在赋值操作的用户变量 */ - bool is_initplan = !query_ref->has_exec_param() && !has_ref_assign_user_var; - info = new(info)SubPlanInfo(query_ref, logical_plan, is_initplan); - if (OB_FAIL(add_subplan(info))) { - LOG_WARN("failed to add sp params to rel", K(ret)); - } else { - logical_plan->set_query_ref(query_ref); - subplan_info = info; - LOG_TRACE("succ to generate logical plan of sub-select"); - } + info = new(info)SubPlanInfo(query_ref, logical_plan, is_initplan); + if (OB_FAIL(add_subplan(info))) { + LOG_WARN("failed to add sp params to rel", K(ret)); + } else { + logical_plan->set_query_ref(query_ref); + subplan_info = info; + LOG_TRACE("succ to generate logical plan of sub-select"); } if (OB_FAIL(ret) && NULL != info) { @@ -2539,6 +2545,29 @@ int ObLogPlan::generate_subplan_for_query_ref(ObQueryRefRawExpr *query_ref, return ret; } +int ObLogPlan::init_rescan_info_for_query_ref(const ObLogPlan &parent_plan, + const bool is_rescan_subquery) +{ + int ret = OB_SUCCESS; + is_rescan_subplan_ = parent_plan.is_rescan_subplan_ || is_rescan_subquery; + disable_child_batch_rescan_ = parent_plan.disable_child_batch_rescan_ + || (is_rescan_subquery + && !get_optimizer_context().enable_experimental_batch_rescan()); + return ret; +} + +int ObLogPlan::init_rescan_info_for_subquery_paths(const ObLogPlan &parent_plan, + const bool is_inner_path, + const bool is_semi_anti_join_inner_path) +{ + int ret = OB_SUCCESS; + is_rescan_subplan_ = parent_plan.is_rescan_subplan_ || is_inner_path; + disable_child_batch_rescan_ = parent_plan.disable_child_batch_rescan_ + || (is_semi_anti_join_inner_path + && !get_optimizer_context().enable_experimental_batch_rescan()); + return ret; +} + int ObLogPlan::add_exec_params_meta(ObIArray &exec_params, const OptTableMetas &table_metas, const OptSelectivityCtx &ctx) @@ -2957,10 +2986,10 @@ int ObLogPlan::allocate_access_path(AccessPath *ap, if (ap->est_cost_info_.table_filters_.count() > 0) { bool has_index_scan_filter = false; bool has_index_lookup_filter = false; - if (OB_FAIL(get_has_global_index_filters(ap->filter_, - scan->get_idx_columns(), - has_index_scan_filter, - has_index_lookup_filter))) { + if (OB_FAIL(ObOptimizerUtil::get_has_global_index_filters(scan->get_filter_exprs(), + scan->get_idx_columns(), + has_index_scan_filter, + has_index_lookup_filter))) { LOG_WARN("failed to get has global index filters", K(ret)); } else { scan->set_has_index_scan_filter(has_index_scan_filter); @@ -2977,39 +3006,6 @@ int ObLogPlan::allocate_access_path(AccessPath *ap, return ret; } -int ObLogPlan::get_has_global_index_filters(const ObIArray &filter_exprs, - const ObIArray &index_columns, - bool &has_index_scan_filter, - bool &has_index_lookup_filter) -{ - int ret = OB_SUCCESS; - has_index_scan_filter = false; - has_index_lookup_filter = false; - ObSEArray filter_before_index_back; - if (OB_FAIL(ObOptimizerUtil::check_filter_before_indexback(filter_exprs, - index_columns, - filter_before_index_back))) { - LOG_WARN("Failed to check filter before index back", K(ret)); - } else if (OB_UNLIKELY(filter_before_index_back.count() != filter_exprs.count())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unequal array size", K(filter_before_index_back.count()), - K(filter_exprs.count()), K(ret)); - } else { - for (int64_t i = 0; OB_SUCC(ret) && i < filter_before_index_back.count(); i++) { - if (OB_ISNULL(filter_exprs.at(i))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("null expr", K(ret)); - } else if (filter_before_index_back.at(i) && - !filter_exprs.at(i)->has_flag(CNT_SUB_QUERY)) { - has_index_scan_filter = true; - } else { - has_index_lookup_filter = true; - } - } - } - return ret; -} - int ObLogPlan::store_index_column_ids( ObSqlSchemaGuard &schema_guard, ObLogTableScan &scan, @@ -5196,6 +5192,7 @@ int ObLogPlan::try_to_generate_pullup_aggr(ObAggFunRawExpr *old_aggr, } else if (OB_FAIL(ObOptimizerUtil::generate_pullup_aggr_expr( get_optimizer_context().get_expr_factory(), get_optimizer_context().get_session_info(), + static_cast(group_replaced_exprs_.at(i).second)->get_expr_type(), static_cast(group_replaced_exprs_.at(i).second), new_aggr))) { LOG_WARN("failed to generate pullup aggr expr", K(ret)); @@ -5615,18 +5612,8 @@ int ObLogPlan::init_distinct_helper(const ObIArray &distinct_exprs, } else if (OB_FAIL(check_storage_distinct_pushdown(distinct_exprs, distinct_helper.can_storage_pushdown_))) { LOG_WARN("failed to check can storage distinct pushdown", K(ret)); - } else if (get_log_plan_hint().no_pushdown_distinct()) { - OPT_TRACE("hint disable pushdown distinct"); - } else if (OB_ISNULL(session_info = get_optimizer_context().get_session_info())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(session_info), K(ret)); - } else if (OB_FAIL(session_info->if_aggr_pushdown_allowed(push_distinct))) { - LOG_WARN("fail to get aggr_pushdown_allowed", K(ret)); - } else if (!push_distinct && !get_log_plan_hint().pushdown_distinct()) { - OPT_TRACE("session info disable pushdown distinct"); - } else { - distinct_helper.can_basic_pushdown_ = true; - OPT_TRACE("try pushdown distinct"); + } else if (OB_FAIL(check_basic_distinct_pushdown(distinct_helper.can_basic_pushdown_))) { + LOG_WARN("failed to check can basic distinct pushdown", K(ret)); } if (OB_SUCC(ret)) { @@ -6050,7 +6037,7 @@ int ObLogPlan::check_can_pullup_gi(ObLogicalOperator &top, can_pullup = true; } else if (need_sort || !top.get_is_local_order() || top.is_exchange_allocated()) { /* do nothing */ - } else if (OB_FAIL(top.has_window_function_below(has_win_func))) { + } else if (OB_FAIL(top.check_has_op_below(LOG_WINDOW_FUNCTION, has_win_func))) { LOG_WARN("failed to check has window function below", K(ret)); } else { can_pullup = !has_win_func; @@ -7866,11 +7853,15 @@ int ObLogPlan::inner_candi_allocate_subplan_filter(ObIArray &subplan ObSEArray, 8> best_subplan_list; ObSEArray, 8> best_dist_subplan_list; ObSEArray subquery_plans; + const bool has_onetime = !onetime_idxs.is_empty(); 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, + } else if (OB_FAIL(get_valid_subplan_filter_dist_method(subplans, + for_cursor_expr, + has_onetime, + false, dist_methods))) { LOG_WARN("failed to get valid subplan filter dist method", K(ret)); } else if (DIST_INVALID_METHOD != dist_methods && @@ -7892,7 +7883,10 @@ int ObLogPlan::inner_candi_allocate_subplan_filter(ObIArray &subplan 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, + } else if (OB_FAIL(get_valid_subplan_filter_dist_method(subplans, + for_cursor_expr, + has_onetime, + 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, @@ -7986,6 +7980,7 @@ int ObLogPlan::prepare_subplan_candidate_list(ObIArray &subplans, int ObLogPlan::get_valid_subplan_filter_dist_method(ObIArray &subplans, const bool for_cursor_expr, + const bool has_onetime, const bool ignore_hint, int64_t &dist_methods) { @@ -8029,6 +8024,11 @@ int ObLogPlan::get_valid_subplan_filter_dist_method(ObIArray &subpla dist_methods &= ~DIST_PARTITION_NONE; } + if (OB_SUCC(ret) && has_onetime) { + dist_methods &= ~DIST_NONE_ALL; + OPT_TRACE("SPF will not use DIST_NONE_ALL/DIST_HASH_ALL/DIST_RANDOM_ALL method due to onetime subquery"); + } + if (OB_FAIL(ret)) { } else if (for_cursor_expr || contain_recursive_cte) { dist_methods &= (DIST_BASIC_METHOD | DIST_PULL_TO_LOCAL); @@ -8305,7 +8305,7 @@ int ObLogPlan::get_subplan_filter_distributed_method(ObLogicalOperator *&top, 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) { + } else if (is_none_all) { distributed_methods = DistAlgo::DIST_NONE_ALL; OPT_TRACE("SPF will use none all method"); } else { @@ -8895,6 +8895,8 @@ int ObLogPlan::allocate_subplan_filter_as_top(ObLogicalOperator *&top, LOG_WARN("failed to add init plan idxs", K(ret)); } else if (OB_FAIL(spf_node->add_onetime_idxs(onetime_idxs))) { LOG_WARN("failed to add onetime idxs", K(ret)); + } else if (OB_FAIL(spf_node->compute_spf_batch_rescan())) { + LOG_WARN("failed to compute spf batch rescan", K(ret)); } else if (OB_FAIL(spf_node->compute_property())) { LOG_WARN("failed to compute property", K(ret)); } else { @@ -9037,7 +9039,9 @@ int ObLogPlan::plan_tree_traverse(const TraverseOp &operation, void *ctx) break; } case ALLOC_EXPR: { - if (OB_FAIL(alloc_expr_ctx.flattern_expr_map_.create(128, "ExprAlloc"))) { + if (OB_FAIL(set_use_batch_for_table_scan(get_plan_root(), true, false))) { + LOG_WARN("failed to set use batch for table scan", K(ret)); + } else if (OB_FAIL(alloc_expr_ctx.flattern_expr_map_.create(128, "ExprAlloc"))) { LOG_WARN("failed to init hash map", K(ret)); } else { ctx = &alloc_expr_ctx; @@ -9118,69 +9122,6 @@ int ObLogPlan::plan_tree_traverse(const TraverseOp &operation, void *ctx) return ret; } -int ObLogPlan::contains_limit_or_pushdown_limit(ObLogicalOperator *op, - bool &contains) -{ - int ret = OB_SUCCESS; - contains = false; - if (OB_ISNULL(op)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid op", K(ret)); - } else if (log_op_def::LOG_LIMIT == op->get_type()) { - contains = true; - } else if (log_op_def::LOG_TABLE_SCAN == op->get_type()) { - ObLogTableScan *ts = static_cast(op); - if (NULL != ts->get_limit_expr()) { - contains = true; - } - } else { - for (int64_t i = 0; OB_SUCC(ret) && !contains && i < op->get_num_of_child(); ++i) { - ObLogicalOperator *child = op->get_child(i); - if (OB_ISNULL(child)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid child", K(ret)); - } else if (OB_FAIL(SMART_CALL(contains_limit_or_pushdown_limit(child, contains)))) { - LOG_WARN("failed to check contains limit", K(ret)); - } else {/*do nothing*/} - } - } - return ret; -} - -int ObLogPlan::contains_startup_with_exec_param(ObLogicalOperator *op, - bool &contains) -{ - int ret = OB_SUCCESS; - contains = false; - if (OB_ISNULL(op)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid op", K(ret)); - } else { - ObIArray &startup_exprs = op->get_startup_exprs(); - for (int64_t i = 0; OB_SUCC(ret) && !contains && i < startup_exprs.count(); ++i) { - ObRawExpr *expr = startup_exprs.at(i); - if (OB_ISNULL(expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpect null expr", K(ret)); - } else if (expr->has_flag(CNT_DYNAMIC_PARAM)) { - contains = true; - } else {/*do nothing*/} - } - if (OB_SUCC(ret) && !contains) { - for (int64_t i = 0; OB_SUCC(ret) && !contains && i < op->get_num_of_child(); ++i) { - ObLogicalOperator *child = op->get_child(i); - if (OB_ISNULL(child)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid child", K(ret)); - } else if (OB_FAIL(SMART_CALL(contains_startup_with_exec_param(child, contains)))) { - LOG_WARN("failed to check contains startup with exec param", K(ret)); - } else {/*do nothing*/} - } - } - } - return ret; -} - int ObLogPlan::init_onetime_subquery_info() { int ret = OB_SUCCESS; @@ -9751,6 +9692,10 @@ int ObLogPlan::compute_plan_relationship(const CandidatePlan &first_candi_plan, OB_ISNULL(second_plan = second_candi_plan.plan_tree_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(stmt), K(first_plan), K(second_plan), K(ret)); + } else if (OB_FAIL(compute_rescan_plan_relationship(*first_plan, *second_plan, plan_rel))) { + LOG_WARN("failed to compute rescan plan relationship", K(ret)); + } else if (DominateRelation::OBJ_UNCOMPARABLE != plan_rel) { + } else { DominateRelation temp_relation; int64_t left_dominated_count = 0; @@ -9870,6 +9815,82 @@ int ObLogPlan::compute_plan_relationship(const CandidatePlan &first_candi_plan, return ret; } +int ObLogPlan::compute_rescan_plan_relationship(const ObLogicalOperator &first_plan, + const ObLogicalOperator &second_plan, + DominateRelation &relation) +{ + int ret = OB_SUCCESS; + relation = DominateRelation::OBJ_UNCOMPARABLE; + if (get_is_rescan_subplan()) { + bool first_is_px_with_das = !first_plan.is_match_all() && first_plan.get_contains_das_op(); + bool second_is_px_with_das = !second_plan.is_match_all() && second_plan.get_contains_das_op(); + if (first_is_px_with_das && !second_is_px_with_das) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right plan dominate left plan because of px rescan plan use das op"); + } else if (!first_is_px_with_das && second_is_px_with_das) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left plan dominate right plan because of px rescan plan use das op"); + } + } + if (log_op_def::LOG_SUBPLAN_FILTER == first_plan.get_type() + && log_op_def::LOG_SUBPLAN_FILTER == second_plan.get_type()) { + const ObLogSubPlanFilter *first_spf = static_cast(&first_plan); + const ObLogSubPlanFilter *second_spf = static_cast(&second_plan); + bool first_right_local_rescan = false; + bool second_right_local_rescan = false; + bool first_can_px_batch_rescan = false; + bool second_can_px_batch_rescan = false; + bool first_rescan_contain_match_all = false; + bool second_rescan_contain_match_all = false; + if (!first_spf->enable_das_group_rescan() && second_spf->enable_das_group_rescan()) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right plan dominate left plan because of group rescan subplan filter"); + } else if (first_spf->enable_das_group_rescan() && !second_spf->enable_das_group_rescan()) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left plan dominate right plan because of group rescan subplan filter"); + } else if (OB_FAIL(first_spf->check_right_is_local_scan(first_right_local_rescan)) + || OB_FAIL(second_spf->check_right_is_local_scan(second_right_local_rescan))) { + LOG_WARN("failed to check right is local rescan", K(ret)); + } else if (first_spf->enable_das_group_rescan() && second_spf->enable_das_group_rescan()) { + if (first_spf->get_parallel() != second_spf->get_parallel()) { + /* do nothing */ + } else if (!first_right_local_rescan && second_right_local_rescan) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right path dominate left path because of right local group rescan"); + } else if (first_right_local_rescan && !second_right_local_rescan) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left path dominate right path because of right local group rescan"); + } + } else if (!first_right_local_rescan && second_right_local_rescan) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right plan dominate left plan because of right local rescan subplan filter"); + } else if (first_right_local_rescan && !second_right_local_rescan) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left plan dominate right plan because of right local rescan subplan filter"); + } else if (first_right_local_rescan && second_right_local_rescan) { + /* do nothing */ + } else if (OB_FAIL(first_spf->pre_check_spf_can_px_batch_rescan(first_can_px_batch_rescan, first_rescan_contain_match_all)) + || OB_FAIL(second_spf->pre_check_spf_can_px_batch_rescan(second_can_px_batch_rescan, second_rescan_contain_match_all))) { + LOG_WARN("failed to pre check spf can px batch rescan", K(ret)); + } else if ((!first_can_px_batch_rescan || (first_rescan_contain_match_all && !second_rescan_contain_match_all)) + && second_can_px_batch_rescan) { + relation = DominateRelation::OBJ_RIGHT_DOMINATE; + OPT_TRACE("right plan dominate left plan because of px batch rescan subplan filter"); + } else if (first_can_px_batch_rescan + && (!second_can_px_batch_rescan || (!first_rescan_contain_match_all && second_rescan_contain_match_all))) { + relation = DominateRelation::OBJ_LEFT_DOMINATE; + OPT_TRACE("left plan dominate right plan because of px batch rescan subplan filter"); + } else { + /* do nothing */ + } + LOG_TRACE("finish compute spf rescan plan relationship", + K(first_spf->enable_das_group_rescan()), K(second_spf->enable_das_group_rescan()), + K(first_right_local_rescan), K(second_right_local_rescan), + K(first_can_px_batch_rescan), K(second_can_px_batch_rescan)); + } + return ret; +} + int ObLogPlan::compute_pipeline_relationship(const ObLogicalOperator &first_plan, const ObLogicalOperator &second_plan, DominateRelation &relation) @@ -10443,86 +10464,6 @@ int ObLogPlan::get_source_table_info(ObLogicalOperator &top, return ret; } -int ObLogPlan::collect_subq_pushdown_filter_table_relids(const ObIArray &conditions) -{ - int ret = OB_SUCCESS; - const ObDMLStmt *stmt = NULL; - ObSEArray column_exprs; - ObSEArray pushdown_col_exprs; - ObSEArray all_pushdown_col_exprs; - ObSEArray table_ids; - bool contribute_query_range = false; - if (OB_ISNULL(stmt = get_stmt())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid stmt", K(ret)); - } else { - for (int64_t i = 0; i < conditions.count(); ++i) { - ObRawExpr *expr = conditions.at(i); - column_exprs.reuse(); - table_ids.reuse(); - if (OB_ISNULL(expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid expr", K(expr)); - } else if (!expr->has_flag(CNT_DYNAMIC_PARAM) || - expr->has_flag(CNT_ONETIME) || - expr->has_flag(CNT_PSEUDO_COLUMN) || - expr->has_flag(CNT_PRIOR) || - expr->has_flag(CNT_ROWNUM) || - T_OP_NE == expr->get_expr_type()) { - // do nothing - } else if (OB_FAIL(ObRawExprUtils::extract_column_exprs(expr, column_exprs))) { - LOG_WARN("failed to extract column exprs", K(ret)); - } else { - for (int64_t j = 0; OB_SUCC(ret) && j < column_exprs.count(); ++j) { - ObColumnRefRawExpr *col_expr = NULL; - if (OB_ISNULL(column_exprs.at(j)) || - !column_exprs.at(j)->is_column_ref_expr()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (OB_FALSE_IT(col_expr = static_cast(column_exprs.at(j)))) { - } else if (OB_FAIL(add_var_to_array_no_dup(table_ids, col_expr->get_table_id()))) { - LOG_WARN("failed to add var to array no dup", K(ret)); - } - } - for (int64_t j = 0; OB_SUCC(ret) && j < table_ids.count(); ++j) { - pushdown_col_exprs.reuse(); - if (OB_FAIL(ObTransformUtils::get_simple_filter_column(stmt, - expr, - table_ids.at(j), - pushdown_col_exprs))) { - LOG_WARN("failed to get simple filter column", K(ret)); - } else if (OB_FAIL(append_array_no_dup(all_pushdown_col_exprs, - pushdown_col_exprs))) { - LOG_WARN("failed to append array no dup", K(ret)); - } - } - } - } - for (int64_t i = 0; OB_SUCC(ret) && i < all_pushdown_col_exprs.count(); ++i) { - ObColumnRefRawExpr *col_expr = all_pushdown_col_exprs.at(i); - int64_t table_index = OB_INVALID_ID; - contribute_query_range = false; - if (OB_ISNULL(col_expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (OB_FALSE_IT(table_index = stmt->get_table_bit_index(col_expr->get_table_id()))) { - } else if (subq_pushdown_filter_table_set_.has_member(table_index)) { - // do nothing - } else if (OB_FAIL(ObTransformUtils::is_match_index(get_optimizer_context().get_sql_schema_guard(), - stmt, - col_expr, - contribute_query_range))) { - LOG_WARN("failed to check is match index", K(ret)); - } else if (!contribute_query_range) { - // do nothing - } else if (OB_FAIL(subq_pushdown_filter_table_set_.add_member(table_index))) { - LOG_WARN("failed to add members", K(ret)); - } - } - } - return ret; -} - int ObLogPlan::init_plan_info() { int ret = OB_SUCCESS; @@ -10849,6 +10790,8 @@ int ObLogPlan::do_post_plan_processing() if (OB_ISNULL(root = get_plan_root())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(set_use_batch_for_table_scan(root, false, false))) { + LOG_WARN("failed to set use batch for table scan", K(ret)); } else if (OB_FAIL(adjust_final_plan_info(root))) { LOG_WARN("failed to adjust parent-child relationship", K(ret)); } else if (OB_FAIL(remove_duplicate_constraints())) { @@ -11037,12 +10980,6 @@ int ObLogPlan::adjust_final_plan_info(ObLogicalOperator *&op) LOG_WARN("failed to perform gather stat replace"); } else if (OB_FAIL(op->reorder_filter_exprs())) { LOG_WARN("failed to reorder filter exprs", K(ret)); - } else if (log_op_def::LOG_JOIN == op->get_type() && - OB_FAIL(static_cast(op)->check_and_set_use_batch())) { - LOG_WARN("failed to set use batch nlj", K(ret)); - } else if (log_op_def::LOG_SUBPLAN_FILTER == op->get_type() && - OB_FAIL(static_cast(op)->check_and_set_das_group_rescan())) { - LOG_WARN("failed to set use batch spf", K(ret)); } else if (log_op_def::LOG_JOIN == op->get_type() && OB_FAIL(static_cast(op)->adjust_join_conds(static_cast(op)->get_join_conditions()))) { LOG_WARN("failed to adjust join conds", K(ret)); @@ -11052,6 +10989,86 @@ int ObLogPlan::adjust_final_plan_info(ObLogicalOperator *&op) return ret; } +// 1. set use batch for table scan +// 2. clear function storage pushdown aggr for batch rescan table scan +int ObLogPlan::set_use_batch_for_table_scan(ObLogicalOperator *op, bool check_gi, bool in_batch_rescan) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(op)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (op->is_table_scan()) { + ObLogTableScan *scan_op = static_cast(op); + scan_op->set_use_batch(in_batch_rescan); + if (in_batch_rescan) { + scan_op->get_pushdown_aggr_exprs().reuse(); + } + } else if (check_gi && OB_FAIL(reset_use_batch_due_to_gi_allocated_below(op))) { + LOG_WARN("failed to reset use batch due to gi allocated below", K(ret)); + } else { + bool is_batch_rescan_op = false; + for (int64_t i = 0; OB_SUCC(ret) && i < op->get_num_of_child(); i++) { + is_batch_rescan_op = in_batch_rescan; + if (0 == i) { + } else if (log_op_def::LOG_JOIN == op->get_type()) { + is_batch_rescan_op |= static_cast(op)->can_use_batch_nlj(); + } else if (log_op_def::LOG_SUBPLAN_FILTER == op->get_type()) { + ObLogSubPlanFilter *spf = static_cast(op); + is_batch_rescan_op |= spf->enable_das_group_rescan() + && !spf->get_onetime_idxs().has_member(i) + && !spf->get_initplan_idxs().has_member(i); + } + if (OB_FAIL(SMART_CALL(set_use_batch_for_table_scan(op->get_child(i), check_gi, is_batch_rescan_op)))) { + LOG_WARN("failed to set use batch for table scan", K(ret), K(i), K(op->get_type()), + K(op->get_name()), K(op->get_op_id())); + } + } + } + return ret; +} + +int ObLogPlan::reset_use_batch_due_to_gi_allocated_below(ObLogicalOperator *op) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(op)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(op)); + } else if (log_op_def::LOG_JOIN == op->get_type() + && static_cast(op)->can_use_batch_nlj()) { + bool has_gi_below = false; + if (OB_ISNULL(op->get_child(1))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null right child", K(ret)); + } else if (OB_FAIL(op->get_child(1)->check_has_op_below(LOG_GRANULE_ITERATOR, has_gi_below))) { + LOG_WARN("failed to check has gi below", K(ret)); + } else if (!has_gi_below) { + /* do nothing */ + } else { + static_cast(op)->set_can_use_batch_nlj(false); + LOG_TRACE("reset batch nlj due to gi allocated", K(op->get_type()), K(op->get_name()), K(op->get_op_id())); + } + } else if (log_op_def::LOG_SUBPLAN_FILTER == op->get_type() + && static_cast(op)->enable_das_group_rescan()) { + ObLogSubPlanFilter *spf = static_cast(op); + bool has_gi_below = false; + for (int64_t i = 1; !has_gi_below && OB_SUCC(ret) && i < spf->get_num_of_child(); i++) { + if (OB_ISNULL(spf->get_child(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null child", K(ret), K(i)); + } else if (spf->get_onetime_idxs().has_member(i) || spf->get_initplan_idxs().has_member(i)) { + /* do nothing */ + } else if (OB_FAIL(spf->get_child(i)->check_has_op_below(LOG_GRANULE_ITERATOR, has_gi_below))) { + LOG_WARN("failed to check has gi below", K(ret)); + } + } + if (OB_SUCC(ret) && has_gi_below) { + spf->set_enable_das_group_rescan(false); + LOG_TRACE("reset spf group rescan due to gi allocated", K(op->get_type()), K(op->get_name()), K(op->get_op_id())); + } + } + return ret; +} + int ObLogPlan::set_identify_seq_expr_for_recursive_union_all(ObLogicalOperator *op) { int ret = OB_SUCCESS; @@ -13849,6 +13866,28 @@ int ObLogPlan::perform_gather_stat_replace(ObLogicalOperator *op) return ret; } +int ObLogPlan::check_basic_distinct_pushdown(bool &can_push) +{ + int ret = OB_SUCCESS; + ObSQLSessionInfo *session_info = NULL; + bool sys_var_allow_push = false; + can_push = false; + if (get_log_plan_hint().no_pushdown_distinct()) { + OPT_TRACE("hint disable pushdown distinct"); + } else if (OB_ISNULL(session_info = get_optimizer_context().get_session_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(session_info), K(ret)); + } else if (OB_FAIL(session_info->if_aggr_pushdown_allowed(sys_var_allow_push))) { + LOG_WARN("failed to get aggr_pushdown_allowed", K(ret)); + } else if (!sys_var_allow_push && !get_log_plan_hint().pushdown_distinct()) { + OPT_TRACE("session info disable pushdown distinct"); + } else { + can_push = true; + OPT_TRACE("try pushdown distinct"); + } + return ret; +} + int ObLogPlan::check_stmt_is_all_distinct_col(const ObSelectStmt *stmt, const ObIArray &distinct_exprs, bool &is_all_distinct_col) diff --git a/src/sql/optimizer/ob_log_plan.h b/src/sql/optimizer/ob_log_plan.h index de13fef97d..3505554aa7 100644 --- a/src/sql/optimizer/ob_log_plan.h +++ b/src/sql/optimizer/ob_log_plan.h @@ -254,6 +254,9 @@ public: int adjust_final_plan_info(ObLogicalOperator *&op); + int set_use_batch_for_table_scan(ObLogicalOperator *op, bool check_gi, bool in_batch_rescan); + int reset_use_batch_due_to_gi_allocated_below(ObLogicalOperator *op); + int set_identify_seq_expr_for_recursive_union_all(ObLogicalOperator *op); int set_identify_seq_expr_for_fake_cte(ObLogicalOperator *op, ObRawExpr *expr, bool &is_valid); @@ -366,34 +369,12 @@ public: //get expr selectivity from predicate_selectivities_ double get_expr_selectivity(const ObRawExpr *expr, bool &found); - - int can_be_late_materialization(bool &can_be); - - int check_late_materialization_project(const uint64_t table_id, - const common::ObIArray &filter_exprs, - const common::ObIArray &sort_exprs, - const common::ObIArray &index_keys, - bool &need, - common::ObIArray &pre_access_columns, - common::ObIArray &project_columns); - int get_pre_project_cost(ObLogicalOperator *top, ObLogicalOperator *scan, common::ObIArray &index_columns, bool index_back, bool need_set, double &cost); - - int check_late_materialization_cost(ObLogicalOperator *top, - ObLogicalOperator *scan, - common::ObIArray &index_columns, - common::ObIArray &table_columns, - bool index_back, - double min_cost, - bool &need, - double &get_cost, - double &join_cost); - static int select_one_server(const common::ObAddr &selected_server, common::ObIArray &phy_tbl_loc_info_list); @@ -590,11 +571,6 @@ public: int allocate_values_table_path(ValuesTablePath *values_table_path, ObLogicalOperator *&out_access_path_op); - int get_has_global_index_filters(const ObIArray &filter_exprs, - const ObIArray &index_columns, - bool &has_index_scan_filter, - bool &has_index_lookup_filter) ; - int allocate_json_table_path(JsonTablePath *json_table_path, ObLogicalOperator *&out_access_path_op); @@ -803,6 +779,8 @@ public: const ObIArray &distinct_exprs, bool &is_all_distinct_col); + int check_basic_distinct_pushdown(bool &can_push); + int check_storage_distinct_pushdown(const ObIArray &distinct_exprs, bool &can_push); @@ -1092,6 +1070,7 @@ public: ObIArray> &dist_best_list); int get_valid_subplan_filter_dist_method(ObIArray &subplans, const bool for_cursor_expr, + const bool has_onetime, const bool ignore_hint, int64_t &dist_methods); @@ -1207,13 +1186,15 @@ public: const ObRawExprSets &get_empty_expr_sets() { return empty_expr_sets_; } const ObFdItemSet &get_empty_fd_item_set() { return empty_fd_item_set_; } const ObRelIds &get_empty_table_set() { return empty_table_set_; } - ObRelIds &get_subq_pdfilter_tset() { return subq_pushdown_filter_table_set_; } inline common::ObIArray &get_subquery_filters() { return subquery_filters_; } int init_plan_info(); - int collect_subq_pushdown_filter_table_relids(const ObIArray &quals); + int init_rescan_info_for_query_ref(const ObLogPlan &parent_plan, const bool is_rescan_subquery); + int init_rescan_info_for_subquery_paths(const ObLogPlan &parent_plan, + const bool is_inner_path, + const bool is_semi_anti_join_inner_path); EqualSets &get_equal_sets() { return equal_sets_; } const EqualSets &get_equal_sets() const { return equal_sets_; } @@ -1232,6 +1213,8 @@ public: inline const OptSelectivityCtx& get_selectivity_ctx() const { return selectivity_ctx_; } inline bool get_is_subplan_scan() const { return is_subplan_scan_; } inline void set_is_subplan_scan(bool is_subplan_scan) { is_subplan_scan_ = is_subplan_scan; } + inline bool get_is_rescan_subplan() const { return is_rescan_subplan_; } + inline bool get_disable_child_batch_rescan() const { return disable_child_batch_rescan_; } inline bool get_is_parent_set_distinct() const { return is_parent_set_distinct_; } inline void set_is_parent_set_distinct(bool is_parent_set_distinct) { is_parent_set_distinct_ = is_parent_set_distinct; } @@ -1285,12 +1268,6 @@ public: ObIArray &onetime_query_refs, const bool for_on_condition); - int contains_startup_with_exec_param(ObLogicalOperator *op, - bool &contains); - - int contains_limit_or_pushdown_limit(ObLogicalOperator *op, - bool &contains); - int replace_generate_column_exprs(ObLogicalOperator *op); int generate_old_column_values_exprs(ObLogicalOperator *root); int generate_tsc_replace_exprs_pair(ObLogTableScan *op); @@ -1497,7 +1474,9 @@ protected: int compute_plan_relationship(const CandidatePlan &first_plan, const CandidatePlan &second_plan, DominateRelation &relation); - + int compute_rescan_plan_relationship(const ObLogicalOperator &first_plan, + const ObLogicalOperator &second_plan, + DominateRelation &relation); int compute_pipeline_relationship(const ObLogicalOperator &first_plan, const ObLogicalOperator &second_plan, DominateRelation &relation); @@ -1898,6 +1877,8 @@ private: uint64_t max_op_id_; bool is_subplan_scan_; // 当前plan是否是一个subplan scan bool is_parent_set_distinct_; + bool is_rescan_subplan_; // generate subquery subplan for subplan filter or inner subquery path + bool disable_child_batch_rescan_; // before version 4_2_5, semi/anti join and subplan filter child op can not use batch rescan ObSqlTempTableInfo *temp_table_info_; // current plan is a temp table // 从where condition中抽出的常量表达式 common::ObSEArray const_exprs_; @@ -1911,7 +1892,6 @@ private: // all basic table meta after base table predicate OptTableMetas update_table_metas_; OptSelectivityCtx selectivity_ctx_; - ObRelIds subq_pushdown_filter_table_set_; // have been allocated for update table list common::ObSEArray alloc_sfu_list_; struct PartIdExpr { diff --git a/src/sql/optimizer/ob_log_set.cpp b/src/sql/optimizer/ob_log_set.cpp index 3592a5453c..1790ceb224 100644 --- a/src/sql/optimizer/ob_log_set.cpp +++ b/src/sql/optimizer/ob_log_set.cpp @@ -761,11 +761,21 @@ int ObLogSet::print_outline_data(PlanText &plan_text) const ObDMLStmt *stmt = NULL; ObString qb_name; ObPQSetHint hint; + bool has_push_down = false; 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 (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(check_has_push_down(has_push_down))) { + LOG_WARN("failed to check has push down", K(ret)); + } else if (has_push_down && + OB_FAIL(BUF_PRINTF("%s%s(@\"%.*s\")", + ObQueryHint::get_outline_indent(plan_text.is_oneline_), + ObHint::get_hint_name(T_DISTINCT_PUSHDOWN), + qb_name.length(), + qb_name.ptr()))) { + LOG_WARN("fail to print buffer", K(ret), K(buf), K(buf_len), K(pos)); } else if (HASH_SET == set_algo_ && OB_FAIL(BUF_PRINTF("%s%s(@\"%.*s\")", ObQueryHint::get_outline_indent(plan_text.is_oneline_), @@ -791,6 +801,7 @@ int ObLogSet::print_used_hint(PlanText &plan_text) LOG_WARN("unexpected NULL", K(ret), K(get_plan())); } else { const ObHint *use_hash = get_plan()->get_log_plan_hint().get_normal_hint(T_USE_HASH_SET); + const ObHint *pushdown = get_plan()->get_log_plan_hint().get_normal_hint(T_DISTINCT_PUSHDOWN); const bool algo_match = NULL != use_hash && ((HASH_SET == set_algo_ && use_hash->is_enable_hint()) || (MERGE_SET == set_algo_ && use_hash->is_disable_hint())); @@ -801,6 +812,17 @@ int ObLogSet::print_used_hint(PlanText &plan_text) LOG_WARN("failed to get used pq set hint", K(ret)); } else if (NULL != used_pq_hint && OB_FAIL(used_pq_hint->print_hint(plan_text))) { LOG_WARN("failed to print pq_set hint for set", K(ret), K(*used_pq_hint)); + } else if (NULL != pushdown) { + bool has_push_down = false; + if (OB_FAIL(check_has_push_down(has_push_down))) { + LOG_WARN("failed to check has push down", K(ret)); + } else { + bool pushdown_match = has_push_down ? pushdown->is_enable_hint() + : pushdown->is_disable_hint(); + if (pushdown_match && OB_FAIL(pushdown->print_hint(plan_text))) { + LOG_WARN("failed to print used push down hint for set", K(ret), KPC(pushdown)); + } + } } } return ret; @@ -874,6 +896,30 @@ int ObLogSet::construct_pq_set_hint(ObPQSetHint &hint) return ret; } +int ObLogSet::check_has_push_down(bool &has_push_down) +{ + int ret = OB_SUCCESS; + has_push_down = false; + for (int64_t i = 0; OB_SUCC(ret) && !has_push_down && i < get_num_of_child(); ++i) { + const ObLogicalOperator *child = NULL; + const ObLogicalOperator *pushdown_op = NULL; + if (OB_ISNULL(child = get_child(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(i), K(child)); + } else if (OB_FAIL(child->get_pushdown_op(log_op_def::LOG_DISTINCT, pushdown_op))) { + LOG_WARN("failed to get push down distinct", K(ret)); + } else if (NULL == pushdown_op) { + // do nothing + } else if (OB_UNLIKELY(log_op_def::LOG_DISTINCT != pushdown_op->get_type())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected pushdown op", K(ret), K(pushdown_op->get_type())); + } else if (static_cast(pushdown_op)->is_push_down()) { + has_push_down = true; + } + } + return ret; +} + int ObLogSet::compute_op_parallel_and_server_info() { int ret = OB_SUCCESS; diff --git a/src/sql/optimizer/ob_log_set.h b/src/sql/optimizer/ob_log_set.h index 2ccca9a687..41d0b7afc2 100644 --- a/src/sql/optimizer/ob_log_set.h +++ b/src/sql/optimizer/ob_log_set.h @@ -122,6 +122,7 @@ public: virtual int print_used_hint(PlanText &plan_text) override; int get_used_pq_set_hint(const ObPQSetHint *&used_hint); int construct_pq_set_hint(ObPQSetHint &hint); + int check_has_push_down(bool &has_push_down); int set_child_ndv(ObIArray &ndv) { return child_ndv_.assign(ndv); } int add_child_ndv(double ndv) { return child_ndv_.push_back(ndv); } virtual int get_card_without_filter(double &card) override; diff --git a/src/sql/optimizer/ob_log_subplan_filter.cpp b/src/sql/optimizer/ob_log_subplan_filter.cpp old mode 100644 new mode 100755 index 34cb70003d..917a43e4e1 --- a/src/sql/optimizer/ob_log_subplan_filter.cpp +++ b/src/sql/optimizer/ob_log_subplan_filter.cpp @@ -228,9 +228,9 @@ int ObLogSubPlanFilter::do_re_est_cost(EstimateCostInfo ¶m, double &card, do double sel = 1.0; ObSEArray cost_infos; if (OB_ISNULL(get_plan()) || OB_ISNULL(child = get_child(ObLogicalOperator::first_child)) - || OB_UNLIKELY(param.need_parallel_ < 1)) { + || OB_UNLIKELY(param.need_parallel_ < 1 || param.need_batch_rescan_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected params", K(ret), K(get_plan()), K(child), K(param.need_parallel_)); + LOG_WARN("unexpected params", K(ret), K(get_plan()), K(child), K(param)); } else if (param.need_row_count_ < 0 || param.need_row_count_ >= child->get_card()) { param.need_row_count_ = -1; } else if (OB_FALSE_IT(get_plan()->get_selectivity_ctx().init_op_ctx(child))) { @@ -282,6 +282,8 @@ int ObLogSubPlanFilter::get_re_est_cost_infos(const EstimateCostInfo ¶m, EstimateCostInfo cur_param; double cur_child_card = 0.0; double cur_child_cost = 0.0; + bool first_child_is_match_all = false; + const common::ObIArray *rescan_left_server_list = param.rescan_left_server_list_; for (int64_t i = 0; OB_SUCC(ret) && i < get_num_of_child(); ++i) { const ObLogicalOperator *child = get_child(i); cur_param.reset(); @@ -290,7 +292,19 @@ int ObLogSubPlanFilter::get_re_est_cost_infos(const EstimateCostInfo ¶m, LOG_WARN("set operator i-th child is null", K(ret), K(i)); } else if (OB_FAIL(cur_param.assign(param))) { LOG_WARN("failed to assign param", K(ret)); - } else if (0 != i && OB_FALSE_IT(cur_param.need_row_count_ = -1)) { + } else if (0 == i) { + if (!child->is_match_all()) { + rescan_left_server_list = &child->get_server_list(); + } + } else { + cur_param.need_row_count_ = -1; + cur_param.need_batch_rescan_ = enable_das_group_rescan() + && !init_plan_idxs_.has_member(i) + && !one_time_idxs_.has_member(i); + cur_param.rescan_left_server_list_ = rescan_left_server_list; + } + + if (OB_FAIL(ret)) { } else if (OB_FAIL(SMART_CALL(get_child(i)->re_est_cost(cur_param, cur_child_card, cur_child_cost)))) { LOG_WARN("failed to re-est child cost", K(ret), K(i)); } else if (OB_FAIL(cost_infos.push_back(ObBasicCostInfo(cur_child_card, cur_child_cost, @@ -436,168 +450,124 @@ int ObLogSubPlanFilter::compute_sharding_info() return ret; } -int ObLogSubPlanFilter::check_if_match_das_group_rescan(ObLogicalOperator *root, - bool &group_rescan) +int ObLogSubPlanFilter::compute_spf_batch_rescan() { int ret = OB_SUCCESS; - if (OB_ISNULL(root)) { + enable_das_group_rescan_ = false; + bool can_batch = false; + if (OB_ISNULL(get_plan())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (root->is_table_scan()) { - bool is_valid = false; - ObLogTableScan *tsc = NULL; - ObLogPlan *plan = NULL; - const AccessPath *ap = NULL; - const TableItem *table_item = NULL; - if (OB_ISNULL(tsc = static_cast(root)) - // tsc might belong to a different subquery - // with its own plan - || OB_ISNULL(plan = tsc->get_plan()) - || OB_ISNULL(ap = tsc->get_access_path()) - || OB_ISNULL(table_item = plan->get_stmt()->get_table_item_by_id(ap->table_id_))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (!tsc->use_das()) { - group_rescan = false; - } else if (tsc->use_index_merge()) { - group_rescan = false; - } - if (OB_SUCC(ret) && group_rescan) { - group_rescan = !(is_virtual_table(ap->ref_table_id_) - || table_item->is_link_table() - || ap->is_cte_path() - || ap->is_function_table_path() - || ap->is_temp_table_path() - || ap->is_json_table_path() - || table_item->for_update_ - || !ap->subquery_exprs_.empty() - || EXTERNAL_TABLE == table_item->table_type_ - ); - } - if (OB_SUCC(ret) && group_rescan) { - if (OB_FAIL(ObOptimizerUtil::check_contribute_query_range(root, - get_exec_params(), - is_valid))) { - LOG_WARN("failed to check query range contribution", K(ret)); - } else if (!is_valid) { - group_rescan = false; - } else if (tsc->get_scan_direction() != default_asc_direction() && tsc->get_scan_direction() != ObOrderDirection::UNORDERED) { - group_rescan = false; - } else if (tsc->has_index_scan_filter() && tsc->get_index_back() && tsc->get_is_index_global()) { - // For the global index lookup, if there is a pushdown filter when scanning the index, - // batch cannot be used. - group_rescan = false; - } else {/*do nothing*/} - } - } else if (log_op_def::LOG_SUBPLAN_SCAN == root->get_type()) { - if (1 != root->get_num_of_child()) { - group_rescan = false; - } else if (OB_ISNULL(root->get_child(0))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (!root->get_child(0)->is_table_scan()) { - group_rescan = false; - } else if (OB_FAIL(SMART_CALL(check_if_match_das_group_rescan(root->get_child(0), - group_rescan)))) { - LOG_WARN("failed to check match das batch rescan", K(ret)); - } - } else {/*do nothing*/} - return ret; -} - -int ObLogSubPlanFilter::set_use_das_batch(ObLogicalOperator* root) -{ - int ret = OB_SUCCESS; - if (OB_ISNULL(root)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid input", K(ret)); - } else if (root->is_table_scan()) { - ObLogTableScan *ts = static_cast(root); - if (!ts->get_range_conditions().empty()) { - if (ts->is_text_retrieval_scan()) { - ts->set_use_batch(false); - } else { - ts->set_use_batch(enable_das_group_rescan_); - } - } - } else if (root->get_num_of_child() == 1) { - if(OB_FAIL(SMART_CALL(set_use_das_batch(root->get_child(first_child))))) { - LOG_WARN("failed to check use das batch", K(ret)); - } - } else { /*do nothing*/ } - return ret; -} - -int ObLogSubPlanFilter::check_and_set_das_group_rescan() -{ - int ret = OB_SUCCESS; - ObSQLSessionInfo *session_info = NULL; - ObQueryCtx *query_ctx = NULL; - ObLogPlan *plan = NULL; - const ObRawExpr *ref_expr = NULL; - bool contains_invalid_startup = false; - bool has_ref_assign_user_var = false; - if (OB_ISNULL(plan = get_plan()) - || OB_ISNULL(session_info = plan->get_optimizer_context().get_session_info()) - || OB_ISNULL(query_ctx = plan->get_optimizer_context().get_query_ctx())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(plan), K(session_info), K(query_ctx)); - } else if (!plan->get_optimizer_context().get_enable_spf_batch_rescan()) { - enable_das_group_rescan_ = false; + LOG_WARN("get unexpected null", K(ret), K(get_plan())); + } else if (!get_plan()->get_optimizer_context().enable_spf_batch_rescan()) { + /* subplan filter group rescan is disabled */ + } else if (get_plan()->get_disable_child_batch_rescan()) { + /* do nothing */ + } else if (get_plan()->get_optimizer_context().enable_experimental_batch_rescan() + && OB_FAIL(compute_spf_batch_rescan(can_batch))) { + LOG_WARN("failed to compute group rescan", K(ret)); + } else if (!get_plan()->get_optimizer_context().enable_experimental_batch_rescan() + && OB_FAIL(compute_spf_batch_rescan_compat(can_batch))) { + LOG_WARN("failed to compute group rescan compat", K(ret)); } else { - enable_das_group_rescan_ = plan->get_optimizer_context().get_nlj_batching_enabled(); + enable_das_group_rescan_ = can_batch; } - // check use batch - for (int64_t i = 1; OB_SUCC(ret) && enable_das_group_rescan_ && i < get_num_of_child(); i++) { - ObLogicalOperator *child = get_child(i); - bool contains_invalid_startup = false; - bool contains_limit = false; - if (OB_ISNULL(child) || OB_ISNULL(child->get_stmt())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret), K(child)); - } else if (get_initplan_idxs().has_member(i) || get_onetime_idxs().has_member(i)) { - enable_das_group_rescan_ = false; - } else if (!(child->get_type() == log_op_def::LOG_TABLE_SCAN - || child->get_type() == log_op_def::LOG_SUBPLAN_SCAN)) { - enable_das_group_rescan_ = false; - } else if (OB_FAIL(check_if_match_das_group_rescan(child, enable_das_group_rescan_))) { - LOG_WARN("failed to check match das batch rescan", K(ret)); - } else if (!enable_das_group_rescan_) { - /* do nothing */ - } else if (OB_FAIL(plan->contains_startup_with_exec_param(child, contains_invalid_startup))) { - LOG_WARN("failed to check contains invalid startup", K(ret)); - } else if (contains_invalid_startup) { - enable_das_group_rescan_ = false; - } else if (OB_FAIL(child->get_stmt()->has_ref_assign_user_var(has_ref_assign_user_var))) { - LOG_WARN("faield to check stmt has assignment ref user var", K(ret)); - } else if (has_ref_assign_user_var) { - enable_das_group_rescan_ = false; - } - } - if (OB_SUCC(ret) && enable_das_group_rescan_ && - OB_FAIL(ObOptimizerUtil::check_ancestor_node_support_skip_scan(this, enable_das_group_rescan_))) { - LOG_WARN("failed to check whether ancestor node support skip read", K(ret)); - } - // check if exec params contain sub_query or rownum - for (int64_t i = 0; OB_SUCC(ret) && enable_das_group_rescan_ && i < exec_params_.count(); i++) { + return ret; +} + +int ObLogSubPlanFilter::compute_spf_batch_rescan(bool &can_batch) +{ + int ret = OB_SUCCESS; + can_batch = true; + const ObRawExpr *ref_expr = NULL; + const ObShardingInfo *sharding = NULL; + const ObLogicalOperator *child = NULL; + const ObDMLStmt *stmt = NULL; + bool has_ref_assign_user_var = false; + bool left_allocated_exchange = false; + bool right_allocated_exchange = false; + bool has_rescan_subquery = false; + // check if exec params contain rownum + for (int64_t i = 0; OB_SUCC(ret) && can_batch && i < exec_params_.count(); i++) { if (OB_ISNULL(exec_params_.at(i)) || OB_ISNULL(ref_expr = exec_params_.at(i)->get_ref_expr())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret), K(i), K(ref_expr), KPC(exec_params_.at(i))); - } else if (ref_expr->has_flag(CNT_SUB_QUERY) || ref_expr->has_flag(CNT_ROWNUM)) { - enable_das_group_rescan_ = false; + } else { + can_batch = !ref_expr->has_flag(CNT_ROWNUM); } } - // set use batch - for (int64_t i = 1; OB_SUCC(ret) && i < get_num_of_child(); i++) { - ObLogicalOperator *child = get_child(i); - if (OB_ISNULL(child)) { + for (int64_t i = 0; OB_SUCC(ret) && can_batch && i < get_num_of_child(); i++) { + if (OB_ISNULL(child = get_child(i)) || OB_ISNULL(sharding = child->get_sharding()) + || OB_ISNULL(stmt= child->get_stmt())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (OB_FAIL(set_use_das_batch(child))) { - LOG_WARN("failed to set use das batch rescan", K(ret)); + LOG_WARN("get unexpected null", K(ret), K(i), K(sharding), K(stmt)); + } else if (0 >= i) { + left_allocated_exchange = child->is_exchange_allocated(); + } else if (init_plan_idxs_.has_member(i) || one_time_idxs_.has_member(i)) { + can_batch = sharding->is_single(); + } else if (OB_FAIL(ObOptimizerUtil::check_can_batch_rescan(child, true, can_batch))) { + LOG_WARN("failed to check plan can batch rescan", K(ret)); + } else if (OB_FAIL(stmt->has_ref_assign_user_var(has_ref_assign_user_var))) { + LOG_WARN("faield to check stmt has assignment ref user var", K(ret)); + } else { + can_batch &= !has_ref_assign_user_var; + has_rescan_subquery = true; + right_allocated_exchange |= child->is_exchange_allocated(); + } + } + if (OB_FAIL(ret) || !can_batch || !has_rescan_subquery) { + can_batch = false; + } else if (DistAlgo::DIST_BASIC_METHOD == dist_algo_ + || DistAlgo::DIST_NONE_ALL == dist_algo_ + || (DistAlgo::DIST_PARTITION_WISE == dist_algo_ + && !left_allocated_exchange + && !right_allocated_exchange)) { + can_batch = true; + } else if (DistAlgo::DIST_PULL_TO_LOCAL == dist_algo_ && !right_allocated_exchange) { + can_batch = true; + } else { + can_batch = false; + } + return ret; +} + +int ObLogSubPlanFilter::compute_spf_batch_rescan_compat(bool &can_batch) +{ + int ret = OB_SUCCESS; + can_batch = false; + if (!init_plan_idxs_.is_empty() || !one_time_idxs_.is_empty()) { + /* disable group rescan for onetime/init plan */ + } else { + can_batch = true; + const ObRawExpr *ref_expr = NULL; + const ObDMLStmt *stmt = NULL; + bool has_ref_assign_user_var = false; + // check if exec params contain sub_query/rownum + for (int64_t i = 0; OB_SUCC(ret) && can_batch && i < exec_params_.count(); i++) { + if (OB_ISNULL(exec_params_.at(i)) || OB_ISNULL(ref_expr = exec_params_.at(i)->get_ref_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(i), K(ref_expr), KPC(exec_params_.at(i))); + } else { + can_batch = !ref_expr->has_flag(CNT_SUB_QUERY) && !ref_expr->has_flag(CNT_ROWNUM); + } + } + for (int64_t i = 1; OB_SUCC(ret) && can_batch && i < get_num_of_child(); i++) { + if (OB_ISNULL(get_child(i)) || OB_ISNULL(stmt= get_child(i)->get_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(i), K(get_child(i)), K(stmt)); + } else if (OB_FAIL(ObOptimizerUtil::check_can_batch_rescan_compat(get_child(i), + exec_params_, + false, + can_batch))) { + LOG_WARN("failed to check plan can batch rescan", K(ret)); + } else if (init_plan_idxs_.has_member(i) || one_time_idxs_.has_member(i)) { + /* do nothing */ + } else if (OB_FAIL(stmt->has_ref_assign_user_var(has_ref_assign_user_var))) { + LOG_WARN("faield to check stmt has assignment ref user var", K(ret)); + } else { + can_batch &= !has_ref_assign_user_var; + } } } - LOG_TRACE("spf das batch rescan", K(ret), K(enable_das_group_rescan_)); return ret; } @@ -929,6 +899,66 @@ int ObLogSubPlanFilter::get_sub_qb_names(ObIArray &sub_qb_names) return ret; } +int ObLogSubPlanFilter::check_right_is_local_scan(bool &is_local_scan) const +{ + int ret = OB_SUCCESS; + is_local_scan = true; + const ObLogicalOperator *child = NULL; + for (int64_t i = 1; is_local_scan && OB_SUCC(ret) && i < get_num_of_child(); i++) { + if (init_plan_idxs_.has_member(i) || one_time_idxs_.has_member(i)) { + /* do nothing */ + } else if (OB_ISNULL(child = get_child(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(i)); + } else if (child->is_exchange_allocated() || child->get_contains_das_op()) { + is_local_scan = false; + } + } + return ret; +} + +int ObLogSubPlanFilter::pre_check_spf_can_px_batch_rescan(bool &can_px_batch_rescan, + bool &rescan_contain_match_all) const +{ + int ret = OB_SUCCESS; + can_px_batch_rescan = false; + rescan_contain_match_all = false; + if (OB_ISNULL(get_plan())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(get_plan())); + } else if (1 < get_available_parallel() || 1 < get_parallel() + || get_exec_params().empty() + || !get_plan()->get_optimizer_context().enable_px_batch_rescan()) { + /* do nothing */ + } else { + bool find_nested_rescan = false; + bool find_rescan_px = false; + bool tmp_find_nested_rescan = false; + bool tmp_find_rescan_px = false; + const ObLogicalOperator *child = NULL; + for (int i = 1; !find_nested_rescan && OB_SUCC(ret) && i < get_num_of_child(); ++i) { + tmp_find_nested_rescan = false; + tmp_find_rescan_px = false; + if (OB_ISNULL(child = get_child(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(i)); + } else if (one_time_idxs_.has_member(i)) { + /* do nothing */ + } else if (OB_FAIL(child->pre_check_can_px_batch_rescan(tmp_find_nested_rescan, tmp_find_rescan_px, false))) { + LOG_WARN("fail to pre check can px batch rescan", K(ret)); + } else { + find_nested_rescan |= tmp_find_nested_rescan; + find_rescan_px |= tmp_find_rescan_px; + rescan_contain_match_all |= child->is_match_all() && child->get_contains_das_op(); + } + } + if (OB_SUCC(ret)) { + can_px_batch_rescan = !find_nested_rescan && find_rescan_px; + } + } + return ret; +} + int ObLogSubPlanFilter::open_px_resource_analyze(OPEN_PX_RESOURCE_ANALYZE_DECLARE_ARG) { int ret = OB_SUCCESS; diff --git a/src/sql/optimizer/ob_log_subplan_filter.h b/src/sql/optimizer/ob_log_subplan_filter.h index ad933dbc3d..265443800f 100644 --- a/src/sql/optimizer/ob_log_subplan_filter.h +++ b/src/sql/optimizer/ob_log_subplan_filter.h @@ -96,17 +96,14 @@ public: int allocate_granule_post(AllocGIContext &ctx); virtual int compute_one_row_info() override; virtual int compute_sharding_info() override; - inline DistAlgo get_distributed_algo() { return dist_algo_; } + inline DistAlgo get_distributed_algo() const { return dist_algo_; } inline void set_distributed_algo(const DistAlgo set_dist_algo) { dist_algo_ = set_dist_algo; } int add_px_batch_rescan_flag(bool flag) { return enable_px_batch_rescans_.push_back(flag); } common::ObIArray &get_px_batch_rescans() { return enable_px_batch_rescans_; } - inline bool enable_das_group_rescan() { return enable_das_group_rescan_; } + inline bool enable_das_group_rescan() const { return enable_das_group_rescan_; } inline void set_enable_das_group_rescan(bool flag) { enable_das_group_rescan_ = flag; } - int check_and_set_das_group_rescan(); - int check_if_match_das_group_rescan(ObLogicalOperator *root, bool &group_rescan); - int set_use_das_batch(ObLogicalOperator* root); int allocate_startup_expr_post() override; @@ -137,6 +134,11 @@ public: virtual int print_used_hint(PlanText &plan_text) override; virtual int open_px_resource_analyze(OPEN_PX_RESOURCE_ANALYZE_DECLARE_ARG) override; virtual int close_px_resource_analyze(CLOSE_PX_RESOURCE_ANALYZE_DECLARE_ARG) override; + int compute_spf_batch_rescan(); + int compute_spf_batch_rescan(bool &can_batch); + int compute_spf_batch_rescan_compat(bool &can_batch); + int check_right_is_local_scan(bool &is_local_scan) const; + int pre_check_spf_can_px_batch_rescan(bool &can_px_batch_rescan, bool &rescan_contain_match_all) const; private: int extract_exist_style_subquery_exprs(ObRawExpr *expr, ObIArray &exist_style_exprs); diff --git a/src/sql/optimizer/ob_log_table_scan.cpp b/src/sql/optimizer/ob_log_table_scan.cpp index 8780e96dc6..ee6238cff1 100644 --- a/src/sql/optimizer/ob_log_table_scan.cpp +++ b/src/sql/optimizer/ob_log_table_scan.cpp @@ -136,6 +136,7 @@ int ObLogTableScan::do_re_est_cost(EstimateCostInfo ¶m, double &card, double limit_percent, limit_count, offset_count))) { LOG_WARN("failed to get limit offset value", K(ret)); } else { + est_cost_info_->rescan_left_server_list_ = param.rescan_left_server_list_; card = get_output_row_count(); int64_t part_count = est_cost_info_->index_meta_info_.index_part_count_; double limit_count_double = static_cast(limit_count); @@ -169,10 +170,12 @@ int ObLogTableScan::do_re_est_cost(EstimateCostInfo ¶m, double &card, double *est_cost_info_, sample_info_, get_plan()->get_optimizer_context(), + access_path_->can_batch_rescan_, card, op_cost))) { LOG_WARN("failed to re estimate cost", K(ret)); } else { + est_cost_info_->rescan_left_server_list_ = NULL; cost = op_cost; if (0 <= limit_count && param.need_row_count_ == -1) { // full scan with table filters @@ -1595,21 +1598,11 @@ int ObLogTableScan::get_plan_item_info(PlanText &plan_text, LOG_WARN("unexpected null param", K(ret)); } else if (OB_FAIL(explain_index_selection_info(buf, buf_len, pos))) { LOG_WARN("failed to explain index selection info", K(ret)); - } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { - LOG_WARN("BUF_PRINTF fails", K(ret)); - } else if (OB_FAIL(BUF_PRINTF(OUTPUT_PREFIX))) { - LOG_WARN("BUF_PRINTF fails", K(ret)); } else if (OB_ISNULL(table_meta = plan->get_basic_table_metas().get_table_meta_by_table_id(table_id_))) { //do nothing - } else if (OB_FAIL(BUF_PRINTF("stats info:[version=%ld", table_meta->get_version()))) { - LOG_WARN("BUF_PRINTF fails", K(ret)); - } else if (OB_FAIL(BUF_PRINTF(", is_locked=%d", table_meta->is_stat_locked()))) { - LOG_WARN("BUF_PRINTF fails", K(ret)); - } else if (OB_FAIL(BUF_PRINTF(", is_expired=%d", table_meta->is_opt_stat_expired()))) { - LOG_WARN("BUF_PRINTF fails", K(ret)); - } else if (OB_FAIL(BUF_PRINTF("]"))) { - LOG_WARN("BUF_PRINTF fails", K(ret)); + } else if (OB_FAIL(print_stats_version(*table_meta, buf, buf_len, pos))) { + LOG_WARN("failed to print stats version", K(ret)); } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { LOG_WARN("BUF_PRINTF fails", K(ret)); } else if (OB_FAIL(BUF_PRINTF(OUTPUT_PREFIX))) { @@ -1732,6 +1725,43 @@ int ObLogTableScan::get_plan_item_info(PlanText &plan_text, return ret; } +int ObLogTableScan::print_stats_version(OptTableMeta &table_meta, char *buf, int64_t &buf_len, int64_t &pos) +{ + int ret = OB_SUCCESS; + ObLogPlan *plan = NULL; + ObSQLSessionInfo *session_info = NULL; + const ObTimeZoneInfo *cur_tz_info = NULL; + if (OB_ISNULL(plan = get_plan()) || + OB_ISNULL(session_info = plan->get_optimizer_context().get_session_info()) || + OB_ISNULL(cur_tz_info = session_info->get_tz_info_wrap().get_time_zone_info())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null param", K(ret)); + } else { + char date[OB_CAST_TO_VARCHAR_MAX_LENGTH] = {0}; + int64_t date_len = 0; + const ObDataTypeCastParams dtc_params(cur_tz_info); + ObOTimestampData in_val; + in_val.time_us_ = table_meta.get_version(); + if (OB_FAIL(ObTimeConverter::otimestamp_to_str(in_val, dtc_params, 6, ObTimestampLTZType, date, + sizeof(date), date_len))) { + LOG_WARN("failed to convert otimestamp to string", K(ret)); + } else if (OB_FAIL(BUF_PRINTF(NEW_LINE))) { + LOG_WARN("BUF_PRINTF fails", K(ret)); + } else if (OB_FAIL(BUF_PRINTF(OUTPUT_PREFIX))) { + LOG_WARN("BUF_PRINTF fails", K(ret)); + } else if (OB_FAIL(BUF_PRINTF("stats info:[version=%.*s", int32_t(date_len), date))) { + LOG_WARN("BUF_PRINTF fails", K(ret)); + } else if (OB_FAIL(BUF_PRINTF(", is_locked=%d", table_meta.is_stat_locked()))) { + LOG_WARN("BUF_PRINTF fails", K(ret)); + } else if (OB_FAIL(BUF_PRINTF(", is_expired=%d", table_meta.is_opt_stat_expired()))) { + LOG_WARN("BUF_PRINTF fails", K(ret)); + } else if (OB_FAIL(BUF_PRINTF("]"))) { + LOG_WARN("BUF_PRINTF fails", K(ret)); + } + } + return ret; +} + int ObLogTableScan::print_est_method(ObBaseTableEstMethod method, char *buf, int64_t &buf_len, int64_t &pos) { int ret = OB_SUCCESS; diff --git a/src/sql/optimizer/ob_log_table_scan.h b/src/sql/optimizer/ob_log_table_scan.h index cfcd054c4e..834ca20058 100644 --- a/src/sql/optimizer/ob_log_table_scan.h +++ b/src/sql/optimizer/ob_log_table_scan.h @@ -516,6 +516,7 @@ public: virtual int inner_replace_op_exprs(ObRawExprReplacer &replacer) override; inline common::ObIArray &get_filter_before_index_flags() { return filter_before_index_back_; } inline const common::ObIArray &get_filter_before_index_flags() const { return filter_before_index_back_; } + inline const ObRawExpr *get_limit_expr() const { return limit_count_expr_; } inline ObRawExpr *get_limit_expr() { return limit_count_expr_; } inline ObRawExpr *get_offset_expr() { return limit_offset_expr_; } int set_limit_offset(ObRawExpr *limit, ObRawExpr *offset); @@ -621,6 +622,7 @@ public: share::schema::ObTableType get_table_type() const { return table_type_; } virtual int get_plan_item_info(PlanText &plan_text, ObSqlPlanItem &plan_item) override; + int print_stats_version(OptTableMeta &table_meta, char *buf, int64_t &buf_len, int64_t &pos); int print_est_method(ObBaseTableEstMethod method, char *buf, int64_t &buf_len, int64_t &pos); int get_plan_object_info(PlanText &plan_text, ObSqlPlanItem &plan_item); @@ -681,6 +683,7 @@ public: inline bool is_vec_idx_scan() const { return is_index_scan() && vector_index_info_.delta_buffer_tid_ != OB_INVALID_ID; } inline ObVectorIndexInfo &get_vector_index_info() { return vector_index_info_; } inline const ObVectorIndexInfo &get_vector_index_info() const { return vector_index_info_; } + inline bool can_batch_rescan() const { return NULL != access_path_ && access_path_->can_batch_rescan_; } inline bool das_need_keep_ordering() const { return das_keep_ordering_; } diff --git a/src/sql/optimizer/ob_logical_operator.cpp b/src/sql/optimizer/ob_logical_operator.cpp index 94c1ded8c9..58f0b54b8e 100644 --- a/src/sql/optimizer/ob_logical_operator.cpp +++ b/src/sql/optimizer/ob_logical_operator.cpp @@ -3087,19 +3087,19 @@ int ObLogicalOperator::check_exchange_rescan(bool &need_rescan) return ret; } -int ObLogicalOperator::check_has_exchange_below(bool &has_exchange) const +int ObLogicalOperator::check_has_op_below(const log_op_def::ObLogOpType target_type, bool &has) const { int ret = OB_SUCCESS; - has_exchange = false; - if (LOG_EXCHANGE == get_type()) { - has_exchange = true; + has = false; + if (target_type == get_type()) { + has = true; } else { ObLogicalOperator *child_op = NULL; - for (int64_t i = 0; OB_SUCC(ret) && !has_exchange && i < get_num_of_child(); ++i) { + for (int64_t i = 0; OB_SUCC(ret) && !has && i < get_num_of_child(); ++i) { if (OB_ISNULL(child_op = get_child(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get_child(i) returns null", K(i), K(ret)); - } else if (OB_FAIL(SMART_CALL(child_op->check_has_exchange_below(has_exchange)))) { + } else if (OB_FAIL(SMART_CALL(child_op->check_has_op_below(target_type, has)))) { LOG_WARN("failed to check if child operator has exchange below", KPC(child_op), K(ret)); } else { /* Do nothing */ } } @@ -5491,6 +5491,10 @@ int ObLogicalOperator::allocate_partition_join_filter(const ObIArrayget_log_op_factory(); CK(LOG_JOIN == get_type()); DistAlgo join_dist_algo = static_cast(this)->get_join_distributed_method(); + if (OB_ISNULL(get_plan())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null plan", K(ret)); + } for (int i = 0; i < infos.count() && OB_SUCC(ret); ++i) { filter_create = NULL; bool right_has_exchange = false; @@ -5543,7 +5547,28 @@ int ObLogicalOperator::allocate_partition_join_filter(const ObIArrayset_is_shared_partition_join_filter(); } - join_filter_create->set_tablet_id_expr(info.calc_part_id_expr_); + if (get_plan()->get_optimizer_context().get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_3_5) && + DistAlgo::DIST_PARTITION_NONE == join_dist_algo) { + ObLogicalOperator* child = get_child(first_child); + if (OB_ISNULL(child)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null child", K(ret)); + } else if (OB_ISNULL(child=child->get_child(first_child))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null child", K(ret)); + } else if (OB_ISNULL(child=child->get_child(first_child))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null child", K(ret)); + } else if (LOG_EXCHANGE != child->get_type()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect child type", K(ret)); + } else { + ObLogExchange *exch_op = static_cast(child); + join_filter_create->set_tablet_id_expr(exch_op->get_calc_part_id_expr()); + } + } else { + join_filter_create->set_tablet_id_expr(info.calc_part_id_expr_); + } OZ(join_filter_create->compute_property()); OZ(bf_info.init(get_plan()->get_optimizer_context().get_session_info()->get_effective_tenant_id(), filter_id, GCTX.get_server_id(), @@ -5862,6 +5887,33 @@ int ObLogicalOperator::find_nested_dis_rescan(bool &find, bool nested) return ret; } +int ObLogicalOperator::pre_check_can_px_batch_rescan(bool &find_nested_rescan, + bool &find_rescan_px, + bool nested) const +{ + int ret = OB_SUCCESS; + if (find_nested_rescan) { + } else if (LOG_EXCHANGE == get_type()) { + const ObLogExchange *op = static_cast(this); + find_nested_rescan |= nested; + find_rescan_px |= !nested && op->is_consumer() && !op->is_task_order(); + } else { + nested = LOG_SUBPLAN_FILTER == get_type() || + (LOG_JOIN == get_type() && + JoinAlgo::NESTED_LOOP_JOIN == static_cast(this)->get_join_algo()); + for (int64_t i = 0; !find_nested_rescan && OB_SUCC(ret) && i < get_num_of_child(); i++) { + const ObLogicalOperator *child = NULL; + if (OB_ISNULL(child = get_child(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(get_child(i)), K(ret)); + } else if (OB_FAIL(SMART_CALL(child->pre_check_can_px_batch_rescan(find_nested_rescan, find_rescan_px, nested)))) { + LOG_WARN("fail to find px for batch rescan", K(ret)); + } + } + } + return ret; +} + int ObLogicalOperator::check_subplan_filter_child_exchange_rescanable() { int ret = OB_SUCCESS; @@ -5982,22 +6034,6 @@ int ObLogicalOperator::find_shuffle_join_filter(bool &find) const return ret; } -int ObLogicalOperator::has_window_function_below(bool &has_win_func) const -{ - int ret = OB_SUCCESS; - has_win_func = LOG_WINDOW_FUNCTION == get_type(); - const ObLogicalOperator *child = NULL; - for (int64_t i = 0; !has_win_func && OB_SUCC(ret) && i < get_num_of_child(); i++) { - if (OB_ISNULL(child = get_child(i))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret), K(child)); - } else if (OB_FAIL(SMART_CALL(child->has_window_function_below(has_win_func)))) { - LOG_WARN("failed to check has window function below", K(ret)); - } - } - return ret; -} - int ObLogicalOperator::get_pushdown_op(log_op_def::ObLogOpType op_type, const ObLogicalOperator *&op) const { int ret = OB_SUCCESS; @@ -6171,12 +6207,9 @@ int ObLogicalOperator::pick_out_startup_filters() { int ret = OB_SUCCESS; ObLogPlan *plan = get_plan(); - const ParamStore *params = NULL; ObOptimizerContext *opt_ctx = NULL; ObArray filter_exprs; - if (OB_ISNULL(plan) - || OB_ISNULL(opt_ctx = &plan->get_optimizer_context()) - || OB_ISNULL(params = opt_ctx->get_params())) { + if (OB_ISNULL(plan) || OB_ISNULL(opt_ctx = &plan->get_optimizer_context())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("NULL pointer error", K(plan), K(opt_ctx), K(ret)); } else if (OB_FAIL(filter_exprs.assign(filter_exprs_))) { diff --git a/src/sql/optimizer/ob_logical_operator.h b/src/sql/optimizer/ob_logical_operator.h index 52f1218d83..648aa98396 100644 --- a/src/sql/optimizer/ob_logical_operator.h +++ b/src/sql/optimizer/ob_logical_operator.h @@ -1412,9 +1412,9 @@ public: int check_exchange_rescan(bool &need_rescan); /** - * Check if has exchange below. + * Check if has target op below. */ - int check_has_exchange_below(bool &has_exchange) const; + int check_has_op_below(const log_op_def::ObLogOpType target_type, bool &has) const; /** * Allocate runtime filter operator. */ @@ -1655,7 +1655,6 @@ public: ObIArray &filters_exprs); int find_shuffle_join_filter(bool &find) const; - int has_window_function_below(bool &has_win_func) const; int get_pushdown_op(log_op_def::ObLogOpType op_type, const ObLogicalOperator *&op) const; virtual int get_plan_item_info(PlanText &plan_text, @@ -1723,6 +1722,9 @@ public: inline ObIArray &get_ambient_card() { return ambient_card_; } + int pre_check_can_px_batch_rescan(bool &find_nested_rescan, + bool &find_rescan_px, + bool nested) const; public: ObSEArray child_; ObSEArray equal_param_constraints_; diff --git a/src/sql/optimizer/ob_opt_cost_model_parameter.cpp b/src/sql/optimizer/ob_opt_cost_model_parameter.cpp index 5255ffa99d..9eae875e45 100644 --- a/src/sql/optimizer/ob_opt_cost_model_parameter.cpp +++ b/src/sql/optimizer/ob_opt_cost_model_parameter.cpp @@ -210,6 +210,24 @@ double ObOptCostModelParameter::get_px_batch_rescan_per_row_cost(const OptSystem } } +double ObOptCostModelParameter::get_das_rescan_per_row_rpc_cost(const OptSystemStat& stat) const +{ + if (stat.get_network_speed() <= 0) { + return DAS_RESCAN_PER_ROW_RPC_COST; + } else { + return DAS_RESCAN_PER_ROW_RPC_COST / stat.get_network_speed(); + } +} + +double ObOptCostModelParameter::get_das_batch_rescan_per_row_rpc_cost(const OptSystemStat& stat) const +{ + if (stat.get_network_speed() <= 0) { + return DAS_BATCH_RESCAN_PER_ROW_RPC_COST; + } else { + return DAS_BATCH_RESCAN_PER_ROW_RPC_COST / stat.get_network_speed(); + } +} + double ObOptCostModelParameter::get_nl_scan_cost(const OptSystemStat& stat) const { if (stat.get_cpu_speed() <= 0) { diff --git a/src/sql/optimizer/ob_opt_cost_model_parameter.h b/src/sql/optimizer/ob_opt_cost_model_parameter.h index 1006629866..bd877f47e1 100644 --- a/src/sql/optimizer/ob_opt_cost_model_parameter.h +++ b/src/sql/optimizer/ob_opt_cost_model_parameter.h @@ -53,6 +53,8 @@ public: const double DEFAULT_NETWORK_TRANS_PER_BYTE_COST, const double DEFAULT_PX_RESCAN_PER_ROW_COST, const double DEFAULT_PX_BATCH_RESCAN_PER_ROW_COST, + const double DEFAULT_DAS_RESCAN_PER_ROW_RPC_COST, + const double DEFAULT_DAS_BATCH_RESCAN_PER_ROW_RPC_COST, const double DEFAULT_NL_SCAN_COST, const double DEFAULT_BATCH_NL_SCAN_COST, const double DEFAULT_NL_GET_COST, @@ -96,6 +98,8 @@ public: NETWORK_TRANS_PER_BYTE_COST(DEFAULT_NETWORK_TRANS_PER_BYTE_COST), PX_RESCAN_PER_ROW_COST(DEFAULT_PX_RESCAN_PER_ROW_COST), PX_BATCH_RESCAN_PER_ROW_COST(DEFAULT_PX_BATCH_RESCAN_PER_ROW_COST), + DAS_RESCAN_PER_ROW_RPC_COST(DEFAULT_DAS_RESCAN_PER_ROW_RPC_COST), + DAS_BATCH_RESCAN_PER_ROW_RPC_COST(DEFAULT_DAS_BATCH_RESCAN_PER_ROW_RPC_COST), NL_SCAN_COST(DEFAULT_NL_SCAN_COST), BATCH_NL_SCAN_COST(DEFAULT_BATCH_NL_SCAN_COST), NL_GET_COST(DEFAULT_NL_GET_COST), @@ -145,6 +149,8 @@ public: double get_network_trans_per_byte_cost(const OptSystemStat& stat) const; double get_px_rescan_per_row_cost(const OptSystemStat& stat) const; double get_px_batch_rescan_per_row_cost(const OptSystemStat& stat) const; + double get_das_rescan_per_row_rpc_cost(const OptSystemStat& stat) const; + double get_das_batch_rescan_per_row_rpc_cost(const OptSystemStat& stat) const; double get_nl_scan_cost(const OptSystemStat& stat) const; double get_batch_nl_scan_cost(const OptSystemStat& stat) const; double get_nl_get_cost(const OptSystemStat& stat) const; @@ -206,6 +212,9 @@ protected: /*additional px-rescan cost*/ double PX_RESCAN_PER_ROW_COST; double PX_BATCH_RESCAN_PER_ROW_COST; + /*additional das-rescan cost*/ + double DAS_RESCAN_PER_ROW_RPC_COST; + double DAS_BATCH_RESCAN_PER_ROW_RPC_COST; //条件下压nestloop join右表扫一次的代价 double NL_SCAN_COST; //条件下压batch nestloop join右表扫一次的代价 diff --git a/src/sql/optimizer/ob_opt_est_cost.cpp b/src/sql/optimizer/ob_opt_est_cost.cpp index 4ac4349400..a0b088cd7d 100644 --- a/src/sql/optimizer/ob_opt_est_cost.cpp +++ b/src/sql/optimizer/ob_opt_est_cost.cpp @@ -51,16 +51,12 @@ const int64_t ObOptEstCost::MAX_STORAGE_RANGE_ESTIMATION_NUM = 10; int ObOptEstCost::cost_nestloop(const ObCostNLJoinInfo &est_cost_info, double &cost, - double &filter_selectivity, - ObIArray &all_predicate_sel, const ObOptimizerContext &opt_ctx) { int ret = OB_SUCCESS; GET_COST_MODEL(); if (OB_FAIL(model->cost_nestloop(est_cost_info, - cost, - filter_selectivity, - all_predicate_sel))) { + cost))) { LOG_WARN("failed to est cost for nestloop join", K(ret)); } return ret; diff --git a/src/sql/optimizer/ob_opt_est_cost.h b/src/sql/optimizer/ob_opt_est_cost.h index c8e0f34bfa..30477dc026 100644 --- a/src/sql/optimizer/ob_opt_est_cost.h +++ b/src/sql/optimizer/ob_opt_est_cost.h @@ -38,8 +38,6 @@ public: static int cost_nestloop(const ObCostNLJoinInfo &est_cost_info, double &cost, - double &filter_selectivity, - common::ObIArray &all_predicate_sel, const ObOptimizerContext &opt_ctx); static int cost_mergejoin(const ObCostMergeJoinInfo &est_cost_info, diff --git a/src/sql/optimizer/ob_opt_est_cost_model.cpp b/src/sql/optimizer/ob_opt_est_cost_model.cpp index 942f43cced..e33ddc6616 100644 --- a/src/sql/optimizer/ob_opt_est_cost_model.cpp +++ b/src/sql/optimizer/ob_opt_est_cost_model.cpp @@ -86,8 +86,9 @@ int ObCostTableScanInfo::assign(const ObCostTableScanInfo &est_cost_info) index_meta_info_.assign(est_cost_info.index_meta_info_); is_virtual_table_ = est_cost_info.is_virtual_table_; is_unique_ = est_cost_info.is_unique_; - is_inner_path_ = est_cost_info.is_inner_path_; - can_use_batch_nlj_ = est_cost_info.can_use_batch_nlj_; + is_das_scan_ = est_cost_info.is_das_scan_; + is_rescan_ = est_cost_info.is_rescan_; + is_batch_rescan_ = est_cost_info.is_batch_rescan_; table_metas_ = est_cost_info.table_metas_; sel_ctx_ = est_cost_info.sel_ctx_; est_method_ = est_cost_info.est_method_; @@ -107,6 +108,8 @@ int ObCostTableScanInfo::assign(const ObCostTableScanInfo &est_cost_info) use_column_store_ = est_cost_info.use_column_store_; at_most_one_range_ = est_cost_info.at_most_one_range_; index_back_with_column_store_ = est_cost_info.index_back_with_column_store_; + rescan_left_server_list_ = est_cost_info.rescan_left_server_list_; + rescan_server_list_ = est_cost_info.rescan_server_list_; limit_rows_ = est_cost_info.limit_rows_; // no need to copy table scan param } @@ -208,9 +211,7 @@ double ObIndexMetaInfo::get_micro_block_numbers() const * + qual_cost */ int ObOptEstCostModel::cost_nestloop(const ObCostNLJoinInfo &est_cost_info, - double &cost, - double &filter_selectivity, - ObIArray &all_predicate_sel) + double &cost) { int ret = OB_SUCCESS; cost = 0.0; @@ -222,60 +223,47 @@ int ObOptEstCostModel::cost_nestloop(const ObCostNLJoinInfo &est_cost_info, double right_rows = est_cost_info.right_rows_; double cart_tuples = left_rows * right_rows; // tuples of Cartesian product double out_tuples = 0.0; - filter_selectivity = 0.0; double material_cost = 0.0; - //selectivity for equal conds - if (OB_FAIL(ObOptSelectivity::calculate_selectivity(*est_cost_info.table_metas_, - *est_cost_info.sel_ctx_, - est_cost_info.other_join_conditions_, - filter_selectivity, - all_predicate_sel))) { - LOG_WARN("Failed to calculate filter selectivity", K(ret)); + double join_sel = est_cost_info.other_cond_sel_; + if (IS_SEMI_ANTI_JOIN(est_cost_info.join_type_)) { + // nested loop join must be left semi/anti join + out_tuples = left_rows * join_sel; } else { - out_tuples = cart_tuples * filter_selectivity; - - // 再次扫描右表全表的代价。如果不使用物化,就是读取一次右表和本层get_next_row的代价; - // 如果物化,则为读取物化后的行的代价。 - double once_rescan_cost = 0.0; - if (est_cost_info.need_mat_) { - once_rescan_cost = cost_read_materialized(right_rows); - } else { - double rescan_cost = 0.0; - if (est_cost_info.right_has_px_rescan_) { - if (est_cost_info.parallel_ > 1) { - rescan_cost = cost_params_.get_px_rescan_per_row_cost(sys_stat_); - } else { - rescan_cost = cost_params_.get_px_batch_rescan_per_row_cost(sys_stat_); - } - } else { - rescan_cost = cost_params_.get_rescan_cost(sys_stat_); - } - once_rescan_cost = est_cost_info.right_cost_ + rescan_cost - + right_rows * cost_params_.get_cpu_tuple_cost(sys_stat_); - } - // total rescan cost - if (LEFT_SEMI_JOIN == est_cost_info.join_type_ - || LEFT_ANTI_JOIN == est_cost_info.join_type_) { - double match_sel = (est_cost_info.anti_or_semi_match_sel_ < OB_DOUBLE_EPSINON) ? - OB_DOUBLE_EPSINON : est_cost_info.anti_or_semi_match_sel_; - out_tuples = left_rows * match_sel; - } - cost += left_rows * once_rescan_cost; - //qual cost - double qual_cost = cost_quals(left_rows * right_rows, est_cost_info.equal_join_conditions_) + - cost_quals(left_rows * right_rows, est_cost_info.other_join_conditions_); - - cost += qual_cost; - - double join_cost = cost_params_.get_join_per_row_cost(sys_stat_) * out_tuples; - cost += join_cost; - - LOG_TRACE("OPT: [COST NESTLOOP JOIN]", - K(cost), K(qual_cost), K(join_cost),K(once_rescan_cost), - K(est_cost_info.left_cost_), K(est_cost_info.right_cost_), - K(left_rows), K(right_rows), K(est_cost_info.right_width_), - K(filter_selectivity), K(cart_tuples), K(material_cost)); + out_tuples = left_rows * right_rows * join_sel; } + + + // 再次扫描右表全表的代价。如果不使用物化,就是读取一次右表和本层get_next_row的代价; + // 如果物化,则为读取物化后的行的代价。 + double once_rescan_cost = 0.0; + if (est_cost_info.need_mat_) { + once_rescan_cost = cost_read_materialized(right_rows); + } else { + double rescan_cost = 0.0; + if (est_cost_info.right_has_px_rescan_) { + if (est_cost_info.parallel_ > 1) { + rescan_cost = cost_params_.get_px_rescan_per_row_cost(sys_stat_); + } else { + rescan_cost = cost_params_.get_px_batch_rescan_per_row_cost(sys_stat_); + } + } else { + rescan_cost = cost_params_.get_rescan_cost(sys_stat_); + } + once_rescan_cost = est_cost_info.right_cost_ + rescan_cost + + right_rows * cost_params_.get_cpu_tuple_cost(sys_stat_); + } + cost += left_rows * once_rescan_cost; + //qual cost + double qual_cost = cost_quals(left_rows * right_rows, est_cost_info.equal_join_conditions_) + + cost_quals(left_rows * right_rows, est_cost_info.other_join_conditions_); + cost += qual_cost; + double join_cost = cost_params_.get_join_per_row_cost(sys_stat_) * out_tuples; + cost += join_cost; + LOG_TRACE("OPT: [COST NESTLOOP JOIN]", K(out_tuples), + K(cost), K(qual_cost), K(join_cost),K(once_rescan_cost), + K(est_cost_info.left_cost_), K(est_cost_info.right_cost_), + K(left_rows), K(right_rows), K(est_cost_info.right_width_), + K(join_sel), K(cart_tuples), K(material_cost)); } return ret; } @@ -1392,6 +1380,7 @@ int ObOptEstCostModel::cost_basic_table(const ObCostTableScanInfo &est_cost_info double index_scan_cost = 0; double index_back_cost = 0; double prefix_filter_sel = 1.0; + double das_rpc_cost = 0.0; // calc scan one partition cost if (OB_FAIL(cost_index_scan(est_cost_info, row_count_per_part, @@ -1405,6 +1394,8 @@ int ObOptEstCostModel::cost_basic_table(const ObCostTableScanInfo &est_cost_info prefix_filter_sel, index_back_cost))) { LOG_WARN("failed to calc index back cost", K(ret)); + } else if (OB_FAIL(calc_das_rpc_cost(est_cost_info, das_rpc_cost))) { + LOG_WARN("failed to calc das rpc cost", K(ret)); } else { cost += index_scan_cost; OPT_TRACE_COST_MODEL(KV(cost), "+=", KV(index_scan_cost)); @@ -1413,7 +1404,10 @@ int ObOptEstCostModel::cost_basic_table(const ObCostTableScanInfo &est_cost_info // calc one parallel scan cost cost *= part_cnt_per_dop; OPT_TRACE_COST_MODEL(KV(cost), "*=", KV(part_cnt_per_dop)); - LOG_TRACE("OPT:[ESTIMATE FINISH]", K(cost), K(part_cnt_per_dop), K(est_cost_info)); + // calc das rescan scan rpc cost + cost += das_rpc_cost; + OPT_TRACE_COST_MODEL(KV(cost), "+=", KV(das_rpc_cost)); + LOG_TRACE("OPT:[ESTIMATE FINISH]", K(cost), K(part_cnt_per_dop), K(das_rpc_cost), K(est_cost_info)); } return ret; } @@ -1691,6 +1685,67 @@ int ObOptEstCostModel::cost_row_store_index_back(const ObCostTableScanInfo &est_ return ret; } + +int ObOptEstCostModel::calc_das_rpc_cost(const ObCostTableScanInfo &est_cost_info, + double &das_rpc_cost) +{ + int ret = OB_SUCCESS; + das_rpc_cost = 0.0; + double remote_rpc_cnt = 0; + double local_rpc_cnt = 0; + if (OB_ISNULL(est_cost_info.sel_ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(est_cost_info.sel_ctx_)); + } else if (!est_cost_info.sel_ctx_->get_opt_ctx().enable_425_batch_rescan()) { + /* do nothing */ + } else if (!est_cost_info.is_das_scan_ || !est_cost_info.is_rescan_) { + /* do nothing */ + } else if (OB_FAIL(get_rescan_rpc_cnt(est_cost_info.rescan_left_server_list_, + est_cost_info.rescan_server_list_, + remote_rpc_cnt, + local_rpc_cnt))) { + LOG_WARN("failed to get rescan rpc cnt", K(ret)); + } else if (est_cost_info.is_batch_rescan_) { + // ignore local rpc now + das_rpc_cost = remote_rpc_cnt * cost_params_.get_das_batch_rescan_per_row_rpc_cost(sys_stat_); + } else { + das_rpc_cost = remote_rpc_cnt * cost_params_.get_das_rescan_per_row_rpc_cost(sys_stat_); + } + return ret; +} + +int ObOptEstCostModel::get_rescan_rpc_cnt(const ObIArray *left_server_list, + const ObIArray *right_server_list, + double &remote_rpc_cnt, + double &local_rpc_cnt) +{ + int ret = OB_SUCCESS; + remote_rpc_cnt = 0; + local_rpc_cnt = 0; + if (OB_ISNULL(right_server_list) || OB_UNLIKELY(right_server_list->empty())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected right server list", K(ret), KPC(right_server_list)); + } else if (NULL == left_server_list || left_server_list->empty() + || ObShardingInfo::is_shuffled_server_list(*left_server_list)) { + remote_rpc_cnt = right_server_list->count(); + } else if (1 == left_server_list->count() && 1 == right_server_list->count()) { + if (left_server_list->at(0) == right_server_list->at(0)) { + local_rpc_cnt = 1; + } else { + remote_rpc_cnt = 1; + } + } else if (ObOptimizerUtil::is_subset(*left_server_list, *right_server_list)) { + remote_rpc_cnt = right_server_list->count() - 1; + local_rpc_cnt = 1; + } else { + remote_rpc_cnt = right_server_list->count(); + local_rpc_cnt = 0; + } + LOG_TRACE("OPT:[GET RESCAN RPC CNT]", KPC(left_server_list), KPC(right_server_list), + K(remote_rpc_cnt), K(local_rpc_cnt)); + return ret; +} + /* * estimate the network transform and rpc cost for global index, * so far, this cost model should be revised by banliu @@ -1828,8 +1883,8 @@ int ObOptEstCostModel::range_get_io_cost(const ObCostTableScanInfo &est_cost_inf } // IO代价,包括读取整个微块及反序列化的代价和每行定位微块的代价 double first_block_cost = cost_params_.get_micro_block_rnd_cost(sys_stat_); - if (est_cost_info.is_inner_path_) { - if (est_cost_info.can_use_batch_nlj_) { + if (est_cost_info.is_rescan_) { + if (est_cost_info.is_batch_rescan_) { first_block_cost = cost_params_.get_batch_nl_get_cost(sys_stat_); } else { first_block_cost = cost_params_.get_nl_get_cost(sys_stat_); @@ -1881,8 +1936,8 @@ int ObOptEstCostModel::range_scan_io_cost(const ObCostTableScanInfo &est_cost_in // IO代价,主要包括读取微块、反序列化的代价的代价 double first_block_cost = cost_params_.get_micro_block_rnd_cost(sys_stat_); - if (!est_cost_info.pushdown_prefix_filters_.empty()) { - if (est_cost_info.can_use_batch_nlj_) { + if (est_cost_info.is_rescan_) { + if (est_cost_info.is_batch_rescan_) { first_block_cost = cost_params_.get_batch_nl_scan_cost(sys_stat_); } else { first_block_cost = cost_params_.get_nl_scan_cost(sys_stat_); diff --git a/src/sql/optimizer/ob_opt_est_cost_model.h b/src/sql/optimizer/ob_opt_est_cost_model.h index 1796af3a46..200b2d9c00 100644 --- a/src/sql/optimizer/ob_opt_est_cost_model.h +++ b/src/sql/optimizer/ob_opt_est_cost_model.h @@ -216,8 +216,9 @@ struct ObCostTableScanInfo index_meta_info_(ref_table_id, index_id), is_virtual_table_(is_virtual_table(ref_table_id)), is_unique_(false), - is_inner_path_(false), - can_use_batch_nlj_(false), + is_das_scan_(false), + is_rescan_(false), + is_batch_rescan_(false), ranges_(), ss_ranges_(), range_columns_(), @@ -244,6 +245,8 @@ struct ObCostTableScanInfo use_column_store_(false), at_most_one_range_(false), index_back_with_column_store_(false), + rescan_left_server_list_(NULL), + rescan_server_list_(NULL), limit_rows_(-1.0) { } virtual ~ObCostTableScanInfo() @@ -257,7 +260,7 @@ struct ObCostTableScanInfo K_(table_meta_info), K_(index_meta_info), K_(access_column_items), K_(is_virtual_table), K_(is_unique), - K_(is_inner_path), K_(can_use_batch_nlj), K_(est_method), + K_(is_das_scan), K_(is_rescan), K_(is_batch_rescan), K_(est_method), K_(prefix_filter_sel), K_(pushdown_prefix_filter_sel), K_(postfix_filter_sel), K_(table_filter_sel), K_(ss_prefix_ndv), K_(ss_postfix_range_filters_sel), @@ -274,8 +277,9 @@ struct ObCostTableScanInfo ObIndexMetaInfo index_meta_info_; // index related meta info bool is_virtual_table_; // is virtual table bool is_unique_; // whether query range is unique - bool is_inner_path_; - bool can_use_batch_nlj_; + bool is_das_scan_; + bool is_rescan_; + bool is_batch_rescan_; ObRangesArray ranges_; // all the ranges ObRangesArray ss_ranges_; // skip scan ranges common::ObSEArray range_columns_; // all the range columns @@ -313,6 +317,8 @@ struct ObCostTableScanInfo bool index_back_with_column_store_; common::ObSEArray index_scan_column_group_infos_; common::ObSEArray index_back_column_group_infos_; + const common::ObIArray *rescan_left_server_list_; + const common::ObIArray *rescan_server_list_; double limit_rows_; private: @@ -360,7 +366,7 @@ struct ObCostNLJoinInfo : public ObCostBaseJoinInfo ObCostNLJoinInfo(double left_rows, double left_cost, double left_width, double right_rows, double right_cost, double right_width, ObRelIds left_ids, ObRelIds right_ids, ObJoinType join_type, - double anti_or_semi_match_sel, + double other_cond_sel, bool with_nl_param, bool need_mat, bool right_has_px_rescan, @@ -379,7 +385,7 @@ struct ObCostNLJoinInfo : public ObCostBaseJoinInfo sel_ctx), left_cost_(left_cost), right_cost_(right_cost), - anti_or_semi_match_sel_(anti_or_semi_match_sel), + other_cond_sel_(other_cond_sel), parallel_(parallel), with_nl_param_(with_nl_param), need_mat_(need_mat), @@ -393,7 +399,7 @@ struct ObCostNLJoinInfo : public ObCostBaseJoinInfo K_(equal_join_conditions), K_(other_join_conditions), K_(filters)); double left_cost_; double right_cost_; - double anti_or_semi_match_sel_; + double other_cond_sel_; int64_t parallel_; bool with_nl_param_; bool need_mat_; @@ -669,9 +675,7 @@ public: virtual ~ObOptEstCostModel()=default; int cost_nestloop(const ObCostNLJoinInfo &est_cost_info, - double &cost, - double &filter_selectivity, - common::ObIArray &all_predicate_sel); + double &cost); int cost_mergejoin(const ObCostMergeJoinInfo &est_cost_info, double &cost); @@ -879,7 +883,6 @@ protected: double limit_count, double &prefix_filter_sel, double &cost); - int cost_column_store_index_scan(const ObCostTableScanInfo &est_cost_info, double row_count, double &prefix_filter_sel, @@ -898,6 +901,12 @@ protected: double row_count, double limit_count, double &cost); + int calc_das_rpc_cost(const ObCostTableScanInfo &est_cost_info, + double &das_rpc_cost); + int get_rescan_rpc_cnt(const ObIArray *left_server_list, + const ObIArray *right_server_list, + double &remote_rpc_cnt, + double &local_rpc_cnt); // estimate the network transform and rpc cost for global index int cost_global_index_back_with_rp(double row_count, const ObCostTableScanInfo &est_cost_info, diff --git a/src/sql/optimizer/ob_opt_est_parameter_normal.h b/src/sql/optimizer/ob_opt_est_parameter_normal.h index 8b459dfc47..72c2524c00 100644 --- a/src/sql/optimizer/ob_opt_est_parameter_normal.h +++ b/src/sql/optimizer/ob_opt_est_parameter_normal.h @@ -38,6 +38,8 @@ const static double NORMAL_NETWORK_DESER_PER_BYTE_COST = 0.0094539370039375 * DE const static double NORMAL_NETWORK_TRANS_PER_BYTE_COST = 0.011832508338 * DEFAULT_NETWORK_SPEED; const static double NORMAL_PX_RESCAN_PER_ROW_COST = 398.267410467 * DEFAULT_CPU_SPEED; const static double NORMAL_PX_BATCH_RESCAN_PER_ROW_COST = 49.5841472833 * DEFAULT_CPU_SPEED; +const static double NORMAL_DAS_RESCAN_PER_ROW_RPC_COST = 258.3167 * DEFAULT_NETWORK_SPEED; +const static double NORMAL_DAS_BATCH_RESCAN_PER_ROW_RPC_COST = 2.1243 * DEFAULT_NETWORK_SPEED; const static double NORMAL_NL_SCAN_COST = 19.2 * DEFAULT_CPU_SPEED; const static double NORMAL_BATCH_NL_SCAN_COST = 16.11 * DEFAULT_CPU_SPEED; const static double NORMAL_NL_GET_COST = 8.24 * DEFAULT_CPU_SPEED; @@ -206,6 +208,8 @@ const static ObOptCostModelParameter cost_params_normal( NORMAL_NETWORK_TRANS_PER_BYTE_COST, NORMAL_PX_RESCAN_PER_ROW_COST, NORMAL_PX_BATCH_RESCAN_PER_ROW_COST, + NORMAL_DAS_RESCAN_PER_ROW_RPC_COST, + NORMAL_DAS_BATCH_RESCAN_PER_ROW_RPC_COST, NORMAL_NL_SCAN_COST, NORMAL_BATCH_NL_SCAN_COST, NORMAL_NL_GET_COST, diff --git a/src/sql/optimizer/ob_opt_est_parameter_vector.h b/src/sql/optimizer/ob_opt_est_parameter_vector.h index 02f32a77f0..de49c0cc92 100644 --- a/src/sql/optimizer/ob_opt_est_parameter_vector.h +++ b/src/sql/optimizer/ob_opt_est_parameter_vector.h @@ -38,6 +38,8 @@ const static double VECTOR_NETWORK_DESER_PER_BYTE_COST = 0.0094539370039375 * DE const static double VECTOR_NETWORK_TRANS_PER_BYTE_COST = 0.011832508338 * DEFAULT_NETWORK_SPEED; const static double VECTOR_PX_RESCAN_PER_ROW_COST = 398.267410467 * DEFAULT_CPU_SPEED; const static double VECTOR_PX_BATCH_RESCAN_PER_ROW_COST = 49.5841472833 * DEFAULT_CPU_SPEED; +const static double VECTOR_DAS_RESCAN_PER_ROW_RPC_COST = 258.3167 * DEFAULT_NETWORK_SPEED; +const static double VECTOR_DAS_BATCH_RESCAN_PER_ROW_RPC_COST = 2.1243 * DEFAULT_NETWORK_SPEED; const static double VECTOR_NL_SCAN_COST = 17.92 * DEFAULT_CPU_SPEED; const static double VECTOR_BATCH_NL_SCAN_COST = 15.32 * DEFAULT_CPU_SPEED; const static double VECTOR_NL_GET_COST = 6.4 * DEFAULT_CPU_SPEED; @@ -201,6 +203,8 @@ const static ObOptCostModelParameter cost_params_vector( VECTOR_NETWORK_TRANS_PER_BYTE_COST, VECTOR_PX_RESCAN_PER_ROW_COST, VECTOR_PX_BATCH_RESCAN_PER_ROW_COST, + VECTOR_DAS_RESCAN_PER_ROW_RPC_COST, + VECTOR_DAS_BATCH_RESCAN_PER_ROW_RPC_COST, VECTOR_NL_SCAN_COST, VECTOR_BATCH_NL_SCAN_COST, VECTOR_NL_GET_COST, diff --git a/src/sql/optimizer/ob_opt_selectivity.cpp b/src/sql/optimizer/ob_opt_selectivity.cpp index 33162aacf4..8318debac1 100644 --- a/src/sql/optimizer/ob_opt_selectivity.cpp +++ b/src/sql/optimizer/ob_opt_selectivity.cpp @@ -146,6 +146,7 @@ int OptColumnMeta::assign(const OptColumnMeta &other) cg_macro_blk_cnt_ = other.cg_macro_blk_cnt_; cg_micro_blk_cnt_ = other.cg_micro_blk_cnt_; cg_skip_rate_ = other.cg_skip_rate_; + base_ndv_ = other.base_ndv_; return ret; } @@ -164,6 +165,7 @@ void OptColumnMeta::init(const uint64_t column_id, cg_macro_blk_cnt_ = cg_macro_blk_cnt; cg_micro_blk_cnt_ = cg_micro_blk_cnt; cg_skip_rate_ = cg_skip_rate; + base_ndv_ = ndv; } int OptTableMeta::assign(const OptTableMeta &other) @@ -180,6 +182,7 @@ int OptTableMeta::assign(const OptTableMeta &other) base_meta_info_ = other.base_meta_info_; real_rows_ = other.real_rows_; stale_stats_ = other.stale_stats_; + base_rows_ = other.base_rows_; if (OB_FAIL(all_used_parts_.assign(other.all_used_parts_))) { LOG_WARN("failed to assign all used parts", K(ret)); @@ -224,6 +227,7 @@ int OptTableMeta::init(const uint64_t table_id, table_partition_info_ = table_partition_info; base_meta_info_ = base_meta_info; real_rows_ = -1.0; + base_rows_ = rows; if (OB_FAIL(all_used_parts_.assign(all_used_part_id))) { LOG_WARN("failed to assign all used partition ids", K(ret)); } else if (OB_FAIL(all_used_tablets_.assign(all_used_tablets))) { @@ -307,6 +311,7 @@ int OptTableMeta::init_column_meta(const OptSelectivityCtx &ctx, col_meta.set_cg_macro_blk_cnt(stat.cg_macro_blk_cnt_); col_meta.set_cg_micro_blk_cnt(stat.cg_micro_blk_cnt_); col_meta.set_cg_skip_rate(stat.cg_skip_rate_); + col_meta.set_base_ndv(col_meta.get_ndv()); } return ret; } @@ -487,6 +492,7 @@ int OptTableMetas::add_set_child_stmt_meta_info(const ObSelectStmt *parent_stmt, table_meta->set_table_id(table_id); table_meta->set_ref_table_id(OB_INVALID_ID); table_meta->set_rows(table_rows); + table_meta->set_base_rows(table_rows); for (int64_t i = 0; OB_SUCC(ret) && i < child_stmt->get_select_item_size(); ++i) { exprs.reset(); double ndv = 1; @@ -562,7 +568,7 @@ int OptTableMetas::add_generate_table_meta_info(const ObDMLStmt *parent_stmt, ObSEArray column_items; ObSEArray exprs; ObRawExpr *select_expr = NULL; - if (OB_ISNULL(parent_stmt) || OB_ISNULL(child_stmt)) { + if (OB_ISNULL(parent_stmt) || OB_ISNULL(child_stmt) || OB_ISNULL(child_ctx.get_plan())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get null stmt", K(ret), K(parent_stmt), K(child_stmt)); } else if (OB_ISNULL(table_meta = table_metas_.alloc_place_holder())) { @@ -572,9 +578,20 @@ int OptTableMetas::add_generate_table_meta_info(const ObDMLStmt *parent_stmt, LOG_WARN("failed to get column items", K(ret)); } else { const double table_rows = child_rows < 1.0 ? 1.0 : child_rows; + double base_table_rows = table_rows; + bool is_child_single_spj = child_stmt->is_spj() && 1 == child_stmt->get_table_size(); table_meta->set_table_id(table_id); table_meta->set_ref_table_id(OB_INVALID_ID); table_meta->set_rows(table_rows); + if (is_child_single_spj) { + const TableItem *table = child_stmt->get_table_item(0); + if (OB_NOT_NULL(table)) { + base_table_rows = child_table_metas.get_base_rows(table->table_id_); + table_meta->set_base_rows(base_table_rows); + } + } else { + table_meta->set_base_rows(table_rows); + } for (int64_t i = 0; OB_SUCC(ret) && i < column_items.count(); ++i) { const ColumnItem &column_item = column_items.at(i); exprs.reset(); @@ -629,6 +646,23 @@ int OptTableMetas::add_generate_table_meta_info(const ObDMLStmt *parent_stmt, column_meta->set_max_value(maxobj); column_meta->set_avg_len(avg_len); } + if (OB_SUCC(ret) && is_child_single_spj) { + double base_ndv = ndv; + double nns = 1.0; + if (OB_FAIL(ObOptSelectivity::calc_expr_basic_info(child_table_metas, + child_ctx, + select_expr, + NULL, + &nns, + &base_ndv))) { + LOG_WARN("failed to calculate distinct", K(ret)); + } else { + nns = ObOptSelectivity::revise_between_0_1(nns); + base_ndv = revise_ndv(base_ndv); + column_meta->set_num_null(table_rows * (1 - nns)); + column_meta->set_base_ndv(base_ndv); + } + } } } } @@ -660,6 +694,7 @@ int OptTableMetas::add_values_table_meta_info(const ObDMLStmt *stmt, table_meta->set_table_id(table_id); table_meta->set_ref_table_id(OB_INVALID_ID); table_meta->set_rows(table_def->row_cnt_); + table_meta->set_base_rows(table_def->row_cnt_); for (int64_t i = 0; OB_SUCC(ret) && i < column_items.count(); ++i) { const ColumnItem &column_item = column_items.at(i); int64_t idx = column_item.column_id_ - OB_APP_MIN_COLUMN_ID; @@ -810,6 +845,16 @@ double OptTableMetas::get_rows(const uint64_t table_id) const return rows; } +double OptTableMetas::get_base_rows(const uint64_t table_id) const +{ + const OptTableMeta *table_meta = get_table_meta_by_table_id(table_id); + double rows = 1.0; + if (OB_NOT_NULL(table_meta)) { + rows = table_meta->get_base_rows(); + } + return rows; +} + int ObOptSelectivity::calculate_conditional_selectivity(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, common::ObIArray &total_filters, @@ -950,12 +995,19 @@ int ObOptSelectivity::calculate_join_selectivity(const OptTableMetas &table_meta const OptSelectivityCtx &ctx, const ObIArray &predicates, double &selectivity, - ObIArray &all_predicate_sel) + ObIArray &all_predicate_sel, + bool is_outerjoin_filter) { int ret = OB_SUCCESS; selectivity = 1.0; ObSEArray sel_estimators; ObSelEstimatorFactory factory; + double reliable_sel_upper_bound = 1.0; + double default_complex_sel = 1.0; + bool is_complex_join = !is_outerjoin_filter && + (INNER_JOIN == ctx.get_assumption_type() || + IS_OUTER_JOIN(ctx.get_assumption_type())); + bool cnt_complex_qual = false; if (OB_ISNULL(ctx.get_session_info())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret)); @@ -993,9 +1045,49 @@ int ObOptSelectivity::calculate_join_selectivity(const OptTableMetas &table_meta } else if (OB_FAIL(estimator->get_sel(table_metas, ctx, tmp_selectivity, all_predicate_sel))) { LOG_WARN("failed to get sel", K(ret), KPC(estimator)); } else { - selectivity *= revise_between_0_1(tmp_selectivity); + tmp_selectivity = revise_between_0_1(tmp_selectivity); + selectivity *= tmp_selectivity; + if (estimator->is_complex_join_qual()) { + cnt_complex_qual = true; + } else { + reliable_sel_upper_bound = std::min(reliable_sel_upper_bound, tmp_selectivity); + } } } + + /** + * For complex inner/outer join (which has at least two kinds of quals or one complex join qual), + * we assume that each row of the small table matches at least one row of the large table. + */ + if (OB_SUCC(ret) && ctx.check_opt_compat_version(COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, + COMPAT_VERSION_4_3_5)) { + is_complex_join &= sel_estimators.count() > 1 || cnt_complex_qual; + if (is_complex_join) { + if (LEFT_SEMI_JOIN == ctx.get_join_type()) { + default_complex_sel = ctx.get_left_row_count() > 1.0 ? + std::min(1.0, ctx.get_right_row_count() / ctx.get_left_row_count()) : + 1.0; + } else if (RIGHT_SEMI_JOIN == ctx.get_join_type()) { + default_complex_sel = ctx.get_right_row_count() > 1.0 ? + std::min(1.0, ctx.get_left_row_count() / ctx.get_right_row_count()) : + 1.0; + } else { + double max_rowcnt = MAX(ctx.get_left_row_count(), ctx.get_right_row_count()); + default_complex_sel = max_rowcnt > 1.0 ? 1.0 / max_rowcnt : 1.0; + } + /** + * If the join has some normal quals, the selectivity could not be greater than the minimal one + * e.g. For join condition `A = B and M = N and X like Y`, + * join_selectivity should be less than `A = B` and 'M = N', + * but could be greater than `X like Y`. + * Because we assume that the selectivity of single equal quals is reliable. + */ + default_complex_sel = std::min(default_complex_sel, reliable_sel_upper_bound); + selectivity = std::max(selectivity, default_complex_sel); + } + } + LOG_TRACE("succeed to calculate join selectivity", + K(selectivity), K(is_complex_join), K(default_complex_sel), K(reliable_sel_upper_bound), K(ctx)); return ret; } @@ -2198,7 +2290,8 @@ int ObOptSelectivity::get_column_basic_info(const OptTableMetas &table_metas, double *ndv_ptr, double *num_null_ptr, double *avg_len_ptr, - double *row_count_ptr) + double *row_count_ptr, + DistinctEstType est_type) { int ret = OB_SUCCESS; if (OB_UNLIKELY(!expr.is_column_ref_expr())) { @@ -2212,6 +2305,7 @@ int ObOptSelectivity::get_column_basic_info(const OptTableMetas &table_metas, double avg_len = 0; double row_count = 0; double cur_rowcnt = ctx.get_current_rows(); + double base_ndv = 0; if (OB_FAIL(get_column_basic_from_meta(table_metas, column_expr, @@ -2219,36 +2313,48 @@ int ObOptSelectivity::get_column_basic_info(const OptTableMetas &table_metas, row_count, ndv, num_null, - avg_len))) { + avg_len, + base_ndv))) { LOG_WARN("failed to get column basic from meta", K(ret)); - } else if (need_default && OB_FAIL(get_var_basic_default(row_count, ndv, num_null, avg_len))) { + } else if (need_default && + OB_FAIL(get_var_basic_default(row_count, ndv, num_null, avg_len, base_ndv))) { LOG_WARN("failed to get var default info", K(ret)); } else { if (num_null > row_count - ndv) { num_null = row_count - ndv > 0 ? row_count - ndv : 0; } - if (NULL != ctx.get_ambient_card() && - !ctx.get_ambient_card()->empty() && - ctx.check_opt_compat_version(COMPAT_VERSION_4_2_4, COMPAT_VERSION_4_3_0, - COMPAT_VERSION_4_3_3)) { - ObSEArray table_idx; - if (OB_FAIL(expr.get_relation_ids().to_array(table_idx))) { - LOG_WARN("failed to get table idx", K(ret), K(expr)); - } else if (OB_UNLIKELY(table_idx.count() != 1) || - OB_UNLIKELY(table_idx.at(0) < 1) || - OB_UNLIKELY(table_idx.at(0) >= ctx.get_ambient_card()->count())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected expr relation ids", K(expr), K(table_idx), K(ctx)); - } else { - cur_rowcnt = ctx.get_ambient_card()->at(table_idx.at(0)); + switch (est_type) { + case DistinctEstType::BASE: + ndv = base_ndv; + cur_rowcnt = -1.0; + break; + case DistinctEstType::CURRENT: { + cur_rowcnt = ctx.get_current_rows(); + if (NULL != ctx.get_ambient_card() && + !ctx.get_ambient_card()->empty() && + ctx.check_opt_compat_version(COMPAT_VERSION_4_2_4, COMPAT_VERSION_4_3_0, + COMPAT_VERSION_4_3_3)) { + ObSEArray table_idx; + if (OB_FAIL(expr.get_relation_ids().to_array(table_idx))) { + LOG_WARN("failed to get table idx", K(ret), K(expr)); + } else if (OB_UNLIKELY(table_idx.count() != 1) || + OB_UNLIKELY(table_idx.at(0) < 1) || + OB_UNLIKELY(table_idx.at(0) >= ctx.get_ambient_card()->count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected expr relation ids", K(expr), K(table_idx), K(ctx)); + } else { + cur_rowcnt = ctx.get_ambient_card()->at(table_idx.at(0)); + } + } + break; } } - if (OB_SUCC(ret) && cur_rowcnt > 0.0 && cur_rowcnt < row_count) { ndv = scale_distinct(cur_rowcnt, row_count, ndv); } - LOG_TRACE("show column basic info", K(row_count), K(cur_rowcnt), K(num_null), K(avg_len), K(ndv)); + LOG_TRACE("show column basic info", + K(row_count), K(cur_rowcnt), K(num_null), K(avg_len), K(ndv), K(est_type)); // set return if (OB_SUCC(ret)) { @@ -2268,7 +2374,8 @@ int ObOptSelectivity::get_column_basic_from_meta(const OptTableMetas &table_meta double &row_count, double &ndv, double &num_null, - double &avg_len) + double &avg_len, + double &base_ndv) { int ret = OB_SUCCESS; uint64_t table_id = column_expr.get_table_id(); @@ -2284,6 +2391,7 @@ int ObOptSelectivity::get_column_basic_from_meta(const OptTableMetas &table_meta ndv = column_meta->get_ndv(); num_null = column_meta->get_num_null(); avg_len = column_meta->get_avg_len(); + base_ndv = column_meta->get_base_ndv(); } } else { use_default = true; @@ -2294,13 +2402,15 @@ int ObOptSelectivity::get_column_basic_from_meta(const OptTableMetas &table_meta int ObOptSelectivity::get_var_basic_default(double &row_count, double &ndv, double &null_num, - double &avg_len) + double &avg_len, + double &base_ndv) { int ret = OB_SUCCESS; row_count = 1.0; ndv = 1.0; null_num = static_cast(row_count * EST_DEF_COL_NULL_RATIO); avg_len = DEFAULT_COLUMN_SIZE; + base_ndv = 1.0; return ret; } @@ -2349,10 +2459,9 @@ int ObOptSelectivity::get_compare_value(const OptSelectivityCtx &ctx, LOG_WARN("stmt is null", K(ret)); } else if (!calc_expr->is_static_scalar_const_expr()) { can_cmp = false; - } else if (OB_FAIL(ObRelationalExprOperator::is_equivalent(col->get_result_type(), - col->get_result_type(), - calc_expr->get_result_type(), - type_safe))) { + } else if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive(col->get_result_type(), + calc_expr->get_result_type(), + type_safe))) { LOG_WARN("failed to check is type safe", K(ret)); } else if (!type_safe) { can_cmp = false; @@ -2747,11 +2856,13 @@ int ObOptSelectivity::calculate_table_ambient_cardinality(const OptTableMetas &t const OptSelectivityCtx &ctx, const ObRelIds &rel_ids, const double cur_rows, - double &table_ambient_card) + double &table_ambient_card, + DistinctEstType est_type) { int ret = OB_SUCCESS; if (NULL != ctx.get_ambient_card() && - !ctx.get_ambient_card()->empty()) { + !ctx.get_ambient_card()->empty() && + DistinctEstType::CURRENT == est_type) { table_ambient_card = 1.0; for (int64_t i = 0; i < ctx.get_ambient_card()->count(); i ++) { if (rel_ids.has_member(i)) { @@ -2769,7 +2880,10 @@ int ObOptSelectivity::calculate_table_ambient_cardinality(const OptTableMetas &t LOG_WARN("faile to get table ids", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && i < table_ids.count(); i ++) { - table_ambient_card *= std::max(1.0, table_metas.get_rows(table_ids.at(i))); + table_ambient_card *= std::max(1.0, + DistinctEstType::BASE == est_type ? + table_metas.get_base_rows(table_ids.at(i)) : + table_metas.get_rows(table_ids.at(i))); } } if (cur_rows > 0) { @@ -2783,6 +2897,7 @@ int ObOptSelectivity::calculate_distinct_in_single_table(const OptTableMetas &ta const ObRelIds &rel_id, const common::ObIArray& exprs, const double cur_rows, + DistinctEstType est_type, double &rows) { int ret = OB_SUCCESS; @@ -2795,11 +2910,11 @@ int ObOptSelectivity::calculate_distinct_in_single_table(const OptTableMetas &ta if (OB_UNLIKELY(rel_id.num_members() != 1)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected relation id", K(ret)); - } else if (OB_FAIL(calculate_table_ambient_cardinality(table_metas, ctx, rel_id, cur_rows, ambient_card))) { + } else if (OB_FAIL(calculate_table_ambient_cardinality(table_metas, ctx, rel_id, cur_rows, ambient_card, est_type))) { LOG_WARN("failed to calculate ambient card", K(ret)); - } else if (OB_FAIL(filter_column_by_equal_set(table_metas, ctx, exprs, filtered_exprs))) { + } else if (OB_FAIL(filter_column_by_equal_set(table_metas, ctx, est_type, exprs, filtered_exprs))) { LOG_WARN("failed filter column by equal set", K(ret)); - } else if (OB_FAIL(calculate_expr_ndv(filtered_exprs, expr_ndv, table_metas, ctx, ambient_card))) { + } else if (OB_FAIL(calculate_expr_ndv(filtered_exprs, expr_ndv, table_metas, ctx, ambient_card, est_type))) { LOG_WARN("fail to calculate expr ndv", K(ret)); } else if (!ctx.check_opt_compat_version(COMPAT_VERSION_4_2_4, COMPAT_VERSION_4_3_0, COMPAT_VERSION_4_3_3)) { @@ -2884,7 +2999,8 @@ int ObOptSelectivity::calculate_distinct(const OptTableMetas &table_metas, const ObIArray& exprs, const double origin_rows, double &rows, - const bool need_refine) + const bool need_refine, + DistinctEstType est_type) { int ret = OB_SUCCESS; rows = 1; @@ -2899,7 +3015,7 @@ int ObOptSelectivity::calculate_distinct(const OptTableMetas &table_metas, LOG_WARN("failed to classify_exprs", K(ret)); } else if (OB_FAIL(remove_dummy_distinct_exprs(helpers, special_exprs))) { LOG_WARN("failed to remove dummy exprs", K(ret)); - } else if (OB_FAIL(calculate_expr_ndv(special_exprs, single_ndvs, table_metas, ctx, origin_rows))) { + } else if (OB_FAIL(calculate_expr_ndv(special_exprs, single_ndvs, table_metas, ctx, origin_rows, est_type))) { LOG_WARN("fail to calculate expr ndv", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && i < helpers.count(); i ++) { @@ -2908,7 +3024,7 @@ int ObOptSelectivity::calculate_distinct(const OptTableMetas &table_metas, if (OB_FAIL(remove_dummy_distinct_exprs(helpers, helper.exprs_))) { LOG_WARN("failed to remove dummy exprs", K(ret)); } else if (OB_FAIL(calculate_distinct_in_single_table( - table_metas, ctx, helper.rel_id_, helper.exprs_, need_refine ? origin_rows : -1, single_table_ndv))) { + table_metas, ctx, helper.rel_id_, helper.exprs_, need_refine ? origin_rows : -1, est_type, single_table_ndv))) { LOG_WARN("failed to calculate distinct in single table", K(helper.exprs_)); } else if (OB_FAIL(single_ndvs.push_back(single_table_ndv))) { LOG_WARN("failed to push back", K(ret)); @@ -2939,13 +3055,14 @@ int ObOptSelectivity::calculate_distinct(const OptTableMetas &table_metas, const ObRawExpr& expr, const double origin_rows, double &rows, - const bool need_refine) + const bool need_refine, + DistinctEstType est_type) { int ret = OB_SUCCESS; ObSEArray expr_array; if (OB_FAIL(expr_array.push_back(const_cast(&expr)))) { LOG_WARN("failed to push back expr", K(ret)); - } else if (OB_FAIL(calculate_distinct(table_metas, ctx, expr_array, origin_rows, rows, need_refine))) { + } else if (OB_FAIL(calculate_distinct(table_metas, ctx, expr_array, origin_rows, rows, need_refine, est_type))) { LOG_WARN("failed to calculate distinct", K(expr)); } return ret; @@ -3068,7 +3185,8 @@ int ObOptSelectivity::calculate_expr_ndv(const ObIArray& exprs, ObIArray& expr_ndv, const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, - const double origin_rows) + const double origin_rows, + DistinctEstType est_type) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) { @@ -3080,12 +3198,12 @@ int ObOptSelectivity::calculate_expr_ndv(const ObIArray& exprs, } else if (expr->is_column_ref_expr()) { if (OB_FAIL(check_column_in_current_level_stmt(ctx.get_stmt(), *expr))) { LOG_WARN("failed to check column in current level stmt", K(ret)); - } else if (OB_FAIL(get_column_basic_info(table_metas, ctx, *expr, &ndv, NULL, NULL, NULL))) { + } else if (OB_FAIL(get_column_basic_info(table_metas, ctx, *expr, &ndv, NULL, NULL, NULL, est_type))) { LOG_WARN("failed to get column basic info", K(ret), K(*expr)); } else if (OB_FAIL(expr_ndv.push_back(ndv))) { LOG_WARN("failed to push back expr", K(ret), K(ndv)); } - } else if (OB_FAIL(calculate_special_ndv(table_metas, expr, ctx, ndv, origin_rows))) { + } else if (OB_FAIL(calculate_special_ndv(table_metas, expr, ctx, ndv, origin_rows, est_type))) { LOG_WARN("failed to calculate special expr ndv", K(ret), K(ndv)); } else if (OB_FAIL(expr_ndv.push_back(ndv))) { LOG_WARN("failed to push back", K(ret), K(ndv)); @@ -3148,7 +3266,8 @@ int ObOptSelectivity::calculate_special_ndv(const OptTableMetas &table_metas, const ObRawExpr* expr, const OptSelectivityCtx &ctx, double &special_ndv, - const double origin_rows) + const double origin_rows, + DistinctEstType est_type) { int ret = OB_SUCCESS; const ObRawExpr *param_expr = NULL; @@ -3186,7 +3305,8 @@ int ObOptSelectivity::calculate_special_ndv(const OptTableMetas &table_metas, substr_len - ObOptEstCostModel::DEFAULT_FIXED_OBJ_WIDTH, origin_rows, special_ndv, - dummy))) { + dummy, + est_type))) { LOG_WARN("failed to calculate substr ndv", K(ret)); } } else if (is_dense_time_expr_type(expr->get_expr_type()) || @@ -3253,7 +3373,9 @@ int ObOptSelectivity::calculate_special_ndv(const OptTableMetas &table_metas, ctx, *param_expr, origin_rows, - ndv_upper_bound)))) { + ndv_upper_bound, + true, + est_type)))) { LOG_WARN("failed to calculate distinct", K(ret), KPC(param_expr)); } else { special_ndv = std::min(special_ndv, ndv_upper_bound); @@ -3401,12 +3523,13 @@ int ObOptSelectivity::calculate_winfunc_ndv(const OptTableMetas &table_metas, // 再把不在 equal set 中的列加入到 filtered_exprs 中, int ObOptSelectivity::filter_column_by_equal_set(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, + DistinctEstType est_type, const ObIArray &column_exprs, ObIArray &filtered_exprs) { int ret = OB_SUCCESS; const EqualSets *equal_sets = ctx.get_equal_sets(); - if (NULL == equal_sets) { + if (NULL == equal_sets || DistinctEstType::CURRENT != est_type) { if (OB_FAIL(append(filtered_exprs, column_exprs))) { LOG_WARN("failed to append filtered exprs", K(ret)); } @@ -3507,12 +3630,13 @@ int ObOptSelectivity::get_min_ndv_by_equal_set(const OptTableMetas &table_metas, } else if (!is_in) { //do nothing } else if (OB_FAIL(get_column_basic_info(table_metas, - ctx, - *equal_set->at(k), - &tmp_ndv, - NULL, - NULL, - NULL))) { + ctx, + *equal_set->at(k), + &tmp_ndv, + NULL, + NULL, + NULL, + DistinctEstType::CURRENT))) { LOG_WARN("failed to get var basic sel", K(ret)); } else if (OB_INVALID_INDEX_INT64 == min_idx || tmp_ndv < min_ndv) { min_idx = k; @@ -3929,7 +4053,7 @@ double ObOptSelectivity::scale_distinct(double selected_rows, */ int ObOptSelectivity::get_join_pred_rows(const ObHistogram &left_hist, const ObHistogram &right_hist, - const bool is_semi, + const ObJoinType join_type, double &rows) { int ret = OB_SUCCESS; @@ -3943,8 +4067,10 @@ int ObOptSelectivity::get_join_pred_rows(const ObHistogram &left_hist, LOG_WARN("failed to compare histogram endpoint value", K(ret), K(left_hist.get(lidx).endpoint_value_), K(right_hist.get(ridx).endpoint_value_)); } else if (0 == eq_cmp) { - if (is_semi) { + if (IS_LEFT_SEMI_ANTI_JOIN(join_type)) { rows += left_hist.get(lidx).endpoint_repeat_count_; + } else if (IS_RIGHT_SEMI_ANTI_JOIN(join_type)) { + rows += right_hist.get(ridx).endpoint_repeat_count_; } else { rows += left_hist.get(lidx).endpoint_repeat_count_ * right_hist.get(ridx).endpoint_repeat_count_; } @@ -4295,7 +4421,8 @@ int ObOptSelectivity::calculate_substrb_info(const OptTableMetas &table_metas, const double substrb_len, const double cur_rows, double &substr_ndv, - double &nns) + double &nns, + DistinctEstType est_type) { int ret = OB_SUCCESS; double expr_len = 0.0; @@ -4316,7 +4443,9 @@ int ObOptSelectivity::calculate_substrb_info(const OptTableMetas &table_metas, ctx, *str_expr, cur_rows, - expr_ndv))) { + expr_ndv, + true, + est_type))) { LOG_WARN("failed to calculate distinct", K(ret)); } else if (OB_FAIL(calculate_expr_nns(table_metas, ctx, str_expr, nns))) { LOG_WARN("failed to calculate nns", KPC(str_expr)); @@ -4634,5 +4763,172 @@ int ObOptSelectivity::convert_obj_to_expr_type(const OptSelectivityCtx &ctx, return ret; } +double ObOptSelectivity::calc_equal_filter_sel(const OptSelectivityCtx &ctx, + bool is_same_expr, + ObItemType op_type, + double left_ndv, + double right_ndv, + double left_nns, + double right_nns) +{ + double selectivity = 0.0; + if (is_same_expr) { + // same table same column + if (T_OP_NSEQ == op_type) { + selectivity = 1.0; + } else if (T_OP_EQ == op_type) { + selectivity = left_nns; + } else if (T_OP_NE == op_type) { + selectivity = 0.0; + } + } else if (ctx.check_opt_compat_version(COMPAT_VERSION_4_2_4, COMPAT_VERSION_4_3_0, + COMPAT_VERSION_4_3_3)) { + double combine_ndv = combine_two_ndvs(ctx.get_current_rows(), left_ndv, right_ndv); + combine_ndv = std::max(1.0, combine_ndv); + selectivity = std::min(left_ndv, right_ndv) / combine_ndv; + if (T_OP_NSEQ == op_type) { + selectivity = selectivity * left_nns * right_nns + (1 - left_nns) * (1 - right_nns); + } else if (T_OP_EQ == op_type) { + selectivity = selectivity * left_nns * right_nns; + } else if (T_OP_NE == op_type) { + selectivity = std::max(1 - selectivity, 1 / combine_ndv / 2.0) * left_nns * right_nns ; + } + } else { + // deprecated + if (T_OP_NSEQ == op_type) { + selectivity = left_nns * right_nns / std::max(left_ndv, right_ndv) + + (1 - left_nns) * (1 - right_nns); + } else if (T_OP_EQ == op_type) { + selectivity = left_nns * right_nns / std::max(left_ndv, right_ndv); + } else if (T_OP_NE == op_type) { + selectivity = left_nns * right_nns * (1 - 1/std::max(left_ndv, right_ndv)); + } + } + + return selectivity; +} + +double ObOptSelectivity::calc_equal_join_sel(const OptSelectivityCtx &ctx, + ObItemType op_type, + double left_ndv, + double right_ndv, + double left_nns, + double right_nns, + double left_base_ndv, + double right_base_ndv) + +{ + double selectivity = 0.0; + ObJoinType join_type = ctx.get_join_type(); + left_base_ndv = MAX(left_ndv, left_base_ndv); + right_base_ndv = MAX(right_ndv, right_base_ndv); + if (IS_RIGHT_STYLE_JOIN(join_type)) { + std::swap(left_ndv, right_ndv); + std::swap(left_nns, right_nns); + std::swap(left_base_ndv, right_base_ndv); + } + if (T_OP_NE == op_type && IS_SEMI_ANTI_JOIN(join_type)) { + if (right_ndv > 1.0) { + // if right ndv > 1.0, then there must exist one value not equal to left value + selectivity = left_nns; + } else { + selectivity = left_nns * std::max(1 - 1 / left_ndv, 1 / left_ndv); + } + } else if (IS_ANTI_JOIN(ctx.get_join_type()) && ctx.check_opt_compat_version(COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, + COMPAT_VERSION_4_3_5)) { + // use base containment assumption only for anti join + selectivity = (std::min(left_base_ndv, right_base_ndv) / left_base_ndv) * (right_ndv / right_base_ndv) * left_nns; + if (T_OP_NSEQ == op_type && 1 - right_nns > 0) { + selectivity += (1 - left_nns); + } + } else if (IS_SEMI_ANTI_JOIN(join_type)) { + selectivity = (std::min(left_ndv, right_ndv) / left_ndv) * left_nns; + if (T_OP_NSEQ == op_type && 1 - right_nns > 0) { + selectivity += (1 - left_nns); + } + } else { + // inner/outer join + double max_ndv = std::max(left_ndv, right_ndv); + if (T_OP_NSEQ == op_type) { + selectivity = left_nns * right_nns / max_ndv + (1 - left_nns) * (1 - right_nns); + } else if (T_OP_EQ == op_type) { + selectivity = left_nns * right_nns / max_ndv; + } else if (T_OP_NE == op_type) { + selectivity = left_nns * right_nns * std::max(1 - 1 / max_ndv, 1 / max_ndv); + } + } + if (IS_ANTI_JOIN(ctx.get_join_type())) { + selectivity = std::min(selectivity, 1 - DEFAULT_ANTI_JOIN_SEL); + } + return selectivity; +} + +int ObOptSelectivity::calc_expr_basic_info(const OptTableMetas &table_metas, + const OptSelectivityCtx &ctx, + const ObRawExpr *expr, + double *ndv, + double *nns, + double *base_ndv) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null expr", K(ret)); + } else if (OB_FAIL(remove_ignorable_func_for_est_sel(expr))) { + LOG_WARN("failed to remove ignorable function", K(ret)); + } else if (expr->is_column_ref_expr()) { + double num_null = 0; + double min_ndv = 0; + if (OB_FAIL(get_column_ndv_and_nns(table_metas, ctx, *expr, ndv, nns))) { + LOG_WARN("failed to get ndv and nns", K(ret)); + } else if ((OB_NOT_NULL(ndv) || OB_NOT_NULL(nns)) && OB_NOT_NULL(ctx.get_equal_sets())) { + bool find = false; + ObRawExpr *dummy = NULL; + if (OB_FAIL(get_min_ndv_by_equal_set(table_metas, + ctx, + expr, + find, + dummy, + min_ndv))) { + LOG_WARN("failed to find the expr with min ndv", K(ret)); + } else if (find) { + assign_value(min_ndv, ndv); + assign_value(1.0, nns); + } + } + if (OB_NOT_NULL(base_ndv)) { + if (OB_FAIL(get_column_basic_info( + table_metas, ctx, *expr, base_ndv, NULL, NULL, NULL, DistinctEstType::BASE))) { + LOG_WARN("failed to get base ndv", K(ret), KPC(expr)); + } + } + } else { + if (OB_NOT_NULL(ndv) && + OB_FAIL(calculate_distinct(table_metas, + ctx, + *expr, + ctx.get_current_rows(), + *ndv))) { + LOG_WARN("Failed to calculate distinct", K(ret)); + } else if (OB_NOT_NULL(nns) && + OB_FAIL(calculate_expr_nns(table_metas, + ctx, + expr, + *nns))) { + LOG_WARN("failed to calculate nns", K(ret)); + } else if (OB_NOT_NULL(base_ndv) && + OB_FAIL(calculate_distinct(table_metas, + ctx, + *expr, + ctx.get_current_rows(), + *base_ndv, + false, + DistinctEstType::BASE))) { + LOG_WARN("Failed to calculate distinct", K(ret)); + } + } + return ret; +} + }//end of namespace sql }//end of namespace oceanbase diff --git a/src/sql/optimizer/ob_opt_selectivity.h b/src/sql/optimizer/ob_opt_selectivity.h index df04ee04b3..9016bc5917 100644 --- a/src/sql/optimizer/ob_opt_selectivity.h +++ b/src/sql/optimizer/ob_opt_selectivity.h @@ -250,7 +250,7 @@ class OptSelectivityCtx ambient_card_ = NULL; } - TO_STRING_KV(KP_(stmt), KP_(equal_sets), K_(join_type), KP_(left_rel_ids), KP_(right_rel_ids), + TO_STRING_KV(KP_(stmt), KP_(equal_sets), K_(join_type), KPC_(left_rel_ids), KPC_(right_rel_ids), K_(row_count_1), K_(row_count_2), K_(current_rows), KPC_(ambient_card)); private: @@ -293,7 +293,8 @@ public: min_max_inited_(false), cg_macro_blk_cnt_(0), cg_micro_blk_cnt_(0), - cg_skip_rate_(1.0) + cg_skip_rate_(1.0), + base_ndv_(-1.0) { min_val_.set_min_value(); max_val_.set_max_value(); @@ -336,12 +337,15 @@ public: void set_default_meta(double rows) { ndv_ = std::min(rows, std::max(100.0, rows / 100.0)); + base_ndv_ = ndv_; num_null_ = rows * EST_DEF_COL_NULL_RATIO; } + double get_base_ndv() const { return base_ndv_; } + void set_base_ndv(double ndv) { base_ndv_ = ndv; } TO_STRING_KV(K_(column_id), K_(ndv), K_(num_null), K_(avg_len), K_(hist_scale), K_(min_val), K_(max_val) , K_(min_max_inited), K_(cg_macro_blk_cnt), - K_(cg_micro_blk_cnt), K_(cg_skip_rate)); + K_(cg_micro_blk_cnt), K_(cg_skip_rate), K_(base_ndv)); private: uint64_t column_id_; double ndv_; @@ -356,6 +360,7 @@ private: int64_t cg_macro_blk_cnt_; int64_t cg_micro_blk_cnt_; double cg_skip_rate_; + double base_ndv_; }; enum OptTableStatType { @@ -447,6 +452,8 @@ public: void set_ref_table_id(const uint64_t &ref_table_id) { ref_table_id_ = ref_table_id; } double get_rows() const { return rows_; } void set_rows(const double rows) { rows_ = rows; } + double get_base_rows() const { return base_rows_; } + void set_base_rows(const double rows) { base_rows_ = rows; } int64_t get_version() const { return last_analyzed_; } void set_version(const int64_t version) { last_analyzed_ = version; } int64_t get_micro_block_count() const { return micro_block_count_; } @@ -521,6 +528,8 @@ private: double real_rows_; //mark stat is expired bool stale_stats_; + // rows without filters + double base_rows_; }; struct OptSelectivityDSParam { @@ -534,6 +543,12 @@ struct OptSelectivityDSParam { ObSEArray quals_; }; +enum class DistinctEstType +{ + BASE, // estimate the ndv without any filters + CURRENT, // estimate current ndv according to current rows and ambient cardinality +}; + class OptTableMetas { public: @@ -598,6 +613,7 @@ public: const ObIArray &get_dynamic_expr_metas() const { return dynamic_expr_metas_; } double get_rows(const uint64_t table_id) const; + double get_base_rows(const uint64_t table_id) const; TO_STRING_KV(K_(table_metas), K_(dynamic_expr_metas)); private: common::ObSEArray table_metas_; @@ -671,7 +687,8 @@ public: const OptSelectivityCtx &ctx, const common::ObIArray &quals, double &selectivity, - common::ObIArray &all_predicate_sel); + common::ObIArray &all_predicate_sel, + bool is_outerjoin_filter = false); static int calculate_qual_selectivity(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, @@ -704,13 +721,15 @@ public: const OptSelectivityCtx &ctx, const ObRelIds &rel_id, const double cur_rows, - double &table_ambient_card); + double &table_ambient_card, + DistinctEstType est_type); static int calculate_distinct_in_single_table(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, const ObRelIds &rel_ids, const common::ObIArray& exprs, const double cur_rows, + DistinctEstType est_type, double &rows); static int remove_dummy_distinct_exprs(ObIArray &helpers, @@ -726,14 +745,16 @@ public: const common::ObIArray& exprs, const double origin_rows, double &rows, - const bool need_refine = true); + const bool need_refine = true, + DistinctEstType est_type = DistinctEstType::CURRENT); static int calculate_distinct(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, const ObRawExpr& expr, const double origin_rows, double &rows, - const bool need_refine = true); + const bool need_refine = true, + DistinctEstType est_type = DistinctEstType::CURRENT); static double combine_two_ndvs(double ambient_card, double ndv1, double ndv2); @@ -846,7 +867,8 @@ public: double *ndv_ptr, double *num_null_ptr, double *avg_len_ptr, - double *row_count_ptr); + double *row_count_ptr, + DistinctEstType est_type = DistinctEstType::CURRENT); static int get_column_hist_scale(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, @@ -859,12 +881,14 @@ public: double &row_count, double &ndv, double &num_null, - double &avg_len); + double &avg_len, + double &base_ndv); static int get_var_basic_default(double &row_count, double &ndv, double &null_num, - double &avg_len); + double &avg_len, + double &base_ndv); static int get_histogram_by_column(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, @@ -937,6 +961,7 @@ public: static int filter_column_by_equal_set(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, + DistinctEstType est_type, const common::ObIArray &column_exprs, common::ObIArray &filtered_exprs); static int filter_one_column_by_equal_set(const OptTableMetas &table_metas, @@ -995,7 +1020,7 @@ public: static int get_join_pred_rows(const ObHistogram &left_histogram, const ObHistogram &right_histogram, - const bool is_semi, + const ObJoinType join_type, double &rows); static int calc_complex_predicates_selectivity_by_ds(const OptTableMetas &table_metas, @@ -1042,7 +1067,8 @@ public: const ObRawExpr* expr, const OptSelectivityCtx &ctx, double &special_ndv, - const double origin_rows); + const double origin_rows, + DistinctEstType est_type); static int calculate_winfunc_ndv(const OptTableMetas &table_meta, const ObRawExpr* expr, const OptSelectivityCtx &ctx, @@ -1052,7 +1078,8 @@ public: ObIArray& expr_ndv, const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, - const double origin_rows); + const double origin_rows, + DistinctEstType est_type); static int check_is_special_distinct_expr(const OptSelectivityCtx &ctx, const ObRawExpr *expr, bool &is_special); @@ -1086,7 +1113,8 @@ public: const double substrb_len, const double cur_rows, double &ndv, - double &nns); + double &nns, + DistinctEstType est_type = DistinctEstType::CURRENT); static int calculate_expr_nns(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, const ObRawExpr *expr, @@ -1128,6 +1156,30 @@ public: T_FUN_SYS_SECOND == type; } + static double calc_equal_filter_sel(const OptSelectivityCtx &ctx, + bool is_same_expr, + ObItemType op_type, + double left_ndv, + double right_ndv, + double left_nns, + double right_nns); + + static double calc_equal_join_sel(const OptSelectivityCtx &ctx, + ObItemType op_type, + double left_ndv, + double right_ndv, + double left_nns, + double right_nns, + double left_base_ndv = -1.0, + double right_base_ndv = -1.0); + + static int calc_expr_basic_info(const OptTableMetas &table_metas, + const OptSelectivityCtx &ctx, + const ObRawExpr *expr, + double *ndv, + double *nns, + double *base_ndv); + private: DISALLOW_COPY_AND_ASSIGN(ObOptSelectivity); }; diff --git a/src/sql/optimizer/ob_optimizer.cpp b/src/sql/optimizer/ob_optimizer.cpp index 3bd3593265..a3a714c03a 100644 --- a/src/sql/optimizer/ob_optimizer.cpp +++ b/src/sql/optimizer/ob_optimizer.cpp @@ -564,6 +564,7 @@ int ObOptimizer::extract_opt_ctx_basic_flags(const ObDMLStmt &stmt, ObSQLSession bool storage_estimation_enabled = false; bool has_cursor_expr = false; int64_t link_stmt_count = 0; + ObQueryCtx* query_ctx = ctx_.get_query_ctx(); bool push_join_pred_into_view_enabled = true; bool partition_wise_plan_enabled = true; bool exists_partition_wise_plan_enabled_hint = false; @@ -581,7 +582,10 @@ int ObOptimizer::extract_opt_ctx_basic_flags(const ObDMLStmt &stmt, ObSQLSession bool better_inlist_costing = false; bool enable_spf_batch_rescan = session.is_spf_mlj_group_rescan_enabled(); const ObOptParamHint &opt_params = ctx_.get_global_hint().opt_params_; - if (OB_FAIL(check_whether_contain_nested_sql(stmt))) { + if (OB_ISNULL(query_ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get null query ctx"); + } else if (OB_FAIL(check_whether_contain_nested_sql(stmt))) { LOG_WARN("check whether contain nested sql failed", K(ret)); } else if (OB_FAIL(stmt.check_has_subquery_in_function_table(has_subquery_in_function_table))) { LOG_WARN("failed to check stmt has function table", K(ret)); @@ -634,6 +638,8 @@ int ObOptimizer::extract_opt_ctx_basic_flags(const ObDMLStmt &stmt, ObSQLSession exists_partition_wise_plan_enabled_hint))) { LOG_WARN("failed to check partition wise plan enabled", K(ret)); } else { + ctx_.init_batch_rescan_flags(enable_use_batch_nlj, enable_spf_batch_rescan, + query_ctx->optimizer_features_enable_version_); ctx_.set_storage_estimation_enabled(storage_estimation_enabled); ctx_.set_serial_set_order(force_serial_set_order); ctx_.set_has_multiple_link_stmt(link_stmt_count > 1); @@ -647,8 +653,6 @@ int ObOptimizer::extract_opt_ctx_basic_flags(const ObDMLStmt &stmt, ObSQLSession ctx_.set_optimizer_index_cost_adj(optimizer_index_cost_adj); ctx_.set_is_skip_scan_enabled(is_skip_scan_enable); ctx_.set_enable_better_inlist_costing(better_inlist_costing); - ctx_.set_nlj_batching_enabled(enable_use_batch_nlj); - ctx_.set_enable_spf_batch_rescan(enable_spf_batch_rescan); ctx_.set_push_join_pred_into_view_enabled(push_join_pred_into_view_enabled); if (!hash_join_enabled && !optimizer_sortmerge_join_enabled diff --git a/src/sql/optimizer/ob_optimizer_context.h b/src/sql/optimizer/ob_optimizer_context.h index 0de7a4bf40..48f7939464 100644 --- a/src/sql/optimizer/ob_optimizer_context.h +++ b/src/sql/optimizer/ob_optimizer_context.h @@ -219,6 +219,7 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, batch_size_(0), root_stmt_(root_stmt), enable_px_batch_rescan_(-1), + batch_rescan_flags_(0), column_usage_infos_(), temp_table_infos_(), exchange_allocated_(false), @@ -255,8 +256,6 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, optimizer_index_cost_adj_(0), is_skip_scan_enabled_(false), enable_better_inlist_costing_(false), - nlj_batching_enabled_(false), - enable_spf_batch_rescan_(false), correlation_type_(ObEstCorrelationType::MAX), use_column_store_replica_(false), push_join_pred_into_view_enabled_(true), @@ -425,6 +424,21 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, return enable_px_batch_rescan_; } + void init_batch_rescan_flags(const bool enable_batch_nlj, + const bool enable_batch_spf, + const uint64_t opt_version) + { + enable_nlj_batch_rescan_ = enable_batch_nlj; + enable_spf_batch_rescan_ = enable_batch_nlj && enable_batch_spf; + // adaptive group-rescan is supported in 4.2.3.0 + enable_425_batch_rescan_ = GET_MIN_CLUSTER_VERSION() >= COMPAT_VERSION_4_2_3 + && (opt_version >= COMPAT_VERSION_4_2_5 || opt_version >= COMPAT_VERSION_4_3_5); + } + inline bool enable_nlj_batch_rescan() const { return enable_nlj_batch_rescan_; } + inline bool enable_spf_batch_rescan() const { return enable_spf_batch_rescan_; } + inline bool enable_425_batch_rescan() const { return enable_425_batch_rescan_; } + inline bool enable_experimental_batch_rescan() const { return false; } + int get_px_object_sample_rate() { if (-1 == px_object_sample_rate_) { @@ -658,10 +672,6 @@ ObOptimizerContext(ObSQLSessionInfo *session_info, inline void set_is_skip_scan_enabled(bool v) { is_skip_scan_enabled_ = v; } inline bool get_enable_better_inlist_costing() const { return enable_better_inlist_costing_; } inline void set_enable_better_inlist_costing(bool v) { enable_better_inlist_costing_ = v; } - inline bool get_nlj_batching_enabled() const { return nlj_batching_enabled_; } - inline void set_nlj_batching_enabled(bool v) { nlj_batching_enabled_ = v; } - inline bool get_enable_spf_batch_rescan() const { return enable_spf_batch_rescan_; } - inline void set_enable_spf_batch_rescan(bool v) { enable_spf_batch_rescan_ = v; } inline bool use_column_store_replica() const { return use_column_store_replica_; } inline void set_use_column_store_replica(bool use) { use_column_store_replica_ = use; } @@ -707,6 +717,14 @@ private: int64_t batch_size_; ObDMLStmt *root_stmt_; int enable_px_batch_rescan_; + union { + int64_t batch_rescan_flags_; + struct { + int64_t enable_nlj_batch_rescan_ : 1; // enable nestloop inner path batch rescan + int64_t enable_spf_batch_rescan_ : 1; // enable subplan filter batch rescan + int64_t enable_425_batch_rescan_ : 1; // enbale batch rescan behaviors supported in 4.2.5 + }; + }; common::ObSEArray column_usage_infos_; common::ObSEArray temp_table_infos_; bool exchange_allocated_; @@ -761,8 +779,6 @@ private: int64_t optimizer_index_cost_adj_; bool is_skip_scan_enabled_; bool enable_better_inlist_costing_; - bool nlj_batching_enabled_; - bool enable_spf_batch_rescan_; ObEstCorrelationType correlation_type_; bool use_column_store_replica_; bool push_join_pred_into_view_enabled_; diff --git a/src/sql/optimizer/ob_optimizer_util.cpp b/src/sql/optimizer/ob_optimizer_util.cpp index 207170a0e9..05fb6039b6 100644 --- a/src/sql/optimizer/ob_optimizer_util.cpp +++ b/src/sql/optimizer/ob_optimizer_util.cpp @@ -636,14 +636,16 @@ bool ObOptimizerUtil::is_expr_equivalent(const ObRawExpr *from, const ObRawExpr *to, const EqualSets &equal_sets) { - bool found = false; + bool bret = false; + bool l_found = false; + bool r_found = false; bool is_consistent = false; if (OB_ISNULL(from) || OB_ISNULL(to)) { // do nothing } else if (from == to) { - found = true; + bret = true; } else if (!from->is_generalized_column() && from->same_as(*to)) { - found = true; + bret = true; } else if (equal_sets.empty()) { // do nothing } else if (ObRawExprUtils::expr_is_order_consistent(from, to, is_consistent) @@ -651,16 +653,17 @@ bool ObOptimizerUtil::is_expr_equivalent(const ObRawExpr *from, LOG_WARN_RET(OB_ERR_UNEXPECTED, "check expr is order consist ent failed"); } else if (is_consistent) { int64_t N = equal_sets.count(); - for (int64_t i = 0; !found && i < N; ++i) { + for (int64_t i = 0; !l_found && !r_found && i < N; ++i) { if (OB_ISNULL(equal_sets.at(i))) { LOG_WARN_RET(OB_ERR_UNEXPECTED, "get null equal set"); - } else if (find_equal_expr(*equal_sets.at(i), from) && - find_equal_expr(*equal_sets.at(i), to)) { - found = true; + } else { + l_found = find_equal_expr(*equal_sets.at(i), from); + r_found = find_equal_expr(*equal_sets.at(i), to); } } + bret = l_found && r_found; } - return found; + return bret; } bool ObOptimizerUtil::is_exprs_equivalent(const common::ObIArray &from, @@ -4831,15 +4834,13 @@ int ObOptimizerUtil::get_type_safe_join_exprs(const ObIArray &join_ if (OB_SUCC(ret) && OB_NOT_NULL(left_expr) && OB_NOT_NULL(right_expr)) { bool is_right_valid = false; bool is_left_valid = false; - if (OB_FAIL(ObRelationalExprOperator::is_equivalent(left_expr->get_result_type(), - right_expr->get_result_type(), - right_expr->get_result_type(), - is_right_valid))) { + if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive(left_expr->get_result_type(), + right_expr->get_result_type(), + is_right_valid))) { LOG_WARN("failed to check the compare type is the same", K(ret)); - } else if (OB_FAIL(ObRelationalExprOperator::is_equivalent(left_expr->get_result_type(), - left_expr->get_result_type(), - right_expr->get_result_type(), - is_left_valid))) { + } else if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive(left_expr->get_result_type(), + right_expr->get_result_type(), + is_left_valid))) { LOG_WARN("failed to check the compare type is the same", K(ret)); } else if (is_left_valid && OB_FAIL(left_exprs.push_back(left_expr))) { LOG_WARN("failed to add left exprs", K(ret)); @@ -6737,8 +6738,6 @@ int ObOptimizerUtil::get_set_res_types(ObIAllocator *allocator, LOG_WARN("failed to get collation connection", K(ret)); } else { ObExprVersion dummy_op(*allocator); - ObSEArray types; - ObExprResType res_type; ObExprTypeCtx type_ctx; ObSQLUtils::init_type_ctx(session_info, type_ctx); const int64_t child_num = child_querys.count(); @@ -6749,7 +6748,8 @@ int ObOptimizerUtil::get_set_res_types(ObIAllocator *allocator, ObColumnRefRawExpr *col_expr = NULL; ObRawExpr *expr = NULL; for (int64_t idx = 0; OB_SUCC(ret) && idx < select_num; ++idx) { - types.reuse(); + ObSEArray types; + ObExprResType res_type; is_all_not_null = true; res_type.unset_result_flag(NOT_NULL_FLAG); for (int64_t i = 0; OB_SUCC(ret) && i < child_num; ++i) { @@ -6811,6 +6811,104 @@ int ObOptimizerUtil::get_set_res_types(ObIAllocator *allocator, return ret; } +/* +* Oracle has more strict constraints for data types used in set operator +* https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries004.htm +*/ +// need to refine this when more data type are added in oracle mode +int ObOptimizerUtil::check_set_child_res_types(const ObExprResType &left_type, + const ObExprResType &right_type, + const bool is_ps_prepare_stage, + const bool is_distinct, + const bool is_mysql_recursive_union, + bool &skip_add_cast) +{ + int ret = OB_SUCCESS; + const bool is_oracle_mode = lib::is_oracle_mode(); + if (left_type != right_type || ob_is_enumset_tc(right_type.get_type()) || is_mysql_recursive_union) { + if (is_oracle_mode) { + if (!((left_type.is_null() && !right_type.is_lob() && !right_type.is_lob_locator()) + || (left_type.is_null() && (right_type.is_lob() || right_type.is_lob_locator()) && !is_distinct) + || (right_type.is_null() && !left_type.is_lob() && !left_type.is_lob_locator()) + || (right_type.is_null() && (left_type.is_lob() || left_type.is_lob_locator()) && !is_distinct) + || (left_type.is_raw() && right_type.is_raw()) + || (left_type.is_character_type() && right_type.is_character_type()) + || (ob_is_oracle_numeric_type(left_type.get_type()) && ob_is_oracle_numeric_type(right_type.get_type())) + || (ob_is_oracle_temporal_type(left_type.get_type()) && (ob_is_oracle_temporal_type(right_type.get_type()))) + || (left_type.is_urowid() && right_type.is_urowid()) + || (left_type.is_lob() && right_type.is_lob() && left_type.get_collation_type() == right_type.get_collation_type()) + || (left_type.is_geometry() && right_type.is_geometry()) + || (left_type.is_lob_locator() && right_type.is_lob_locator() && left_type.get_collation_type() == right_type.get_collation_type()) + || ((ob_is_user_defined_sql_type(left_type.get_type()) || ob_is_user_defined_pl_type(left_type.get_type())) + && (ob_is_user_defined_sql_type(right_type.get_type()) || ob_is_user_defined_pl_type(right_type.get_type()))))) { + // || (left_type.is_lob() && right_type.is_lob() && !is_distinct))) { + // Originally, cases like "select clob from t union all select blob from t" return errorif (is_ps_prepare_stage) { + if (is_ps_prepare_stage) { + skip_add_cast = true; + LOG_WARN("ps prepare stage expression has different datatype", K(left_type), K(right_type)); + } else { + ret = OB_ERR_EXP_NEED_SAME_DATATYPE; + LOG_WARN("expression must have same datatype as corresponding expression", K(ret), + K(right_type.is_varchar_or_char()), K(left_type), K(right_type)); + } + } else if (left_type.is_character_type() && + right_type.is_character_type() && + (left_type.is_varchar_or_char() != right_type.is_varchar_or_char())) { + ret = OB_ERR_CHARACTER_SET_MISMATCH; + LOG_WARN("character set mismatch", K(ret), K(left_type), K(right_type)); + } else if (left_type.is_string_or_lob_locator_type() && + right_type.is_string_or_lob_locator_type()) { + ObCharsetType left_cs = left_type.get_charset_type(); + ObCharsetType right_cs = right_type.get_charset_type(); + if (left_cs != right_cs) { + if (CHARSET_UTF8MB4 == left_cs || CHARSET_UTF8MB4 == right_cs) { + //sys table column exist utf8 varchar types, let it go + } else { + ret = OB_ERR_COLLATION_MISMATCH; //ORA-12704 + LOG_WARN("character set mismatch", K(ret), K(left_cs), K(right_cs)); + } + } + } else if (is_distinct && (right_type.is_geometry() || left_type.is_geometry())) { + ret = OB_ERR_COMPARE_VARRAY_LOB_ATTR; + LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); + } + } + if (OB_SUCC(ret) && is_mysql_recursive_union && left_type.is_null()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected rcte type", K(ret), K(left_type)); + } + if (OB_SUCC(ret) && !skip_add_cast && !is_ps_prepare_stage) { + if ((left_type.is_ext() && !right_type.is_ext()) || + (!left_type.is_ext() && right_type.is_ext()) || + (left_type.is_ext() && right_type.is_ext() && left_type.get_udt_id() != right_type.get_udt_id())) { + ret = OB_ERR_EXP_NEED_SAME_DATATYPE; + LOG_WARN("expression must have same datatype as corresponding expression", K(ret), + K(left_type), K(right_type)); + } + } + } else { + if (is_oracle_mode) { + if (is_distinct && (left_type.is_lob() || left_type.is_lob_locator())) { + ret = OB_ERR_INVALID_TYPE_FOR_OP; + LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); + } else if (is_distinct && right_type.is_json()) { + ret = OB_ERR_INVALID_CMP_OP; + LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); + } else if (is_distinct && right_type.is_geometry()) { + ret = OB_ERR_COMPARE_VARRAY_LOB_ATTR; + LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); + } + } + + if (OB_SUCC(ret) && + is_distinct && (left_type.is_roaringbitmap() || right_type.is_roaringbitmap())) { + ret = OB_ERR_INVALID_TYPE_FOR_OP; + LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); + } + } + return ret; +} + int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, @@ -6822,9 +6920,9 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, ObIArray *rcte_col_name /* null */) { int ret = OB_SUCCESS; - ObExprResType res_type; ObSEArray left_types; ObSEArray right_types; + ObCollationType coll_type = CS_TYPE_INVALID; if (OB_ISNULL(allocator) || OB_ISNULL(session_info) || OB_ISNULL(expr_factory)) { ret = OB_NOT_INIT; LOG_WARN("params is invalid", K(ret)); @@ -6838,144 +6936,56 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, ret = OB_ERR_COLUMN_SIZE; LOG_WARN("The used SELECT statements have a different number of columns", K(left_types.count()), K(right_types.count())); + } else if (OB_FAIL(session_info->get_collation_connection(coll_type))) { + LOG_WARN("failed to get collation connection", K(ret)); } else { if (NULL != res_types) { res_types->reuse(); } + const ObLengthSemantics length_semantics = session_info->get_actual_nls_length_semantics(); + const bool is_ps_prepare_stage = session_info->is_varparams_sql_prepare(); const int64_t num = left_types.count(); + const bool is_oracle_mode = lib::is_oracle_mode(); ObExprTypeCtx type_ctx; ObSQLUtils::init_type_ctx(session_info, type_ctx); for (int64_t i = 0; OB_SUCC(ret) && i < num; i++) { - res_type.reset(); + ObExprResType res_type; ObExprResType &left_type = left_types.at(i); ObExprResType &right_type = right_types.at(i); + bool skip_add_cast = false; if (!left_type.has_result_flag(NOT_NULL_FLAG) || !right_type.has_result_flag(NOT_NULL_FLAG)) { left_type.unset_result_flag(NOT_NULL_FLAG); right_type.unset_result_flag(NOT_NULL_FLAG); } - if (left_type != right_type || ob_is_enumset_tc(right_type.get_type()) || is_mysql_recursive_union) { + if (OB_FAIL(check_set_child_res_types(left_type, right_type, is_ps_prepare_stage, is_distinct, + is_mysql_recursive_union, skip_add_cast))) { + LOG_WARN("failed to check set child res types", K(ret)); + } else if (left_type != right_type || ob_is_enumset_tc(right_type.get_type()) || is_mysql_recursive_union) { ObSEArray types; ObExprVersion dummy_op(*allocator); - ObCollationType coll_type = CS_TYPE_INVALID; - bool skip_add_cast = false; - if (lib::is_oracle_mode()) { - /* - * Oracle has more strict constraints for data types used in set operator - * https://docs.oracle.com/cd/B19306_01/server.102/b14200/queries004.htm - */ - // need to refine this when more data type are added in oracle mode - if (!((left_type.is_null() && !right_type.is_lob() && !right_type.is_lob_locator()) - || (left_type.is_null() && (right_type.is_lob() || right_type.is_lob_locator()) && !is_distinct) - || (right_type.is_null() && !left_type.is_lob() && !left_type.is_lob_locator()) - || (right_type.is_null() && (left_type.is_lob() || left_type.is_lob_locator()) && !is_distinct) - || (left_type.is_raw() && right_type.is_raw()) - || (left_type.is_character_type() && right_type.is_character_type()) - || (ob_is_oracle_numeric_type(left_type.get_type()) - && ob_is_oracle_numeric_type(right_type.get_type())) - || (ob_is_oracle_temporal_type(left_type.get_type()) - && (ob_is_oracle_temporal_type(right_type.get_type()))) - || (left_type.is_urowid() && right_type.is_urowid()) - || (is_oracle_mode() && left_type.is_lob() && right_type.is_lob() && left_type.get_collation_type() == right_type.get_collation_type()) - || (is_oracle_mode() && left_type.is_geometry() && right_type.is_geometry()) - || (is_oracle_mode() && left_type.is_lob_locator() && right_type.is_lob_locator() && left_type.get_collation_type() == right_type.get_collation_type()) - || (is_oracle_mode() && (ob_is_user_defined_sql_type(left_type.get_type()) || ob_is_user_defined_pl_type(left_type.get_type())) - && (ob_is_user_defined_sql_type(right_type.get_type()) || ob_is_user_defined_pl_type(right_type.get_type()))))) { - // || (left_type.is_lob() && right_type.is_lob() && !is_distinct))) { - // Originally, cases like "select clob from t union all select blob from t" return error - if (session_info->is_varparams_sql_prepare()) { - skip_add_cast = true; - LOG_WARN("ps prepare stage expression has different datatype", K(i), K(left_type), K(right_type)); - } else { - ret = OB_ERR_EXP_NEED_SAME_DATATYPE; - LOG_WARN("expression must have same datatype as corresponding expression", K(ret), - K(session_info->is_varparams_sql_prepare()), K(right_type.is_varchar_or_char()), - K(i), K(left_type), K(right_type)); - } - } else if (left_type.is_character_type() - && right_type.is_character_type() - && (left_type.is_varchar_or_char() != right_type.is_varchar_or_char())) { - ret = OB_ERR_CHARACTER_SET_MISMATCH; - LOG_WARN("character set mismatch", K(ret), K(left_type), K(right_type)); - } else if (left_type.is_string_or_lob_locator_type() && - right_type.is_string_or_lob_locator_type()) { - ObCharsetType left_cs = left_type.get_charset_type(); - ObCharsetType right_cs = right_type.get_charset_type(); - if (left_cs != right_cs) { - if (CHARSET_UTF8MB4 == left_cs || CHARSET_UTF8MB4 == right_cs) { - //sys table column exist utf8 varchar types, let it go - } else { - ret = OB_ERR_COLLATION_MISMATCH; //ORA-12704 - LOG_WARN("character set mismatch", K(ret), K(left_cs), K(right_cs)); - } - } - } else if (lib::is_oracle_mode() && is_distinct - && (right_type.is_geometry() || left_type.is_geometry())) { - ret = OB_ERR_COMPARE_VARRAY_LOB_ATTR; - LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); - } - LOG_DEBUG("data type check for each select item in set operator", K(left_type), - K(right_type)); - } - const ObLengthSemantics length_semantics = session_info->get_actual_nls_length_semantics(); - if (OB_FAIL(ret)) { - } else if (is_mysql_recursive_union) { - if (left_type.is_null()) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected rcte type", K(ret), K(left_stmts)); - } else { - res_type = left_type; - } - } else if (skip_add_cast) { + if (skip_add_cast || is_mysql_recursive_union) { res_type = left_type; } else if (OB_FAIL(types.push_back(left_type)) || OB_FAIL(types.push_back(right_type))) { LOG_WARN("failed to push back", K(ret)); - } else if (OB_FAIL(session_info->get_collation_connection(coll_type))) { - LOG_WARN("failed to get collation connection", K(ret)); } else if (OB_FAIL(dummy_op.aggregate_result_type_for_merge(res_type, &types.at(0), 2, - is_oracle_mode(), type_ctx))) { - if (session_info->is_varparams_sql_prepare()) { - skip_add_cast = true; - res_type = left_type; - LOG_WARN("failed to deduce type in ps prepare stage", K(types)); - } else { - LOG_WARN("failed to aggregate result type for merge", K(ret)); - } + is_oracle_mode, type_ctx))) { + LOG_WARN("failed to aggregate result type for merge", K(ret)); } if (OB_FAIL(ret) || skip_add_cast) { - } else if (ObMaxType == res_type.get_type()) { + } else if (OB_UNLIKELY(ObMaxType == res_type.get_type())) { ret = OB_ERR_INVALID_TYPE_FOR_OP; LOG_WARN("column type incompatible", K(left_type), K(right_type)); - } else if ((left_type.is_ext() && !right_type.is_ext()) - || (!left_type.is_ext() && right_type.is_ext()) - || (left_type.is_ext() && right_type.is_ext() - && left_type.get_udt_id() != right_type.get_udt_id())) { - ret = OB_ERR_EXP_NEED_SAME_DATATYPE; - LOG_WARN("expression must have same datatype as corresponding expression", K(ret), K(left_type), K(right_type)); - } else if (left_type != res_type && OB_FAIL(add_cast_to_set_list(session_info, - expr_factory, left_stmts, res_type, i))) { + } else if (left_type != res_type && + OB_FAIL(add_cast_to_set_list(session_info, expr_factory, left_stmts, res_type, i))) { LOG_WARN("failed to add add cast to set list", K(ret)); - } else if (!is_mysql_recursive_union && - right_type != res_type && OB_FAIL(add_cast_to_set_list(session_info, - expr_factory, right_stmts, res_type, i))) { + } else if (!is_mysql_recursive_union && right_type != res_type && + OB_FAIL(add_cast_to_set_list(session_info, expr_factory, right_stmts, res_type, i))) { LOG_WARN("failed to add add cast to set list", K(ret)); } else if (is_mysql_recursive_union && OB_FAIL(add_column_conv_to_set_list(session_info, expr_factory, right_stmts, res_type, i, rcte_col_name))) { LOG_WARN("failed to add column_conv to set list", K(ret)); } - } else if (lib::is_oracle_mode() && is_distinct && - (left_type.is_lob() || left_type.is_lob_locator())) { - ret = OB_ERR_INVALID_TYPE_FOR_OP; - LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); - } else if (lib::is_oracle_mode() && is_distinct && right_type.is_json()) { - ret = OB_ERR_INVALID_CMP_OP; - LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); - } else if (lib::is_oracle_mode() && is_distinct && right_type.is_geometry()) { - ret = OB_ERR_COMPARE_VARRAY_LOB_ATTR; - LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); - } else if (is_distinct && (left_type.is_roaringbitmap() || right_type.is_roaringbitmap())) { - ret = OB_ERR_INVALID_TYPE_FOR_OP; - LOG_WARN("column type incompatible", K(ret), K(left_type), K(right_type)); } else { res_type = left_type; } @@ -6987,6 +6997,28 @@ int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, return ret; } +int ObOptimizerUtil::try_add_cast_to_set_child_list(ObIAllocator *allocator, + ObSQLSessionInfo *session_info, + ObRawExprFactory *expr_factory, + const bool is_distinct, + ObIArray &left_stmts, + ObSelectStmt *right_stmt, + ObIArray *res_types, + const bool is_mysql_recursive_union /* false */, + ObIArray *rcte_col_name /* null */) +{ + int ret = OB_SUCCESS; + ObSEArray child_stmts; + if (OB_FAIL(child_stmts.push_back(right_stmt))) { + LOG_WARN("failed to push back right_stmt", K(ret)); + } else if (OB_FAIL(try_add_cast_to_set_child_list(allocator, session_info, expr_factory, + is_distinct, left_stmts, child_stmts, res_types, + is_mysql_recursive_union, rcte_col_name))) { + LOG_WARN("failed to add cast to set child list", K(ret)); + } + return ret; +} + int ObOptimizerUtil::add_cast_to_set_list(ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, ObIArray &stmts, @@ -7007,37 +7039,81 @@ int ObOptimizerUtil::add_cast_to_set_list(ObSQLSessionInfo *session_info, || OB_ISNULL(src_expr = stmt->get_select_item(idx).expr_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected stmt", K(ret), K(stmts.at(i))); - } else if (ob_is_enumset_tc(src_expr->get_result_type().get_type()) + } else if (OB_FAIL(add_cast_to_set_select_expr(session_info, *expr_factory, res_type, + stmt->get_select_item(idx).expr_))) { + LOG_WARN("failed to add cast to expr"); + } + } + return ret; +} + +int ObOptimizerUtil::add_cast_to_set_list(ObSQLSessionInfo *session_info, + ObRawExprFactory *expr_factory, + ObIArray &exprs, + const ObExprResType &res_type, + const int64_t column_idx, + const int64_t row_cnt) +{ + int ret = OB_SUCCESS; + ObRawExpr *src_expr = NULL; + ObRawExpr *new_expr = NULL; + int64_t column_cnt = 0; + if (OB_ISNULL(session_info) || OB_ISNULL(expr_factory) || + OB_UNLIKELY(exprs.empty() || row_cnt <= 0 || column_idx < 0 || exprs.count() % row_cnt != 0 || + exprs.count() / row_cnt <= column_idx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected param", K(ret)); + } else { + column_cnt = exprs.count() / row_cnt; + } + for (int64_t i = 0; OB_SUCC(ret) && i < row_cnt; ++i) { + if (OB_ISNULL(exprs.at(column_idx + column_cnt * i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected expr", K(ret)); + } else if (OB_FAIL(add_cast_to_set_select_expr(session_info, *expr_factory, res_type, + exprs.at(column_idx + column_cnt * i)))) { + LOG_WARN("failed to add cast to expr"); + } + } + return ret; +} + +/* add cast to a select_expr of set child */ +int ObOptimizerUtil::add_cast_to_set_select_expr(ObSQLSessionInfo *session_info, + ObRawExprFactory &expr_factory, + const ObExprResType &res_type, + ObRawExpr *&src_expr) +{ + int ret = OB_SUCCESS; + ObRawExpr *new_expr = NULL; + if (OB_ISNULL(src_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected select expr", K(ret)); + } else if (ob_is_enumset_tc(src_expr->get_result_type().get_type()) && !src_expr->is_enum_set_with_subschema()) { - ObSysFunRawExpr *to_str_expr = NULL; - if (src_expr->get_result_type() == res_type) { - /*do nothing*/ - } else if (OB_FAIL(ObRawExprUtils::create_type_to_str_expr(*expr_factory, - src_expr, - to_str_expr, - session_info, - true))) { - LOG_WARN("create to str expr for stmt failed", K(ret)); - } else if (OB_FAIL(ObRawExprUtils::try_add_cast_expr_above(expr_factory, session_info, - *to_str_expr, res_type, - new_expr))) { - LOG_WARN("create cast expr for stmt failed", K(ret)); - } else if (OB_FAIL(new_expr->add_flag(IS_INNER_ADDED_EXPR))) { - LOG_WARN("failed to add flag", K(ret)); - } else { - stmt->get_select_item(idx).expr_ = new_expr; - } - } else if (OB_FAIL(ObRawExprUtils::try_add_cast_expr_above(expr_factory, session_info, - *src_expr, res_type, - new_expr))) { - LOG_WARN("create cast expr for stmt failed", K(ret)); - } else if (src_expr == new_expr) { + ObSysFunRawExpr *to_str_expr = NULL; + if (src_expr->get_result_type() == res_type) { /*do nothing*/ + } else if (OB_FAIL(ObRawExprUtils::create_type_to_str_expr(expr_factory, src_expr, to_str_expr, + session_info, true))) { + LOG_WARN("create to str expr for stmt failed", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::try_add_cast_expr_above(&expr_factory, session_info, + *to_str_expr, res_type, new_expr))) { + LOG_WARN("create cast expr for stmt failed", K(ret)); } else if (OB_FAIL(new_expr->add_flag(IS_INNER_ADDED_EXPR))) { LOG_WARN("failed to add flag", K(ret)); } else { - stmt->get_select_item(idx).expr_ = new_expr; + src_expr = new_expr; } + } else if (OB_FAIL(ObRawExprUtils::try_add_cast_expr_above(&expr_factory, session_info, + *src_expr, res_type, new_expr))) { + LOG_WARN("create cast expr for stmt failed", K(ret)); + } else if (src_expr == new_expr) { + /*do nothing*/ + } else if (OB_FAIL(new_expr->add_flag(IS_INNER_ADDED_EXPR))) { + LOG_WARN("failed to add flag", K(ret)); + } else { + src_expr = new_expr; } return ret; } @@ -7078,6 +7154,94 @@ int ObOptimizerUtil::add_column_conv_to_set_list(ObSQLSessionInfo *session_info, return ret; } +int ObOptimizerUtil::try_add_cast_to_select_list(ObIAllocator *allocator, + ObSQLSessionInfo *session_info, + ObRawExprFactory *expr_factory, + const int64_t column_cnt, + const bool is_distinct, + ObIArray &select_exprs, + ObIArray *res_types) +{ + int ret = OB_SUCCESS; + ObCollationType coll_type = CS_TYPE_INVALID; + if (OB_ISNULL(allocator) || OB_ISNULL(session_info) || OB_ISNULL(expr_factory)) { + ret = OB_NOT_INIT; + LOG_WARN("params is invalid", K(ret)); + } else if (OB_UNLIKELY(column_cnt == 0) || OB_UNLIKELY(select_exprs.empty())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("empty select exprs", K(ret)); + } else if (OB_UNLIKELY(select_exprs.count() % column_cnt != 0)) { + ret = OB_ERR_COLUMN_SIZE; + LOG_WARN("The used SELECT statements have a different number of columns", K(column_cnt)); + } else if (OB_FAIL(session_info->get_collation_connection(coll_type))) { + LOG_WARN("failed to get collation connection", K(ret)); + } else { + if (NULL != res_types) { + res_types->reuse(); + } + const ObLengthSemantics length_semantics = session_info->get_actual_nls_length_semantics(); + const bool is_ps_prepare_stage = session_info->is_varparams_sql_prepare(); + const bool is_oracle_mode = lib::is_oracle_mode(); + const int64_t row_cnt = select_exprs.count() / column_cnt; + ObExprTypeCtx type_ctx; + ObSQLUtils::init_type_ctx(session_info, type_ctx); + ObRawExpr *expr = NULL; + for (int64_t i = 0; OB_SUCC(ret) && i < column_cnt; i++) { + ObExprResType result_type; + /* 1. column type decude */ + if (OB_ISNULL(expr = select_exprs.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("empty select exprs", K(ret), K(i)); + } else { + result_type = expr->get_result_type(); + } + for (int64_t j = 1; OB_SUCC(ret) && j < row_cnt; j++) { + ObExprResType left_type = result_type; + bool skip_add_cast = false; + if (OB_ISNULL(expr = select_exprs.at(i + j * column_cnt))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("empty select exprs", K(ret), K(i), K(j)); + } else { + const ObExprResType &right_type = expr->get_result_type(); + if (left_type != right_type || ob_is_enumset_tc(right_type.get_type())) { + ObSEArray types; + ObExprVersion dummy_op(*allocator); + if (OB_FAIL(check_set_child_res_types(left_type, right_type, is_ps_prepare_stage, + is_distinct, false, skip_add_cast))) { + LOG_WARN("failed to check set child res types", K(ret)); + } else if (skip_add_cast) { + /* left_type is res_type */ + } else if (OB_FAIL(types.push_back(left_type)) || OB_FAIL(types.push_back(right_type))) { + LOG_WARN("failed to push back", K(ret)); + } else if (OB_FAIL(dummy_op.aggregate_result_type_for_merge(result_type, &types.at(0), 2, + is_oracle_mode, type_ctx))) { + LOG_WARN("failed to aggregate result type for merge", K(ret)); + } else if (OB_UNLIKELY(ObMaxType == result_type.get_type())) { + ret = OB_ERR_INVALID_TYPE_FOR_OP; + LOG_WARN("column type incompatible", K(ret), K(result_type)); + } else if (left_type != result_type && + OB_FAIL(add_cast_to_set_list(session_info, expr_factory, select_exprs, result_type, i, row_cnt))) { + LOG_WARN("failed to add add cast to set list", K(ret)); + } else if (right_type != result_type && + OB_FAIL(add_cast_to_set_list(session_info, expr_factory, select_exprs, result_type, i, row_cnt))) { + LOG_WARN("failed to add add cast to set list", K(ret)); + } + } + } + } // end for row + /* 2. add cast*/ + if (OB_SUCC(ret)) { + // const set query doesn't use not null flag + result_type.unset_result_flag(NOT_NULL_FLAG); + if (NULL != res_types && OB_FAIL(res_types->push_back(result_type))) { + LOG_WARN("failed to push back res type", K(ret)); + } + } + } // end for column + } + return ret; +} + /** * check_subquery_has_ref_assign_user_var * 检查expr的子查询中是否包含涉及到赋值操作的用户变量 @@ -8513,29 +8677,31 @@ ObPQDistributeMethod::Type ObOptimizerUtil::get_right_dist_method(const ObShardi int ObOptimizerUtil::generate_pullup_aggr_expr(ObRawExprFactory &expr_factory, ObSQLSessionInfo *session_info, - ObAggFunRawExpr *origin_expr, + ObItemType aggr_type, + ObRawExpr *origin_expr, ObAggFunRawExpr *&pullup_aggr) { int ret = OB_SUCCESS; + ObAggFunRawExpr *origin_aggr = NULL; pullup_aggr = NULL; if (OB_ISNULL(origin_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(origin_expr)); - } else if (T_FUN_MAX == origin_expr->get_expr_type() || - T_FUN_MIN == origin_expr->get_expr_type() || - T_FUN_SUM == origin_expr->get_expr_type() || - T_FUN_COUNT == origin_expr->get_expr_type() || - T_FUN_COUNT_SUM == origin_expr->get_expr_type() || - T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS == origin_expr->get_expr_type() || - T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS_MERGE == origin_expr->get_expr_type() || - T_FUN_SYS_BIT_AND == origin_expr->get_expr_type() || - T_FUN_SYS_BIT_OR == origin_expr->get_expr_type() || - T_FUN_SYS_BIT_XOR == origin_expr->get_expr_type() || - T_FUN_SUM_OPNSIZE == origin_expr->get_expr_type() || + } else if (T_FUN_MAX == aggr_type || + T_FUN_MIN == aggr_type || + T_FUN_SUM == aggr_type || + T_FUN_COUNT == aggr_type || + T_FUN_COUNT_SUM == aggr_type || + T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS == aggr_type || + T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS_MERGE == aggr_type || + T_FUN_SYS_BIT_AND == aggr_type || + T_FUN_SYS_BIT_OR == aggr_type || + T_FUN_SYS_BIT_XOR == aggr_type || + T_FUN_SUM_OPNSIZE == aggr_type || T_FUN_SYS_RB_OR_AGG == origin_expr->get_expr_type() || T_FUN_SYS_RB_BUILD_AGG == origin_expr->get_expr_type()) { /* MAX(a) -> MAX(MAX(a)), MIN(a) -> MIN(MIN(a)) SUM(a) -> SUM(SUM(a)) */ - ObItemType pullup_aggr_type = origin_expr->get_expr_type(); + ObItemType pullup_aggr_type = aggr_type; if (T_FUN_COUNT == pullup_aggr_type || T_FUN_SUM_OPNSIZE == pullup_aggr_type) { pullup_aggr_type = T_FUN_COUNT_SUM; } else if (T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS == pullup_aggr_type) { @@ -8551,9 +8717,13 @@ int ObOptimizerUtil::generate_pullup_aggr_expr(ObRawExprFactory &expr_factory, pullup_aggr))) { LOG_WARN("failed to build common aggr expr", K(ret)); } - } else if (T_FUN_GROUPING == origin_expr->get_expr_type() && - origin_expr->get_real_param_count() == 1) { - ObRawExpr *param_expr = origin_expr->get_real_param_exprs_for_update().at(0); + } else if (OB_UNLIKELY(!origin_expr->is_aggr_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected aggr type", K(ret), KPC(origin_expr)); + } else if (OB_FALSE_IT(origin_aggr = static_cast(origin_expr))) { + } else if (T_FUN_GROUPING == aggr_type && + origin_aggr->get_real_param_count() == 1) { + ObRawExpr *param_expr = origin_aggr->get_real_param_exprs_for_update().at(0); if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(expr_factory, session_info, T_FUN_GROUPING, @@ -8561,23 +8731,23 @@ int ObOptimizerUtil::generate_pullup_aggr_expr(ObRawExprFactory &expr_factory, pullup_aggr))) { LOG_WARN("failed to pullup grouping aggr expr", K(ret)); } - } else if (T_FUN_TOP_FRE_HIST == origin_expr->get_expr_type()) { - if (OB_UNLIKELY(4 != origin_expr->get_real_param_count())) { + } else if (T_FUN_TOP_FRE_HIST == aggr_type) { + if (OB_UNLIKELY(4 != origin_aggr->get_real_param_count())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("real param count is invalid", K(ret)); } else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_TOP_FRE_HIST, pullup_aggr))) { LOG_WARN("failed to create top frequency expr", K(ret)); } else if (OB_FAIL(pullup_aggr->add_real_param_expr( - origin_expr->get_real_param_exprs_for_update().at(0)))) { + origin_aggr->get_real_param_exprs_for_update().at(0)))) { LOG_WARN("failed to add real param expr", K(ret)); } else if (OB_FAIL(pullup_aggr->add_real_param_expr( - origin_expr))) { + origin_aggr))) { LOG_WARN("failed to add real param expr", K(ret)); } else if (OB_FAIL(pullup_aggr->add_real_param_expr( - origin_expr->get_real_param_exprs_for_update().at(2)))) { + origin_aggr->get_real_param_exprs_for_update().at(2)))) { LOG_WARN("failed to add real param expr", K(ret)); } else if (OB_FAIL(pullup_aggr->add_real_param_expr( - origin_expr->get_real_param_exprs_for_update().at(3)))) { + origin_aggr->get_real_param_exprs_for_update().at(3)))) { LOG_WARN("failed to add real param expr", K(ret)); } else if (FALSE_IT(pullup_aggr->set_is_need_deserialize_row(true))) { // do nothing @@ -8586,7 +8756,7 @@ int ObOptimizerUtil::generate_pullup_aggr_expr(ObRawExprFactory &expr_factory, } } else { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected aggr type", K(ret), K(*origin_expr)); + LOG_WARN("get unexpected aggr type", K(ret), KPC(origin_expr)); } return ret; } @@ -8764,62 +8934,24 @@ int ObOptimizerUtil::allocate_identify_seq_expr(ObOptimizerContext &opt_ctx, ObR return ret; } -int ObOptimizerUtil::check_contribute_query_range(ObLogicalOperator *root, - const ObIArray ¶ms, - bool &is_valid) +int ObOptimizerUtil::check_exec_param_filter_exprs(const ObIArray &filters, + const ObIArray &exec_params, + bool &used_in_filter) { int ret = OB_SUCCESS; - is_valid = false; - ObSEArray range_exprs; - ObSEArray all_table_filters; - ObSEArray range_params; - ObSEArray pushdown_params; - ObSEArray exec_params; - if (OB_ISNULL(root)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid root", K(ret)); - } else if (params.empty()) { - // do nothing - } else if (OB_FAIL(append(exec_params, params))) { - LOG_WARN("failed to append nl params", K(ret)); - } else if (OB_FAIL(ObOptimizerUtil::get_range_params(root, range_exprs, all_table_filters))) { - LOG_WARN("failed to get range_exprs", K(ret)); - } else if (OB_FAIL(ObRawExprUtils::extract_params(range_exprs, range_params))) { - LOG_WARN("failed to extract range params", K(ret)); - } else if (OB_FAIL(ObOptimizerUtil::intersect(exec_params, range_params, pushdown_params))) { - LOG_WARN("failed to get intersect params", K(ret)); - } else if (pushdown_params.empty()) { - // do nothing - } else { - is_valid = true; - LOG_TRACE("pushdown filters can extend query range", K(pushdown_params)); - } - return ret; -} - -int ObOptimizerUtil::check_pushdown_range_cond(ObLogicalOperator *root, - bool &cnt_pd_range_cond) -{ - int ret = OB_SUCCESS; - cnt_pd_range_cond = false; - if (OB_ISNULL(root)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid root", K(ret)); - } else if (root->is_table_scan()) { - ObLogTableScan *tsc = static_cast(root); - if (OB_FAIL(check_exec_param_filter_exprs(tsc->get_range_conditions(), - cnt_pd_range_cond))) { - LOG_WARN("failed to check exec param filter", K(ret)); - } else {/*do nothing*/} - } else { - for (int64_t i = 0; OB_SUCC(ret) && !cnt_pd_range_cond && i < root->get_num_of_child(); ++i) { - ObLogicalOperator *child = root->get_child(i); - if (OB_ISNULL(child)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("invalid child", K(ret)); - } else if (OB_FAIL(SMART_CALL(check_pushdown_range_cond(child, cnt_pd_range_cond)))) { - LOG_WARN("failed to check pd range cond", K(ret)); - } else {/*do nothing*/} + used_in_filter = false; + if (!filters.empty() && !exec_params.empty()) { + ObSEArray tmp_exec_params; + ObSEArray filter_params; + ObSEArray used_params; + if (OB_FAIL(append(tmp_exec_params, exec_params))) { + LOG_WARN("failed to append nl params", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::extract_params(filters, filter_params))) { + LOG_WARN("failed to extract range params", K(ret)); + } else if (OB_FAIL(intersect(tmp_exec_params, filter_params, used_params))) { + LOG_WARN("failed to get intersect params", K(ret)); + } else { + used_in_filter = !used_params.empty(); } } return ret; @@ -9942,31 +10074,6 @@ int ObOptimizerUtil::check_contain_my_exec_param(const ObIArray &ex return ret; } -int ObOptimizerUtil::check_ancestor_node_support_skip_scan(ObLogicalOperator* op, bool &can_use_batch_nlj) -{ - int ret = OB_SUCCESS; - ObLogicalOperator* parent = nullptr; - if (OB_ISNULL(op)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("Current operator node is null", K(ret)); - } else if (OB_ISNULL(parent = op->get_parent())) { - // do nothing - } else if (can_use_batch_nlj) { - if (parent->get_type() == log_op_def::LOG_SUBPLAN_FILTER) { - can_use_batch_nlj = false; - } else if (parent->get_type() == log_op_def::LOG_JOIN) { - ObLogJoin *join = static_cast(parent); - if (IS_SEMI_ANTI_JOIN(join->get_join_type())) { - can_use_batch_nlj = false; - } - } - if (can_use_batch_nlj && OB_FAIL(SMART_CALL(check_ancestor_node_support_skip_scan(parent, can_use_batch_nlj)))) { - LOG_WARN("failed to check parent node can use batch NLJ", K(ret)); - } - } - return ret; -} - int ObOptimizerUtil::try_split_or_qual(const ObDMLStmt *stmt, ObRawExprFactory &expr_factory, const ObSQLSessionInfo *session_info, @@ -10097,6 +10204,170 @@ int ObOptimizerUtil::is_joined_table_filter(const ObDMLStmt *stmt, return ret; } +int ObOptimizerUtil::get_has_global_index_filters(const ObSqlSchemaGuard *schema_guard, + const uint64_t index_id, + const ObIArray &filter_exprs, + bool &has_index_scan_filter, + bool &has_index_lookup_filter) +{ + int ret = OB_SUCCESS; + has_index_scan_filter = false; + has_index_lookup_filter = false; + const ObTableSchema* index_schema = NULL; + ObSEArray index_columns; + if (OB_ISNULL(schema_guard)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("get unexpected null", K(ret), K(schema_guard)); + } else if (OB_FAIL(schema_guard->get_table_schema(index_id, index_schema))) { + LOG_WARN("failed to get table schema", K(ret)); + } else if (OB_ISNULL(index_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("null table schema", K(ret)); + } else if (OB_FAIL(index_schema->get_column_ids(index_columns))) { + LOG_WARN("failed to get index schema", K(ret)); + } else if (OB_FAIL(get_has_global_index_filters(filter_exprs, + index_columns, + has_index_scan_filter, + has_index_lookup_filter))) { + LOG_WARN("failed to get has global index filters", K(ret)); + } + return ret; +} + +int ObOptimizerUtil::get_has_global_index_filters(const ObIArray &filter_exprs, + const ObIArray &index_columns, + bool &has_index_scan_filter, + bool &has_index_lookup_filter) +{ + int ret = OB_SUCCESS; + has_index_scan_filter = false; + has_index_lookup_filter = false; + ObSEArray filter_before_index_back; + if (OB_FAIL(ObOptimizerUtil::check_filter_before_indexback(filter_exprs, + index_columns, + filter_before_index_back))) { + LOG_WARN("Failed to check filter before index back", K(ret)); + } else if (OB_UNLIKELY(filter_before_index_back.count() != filter_exprs.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unequal array size", K(filter_before_index_back.count()), + K(filter_exprs.count()), K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < filter_before_index_back.count(); i++) { + if (OB_ISNULL(filter_exprs.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("null expr", K(ret)); + } else if (filter_before_index_back.at(i) && + !filter_exprs.at(i)->has_flag(CNT_SUB_QUERY)) { + has_index_scan_filter = true; + } else { + has_index_lookup_filter = true; + } + } + } + return ret; +} + +// check batch rescan for nlj / subplan filter +int ObOptimizerUtil::check_can_batch_rescan(const ObLogicalOperator *op, + const bool allow_normal_scan, + bool &can_batch_rescan) +{ + int ret = OB_SUCCESS; + can_batch_rescan = false; + if (OB_ISNULL(op)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(op)); + } else if (op->is_table_scan()) { + const ObLogTableScan *table_scan = static_cast(op); + can_batch_rescan = (allow_normal_scan || table_scan->use_das()) && table_scan->can_batch_rescan(); + } else if (1 == op->get_num_of_child() || log_op_def::LOG_SET == op->get_type()) { + can_batch_rescan = true; + for (int64_t i = 0; OB_SUCC(ret) && can_batch_rescan && i < op->get_num_of_child(); ++i) { + if (OB_FAIL(SMART_CALL(check_can_batch_rescan(op->get_child(i), false, can_batch_rescan)))) { + LOG_WARN("failed to check batch nlj", K(ret)); + } + } + } else { // other multi child op use batch is disabled, multi level nlj use batch is disabled + can_batch_rescan = false; + } + return ret; +} + +// check batch rescan for nlj / subplan filter +// check_can_batch_rescan compatible before 425 +int ObOptimizerUtil::check_can_batch_rescan_compat(ObLogicalOperator *op, + const ObIArray &rescan_params, + bool for_nlj, + bool &can_batch_rescan) +{ + int ret = OB_SUCCESS; + can_batch_rescan = false; + bool has_exec_param = false; + if (OB_ISNULL(op)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(op)); + } else if (OB_FAIL(check_exec_param_filter_exprs(op->get_startup_exprs(), has_exec_param))) { + LOG_WARN("failed to check exec param filter exprs", K(ret)); + } else if (has_exec_param) { + /* do nothing */ + } else if (log_op_def::LOG_LIMIT == op->get_type() + || (op->is_table_scan() && NULL != static_cast(op)->get_limit_expr())) { + /* do nothing */ + } else if (op->is_table_scan()) { + const ObLogTableScan *table_scan = static_cast(op); + if (!table_scan->use_das() || !table_scan->can_batch_rescan() + || table_scan->get_range_conditions().empty() || NULL == table_scan->get_est_cost_info()) { + can_batch_rescan = false; + } else if (OB_FAIL(check_exec_param_filter_exprs(table_scan->get_est_cost_info()->pushdown_prefix_filters_, + rescan_params, + can_batch_rescan))) { + LOG_WARN("failed to check exec param filter exprs", K(ret)); + } + } else if (log_op_def::LOG_SUBPLAN_SCAN == op->get_type()) { + if (OB_FAIL(SMART_CALL(check_can_batch_rescan_compat(op->get_child(0), rescan_params, for_nlj, can_batch_rescan)))) { + LOG_WARN("failed to smart call check check op can batch", K(ret)); + } + } else if (!for_nlj) { + /* do nothing */ + } else if (1 == op->get_num_of_child() || log_op_def::LOG_SET == op->get_type()) { + can_batch_rescan = true; + for (int64_t i = 0; OB_SUCC(ret) && can_batch_rescan && i < op->get_num_of_child(); ++i) { + if (OB_FAIL(SMART_CALL(check_can_batch_rescan_compat(op->get_child(i), rescan_params, for_nlj, can_batch_rescan)))) { + LOG_WARN("failed to check batch nlj", K(ret)); + } else {/* do nothing */} + } + } else { + // other multi child op use batch is disabled + // multi level nlj use batch is disabled + can_batch_rescan = false; + } + return ret; +} + +int ObOptimizerUtil::check_aggr_can_pre_aggregate(const ObAggFunRawExpr *aggr, + bool &can_pre_aggr) +{ + int ret = OB_SUCCESS; + can_pre_aggr = false; + if (OB_ISNULL(aggr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (T_FUN_MAX == aggr->get_expr_type() || + T_FUN_MIN == aggr->get_expr_type() || + T_FUN_SUM == aggr->get_expr_type() || + T_FUN_COUNT == aggr->get_expr_type() || + T_FUN_COUNT_SUM == aggr->get_expr_type() || + T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS == aggr->get_expr_type() || + T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS_MERGE == aggr->get_expr_type() || + T_FUN_SYS_BIT_AND == aggr->get_expr_type() || + T_FUN_SYS_BIT_OR == aggr->get_expr_type() || + T_FUN_SYS_BIT_XOR == aggr->get_expr_type() || + T_FUN_SUM_OPNSIZE == aggr->get_expr_type()) { + can_pre_aggr = true; + } + return ret; +} + int ObOptimizerUtil::compute_nlj_spf_storage_compute_parallel_skew(ObOptimizerContext *opt_ctx, uint64_t ref_table_id, const ObTableMetaInfo * esti_table_meta_info, @@ -10147,4 +10418,4 @@ int ObOptimizerUtil::compute_nlj_spf_storage_compute_parallel_skew(ObOptimizerCo } return ret; -} \ No newline at end of file +} diff --git a/src/sql/optimizer/ob_optimizer_util.h b/src/sql/optimizer/ob_optimizer_util.h index b9c17d398a..719e96c5da 100644 --- a/src/sql/optimizer/ob_optimizer_util.h +++ b/src/sql/optimizer/ob_optimizer_util.h @@ -77,6 +77,7 @@ class ObTablePartitionInfo; struct SubPlanInfo; class OptSelectivityCtx; class Path; +class AccessPath; class ObSharedExprResolver; class ObTableMetaInfo; class ObOptimizerUtil @@ -1150,7 +1151,23 @@ public: ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, ObSelectStmt *select_stmt); - + static int try_add_cast_to_select_list(ObIAllocator *allocator, + ObSQLSessionInfo *session_info, + ObRawExprFactory *expr_factory, + const int64_t column_cnt, + const bool is_set_distinct, + ObIArray &select_exprs, + ObIArray *res_types); + static int add_cast_to_set_select_expr(ObSQLSessionInfo *session_info, + ObRawExprFactory &expr_factory, + const ObExprResType &res_type, + ObRawExpr *&src_expr); + static int check_set_child_res_types(const ObExprResType &left_type, + const ObExprResType &right_type, + const bool is_ps_prepare_stage, + const bool is_distinct, + const bool is_mysql_recursive_union, + bool &skip_add_cast); static int get_set_res_types(ObIAllocator *allocator, ObSQLSessionInfo *session_info, ObIArray &child_querys, @@ -1165,13 +1182,26 @@ public: ObIArray *res_types, const bool is_mysql_recursive_union = false, ObIArray *rcte_col_name = NULL); - + static int try_add_cast_to_set_child_list(ObIAllocator *allocator, + ObSQLSessionInfo *session_info, + ObRawExprFactory *expr_factory, + const bool is_distinct, + ObIArray &left_stmts, + ObSelectStmt *right_stmt, + ObIArray *res_types, + const bool is_mysql_recursive_union = false, + ObIArray *rcte_col_name = NULL); static int add_cast_to_set_list(ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, ObIArray &stmts, const ObExprResType &res_type, const int64_t idx); - + static int add_cast_to_set_list(ObSQLSessionInfo *session_info, + ObRawExprFactory *expr_factory, + ObIArray &exprs, + const ObExprResType &res_type, + const int64_t column_idx, + const int64_t row_cnt); static int add_column_conv_to_set_list(ObSQLSessionInfo *session_info, ObRawExprFactory *expr_factory, ObIArray &stmts, @@ -1412,8 +1442,9 @@ public: // aggregate partial results static int generate_pullup_aggr_expr(ObRawExprFactory &expr_factory, ObSQLSessionInfo *session_info, - ObAggFunRawExpr *origin_aggr, - ObAggFunRawExpr *&replaced_aggr); + ObItemType aggr_type, + ObRawExpr *origin_expr, + ObAggFunRawExpr *&pullup_aggr); static int check_filter_before_indexback(const ObIArray &filter_exprs, const ObIArray &index_columns, @@ -1435,13 +1466,9 @@ public: static int allocate_identify_seq_expr(ObOptimizerContext &opt_ctx, ObRawExpr *&identify_seq_expr); - static int check_contribute_query_range(ObLogicalOperator *tsc, - const ObIArray ¶ms, - bool &is_valid); - - static int check_pushdown_range_cond(ObLogicalOperator *root, - bool &cnt_pd_range_cond); - + static int check_exec_param_filter_exprs(const ObIArray &filters, + const ObIArray &exec_params, + bool &used_in_filter); static int check_exec_param_filter_exprs(const ObIArray &input_filters, bool &has_exec_param_filters); @@ -1610,6 +1637,25 @@ public: const ObIArray &table_items, const ObRawExpr *expr, bool &is_filter); + static int get_has_global_index_filters(const ObSqlSchemaGuard *schema_guard, + const uint64_t index_id, + const ObIArray &filter_exprs, + bool &has_index_scan_filter, + bool &has_index_lookup_filter); + static int get_has_global_index_filters(const ObIArray &filter_exprs, + const ObIArray &index_columns, + bool &has_index_scan_filter, + bool &has_index_lookup_filter); + static int check_can_batch_rescan(const ObLogicalOperator *op, + const bool allow_normal_scan, + bool &can_batch_rescan); + static int check_can_batch_rescan_compat(const AccessPath &access_path, bool &can_batch_rescan); + static int check_can_batch_rescan_compat(ObLogicalOperator *op, + const ObIArray &rescan_params, + bool for_nlj, + bool &can_batch_rescan); + static int check_aggr_can_pre_aggregate(const ObAggFunRawExpr *aggr, + bool &can_pre_aggr); static int compute_nlj_spf_storage_compute_parallel_skew(ObOptimizerContext *opt_ctx, uint64_t ref_table_id, diff --git a/src/sql/optimizer/ob_sel_estimator.cpp b/src/sql/optimizer/ob_sel_estimator.cpp index a9040b9232..5da8c0bbcf 100644 --- a/src/sql/optimizer/ob_sel_estimator.cpp +++ b/src/sql/optimizer/ob_sel_estimator.cpp @@ -972,291 +972,158 @@ int ObEqualSelEstimator::get_cntcol_op_cntcol_sel(const OptTableMetas &table_met selectivity = DEFAULT_EQ_SEL; const ObRawExpr* left_expr = &input_left_expr; const ObRawExpr* right_expr = &input_right_expr; + double left_base_ndv = -1.0; + double right_base_ndv = -1.0; if (OB_FAIL(ObOptSelectivity::remove_ignorable_func_for_est_sel(left_expr)) || OB_FAIL(ObOptSelectivity::remove_ignorable_func_for_est_sel(right_expr))) { LOG_WARN("failed to remove ignorable function", K(ret)); - } else if (OB_ISNULL(left_expr) || OB_ISNULL(right_expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(left_expr), K(right_expr)); - } else if (left_expr->get_relation_ids().equal(right_expr->get_relation_ids()) && - ctx.check_opt_compat_version(COMPAT_VERSION_4_2_4, COMPAT_VERSION_4_3_0, - COMPAT_VERSION_4_3_3)) { - double combine_ndv = 1; - if (left_expr->is_column_ref_expr() && right_expr->is_column_ref_expr()) { - const ObColumnRefRawExpr* left_col = static_cast(left_expr); - const ObColumnRefRawExpr* right_col = static_cast(right_expr); - if (OB_FAIL(ObOptSelectivity::get_column_ndv_and_nns(table_metas, ctx, *left_expr, &left_ndv, &left_nns))) { - LOG_WARN("failed to get column basic sel", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::get_column_ndv_and_nns(table_metas, ctx, *right_expr, &right_ndv, &right_nns))) { - LOG_WARN("failed to get column basic sel", K(ret)); - } else if (left_col->get_column_id() == right_col->get_column_id()) { - // same table same column - if (T_OP_NSEQ == op_type) { - selectivity = 1.0; - } else if (T_OP_EQ == op_type) { - selectivity = left_nns; - } else if (T_OP_NE == op_type) { - selectivity = 0.0; - } - } else { - combine_ndv = ObOptSelectivity::combine_two_ndvs(ctx.get_current_rows(), left_ndv, right_ndv); - combine_ndv = std::max(1.0, combine_ndv); - selectivity = std::min(left_ndv, right_ndv) / combine_ndv; - if (T_OP_NSEQ == op_type) { - selectivity += (1 - left_nns) * (1 - right_nns); - } else if (T_OP_EQ == op_type) { - // do nothing - } else if (T_OP_NE == op_type) { - selectivity = std::max(1 - selectivity, 1 / combine_ndv / 2.0); - } - } - } else { - if (OB_FAIL(ObOptSelectivity::calculate_distinct(table_metas, ctx, *left_expr, ctx.get_current_rows(), left_ndv))) { - LOG_WARN("Failed to calculate distinct", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::calculate_distinct(table_metas, ctx, *right_expr, ctx.get_current_rows(), right_ndv))) { - LOG_WARN("Failed to calculate distinct", K(ret)); - } else { - combine_ndv = ObOptSelectivity::combine_two_ndvs(ctx.get_current_rows(), left_ndv, right_ndv); - combine_ndv = std::max(1.0, combine_ndv); - selectivity = std::min(left_ndv, right_ndv) / combine_ndv; - if (T_OP_NE == op_type) { - selectivity = std::max(1 - selectivity, 1 / combine_ndv / 2.0); - } - } - } - } else if (left_expr->is_column_ref_expr() && right_expr->is_column_ref_expr()) { - const ObColumnRefRawExpr* left_col = NULL; - const ObColumnRefRawExpr* right_col = NULL; - if (OB_FAIL(ObOptSelectivity::filter_one_column_by_equal_set(table_metas, ctx, left_expr, left_expr))) { - LOG_WARN("failed filter column by equal set", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::filter_one_column_by_equal_set(table_metas, ctx, right_expr, right_expr))) { - LOG_WARN("failed filter column by equal set", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::get_column_ndv_and_nns(table_metas, ctx, *left_expr, &left_ndv, &left_nns))) { - LOG_WARN("failed to get column basic sel", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::get_column_ndv_and_nns(table_metas, ctx, *right_expr, - &right_ndv, &right_nns))) { - LOG_WARN("failed to get column basic sel", K(ret)); - } else if (FALSE_IT(left_col = static_cast(left_expr)) || - FALSE_IT(right_col = static_cast(right_expr))) { - // never reach - } else if (left_expr->get_relation_ids() == right_expr->get_relation_ids()) { - if (left_col->get_column_id() == right_col->get_column_id()) { - // same table same column - if (T_OP_NSEQ == op_type) { - selectivity = 1.0; - } else if (T_OP_EQ == op_type) { - selectivity = left_nns; - } else if (T_OP_NE == op_type) { - selectivity = 0.0; - } - } else { - //same table different column - if (T_OP_NSEQ == op_type) { - selectivity = left_nns * right_nns / std::max(left_ndv, right_ndv) - + (1 - left_nns) * (1 - right_nns); - } else if (T_OP_EQ == op_type) { - selectivity = left_nns * right_nns / std::max(left_ndv, right_ndv); - } else if (T_OP_NE == op_type) { - selectivity = left_nns * right_nns * (1 - 1/std::max(left_ndv, right_ndv)); - } - } - } else { - // different table - ObOptColumnStatHandle left_handler; - ObOptColumnStatHandle right_handler; - obj_cmp_func cmp_func = NULL; - bool calc_with_hist = false; - if (!ObObjCmpFuncs::can_cmp_without_cast(left_col->get_result_type(), - right_col->get_result_type(), - CO_EQ, cmp_func)) { - // do nothing - } else if (OB_FAIL(ObOptSelectivity::get_histogram_by_column(table_metas, ctx, left_col->get_table_id(), - left_col->get_column_id(), left_handler))) { - LOG_WARN("failed to get histogram by column", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::get_histogram_by_column(table_metas, ctx, right_col->get_table_id(), - right_col->get_column_id(), right_handler))) { - LOG_WARN("failed to get histogram by column", K(ret)); - } else if (left_handler.stat_ != NULL && right_handler.stat_ != NULL && - left_handler.stat_->get_histogram().is_frequency() && - right_handler.stat_->get_histogram().is_frequency()) { - calc_with_hist = true; - } - if (OB_FAIL(ret)) { - } else if (IS_SEMI_ANTI_JOIN(ctx.get_join_type())) { - if (OB_ISNULL(ctx.get_left_rel_ids()) || OB_ISNULL(ctx.get_right_rel_ids())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ctx.get_left_rel_ids()), K(ctx.get_right_rel_ids())); - } else if (left_expr->get_relation_ids().overlap(*ctx.get_right_rel_ids()) || - right_expr->get_relation_ids().overlap(*ctx.get_left_rel_ids())) { - std::swap(left_ndv, right_ndv); - std::swap(left_nns, right_nns); - } - if (OB_SUCC(ret)) { - if (calc_with_hist) { - double total_rows = 0; - double left_rows = 0; - double left_null = 0; - double right_rows = 0; - double right_null = 0; - if (OB_FAIL(ObOptSelectivity::get_join_pred_rows(left_handler.stat_->get_histogram(), - right_handler.stat_->get_histogram(), - true, total_rows))) { - LOG_WARN("failed to get join pred rows", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::get_column_basic_info(ctx.get_plan()->get_basic_table_metas(), ctx, - *left_expr, NULL, &left_null, NULL, &left_rows))) { - LOG_WARN("failed to get column basic info", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::get_column_basic_info(ctx.get_plan()->get_basic_table_metas(), ctx, - *right_expr, NULL, &right_null, NULL, &right_rows))) { - LOG_WARN("failed to get column basic info", K(ret)); - } else if (T_OP_NSEQ == op_type) { - total_rows += right_null > 0 ? left_null : 0; - selectivity = total_rows / left_rows; - } else if (T_OP_EQ == op_type) { - selectivity = total_rows / left_rows; - } else if (T_OP_NE == op_type) { - selectivity = ((left_rows - left_null) * (right_rows - right_null) - total_rows) - / left_rows / right_rows; - } - } else { - /** - * ## non NULL safe - * a) semi: `(min(ndv1, ndv2) / ndv1) * (1.0 - nullfrac1)` - * ## NULL safe - * a) semi: `(min(ndv1, ndv2) / ndv1) * (1.0 - nullfrac1) + nullfrac2 > 0 && nullsafe ? nullfrac1: 0` - */ - if (IS_LEFT_SEMI_ANTI_JOIN(ctx.get_join_type())) { - if (T_OP_NSEQ == op_type) { - selectivity = (std::min(left_ndv, right_ndv) / left_ndv) * left_nns; - if (1 - right_nns > 0) { - selectivity += (1 - left_nns); - } - } else if (T_OP_EQ == op_type) { - selectivity = (std::min(left_ndv, right_ndv) / left_ndv) * left_nns; - } else if (T_OP_NE == op_type) { - if (right_ndv > 1.0) { - // if right ndv > 1.0, then there must exist one value not equal to left value - selectivity = left_nns; - } else { - selectivity = (1 - 1 / left_ndv) * left_nns; - } - } - } else { - if (T_OP_NSEQ == op_type) { - selectivity = (std::min(left_ndv, right_ndv) / right_ndv) * right_nns; - if (1 - left_nns > 0) { - selectivity += (1 - right_nns); - } - } else if (T_OP_EQ == op_type) { - selectivity = (std::min(left_ndv, right_ndv) / right_ndv) * right_nns; - } else if (T_OP_NE == op_type) { - if (left_ndv > 1.0) { - // if left ndv > 1.0, then there must exist one value not equal to right value - selectivity = right_nns; - } else { - selectivity = (1 - 1 / right_ndv) * right_nns; - } - } - } - } - } - if (OB_SUCC(ret) && selectivity >= 1.0 && IS_ANTI_JOIN(ctx.get_join_type())) { - selectivity = 1 - DEFAULT_ANTI_JOIN_SEL; - } - } else { - // inner join, outer join - if (calc_with_hist) { - // use frequency histogram calculate selectivity - double total_rows = 0; - double left_rows = 0; - double left_null = 0; - double right_rows = 0; - double right_null = 0; - if (OB_FAIL(ObOptSelectivity::get_join_pred_rows(left_handler.stat_->get_histogram(), - right_handler.stat_->get_histogram(), - false, total_rows))) { - LOG_WARN("failed to get join pred rows", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::get_column_basic_info(ctx.get_plan()->get_basic_table_metas(), ctx, - *left_expr, NULL, &left_null, NULL, &left_rows))) { - LOG_WARN("failed to get column basic info", K(ret)); - } else if (OB_FAIL(ObOptSelectivity::get_column_basic_info(ctx.get_plan()->get_basic_table_metas(), ctx, - *right_expr, NULL, &right_null, NULL, &right_rows))) { - LOG_WARN("failed to get column basic info", K(ret)); - } else if (T_OP_NSEQ == op_type) { - selectivity = (total_rows + left_null * right_null) / left_rows / right_rows; - } else if (T_OP_EQ == op_type) { - selectivity = total_rows / left_rows / right_rows; - } else if (T_OP_NE == op_type) { - selectivity = ((left_rows - left_null) * (right_rows - right_null) - total_rows) - / left_rows / right_rows; - } - } else { - /** - * ## non NULL safe - * (1.0 - nullfrac1) * (1.0 - nullfrac2) / MAX(nd1, nd2) - * ## NULL safe - * (1.0 - nullfrac1) * (1.0 - nullfrac2) / MAX(nd1, nd2) + nullfraf1 * nullfrac2 - * 目前不会特殊考虑 outer join 的选择率, 而是在外层对行数进行 revise. - */ - if (T_OP_NSEQ == op_type) { - selectivity = left_nns * right_nns / std::max(left_ndv, right_ndv) - + (1 - left_nns) * (1 - right_nns); - } else if (T_OP_EQ == op_type) { - selectivity = left_nns * right_nns / std::max(left_ndv, right_ndv); - } else if (T_OP_NE == op_type) { - selectivity = left_nns * right_nns * (1 - 1/std::max(left_ndv, right_ndv)); - } - } - } - } } else { - // func(col) = func(col) or col = func(col) - double left_sel = 0.0; - double right_sel = 0.0; - if (OB_FAIL(get_simple_equal_sel(table_metas, ctx, *left_expr, NULL, - T_OP_NSEQ == op_type, left_sel))) { - LOG_WARN("Failed to get simple predicate sel", K(ret)); - } else if (OB_FAIL(get_simple_equal_sel(table_metas, ctx, *right_expr, NULL, - T_OP_NSEQ == op_type, right_sel))) { - LOG_WARN("Failed to get simple predicate sel", K(ret)); - } else if (IS_SEMI_ANTI_JOIN(ctx.get_join_type())) { - if (OB_ISNULL(ctx.get_left_rel_ids()) || OB_ISNULL(ctx.get_right_rel_ids())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ctx.get_left_rel_ids()), K(ctx.get_right_rel_ids())); - } else if (left_expr->get_relation_ids().overlap(*ctx.get_right_rel_ids()) || - right_expr->get_relation_ids().overlap(*ctx.get_left_rel_ids())) { - std::swap(left_sel, right_sel); + bool calc_with_hist = false; + if (OB_FAIL(try_calc_equal_sel_with_hist(table_metas, + ctx, + left_expr, + right_expr, + op_type, + selectivity, + calc_with_hist))) { + LOG_WARN("failed to calc equal sel with hist", K(ret)); + } else if (calc_with_hist) { + // do nothing + } else if (OB_FAIL(ObOptSelectivity::calc_expr_basic_info(table_metas, + ctx, + left_expr, + &left_ndv, + &left_nns, + IS_ANTI_JOIN(ctx.get_join_type()) ? + &left_base_ndv : + NULL))) { + LOG_WARN("Failed to calculate distinct", K(ret)); + } else if (OB_FAIL(ObOptSelectivity::calc_expr_basic_info(table_metas, + ctx, + right_expr, + &right_ndv, + &right_nns, + IS_ANTI_JOIN(ctx.get_join_type()) ? + &right_base_ndv : + NULL))) { + LOG_WARN("Failed to calculate distinct", K(ret)); + } else if (left_expr->get_relation_ids() == right_expr->get_relation_ids()) { + selectivity = ObOptSelectivity::calc_equal_filter_sel(ctx, left_expr->same_as(*right_expr), op_type, + left_ndv, right_ndv, + left_nns, right_nns); + } else { + if (OB_NOT_NULL(ctx.get_left_rel_ids()) && OB_NOT_NULL(ctx.get_right_rel_ids()) && + (left_expr->get_relation_ids().overlap(*ctx.get_right_rel_ids()) || + right_expr->get_relation_ids().overlap(*ctx.get_left_rel_ids()))) { + std::swap(left_ndv, right_ndv); + std::swap(left_base_ndv, right_base_ndv); + std::swap(left_nns, right_nns); } - if (OB_SUCC(ret)) { - if (IS_LEFT_SEMI_ANTI_JOIN(ctx.get_join_type())) { - if (T_OP_NE == op_type) { - selectivity = 1 - left_sel; - } else if (right_sel < OB_DOUBLE_EPSINON) { - selectivity = 1.0; - } else { - selectivity = std::min(left_sel / right_sel, 1.0); - } - if (selectivity >= 1.0 && IS_ANTI_JOIN(ctx.get_join_type())) { - selectivity = 1 - left_sel; - } + selectivity = ObOptSelectivity::calc_equal_join_sel(ctx, op_type, + left_ndv, right_ndv, + left_nns, right_nns, + left_base_ndv, right_base_ndv); + } + } + return ret; +} + +int ObEqualSelEstimator::try_calc_equal_sel_with_hist(const OptTableMetas &table_metas, + const OptSelectivityCtx &ctx, + const ObRawExpr *left_expr, + const ObRawExpr *right_expr, + ObItemType op_type, + double &selectivity, + bool &calc_with_hist) +{ + int ret = OB_SUCCESS; + ObOptColumnStatHandle left_handler; + ObOptColumnStatHandle right_handler; + const ObOptColumnStat *left_col_stat = NULL; + const ObOptColumnStat *right_col_stat = NULL; + obj_cmp_func cmp_func = NULL; + calc_with_hist = false; + const ObColumnRefRawExpr *left_col = static_cast(left_expr); + const ObColumnRefRawExpr *right_col = static_cast(right_expr); + if (OB_ISNULL(left_expr) || OB_ISNULL(right_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected expr", KPC(left_expr), KPC(right_expr)); + } else if (!left_expr->is_column_ref_expr() || !right_expr->is_column_ref_expr()) { + // do nothing + } else if (left_expr->get_relation_ids() == right_expr->get_relation_ids()) { + // do nothing + } else if (!ObObjCmpFuncs::can_cmp_without_cast(left_col->get_result_type(), + right_col->get_result_type(), + CO_EQ, cmp_func)) { + // do nothing + } else if (OB_FAIL(ObOptSelectivity::get_histogram_by_column(table_metas, ctx, left_col->get_table_id(), + left_col->get_column_id(), left_handler))) { + LOG_WARN("failed to get histogram by column", K(ret)); + } else if (OB_FAIL(ObOptSelectivity::get_histogram_by_column(table_metas, ctx, right_col->get_table_id(), + right_col->get_column_id(), right_handler))) { + LOG_WARN("failed to get histogram by column", K(ret)); + } else if (left_handler.stat_ != NULL && right_handler.stat_ != NULL && + left_handler.stat_->get_histogram().is_frequency() && + right_handler.stat_->get_histogram().is_frequency()) { + calc_with_hist = true; + left_col_stat = left_handler.stat_; + right_col_stat = right_handler.stat_; + if (OB_NOT_NULL(ctx.get_left_rel_ids()) && OB_NOT_NULL(ctx.get_right_rel_ids()) && + (left_expr->get_relation_ids().overlap(*ctx.get_right_rel_ids()) || + right_expr->get_relation_ids().overlap(*ctx.get_left_rel_ids()))) { + std::swap(left_col_stat, right_col_stat); + std::swap(left_expr, right_expr); + } + } + if (OB_SUCC(ret) && calc_with_hist) { + double total_rows = 0; + double left_rows = left_col_stat->get_histogram().get_sample_size(); + double right_rows = right_col_stat->get_histogram().get_sample_size(); + double left_null_sel = 0; + double right_null_sel = 0; + if (OB_FAIL(ObOptSelectivity::get_join_pred_rows(left_col_stat->get_histogram(), + right_col_stat->get_histogram(), + ctx.get_join_type(), total_rows))) { + LOG_WARN("failed to get join pred rows", K(ret)); + } else if (OB_FAIL(ObOptSelectivity::get_column_basic_sel(table_metas, ctx, *left_expr, NULL, &left_null_sel))) { + LOG_WARN("Failed to calc basic equal sel", K(ret)); + } else if (OB_FAIL(ObOptSelectivity::get_column_basic_sel(table_metas, ctx, *right_expr, NULL, &right_null_sel))) { + LOG_WARN("Failed to calc basic equal sel", K(ret)); + } else if (IS_SEMI_ANTI_JOIN(ctx.get_join_type())) { + if (IS_RIGHT_SEMI_ANTI_JOIN(ctx.get_join_type())) { + std::swap(left_rows, right_rows); + std::swap(left_null_sel, right_null_sel); + std::swap(left_col_stat, right_col_stat); + } + double left_nns = 1 - left_null_sel; + double right_nns = 1 - right_null_sel; + if (T_OP_NSEQ == op_type) { + selectivity = left_nns * total_rows / left_rows + + (right_null_sel > OB_DOUBLE_EPSINON ? left_null_sel : 0); + } else if (T_OP_EQ == op_type) { + selectivity = left_nns * total_rows / left_rows; + } else if (T_OP_NE == op_type) { + if (right_col_stat->get_histogram().get_bucket_size() > 1) { + selectivity = left_nns; } else { - if (T_OP_NE == op_type) { - selectivity = 1 - right_sel; - } else if (left_sel < OB_DOUBLE_EPSINON) { - selectivity = 1.0; - } else { - selectivity = std::min(right_sel / left_sel, 1.0); - } - if (selectivity >= 1.0 && IS_ANTI_JOIN(ctx.get_join_type())) { - selectivity = 1 - right_sel; - } + selectivity = left_nns * (1 - total_rows / left_rows); } } + if (IS_ANTI_JOIN(ctx.get_join_type())) { + selectivity = std::min(selectivity, 1 - DEFAULT_ANTI_JOIN_SEL); + } } else { - selectivity = std::min(left_sel, right_sel); - if (T_OP_NE == op_type) { - selectivity = 1 - selectivity; + double left_nns = 1 - left_null_sel; + double right_nns = 1 - right_null_sel; + if (T_OP_NSEQ == op_type) { + selectivity = left_nns * right_nns * total_rows / left_rows / right_rows + left_null_sel * right_null_sel; + } else if (T_OP_EQ == op_type) { + selectivity = left_nns * right_nns * total_rows / left_rows / right_rows; + } else if (T_OP_NE == op_type) { + selectivity = left_nns * right_nns * (1 - total_rows / left_rows / right_rows); } } + selectivity = ObOptSelectivity::revise_between_0_1(selectivity); } return ret; } @@ -1929,9 +1796,9 @@ int ObLikeSelEstimator::calculate_like_sel_by_substr(const OptTableMetas &table_ LOG_WARN("failed to calcualte distinct", KPC_(pattern)); } else { if (NULL == ctx.get_left_rel_ids() || NULL == ctx.get_right_rel_ids()) { - double combine_ndv = ObOptSelectivity::combine_two_ndvs(ctx.get_current_rows(), substr_ndv, pattern_ndv); - selectivity = std::min(substr_ndv, pattern_ndv) / std::max(1.0, combine_ndv); - selectivity *= substr_nns * pattern_nns; + selectivity = ObOptSelectivity::calc_equal_filter_sel(ctx, false, T_OP_EQ, + substr_ndv, pattern_ndv, + substr_nns, pattern_nns); } else { double left_ndv = substr_ndv; double right_ndv = pattern_ndv; @@ -1942,18 +1809,9 @@ int ObLikeSelEstimator::calculate_like_sel_by_substr(const OptTableMetas &table_ std::swap(left_ndv, right_ndv); std::swap(left_nns, right_nns); } - if (IS_LEFT_SEMI_ANTI_JOIN(ctx.get_join_type())) { - selectivity = (std::min(left_ndv, right_ndv) / left_ndv) * left_nns; - } else if (IS_RIGHT_SEMI_ANTI_JOIN(ctx.get_join_type())) { - selectivity = (std::min(left_ndv, right_ndv) / right_ndv) * right_nns; - } else { - selectivity = left_nns * right_nns / std::max(left_ndv, right_ndv); - } - if (OB_SUCC(ret) && selectivity >= 1.0 && IS_ANTI_JOIN(ctx.get_join_type())) { - selectivity = 1 - DEFAULT_ANTI_JOIN_SEL; - } + selectivity = ObOptSelectivity::calc_equal_join_sel(ctx, T_OP_EQ, left_ndv, right_ndv, left_nns, right_nns); } - LOG_WARN("succeed to calculate like selectivity by substr", + LOG_TRACE("succeed to calculate like selectivity by substr", K(selectivity), K(substr_ndv), K(substr_nns), K(pattern_ndv), K(pattern_nns), K(wildcard_length)); } return ret; @@ -2019,12 +1877,25 @@ int ObBoolOpSelEstimator::create_estimator(ObSelEstimatorFactory &factory, return ret; } -bool ObBoolOpSelEstimator::tend_to_use_ds() +bool ObBoolOpSelEstimator::is_complex_filter_qual() { bool bret = false; for (int64_t i = 0; !bret && i < child_estimators_.count(); ++i) { ObSelEstimator *estimator = child_estimators_.at(i); - bret |= OB_NOT_NULL(estimator) ? estimator->tend_to_use_ds() : false; + bret |= OB_NOT_NULL(estimator) ? estimator->is_complex_filter_qual() : false; + } + return bret; +} + +bool ObBoolOpSelEstimator::is_complex_join_qual() +{ + bool bret = false; + if (OB_NOT_NULL(expr_) && T_OP_AND == expr_->get_expr_type()) { + bret = child_estimators_.count() > 1; + } + for (int64_t i = 0; !bret && i < child_estimators_.count(); ++i) { + ObSelEstimator *estimator = child_estimators_.at(i); + bret |= OB_NOT_NULL(estimator) ? estimator->is_complex_join_qual() : false; } return bret; } @@ -2437,6 +2308,8 @@ int ObSimpleJoinSelEstimator::get_cntcols_eq_cntcols_sel(const OptTableMetas &ta bool is_union_pk = false; bool refine_right_ndv = false; bool refine_left_ndv = false; + double left_base_ndv = -1.0; + double right_base_ndv = -1.0; if (OB_ISNULL(ctx.get_plan())) { ret = OB_ERR_UNEXPECTED; @@ -2490,107 +2363,65 @@ int ObSimpleJoinSelEstimator::get_cntcols_eq_cntcols_sel(const OptTableMetas &ta } } + if (OB_SUCC(ret)) { + left_nns = 1.0; + right_nns = 1.0; + for (int64_t i = 0; i < left_not_null_sels.count(); ++i) { + left_nns *= left_not_null_sels.at(i); + } + for (int64_t i = 0; i < right_not_null_sels.count(); ++i) { + right_nns *= right_not_null_sels.at(i); + } + } if (OB_FAIL(ret)) { } else if (OB_FAIL(ObOptSelectivity::calculate_distinct(table_metas, ctx, left_exprs, left_rows, left_ndv))) { LOG_WARN("Failed to calculate distinct", K(ret)); } else if (OB_FAIL(ObOptSelectivity::calculate_distinct(table_metas, ctx, right_exprs, right_rows, right_ndv))) { LOG_WARN("Failed to calculate distinct", K(ret)); - } else if (IS_SEMI_ANTI_JOIN(ctx.get_join_type())) { - /** - * 对于 semi anti join, 选择率描述的是外表行数为基础的选择率 - * # FORMULA - * ## non NULL safe - * a) semi: `(min(left_ndv, right_ndv) / left_ndv) * left_not_null_sel(i)` - * ## NULL safe - * a) semi: non NULL safe selectivity + `nullsafe(i) && left_not_null_sel(i) < 1.0 ? null_sel(i) * selectivity(j) [where j != i]: 0` - */ - if (IS_SEMI_ANTI_JOIN(ctx.get_assumption_type())) { - // do nothing - } else if (left_contain_pk == right_contain_pk) { - // 两侧都不是主键或都是主键, 不做修正 - } else if (refine_right_ndv) { - // 一侧有主键时, 认为是主外键连接, 外键上最大的ndv为即为主键的原始ndv - right_ndv = std::min(right_ndv, left_origin_rows); - } else if (refine_left_ndv) { - left_ndv = std::min(left_ndv, right_origin_rows); - } else { - // do nothing + } else if (IS_SEMI_ANTI_JOIN(ctx.get_assumption_type())) { + // do nothing + } else if (left_contain_pk == right_contain_pk) { + // 两侧都不是主键或都是主键, 不做修正 + } else if (refine_right_ndv) { + // 一侧有主键时, 认为是主外键连接, 外键上最大的ndv为即为主键的原始ndv + right_ndv = std::min(right_ndv, left_origin_rows); + } else if (refine_left_ndv) { + left_ndv = std::min(left_ndv, right_origin_rows); + } + if (OB_SUCC(ret) && IS_ANTI_JOIN(ctx.get_join_type())) { + if (OB_FAIL(ObOptSelectivity::calculate_distinct(table_metas, ctx, left_exprs, -1.0, left_base_ndv, false, DistinctEstType::BASE))) { + LOG_WARN("Failed to calculate distinct", K(ret)); + } else if (OB_FAIL(ObOptSelectivity::calculate_distinct(table_metas, ctx, right_exprs, -1.0, right_base_ndv, false, DistinctEstType::BASE))) { + LOG_WARN("Failed to calculate distinct", K(ret)); } - if (IS_LEFT_SEMI_ANTI_JOIN(ctx.get_join_type())) { - selectivity = std::min(left_ndv, right_ndv) / left_ndv; - for (int64_t i = 0; i < left_not_null_sels.count(); ++i) { - selectivity *= left_not_null_sels.at(i); - } - // 处理 null safe,这里假设多列上同时为null即小概率事件,只考虑特定列上为null的情况 - for (int64_t i = 0; i < null_safes.count(); ++i) { - if (OB_UNLIKELY(null_safes.at(i) && right_not_null_sels.at(i) < 1.0)) { - double factor = 1.0; - for (int64_t j = 0; j < null_safes.count(); ++j) { - if (i == j) { - factor *= (1 - left_not_null_sels.at(j)); - } else { - factor *= left_not_null_sels.at(j) * std::min(left_ndvs.at(j), right_ndvs.at(j)) / left_ndvs.at(j); - } - } - selectivity += factor; - } - } - } else { - selectivity = std::min(left_ndv, right_ndv) / right_ndv; - for (int64_t i = 0; i < right_not_null_sels.count(); ++i) { - selectivity *= right_not_null_sels.at(i); - } - // 处理 null safe,这里假设多列上同时为null即小概率事件,只考虑特定列上为null的情况 - for (int64_t i = 0; i < null_safes.count(); ++i) { - if (OB_UNLIKELY(null_safes.at(i) && right_not_null_sels.at(i) < 1.0)) { - double factor = 1.0; - for (int64_t j = 0; j < null_safes.count(); ++j) { - if (i == j) { - factor *= (1 - right_not_null_sels.at(j)); - } else { - factor *= right_not_null_sels.at(j) * std::min(left_ndvs.at(j), right_ndvs.at(j)) / right_ndvs.at(j); - } - } - selectivity += factor; - } - } - } - } else { - /** - * # FORMULA - * ## non NULL safe - * 1 / MAX(ndv1, ndv2) * not_null_frac1_col1 * not_null_frac2_col1 * not_null_frac1_col2 * not_null_frac2_col2 * ... - * ## NULL safe - * non NULL safe selectivity + `nullsafe(i) ? (1 - not_null_frac1_col(i)) * (1 - not_null_frac2_col(i)) * selectivity(col(j)) [where j != i]: 0` - * 目前不会特殊考虑 outer join 的选择率, 而是在外层对行数进行 revise. - */ - if (left_contain_pk == right_contain_pk) { - // 两侧都不是主键或都是主键, 不做修正 - } else if (refine_right_ndv) { - // 一侧有主键时, 认为是主外键连接, 外键上最大的ndv为即为主键的原始ndv - right_ndv = std::min(right_ndv, left_origin_rows); - } else if (refine_left_ndv) { - left_ndv = std::min(left_ndv, right_origin_rows); - } else { - // do nothing - } - selectivity = 1.0 / std::max(left_ndv, right_ndv); - for (int64_t i = 0; i < left_not_null_sels.count(); ++i) { - selectivity *= left_not_null_sels.at(i) * right_not_null_sels.at(i); - } - // 处理null safe, 这里假设多列上同时为null即小概率事件,只考虑特定列上为null的情况 + } + if (OB_SUCC(ret)) { + selectivity = ObOptSelectivity::calc_equal_join_sel(ctx, T_OP_EQ, left_ndv, right_ndv, left_nns, right_nns, left_base_ndv, right_base_ndv); + // 处理 null safe,这里假设多列上同时为null即小概率事件,只考虑特定列上为null的情况 for (int64_t i = 0; i < null_safes.count(); ++i) { if (null_safes.at(i)) { double factor = 1.0; for (int64_t j = 0; j < null_safes.count(); ++j) { if (i == j) { - factor *= (1 - left_not_null_sels.at(j)) * (1 - right_not_null_sels.at(j)); + if (IS_LEFT_SEMI_ANTI_JOIN(ctx.get_join_type())) { + factor *= (1 - left_not_null_sels.at(j)); + } else if (IS_RIGHT_SEMI_ANTI_JOIN(ctx.get_join_type())) { + factor *= (1 - right_not_null_sels.at(j)); + } else { + factor *= (1 - left_not_null_sels.at(j)) * (1 - right_not_null_sels.at(j)); + } } else { - factor *= left_not_null_sels.at(j) * right_not_null_sels.at(j) / std::max(left_ndvs.at(j), right_ndvs.at(j)); + if (IS_LEFT_SEMI_ANTI_JOIN(ctx.get_join_type())) { + factor *= left_not_null_sels.at(j) * std::min(left_ndvs.at(j), right_ndvs.at(j)) / left_ndvs.at(j); + } else if (IS_RIGHT_SEMI_ANTI_JOIN(ctx.get_join_type())) { + factor *= right_not_null_sels.at(j) * std::min(left_ndvs.at(j), right_ndvs.at(j)) / right_ndvs.at(j); + } else { + factor *= left_not_null_sels.at(j) * right_not_null_sels.at(j) / std::max(left_ndvs.at(j), right_ndvs.at(j)); + } } } selectivity += factor; - } else {/* do nothing */} + } } } LOG_TRACE("selectivity of `col_ref1 =|<=> col_ref1 and col_ref2 =|<=> col_ref2`", K(selectivity)); @@ -2924,12 +2755,14 @@ int ObInequalJoinSelEstimator::get_sel(const OptTableMetas &table_metas, } else { // TODO : c1 + c1 < 1 selectivity = DEFAULT_INEQ_JOIN_SEL; + use_default_ = true; } } else if (OB_FAIL(ObOptSelectivity::get_column_min_max(table_metas, ctx, *term_.col1_, obj_min, obj_max))) { LOG_WARN("failed to get column min max", K(ret), KPC(term_.col1_)); } else if (obj_min.is_min_value() || obj_min.is_max_value() || obj_max.is_max_value() || obj_max.is_min_value()) { selectivity = DEFAULT_INEQ_JOIN_SEL; + use_default_ = true; } else if (OB_FAIL(ObOptEstObjToScalar::convert_obj_to_scalar_obj(&obj_min, &tmp_obj))) { LOG_WARN("failed to convert obj", K(obj_min)); } else if (FALSE_IT(min1 = tmp_obj.get_double() * term_.coefficient1_)) { @@ -2941,6 +2774,7 @@ int ObInequalJoinSelEstimator::get_sel(const OptTableMetas &table_metas, } else if (obj_min.is_min_value() || obj_min.is_max_value() || obj_max.is_max_value() || obj_max.is_min_value()) { selectivity = DEFAULT_INEQ_JOIN_SEL; + use_default_ = true; } else if (OB_FAIL(ObOptEstObjToScalar::convert_obj_to_scalar_obj(&obj_min, &tmp_obj))) { LOG_WARN("failed to convert obj", K(obj_min)); } else if (FALSE_IT(min2 = tmp_obj.get_double() * term_.coefficient2_)) { diff --git a/src/sql/optimizer/ob_sel_estimator.h b/src/sql/optimizer/ob_sel_estimator.h index d43a43209d..c52d21ff48 100644 --- a/src/sql/optimizer/ob_sel_estimator.h +++ b/src/sql/optimizer/ob_sel_estimator.h @@ -97,7 +97,8 @@ public: double &selectivity, ObIArray &all_predicate_sel) = 0; // Check whether we tend to use dynamic sampling for this estimator - virtual bool tend_to_use_ds() = 0; + virtual bool is_complex_filter_qual() = 0; + virtual bool is_complex_join_qual() = 0; inline ObSelEstType get_type() const { return type_; } const ObRawExpr *get_eigen_expr() const { return eigen_expr_; } @@ -243,7 +244,8 @@ public: { return create_simple_estimator(factory, ctx, expr, estimator); } - virtual bool tend_to_use_ds() override { return true; } + virtual bool is_complex_filter_qual() override { return true; } + virtual bool is_complex_join_qual() override { return true; } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -270,7 +272,8 @@ public: { return create_simple_estimator(factory, ctx, expr, estimator); } - virtual bool tend_to_use_ds() override { return false; } + virtual bool is_complex_filter_qual() override { return false; } + virtual bool is_complex_join_qual() override { return false; } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -343,7 +346,8 @@ public: { return create_simple_estimator(factory, ctx, expr, estimator); } - virtual bool tend_to_use_ds() override { return false; } + virtual bool is_complex_filter_qual() override { return false; } + virtual bool is_complex_join_qual() override { return true; } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -385,7 +389,8 @@ public: { return create_simple_estimator(factory, ctx, expr, estimator); } - virtual bool tend_to_use_ds() override { return false; } + virtual bool is_complex_filter_qual() override { return false; } + virtual bool is_complex_join_qual() override { return true; } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -432,7 +437,8 @@ public: { return create_simple_estimator(factory, ctx, expr, estimator); } - virtual bool tend_to_use_ds() override { return false; } + virtual bool is_complex_filter_qual() override { return false; } + virtual bool is_complex_join_qual() override { return true; } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -487,7 +493,8 @@ public: const ObRawExpr &expr, ObSelEstimator *&estimator); - virtual bool tend_to_use_ds() override { return !can_calc_sel_; } + virtual bool is_complex_filter_qual() override { return !can_calc_sel_; } + virtual bool is_complex_join_qual() override { return true; } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -518,7 +525,8 @@ public: const OptSelectivityCtx &ctx, const ObRawExpr &expr, ObSelEstimator *&estimator); - virtual bool tend_to_use_ds() override { return !can_calc_sel_; } + virtual bool is_complex_filter_qual() override { return !can_calc_sel_; } + virtual bool is_complex_join_qual() override { return true; } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -549,7 +557,8 @@ public: const OptSelectivityCtx &ctx, const ObRawExpr &expr, ObSelEstimator *&estimator); - virtual bool tend_to_use_ds() override { return !can_calc_sel_; } + virtual bool is_complex_filter_qual() override { return !can_calc_sel_; } + virtual bool is_complex_join_qual() override { return true; } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -578,7 +587,10 @@ public: const OptSelectivityCtx &ctx, const ObRawExpr &expr, ObSelEstimator *&estimator); - virtual bool tend_to_use_ds() override { return !can_calc_sel_; } + virtual bool is_complex_filter_qual() override { return !can_calc_sel_; } + virtual bool is_complex_join_qual() override { + return OB_NOT_NULL(expr_) && expr_->get_relation_ids().num_members() > 2; + } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -645,6 +657,14 @@ private: ObItemType op_type, double &selectivity); + static int try_calc_equal_sel_with_hist(const OptTableMetas &table_metas, + const OptSelectivityCtx &ctx, + const ObRawExpr *left_expr, + const ObRawExpr *right_expr, + ObItemType op_type, + double &selectivity, + bool &calc_with_hist); + static int check_can_calc_sel(const ObRawExpr &l_expr, const ObRawExpr &r_expr, bool &can_calc_sel); @@ -675,7 +695,8 @@ public: const OptSelectivityCtx &ctx, const ObRawExpr &expr, ObSelEstimator *&estimator); - virtual bool tend_to_use_ds() override { return !can_calc_sel_by_prefix_; } + virtual bool is_complex_filter_qual() override { return !can_calc_sel_by_prefix_; } + virtual bool is_complex_join_qual() override { return true; } virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -709,7 +730,8 @@ public: const OptSelectivityCtx &ctx, const ObRawExpr &expr, ObSelEstimator *&estimator); - virtual bool tend_to_use_ds() override; + virtual bool is_complex_filter_qual() override; + virtual bool is_complex_join_qual() override; virtual int get_sel(const OptTableMetas &table_metas, const OptSelectivityCtx &ctx, double &selectivity, @@ -745,7 +767,8 @@ public: double &selectivity, ObIArray &all_predicate_sel) override; - virtual bool tend_to_use_ds() override { return false; } + virtual bool is_complex_filter_qual() override { return false; } + virtual bool is_complex_join_qual() override { return true; } VIRTUAL_TO_STRING_KV(K_(type), KPC_(column_expr), K_(range_exprs)); @@ -788,7 +811,8 @@ public: double &selectivity, ObIArray &all_predicate_sel) override; - virtual bool tend_to_use_ds() override { return false; } + virtual bool is_complex_filter_qual() override { return false; } + virtual bool is_complex_join_qual() override { return false; } VIRTUAL_TO_STRING_KV(K_(type), KPC_(left_rel_ids), KPC_(right_rel_ids), K_(join_conditions)); private: @@ -849,7 +873,8 @@ public: public: ObInequalJoinSelEstimator() : - ObSelEstimator(ObSelEstType::INEQUAL_JOIN) {} + ObSelEstimator(ObSelEstType::INEQUAL_JOIN), + use_default_(false) {} virtual ~ObInequalJoinSelEstimator() = default; static int create_estimator(ObSelEstimatorFactory &factory, @@ -864,7 +889,8 @@ public: double &selectivity, ObIArray &all_predicate_sel) override; - virtual bool tend_to_use_ds() override { return false; } + virtual bool is_complex_filter_qual() override { return false; } + virtual bool is_complex_join_qual() override { return use_default_; } VIRTUAL_TO_STRING_KV(K_(type), K_(term), K_(range)); @@ -918,6 +944,7 @@ private: Term term_; SimpleRange range_; + bool use_default_; private: DISALLOW_COPY_AND_ASSIGN(ObInequalJoinSelEstimator); @@ -976,7 +1003,8 @@ public: const double end_scalar, double &selectivity); - virtual bool tend_to_use_ds() override { return true; } + virtual bool is_complex_filter_qual() override { return true; } + virtual bool is_complex_join_qual() override { return true; } }; } diff --git a/src/sql/optimizer/ob_select_log_plan.cpp b/src/sql/optimizer/ob_select_log_plan.cpp index 1a1a30a2a6..cbf03d87bd 100644 --- a/src/sql/optimizer/ob_select_log_plan.cpp +++ b/src/sql/optimizer/ob_select_log_plan.cpp @@ -2091,26 +2091,18 @@ int ObSelectLogPlan::generate_union_all_plans(const ObIArray & { int ret = OB_SUCCESS; if (child_plans.count() > 2) { - ObSEArray child_ops; + ObSEArray, 3> child_ops; // get best children plan - for (int64_t i = 0; OB_SUCC(ret) && i < child_plans.count(); i++) { - ObLogicalOperator *best_plan = NULL; - if (OB_ISNULL(child_plans.at(i))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (OB_FAIL(child_plans.at(i)->get_candidate_plans().get_best_plan(best_plan))) { - LOG_WARN("failed to get best plan", K(ret)); - } else if (OB_ISNULL(best_plan)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (OB_FAIL(child_ops.push_back(best_plan))) { - LOG_WARN("failed to push back child ops", K(ret)); - } else { /*do nothing*/ } + if (OB_FAIL(child_ops.prepare_allocate(3))) { + LOG_WARN("fail to prepare allocate", K(ret)); + } else if (OB_FAIL(get_best_child_candidate_plans(child_plans, child_ops.at(0), child_ops.at(1), child_ops.at(2)))) { + LOG_WARN("failed to get best child candi plans", K(ret)); } // generate union all plan - if (OB_SUCC(ret)) { + for (int i = 0; OB_SUCC(ret) && i < 3; ++i) { CandidatePlan candidate_plan; - if (OB_FAIL(create_union_all_plan(child_ops, ignore_hint, candidate_plan.plan_tree_))) { + if (!child_ops.at(i).empty() && + OB_FAIL(create_union_all_plan(child_ops.at(i), ignore_hint, candidate_plan.plan_tree_))) { LOG_WARN("failed to create union all plan", K(ret)); } else if (NULL == candidate_plan.plan_tree_) { /*do nothing*/ @@ -2187,6 +2179,66 @@ int ObSelectLogPlan::generate_union_all_plans(const ObIArray & return ret; } +int ObSelectLogPlan::get_best_child_candidate_plans(const ObIArray &child_plans, + ObIArray &best_child_ops, + ObIArray &best_das_child_ops, + ObIArray &best_px_child_ops) +{ + int ret = OB_SUCCESS; + best_child_ops.reuse(); + best_das_child_ops.reuse(); + best_px_child_ops.reuse(); + ObLogicalOperator *best_plan = NULL; + for (int64_t i = 0; OB_SUCC(ret) && i < child_plans.count(); i++) { + if (OB_ISNULL(child_plans.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(i)); + } else if (OB_FAIL(child_plans.at(i)->get_candidate_plans().get_best_plan(best_plan))) { + LOG_WARN("failed to get best plan", K(ret)); + } else if (OB_ISNULL(best_plan)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(best_child_ops.push_back(best_plan))) { + LOG_WARN("failed to push back child ops", K(ret)); + } else { + ObIArray &candidate_plans = child_plans.at(i)->get_candidate_plans().candidate_plans_; + ObLogicalOperator *child_op = NULL; + ObLogicalOperator *best_das_plan = NULL; + ObLogicalOperator *best_px_plan = NULL; + for (int64_t j = 0; OB_SUCC(ret) && j < candidate_plans.count(); ++j) { + if (OB_ISNULL(child_op = candidate_plans.at(j).plan_tree_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(j)); + } else if (!child_op->is_match_all() && child_op->get_contains_das_op()) { + /* ignore this plan */ + } else if (child_op->is_match_all()) { + best_das_plan = (NULL == best_das_plan || best_das_plan->get_cost() > child_op->get_cost()) + ? child_op : best_das_plan; + } else { + best_px_plan = (NULL == best_px_plan || best_px_plan->get_cost() > child_op->get_cost()) + ? child_op : best_px_plan; + } + } + if (OB_FAIL(ret)) { + } else if (NULL != best_das_plan && OB_FAIL(best_das_child_ops.push_back(best_das_plan))) { + LOG_WARN("failed to push back child op", K(ret)); + } else if (NULL != best_px_plan && OB_FAIL(best_px_child_ops.push_back(best_px_plan))) { + LOG_WARN("failed to push back child op", K(ret)); + } + } + } + + if (OB_SUCC(ret)) { + if (best_das_child_ops.count() != child_plans.count()) { + best_das_child_ops.reuse(); + } + if (best_px_child_ops.count() != child_plans.count()) { + best_px_child_ops.reuse(); + } + } + return ret; +} + int ObSelectLogPlan::create_union_all_plan(const ObIArray &child_ops, const bool ignore_hint, ObLogicalOperator *&top) @@ -2205,10 +2257,13 @@ int ObSelectLogPlan::create_union_all_plan(const ObIArray &c bool is_partition_wise = false; bool is_ext_partition_wise = false; bool is_set_partition_wise = false; + bool basic_push_distinct = false; DistAlgo hint_dist_methods = get_log_plan_hint().get_valid_set_dist_algo(&random_none_idx); if (OB_ISNULL(select_stmt = get_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected error", K(select_stmt), K(ret)); + } else if (select_stmt->is_set_distinct() && OB_FAIL(check_basic_distinct_pushdown(basic_push_distinct))) { + LOG_WARN("failed to check basic distinct pushdown", K(ret)); } else if (!get_optimizer_context().is_var_assign_only_in_root_stmt() && get_optimizer_context().has_var_assign()) { set_dist_methods &= DistAlgo::DIST_PULL_TO_LOCAL | DistAlgo::DIST_BASIC_METHOD; @@ -2315,11 +2370,33 @@ int ObSelectLogPlan::create_union_all_plan(const ObIArray &c set_dist_methods = DistAlgo::DIST_SET_RANDOM; for (int64_t i = 0; OB_SUCC(ret) && i < child_ops.count(); i++) { ObLogicalOperator *child_op = NULL; + const ObDMLStmt *child_stmt = NULL; + ObSEArray child_select_exprs; + bool child_push_distinct = false; + bool need_exchange = false; if (OB_ISNULL(child_op = child_ops.at(i)) || - OB_ISNULL(child_op->get_plan())) { + OB_ISNULL(child_op->get_plan()) || + OB_ISNULL(child_stmt = child_op->get_plan()->get_stmt())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (child_op != largest_op && + LOG_WARN("get unexpected null", K(ret), K(child_op), K(child_stmt)); + } else if (OB_FALSE_IT(need_exchange = child_op != largest_op)) { + } else if (OB_UNLIKELY(!child_stmt->is_select_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("child stmt is not select stmt", K(ret), KPC(child_stmt)); + } else if (OB_FAIL(static_cast(child_stmt)->get_select_exprs(child_select_exprs))) { + LOG_WARN("failed to get select exprs", K(ret)); + } else if (basic_push_distinct && need_exchange && + OB_FAIL(check_need_pushdown_set_distinct(child_op, + child_select_exprs, + child_push_distinct))) { + LOG_WARN("failed to check need pushdown set distinct", K(ret)); + } else if (child_push_distinct && + OB_FAIL(allocate_pushdown_set_distinct_as_top(child_op, + child_select_exprs, + HASH_AGGREGATE, + get_update_table_metas().get_table_meta_by_table_id(i)))) { + LOG_WARN("failed to allocate push down distinct as top", K(ret)); + } else if (need_exchange && OB_FAIL(child_op->get_plan()->allocate_exchange_as_top(child_op, exch_info))) { LOG_WARN("failed to allocate exchange as top", K(ret)); } else if (OB_FAIL(set_child_ops.push_back(child_op))) { @@ -2335,11 +2412,33 @@ int ObSelectLogPlan::create_union_all_plan(const ObIArray &c set_dist_methods = DistAlgo::DIST_PULL_TO_LOCAL; for (int64_t i = 0; OB_SUCC(ret) && i < child_ops.count(); i++) { ObLogicalOperator *child_op = NULL; + const ObDMLStmt *child_stmt = NULL; + ObSEArray child_select_exprs; + bool child_push_distinct = false; + bool need_exchange = false; if (OB_ISNULL(child_op = child_ops.at(i)) || - OB_ISNULL(child_op->get_plan())) { + OB_ISNULL(child_op->get_plan()) || + OB_ISNULL(child_stmt = child_op->get_plan()->get_stmt())) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (child_op->is_sharding() && + LOG_WARN("get unexpected null", K(ret), K(child_op), K(child_stmt)); + } else if (OB_FALSE_IT(need_exchange = child_op->is_sharding())) { + } else if (OB_UNLIKELY(!child_stmt->is_select_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("child stmt is not select stmt", K(ret), KPC(child_stmt)); + } else if (OB_FAIL(static_cast(child_stmt)->get_select_exprs(child_select_exprs))) { + LOG_WARN("failed to get select exprs", K(ret)); + } else if (basic_push_distinct && need_exchange && + OB_FAIL(check_need_pushdown_set_distinct(child_op, + child_select_exprs, + child_push_distinct))) { + LOG_WARN("failed to check need pushdown set distinct", K(ret)); + } else if (child_push_distinct && + OB_FAIL(allocate_pushdown_set_distinct_as_top(child_op, + child_select_exprs, + HASH_AGGREGATE, + get_update_table_metas().get_table_meta_by_table_id(i)))) { + LOG_WARN("failed to allocate push down distinct as top", K(ret)); + } else if (need_exchange && OB_FAIL(child_op->get_plan()->allocate_exchange_as_top(child_op, exch_info))) { LOG_WARN("failed to allocate exchange as top", K(ret)); } else if (OB_ISNULL(child_op)) { @@ -3811,11 +3910,11 @@ int ObSelectLogPlan::create_merge_set_plan(const EqualSets &equal_sets, const ObIArray &order_directions, const ObIArray &map_array, const ObIArray &left_sort_keys, - const bool left_need_sort, - const int64_t left_prefix_pos, + bool left_need_sort, + int64_t left_prefix_pos, const ObIArray &right_sort_keys, - const bool right_need_sort, - const int64_t right_prefix_pos, + bool right_need_sort, + int64_t right_prefix_pos, CandidatePlan &merge_plan) { int ret = OB_SUCCESS; @@ -3823,16 +3922,31 @@ int ObSelectLogPlan::create_merge_set_plan(const EqualSets &equal_sets, ObLogPlan *right_plan = NULL; ObExchangeInfo left_exch_info; ObExchangeInfo right_exch_info; + bool basic_push_distinct = false; + bool left_push_distinct = false; + bool right_push_distinct = false; if (OB_ISNULL(left_child) || OB_ISNULL(right_child) || OB_ISNULL(left_plan = left_child->get_plan()) || OB_ISNULL(right_plan = right_child->get_plan())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(left_child), K(right_child), K(left_plan), K(right_plan)); + } else if (OB_FAIL(check_basic_distinct_pushdown(basic_push_distinct))) { + LOG_WARN("failed to check basic distinct pushdown", K(ret)); + } else if (basic_push_distinct + && OB_FAIL(check_need_pushdown_set_distinct(left_child, + left_set_keys, + left_push_distinct))) { + LOG_WARN("failed to check need pushdown set distinct", K(ret)); + } else if (basic_push_distinct + && OB_FAIL(check_need_pushdown_set_distinct(right_child, + right_set_keys, + right_push_distinct))) { + LOG_WARN("failed to check need pushdown set distinct", K(ret)); } else { bool is_fully_partition_wise = DistAlgo::DIST_PARTITION_WISE == dist_set_method && !left_child->is_exchange_allocated() && !right_child->is_exchange_allocated(); - bool is_left_local_order = left_child->get_is_local_order() && !is_fully_partition_wise; - bool is_right_local_order = right_child->get_is_local_order() && !is_fully_partition_wise; + bool is_left_local_order = false; + bool is_right_local_order = false; if (OB_FAIL(compute_set_exchange_info(equal_sets, *left_child, *right_child, @@ -3843,6 +3957,26 @@ int ObSelectLogPlan::create_merge_set_plan(const EqualSets &equal_sets, left_exch_info, right_exch_info))) { LOG_WARN("failed to compute set exchange info", K(ret)); + } else if (OB_FAIL(init_width_estimation_info(get_stmt()))) { + LOG_WARN("failed to init width estimation info", K(ret)); + } else if (left_push_distinct && left_exch_info.need_exchange() + && OB_FAIL(allocate_pushdown_merge_set_distinct_as_top(left_child, + left_set_keys, + left_sort_keys, + get_update_table_metas().get_table_meta_by_table_id(0), + left_need_sort, + left_prefix_pos))) { + LOG_WARN("failed to allocate push down distinct as top", K(ret)); + } else if (right_push_distinct && right_exch_info.need_exchange() + && OB_FAIL(allocate_pushdown_merge_set_distinct_as_top(right_child, + right_set_keys, + right_sort_keys, + get_update_table_metas().get_table_meta_by_table_id(1), + right_need_sort, + right_prefix_pos))) { + LOG_WARN("failed to allocate push down distinct as top", K(ret)); + } else if (OB_FALSE_IT(is_left_local_order = left_child->get_is_local_order() && !is_fully_partition_wise)) { + } else if (OB_FALSE_IT(is_right_local_order = right_child->get_is_local_order() && !is_fully_partition_wise)) { } else if (OB_FAIL(left_plan->allocate_sort_and_exchange_as_top(left_child, left_exch_info, left_sort_keys, @@ -4011,12 +4145,27 @@ int ObSelectLogPlan::create_hash_set_plan(const EqualSets &equal_sets, ObLogPlan *left_log_plan = NULL; ObLogPlan *right_log_plan = NULL; const ObSelectStmt *select_stmt = get_stmt(); + bool basic_push_distinct = false; + bool left_push_distinct = false; + bool right_push_distinct = false; if (OB_ISNULL(left_child) || OB_ISNULL(right_child) || OB_ISNULL(left_log_plan = left_child->get_plan()) || OB_ISNULL(right_log_plan = right_child->get_plan())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(left_child), K(right_child), K(left_log_plan), K(right_log_plan), K(ret)); + } else if (OB_FAIL(check_basic_distinct_pushdown(basic_push_distinct))) { + LOG_WARN("failed to check basic distinct pushdown", K(ret)); + } else if (basic_push_distinct + && OB_FAIL(check_need_pushdown_set_distinct(left_child, + left_set_keys, + left_push_distinct))) { + LOG_WARN("failed to check need pushdown set distinct", K(ret)); + } else if (basic_push_distinct + && OB_FAIL(check_need_pushdown_set_distinct(right_child, + right_set_keys, + right_push_distinct))) { + LOG_WARN("failed to check need pushdown set distinct", K(ret)); } else if (OB_FAIL(compute_set_exchange_info(equal_sets, *left_child, *right_child, @@ -4027,6 +4176,20 @@ int ObSelectLogPlan::create_hash_set_plan(const EqualSets &equal_sets, left_exch_info, right_exch_info))) { LOG_WARN("failed to compute set exchange info", K(ret)); + } else if (OB_FAIL(init_width_estimation_info(get_stmt()))) { + LOG_WARN("failed to init width estimation info", K(ret)); + } else if (left_push_distinct && left_exch_info.need_exchange() + && OB_FAIL(allocate_pushdown_set_distinct_as_top(left_child, + left_set_keys, + HASH_AGGREGATE, + get_update_table_metas().get_table_meta_by_table_id(0)))) { + LOG_WARN("failed to allocate push down distinct as top", K(ret)); + } else if (right_push_distinct && right_exch_info.need_exchange() + && OB_FAIL(allocate_pushdown_set_distinct_as_top(right_child, + right_set_keys, + HASH_AGGREGATE, + get_update_table_metas().get_table_meta_by_table_id(1)))) { + LOG_WARN("failed to allocate push down distinct as top", K(ret)); } else if (left_exch_info.need_exchange() && OB_FAIL(left_log_plan->allocate_exchange_as_top(left_child, left_exch_info))) { LOG_WARN("failed to allocate exchange as top", K(ret)); @@ -4045,6 +4208,117 @@ int ObSelectLogPlan::create_hash_set_plan(const EqualSets &equal_sets, return ret; } +int ObSelectLogPlan::check_need_pushdown_set_distinct(ObLogicalOperator *&child, + const ObIArray &set_keys, + bool &is_valid) +{ + int ret = OB_SUCCESS; + bool is_const = true; + bool is_unique = true; + is_valid = false; + if (OB_ISNULL(child) || OB_ISNULL(optimizer_context_.get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(child), K(optimizer_context_.get_query_ctx())); + } else if (!optimizer_context_.get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_3_5)) { + // do nothing + } else if (LOG_SET == child->get_type() + && static_cast(child)->is_set_distinct()) { + // do nothing + } else if (OB_FAIL(ObOptimizerUtil::is_exprs_unique(set_keys, + child->get_table_set(), + child->get_fd_item_set(), + child->get_output_equal_sets(), + child->get_output_const_exprs(), + is_unique))) { + LOG_WARN("failed to check whether distinct exprs is unique", K(ret)); + } else if (is_unique) { + // do nothing + } else { + for (int64_t i = 0; OB_SUCC(ret) && is_const && i < set_keys.count(); ++i) { + if (OB_FAIL(ObOptimizerUtil::is_const_expr(set_keys.at(i), + child->get_output_equal_sets(), + child->get_output_const_exprs(), + get_onetime_query_refs(), + is_const))) { + LOG_WARN("check is const expr failed", K(ret)); + } + } + if (OB_SUCC(ret)) { + is_valid = !is_const; + } + } + return ret; +} + +int ObSelectLogPlan::allocate_pushdown_set_distinct_as_top(ObLogicalOperator *&child, + const ObIArray &set_keys, + AggregateAlgo algo, + const OptTableMeta *table_meta, + bool is_partition_wise, + bool is_partition_gi) +{ + int ret = OB_SUCCESS; + ObSelectLogPlan *child_plan = NULL; + if (OB_ISNULL(child) + || OB_ISNULL(child_plan = static_cast(child->get_plan()))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(child)); + } else { + double child_ndv = 1.0; + if (OB_NOT_NULL(table_meta)) { + child_ndv = table_meta->get_distinct_rows(); + } + if (OB_FAIL(child_plan->allocate_distinct_as_top(child, + algo, + set_keys, + child_ndv, + is_partition_wise, + true, /* is_push_down */ + is_partition_gi))) { + LOG_WARN("failed to allocate push down distinct as top", K(ret)); + } + } + return ret; +} + +int ObSelectLogPlan::allocate_pushdown_merge_set_distinct_as_top(ObLogicalOperator *&child, + const ObIArray &set_keys, + const ObIArray &sort_keys, + const OptTableMeta *table_meta, + bool &need_sort, + int64_t &prefix_pos) +{ + int ret = OB_SUCCESS; + bool should_pullup_gi = false; + bool child_is_local_order = false; + bool is_partition_gi = false; + if (OB_ISNULL(child)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(child)); + } else if (OB_FAIL(check_can_pullup_gi(*child, false, need_sort, should_pullup_gi))) { + LOG_WARN("failed to check can pullup gi", K(ret)); + } else if (OB_FALSE_IT(is_partition_gi = child->is_partition_wise())) { + } else if (OB_FALSE_IT(child_is_local_order = child->get_is_local_order() && !should_pullup_gi)) { + } else if ((need_sort || child_is_local_order) && + OB_FAIL(allocate_sort_as_top(child, + sort_keys, + need_sort && child_is_local_order ? 0 : prefix_pos, + !need_sort && child_is_local_order))) { + LOG_WARN("failed to allocate sort as top", K(ret)); + } else if (OB_FAIL(allocate_pushdown_set_distinct_as_top(child, + set_keys, + MERGE_AGGREGATE, + table_meta, + should_pullup_gi, + is_partition_gi))) { + LOG_WARN("failed to allocate distinct as top", K(ret)); + } else { + prefix_pos = 0; + need_sort = false; + } + return ret; +} + int ObSelectLogPlan::allocate_distinct_set_as_top(ObLogicalOperator *left_child, ObLogicalOperator *right_child, SetAlgo set_method, @@ -4758,6 +5032,8 @@ int ObSelectLogPlan::generate_child_plan_for_set(const ObDMLStmt *sub_stmt, } else if (FALSE_IT(sub_plan->set_is_parent_set_distinct(is_set_distinct)) || FALSE_IT(sub_plan->set_nonrecursive_plan_for_fake_cte(nonrecursive_plan))) { // do nothing + } else if (OB_FAIL(sub_plan->init_rescan_info_for_subquery_paths(*this, false, false))) { + LOG_WARN("failed to init rescan info", K(ret)); } else if (OB_FAIL(sub_plan->add_pushdown_filters(pushdown_filters))) { LOG_WARN("failed to add pushdown filters", K(ret)); } else if (OB_FAIL(sub_plan->generate_raw_plan())) { diff --git a/src/sql/optimizer/ob_select_log_plan.h b/src/sql/optimizer/ob_select_log_plan.h index 88e0710582..c73a679b23 100644 --- a/src/sql/optimizer/ob_select_log_plan.h +++ b/src/sql/optimizer/ob_select_log_plan.h @@ -221,7 +221,10 @@ private: int generate_union_all_plans(const ObIArray &child_plans, const bool ignore_hint, ObIArray &all_plans); - + int get_best_child_candidate_plans(const ObIArray &child_plans, + ObIArray &best_child_ops, + ObIArray &best_das_child_ops, + ObIArray &best_px_child_ops); int create_union_all_plan(const ObIArray &child_plans, const bool ignore_hint, ObLogicalOperator *&top); @@ -383,13 +386,31 @@ private: const ObIArray &order_directions, const ObIArray &map_array, const ObIArray &left_sort_keys, - const bool left_need_sort, - const int64_t left_prefix_pos, + bool left_need_sort, + int64_t left_prefix_pos, const ObIArray &right_sort_keys, - const bool right_need_sort, - const int64_t right_prefix_pos, + bool right_need_sort, + int64_t right_prefix_pos, CandidatePlan &merge_plan); + int check_need_pushdown_set_distinct(ObLogicalOperator *&child, + const ObIArray &set_keys, + bool &is_valid); + + int allocate_pushdown_set_distinct_as_top(ObLogicalOperator *&child, + const ObIArray &set_keys, + AggregateAlgo algo, + const OptTableMeta *table_meta, + bool is_partition_wise = false, + bool is_partition_gi = false); + + int allocate_pushdown_merge_set_distinct_as_top(ObLogicalOperator *&child, + const ObIArray &set_keys, + const ObIArray &sort_keys, + const OptTableMeta *table_meta, + bool &need_sort, + int64_t &prefix_pos); + int allocate_distinct_set_as_top(ObLogicalOperator *left_child, ObLogicalOperator *right_child, SetAlgo set_method, diff --git a/src/sql/optimizer/ob_sharding_info.cpp b/src/sql/optimizer/ob_sharding_info.cpp index a830222d06..2ea635d7f6 100644 --- a/src/sql/optimizer/ob_sharding_info.cpp +++ b/src/sql/optimizer/ob_sharding_info.cpp @@ -93,14 +93,14 @@ int ObShardingInfo::init_partition_info(ObOptimizerContext &ctx, LOG_WARN("There is no part expr in stmt", K(table_id), K(ret)); } else if (OB_FAIL(part_func_exprs_.push_back(part_expr))) { LOG_WARN("Failed to push back to part expr"); - } else if (OB_FAIL(set_partition_key(part_expr, part_func_type_, partition_keys_))) { + } else if (OB_FAIL(get_partition_key(part_expr, part_func_type_, partition_keys_))) { LOG_WARN("Failed to set partition key", K(ret), K(table_id), K(ref_table_id)); } else if (PARTITION_LEVEL_TWO == part_level_) { subpart_func_type_ = table_schema->get_sub_part_option().get_part_func_type(); if (OB_ISNULL(subpart_expr = stmt.get_subpart_expr(table_id, ref_table_id))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("There is no subpart expr in stmt", K(ret)); - } else if (OB_FAIL(set_partition_key(subpart_expr, subpart_func_type_, sub_partition_keys_))) { + } else if (OB_FAIL(get_partition_key(subpart_expr, subpart_func_type_, sub_partition_keys_))) { LOG_WARN("Failed to set sub partition key", K(ret), K(table_id), K(ref_table_id)); } else if (OB_FAIL(part_func_exprs_.push_back(subpart_expr))) { LOG_WARN("Failed to set key partition func", K(ret), K(table_id), K(ref_table_id)); @@ -130,7 +130,50 @@ int ObShardingInfo::init_partition_info(ObOptimizerContext &ctx, return ret; } -int ObShardingInfo::set_partition_key( +int ObShardingInfo::get_all_partition_key(ObOptimizerContext &ctx, + const ObDMLStmt &stmt, + const uint64_t table_id, + const uint64_t ref_table_id, + ObIArray &all_partition_keys) +{ + int ret = OB_SUCCESS; + all_partition_keys.reuse(); + ObSqlSchemaGuard *schema_guard = NULL; + const ObTableSchema *table_schema = NULL; + ObRawExpr *part_expr = NULL; + if (OB_ISNULL(schema_guard = ctx.get_sql_schema_guard())) { + ret = OB_SCHEMA_ERROR; + LOG_WARN("failed to get table schema", K(ref_table_id)); + } else if (OB_FAIL(schema_guard->get_table_schema(table_id, ref_table_id, &stmt, table_schema))) { + ret = OB_SCHEMA_ERROR; + LOG_WARN("failed to get table schema", K(ref_table_id)); + } else if (OB_ISNULL(table_schema)) { + ret = OB_SCHEMA_ERROR; + LOG_WARN("failed to get table schema", K(ref_table_id)); + } else if (PARTITION_LEVEL_ONE != table_schema->get_part_level() + && PARTITION_LEVEL_TWO != table_schema->get_part_level()) { + /* do nohitng */ + } else if (OB_ISNULL(part_expr = stmt.get_part_expr(table_id, ref_table_id))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("There is no part expr in stmt", K(table_id), K(ret)); + } else if (OB_FAIL(get_partition_key(part_expr, + table_schema->get_part_option().get_part_func_type(), + all_partition_keys))) { + LOG_WARN("Failed to get partition key", K(ret), K(table_id), K(ref_table_id)); + } else if (PARTITION_LEVEL_TWO != table_schema->get_part_level()) { + /* do nohitng */ + } else if (OB_ISNULL(part_expr = stmt.get_subpart_expr(table_id, ref_table_id))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("There is no subpart expr in stmt", K(ret)); + } else if (OB_FAIL(get_partition_key(part_expr, + table_schema->get_sub_part_option().get_part_func_type(), + all_partition_keys))) { + LOG_WARN("Failed to get sub partition key", K(ret), K(table_id), K(ref_table_id)); + } + return ret; +} + +int ObShardingInfo::get_partition_key( ObRawExpr *part_expr, const ObPartitionFuncType part_func_type, ObIArray &partition_keys) diff --git a/src/sql/optimizer/ob_sharding_info.h b/src/sql/optimizer/ob_sharding_info.h index 8dcf67e552..bcf54a2edb 100644 --- a/src/sql/optimizer/ob_sharding_info.h +++ b/src/sql/optimizer/ob_sharding_info.h @@ -322,6 +322,11 @@ public: int copy_without_part_keys(const ObShardingInfo &other); int get_remote_addr(ObAddr &remote) const; int get_total_part_cnt(int64_t &total_part_cnt) const; + static int get_all_partition_key(ObOptimizerContext &ctx, + const ObDMLStmt &stmt, + const uint64_t table_id, + const uint64_t ref_table_id, + ObIArray &all_partition_keys); TO_STRING_KV(K_(part_level), K_(part_func_type), K_(subpart_func_type), @@ -331,10 +336,9 @@ public: K_(phy_table_location_info)); private: - int set_partition_key(ObRawExpr *part_expr, - const share::schema::ObPartitionFuncType part_func_type, - common::ObIArray &partition_keys); - + static int get_partition_key(ObRawExpr *part_expr, + const share::schema::ObPartitionFuncType part_func_type, + common::ObIArray &partition_keys); // check whether all partition keys are of the same type static int is_compatible_partition_key(const ObShardingInfo *first_sharding, const ObIArray> &first_part_keys_list, diff --git a/src/sql/parser/parse_node.c b/src/sql/parser/parse_node.c index 0ab33cd663..b16e315917 100644 --- a/src/sql/parser/parse_node.c +++ b/src/sql/parser/parse_node.c @@ -884,14 +884,18 @@ int64_t get_need_reserve_capacity(int64_t n) ParseNode *push_back_child(void *malloc_pool, int *error_code, ParseNode *left_node, ParseNode *node) { ParseNode *ret_node = NULL; - if (OB_ISNULL(malloc_pool) || OB_ISNULL(error_code)) { + if (OB_ISNULL(error_code)) { (void)fprintf(stderr, "ERROR parser result is NULL\n"); - } else if (NULL == left_node || NULL == node) { - /* do nothing */ - } else if ((left_node->type_ != T_OP_OR && - left_node->type_ != T_OP_AND && - left_node->type_ != T_EXPR_LIST) || - left_node->value_ == INT64_MAX) { + } else if (OB_ISNULL(malloc_pool) || + OB_ISNULL(left_node) || + OB_ISNULL(node) || + OB_UNLIKELY(INT64_MAX == left_node->value_)) { + *error_code = OB_PARSER_ERR_UNEXPECTED; + } else if (OB_UNLIKELY(!(T_OP_OR == left_node->type_ || + T_OP_AND == left_node->type_ || + T_EXPR_LIST == left_node->type_ || + T_SET_UNION == left_node->type_ || + T_SET_UNION_ALL == left_node->type_))) { *error_code = OB_PARSER_ERR_UNEXPECTED; } else { int64_t capacity = get_need_reserve_capacity(left_node->num_child_ + 1); @@ -919,14 +923,18 @@ ParseNode *push_back_child(void *malloc_pool, int *error_code, ParseNode *left_n ParseNode *push_front_child(void *malloc_pool, int *error_code, ParseNode *right_node, ParseNode *node) { ParseNode *ret_node = NULL; - if (OB_ISNULL(malloc_pool) || OB_ISNULL(error_code)) { + if (OB_ISNULL(error_code)) { (void)fprintf(stderr, "ERROR parser result is NULL\n"); - } else if (NULL == right_node || NULL == node) { - /* do nothing */ - } else if ((right_node->type_ != T_OP_OR && - right_node->type_ != T_OP_AND && - right_node->type_ != T_EXPR_LIST) || - right_node->value_ == INT64_MAX) { + } else if (OB_ISNULL(malloc_pool) || + OB_ISNULL(right_node) || + OB_ISNULL(node) || + OB_UNLIKELY(INT64_MAX == right_node->value_)) { + *error_code = OB_PARSER_ERR_UNEXPECTED; + } else if (OB_UNLIKELY(!(T_OP_OR == right_node->type_ || + T_OP_AND == right_node->type_ || + T_EXPR_LIST == right_node->type_ || + T_SET_UNION == right_node->type_ || + T_SET_UNION_ALL == right_node->type_))) { *error_code = OB_PARSER_ERR_UNEXPECTED; } else { int64_t capacity = get_need_reserve_capacity(right_node->num_child_ + 1); @@ -948,17 +956,21 @@ ParseNode *push_front_child(void *malloc_pool, int *error_code, ParseNode *right ParseNode *append_child(void *malloc_pool, int *error_code, ParseNode *left_node, ParseNode *right_node) { ParseNode *ret_node = NULL; - if (OB_ISNULL(malloc_pool) || OB_ISNULL(error_code)) { + if (OB_ISNULL(error_code)) { (void)fprintf(stderr, "ERROR parser result is NULL\n"); - } else if (NULL == left_node || NULL == right_node) { - /* do nothing */ - } else if (left_node->type_ != right_node->type_ || - (left_node->type_ != T_OP_OR && - left_node->type_ != T_OP_AND && - left_node->type_ != T_EXPR_LIST) || - left_node->value_ == INT64_MAX || - right_node->value_ == INT64_MAX) { + } else if (OB_ISNULL(malloc_pool) || + OB_ISNULL(left_node) || + OB_ISNULL(right_node) || + OB_UNLIKELY(INT64_MAX == left_node->value_ || INT64_MAX == right_node->value_) || + OB_UNLIKELY(left_node->type_ != right_node->type_)) { *error_code = OB_PARSER_ERR_UNEXPECTED; + } else if (OB_UNLIKELY(!(T_OP_OR == left_node->type_ || + T_OP_AND == left_node->type_ || + T_EXPR_LIST == left_node->type_ || + T_SET_UNION == left_node->type_ || + T_SET_UNION_ALL == left_node->type_))) { + *error_code = OB_PARSER_ERR_UNEXPECTED; + } else { int64_t num_child = left_node->num_child_ + right_node->num_child_; int64_t capacity = get_need_reserve_capacity(num_child); @@ -1005,3 +1017,24 @@ ParseNode *adjust_inner_join_inner(int *error_code, ParseNode *inner_join, Parse } return ret_node; } + +ParseNodeOptParens *new_parse_node_opt_parens(void *malloc) +{ + ParseNodeOptParens *new_node = (ParseNodeOptParens *)parse_malloc(sizeof(ParseNodeOptParens), malloc); + if (NULL == new_node) { + (void)printf("ERROR malloc memory failed\n"); + } else { + new_node->select_node_ = NULL; + new_node->is_parenthesized_ = false; + } + return new_node; +} + +extern int ob_backtrace_c(void **buffer, int size); +extern char *parray_c(char *buf, int64_t len, int64_t *array, int size); +char *parser_lbt(void **addr_buff, const size_t addr_size, + char *str_buff, const size_t str_size) +{ + int size = ob_backtrace_c(addr_buff, addr_size); + return parray_c(str_buff, str_size, (int64_t *)addr_buff, size); +} diff --git a/src/sql/parser/parse_node.h b/src/sql/parser/parse_node.h index 3656d6c456..665a4a1fcb 100644 --- a/src/sql/parser/parse_node.h +++ b/src/sql/parser/parse_node.h @@ -271,6 +271,11 @@ typedef struct _ParenthesesOffset struct _ParenthesesOffset *next_; } ParenthesesOffset; +typedef struct _ParseNodeOptParens { + struct _ParseNode *select_node_; + bool is_parenthesized_; +} ParseNodeOptParens; + //dml base runtime context definition typedef struct _InsMultiValuesResult { @@ -421,6 +426,7 @@ extern ParseNode *push_back_child(void *malloc_pool, int *error_code, ParseNode extern ParseNode *push_front_child(void *malloc_pool, int *error_code, ParseNode *right_node, ParseNode *node); extern ParseNode *append_child(void *malloc_pool, int *error_code, ParseNode *left_node, ParseNode *right_node); extern ParseNode *adjust_inner_join_inner(int *error_code, ParseNode *inner_join, ParseNode *table_node); +extern ParseNodeOptParens *new_parse_node_opt_parens(void *malloc_pool); // compare ParseNode str_value_ to pattern // @param [in] node ParseNode diff --git a/src/sql/parser/sql_parser_base.h b/src/sql/parser/sql_parser_base.h index 9a83f1e656..5637cbfe4a 100644 --- a/src/sql/parser/sql_parser_base.h +++ b/src/sql/parser/sql_parser_base.h @@ -1319,4 +1319,111 @@ do {\ } \ } while (0); \ +#define malloc_select_set_body(body_node, result, select_node, is_parenthesized) \ + do { \ + body_node = new_parse_node_opt_parens(result->malloc_pool_); \ + if (NULL == body_node) { \ + yyerror(NULL, result, "No more space for alloc node"); \ + YYABORT_NO_MEMORY; \ + } else { \ + body_node->select_node_ = select_node; \ + body_node->is_parenthesized_ = is_parenthesized; \ + } \ + } while(0); \ + +#define refine_recursive_cte_list(with_list, result) \ + do { \ + ParseNode *subquery = NULL; \ + ParseNode *set_node = NULL; \ + if (NULL == with_list) { \ + yyerror(NULL, result, "got NULL ptr"); \ + YYABORT_UNEXPECTED; \ + } else { \ + for (int64_t i = 0; i < with_list->num_child_; i++) { \ + if (OB_NOT_NULL(subquery = with_list->children_[i]->children_[2]) && \ + OB_NOT_NULL(set_node = subquery->children_[PARSE_SELECT_SET]) && \ + 2 < set_node->num_child_) { \ + int64_t num_child = set_node->num_child_; \ + ParseNode *right_node = set_node->children_[num_child - 1]; \ + ParseNode *left_node = NULL; \ + malloc_select_node(left_node, result->malloc_pool_); \ + if (NULL == left_node) { \ + yyerror(NULL, result, "No more space for alloc node"); \ + YYABORT_NO_MEMORY; \ + } else { \ + set_node->num_child_ = num_child - 1; \ + left_node->children_[PARSE_SELECT_SET] = set_node; \ + ParseNode *new_set_node = NULL; \ + malloc_non_terminal_node(new_set_node, result->malloc_pool_, set_node->type_, 2, left_node, right_node); \ + subquery->children_[PARSE_SELECT_SET] = new_set_node; \ + } \ + } \ + } \ + } \ + } while(0); \ + +#define flatten_set_op(result, select_node, left_paren, right_paren, set_node) \ + do { \ + ParseNode *left_body = NULL; \ + ParseNode *right_body = NULL; \ + select_node = NULL; \ + if (OB_ISNULL(result) || OB_ISNULL(left_paren) || OB_ISNULL(right_paren) || \ + OB_ISNULL(left_body = left_paren->select_node_) || OB_UNLIKELY(T_SELECT != left_body->type_) || \ + OB_ISNULL(right_body = right_paren->select_node_) || OB_UNLIKELY(T_SELECT != right_body->type_) || \ + OB_ISNULL(set_node) || OB_UNLIKELY(2 != set_node->num_child_)) { \ + yyerror(NULL, result, "param is unexpected\n"); \ + YYABORT_UNEXPECTED; \ + } else { \ + ParseNode *left = left_body->children_[PARSE_SELECT_SET]; \ + ParseNode *right = right_body->children_[PARSE_SELECT_SET]; \ + bool is_left_same = !left_paren->is_parenthesized_ && left != NULL && left->type_ == set_node->type_ && \ + (left->type_ == T_SET_UNION || left->type_ == T_SET_UNION_ALL) && \ + left_body->children_[PARSE_SELECT_ORDER] == NULL && \ + left_body->children_[PARSE_SELECT_LIMIT] == NULL && \ + left_body->children_[PARSE_SELECT_FETCH] == NULL; \ + bool is_right_same = !right_paren->is_parenthesized_ && right != NULL && right->type_ == set_node->type_ && \ + (right->type_ == T_SET_UNION || right->type_ == T_SET_UNION_ALL) && \ + right_body->children_[PARSE_SELECT_ORDER] == NULL && \ + right_body->children_[PARSE_SELECT_LIMIT] == NULL && \ + right_body->children_[PARSE_SELECT_FETCH] == NULL; \ + if (!is_left_same && !is_right_same) { \ + set_node->children_[0] = left_body; \ + set_node->children_[1] = right_body; \ + set_node->value_ = 2; \ + select_node = new_non_terminal_node(result->malloc_pool_, T_SELECT, PARSE_SELECT_MAX_IDX, NULL, NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL, NULL, NULL, \ + NULL, NULL, NULL); \ + if (OB_ISNULL(select_node)) { \ + if (OB_PARSER_SUCCESS == result->extra_errno_) { \ + result->extra_errno_ = OB_PARSER_ERR_NO_MEMORY; \ + } \ + yyerror(NULL, result, "No more space for malloc\n"); \ + YYABORT_NO_MEMORY; \ + } else { \ + select_node->children_[PARSE_SELECT_SET] = set_node; \ + } \ + } else { \ + if (is_left_same && is_right_same) { \ + select_node = left_body; \ + select_node->children_[PARSE_SELECT_SET] = append_child(result->malloc_pool_, &result->extra_errno_, left, right); \ + } else if (is_left_same) { \ + select_node = left_body; \ + select_node->children_[PARSE_SELECT_SET] = push_back_child(result->malloc_pool_, &result->extra_errno_, left, right_body); \ + } else if (is_right_same) { \ + select_node = right_body; \ + select_node->children_[PARSE_SELECT_SET] = push_front_child(result->malloc_pool_, &result->extra_errno_, right, left_body); \ + } \ + if (OB_ISNULL(select_node->children_[PARSE_SELECT_SET])) { \ + if (OB_PARSER_SUCCESS == result->extra_errno_) { \ + result->extra_errno_ = OB_PARSER_ERR_NO_MEMORY; \ + } \ + yyerror(NULL, result, "No more space for malloc\n"); \ + YYABORT_NO_MEMORY; \ + } \ + } \ + } \ + } while (0); \ + #endif /* OCEANBASE_SRC_SQL_PARSER_SQL_PARSER_BASE_H_ */ diff --git a/src/sql/parser/sql_parser_mysql_mode.l b/src/sql/parser/sql_parser_mysql_mode.l index 38f9537c04..9b8dd1479a 100644 --- a/src/sql/parser/sql_parser_mysql_mode.l +++ b/src/sql/parser/sql_parser_mysql_mode.l @@ -1061,6 +1061,8 @@ Timestamp{whitespace}?\"[^\"]*\" { WF_TOPN { return WF_TOPN; } USE_LATE_MATERIALIZATION { return USE_LATE_MATERIALIZATION; } NO_USE_LATE_MATERIALIZATION { return NO_USE_LATE_MATERIALIZATION; } +TRANSFORM_DISTINCT_AGG { return TRANSFORM_DISTINCT_AGG; } +NO_TRANSFORM_DISTINCT_AGG { return NO_TRANSFORM_DISTINCT_AGG; } TRACE_LOG { return TRACE_LOG; } LOAD_BATCH_SIZE { return LOAD_BATCH_SIZE; } NO_DIRECT { return NO_DIRECT; } diff --git a/src/sql/parser/sql_parser_mysql_mode.y b/src/sql/parser/sql_parser_mysql_mode.y index 6e3fce475b..f520cc4be0 100644 --- a/src/sql/parser/sql_parser_mysql_mode.y +++ b/src/sql/parser/sql_parser_mysql_mode.y @@ -26,6 +26,7 @@ const struct _NonReservedKeyword *non_reserved_keyword; const struct _NonReservedKeyword *reserved_keyword; int32_t ival[2]; //ival[0]表示value, ival[1]表示fast parse在对应的该node及其子node可识别的常量个数 + struct _ParseNodeOptParens *node_opt_parens; } %{ @@ -179,7 +180,7 @@ COALESCE_SQ NO_COALESCE_SQ COUNT_TO_EXISTS NO_COUNT_TO_EXISTS LEFT_TO_ANTI NO_LE ELIMINATE_JOIN NO_ELIMINATE_JOIN PUSH_LIMIT NO_PUSH_LIMIT PULLUP_EXPR NO_PULLUP_EXPR WIN_MAGIC NO_WIN_MAGIC AGGR_FIRST_UNNEST NO_AGGR_FIRST_UNNEST JOIN_FIRST_UNNEST NO_JOIN_FIRST_UNNEST COALESCE_AGGR NO_COALESCE_AGGR WITH_PULLUP WO_PULLUP -MV_REWRITE NO_MV_REWRITE +MV_REWRITE NO_MV_REWRITE TRANSFORM_DISTINCT_AGG NO_TRANSFORM_DISTINCT_AGG DECORRELATE NO_DECORRELATE // optimize hint INDEX_HINT FULL_HINT NO_INDEX_HINT USE_DAS_HINT NO_USE_DAS_HINT UNION_MERGE_HINT @@ -419,7 +420,7 @@ END_P SET_VAR DELIMITER %type data_type special_table_type opt_if_not_exists opt_if_exists opt_charset collation opt_collation cast_data_type %type replace_with_opt_hint insert_with_opt_hint column_list opt_on_duplicate_key_clause opt_into opt_replace opt_temporary opt_algorithm opt_sql_security opt_definer view_algorithm no_param_column_ref %type insert_vals_list insert_vals value_or_values opt_insert_row_alias -%type select_with_parens select_no_parens select_clause select_into no_table_select_with_order_and_limit simple_select_with_order_and_limit select_with_parens_with_order_and_limit select_clause_set select_clause_set_left select_clause_set_right select_clause_set_with_order_and_limit +%type select_with_parens select_no_parens select_clause select_into no_table_select_with_order_and_limit simple_select_with_order_and_limit select_with_parens_with_order_and_limit select_clause_set_with_order_and_limit %type simple_select no_table_select limit_clause select_expr_list opt_approx %type with_select with_clause with_list common_table_expr opt_column_alias_name_list alias_name_list column_alias_name %type opt_where opt_hint_value opt_groupby opt_rollup opt_order_by order_by opt_having groupby_clause @@ -479,9 +480,9 @@ END_P SET_VAR DELIMITER %type drop_mlog_stmt %type unreserved_keyword unreserved_keyword_normal unreserved_keyword_special unreserved_keyword_extra unreserved_keyword_ambiguous_roles unreserved_keyword_for_role_name %type mysql_reserved_keyword -%type set_type_other set_type_union audit_by_session_access_option audit_whenever_option audit_or_noaudit +%type audit_by_session_access_option audit_whenever_option audit_or_noaudit %type consistency_level use_plan_cache_type -%type set_type set_expression_option +%type set_type %type drop_index_stmt hint_options opt_expr_as_list expr_as_list expr_with_opt_alias substr_params opt_comma substr_or_substring %type /*frozen_type*/ opt_binary %type ip_port @@ -566,6 +567,8 @@ END_P SET_VAR DELIMITER %type any_expr %type opt_empty_table_list opt_repair_mode opt_repair_option_list repair_option repair_option_list opt_checksum_option %type cache_index_stmt load_index_into_cache_stmt tbl_index_list tbl_index tbl_partition_list opt_tbl_partition_list tbl_index_or_partition_list tbl_index_or_partition opt_ignore_leaves key_cache_name +%type select_clause_set select_clause_set_body + %start sql_stmt %% //////////////////////////////////////////////////////////////// @@ -10434,7 +10437,7 @@ select_clause opt_lock_type } | select_clause_set opt_lock_type { - $$ = $1; + $$ = $1->select_node_; $$->children_[PARSE_SELECT_FOR_UPD] = $2; } | select_clause_set_with_order_and_limit opt_lock_type @@ -10532,60 +10535,93 @@ no_table_select select_clause_set_with_order_and_limit: select_clause_set order_by { - $$ = $1; + $$ = $1->select_node_; $$->children_[PARSE_SELECT_ORDER] = $2; } | select_clause_set opt_order_by limit_clause { - $$ = $1; + $$ = $1->select_node_; $$->children_[PARSE_SELECT_ORDER] = $2; $$->children_[PARSE_SELECT_LIMIT] = $3; } ; select_clause_set: -select_clause_set set_type select_clause_set_right +select_clause_set set_type select_clause_set_body { ParseNode *select_node = NULL; - malloc_select_node(select_node, result->malloc_pool_); - select_node->children_[PARSE_SELECT_SET] = $2; - select_node->children_[PARSE_SELECT_FORMER] = $1; - select_node->children_[PARSE_SELECT_LATER] = $3; - $$ = select_node; + flatten_set_op(result, select_node, $1, $3, $2); + if (OB_ISNULL(select_node)) { + yyerror(NULL, result, "No more space for flatten set op"); + YYABORT_NO_MEMORY; + } else { + $$ = $1; + $$->select_node_ = select_node; + $$->is_parenthesized_ = false; + } } -| select_clause_set_left set_type select_clause_set_right { +| select_clause_set_body set_type select_clause_set_body +{ ParseNode *select_node = NULL; - malloc_select_node(select_node, result->malloc_pool_); - select_node->children_[PARSE_SELECT_SET] = $2; - select_node->children_[PARSE_SELECT_FORMER] = $1; - select_node->children_[PARSE_SELECT_LATER] = $3; - $$ = select_node; + flatten_set_op(result, select_node, $1, $3, $2); + if (OB_ISNULL(select_node)) { + yyerror(NULL, result, "No more space for flatten set op"); + YYABORT_NO_MEMORY; + } else { + $$ = $1; + $$->select_node_ = select_node; + $$->is_parenthesized_ = false; + } } ; -select_clause_set_right: +select_clause_set_body: no_table_select { - $$ = $1; + malloc_select_set_body($$, result, $1, false); } | simple_select { - $$ = $1; + malloc_select_set_body($$, result, $1, false); } | select_with_parens %prec LOWER_PARENS { - $$ = $1; + malloc_select_set_body($$, result, $1, true); } | table_values_clause { - $$ = $1; + malloc_select_set_body($$, result, $1, false); } ; -select_clause_set_left: -select_clause_set_right +set_type: +UNION /* EMPTY */ { - $$ = $1; + malloc_non_terminal_node($$, result->malloc_pool_, T_SET_UNION, 2, NULL, NULL); +} +| UNION ALL +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_SET_UNION_ALL, 2, NULL, NULL); +} +| UNION DISTINCT +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_SET_UNION, 2, NULL, NULL); +} +| UNION UNIQUE +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_SET_UNION, 2, NULL, NULL); +} +| INTERSECT +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_SET_INTERSECT, 2, NULL, NULL); +} +| EXCEPT +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_SET_EXCEPT, 2, NULL, NULL); +} +| MINUS +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_SET_EXCEPT, 2, NULL, NULL); } ; @@ -10766,43 +10802,6 @@ opt_where opt_groupby opt_having opt_named_windows } ; -set_type_union: -UNION { $$[0] = T_SET_UNION; } -; - -set_type_other: -INTERSECT { $$[0] = T_SET_INTERSECT; } -| EXCEPT { $$[0] = T_SET_EXCEPT; } -| MINUS { $$[0] = T_SET_EXCEPT; } -; - -set_type: -set_type_union set_expression_option -{ - malloc_non_terminal_node($$, result->malloc_pool_, $1[0], 1, $2); -} -| set_type_other -{ - malloc_non_terminal_node($$, result->malloc_pool_, $1[0], 1, NULL); -} - -set_expression_option: -/* EMPTY */ -{ $$ = NULL; } -| ALL -{ - malloc_terminal_node($$, result->malloc_pool_, T_ALL); -} -| DISTINCT -{ - malloc_terminal_node($$, result->malloc_pool_, T_DISTINCT); -} -| UNIQUE -{ - malloc_terminal_node($$, result->malloc_pool_, T_DISTINCT); -} -; - opt_where: /* EMPTY */ {$$ = NULL;} @@ -11658,6 +11657,14 @@ NO_REWRITE opt_qb_name { malloc_non_terminal_node($$, result->malloc_pool_, T_NO_USE_LATE_MATERIALIZATION, 1, $2); } +| TRANSFORM_DISTINCT_AGG opt_qb_name +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_TRANSFORM_DISTINCT_AGG, 1, $2); +} +| NO_TRANSFORM_DISTINCT_AGG opt_qb_name +{ + malloc_non_terminal_node($$, result->malloc_pool_, T_NO_TRANSFORM_DISTINCT_AGG, 1, $2); +} ; multi_qb_name_list: @@ -13976,6 +13983,7 @@ WITH RECURSIVE with_list { ParseNode *with_list = NULL; merge_nodes(with_list, result, T_WITH_CLAUSE_LIST, $3); + refine_recursive_cte_list(with_list, result); $$ = with_list; $$->value_ = 1; } diff --git a/src/sql/plan_cache/ob_plan_cache_value.cpp b/src/sql/plan_cache/ob_plan_cache_value.cpp index 42e4d979f6..63b867608a 100644 --- a/src/sql/plan_cache/ob_plan_cache_value.cpp +++ b/src/sql/plan_cache/ob_plan_cache_value.cpp @@ -503,7 +503,7 @@ int ObPlanCacheValue::choose_plan(ObPlanCacheCtx &pc_ctx, } else if (FALSE_IT(session->set_stmt_type(stmt_type_))) { } else if (OB_FAIL(session->get_spm_mode(spm_mode))) { LOG_WARN("fail to get spm mode", K(ret)); - } else if (spm_mode > 0) { + } else if (spm_mode > SPM_MODE_DISABLE) { if (OB_FAIL(ob_write_string(pc_ctx.allocator_, constructed_sql_, pc_ctx.sql_ctx_.spm_ctx_.bl_key_.constructed_sql_))) { diff --git a/src/sql/resolver/dml/ob_del_upd_resolver.cpp b/src/sql/resolver/dml/ob_del_upd_resolver.cpp index ab8a98f991..1f52797c21 100644 --- a/src/sql/resolver/dml/ob_del_upd_resolver.cpp +++ b/src/sql/resolver/dml/ob_del_upd_resolver.cpp @@ -356,7 +356,9 @@ int ObDelUpdResolver::resolve_column_and_values(const ParseNode &assign_list, LOG_WARN("failed to assign '' to date time", K(ret)); } OZ (c_expr->add_flag(IS_TABLE_ASSIGN)); + ObObj val = c_expr->get_result_type().get_param(); OX (c_expr->set_result_type(col_expr->get_result_type())); + OX (c_expr->set_param(val)); if (col_expr->get_result_type().get_obj_meta().is_collection_sql_type() && col_expr->get_enum_set_values().count() > 0) { // array type diff --git a/src/sql/resolver/dml/ob_dml_resolver.cpp b/src/sql/resolver/dml/ob_dml_resolver.cpp index a7c7434c27..cbac0a5799 100755 --- a/src/sql/resolver/dml/ob_dml_resolver.cpp +++ b/src/sql/resolver/dml/ob_dml_resolver.cpp @@ -1833,6 +1833,8 @@ int ObDMLResolver::resolve_sql_expr(const ParseNode &node, ObRawExpr *&expr, LOG_WARN("Failed to check and remove outer join symbol", K(ret)); } else if (OB_FAIL(resolve_special_expr(expr, current_scope_))) { LOG_WARN("resolve special expression failed", K(ret)); + } else if (OB_FAIL(expr->calc_hash())) { + LOG_WARN("failed to calc expr hash", K(ret), KPC(expr)); } } if (OB_SUCC(ret) && @@ -14873,7 +14875,9 @@ int ObDMLResolver::resolve_transform_hint(const ParseNode &hint_node, case T_DECORRELATE: case T_NO_DECORRELATE: case T_USE_LATE_MATERIALIZATION: - case T_NO_USE_LATE_MATERIALIZATION: { + case T_NO_USE_LATE_MATERIALIZATION: + case T_TRANSFORM_DISTINCT_AGG: + case T_NO_TRANSFORM_DISTINCT_AGG: { if (OB_FAIL(resolve_normal_transform_hint(hint_node, trans_hint))) { LOG_WARN("failed to resolve hint with qb name param.", K(ret)); } @@ -17949,6 +17953,7 @@ int ObDMLResolver::compute_values_table_row_count(ObValuesTableDef &table_def) table_def.start_param_idx_ = param_idx; param_expr = static_cast(expr2); table_def.end_param_idx_ = param_expr->get_value().get_unknown(); + table_def.is_const_ = true; } } } diff --git a/src/sql/resolver/dml/ob_dml_resolver.h b/src/sql/resolver/dml/ob_dml_resolver.h index ad9c1b2417..8aeb560e98 100644 --- a/src/sql/resolver/dml/ob_dml_resolver.h +++ b/src/sql/resolver/dml/ob_dml_resolver.h @@ -90,7 +90,6 @@ class ObDMLResolver : public ObStmtResolver public: ObCteResolverCtx(): left_select_stmt_(NULL), - left_select_stmt_parse_node_(NULL), opt_col_alias_parse_node_(NULL), is_with_clause_resolver_(false), current_cte_table_name_(""), @@ -119,17 +118,15 @@ class ObDMLResolver : public ObStmtResolver inline void reset_subquery_level() { cte_resolve_level_ = 0; } inline bool is_recursive() const { return is_recursive_cte_; } inline void set_left_select_stmt(ObSelectStmt* left_stmt) { left_select_stmt_ = left_stmt; } - inline void set_left_parse_node(const ParseNode* node) { left_select_stmt_parse_node_ = node; } inline void set_set_all(bool all) { is_set_all_ = all; } inline bool invalid_recursive_union() { return (nullptr != left_select_stmt_ && !is_set_all_); } inline bool more_than_two_branch() { return cte_branch_count_ >= 2; } inline void reset_branch_count() { cte_branch_count_ = 0; } inline void set_recursive_left_branch() { is_set_left_resolver_ = true; cte_branch_count_ ++; } - inline void set_recursive_right_branch(ObSelectStmt* left_stmt, const ParseNode* node, bool all) { + inline void set_recursive_right_branch(ObSelectStmt* left_stmt, bool all) { is_set_left_resolver_ = false; cte_branch_count_ ++; left_select_stmt_ = left_stmt; - left_select_stmt_parse_node_ = node; is_set_all_ = all; } inline void set_has_param_list(bool has) { has_cte_param_list_ = has; } @@ -138,7 +135,6 @@ class ObDMLResolver : public ObStmtResolver inline bool check_has_recursive_word() const { return has_recursive_word_; } int assign(ObCteResolverCtx &cte_ctx) { left_select_stmt_ = cte_ctx.left_select_stmt_; - left_select_stmt_parse_node_ = cte_ctx.left_select_stmt_parse_node_; opt_col_alias_parse_node_ = cte_ctx.opt_col_alias_parse_node_; is_with_clause_resolver_ = cte_ctx.is_with_clause_resolver_; current_cte_table_name_ = cte_ctx.current_cte_table_name_; @@ -162,7 +158,6 @@ class ObDMLResolver : public ObStmtResolver K_(has_recursive_word)); private: ObSelectStmt* left_select_stmt_; - const ParseNode* left_select_stmt_parse_node_; const ParseNode* opt_col_alias_parse_node_; bool is_with_clause_resolver_; ObString current_cte_table_name_; diff --git a/src/sql/resolver/dml/ob_dml_stmt.cpp b/src/sql/resolver/dml/ob_dml_stmt.cpp index 695e76f22b..30c5bde0a9 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.cpp +++ b/src/sql/resolver/dml/ob_dml_stmt.cpp @@ -1974,6 +1974,140 @@ int ObDMLStmt::formalize_child_stmt_expr_reference(ObRawExprFactory *expr_factor return ret; } + +/** + * @brief ObDMLStmt::formalize_implicit_distinct + * + * 1. Check current stmt is legal for implicit distinct (only for ObSelectStmt) + * 2. Set implicit distinct for subquery + */ +int ObDMLStmt::formalize_implicit_distinct() +{ + int ret = OB_SUCCESS; + if (OB_FAIL(formalize_implicit_distinct_for_subquery())) { + LOG_WARN("failed to set implicit distinct for subquery", K(ret)); + } + return ret; +} + +/** + * @brief ObDMLStmt::formalize_implicit_distinct_for_subquery + * + * Set implicit distinct for subquery + * 1. If stmt is FROM dup insensitive, set implicit distinct for FROM subquery + * 2. Set implicit distinct for semi right subquery + * 3. Set implicit distinct for exists, any, all subquery + * 4. Recursive set implicit distinct for subquery + */ +int ObDMLStmt::formalize_implicit_distinct_for_subquery() { + int ret = OB_SUCCESS; + bool is_from_dul_insene = false; + ObSEArray all_child_stmts; + ObSEArray from_table_stmts; + ObSEArray semi_right_stmts; + ObSEArray exists_anyall_stmts; + if (OB_FAIL(get_child_stmts(all_child_stmts))) { + LOG_WARN("failed to get child stmts", K(ret)); + } else if (OB_FAIL(get_from_subquery_stmts(from_table_stmts, false))) { + LOG_WARN("get from subquery stmts failed", K(ret)); + } else if (OB_FAIL(get_semi_right_subquery_stmts(semi_right_stmts, false))) { + LOG_WARN("failed to get semi right subquery stmts", K(ret)); + } else if (OB_FAIL(get_exists_any_all_subquery(exists_anyall_stmts))) { + LOG_WARN("failed to get exists any all subquery stmts", K(ret)); + } else if (is_set_stmt()) { + const ObSelectStmt* select_stmt = static_cast(this); + is_from_dul_insene = select_stmt->is_set_distinct() + || select_stmt->is_implicit_distinct(); + } else if (OB_FAIL(check_from_dup_insensitive(is_from_dul_insene))) { + LOG_WARN("failed to check from dup insens", K(ret)); + } + + // reset implicit distinct for subquery + for (int64_t i = 0; OB_SUCC(ret) && i < all_child_stmts.count(); ++i) { + ObSelectStmt *child_stmt = all_child_stmts.at(i); + if (OB_ISNULL(child_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("child_stmt is null", K(ret)); + } else { + child_stmt->reset_implicit_distinct(); + } + } + + if (OB_FAIL(ret)) { + // do nothing + } else if (is_from_dul_insene + && OB_FAIL(add_implicit_distinct_for_child_stmts(from_table_stmts))) { + LOG_WARN("failed to add implicit distinct for FROM child stmts", K(ret)); + } else if (OB_FAIL(add_implicit_distinct_for_child_stmts(semi_right_stmts))) { + LOG_WARN("failed to add implicit distinct for semi right child stmts", K(ret)); + } else if (OB_FAIL(add_implicit_distinct_for_child_stmts(exists_anyall_stmts))) { + LOG_WARN("failed to add implicit distinct for EXISTS, ANY/ALL child stmts", K(ret)); + } + + // recursive set implicit distinct for subquery + for (int64_t i = 0; OB_SUCC(ret) && i < all_child_stmts.count(); ++i) { + ObSelectStmt *child_stmt = all_child_stmts.at(i); + if (OB_ISNULL(child_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("child_stmt is null", K(ret)); + } else if (OB_FAIL(SMART_CALL(child_stmt->formalize_implicit_distinct_for_subquery()))) { + LOG_WARN("failed to set implicit distinct for subquery", K(ret)); + } + } + return ret; +} + +int ObDMLStmt::add_implicit_distinct_for_child_stmts(ObIArray &child_stmts) +{ + int ret = OB_SUCCESS; + for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) { + ObSelectStmt *child_stmt = child_stmts.at(i); + if (OB_ISNULL(child_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("child_stmt is null", K(ret)); + } else if (child_stmt->is_implicit_distinct_allowed()) { + child_stmt->set_implicit_distinct(true); + } + } + return ret; +} + +/** + * @brief ObDMLStmt::get_exists_any_all_subquery + * + * Get all subquery stmt which is in exists or any/all ObQueryRefRawExpr + */ +int ObDMLStmt::get_exists_any_all_subquery(ObIArray &subquerys) +{ + int ret = OB_SUCCESS; + for (int64_t i = 0; OB_SUCC(ret) && i < get_subquery_exprs().count(); ++i) { + ObQueryRefRawExpr *expr = get_subquery_exprs().at(i); + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("subquery expr is null", K(ret)); + } else if (!expr->is_set()) { + // do nothing, it is not a exists, any/all query + } else if (OB_FAIL(subquerys.push_back(expr->get_ref_stmt()))) { + LOG_WARN("failed push back subquery", K(ret)); + } + } + return ret; +} + +/** + * @brief ObDMLStmt::check_from_dup_insensitive + * + * Stmt contains duplicate-insensitive aggregation or DISTINCT, making it + * insensitive to duplicate values ​​in From Scope. + */ +int ObDMLStmt::check_from_dup_insensitive(bool &is_from_dup_insens) const +{ + int ret = OB_SUCCESS; + // only check FROM scope duplicate-insensitive for ObSelectStmt + is_from_dup_insens = false; + return ret; +} + int ObDMLStmt::get_table_pseudo_column_like_exprs(uint64_t table_id, ObIArray &pseudo_columns) { @@ -2303,7 +2437,8 @@ int ObDMLStmt::clear_sharable_expr_reference() return ret; } -int ObDMLStmt::get_from_subquery_stmts(ObIArray &child_stmts) const +int ObDMLStmt::get_from_subquery_stmts(ObIArray &child_stmts, + bool contain_lateral_table/* =true */) const { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < get_table_size(); ++i) { @@ -2312,9 +2447,32 @@ int ObDMLStmt::get_from_subquery_stmts(ObIArray &child_stmts) con ret = OB_ERR_UNEXPECTED; LOG_WARN("table_item is null", K(i)); } else if (table_item->is_generated_table() || - table_item->is_lateral_table()) {// to remove temp table + (contain_lateral_table && table_item->is_lateral_table())) {// to remove temp table if (OB_FAIL(child_stmts.push_back(table_item->ref_query_))) { - LOG_WARN("adjust parent namespace stmt failed", K(ret)); + LOG_WARN("failed to push back child stmt", K(ret)); + } + } + } + return ret; +} + +int ObDMLStmt::get_semi_right_subquery_stmts(ObIArray &child_stmts, + bool contain_lateral_table/* =true */) const +{ + int ret = OB_SUCCESS; + for (int64_t i = 0; OB_SUCC(ret) && i < get_semi_info_size(); ++i) { + const SemiInfo *semi_info = get_semi_infos().at(i); + const TableItem *table_item = NULL; + if (OB_ISNULL(semi_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("semi info is null", K(ret), K(i)); + } else if (OB_ISNULL(table_item = get_table_item_by_id(semi_info->right_table_id_))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table item is null", K(ret), KPC(semi_info)); + } else if (table_item->is_generated_table() || + (contain_lateral_table && table_item->is_lateral_table())) { + if (OB_FAIL(child_stmts.push_back(table_item->ref_query_))) { + LOG_WARN("failed to push back child stmt", K(ret)); } } } @@ -3740,6 +3898,32 @@ int ObDMLStmt::get_relation_exprs_for_enum_set_wrapper(ObIArray &rel return ret; } +int ObDMLStmt::check_relation_exprs_deterministic(bool &is_deterministic) const +{ + int ret = OB_SUCCESS; + ObSEArray rel_exprs; + is_deterministic = true; + if (is_contains_assignment() + || has_sequence()) { + is_deterministic = false; + } else if (OB_FAIL(get_relation_exprs(rel_exprs))) { + LOG_WARN("failed to get relation exprs", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && is_deterministic && i < rel_exprs.count(); ++i) { + const ObRawExpr *expr = rel_exprs.at(i); + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("rel expr is null", K(ret)); + } else if (!expr->is_deterministic() + || expr->has_flag(CNT_RAND_FUNC) + || expr->has_flag(CNT_STATE_FUNC)) { + is_deterministic = false; + break; + } + } + return ret; +} + ColumnItem *ObDMLStmt::get_column_item_by_id(uint64_t table_id, uint64_t column_id) const { const ColumnItem *column_item = NULL; @@ -5167,6 +5351,16 @@ bool ObDMLStmt::is_values_table_query() const table_items_.at(0)->is_values_table(); } +bool ObDMLStmt::is_const_values_table_query() const +{ + return is_select_stmt() && + table_items_.count() == 1 && + table_items_.at(0) != NULL && + table_items_.at(0)->is_values_table() && + table_items_.at(0)->values_table_def_ != NULL && + table_items_.at(0)->values_table_def_->is_const_; +} + int ObDMLStmt::do_formalize_lateral_derived_table_pre() { int ret = OB_SUCCESS; @@ -5452,6 +5646,7 @@ int ObValuesTableDef::deep_copy(const ObValuesTableDef &other, end_param_idx_ = other.end_param_idx_; column_cnt_ = other.column_cnt_; row_cnt_ = other.row_cnt_; + is_const_ = other.is_const_; for (int64_t i = 0; OB_SUCC(ret) && i < other.access_objs_.count(); ++i) { const ObObjParam &obj = other.access_objs_.at(i); ObObjParam tmp_obj = obj; diff --git a/src/sql/resolver/dml/ob_dml_stmt.h b/src/sql/resolver/dml/ob_dml_stmt.h index 4b957356c8..3c274bc94e 100644 --- a/src/sql/resolver/dml/ob_dml_stmt.h +++ b/src/sql/resolver/dml/ob_dml_stmt.h @@ -213,7 +213,8 @@ typedef struct ObJsonTableDef { } ObJsonTableDef; struct ObValuesTableDef { - ObValuesTableDef() : start_param_idx_(-1), end_param_idx_(-1), column_cnt_(0), row_cnt_(0) , access_type_(ACCESS_EXPR) {} + ObValuesTableDef() : start_param_idx_(-1), end_param_idx_(-1), column_cnt_(0), row_cnt_(0), + access_type_(ACCESS_EXPR), is_const_(false) {} enum TableAccessType { ACCESS_EXPR = 0, // expr, one by one FOLD_ACCESS_EXPR, // expr, one expr->ObSqlArray @@ -232,10 +233,11 @@ struct ObValuesTableDef { int64_t column_cnt_; int64_t row_cnt_; TableAccessType access_type_; + bool is_const_; // values table’s outputs are all params. common::ObArray column_types_; virtual TO_STRING_KV(K(column_cnt_), K(row_cnt_), K(access_exprs_), K(start_param_idx_), K(end_param_idx_), K(access_objs_), K(column_ndvs_), K(column_nnvs_), - K(access_type_), K(column_types_)); + K(access_type_), K(is_const_), K(column_types_)); }; struct TableItem @@ -882,7 +884,11 @@ public: ObSQLSessionInfo *session_info, bool explicit_for_col); virtual int clear_sharable_expr_reference(); - virtual int get_from_subquery_stmts(common::ObIArray &child_stmts) const; + virtual int get_from_subquery_stmts(common::ObIArray &child_stmts, + bool contain_lateral_table = true) const; + int get_semi_right_subquery_stmts(ObIArray &child_stmts, + bool contain_lateral_table = true) const; + int get_exists_any_all_subquery(ObIArray &subquerys); virtual int get_subquery_stmts(common::ObIArray &child_stmts) const; int generated_column_depend_column_is_referred(ObRawExpr *expr, bool &has_no_dep); int is_referred_by_partitioning_expr(const ObRawExpr *expr, @@ -1112,6 +1118,7 @@ public: int get_relation_exprs(common::ObIArray &relation_expr_ptrs); //this func is used for enum_set_wrapper to get exprs which need to be handled int get_relation_exprs_for_enum_set_wrapper(common::ObIArray &rel_array); + int check_relation_exprs_deterministic(bool &is_deterministic) const; ColumnItem *get_column_item_by_id(uint64_t table_id, uint64_t column_id) const; const ColumnItem *get_column_item_by_base_id(uint64_t table_id, uint64_t base_column_id) const; ObColumnRefRawExpr *get_column_expr_by_id(uint64_t table_id, uint64_t column_id) const; @@ -1244,6 +1251,7 @@ public: int check_has_cursor_expression(bool &has_cursor_expr) const; bool is_values_table_query() const; + bool is_const_values_table_query() const; int do_formalize_query_ref_exprs_pre(); @@ -1257,6 +1265,12 @@ public: int do_formalize_lateral_derived_table_post(); + virtual int formalize_implicit_distinct(); + + int formalize_implicit_distinct_for_subquery(); + + virtual int check_from_dup_insensitive(bool &is_from_dup_insens) const; + int get_partition_columns(const int64_t table_id, const int64_t ref_table_id, const share::schema::ObPartitionLevel part_level, @@ -1286,6 +1300,7 @@ protected: TableItem &new_item, ObIAllocator *allocator); int adjust_duplicated_table_name(ObIAllocator &allocator, TableItem &table_item, bool &adjusted); + static int add_implicit_distinct_for_child_stmts(ObIArray &child_stmts); protected: /** diff --git a/src/sql/resolver/dml/ob_hint.cpp b/src/sql/resolver/dml/ob_hint.cpp index acfb70223d..7676710e4d 100644 --- a/src/sql/resolver/dml/ob_hint.cpp +++ b/src/sql/resolver/dml/ob_hint.cpp @@ -891,8 +891,8 @@ bool ObOptParamHint::is_param_val_valid(const OptParamType param_type, const ObO is_valid = val.is_int() && (0 <= val.get_int() && val.get_int() < 100); break; } - case PUSHDOWN_STORAGE_LEVEL: { - is_valid = val.is_int() && (0 <= val.get_int() && val.get_int() <= 4); + case OPTIMIZER_COST_BASED_TRANSFORMATION: { + is_valid = val.is_int() && (0 <= val.get_int() && val.get_int() <= 2); break; } case CORRELATION_FOR_CARDINALITY_ESTIMATION: @@ -1203,6 +1203,7 @@ ObItemType ObHint::get_hint_type(ObItemType type) case T_NO_COALESCE_AGGR: return T_COALESCE_AGGR; case T_MV_NO_REWRITE: return T_MV_REWRITE; case T_NO_USE_LATE_MATERIALIZATION: return T_USE_LATE_MATERIALIZATION; + case T_NO_TRANSFORM_DISTINCT_AGG: return T_TRANSFORM_DISTINCT_AGG; // optimize hint case T_NO_USE_DAS_HINT: return T_USE_DAS_HINT; @@ -1263,6 +1264,8 @@ const char* ObHint::get_hint_name(ObItemType type, bool is_enable_hint /* defaul case T_MV_REWRITE: return is_enable_hint ? "MV_REWRITE" : "NO_MV_REWRITE"; case T_USE_LATE_MATERIALIZATION: return is_enable_hint ? "USE_LATE_MATERIALIZATION" : "NO_USE_LATE_MATERIALIZATION"; + case T_TRANSFORM_DISTINCT_AGG: + return is_enable_hint ? "TRANSFORM_DISTINCT_AGG" : "NO_TRANSFORM_DISTINCT_AGG"; // optimize hint case T_INDEX_HINT: return "INDEX"; case T_FULL_HINT: return "FULL"; diff --git a/src/sql/resolver/dml/ob_hint.h b/src/sql/resolver/dml/ob_hint.h index 093dc2102f..1138b24c7c 100644 --- a/src/sql/resolver/dml/ob_hint.h +++ b/src/sql/resolver/dml/ob_hint.h @@ -181,6 +181,7 @@ struct ObOptParamHint DEF(NLJ_BATCHING_ENABLED,) \ DEF(RUNTIME_FILTER_TYPE,) \ DEF(BLOOM_FILTER_RATIO,) \ + DEF(OPTIMIZER_COST_BASED_TRANSFORMATION,) \ DEF(CORRELATION_FOR_CARDINALITY_ESTIMATION,) \ DEF(CARDINALITY_ESTIMATION_MODEL,) \ DEF(_PUSH_JOIN_PREDICATE,) \ @@ -278,7 +279,8 @@ struct ObGlobalHint { #define COMPAT_VERSION_4_3_2 (oceanbase::common::cal_version(4, 3, 2, 0)) #define COMPAT_VERSION_4_3_3 (oceanbase::common::cal_version(4, 3, 3, 0)) #define COMPAT_VERSION_4_3_4 (oceanbase::common::cal_version(4, 3, 4, 0)) -#define LASTED_COMPAT_VERSION COMPAT_VERSION_4_3_4 +#define COMPAT_VERSION_4_3_5 (oceanbase::common::cal_version(4, 3, 5, 0)) +#define LASTED_COMPAT_VERSION COMPAT_VERSION_4_3_5 static bool is_valid_opt_features_version(uint64_t version) { return COMPAT_VERSION_4_0 <= version && LASTED_COMPAT_VERSION >= version; } diff --git a/src/sql/resolver/dml/ob_inlist_resolver.cpp b/src/sql/resolver/dml/ob_inlist_resolver.cpp index 382e29cd59..e50b599685 100644 --- a/src/sql/resolver/dml/ob_inlist_resolver.cpp +++ b/src/sql/resolver/dml/ob_inlist_resolver.cpp @@ -83,6 +83,7 @@ int ObInListResolver::resolve_values_table_from_inlist(const ParseNode *in_list, table_def->column_cnt_ = column_cnt; table_def->row_cnt_ = row_cnt; table_def->access_type_ = access_type; + table_def->is_const_ = true; } if (OB_FAIL(ret)) { } else if (ObValuesTableDef::ACCESS_PARAM == access_type && diff --git a/src/sql/resolver/dml/ob_merge_resolver.cpp b/src/sql/resolver/dml/ob_merge_resolver.cpp index 88e5977c9b..2747412442 100644 --- a/src/sql/resolver/dml/ob_merge_resolver.cpp +++ b/src/sql/resolver/dml/ob_merge_resolver.cpp @@ -686,7 +686,9 @@ int ObMergeResolver::find_value_desc(ObInsertTableInfo &table_info, column_ref = table_info.values_vector_.at(idx); if (T_QUESTIONMARK == column_ref->get_expr_type()) { OZ (column_ref->add_flag(IS_TABLE_ASSIGN)); + ObObj val = column_ref->get_result_type().get_param(); OX (column_ref->set_result_type(value_desc.at(idx)->get_result_type())); + OX (column_ref->set_param(val)); } } if (OB_ENTRY_NOT_EXIST == ret) { diff --git a/src/sql/resolver/dml/ob_select_resolver.cpp b/src/sql/resolver/dml/ob_select_resolver.cpp index d6adc5f774..e7588de1fe 100644 --- a/src/sql/resolver/dml/ob_select_resolver.cpp +++ b/src/sql/resolver/dml/ob_select_resolver.cpp @@ -36,6 +36,8 @@ #include "common/ob_smart_call.h" #include "sql/engine/expr/ob_expr_regexp_context.h" #include "sql/engine/expr/ob_json_param_type.h" +#include "sql/parser/ob_parser_utils.h" + #include "sql/executor/ob_memory_tracker.h" namespace oceanbase { @@ -84,15 +86,19 @@ int ObSelectResolver::resolve_set_query(const ParseNode &parse_tree) { int ret = OB_SUCCESS; bool recursive_union = false; - bool need_swap_child = false; - - if (cte_ctx_.is_with_resolver() && OB_FAIL(check_query_is_recursive_union(parse_tree, recursive_union, need_swap_child))) { + bool resolve_happened = false; + if (OB_FAIL(check_query_is_recursive_union(parse_tree, recursive_union))) { LOG_WARN("failed to do resolve set query", K(ret)); } else if (recursive_union) { - if (OB_FAIL(do_resolve_set_query_in_cte(parse_tree, need_swap_child))) { + if (OB_FAIL(do_resolve_set_query_in_recursive_cte(parse_tree))) { LOG_WARN("failed to do resolve set query in cte", K(ret)); } - } else if (OB_FAIL(do_resolve_set_query(parse_tree))) { + } else if (OB_FAIL(try_resolve_values_table_from_union(parse_tree, resolve_happened))) { + LOG_WARN("failed to rewrite union to values", K(ret)); + } else if (resolve_happened) { + OPT_TRACE("resolve values table from union", resolve_happened); + OPT_TRACE(get_stmt()); + } else if (OB_FAIL(do_resolve_set_query_in_normal(parse_tree))) { LOG_WARN("failed to do resolve set query", K(ret)); } return ret; @@ -154,181 +160,178 @@ int ObSelectResolver::do_check_node_in_cte_recursive_union(const ParseNode* curr return ret; } -// test if a query node contains recursive nodes -int ObSelectResolver::check_query_is_recursive_union(const ParseNode &parse_tree, bool &recursive_union, bool &need_swap_child) +/* + * test if a query node contains recursive nodes + * 为什么需要交换左右支? + * with cte(c1) as (select 1 from dual union all select c1+1 from cte where c1 < 100) + * select * from cte; + * + * with cte(c1) as (select c1+1 from cte where c1 < 100 union all select 1 from dual) + * select * from cte; + * + * oracle支持这两种写法。之前在cte的实现时是误判了,认为只能左边是anchor member。 + * 对于recursive cte的revolber解析来说,左右支解析是敏感的,右边的解析依赖于左边先被 + * 解析。为什么呢?因为假设在没有解析左边的时候就开始解析右边,我们完全不知道cte这张表 + * 的c1列是什么类型。所以这里先判断是否需要交换左右支。 + */ +int ObSelectResolver::check_query_is_recursive_union(const ParseNode &parse_tree, + bool &recursive_union) { int ret = OB_SUCCESS; - ParseNode *left_node = NULL; - ParseNode *right_node = NULL; - + const bool is_oracle_mode = lib::is_oracle_mode(); + const ParseNode *set_node = parse_tree.children_[PARSE_SELECT_SET]; + ObSelectStmt *select_stmt = get_select_stmt(); bool left_recursive_union = false; bool right_recursive_union = false; - - if (OB_ISNULL(left_node = parse_tree.children_[PARSE_SELECT_FORMER]) - || OB_ISNULL(right_node = parse_tree.children_[PARSE_SELECT_LATER]) - || OB_ISNULL(parse_tree.children_[PARSE_SELECT_SET])) { + recursive_union = false; + if (!cte_ctx_.is_with_resolver()) { + // recursive_union = false + } else if (OB_ISNULL(set_node) || OB_ISNULL(select_stmt)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (NULL != parse_tree.children_[PARSE_SELECT_WITH] && is_oracle_mode()) { - ret = OB_ERR_UNSUPPORTED_USE_OF_CTE; - LOG_WARN("invalid argument, oracle cte do not support a with clause nest", K(ret)); - } else if (OB_FAIL(do_check_node_in_cte_recursive_union(left_node, left_recursive_union))) { - //test left branch - LOG_WARN("failed to check set query in cte is recursive union", K(ret)); - } else if (OB_FAIL(do_check_node_in_cte_recursive_union(right_node, right_recursive_union))) { - //test right branch - LOG_WARN("failed to check set query in cte is recursive union", K(ret)); - } - - recursive_union = left_recursive_union || right_recursive_union; - - /** - * 为什么需要交换左右支? - * with cte(c1) as (select 1 from dual union all select c1+1 from cte where c1 < 100) - * select * from cte; - * - * with cte(c1) as (select c1+1 from cte where c1 < 100 && select 1 from dual) - * select * from cte; - * - * oracle支持这两种写法。之前在cte的实现时是误判了,认为只能左边是anchor member。 - * 对于recursive cte的revolber解析来说,左右支解析是敏感的,右边的解析依赖于左边先被 - * 解析。为什么呢?因为假设在没有解析左边的时候就开始解析右边,我们完全不知道cte这张表 - * 的c1列是什么类型。所以这里先判断是否需要交换左右支。 - */ - if (is_oracle_mode() && left_recursive_union && !right_recursive_union) { - need_swap_child = true; - } - - return ret; -} - -// resolve 对于非cte, union, check child 能否展平(limit、order、fetch) -int ObSelectResolver::do_resolve_set_query_in_cte(const ParseNode &parse_tree, bool swap_branch) -{ - int ret = OB_SUCCESS; - bool need_swap_child = false; - ObSelectStmt *select_stmt = get_select_stmt(); - SelectParserOffset left_member = PARSE_SELECT_FORMER; - SelectParserOffset right_member = PARSE_SELECT_LATER; - ObSelectResolver left_resolver(params_); - ObSelectResolver right_resolver(params_); - ObSelectStmt *left_select_stmt = NULL; - ObSelectStmt *right_select_stmt = NULL; - - left_resolver.set_current_level(current_level_); - left_resolver.set_current_view_level(current_view_level_); - left_resolver.set_in_set_query(true); - left_resolver.set_parent_namespace_resolver(parent_namespace_resolver_); - left_resolver.set_calc_found_rows(has_calc_found_rows_); - - right_resolver.set_current_level(current_level_); - right_resolver.set_current_view_level(current_view_level_); - right_resolver.set_in_set_query(true); - right_resolver.set_parent_namespace_resolver(parent_namespace_resolver_); - - OC( (left_resolver.set_cte_ctx)(cte_ctx_) ); - OC( (right_resolver.set_cte_ctx)(cte_ctx_) ); - - left_resolver.cte_ctx_.set_recursive_left_branch(); - - if (swap_branch) { - left_member = PARSE_SELECT_LATER; - right_member = PARSE_SELECT_FORMER; - } - - if (OB_FAIL(ret)) { - } else if (OB_ISNULL(select_stmt) || OB_ISNULL(parse_tree.children_[PARSE_SELECT_FORMER]) - || OB_ISNULL(parse_tree.children_[PARSE_SELECT_LATER])) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret), K(select_stmt), - K(parse_tree.children_[PARSE_SELECT_FORMER]), K(parse_tree.children_[PARSE_SELECT_LATER])); - } else if (parse_tree.children_[PARSE_SELECT_LATER]->value_ == 1) { - ret = OB_ERR_ILLEGAL_ID; - LOG_WARN("Select for update statement can not process set query"); - } else if (OB_FAIL(set_stmt_set_type(select_stmt, parse_tree.children_[PARSE_SELECT_SET]))) { - LOG_WARN("failed to set stmt set type", K(ret)); - } else if (OB_FAIL(resolve_with_clause(parse_tree.children_[PARSE_SELECT_WITH]))) { - LOG_WARN("failed to resolve with clause", K(ret)); - } else if (OB_FAIL(add_cte_table_to_children(left_resolver)) || - OB_FAIL(add_cte_table_to_children(right_resolver))) { - LOG_WARN("failed to add cte table to children", K(ret)); - } else if (OB_FAIL(left_resolver.resolve_child_stmt(*(parse_tree.children_[left_member])))) { - if (OB_ERR_NEED_INIT_BRANCH_IN_RECURSIVE_CTE == ret) { - if (is_oracle_mode()){ - /* do nothing */ - LOG_WARN("Failed to resolve child stmt", K(ret)); - } else if (cte_ctx_.has_recursive_word_) { - ret = OB_ERR_CTE_NEED_QUERY_BLOCKS; // mysql error: Recursive Common Table Expression 'cte' should have one or - // more non-recursive query blocks followed by one or more recursive ones - LOG_WARN("Failed to resolve child stmt", K(ret)); - } else { - ret = OB_TABLE_NOT_EXIST; - LOG_WARN("cte table shows in left union stmt without recursive keyword", K(ret)); - } - } else { - LOG_WARN("Failed to find anchor member", K(ret)); - } - } else if (OB_ISNULL(left_select_stmt = left_resolver.get_child_stmt())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null stmt"); - } else if (lib::is_oracle_mode() && left_select_stmt->is_set_stmt()) { - ret = OB_ERR_NEED_ONLY_TWO_BRANCH_IN_RECURSIVE_CTE; - LOG_WARN("UNION ALL operation in recursive WITH clause must have only two branches", K(ret)); - } else if (OB_FAIL(ObRawExprUtils::wrap_enum_set_for_stmt(*params_.expr_factory_, left_select_stmt, session_info_))) { - LOG_WARN("failed to wrap_enum_set_for_stmt", KPC(left_select_stmt)); + LOG_WARN("got null ptr", K(ret)); } else { - if (swap_branch) { - select_stmt->set_children_swapped(); - } - } - - if (OB_SUCC(ret)) { - if (!cte_ctx_.has_cte_param_list_ && - !left_resolver.cte_ctx_.cte_col_names_.empty()) { - right_resolver.cte_ctx_.cte_col_names_.reset(); - cte_ctx_.cte_col_names_.reset(); - for (int64_t i = 0; OB_SUCC(ret) && i < left_resolver.cte_ctx_.cte_col_names_.count(); ++i) { - // to right resolver - if (OB_FAIL(right_resolver.cte_ctx_.cte_col_names_.push_back( - left_resolver.cte_ctx_.cte_col_names_.at(i)))) { - LOG_WARN("pass cte column name to child resolver failed", K(ret)); - // to parent resolver - } else if (OB_FAIL(cte_ctx_.cte_col_names_.push_back( - left_resolver.cte_ctx_.cte_col_names_.at(i)))) { - LOG_WARN("pass cte column name to child resolver failed", K(ret)); + for (int64_t i = 0; OB_SUCC(ret) && i < set_node->num_child_; i++) { + bool is_recursive_union = false; + if (OB_FAIL(do_check_node_in_cte_recursive_union(set_node->children_[i], + is_recursive_union))) { + LOG_WARN("failed to check set query in cte is recursive union", K(ret)); + } else { + recursive_union |= is_recursive_union; + if (0 == i) { + left_recursive_union = is_recursive_union; + } else if (1 == i) { + right_recursive_union = is_recursive_union; } } } + if (OB_SUCC(ret) && is_oracle_mode && recursive_union) { + if (2 < set_node->num_child_) { + ret = OB_ERR_NEED_ONLY_TWO_BRANCH_IN_RECURSIVE_CTE; + LOG_WARN("UNION ALL operation in recursive WITH clause must have only two branches", K(ret)); + } else if (left_recursive_union && !right_recursive_union) { + const ParseNode *tmp_node = set_node->children_[0]; + const_cast(set_node)->children_[0] = const_cast(set_node)->children_[1]; + const_cast(set_node)->children_[1] = const_cast(tmp_node); + select_stmt->set_children_swapped(); + LOG_TRACE("swap set child is happened"); + } + } + } + return ret; +} + +/* 1. recursive 只能使用 union all 语法 + * 2. recursive mysql mode, cte只能在最后一支UNION ALL的右支,左支只要不出现cte就行 + * 3. recursive oracle mode, cte可以出现在左右两支其中一支,不允许在子查询中出现, 而且左右两支都不允许是set, 。 +*/ +int ObSelectResolver::do_resolve_set_query_in_recursive_cte(const ParseNode &parse_tree) +{ + int ret = OB_SUCCESS; + ObSelectStmt *select_stmt = get_select_stmt(); + ParseNode *set_node = parse_tree.children_[PARSE_SELECT_SET]; + const bool is_oracle_mode = lib::is_oracle_mode(); + bool is_set_recursive_union = false; + if (OB_FAIL(ret)) { + } else if (OB_ISNULL(select_stmt) || OB_ISNULL(set_node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), KP(select_stmt), KP(set_node)); + } else if (OB_FAIL(set_stmt_set_type(select_stmt, set_node))) { + LOG_WARN("failed to set stmt set type", K(ret)); + } else if (OB_FAIL(resolve_with_clause(parse_tree.children_[PARSE_SELECT_WITH]))) { + LOG_WARN("failed to resolve with clause", K(ret)); + } else { + const int64_t n_set_child = set_node->num_child_; + for (int64_t i = 0; OB_SUCC(ret) && i < n_set_child; ++i) { + ParseNode *child_node = NULL; + ObSelectStmt *child_stmt = NULL; + ObSelectResolver child_resolver(params_); + child_resolver.set_current_level(current_level_); + child_resolver.set_current_view_level(current_view_level_); + child_resolver.set_in_set_query(true); + child_resolver.set_parent_namespace_resolver(parent_namespace_resolver_); + child_resolver.set_calc_found_rows(i == 0 ? has_calc_found_rows_ : false); + if (OB_ISNULL(child_node = set_node->children_[i])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("got unexpected NULL ptr", K(ret)); + } else if (OB_FAIL(child_resolver.set_cte_ctx(cte_ctx_))) { + LOG_WARN("failed to set ctx", K(ret)); + } else if (OB_FAIL(add_cte_table_to_children(child_resolver))) { + LOG_WARN("failed to add cte table to children", K(ret)); + } else { + if (i != n_set_child - 1) { + child_resolver.cte_ctx_.set_recursive_left_branch(); + } else { + child_resolver.cte_ctx_.set_recursive_right_branch(select_stmt->get_set_query(0), + !select_stmt->is_set_distinct()); + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(child_resolver.resolve_child_stmt(*child_node))) { + if (OB_ERR_NEED_INIT_BRANCH_IN_RECURSIVE_CTE == ret && i != n_set_child - 1) { + if (is_oracle_mode){ + /* do nothing */ + LOG_WARN("Failed to resolve child stmt", K(ret)); + } else if (cte_ctx_.has_recursive_word_) { + ret = OB_ERR_CTE_NEED_QUERY_BLOCKS; // mysql error: Recursive Common Table Expression 'cte' should have one or + // more non-recursive query blocks followed by one or more recursive ones + LOG_WARN("Failed to resolve child stmt", K(ret)); + } else { + ret = OB_TABLE_NOT_EXIST; + LOG_WARN("cte table shows in left union stmt without recursive keyword", K(ret)); + } + } else { + LOG_WARN("Failed to find anchor member", K(ret), K(i)); + } + } else if (OB_ISNULL(child_stmt = child_resolver.get_child_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null stmt"); + } else if (is_oracle_mode && child_stmt->is_set_stmt()) { + ret = OB_ERR_NEED_ONLY_TWO_BRANCH_IN_RECURSIVE_CTE; + LOG_WARN("UNION ALL operation in recursive WITH clause must have only two branches", K(ret)); + } else if (i != n_set_child - 1 && + OB_FAIL(ObRawExprUtils::wrap_enum_set_for_stmt(*params_.expr_factory_, + child_stmt, + session_info_))) { + LOG_WARN("failed to wrap_enum_set_for_stmt", KPC(child_stmt)); + } else { + is_set_recursive_union = i == n_set_child - 1 && child_resolver.cte_ctx_.is_recursive(); + if (i == 0) { + select_stmt->set_calc_found_rows(child_stmt->is_calc_found_rows()); + if (OB_FAIL(select_stmt->add_set_query(child_stmt))) { + LOG_WARN("failed to add set query", K(ret)); + } else if (!cte_ctx_.has_cte_param_list_ && !child_resolver.cte_ctx_.cte_col_names_.empty()) { + cte_ctx_.cte_col_names_.reset(); + if (OB_FAIL(append(cte_ctx_.cte_col_names_, child_resolver.cte_ctx_.cte_col_names_))) { + LOG_WARN("pass cte column name to child resolver failed", K(ret)); + } + } + } else if (OB_FAIL(ObOptimizerUtil::try_add_cast_to_set_child_list(allocator_, + session_info_, params_.expr_factory_, + select_stmt->is_set_distinct(), + select_stmt->get_set_query(), + child_stmt, NULL, is_set_recursive_union && !is_oracle_mode, + &cte_ctx_.cte_col_names_))) { + LOG_WARN("failed to try add cast to set child list", K(ret)); + } else if (OB_FAIL(select_stmt->add_set_query(child_stmt))) { + LOG_WARN("failed to add set query", K(ret)); + } + } + /* MySQL + * The types of the CTE result columns are inferred from the column types of the nonrecursive SELECT part only, + * and the columns are all nullable. For type determination, the recursive SELECT part is ignored. + */ + } + } } - if (OB_FAIL(ret)) { - } else if (OB_FALSE_IT(right_resolver.cte_ctx_.set_recursive_right_branch(left_select_stmt, - parse_tree.children_[left_member], !select_stmt->is_set_distinct()))) { - } else if (OB_FAIL(right_resolver.resolve_child_stmt(*parse_tree.children_[right_member]))) { - LOG_WARN("failed to resolve child stmt", K(ret)); - } else if (OB_FAIL(resolve_into_clause(ObResolverUtils::get_select_into_node(parse_tree)))) { - LOG_WARN("failed to resolve into clause", K(ret)); - } else if (OB_ISNULL(right_select_stmt = right_resolver.get_child_stmt()) - || OB_ISNULL(left_select_stmt)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret), K(left_select_stmt), K(right_select_stmt)); - } else { - select_stmt->add_set_query(left_select_stmt); - select_stmt->add_set_query(right_select_stmt); - select_stmt->set_calc_found_rows(left_select_stmt->is_calc_found_rows()); - /**MySQL - * The types of the CTE result columns are inferred from the column types of the nonrecursive SELECT part only, - * and the columns are all nullable. For type determination, the recursive SELECT part is ignored. - */ + if (OB_SUCC(ret)) { if (OB_FAIL(ObOptimizerUtil::gen_set_target_list(allocator_, session_info_, - params_.expr_factory_, *left_select_stmt, - *right_select_stmt, select_stmt, - lib::is_mysql_mode() && right_resolver.cte_ctx_.is_recursive(), - &cte_ctx_.cte_col_names_))) { - LOG_WARN("failed to gen set target list.", K(ret)); - } else if (!right_resolver.cte_ctx_.is_recursive()) { - /*do nothing*/ - } else if (lib::is_oracle_mode() && OB_FAIL(check_cte_set_types(*left_select_stmt, *right_select_stmt))) { + params_.expr_factory_, select_stmt))) { + LOG_WARN("failed to get set target list", K(ret)); + } else if (!is_set_recursive_union) { + /* do nothing */ + } else if (is_oracle_mode && OB_FAIL(check_cte_set_types(*select_stmt->get_set_query(0), + *select_stmt->get_set_query(1)))) { LOG_WARN("check cte set types", K(ret)); } else if (select_stmt->is_set_distinct() || ObSelectStmt::UNION != select_stmt->get_set_op()) { // 必须是union all @@ -340,8 +343,8 @@ int ObSelectResolver::do_resolve_set_query_in_cte(const ParseNode &parse_tree, b } else if (OB_NOT_NULL(parse_tree.children_[PARSE_SELECT_LIMIT])) { ret = OB_ERR_CTE_ILLEGAL_RECURSIVE_BRANCH; LOG_WARN("use limit clause in the recursive cte is not allowed", K(ret)); - } else if (is_oracle_mode() && - OB_FAIL(adjust_recursive_cte_table_columns(select_stmt, right_select_stmt))) { + } else if (is_oracle_mode && + OB_FAIL(adjust_recursive_cte_table_columns(select_stmt, select_stmt->get_set_query(1)))) { LOG_WARN("failed to adjust recursive cte table columns", K(ret)); } else { /** @@ -353,7 +356,9 @@ int ObSelectResolver::do_resolve_set_query_in_cte(const ParseNode &parse_tree, b } if (OB_FAIL(ret)) { - } else if (parse_tree.children_[PARSE_SELECT_FOR_UPD] != NULL && is_oracle_mode()) { + } else if (OB_FAIL(resolve_into_clause(ObResolverUtils::get_select_into_node(parse_tree)))) { + LOG_WARN("failed to resolve into clause", K(ret)); + } else if (is_oracle_mode && NULL != parse_tree.children_[PARSE_SELECT_FOR_UPD]) { ret = OB_ERR_FOR_UPDATE_EXPR_NOT_ALLOWED; LOG_WARN("set stmt can not have for update clause", K(ret)); } else if (OB_FAIL(resolve_order_clause(parse_tree.children_[PARSE_SELECT_ORDER]))) { @@ -395,87 +400,96 @@ int ObSelectResolver::resolve_set_query_hint() return ret; } -int ObSelectResolver::do_resolve_set_query(const ParseNode &parse_tree) +/* 1. 类型推导的过程 (A union B) union (C union D) 不等于 A union B union C union D + 添加cast的过程 cast(cast(A, R1), R2) != cast(A, R2) + 添加完cast之后,才可以展开包含括号的UNION + * 2. calc_found_rows + * 3. is_serial_set_order_forced + */ +int ObSelectResolver::do_resolve_set_query_in_normal(const ParseNode &parse_tree) { int ret = OB_SUCCESS; ObSelectStmt *select_stmt = get_select_stmt(); - ParseNode *left_node = NULL; - ParseNode *right_node = NULL; - ObSEArray left_child_stmts; - ObSEArray right_child_stmts; + ParseNode *select_set = parse_tree.children_[PARSE_SELECT_SET]; bool force_serial_set_order = false; - if (OB_ISNULL(left_node = parse_tree.children_[PARSE_SELECT_FORMER]) - || OB_ISNULL(right_node = parse_tree.children_[PARSE_SELECT_LATER]) - || OB_ISNULL(parse_tree.children_[PARSE_SELECT_SET]) || OB_ISNULL(select_stmt) - || OB_ISNULL(session_info_)) { + const bool is_oracle_mode = lib::is_oracle_mode(); + if (OB_ISNULL(select_set) || OB_ISNULL(select_stmt) || OB_ISNULL(session_info_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null pointer", K(left_node), K(right_node), K(parse_tree.children_[PARSE_SELECT_SET]), - K(select_stmt), K(session_info_), K(ret)); - } else if (right_node->value_ == 1) { - ret = OB_ERR_ILLEGAL_ID; - LOG_WARN("Select for update statement can not process set query", K(ret)); - } else if (OB_FAIL(set_stmt_set_type(select_stmt, parse_tree.children_[PARSE_SELECT_SET]))) { + LOG_WARN("unexpected null pointer", K(select_set), K(select_stmt), K(session_info_), K(ret)); + } else if (OB_FAIL(set_stmt_set_type(select_stmt, select_set))) { LOG_WARN("failed to set stmt set type", K(ret)); } else if (OB_FAIL(resolve_into_clause(ObResolverUtils::get_select_into_node(parse_tree)))) { LOG_WARN("failed to resolve into clause", K(ret)); - } else if (parse_tree.children_[PARSE_SELECT_FOR_UPD] != NULL && is_oracle_mode()) { + } else if (parse_tree.children_[PARSE_SELECT_FOR_UPD] != NULL && is_oracle_mode) { ret = OB_ERR_FOR_UPDATE_EXPR_NOT_ALLOWED; LOG_WARN("set stmt can not have for update clause", K(ret)); + } else if (is_oracle_mode && + NULL != parse_tree.children_[PARSE_SELECT_WITH] && + is_in_set_query()) { + ret = OB_ERR_UNSUPPORTED_USE_OF_CTE; + LOG_WARN("oracle not support use of cte inside union", K(ret)); } else if (OB_FAIL(resolve_with_clause(parse_tree.children_[PARSE_SELECT_WITH]))) { LOG_WARN("failed to resolve with clause", K(ret)); - } else if (T_SET_UNION == parse_tree.children_[PARSE_SELECT_SET]->type_) { - // union 进行展平 - if (OB_FAIL(SMART_CALL(do_resolve_set_query(*left_node, left_child_stmts, true)))) { - LOG_WARN("failed to do resolve set query", K(ret)); - } else if (OB_FAIL(SMART_CALL(do_resolve_set_query(*right_node, right_child_stmts)))) { - LOG_WARN("failed to do resolve set query", K(ret)); - } } else { - // union 以外 set 不进行展平 - ObSelectStmt *left_child_stmt = NULL; - ObSelectStmt *right_child_stmt= NULL; - if (OB_FAIL(SMART_CALL(do_resolve_set_query(*left_node, left_child_stmt, true)))) { - LOG_WARN("failed to do resolve set query", K(ret)); - } else if (OB_FAIL(SMART_CALL(do_resolve_set_query(*right_node, right_child_stmt)))) { - LOG_WARN("failed to do resolve set query", K(ret)); - } else if (OB_FAIL(left_child_stmts.push_back(left_child_stmt)) || - OB_FAIL(right_child_stmts.push_back(right_child_stmt))) { - LOG_WARN("failed set child stmts", K(ret)); + const int64_t num_child = select_set->num_child_; + select_stmt->get_set_query().reuse(); + for (int64_t i = 0; OB_SUCC(ret) && i < num_child; i++) { + ParseNode *child_node = select_set->children_[i]; + ObSelectStmt *child_stmt = NULL; + bool is_type_same = false; + bool enable_pullup = false; + if (OB_ISNULL(child_node) || + OB_UNLIKELY(T_SELECT != child_node->type_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null pointer", K(ret)); + } else if (OB_FAIL(do_resolve_set_query(*child_node, child_stmt, i == 0))) { + // SQL_CALC_FOUND_ROWS is valid in first branch of union only + LOG_WARN("failed to do resolve set query", K(ret)); + } else if (OB_FAIL(check_set_child_stmt_pullup(*child_stmt, enable_pullup))) { + LOG_WARN("failed to check set child_stmt pullup", K(ret)); + } else if (!enable_pullup) { + if (0 != i && OB_FAIL(ObOptimizerUtil::try_add_cast_to_set_child_list(allocator_, + session_info_, params_.expr_factory_, + select_stmt->is_set_distinct(), + select_stmt->get_set_query(), child_stmt, NULL))) { + LOG_WARN("failed to try add cast to set child list", K(ret)); + } else if (OB_FAIL(select_stmt->get_set_query().push_back(child_stmt))) { + LOG_WARN("failed to push back child_stmt", K(ret)); + } + }else { + if (0 != i && OB_FAIL(ObOptimizerUtil::try_add_cast_to_set_child_list(allocator_, + session_info_, params_.expr_factory_, + select_stmt->is_set_distinct(), + select_stmt->get_set_query(), + child_stmt->get_set_query(), NULL))) { + LOG_WARN("failed to try add cast to set child list", K(ret)); + } else if (OB_FAIL(append(select_stmt->get_set_query(), child_stmt->get_set_query()))) { + LOG_WARN("failed set child stmts", K(ret)); + } + } } } if (OB_SUCC(ret)) { - select_stmt->get_set_query().reuse(); - if (OB_FAIL(select_stmt->get_set_query().assign(left_child_stmts)) || - OB_FAIL(append(select_stmt->get_set_query(), right_child_stmts))) { - LOG_WARN("failed add child stmts", K(ret)); - } else if (OB_FAIL(ObOptimizerUtil::gen_set_target_list(allocator_, session_info_, - params_.expr_factory_, - left_child_stmts, right_child_stmts, - select_stmt))) { + if (OB_FAIL(ObOptimizerUtil::gen_set_target_list(allocator_, session_info_, + params_.expr_factory_, select_stmt))) { LOG_WARN("failed to get set target list", K(ret)); } else { + // first branch is_calc_found_rows then this is is_calc_found_rows select_stmt->set_calc_found_rows(select_stmt->get_set_query(0)->is_calc_found_rows()); } } if (OB_FAIL(ret)) { //do nothing - } else if (OB_FAIL(session_info_->is_serial_set_order_forced(force_serial_set_order, lib::is_oracle_mode()))) { + } else if (OB_FAIL(session_info_->is_serial_set_order_forced(force_serial_set_order, is_oracle_mode))) { LOG_WARN("fail to get explicit_defaults_for_timestamp", K(ret)); - } else if (!force_serial_set_order) { - //do nothing - } else if (T_SET_UNION == parse_tree.children_[PARSE_SELECT_SET]->type_ && - NULL != parse_tree.children_[PARSE_SELECT_SET]->children_[0] && - T_ALL == parse_tree.children_[PARSE_SELECT_SET]->children_[0]->type_) { - // for set query except union-all/recursive, when force serial set order, will add select expr as oder by expr - force_serial_set_order = false; + } else if (force_serial_set_order && T_SET_UNION_ALL == parse_tree.children_[PARSE_SELECT_SET]->type_) { + // for set query except union-all/recursive, when force serial set order, will add select expr as order by expr + force_serial_set_order = false; } if (OB_FAIL(ret)) { - } else if (parse_tree.children_[PARSE_SELECT_FOR_UPD] != NULL && is_oracle_mode()) { - ret = OB_ERR_FOR_UPDATE_EXPR_NOT_ALLOWED; - LOG_WARN("set stmt can not have for update clause", K(ret)); } else if (OB_FAIL(resolve_order_clause(parse_tree.children_[PARSE_SELECT_ORDER], force_serial_set_order))) { LOG_WARN("failed to resolve order clause", K(ret)); } else if (OB_FAIL(resolve_limit_clause(parse_tree.children_[PARSE_SELECT_LIMIT]))) { @@ -499,6 +513,29 @@ int ObSelectResolver::do_resolve_set_query(const ParseNode &parse_tree) return ret; } +int ObSelectResolver::check_set_child_stmt_pullup(const ObSelectStmt &child_stmt, + bool &enable_pullup) +{ + int ret = OB_SUCCESS; + enable_pullup = false; + ObSelectStmt *select_stmt = get_select_stmt(); + if (OB_ISNULL(select_stmt) || OB_UNLIKELY(!select_stmt->is_set_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("got unexpected param", K(ret)); + } else if (child_stmt.is_set_stmt() && + ObSelectStmt::UNION == select_stmt->get_set_op() && + child_stmt.get_set_op() == select_stmt->get_set_op() && + child_stmt.is_set_distinct() == select_stmt->is_set_distinct() && + !child_stmt.has_order_by() && + !child_stmt.has_limit() && + !child_stmt.has_fetch()) { + enable_pullup = true; + } else { + enable_pullup = false; + } + return ret; +} + int ObSelectResolver::check_udt_set_query() { int ret = OB_SUCCESS; @@ -527,81 +564,6 @@ int ObSelectResolver::check_udt_set_query() return ret; } -// resolve 对于非cte, union, check child 能否展平(limit、order、fetch) -int ObSelectResolver::do_resolve_set_query(const ParseNode &parse_tree, - common::ObIArray &child_stmts, - const bool is_left_child) /*default false*/ -{ - int ret = OB_SUCCESS; - bool can_flatten = false; - bool is_type_same = false; - ObSelectStmt *select_stmt = NULL; - if (OB_ISNULL(select_stmt = get_select_stmt())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret), K(select_stmt)); - } else if (parse_tree.children_[PARSE_SELECT_FOR_UPD] != NULL && is_oracle_mode()) { - ret = OB_ERR_FOR_UPDATE_EXPR_NOT_ALLOWED; - LOG_WARN("set stmt can not have for update clause", K(ret)); - } else if (OB_FAIL(is_set_type_same(select_stmt, parse_tree.children_[PARSE_SELECT_SET], - is_type_same))) { - LOG_WARN("failed to check is set type same", K(ret)); - } else if (!is_type_same) { - // select_stmt 与待 resolve set stmt 类型不同, 无法展平 - can_flatten = false; - } else if (NULL != parse_tree.children_[PARSE_SELECT_ORDER] || - NULL != parse_tree.children_[PARSE_SELECT_LIMIT] || - NULL != parse_tree.children_[PARSE_SELECT_FETCH]) { - // 待 resolve set stmt 有 order by / limit / fetch, 无法展平 - can_flatten = false; - } else if (ObSelectStmt::UNION == select_stmt->get_set_op()) { - // 仅对 union 进行展平 - can_flatten = true; - } - - if (OB_FAIL(ret)) { - } else if (can_flatten) { - ObSEArray left_child_stmts; - ObSEArray right_child_stmts; - ParseNode *left_node = NULL; - ParseNode *right_node = NULL; - if (OB_ISNULL(left_node = parse_tree.children_[PARSE_SELECT_FORMER]) - || OB_ISNULL(right_node = parse_tree.children_[PARSE_SELECT_LATER])) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (right_node->value_ == 1) { - ret = OB_ERR_ILLEGAL_ID; - LOG_WARN("Select for update statement can not process set query", K(ret)); - } else if (lib::is_oracle_mode() && OB_NOT_NULL(parse_tree.children_[PARSE_SELECT_WITH])) { - ret = OB_ERR_UNSUPPORTED_USE_OF_CTE; - LOG_WARN("oracle not support use of cte", K(ret)); - } else if (OB_FAIL(resolve_into_clause(ObResolverUtils::get_select_into_node(parse_tree)))) { - LOG_WARN("failed to resolve into clause", K(ret)); - } else if (OB_FAIL(resolve_with_clause(parse_tree.children_[PARSE_SELECT_WITH]))) { - LOG_WARN("failed to resolve with clause", K(ret)); - } else if (OB_FAIL(SMART_CALL(do_resolve_set_query(*left_node, left_child_stmts, - is_left_child)))) { - LOG_WARN("failed to do resolve set query", K(ret)); - } else if (OB_FAIL(SMART_CALL(do_resolve_set_query(*right_node, right_child_stmts)))) { - LOG_WARN("failed to do resolve set query", K(ret)); - } else if (OB_FAIL(ObOptimizerUtil::try_add_cast_to_set_child_list(allocator_, session_info_, - params_.expr_factory_, select_stmt->is_set_distinct(), - left_child_stmts, right_child_stmts, NULL))) { - LOG_WARN("failed to try add cast to set child list", K(ret)); - } else if (OB_FAIL(append(child_stmts, left_child_stmts)) || - OB_FAIL(append(child_stmts, right_child_stmts))) { - LOG_WARN("failed to append stmts", K(ret)); - } - } else { - ObSelectStmt *child_stmt = NULL; - if (OB_FAIL(do_resolve_set_query(parse_tree, child_stmt, is_left_child))) { - LOG_WARN("failed to do resolve set query", K(ret)); - } else if (OB_FAIL(child_stmts.push_back(child_stmt))) { - LOG_WARN("failed to push back", K(ret)); - } - } - return ret; -} - int ObSelectResolver::do_resolve_set_query(const ParseNode &parse_tree, ObSelectStmt *&child_stmt, const bool is_left_child) /*default false*/ @@ -639,11 +601,15 @@ int ObSelectResolver::set_stmt_set_type(ObSelectStmt *select_stmt, ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret)); } else { - // assign set type + select_stmt->assign_set_distinct(); switch (set_node->type_) { case T_SET_UNION: select_stmt->assign_set_op(ObSelectStmt::UNION); break; + case T_SET_UNION_ALL: + select_stmt->assign_set_op(ObSelectStmt::UNION); + select_stmt->assign_set_all(); + break; case T_SET_INTERSECT: select_stmt->assign_set_op(ObSelectStmt::INTERSECT); break; @@ -655,55 +621,30 @@ int ObSelectResolver::set_stmt_set_type(ObSelectStmt *select_stmt, LOG_WARN("unknown set operator of set clause"); break; } - // check distinct and all - if (OB_FAIL(ret)) { - } else if (1 != set_node->num_child_) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("wrong num_child_", K(set_node->num_child_)); - } else if (NULL == set_node->children_[0]) { - select_stmt->assign_set_distinct(); - } else { - switch (set_node->children_[0]->type_) { - case T_ALL: - select_stmt->assign_set_all(); - break; - case T_DISTINCT: - select_stmt->assign_set_distinct(); - break; - default: - ret = OB_ERR_OPERATOR_UNKNOWN; - LOG_WARN("unknown set operator of set option"); - break; - } - } } return ret; } -int ObSelectResolver::is_set_type_same(const ObSelectStmt *select_stmt, - ParseNode *set_node, +int ObSelectResolver::is_set_type_same(const ObSelectStmt &select_stmt, + const ParseNode *set_node, bool &is_type_same) { int ret = OB_SUCCESS; is_type_same = false; if (OB_ISNULL(set_node)) { /*do nothing*/ - } else if ((ObSelectStmt::INTERSECT == select_stmt->get_set_op() + } else if ((ObSelectStmt::INTERSECT == select_stmt.get_set_op() && T_SET_INTERSECT == set_node->type_) - || (ObSelectStmt::EXCEPT == select_stmt->get_set_op() + || (ObSelectStmt::EXCEPT == select_stmt.get_set_op() && T_SET_EXCEPT == set_node->type_)) { is_type_same = true; - } else if (ObSelectStmt::UNION == select_stmt->get_set_op() && T_SET_UNION == set_node->type_) { - if (1 != set_node->num_child_) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("wrong num_child_", K(set_node->num_child_)); - } else if (NULL == set_node->children_[0] || T_DISTINCT == set_node->children_[0]->type_) { - is_type_same = select_stmt->is_set_distinct(); - } else if (T_ALL == set_node->children_[0]->type_) { - is_type_same = !select_stmt->is_set_distinct(); + } else if (ObSelectStmt::UNION == select_stmt.get_set_op()) { + if (T_SET_UNION == set_node->type_) { + is_type_same = select_stmt.is_set_distinct(); + } else if (T_SET_UNION_ALL == set_node->type_) { + is_type_same = !select_stmt.is_set_distinct(); } else { - ret = OB_ERR_OPERATOR_UNKNOWN; - LOG_WARN("unknown set operator of set option"); + is_type_same = false; } } else { is_type_same = false; @@ -1576,8 +1517,8 @@ int ObSelectResolver::resolve(const ParseNode &parse_tree) int ObSelectResolver::resolve_query_options(const ParseNode *node) { int ret = OB_SUCCESS; - bool is_set_distinct = false; - bool is_set_all = false; + bool is_distinct = false; + bool is_all = false; ObSelectStmt *select_stmt = get_select_stmt(); if (OB_ISNULL(select_stmt)) { ret = OB_NOT_INIT; @@ -1592,9 +1533,9 @@ int ObSelectResolver::resolve_query_options(const ParseNode *node) for (int64_t i = 0; OB_SUCC(ret) && i < node->num_child_; i++) { option_node = node->children_[i]; if (option_node->type_ == T_DISTINCT) { - is_set_distinct = true; + is_distinct = true; } else if (option_node->type_ == T_ALL) { - is_set_all = true; + is_all = true; } else if (option_node->type_ == T_FOUND_ROWS) { if (has_calc_found_rows_) { has_calc_found_rows_ = false; @@ -1610,10 +1551,10 @@ int ObSelectResolver::resolve_query_options(const ParseNode *node) } if (OB_SUCC(ret)) { //默认为all - if (is_set_all && is_set_distinct) { + if (is_all && is_distinct) { ret = OB_ERR_WRONG_USAGE; LOG_USER_ERROR(OB_ERR_WRONG_USAGE, "ALL and DISTINCT"); - } else if (is_set_distinct) { + } else if (is_distinct) { select_stmt->assign_distinct(); } else { select_stmt->assign_all(); @@ -6262,7 +6203,9 @@ int ObSelectResolver::resolve_win_func_exprs(ObRawExpr *&expr, common::ObIArray< if (OB_SUCC(ret)) { if (OB_FAIL(check_ntile_compatiable_with_mysql(win_expr))) { LOG_WARN("failed to handle compat with mysql ntile.", K(ret)); - } else if (OB_ISNULL(final_win_expr = select_stmt->get_same_win_func_item(win_expr))) { + } else if (OB_FAIL(select_stmt->get_same_win_func_item(win_expr, final_win_expr))) { + LOG_WARN("failed to get same win func item", K(ret)); + } else if (OB_ISNULL(final_win_expr)) { ret = select_stmt->add_window_func_expr(win_expr); } else if (OB_FAIL(ObRawExprUtils::replace_ref_column(expr, win_exprs.at(i), final_win_expr))) { LOG_WARN("failed to replace ref column.", K(ret), K(*win_exprs.at(i))); @@ -6942,6 +6885,8 @@ int ObSelectResolver::check_ntile_validity(const ObSelectStmt *stmt, if (OB_ISNULL(stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt is null", K(ret)); + } else if (stmt->is_const_values_table_query()) { + is_valid = true; } else if (stmt->get_column_size() > 0 || stmt->get_window_func_count() > 0 || stmt->get_aggr_item_size() > 0) { @@ -7514,6 +7459,281 @@ int ObSelectResolver::check_listagg_aggr_param_valid(ObAggFunRawExpr *aggr_expr) return ret; } +int ObSelectResolver::try_resolve_values_table_from_union(const ParseNode &parse_node, + bool &resolve_happened) +{ + int ret = OB_SUCCESS; + bool is_valid = true; + ObSEArray leaf_nodes; + ObValuesTableDef *table_def = NULL; + ObSelectStmt *select_stmt = get_select_stmt(); + const bool is_oracle_mode = lib::is_oracle_mode(); + resolve_happened = false; + if (OB_ISNULL(session_info_) || OB_ISNULL(allocator_) || OB_ISNULL(select_stmt) || + OB_ISNULL(parse_node.children_[PARSE_SELECT_SET])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null pointer", K(ret)); + } else if (OB_FAIL(set_stmt_set_type(select_stmt, parse_node.children_[PARSE_SELECT_SET]))) { + LOG_WARN("failed to set stmt set type", K(ret)); + } else if (OB_FAIL(check_union_to_values_table_valid(parse_node, *select_stmt, leaf_nodes, + is_valid))) { + LOG_WARN("failed to check set to values stmt valid", K(ret)); + } else if (!is_valid) { + /* do nothing */ + } else { + if (is_oracle_mode && (cte_ctx_.is_set_left_resolver_ || + (!cte_ctx_.is_set_left_resolver_ && cte_ctx_.more_than_two_branch()))) { + ret = OB_ERR_NEED_ONLY_TWO_BRANCH_IN_RECURSIVE_CTE; + LOG_WARN("UNION ALL operation in recursive WITH clause must have only two branches", K(ret)); + } else if (OB_FAIL(resolve_into_clause(ObResolverUtils::get_select_into_node(parse_node)))) { + LOG_WARN("failed to resolve into clause", K(ret)); + } else if (OB_FAIL(resolve_with_clause(parse_node.children_[PARSE_SELECT_WITH]))) { + LOG_WARN("failed to resolve with clause", K(ret)); + } else if (OB_FAIL(resolve_values_table_from_union(leaf_nodes, table_def))) { + LOG_WARN("failed to resolve values table def from union", K(ret)); + } else if (OB_FAIL(ObResolverUtils::create_values_table_query(session_info_, allocator_, + params_.expr_factory_, params_.query_ctx_, + select_stmt, table_def))) { + LOG_WARN("failed to resolve values table query", K(ret)); + } else if (OB_FAIL(resolve_order_clause(parse_node.children_[PARSE_SELECT_ORDER]))) { + LOG_WARN("failed to resolve order clause", K(ret)); + } else if (OB_FAIL(resolve_limit_clause(parse_node.children_[PARSE_SELECT_LIMIT]))) { + LOG_WARN("failed to resolve limit clause", K(ret)); + } else if (OB_FAIL(resolve_fetch_clause(parse_node.children_[PARSE_SELECT_FETCH]))) { + LOG_WARN("failed to resolve fetch clause", K(ret)); + } else if (OB_FAIL(resolve_check_option_clause( + parse_node.children_[PARSE_SELECT_WITH_CHECK_OPTION]))) { + LOG_WARN("failed to resolve check option clause", K(ret)); + } else if (OB_FAIL(select_stmt->formalize_stmt(session_info_))) { + LOG_WARN("failed to formalize stmt", K(ret)); + } else if (OB_FAIL(check_order_by())) { + LOG_WARN("failed to check order by", K(ret)); + } else if (has_top_limit_) { + has_top_limit_ = false; + select_stmt->set_has_top_limit(NULL != parse_node.children_[PARSE_SELECT_LIMIT]); + } + if (OB_SUCC(ret)) { + if (select_stmt->is_set_distinct()) { + select_stmt->assign_distinct(); + } else { + select_stmt->assign_all(); + } + select_stmt->assign_set_all(); + select_stmt->assign_set_op(ObSelectStmt::NONE); + } + if (OB_SUCC(ret)) { + resolve_happened = true; + LOG_TRACE("resolve union to values statement happened"); + } + } + return ret; +} + +int ObSelectResolver::check_union_to_values_table_valid(const ParseNode &parse_node, + const ObSelectStmt &select_stmt, + ObIArray &leaf_nodes, + bool &is_valid) +{ + int ret = OB_SUCCESS; + ObSEArray node_stack; + const int64_t UNION_TO_VALUES_THRESHOLD = 2; + int64_t top = 0; + bool is_type_same = false; + is_valid = true; + uint64_t optimizer_version = 0; + const ParseNode *set_node = parse_node.children_[PARSE_SELECT_SET]; + if (OB_ISNULL(session_info_) || OB_ISNULL(set_node)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("got unexpected ptr", K(ret)); + } else if (OB_FAIL(session_info_->get_optimizer_features_enable_version(optimizer_version))) { + LOG_WARN("failed to get optimizer feature enable version", K(ret)); + } else if (optimizer_version < COMPAT_VERSION_4_2_3 || + (optimizer_version >= COMPAT_VERSION_4_3_0 && optimizer_version < COMPAT_VERSION_4_3_5)) { + is_valid = false; + LOG_TRACE("rewrite not happened", K(optimizer_version)); + } else if ((T_SET_UNION != set_node->type_ && T_SET_UNION_ALL != set_node->type_) || + params_.is_from_create_view_ || params_.is_from_create_table_ || + in_pl_ || is_prepare_stage_) { + is_valid = false; + LOG_TRACE("rewrite not happened"); + } else { + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < set_node->num_child_; i++) { + if (OB_FAIL(check_union_leaf_to_values_table_valid(*set_node->children_[i], is_valid))) { + LOG_WARN("failed to check subquery to values stmt valid", K(ret)); + } else if (is_valid && + OB_FAIL(leaf_nodes.push_back(reinterpret_cast(set_node->children_[i])))) { + LOG_WARN("failed to push back", K(ret)); + } else if (!is_valid) { + LOG_TRACE("leaf node is invalid", K(i)); + } + } + } + if (OB_SUCC(ret) && is_valid && leaf_nodes.count() < UNION_TO_VALUES_THRESHOLD) { + is_valid = false; + LOG_TRACE("set count is invalid", K(leaf_nodes.count())); + } + return ret; +} + +int ObSelectResolver::check_union_leaf_to_values_table_valid(const ParseNode &parse_node, + bool &is_valid) +{ + int ret = OB_SUCCESS; + is_valid = true; + /* 1. only has select_item and distinct */ + for (int64_t i = 0; is_valid && i < PARSE_SELECT_MAX_IDX; i++) { + if (parse_node.children_[i] != NULL) { + if (PARSE_SELECT_SELECT != i && PARSE_SELECT_DISTINCT != i) { + is_valid = false; + } + } + } + /* 2. select item must be const param */ + const ParseNode *project_list = parse_node.children_[PARSE_SELECT_SELECT]; + if (!is_valid) { /* do nothing */ + } else if (project_list == NULL || project_list->type_ != T_PROJECT_LIST || + project_list->num_child_ < 1) { + is_valid = false; + } else { + ObCollationType connect_collation = CS_TYPE_INVALID; + int64_t server_collation = CS_TYPE_INVALID; + const ParamStore *param_store = (NULL != params_.secondary_namespace_) ? NULL : params_.param_list_; + bool enable_decimal_int = false; + if (OB_ISNULL(session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("got unexpected ptr", K(ret)); + } else if (OB_FAIL(session_info_->get_collation_connection(connect_collation))) { + LOG_WARN("fail to get collation_connection", K(ret)); + } else if (OB_FAIL(ObSQLUtils::check_enable_decimalint(session_info_, enable_decimal_int))) { + LOG_WARN("fail to check enable decimal int", K(ret)); + } else if (lib::is_oracle_mode() && OB_FAIL(session_info_->get_sys_variable( + share::SYS_VAR_COLLATION_SERVER, server_collation))) { + LOG_WARN("failed to get sys variable"); + } else { + const ObCollationType nchar_collation = session_info_->get_nls_collation_nation(); + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < project_list->num_child_; i++) { + const ParseNode *param_node = NULL; + ObObjType param_type; + ObCollationType dummy_collation_type; + ObCollationLevel dummy_collation_level; + if (OB_ISNULL(project_list->children_[i]) || + OB_UNLIKELY(project_list->children_[i]->num_child_ < 1) || + OB_ISNULL(param_node = project_list->children_[i]->children_[0])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("project node is invalid", K(ret)); + } else if (T_ALIAS == param_node->type_ && + OB_ISNULL(param_node = param_node->children_[0])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("project node is invalid", K(ret)); + } else if (!IS_DATATYPE_OR_QUESTIONMARK_OP(param_node->type_)) { + is_valid = false; + } else if (OB_FAIL(ObResolverUtils::fast_get_param_type(*param_node, param_store, + connect_collation, nchar_collation, + static_cast(server_collation), + enable_decimal_int, *allocator_, param_type, + dummy_collation_type, dummy_collation_level))) { + LOG_WARN("failed to fast get param type", K(ret)); + } else if (ob_is_enum_or_set_type(param_type) || is_lob_locator(param_type)) { + is_valid = false; + } + } + } + } + return ret; +} + +int ObSelectResolver::resolve_values_table_from_union(const ObIArray &leaf_nodes, + ObValuesTableDef *&table_def) +{ + int ret = OB_SUCCESS; + void *table_buf = NULL; + current_scope_ = T_FIELD_LIST_SCOPE; + ObSelectStmt *select_stmt = get_select_stmt(); + if (OB_ISNULL(allocator_) || OB_ISNULL(select_stmt) || OB_UNLIKELY(leaf_nodes.empty())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("got unexpected NULL ptr", K(ret)); + } else if (OB_ISNULL(table_buf = allocator_->alloc(sizeof(ObValuesTableDef)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("sub_query or table_buf is null", K(ret), KP(table_buf)); + } else { + table_def = new (table_buf) ObValuesTableDef(); + table_def->row_cnt_ = leaf_nodes.count(); + table_def->access_type_ = ObValuesTableDef::ACCESS_EXPR; + table_def->is_const_ = true; + } + int64_t column_cnt = 0; + /* first set, need resolve select_item name*/ + if (OB_SUCC(ret)) { + const ParseNode *node = reinterpret_cast(leaf_nodes.at(0)); + const ParseNode *project_list = NULL; + if (OB_ISNULL(node) || OB_ISNULL(node->children_[PARSE_SELECT_SELECT])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null pointer", K(ret), KP(node)); + } else if (OB_FAIL(resolve_query_options(node->children_[PARSE_SELECT_DISTINCT]))) { + LOG_WARN("failed to resolve query options", K(ret)); + } else if (OB_FAIL(resolve_field_list(*node->children_[PARSE_SELECT_SELECT]))) { + LOG_WARN("failed to resolve field list", K(ret)); + } else { + column_cnt = select_stmt->get_select_item_size(); + table_def->column_cnt_ = column_cnt; + for (int64_t i = 0; OB_SUCC(ret) && i < column_cnt; i++) { + SelectItem &select_item = select_stmt->get_select_item(i); + if (OB_FAIL(table_def->access_exprs_.push_back(select_item.expr_))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + } + /* other set */ + for (int64_t i = 1; OB_SUCC(ret) && i < leaf_nodes.count(); i++) { + const ParseNode *node = reinterpret_cast(leaf_nodes.at(i)); + const ParseNode *project_list = NULL; + if (OB_ISNULL(node) || OB_ISNULL(project_list = node->children_[PARSE_SELECT_SELECT]) || + OB_UNLIKELY(project_list->type_ != T_PROJECT_LIST)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null pointer", K(ret), KP(node), KP(project_list)); + } else if (OB_FAIL(resolve_query_options(node->children_[PARSE_SELECT_DISTINCT]))) { + LOG_WARN("failed to resolve query options", K(ret)); + } else if (OB_UNLIKELY(project_list->num_child_ != column_cnt)) { + ret = OB_ERR_COLUMN_SIZE; + LOG_WARN("The used SELECT statements have a different number of columns", K(ret), + K(column_cnt), K(project_list->num_child_)); + } else { + for (int64_t j = 0; OB_SUCC(ret) && j < column_cnt; j++) { + const ParseNode *param_node = NULL; + ObRawExpr *select_expr = NULL; + if (OB_ISNULL(project_list->children_[j]) || + OB_UNLIKELY(project_list->children_[j]->num_child_ < 1) || + OB_ISNULL(param_node = project_list->children_[j]->children_[0])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("project node is invalid", K(ret)); + } else if (T_ALIAS == param_node->type_ && + OB_ISNULL(param_node = param_node->children_[0])) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("project node is invalid", K(ret)); + } else if (OB_FAIL(resolve_sql_expr(*param_node, select_expr))) { + LOG_WARN("resolve sql expr failed", K(ret)); + } else if (OB_FAIL(table_def->access_exprs_.push_back(select_expr))) { + LOG_WARN("failed to push back select expr", K(ret)); + } + } + } + } + /* add cast */ + if (OB_SUCC(ret)) { + if (OB_FAIL(ObOptimizerUtil::try_add_cast_to_select_list(allocator_, session_info_, + params_.expr_factory_, column_cnt, + select_stmt->is_set_distinct(), + table_def->access_exprs_, + &table_def->column_types_))) { + LOG_WARN("failed to add cast to select list", K(ret)); + } else if (OB_FAIL(estimate_values_table_stats(*table_def))) { + LOG_WARN("failed to estimate values table stats", K(ret)); + } + } + return ret; +} + int ObSelectResolver::check_audit_log_stmt(ObSelectStmt *select_stmt) { int ret = OB_SUCCESS; diff --git a/src/sql/resolver/dml/ob_select_resolver.h b/src/sql/resolver/dml/ob_select_resolver.h index c3163d245e..b299c35d6f 100644 --- a/src/sql/resolver/dml/ob_select_resolver.h +++ b/src/sql/resolver/dml/ob_select_resolver.h @@ -105,18 +105,15 @@ public: protected: int resolve_set_query(const ParseNode &parse_node); - int do_resolve_set_query_in_cte(const ParseNode &parse_tree, bool swap_branch); - int do_resolve_set_query(const ParseNode &parse_tree); + int do_resolve_set_query_in_recursive_cte(const ParseNode &parse_tree); + int do_resolve_set_query_in_normal(const ParseNode &parse_tree); int resolve_set_query_hint(); - int do_resolve_set_query(const ParseNode &parse_tree, - common::ObIArray &child_stmt, - const bool is_left_child = false); virtual int do_resolve_set_query(const ParseNode &parse_tree, ObSelectStmt *&child_stmt, const bool is_left_child = false); int check_cte_set_types(ObSelectStmt &left_stmt, ObSelectStmt &right_stmt); int set_stmt_set_type(ObSelectStmt *select_stmt, ParseNode *set_node); - int is_set_type_same(const ObSelectStmt *select_stmt, ParseNode *set_node, bool &is_type_same); + int is_set_type_same(const ObSelectStmt &select_stmt, const ParseNode *set_node, bool &is_type_same); int check_recursive_cte_limited(); int check_pseudo_column_name_legal(const ObString& name); int search_connect_group_by_clause(const ParseNode &parent, @@ -270,11 +267,12 @@ protected: const ObItemType func_type, common::ObIArray &arg_exp_arr, common::ObIArray &partition_exp_arr); - int check_query_is_recursive_union(const ParseNode &parse_tree, bool &recursive_union, bool &need_swap_child); + int check_query_is_recursive_union(const ParseNode &parse_tree, bool &recursive_union); int do_check_basic_table_in_cte_recursive_union(const ParseNode &parse_tree, bool &recursive_union); int do_check_node_in_cte_recursive_union(const ParseNode* node, bool &recursive_union); int resolve_fetch_clause(const ParseNode *node); int resolve_check_option_clause(const ParseNode *node); + int check_set_child_stmt_pullup(const ObSelectStmt &child_stmt, bool &enable_pullup); int transfer_rb_iterate_items(); private: @@ -367,6 +365,14 @@ private: int mark_aggr_in_select_scope(ObSelectStmt *select_stmt); int check_audit_log_stmt(ObSelectStmt *select_stmt); + int try_resolve_values_table_from_union(const ParseNode &parse_node, bool &resolve_happened); + int check_union_to_values_table_valid(const ParseNode &parse_node, + const ObSelectStmt &select_stmt, + ObIArray &leaf_nodes, + bool &is_valid); + int check_union_leaf_to_values_table_valid(const ParseNode &parse_node, bool &is_valid); + int resolve_values_table_from_union(const ObIArray &values_nodes, + ObValuesTableDef *&table_def); protected: // data members /*these member is only for with clause*/ diff --git a/src/sql/resolver/dml/ob_select_stmt.cpp b/src/sql/resolver/dml/ob_select_stmt.cpp index f069d60126..8a04e5c78c 100644 --- a/src/sql/resolver/dml/ob_select_stmt.cpp +++ b/src/sql/resolver/dml/ob_select_stmt.cpp @@ -15,6 +15,7 @@ #include "sql/resolver/expr/ob_raw_expr.h" #include "sql/resolver/expr/ob_raw_expr_util.h" #include "sql/resolver/ob_schema_checker.h" +#include "sql/resolver/expr/ob_shared_expr_resolver.h" #include "sql/rewrite/ob_transform_utils.h" #include "sql/engine/expr/ob_expr_operator.h" #include "sql/session/ob_sql_session_info.h" @@ -265,6 +266,7 @@ int ObSelectStmt::assign(const ObSelectStmt &other) has_reverse_link_ = other.has_reverse_link_; is_expanded_mview_ = other.is_expanded_mview_; is_select_straight_join_ = other.is_select_straight_join_; + is_implicit_distinct_ = false; // it is a property from upper stmt, do not copy } return ret; } @@ -361,6 +363,7 @@ int ObSelectStmt::deep_copy_stmt_struct(ObIAllocator &allocator, has_reverse_link_ = other.has_reverse_link_; is_expanded_mview_ = other.is_expanded_mview_; is_select_straight_join_ = other.is_select_straight_join_; + is_implicit_distinct_ = false; // it is a property from upper stmt, do not copy // copy insert into statement if (OB_SUCC(ret) && NULL != other.into_item_) { ObSelectIntoItem *temp_into_item = NULL; @@ -577,6 +580,7 @@ ObSelectStmt::ObSelectStmt() has_reverse_link_ = false; is_expanded_mview_ = false; is_select_straight_join_ = false; + is_implicit_distinct_ = false; } ObSelectStmt::~ObSelectStmt() @@ -706,12 +710,14 @@ const ObSelectStmt* ObSelectStmt::get_real_stmt() const return cur_stmt; } -int ObSelectStmt::get_from_subquery_stmts(ObIArray &child_stmts) const +int ObSelectStmt::get_from_subquery_stmts(ObIArray &child_stmts, + bool contain_lateral_table/* =true */) const { int ret = OB_SUCCESS; if (OB_FAIL(child_stmts.assign(set_query_))) { LOG_WARN("failed to assign child query", K(ret)); - } else if (OB_FAIL(ObDMLStmt::get_from_subquery_stmts(child_stmts))) { + } else if (OB_FAIL(ObDMLStmt::get_from_subquery_stmts(child_stmts, + contain_lateral_table))) { LOG_WARN("get from subquery stmts failed", K(ret)); } return ret; @@ -773,7 +779,8 @@ int ObSelectStmt::do_to_string(char *buf, const int64_t buf_len, int64_t &pos) c K_(check_option), K_(dblink_id), K_(is_reverse_link), - K_(is_expanded_mview) + K_(is_expanded_mview), + K_(is_implicit_distinct) ); } } else { @@ -787,7 +794,8 @@ int ObSelectStmt::do_to_string(char *buf, const int64_t buf_len, int64_t &pos) c N_SELECT, select_items_, K(child_stmts), K_(dblink_id), - K_(is_reverse_link)); + K_(is_reverse_link), + K_(is_implicit_distinct)); } J_OBJ_END(); return ret; @@ -816,17 +824,28 @@ int ObSelectStmt::check_and_get_same_aggr_item(ObRawExpr *expr, return ret; } -ObWinFunRawExpr *ObSelectStmt::get_same_win_func_item(const ObRawExpr *expr) +int ObSelectStmt::get_same_win_func_item(const ObRawExpr *expr, ObWinFunRawExpr *&win_expr) { - ObWinFunRawExpr *win_expr = NULL; - for (int64_t i = 0; i < win_func_exprs_.count(); ++i) { - if (win_func_exprs_.at(i) != NULL && expr != NULL && - expr->same_as(*win_func_exprs_.at(i))) { - win_expr = win_func_exprs_.at(i); - break; + int ret = OB_SUCCESS; + win_expr = NULL; + if (OB_ISNULL(query_ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else { + ObQuestionmarkEqualCtx cmp_ctx; + for (int64_t i = 0; i < win_func_exprs_.count(); ++i) { + if (win_func_exprs_.at(i) != NULL && expr != NULL && + expr->same_as(*win_func_exprs_.at(i), &cmp_ctx)) { + win_expr = win_func_exprs_.at(i); + break; + } + } + if (OB_FAIL(append(query_ctx_->all_equal_param_constraints_, + cmp_ctx.equal_pairs_))) { + LOG_WARN("failed to append equal param info", K(ret)); } } - return win_expr; + return ret; } bool ObSelectStmt::has_for_update() const @@ -1524,6 +1543,131 @@ int ObSelectStmt::check_is_simple_lock_stmt(bool &is_valid) const return ret; } +/** + * @brief ObSelectStmt::formalize_implicit_distinct + * + * 1. Check current stmt is legal for implicit distinct + * 2. Set implicit distinct for subquery + */ +int ObSelectStmt::formalize_implicit_distinct() +{ + int ret = OB_SUCCESS; + if (!is_implicit_distinct_allowed()) { + reset_implicit_distinct(); + } + if (OB_FAIL(ObDMLStmt::formalize_implicit_distinct())) { + LOG_WARN("failed to do formalize implicit distinct", K(ret)); + } + return ret; +} + +/** + * @brief ObSelectStmt::check_from_dup_insensitive + * + * Stmt contains duplicate-insensitive aggregation or DISTINCT, making it + * insensitive to duplicate values ​​in From Scope. + * + * e.g. + * SELECT DISTINCT * FROM T1, T2; + * SELECT MAX(C1), MIN(C2) FROM T3; + * SELECT * FROM T4 LIMIT 1; + */ +int ObSelectStmt::check_from_dup_insensitive(bool &is_from_dup_insens) const +{ + int ret = OB_SUCCESS; + bool is_valid = true; + bool is_has_rownum = false; + bool is_dup_insens_aggr = false; + is_from_dup_insens = false; + // basic validity check + if (is_set_stmt() || is_hierarchical_query()) { + is_valid = false; + } else if (OB_FAIL(check_relation_exprs_deterministic(is_valid))) { + LOG_WARN("failed to check relation exprs deterministic", K(ret)); + } else if (!is_valid) { + // do nothing + } else if (OB_FAIL(has_rownum(is_has_rownum))) { + LOG_WARN("failed to check has rownum", K(ret)); + } else if (is_has_rownum) { + is_valid = false; + } + + // check whether stmt has aggregation duplicate-insensitive + if (OB_FAIL(ret) || !is_valid) { + // do nothing + } else if (OB_FAIL(is_duplicate_insensitive_aggregation(is_dup_insens_aggr))) { + LOG_WARN("failed to check has duplicate-insensitive aggregation", K(ret)); + } else if (is_dup_insens_aggr) { + is_from_dup_insens = true; + } else if (has_group_by() || has_window_function()) { + is_valid = false; + } + + // check whether stmt has distinct duplicate-insensitive + if (OB_FAIL(ret) || !is_valid || is_from_dup_insens) { + // do nothing + } else if (!(is_distinct() || is_implicit_distinct())) { + // do nothing + } else { + is_from_dup_insens = true; + } + + // check whether stmt has limit 1 + if (OB_FAIL(ret) || !is_valid || is_from_dup_insens) { + // do nothing + } else if (NULL == limit_count_expr_ + || NULL != limit_offset_expr_ + || NULL != limit_percent_expr_) { + // do nothing + } else if (T_INT != limit_count_expr_->get_expr_type() + || 1 != static_cast(limit_count_expr_)->get_value().get_int()) { + // do nothing + } else { + is_from_dup_insens = true; + } + return ret; +} + +/** + * @brief ObSelectStmt::is_duplicate_insensitive_aggregation + * + * Check whether the select stmt has duplicate-insensitive aggregation. + * The stmt should have group by and only contain aggregate function listed: BIT_AND(), + * BIT_OR(), MAX(), MIN() APPROX_COUNT_DISTINCT(), and other aggr func with DISTINCT. + * + * @param is_dup_insens_aggr True if select stmt has duplicate-insensitive aggregation. + */ +int ObSelectStmt::is_duplicate_insensitive_aggregation(bool &is_dup_insens_aggr) const +{ + int ret = OB_SUCCESS; + is_dup_insens_aggr = false; + if (!has_group_by()) { + // do nothing + } else { + is_dup_insens_aggr = true; + for (int64_t i = 0; OB_SUCC(ret) && is_dup_insens_aggr && i < get_aggr_item_size(); ++i) { + const ObAggFunRawExpr *agg_expr = get_aggr_item(i); + if (OB_ISNULL(agg_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("agg expr is null", K(ret)); + } else if (agg_expr->get_expr_type() == T_FUN_SYS_BIT_AND + || agg_expr->get_expr_type() == T_FUN_SYS_BIT_OR + || agg_expr->get_expr_type() == T_FUN_MAX + || agg_expr->get_expr_type() == T_FUN_MIN + || agg_expr->get_expr_type() == T_FUN_APPROX_COUNT_DISTINCT + || agg_expr->get_expr_type() == T_FUN_APPROX_COUNT_DISTINCT_SYNOPSIS) { + // do nothing, it is valid aggregate function + } else if (agg_expr->is_param_distinct()) { + // do nothing, it is valid aggregate function + } else { + is_dup_insens_aggr = false; + break; + } + } + } + return ret; +} + int ObSelectStmt::is_query_deterministic(bool &is_deterministic) const { int ret = OB_SUCCESS; @@ -1572,3 +1716,11 @@ int ObSelectStmt::is_query_deterministic(bool &is_deterministic) const } return ret; } + +bool ObSelectStmt::is_implicit_distinct_allowed() const +{ + return !(is_unpivot_select() + || is_hierarchical_query() + || has_for_update() + || has_limit()); +} diff --git a/src/sql/resolver/dml/ob_select_stmt.h b/src/sql/resolver/dml/ob_select_stmt.h index 0805900b59..b80d2ba8d9 100644 --- a/src/sql/resolver/dml/ob_select_stmt.h +++ b/src/sql/resolver/dml/ob_select_stmt.h @@ -627,14 +627,15 @@ public: */ bool equals(const ObSelectStmt &stmt); int check_and_get_same_aggr_item(ObRawExpr *expr, ObAggFunRawExpr *&same_aggr); - ObWinFunRawExpr *get_same_win_func_item(const ObRawExpr *expr); + int get_same_win_func_item(const ObRawExpr *expr, ObWinFunRawExpr *&win_expr); void set_match_topk(bool is_match) { is_match_topk_ = is_match; } bool is_match_topk() const { return is_match_topk_; } bool is_set_stmt() const { return NONE != set_op_; } int get_child_stmt_size(int64_t &child_size) const; int get_child_stmts(common::ObIArray &child_stmts) const; int set_child_stmt(const int64_t child_num, ObSelectStmt* child_stmt); - int get_from_subquery_stmts(common::ObIArray &child_stmts) const; + virtual int get_from_subquery_stmts(common::ObIArray &child_stmts, + bool contain_lateral_table = true) const override; const common::ObIArray &get_window_func_exprs() const { return win_func_exprs_; }; common::ObIArray &get_window_func_exprs() { return win_func_exprs_; }; bool has_window_function() const { return win_func_exprs_.count() != 0; } @@ -698,6 +699,13 @@ public: void set_select_straight_join(bool flag) { is_select_straight_join_ = flag; } bool is_select_straight_join() const { return is_select_straight_join_; } virtual int check_is_simple_lock_stmt(bool &is_valid) const override; + inline bool is_implicit_distinct() const { return is_implicit_distinct_; } + virtual int formalize_implicit_distinct() override; + virtual int check_from_dup_insensitive(bool &is_from_dup_insens) const override; + int is_duplicate_insensitive_aggregation(bool &is_dup_insens_aggr) const; + bool is_implicit_distinct_allowed() const; + inline void set_implicit_distinct(bool v) { is_implicit_distinct_ = v; } + inline void reset_implicit_distinct() { is_implicit_distinct_ = false; } int is_query_deterministic(bool &is_deterministic) const; private: @@ -763,6 +771,9 @@ private: bool is_expanded_mview_; //denote if the query option 'STRAIGHT_JOIN' has been specified bool is_select_straight_join_; + // denote if the duplicate value of this stmt will not change the query result + // optimizer can assign or remove DISTINCT for this stmt + bool is_implicit_distinct_; }; } } diff --git a/src/sql/resolver/expr/ob_raw_expr.cpp b/src/sql/resolver/expr/ob_raw_expr.cpp index c4fc344d53..75dabb6ea7 100644 --- a/src/sql/resolver/expr/ob_raw_expr.cpp +++ b/src/sql/resolver/expr/ob_raw_expr.cpp @@ -285,6 +285,7 @@ int ObRawExpr::assign(const ObRawExpr &other) partition_id_calc_type_ = other.partition_id_calc_type_; local_session_var_id_ = other.local_session_var_id_; runtime_filter_type_ = other.runtime_filter_type_; + expr_hash_ = other.expr_hash_; if (OB_FAIL(enum_set_values_.assign(other.enum_set_values_))) { LOG_WARN("failed to assign enum set values", K(ret)); } else if (OB_FAIL(local_session_var_.assign(other.local_session_var_))) { @@ -478,6 +479,8 @@ int ObRawExpr::formalize(const ObSQLSessionInfo *session_info, LOG_WARN("failed to extract info", K(*this)); } else if (OB_FAIL(deduce_type(session_info, solidify_session_vars, local_vars, local_var_id))) { LOG_WARN("failed to deduce type", K(*this)); + } else if (OB_FAIL(calc_hash())) { + LOG_WARN("failed to calc hash", K(*this)); } else {} return ret; } @@ -827,6 +830,10 @@ bool ObRawExpr::same_as(const ObRawExpr &expr, int ret = OB_SUCCESS; if (this == &expr) { bret = true; +#ifndef ENABLE_DEBUG_LOG + } else if (is_hash_different(expr, check_context)) { + bret = false; +#endif } else { if (NULL != check_context) { check_context->recursion_level_ += 1; @@ -848,10 +855,55 @@ bool ObRawExpr::same_as(const ObRawExpr &expr, //check if local vars are the same bret = (l->get_local_session_var() == r->get_local_session_var()); } +#ifdef ENABLE_DEBUG_LOG + if (bret && is_hash_different(expr, check_context)) { + const ObFatalErrExtraInfoGuard *info = ObFatalErrExtraInfoGuard::get_thd_local_val_ptr(); + LOG_WARN("expr hash should not be different", K(bret), KPC(this), K(expr), KPC(info)); + } +#endif } return bret; } +int ObRawExpr::calc_hash() +{ + int ret = OB_SUCCESS; + for (int64_t i = 0; OB_SUCC(ret) && i < get_param_count(); ++i) { + if (OB_ISNULL(get_param_expr(i))){ + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(SMART_CALL(get_param_expr(i)->calc_hash()))) { + LOG_WARN("fail to extract sysvar from params", K(ret)); + } + } + if (OB_SUCC(ret)) { + expr_hash_ = 0; + if (is_domain_json_expr() || IS_QUERY_JSON_EXPR(get_expr_type())) { + // Multivalue index matching need make two expr with different expr type to be same + // in ObSysFunRawExpr::inner_same_as. This same_as comparision is not symmetric. + // Set thier expr_hash to 1 temporarily and this will be fixed later. TODO: weiyouchao.wyc + expr_hash_ = 1; + } else { + inner_calc_hash(); + } + } + return ret; +} + +int ObRawExpr::is_hash_different(const ObRawExpr &expr, + ObExprEqualCheckContext *check_context) const +{ + return NULL == check_context && + get_expr_hash() != expr.get_expr_hash() && + get_expr_hash() != 0 && + expr.get_expr_hash() != 0; +} + +void ObRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = result_type_.hash(expr_hash_); +} //////////////////////////////////////////////////////////////// ObRawExpr *&ObTerminalRawExpr::get_param_expr(int64_t index) @@ -1396,6 +1448,13 @@ bool ObConstRawExpr::inner_same_as( return bool_ret; } +void ObConstRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(get_value().get_meta(), expr_hash_); + expr_hash_ = common::do_hash(get_value(), expr_hash_); +} + int ObConstRawExpr::set_local_session_vars(const ObLocalSessionVar *local_sys_vars, const ObBasicSessionInfo *session, int64_t ctx_array_idx) @@ -1545,17 +1604,25 @@ int ObConstRawExpr::get_name_internal(char *buf, const int64_t buf_len, int64_t LOG_WARN("fail to BUF_PRINTF", K(ret)); } } else if (get_value().is_unknown()) { //为explain特殊处理QuestionMark为?,其他地方打印成$IntNum - if (EXPLAIN_DBLINK_STMT != type) { - // if (OB_FAIL(get_value().print_plain_str_literal(buf, buf_len, pos))) { - // LOG_WARN("fail to print_sql_literal", K(get_value()), K(ret)); - // } - if (OB_FAIL(BUF_PRINTF(":%ld", get_value().get_unknown()))) { - LOG_WARN("fail to BUF_PRINTF", K(ret)); - } - } else { + if (EXPLAIN_DBLINK_STMT == type) { if (OB_FAIL(ObLinkStmtParam::write(buf, buf_len, pos, get_value().get_unknown()))) { LOG_WARN("fail to write param to buf", K(ret)); } + } else { + if (OB_FAIL(get_result_type().get_param().print_sql_literal(buf, buf_len, pos))) { + LOG_WARN("fail to print_sql_literal", K(get_result_type().get_param()), K(ret)); + if (OB_ERR_NULL_VALUE == ret) { + ret = OB_SUCCESS; //ignore mull time zone info + } + } else if (EXPLAIN_EXTENDED != type) { + /* do nothing */ + } else if (OB_FAIL(BUF_PRINTF("("))) { + LOG_WARN("fail to BUF_PRINTF", K(ret)); + } else if (OB_FAIL(BUF_PRINTF("%p", this))) { + LOG_WARN("fail to BUF_PRINTF", K(ret)); + } else if (OB_FAIL(BUF_PRINTF(")"))) { + LOG_WARN("fail to BUF_PRINTF", K(ret)); + } } } else { if (OB_FAIL(get_value().print_sql_literal(buf, buf_len, pos))) { @@ -1577,7 +1644,8 @@ int64_t ObConstRawExpr::to_string(char* buf, const int64_t buf_len) const N_RESULT_TYPE, result_type_, N_EXPR_INFO, info_, N_REL_ID, rel_ids_, - N_VALUE, value_); + N_VALUE, value_, + K_(expr_hash)); if (!literal_prefix_.empty()) { J_COMMA(); J_KV(K_(literal_prefix)); @@ -1624,6 +1692,12 @@ bool ObVarRawExpr::inner_same_as(const ObRawExpr &expr, && get_result_type() == expr.get_result_type(); } +void ObVarRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_class(), expr_hash_); + ObRawExpr::inner_calc_hash(); +} + int ObVarRawExpr::get_name_internal(char *buf, const int64_t buf_len, int64_t &pos, ExplainType type) const { @@ -1703,6 +1777,14 @@ bool ObUserVarIdentRawExpr::inner_same_as(const ObRawExpr &expr, return bool_ret; } +void ObUserVarIdentRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(get_value().get_meta(), expr_hash_); + expr_hash_ = common::do_hash(get_value(), expr_hash_); + expr_hash_ = common::do_hash(get_is_contain_assign(), expr_hash_); +} + bool ObUserVarIdentRawExpr::is_same_variable(const ObObj &obj) const { bool bool_ret = false; @@ -1728,7 +1810,8 @@ int64_t ObUserVarIdentRawExpr::to_string(char* buf, const int64_t buf_len) const N_REL_ID, rel_ids_, N_VALUE, value_, "is_contain_assign", is_contain_assign_, - "query_has_udf", query_has_udf_); + "query_has_udf", query_has_udf_, + K_(expr_hash)); J_OBJ_END(); return pos; } @@ -1888,13 +1971,21 @@ bool ObQueryRefRawExpr::inner_same_as( // very tricky, check the definition of ref_stmt_ and get_ref_stmt() bool_ret = (get_ref_id() == u_expr.get_ref_id() && ref_stmt_ == u_expr.ref_stmt_ && - is_set_ == u_expr.is_set_ && - is_multiset_ == u_expr.is_multiset_); + is_set_ == u_expr.is_set_); } } return bool_ret; } +void ObQueryRefRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(is_set_, expr_hash_); + expr_hash_ = common::do_hash(is_multiset_, expr_hash_); + expr_hash_ = common::do_hash(get_ref_id(), expr_hash_); + expr_hash_ = common::do_hash(ref_stmt_, expr_hash_); +} + bool ObExprEqualCheckContext::compare_query(const ObQueryRefRawExpr &left, const ObQueryRefRawExpr &right) { @@ -1950,6 +2041,16 @@ void ObExecParamRawExpr::set_param_index(int64_t index) set_result_type(outer_expr_->get_result_type()); } +void ObExecParamRawExpr::set_param_index(ObQueryCtx &query_ctx) +{ + ObObjParam val; + val.set_unknown(query_ctx.question_marks_count_); + val.set_param_meta(); + set_value(val); + exec_param_idx_ = query_ctx.question_marks_count_ - query_ctx.ori_question_marks_count_; + ++query_ctx.question_marks_count_; +} + int64_t ObExecParamRawExpr::get_param_index() const { int64_t param_index = OB_INVALID_INDEX; @@ -1974,6 +2075,7 @@ int ObExecParamRawExpr::assign(const ObRawExpr &other) outer_expr_ = tmp.outer_expr_; is_onetime_ = tmp.is_onetime_; ref_same_dblink_ = tmp.ref_same_dblink_; + exec_param_idx_ = tmp.exec_param_idx_; eval_by_storage_ = tmp.eval_by_storage_; } } @@ -2021,6 +2123,15 @@ bool ObExecParamRawExpr::inner_same_as(const ObRawExpr &expr, return bret; } +void ObExecParamRawExpr::inner_calc_hash() +{ + // ObRawExpr::get_same_identify will get ref expr from exec param expr + const ObRawExpr *ref_expr = get_ref_expr(); + if (NULL != ref_expr) { + expr_hash_ = ref_expr->get_expr_hash(); + } +} + int ObExecParamRawExpr::do_visit(ObRawExprVisitor &visitor) { return visitor.visit(*this); @@ -2042,18 +2153,30 @@ int ObExecParamRawExpr::get_name_internal(char *buf, ExplainType type) const { int ret = OB_SUCCESS; - if (eval_by_storage_) { + if (EXPLAIN_HINT_FORMAT == type) { if (OB_FAIL(BUF_PRINTF("?"))) { LOG_WARN("fail to BUF_PRINTF", K(ret)); } - } else if (EXPLAIN_DBLINK_STMT != type) { - if (OB_FAIL(ObConstRawExpr::get_name_internal(buf, buf_len, pos, type))) { - LOG_WARN("failed to print const raw expr", K(ret)); + } else if (eval_by_storage_) { + if (OB_FAIL(BUF_PRINTF("?"))) { + LOG_WARN("fail to BUF_PRINTF", K(ret)); } - } else { + } else if (EXPLAIN_DBLINK_STMT == type) { if (OB_FAIL(ObLinkStmtParam::write(buf, buf_len, pos, get_value().get_unknown()))) { LOG_WARN("failed to write param to buf", K(ret)); } + } else { + if (OB_FAIL(BUF_PRINTF(":%ld", exec_param_idx_))) { + LOG_WARN("fail to BUF_PRINTF", K(ret)); + } else if (EXPLAIN_EXTENDED != type) { + /* do nothing */ + } else if (OB_FAIL(BUF_PRINTF("("))) { + LOG_WARN("fail to BUF_PRINTF", K(ret)); + } else if (OB_FAIL(BUF_PRINTF("%p", this))) { + LOG_WARN("fail to BUF_PRINTF", K(ret)); + } else if (OB_FAIL(BUF_PRINTF(")"))) { + LOG_WARN("fail to BUF_PRINTF", K(ret)); + } } return ret; } @@ -2068,6 +2191,7 @@ int64_t ObExecParamRawExpr::to_string(char *buf, const int64_t buf_len) const N_VALUE, value_, K_(outer_expr), K_(is_onetime), + K_(expr_hash), K_(eval_by_storage)); J_OBJ_END(); return pos; @@ -2183,7 +2307,6 @@ bool ObColumnRefRawExpr::inner_same_as( const ObRawExpr &expr, ObExprEqualCheckContext *check_context) const { - UNUSED(check_context); bool bool_ret = false; if (OB_UNLIKELY(check_context != NULL) && OB_UNLIKELY(check_context->override_column_compare_)) { @@ -2201,6 +2324,13 @@ bool ObColumnRefRawExpr::inner_same_as( return bool_ret; } +void ObColumnRefRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(get_table_id(), expr_hash_); + expr_hash_ = common::do_hash(get_column_id(), expr_hash_); +} + bool ObExprEqualCheckContext::compare_column(const ObColumnRefRawExpr &left, const ObColumnRefRawExpr &right) { return left.get_result_type() == right.get_result_type(); @@ -2386,6 +2516,12 @@ bool ObAliasRefRawExpr::inner_same_as(const ObRawExpr &expr, return bret; } +void ObAliasRefRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(get_ref_expr(), expr_hash_); +} + //////////////////////////////////////////////////////////////// ObExprOperator *ObNonTerminalRawExpr::get_op() { @@ -2761,6 +2897,67 @@ bool ObOpRawExpr::inner_same_as( return bool_ret; } +void ObOpRawExpr::inner_calc_hash() +{ + int ret = OB_SUCCESS; + ObItemType regular_expr_type = get_expr_type(); + bool need_param = true; + // this logic is related to ObOpRawExpr::inner_same_as + enum { + REGULAR_CMP = 1, + REVERSE_CMP = 2, + BOTH_CMP = 3 + } cmp_type; + cmp_type = REGULAR_CMP; + + if (get_expr_type() == T_OP_ASSIGN) { + need_param = false; + } else if (T_OP_EQ == get_expr_type() + || T_OP_NSEQ == get_expr_type() + || T_OP_NE == get_expr_type()) { + cmp_type = BOTH_CMP; + } else if (IS_COMMON_COMPARISON_OP(get_expr_type())) { + switch(get_expr_type()) { + case T_OP_GE: + regular_expr_type = T_OP_LE; + cmp_type = REVERSE_CMP; + break; + case T_OP_GT: + regular_expr_type = T_OP_LT; + cmp_type = REVERSE_CMP; + break; + default: + break; + } + } + expr_hash_ = common::do_hash(regular_expr_type, expr_hash_); + if (IS_SUBQUERY_COMPARISON_OP(get_expr_type())) { + expr_hash_ = common::do_hash(get_subquery_comparison_flag(), expr_hash_); + } + if (!need_param) { + } else if (REGULAR_CMP == cmp_type) { + for (int64_t i = 0; i < get_param_count(); ++i) { + if (NULL != get_param_expr(i)) { + expr_hash_ = common::do_hash(get_param_expr(i)->get_expr_hash(), expr_hash_); + } + } + } else if (REVERSE_CMP == cmp_type) { + for (int64_t i = get_param_count() - 1; i >= 0; --i) { + if (NULL != get_param_expr(i)) { + expr_hash_ = common::do_hash(get_param_expr(i)->get_expr_hash(), expr_hash_); + } + } + } else if (BOTH_CMP == cmp_type) { + uint64_t param_hash_sum = 0; + for (int64_t i = 0; i < get_param_count(); ++i) { + if (NULL != get_param_expr(i)) { + param_hash_sum += get_param_expr(i)->get_expr_hash(); + } + } + expr_hash_ = common::do_hash(param_hash_sum, expr_hash_); + } +} + int ObOpRawExpr::do_visit(ObRawExprVisitor &visitor) { return visitor.visit(*this); @@ -3302,6 +3499,14 @@ bool ObObjAccessRawExpr::inner_same_as(const ObRawExpr &expr, return bool_ret; } +void ObObjAccessRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(get_attr_func_, expr_hash_); + expr_hash_ = common::do_hash(for_write_, expr_hash_); + expr_hash_ = common::do_hash(property_type_, expr_hash_); +} + int ObObjAccessRawExpr::add_access_indexs(const ObIArray &access_idxs) { int ret = OB_SUCCESS; @@ -3653,6 +3858,25 @@ bool ObCaseOpRawExpr::inner_same_as( return bool_ret; } +void ObCaseOpRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + if (NULL != arg_expr_) { + expr_hash_ = common::do_hash(arg_expr_->get_expr_hash(), expr_hash_); + } + if (NULL != default_expr_) { + expr_hash_ = common::do_hash(default_expr_->get_expr_hash(), expr_hash_); + } + for (int64_t i = 0; i < get_when_expr_size(); ++i) { + if (NULL != get_when_param_expr(i)) { + expr_hash_ = common::do_hash(get_when_param_expr(i)->get_expr_hash(), expr_hash_); + } + if (NULL != get_then_param_expr(i)) { + expr_hash_ = common::do_hash(get_then_param_expr(i)->get_expr_hash(), expr_hash_); + } + } +} + int ObCaseOpRawExpr::do_visit(ObRawExprVisitor &visitor) { return visitor.visit(*this); @@ -4028,6 +4252,29 @@ bool ObAggFunRawExpr::inner_same_as( return bool_ret; } +void ObAggFunRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(expr_in_inner_stmt_, expr_hash_); + expr_hash_ = common::do_hash(distinct_, expr_hash_); + if (NULL != separator_param_expr_) { + expr_hash_ = common::do_hash(separator_param_expr_->get_expr_hash(), expr_hash_); + } + for (int64_t i = 0; i < real_param_exprs_.count(); ++i) { + if (NULL != real_param_exprs_.at(i)) { + expr_hash_ = common::do_hash(real_param_exprs_.at(i)->get_expr_hash(), expr_hash_); + } + } + for (int64_t i = 0; i < order_items_.count(); ++i) { + if (NULL != order_items_.at(i).expr_) { + expr_hash_ = common::do_hash(order_items_.at(i).expr_->get_expr_hash(), expr_hash_); + } + } + expr_hash_ = common::do_hash(is_need_deserialize_row_, expr_hash_); + if (NULL != pl_agg_udf_expr_) { + expr_hash_ = common::do_hash(pl_agg_udf_expr_->get_expr_hash(), expr_hash_); + } +} int64_t ObAggFunRawExpr::get_param_count() const { @@ -4482,6 +4729,41 @@ bool ObSysFunRawExpr::inner_same_as( return bool_ret; } +void ObSysFunRawExpr::inner_calc_hash() +{ + // ObSysFunRawExpr and ObOpRawExpr both can represent T_OP_CNN, make sure their hash code are same + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + for (int64_t i = 0; i < get_param_count(); i++) { + if (OB_ISNULL(get_param_expr(i))) { + // do nothing + } else if (T_OP_GET_PACKAGE_VAR == get_expr_type() && 2 == i) { + if (T_INT == get_param_expr(i)->get_expr_type()) { + const ObConstRawExpr* val = static_cast(get_param_expr(i)); + ObExprResType* res_type = reinterpret_cast(val->get_value().get_int()); + if (NULL != res_type) { + expr_hash_ = common::do_hash(*res_type, expr_hash_); + } + } + } else { + expr_hash_ = common::do_hash(get_param_expr(i)->get_expr_hash(), expr_hash_); + } + } + if (0 == get_param_count() + && (T_FUN_SYS_CUR_TIMESTAMP == get_expr_type() + || T_FUN_SYS_SYSDATE == get_expr_type() + || T_FUN_SYS_CUR_TIME == get_expr_type() + || T_FUN_SYS_UTC_TIMESTAMP == get_expr_type() + || T_FUN_SYS_UTC_TIME == get_expr_type())) { + expr_hash_ = common::do_hash(result_type_.get_scale(), expr_hash_); + } + if ((T_FUN_SYS == get_expr_type() || + T_FUN_SYS_CALC_TABLET_ID == get_expr_type() || + T_FUN_SYS_CALC_PARTITION_ID == get_expr_type() || + T_FUN_SYS_CALC_PARTITION_TABLET_ID == get_expr_type())) { + expr_hash_ = common::do_hash(get_extra(), expr_hash_); + } +} + ObExprOperator *ObSysFunRawExpr::get_op() { ObExprOperator *op = NULL; @@ -4920,6 +5202,11 @@ bool ObSequenceRawExpr::inner_same_as(const ObRawExpr &expr, return false; } +void ObSequenceRawExpr::inner_calc_hash() +{ + ObRawExpr::inner_calc_hash(); +} + int ObSequenceRawExpr::get_name_internal(char *buf, const int64_t buf_len, int64_t &pos, ExplainType type) const { @@ -5001,6 +5288,11 @@ bool ObNormalDllUdfRawExpr::inner_same_as(const ObRawExpr &expr, return false; } +void ObNormalDllUdfRawExpr::inner_calc_hash() +{ + ObRawExpr::inner_calc_hash(); +} + int ObNormalDllUdfRawExpr::assign(const ObRawExpr &other) { int ret = OB_SUCCESS; @@ -5455,6 +5747,38 @@ bool ObUDFRawExpr::inner_same_as(const ObRawExpr &expr, return bool_ret; } +void ObUDFRawExpr::inner_calc_hash() +{ + ObSysFunRawExpr::inner_calc_hash(); + expr_hash_ = common::do_hash(udf_id_, expr_hash_); + expr_hash_ = common::do_hash(pkg_id_, expr_hash_); + expr_hash_ = common::do_hash(type_id_, expr_hash_); + expr_hash_ = common::do_hash(pls_type_, expr_hash_); + expr_hash_ = common::do_hash(database_name_, expr_hash_); + expr_hash_ = common::do_hash(package_name_, expr_hash_); + expr_hash_ = common::do_hash(is_deterministic(), expr_hash_); + expr_hash_ = common::do_hash(is_parallel_enable_, expr_hash_); + expr_hash_ = common::do_hash(is_udt_udf_, expr_hash_); + expr_hash_ = common::do_hash(is_pkg_body_udf_, expr_hash_); + expr_hash_ = common::do_hash(is_return_sys_cursor_, expr_hash_); + expr_hash_ = common::do_hash(is_aggregate_udf_, expr_hash_); + expr_hash_ = common::do_hash(is_aggr_udf_distinct_, expr_hash_); + expr_hash_ = common::do_hash(loc_, expr_hash_); + expr_hash_ = common::do_hash(is_udt_cons_, expr_hash_); + for (int64_t i = 0; i < subprogram_path_.count(); ++i) { + expr_hash_ = common::do_hash(subprogram_path_.at(i), expr_hash_); + } + for (int64_t i = 0; i < params_type_.count(); ++i) { + expr_hash_ = common::do_hash(params_type_.at(i), expr_hash_); + } + for (int64_t i = 0; i < nocopy_params_.count(); ++i) { + expr_hash_ = common::do_hash(nocopy_params_.at(i), expr_hash_); + } + for (int64_t i = 0; i < params_name_.count(); ++i) { + expr_hash_ = common::do_hash(params_name_.at(i), expr_hash_); + } +} + int ObUDFRawExpr::get_schema_object_version(share::schema::ObSchemaGetterGuard &schema_guard, ObIArray &obj_versions) { @@ -5731,7 +6055,6 @@ bool ObSetOpRawExpr::inner_same_as(const ObRawExpr &expr, ObExprEqualCheckContext *check_context) const { bool bool_ret = false; - UNUSED(check_context); if (get_expr_type() != expr.get_expr_type()) { } else if (&expr == this) { bool_ret = true; @@ -5743,6 +6066,11 @@ bool ObSetOpRawExpr::inner_same_as(const ObRawExpr &expr, return bool_ret; } +void ObSetOpRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); +} + bool ObExprEqualCheckContext::compare_set_op_expr(const ObSetOpRawExpr& left, const ObSetOpRawExpr& right) { @@ -5982,8 +6310,12 @@ int ObWinFunRawExpr::inner_deep_copy(ObIRawExprCopier &copier) } else if (OB_FAIL(lower_.inner_deep_copy(copier))) { LOG_WARN("failed to copy lower bound", K(ret)); } else if (NULL != agg_expr_) { - if (OB_FAIL(copier.do_copy_expr(agg_expr_, new_agg_expr))) { - LOG_WARN("failed to create and copy expr", K(ret), K(agg_expr_)); + if (OB_FAIL(copier.get_expr_factory().create_raw_expr(agg_expr_->get_expr_class(), + agg_expr_->get_expr_type(), + new_agg_expr))) { + LOG_WARN("failed to create new aggr expr", K(ret)); + } else if (OB_FAIL(new_agg_expr->deep_copy(copier, *agg_expr_))) { + LOG_WARN("failed to deep copy aggr fun", K(ret)); } else if (OB_ISNULL(new_agg_expr) || OB_UNLIKELY(!new_agg_expr->is_aggr_expr())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("new aggregation expr is invalid", K(ret), K(new_agg_expr)); @@ -6088,9 +6420,9 @@ bool ObWinFunRawExpr::inner_same_as(const ObRawExpr &expr, bret = false; //如果是聚集函数的窗口函数,需要比较聚集函数。 } else if (agg_expr_ != NULL && other_ma.agg_expr_ != NULL) { - bret = agg_expr_->same_as(*(other_ma.agg_expr_), check_context) ? true : false; + bret = agg_expr_->same_as(*(other_ma.agg_expr_), check_context); } else if (pl_agg_udf_expr_ != NULL && other_ma.pl_agg_udf_expr_ != NULL) { - bret = pl_agg_udf_expr_->same_as(*(other_ma.pl_agg_udf_expr_), check_context) ? true : false; + bret = pl_agg_udf_expr_->same_as(*(other_ma.pl_agg_udf_expr_), check_context); } else { /* do nothing. */ } //如果之上都是相同的,需要比较窗口属性 @@ -6129,6 +6461,41 @@ bool ObWinFunRawExpr::inner_same_as(const ObRawExpr &expr, return bret; } +void ObWinFunRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_class(), expr_hash_); + expr_hash_ = common::do_hash(get_func_type(), expr_hash_); + expr_hash_ = common::do_hash(get_window_type(), expr_hash_); + expr_hash_ = common::do_hash(is_between(), expr_hash_); + if (T_WIN_FUN_NTH_VALUE == get_func_type()) { + expr_hash_ = common::do_hash(is_from_first_, expr_hash_); + expr_hash_ = common::do_hash(is_ignore_null_, expr_hash_); + } else if (T_WIN_FUN_LAG == get_func_type() || T_WIN_FUN_LEAD == get_func_type()) { + expr_hash_ = common::do_hash(is_ignore_null_, expr_hash_); + } else if (agg_expr_ != NULL) { + expr_hash_ = common::do_hash(agg_expr_->get_expr_hash(), expr_hash_); + } else if (pl_agg_udf_expr_ != NULL) { + expr_hash_ = common::do_hash(pl_agg_udf_expr_->get_expr_hash(), expr_hash_); + } + + for (int64_t i = 0; i < func_params_.count(); ++i) { + if (NULL != func_params_.at(i)) { + expr_hash_ = common::do_hash(func_params_.at(i)->get_expr_hash(), expr_hash_); + } + } + for (int64_t i = 0; i < partition_exprs_.count(); ++i) { + if (NULL != partition_exprs_.at(i)) { + expr_hash_ = common::do_hash(partition_exprs_.at(i)->get_expr_hash(), expr_hash_); + } + } + for (int64_t i = 0; i < order_items_.count(); ++i) { + expr_hash_ = common::do_hash(order_items_.at(i).order_type_, expr_hash_); + if (NULL != order_items_.at(i).expr_) { + expr_hash_ = common::do_hash(order_items_.at(i).expr_->get_expr_hash(), expr_hash_); + } + } +} + const ObRawExpr *ObWinFunRawExpr::get_param_expr(int64_t index) const { int i = 0; @@ -6331,7 +6698,7 @@ int ObPseudoColumnRawExpr::replace_expr(const ObIArray &other_exprs } bool ObPseudoColumnRawExpr::inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context/* = NULL*/) const + ObExprEqualCheckContext *check_context) const { UNUSED(check_context); return type_ == expr.get_expr_type() && @@ -6339,6 +6706,12 @@ bool ObPseudoColumnRawExpr::inner_same_as(const ObRawExpr &expr, 0 == data_access_path_.compare(static_cast(expr).get_data_access_path()); } +void ObPseudoColumnRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(table_id_, expr_hash_); +} + int ObPseudoColumnRawExpr::do_visit(ObRawExprVisitor &visitor) { return visitor.visit(*this); @@ -6489,6 +6862,12 @@ bool ObOpPseudoColumnRawExpr::inner_same_as( && strcmp(name_, static_cast(expr).name_) == 0; } +void ObOpPseudoColumnRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(name_, expr_hash_); +} + int ObOpPseudoColumnRawExpr::do_visit(ObRawExprVisitor &visitor) { return visitor.visit(*this); @@ -6586,12 +6965,22 @@ bool ObMultiSetRawExpr::inner_same_as(const ObRawExpr &expr, return ObOpRawExpr::inner_same_as(expr, check_context); } +void ObMultiSetRawExpr::inner_calc_hash() +{ + ObOpRawExpr::inner_calc_hash(); +} + bool ObCollPredRawExpr::inner_same_as(const ObRawExpr &expr, ObExprEqualCheckContext *check_context) const { return ObMultiSetRawExpr::inner_same_as(expr, check_context); } +void ObCollPredRawExpr::inner_calc_hash() +{ + ObMultiSetRawExpr::inner_calc_hash(); +} + void ObExprParamCheckContext::init(const ObIArray *calculable_items, const ObIArray *equal_param_constraints, EqualSets *equal_sets) @@ -6742,26 +7131,21 @@ bool ObPlQueryRefRawExpr::inner_same_as( bool bool_ret = false; if (get_expr_type() == expr.get_expr_type()) { const ObPlQueryRefRawExpr &u_expr = static_cast(expr); - if (check_context != NULL && check_context->override_query_compare_) { - bool_ret = check_context->compare_query(*this, u_expr); - } else { - // very tricky, check the definition of ref_stmt_ and get_ref_stmt() - bool_ret = (get_ps_sql() == u_expr.get_ps_sql() && - get_stmt_type() == u_expr.get_stmt_type() && - get_route_sql() == u_expr.get_route_sql() && - get_subquery_result_type() == u_expr.get_subquery_result_type()); - } + bool_ret = (get_ps_sql() == u_expr.get_ps_sql() && + get_stmt_type() == u_expr.get_stmt_type() && + get_route_sql() == u_expr.get_route_sql() && + get_subquery_result_type() == u_expr.get_subquery_result_type()); } return bool_ret; } -bool ObExprEqualCheckContext::compare_query(const ObPlQueryRefRawExpr &left, - const ObPlQueryRefRawExpr &right) +void ObPlQueryRefRawExpr::inner_calc_hash() { - return left.get_ps_sql() == right.get_ps_sql() && - left.get_stmt_type() == right.get_stmt_type() && - left.get_route_sql() == right.get_route_sql() && - left.get_subquery_result_type() == right.get_subquery_result_type(); + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(get_ps_sql(), expr_hash_); + expr_hash_ = common::do_hash(get_stmt_type(), expr_hash_); + expr_hash_ = common::do_hash(get_route_sql(), expr_hash_); + expr_hash_ = common::do_hash(get_subquery_result_type(), expr_hash_); } int ObPlQueryRefRawExpr::do_visit(ObRawExprVisitor &visitor) @@ -7252,6 +7636,20 @@ bool ObMatchFunRawExpr::inner_same_as(const ObRawExpr &expr, ObExprEqualCheckCon return bret; } +void ObMatchFunRawExpr::inner_calc_hash() +{ + expr_hash_ = common::do_hash(get_expr_type(), expr_hash_); + expr_hash_ = common::do_hash(mode_flag_, expr_hash_); + if (search_key_ != NULL) { + expr_hash_ = common::do_hash(search_key_->get_expr_hash(), expr_hash_); + } + for (int64_t i = 0; i < match_columns_.count(); ++i) { + if (match_columns_.at(i) != NULL) { + expr_hash_ = common::do_hash(match_columns_.at(i)->get_expr_hash(), expr_hash_); + } + } +} + void ObMatchFunRawExpr::clear_child() { match_columns_.reset(); diff --git a/src/sql/resolver/expr/ob_raw_expr.h b/src/sql/resolver/expr/ob_raw_expr.h index 6e4de3b970..c972178852 100644 --- a/src/sql/resolver/expr/ob_raw_expr.h +++ b/src/sql/resolver/expr/ob_raw_expr.h @@ -71,6 +71,7 @@ class ObRTDatumArith; class ObLogicalOperator; class ObInListInfo; extern ObRawExpr *USELESS_POINTER; +struct ObExprEqualCheckContext; // If is_stack_overflow is true, the printing will not continue #ifndef DEFINE_VIRTUAL_TO_STRING_CHECK_STACK_OVERFLOW @@ -1498,9 +1499,6 @@ struct ObExprEqualCheckContext virtual bool compare_query(const ObQueryRefRawExpr &left, const ObQueryRefRawExpr &right); - virtual bool compare_query(const ObPlQueryRefRawExpr &left, - const ObPlQueryRefRawExpr &right); - virtual bool compare_set_op_expr(const ObSetOpRawExpr& left, const ObSetOpRawExpr& right); @@ -1763,7 +1761,8 @@ public: partition_id_calc_type_(CALC_INVALID), local_session_var_(), local_session_var_id_(OB_INVALID_INDEX_INT64), - attr_exprs_() + attr_exprs_(), + expr_hash_(0) { } @@ -1788,7 +1787,8 @@ public: with_null_equal_cond_(false), local_session_var_(&alloc), local_session_var_id_(OB_INVALID_INDEX_INT64), - attr_exprs_() + attr_exprs_(), + expr_hash_(0) { } virtual ~ObRawExpr(); @@ -1810,7 +1810,10 @@ public: ObExprEqualCheckContext *check_context = NULL) const; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const = 0; + ObExprEqualCheckContext *check_context) const = 0; + int calc_hash(); + int is_hash_different(const ObRawExpr &expr, ObExprEqualCheckContext *check_context) const; + virtual void inner_calc_hash() = 0; inline bool is_generalized_column() const { @@ -1973,9 +1976,11 @@ public: void set_rt_expr(sql::ObExpr *expr) { rt_expr_ = expr; } void reset_rt_expr() { rt_expr_ = NULL; } void set_extra(uint64_t extra) { extra_ = extra; } + void set_expr_hash(uint64_t expr_hash) { expr_hash_ = expr_hash; } void set_is_called_in_sql(bool is_called_in_sql) { is_called_in_sql_ = is_called_in_sql; } void set_is_calculated(bool is_calculated) { is_calculated_ = is_calculated; } uint64_t get_extra() const { return extra_; } + uint64_t get_expr_hash() const { return expr_hash_; } bool is_called_in_sql() const { return is_called_in_sql_; } bool is_calculated() const { return is_calculated_; } bool is_deterministic() const { return is_deterministic_; } @@ -2035,7 +2040,8 @@ public: K_(is_calculated), K_(is_deterministic), K_(partition_id_calc_type), - K_(may_add_interval_part)); + K_(may_add_interval_part), + K_(expr_hash)); virtual int set_local_session_vars(const ObLocalSessionVar *local_sys_vars, const ObBasicSessionInfo *session, int64_t ctx_array_idx) @@ -2104,6 +2110,7 @@ protected: ObLocalSessionVar local_session_var_; int64_t local_session_var_id_; common::ObSEArray attr_exprs_; + uint64_t expr_hash_; private: DISALLOW_COPY_AND_ASSIGN(ObRawExpr); }; @@ -2309,7 +2316,8 @@ public: bool is_date_unit() {return true == is_date_unit_; } virtual void reset(); virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; @@ -2378,7 +2386,8 @@ public: virtual int replace_expr(const common::ObIArray &other_exprs, const common::ObIArray &new_exprs) override; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; @@ -2406,7 +2415,8 @@ public: const common::ObIArray &new_exprs) override; virtual void reset(); virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; @@ -2433,7 +2443,10 @@ class ObExecParamRawExpr : public ObConstRawExpr public: ObExecParamRawExpr() : ObConstRawExpr(), + outer_expr_(NULL), + is_onetime_(false), ref_same_dblink_(false), + exec_param_idx_(-1), eval_by_storage_(false) { set_expr_class(ObIRawExpr::EXPR_EXEC_PARAM); @@ -2441,14 +2454,17 @@ public: ObExecParamRawExpr(common::ObIAllocator &alloc) : ObConstRawExpr(alloc), + outer_expr_(NULL), + is_onetime_(false), ref_same_dblink_(false), + exec_param_idx_(-1), eval_by_storage_(false) { set_expr_class(ObIRawExpr::EXPR_EXEC_PARAM); } virtual ~ObExecParamRawExpr() {} - + void set_param_index(ObQueryCtx &query_ctx); void set_param_index(int64_t index); int64_t get_param_index() const; @@ -2471,20 +2487,21 @@ public: const common::ObIArray &new_exprs) override; virtual bool inner_same_as(const ObRawExpr &expr, ObExprEqualCheckContext *check_context) const override; - + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; virtual uint64_t hash_internal(uint64_t seed) const; virtual int get_name_internal(char *buf, const int64_t buf_len, int64_t &pos, - ExplainType type) const; + ExplainType type) const override; DECLARE_VIRTUAL_TO_STRING; private: // the refered expr in the outer stmt ObRawExpr *outer_expr_; bool is_onetime_; bool ref_same_dblink_; + int64_t exec_param_idx_; // used to print exec_param self index in explain bool eval_by_storage_; }; @@ -2573,7 +2590,8 @@ public: bool is_scalar() const { return !is_set_ && !is_multiset_ && get_output_column() == 1; } virtual void reset(); virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; @@ -2592,7 +2610,8 @@ public: K_(is_multiset), K_(column_types), K_(enum_set_values), - N_CHILDREN, exec_params_); + N_CHILDREN, exec_params_, + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObQueryRefRawExpr); //ObUnaryRefExpr是表示对一个stmt或者logical plan的引用, @@ -2754,7 +2773,8 @@ public: inline int64_t get_cte_generate_column_projector_offset() const { return get_column_id() - common::OB_APP_MIN_COLUMN_ID; } virtual void reset(); virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; @@ -2849,7 +2869,8 @@ public: K_(is_mul_key_column), K_(is_strict_json_column), K_(srs_id), - K_(udt_set_id)); + K_(udt_set_id), + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObColumnRefRawExpr); uint64_t table_id_; @@ -2930,7 +2951,8 @@ public: const common::ObIArray &new_exprs) override; int get_name_internal(char *buf, const int64_t buf_len, int64_t &pos, ExplainType type) const; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; int assign(const ObRawExpr &other) override; @@ -2940,7 +2962,8 @@ public: N_RESULT_TYPE, result_type_, N_EXPR_INFO, info_, N_REL_ID, rel_ids_, - K_(idx)); + K_(idx), + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObSetOpRawExpr); int64_t idx_; // set op expr 对应 child stmt select expr 的 index @@ -2986,14 +3009,15 @@ public: virtual uint64_t hash_internal(uint64_t seed) const; int get_name_internal(char *buf, const int64_t buf_len, int64_t &pos, ExplainType type) const; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; - + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; VIRTUAL_TO_STRING_KV_CHECK_STACK_OVERFLOW(N_ITEM_TYPE, type_, N_RESULT_TYPE, result_type_, N_EXPR_INFO, info_, N_REL_ID, rel_ids_, N_VALUE, ref_expr_, - K_(enum_set_values)); + K_(enum_set_values), + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObAliasRefRawExpr); ObRawExpr *ref_expr_; @@ -3095,7 +3119,8 @@ public: virtual void clear_child() override; virtual void reset(); virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; //used for jit expr @@ -3126,7 +3151,8 @@ public: N_RESULT_TYPE, result_type_, N_EXPR_INFO, info_, N_REL_ID, rel_ids_, - N_CHILDREN, exprs_); + N_CHILDREN, exprs_, + K_(expr_hash)); protected: common::ObSEArray exprs_; ObSubQueryKey subquery_key_; @@ -3260,7 +3286,8 @@ public: virtual void clear_child() override; virtual void reset(); virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; @@ -3287,7 +3314,8 @@ public: N_DEFAULT, default_expr_, N_WHEN, when_exprs_, N_THEN, then_exprs_, - N_DECODE, is_decode_func_); + N_DECODE, is_decode_func_, + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObCaseOpRawExpr); ObRawExpr *arg_expr_; @@ -3496,7 +3524,8 @@ public: virtual void clear_child() override; virtual void reset(); virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int64_t get_param_count() const; virtual const ObRawExpr *get_param_expr(int64_t index) const; @@ -3550,8 +3579,8 @@ public: N_SEPARATOR_PARAM_EXPR, separator_param_expr_, K_(udf_meta), K_(expr_in_inner_stmt), - K_(pl_agg_udf_expr)); - + K_(pl_agg_udf_expr), + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObAggFunRawExpr); // real_param_exprs_.count() == 0 means '*' @@ -3667,9 +3696,10 @@ public: virtual ObExprOperator *get_op(); virtual void reset(); virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; virtual bool inner_json_expr_same_as(const ObRawExpr &expr, ObExprEqualCheckContext *check_context = NULL) const; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; virtual uint64_t hash_internal(uint64_t seed) const @@ -3703,7 +3733,8 @@ public: K_(dblink_id), K_(local_session_var), K_(local_session_var_id), - K_(mview_id)); + K_(mview_id), + K_(expr_hash)); private: int check_param_num_internal(int32_t param_num, int32_t param_count, ObExprOperatorType type); DISALLOW_COPY_AND_ASSIGN(ObSysFunRawExpr); @@ -3744,8 +3775,8 @@ public: const common::ObString &get_action() const { return action_; } uint64_t get_sequence_id() const { return sequence_id_; } virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; - + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int get_name_internal(char *buf, const int64_t buf_len, int64_t &pos, ExplainType type) const override; private: common::ObString database_name_; // sequence database name @@ -3767,8 +3798,8 @@ public: int add_udf_attribute(const ObRawExpr *expr, const ParseNode *node); const share::schema::ObUDFMeta &get_udf_meta() const { return udf_meta_; } virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; - + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; private: //for udf function info share::schema::ObUDFMeta udf_meta_; @@ -3840,7 +3871,8 @@ public: N_REL_ID, rel_ids_, N_FUNC, get_func_name(), N_CHILDREN, exprs_, - K_(coll_schema_version)); + K_(coll_schema_version), + K_(expr_hash)); private: pl::ObPLType type_; // PL_NESTED_TABLE_TYPE|PL_ASSOCIATIVE_ARRAY_TYPE|PL_VARRAY_TYPE pl::ObPLDataType elem_type_; // 记录复杂数据类型的元素类型 @@ -3930,7 +3962,8 @@ public: N_FUNC, get_func_name(), N_CHILDREN, exprs_, K_(database_id), - K_(object_schema_version)); + K_(object_schema_version), + K_(expr_hash)); private: int64_t rowsize_; uint64_t udt_id_; @@ -4118,8 +4151,8 @@ public: int assign(const ObRawExpr &other) override; int inner_deep_copy(ObIRawExprCopier &copier) override; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; - + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual ObExprOperator *get_op() override; int check_param() { return common::OB_SUCCESS; } @@ -4201,7 +4234,8 @@ public: K_(loc), K_(is_udt_cons), K_(params_desc_v2), - N_CHILDREN, exprs_); + N_CHILDREN, exprs_, + K_(expr_hash)); private: uint64_t udf_id_; uint64_t pkg_id_; @@ -4256,7 +4290,8 @@ public: N_REL_ID, rel_ids_, K_(pl_integer_type), K_(pl_integer_range_.range), - N_CHILDREN, exprs_); + N_CHILDREN, exprs_, + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObPLIntegerCheckerRawExpr); private: @@ -4281,7 +4316,8 @@ public: N_EXPR_INFO, info_, N_REL_ID, rel_ids_, K_(cursor_info), - N_CHILDREN, exprs_); + N_CHILDREN, exprs_, + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObPLGetCursorAttrRawExpr); private: @@ -4305,7 +4341,8 @@ public: N_EXPR_INFO, info_, N_REL_ID, rel_ids_, K_(is_sqlcode), - N_CHILDREN, exprs_); + N_CHILDREN, exprs_, + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObPLSQLCodeSQLErrmRawExpr); private: @@ -4392,7 +4429,8 @@ public: K_(for_write), N_CHILDREN, exprs_, K_(out_of_range_set_err), - K_(parent_type)); + K_(parent_type), + K_(expr_hash)); private: DISALLOW_COPY_AND_ASSIGN(ObPLAssocIndexRawExpr); private: @@ -4434,7 +4472,8 @@ public: int assign(const ObRawExpr &other) override; int inner_deep_copy(ObIRawExprCopier &copier) override; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; int add_access_indexs(const common::ObIArray &access_idxs); common::ObIArray &get_access_idxs() { return access_indexs_; } @@ -4498,7 +4537,8 @@ public: int assign(const ObRawExpr &other) override; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; inline ObMultiSetModifier get_multiset_modifier() const { return ms_modifier_; } inline ObMultiSetType get_multiset_type() const { return ms_type_; } @@ -4518,7 +4558,8 @@ public: virtual ~ObCollPredRawExpr() {} virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; private: DISALLOW_COPY_AND_ASSIGN(ObCollPredRawExpr); @@ -4704,7 +4745,8 @@ public: virtual void clear_child() override; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int64_t get_param_count() const { @@ -4746,7 +4788,8 @@ public: K_(upper), K_(lower), KPC_(agg_expr), - KPC_(pl_agg_udf_expr)); + KPC_(pl_agg_udf_expr), + K_(expr_hash)); public: common::ObString sort_str_; private: @@ -4780,7 +4823,8 @@ public: virtual int replace_expr(const common::ObIArray &other_exprs, const common::ObIArray &new_exprs); virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; virtual uint64_t hash_internal(uint64_t seed) const; @@ -4802,7 +4846,8 @@ public: N_REL_ID, rel_ids_, N_TABLE_ID, table_id_, N_TABLE_NAME, table_name_, - K_(data_access_path)); + K_(data_access_path), + K_(expr_hash)); private: ObRawExpr *cte_cycle_value_; ObRawExpr *cte_cycle_default_value_; @@ -4834,8 +4879,8 @@ public: virtual int replace_expr(const common::ObIArray &other_exprs, const common::ObIArray &new_exprs) override; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; - + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; virtual int get_name_internal(char *buf, const int64_t buf_len, @@ -4877,7 +4922,8 @@ public: virtual int do_visit(ObRawExprVisitor &visitor) override; virtual uint64_t hash_internal(uint64_t seed) const; int get_name_internal(char *buf, const int64_t buf_len, int64_t &pos, ExplainType type) const override; - virtual bool inner_same_as(const ObRawExpr &expr, ObExprEqualCheckContext *check_context = NULL) const override; + virtual bool inner_same_as(const ObRawExpr &expr, ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual void clear_child() override; virtual void reset(); virtual int64_t get_param_count() const; @@ -5165,7 +5211,8 @@ public: virtual void clear_child() override; virtual bool inner_same_as(const ObRawExpr &expr, - ObExprEqualCheckContext *check_context = NULL) const override; + ObExprEqualCheckContext *check_context) const override; + virtual void inner_calc_hash() override; virtual int do_visit(ObRawExprVisitor &visitor) override; @@ -5290,7 +5337,8 @@ public: N_FUNC, get_func_name(), N_CHILDREN, exprs_, K_(database_id), - K_(object_schema_version)); + K_(object_schema_version), + K_(expr_hash)); private: uint64_t udt_id_; // 记录Object每个元素的类型 diff --git a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp index adcf0927e9..07231b1d54 100644 --- a/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_deduce_type.cpp @@ -4331,6 +4331,7 @@ int ObRawExprDeduceType::try_replace_cast_with_questionmark_ora(ObRawExpr &paren ObConstRawExpr *c_expr = static_cast(param_expr); ObExprResType res_type = cast_expr->get_result_type(); res_type.add_cast_mode(cast_expr->get_extra()); + res_type.set_param(c_expr->get_result_type().get_param()); int64_t param_idx = 0; if (OB_ISNULL(expr_factory_)) { ret = OB_ERR_UNEXPECTED; @@ -4340,7 +4341,7 @@ int ObRawExprDeduceType::try_replace_cast_with_questionmark_ora(ObRawExpr &paren } else if (OB_FAIL(ObRawExprUtils::create_param_expr(*expr_factory_, param_idx, param_expr))) { // create new param store to avoid unexpected problem LOG_WARN("create param expr failed", K(ret)); - } else if (OB_FAIL(static_cast(param_expr)->set_dynamic_eval_questionmark(res_type))){ + } else if (OB_FAIL(static_cast(param_expr)->set_dynamic_eval_questionmark(res_type))) { LOG_WARN("set dynamic eval question mark failed", K(ret)); } else { parent.get_param_expr(child_idx) = param_expr; diff --git a/src/sql/resolver/expr/ob_raw_expr_util.cpp b/src/sql/resolver/expr/ob_raw_expr_util.cpp index ad458398b9..0a6cae3b75 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.cpp +++ b/src/sql/resolver/expr/ob_raw_expr_util.cpp @@ -3779,14 +3779,17 @@ int ObRawExprUtils::extract_invalid_sequence_expr(ObRawExpr *raw_expr, } int ObRawExprUtils::extract_col_aggr_winfunc_exprs(ObIArray &exprs, - ObIArray &column_aggr_winfunc_exprs) + ObIArray &column_aggr_winfunc_exprs, + const bool extract_set_op /* = false */) { int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); ++i) { if (OB_ISNULL(exprs.at(i))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Expr is NULL", K(ret), K(i)); - } else if (OB_FAIL(extract_col_aggr_winfunc_exprs(exprs.at(i), column_aggr_winfunc_exprs))) { + } else if (OB_FAIL(extract_col_aggr_winfunc_exprs(exprs.at(i), + column_aggr_winfunc_exprs, + extract_set_op))) { LOG_WARN("Failed to extract col or aggr exprs", K(ret)); } else {/*do nothing*/} } @@ -3794,7 +3797,8 @@ int ObRawExprUtils::extract_col_aggr_winfunc_exprs(ObIArray &exprs, } int ObRawExprUtils::extract_col_aggr_winfunc_exprs(ObRawExpr* expr, - ObIArray &column_aggr_winfunc_exprs) + ObIArray &column_aggr_winfunc_exprs, + const bool extract_set_op /* = false */) { int ret = OB_SUCCESS; if (OB_ISNULL(expr)) { @@ -3812,6 +3816,10 @@ int ObRawExprUtils::extract_col_aggr_winfunc_exprs(ObRawExpr* expr, if (OB_FAIL(add_var_to_array_no_dup(column_aggr_winfunc_exprs, expr))) { LOG_WARN("fail to add col expr to column_exprs", K(ret)); } + } else if (extract_set_op && expr->has_flag(IS_SET_OP)) { + if (OB_FAIL(add_var_to_array_no_dup(column_aggr_winfunc_exprs, expr))) { + LOG_WARN("fail to add set op to column_exprs", K(ret)); + } } else { for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); i++) { if (OB_FAIL(SMART_CALL(extract_col_aggr_winfunc_exprs(expr->get_param_expr(i), @@ -5146,6 +5154,7 @@ int ObRawExprUtils::create_new_exec_param(ObRawExprFactory &expr_factory, exec_param->set_ref_expr(ref_expr, is_onetime); exec_param->set_param_index(-1); exec_param->set_result_type(ref_expr->get_result_type()); + exec_param->set_expr_hash(ref_expr->get_expr_hash()); if (is_onetime) { exec_param->add_flag(IS_ONETIME); } @@ -5207,7 +5216,7 @@ int ObRawExprUtils::create_new_exec_param(ObQueryCtx *query_ctx, { int ret = OB_SUCCESS; ObExecParamRawExpr *exec_param = NULL; - if (OB_ISNULL(expr)) { + if (OB_ISNULL(expr) || OB_ISNULL(query_ctx)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr is null", K(ret), K(expr)); } else if (OB_FAIL(expr_factory.create_raw_expr(T_QUESTIONMARK, exec_param))) { @@ -5223,13 +5232,12 @@ int ObRawExprUtils::create_new_exec_param(ObQueryCtx *query_ctx, LOG_WARN("failed to add flag", K(ret)); } else { exec_param->set_ref_expr(expr, is_onetime); - exec_param->set_param_index(query_ctx->question_marks_count_); + exec_param->set_param_index(*query_ctx); exec_param->set_result_type(expr->get_result_type()); + exec_param->set_expr_hash(expr->get_expr_hash()); if (is_onetime) { exec_param->add_flag(IS_ONETIME); } - ++query_ctx->question_marks_count_; - expr = exec_param; } return ret; @@ -8838,6 +8846,8 @@ int ObRawExprUtils::process_window_complex_agg_expr(ObRawExprFactory &expr_facto LOG_WARN("failed to replace the agg expr.", K(ret)); } else if (FALSE_IT(win_func_expr->set_func_type(func_type))) { LOG_WARN("failed to set func type.", K(ret)); + } else if (OB_FAIL(win_func_expr->calc_hash())) { + LOG_WARN("failed to calc expr hash", K(ret)); } else if (OB_FAIL(win_exprs->push_back(win_func_expr))) { LOG_WARN("failed to push back win func epxr.", K(ret)); } else {/*do nothing */} @@ -9482,7 +9492,7 @@ int ObRawExprUtils::extract_params(ObRawExpr *expr, ObIArray ¶ms return ret; } -int ObRawExprUtils::extract_params(common::ObIArray &exprs, +int ObRawExprUtils::extract_params(const common::ObIArray &exprs, common::ObIArray ¶ms) { int ret = OB_SUCCESS; @@ -9944,17 +9954,9 @@ int ObRawExprUtils::build_dummy_count_expr(ObRawExprFactory &expr_factory, ObAggFunRawExpr *&expr) { int ret = OB_SUCCESS; - ObConstRawExpr *one_expr = NULL; ObAggFunRawExpr *count_expr = NULL; - if (OB_FAIL(build_const_int_expr(expr_factory, ObInt32Type, static_cast(1), one_expr))) { - LOG_WARN("failed build const int expr for default expr", K(ret)); - } else if (OB_ISNULL(one_expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("operator is unexpected null", K(ret)); - } else if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_COUNT, count_expr))) { + if (OB_FAIL(expr_factory.create_raw_expr(T_FUN_COUNT, count_expr))) { LOG_WARN("fail to create const raw expr", K(ret)); - } else if (OB_FAIL(count_expr->add_real_param_expr(one_expr))) { - LOG_WARN("fail to push back", K(ret)); } else if (OB_FAIL(count_expr->formalize(session_info))) { LOG_WARN("failed to extract expr info", K(ret)); } else { diff --git a/src/sql/resolver/expr/ob_raw_expr_util.h b/src/sql/resolver/expr/ob_raw_expr_util.h index e715f313e5..cabd88f0d2 100644 --- a/src/sql/resolver/expr/ob_raw_expr_util.h +++ b/src/sql/resolver/expr/ob_raw_expr_util.h @@ -456,9 +456,11 @@ public: static int extract_col_aggr_exprs(ObRawExpr* expr, ObIArray &column_or_aggr_exprs); static int extract_col_aggr_winfunc_exprs(ObIArray &exprs, - ObIArray &column_aggr_winfunc_exprs); + ObIArray &column_aggr_winfunc_exprs, + const bool extract_set_op = false); static int extract_col_aggr_winfunc_exprs(ObRawExpr* expr, - ObIArray &column_aggr_winfunc_exprs); + ObIArray &column_aggr_winfunc_exprs, + const bool extract_set_op = false); static int extract_metadata_filename_expr(ObRawExpr *expr, ObRawExpr *&file_name_expr); static int find_alias_expr(ObRawExpr *expr, ObAliasRefRawExpr *&alias_expr); @@ -1205,7 +1207,7 @@ public: ObDMLStmt *stmt ); - static int extract_params(common::ObIArray &exprs, + static int extract_params(const common::ObIArray &exprs, common::ObIArray ¶ms); static int is_contain_params(const common::ObIArray &exprs, bool &is_contain); static int is_contain_params(const ObRawExpr *expr, bool &is_contain); diff --git a/src/sql/resolver/mv/ob_mv_provider.cpp b/src/sql/resolver/mv/ob_mv_provider.cpp index 7fa98b9d84..1b83962f76 100644 --- a/src/sql/resolver/mv/ob_mv_provider.cpp +++ b/src/sql/resolver/mv/ob_mv_provider.cpp @@ -364,8 +364,8 @@ int ObMVProvider::generate_mv_stmt(ObIAllocator &alloc, OB_UNLIKELY(T_SELECT != node->type_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid mv select node", K(ret), K(node), K(node->type_)); - } else if (OB_FALSE_IT(resolver_ctx.query_ctx_->question_marks_count_ = - static_cast(parse_result.question_mark_ctx_.count_))) { + } else if (OB_FALSE_IT(resolver_ctx.query_ctx_->set_questionmark_count( + static_cast(parse_result.question_mark_ctx_.count_)))) { } else if (OB_FAIL(select_resolver.resolve(*node))) { LOG_WARN("resolve view definition failed", K(ret)); } else if (OB_ISNULL(sel_stmt = static_cast(select_resolver.get_basic_stmt()))) { diff --git a/src/sql/resolver/ob_resolver.cpp b/src/sql/resolver/ob_resolver.cpp index 1957093211..7dda269c75 100644 --- a/src/sql/resolver/ob_resolver.cpp +++ b/src/sql/resolver/ob_resolver.cpp @@ -208,8 +208,8 @@ int ObResolver::resolve(IsPrepared if_prepared, const ParseNode &parse_tree, ObS int ret = OB_SUCCESS; const ParseNode *real_parse_tree = NULL; + int64_t questionmark_count = 0; UNUSED(if_prepared); - if (OB_ISNULL(params_.allocator_) || OB_ISNULL(params_.schema_checker_) || OB_ISNULL(params_.session_info_) @@ -229,7 +229,8 @@ int ObResolver::resolve(IsPrepared if_prepared, const ParseNode &parse_tree, ObS *(params_.expr_factory_), NULL, params_.is_prepare_protocol_); - OZ (resolver.resolve_condition_compile(&parse_tree, real_parse_tree, params_.query_ctx_->question_marks_count_)); + OZ (resolver.resolve_condition_compile(&parse_tree, real_parse_tree, questionmark_count)); + OX (params_.query_ctx_->set_questionmark_count(questionmark_count)); } else { real_parse_tree = &parse_tree; } diff --git a/src/sql/resolver/ob_resolver_utils.cpp b/src/sql/resolver/ob_resolver_utils.cpp index 84c369d73e..4134fdd2ab 100644 --- a/src/sql/resolver/ob_resolver_utils.cpp +++ b/src/sql/resolver/ob_resolver_utils.cpp @@ -8694,23 +8694,23 @@ int ObResolverUtils::get_select_into_node(const ParseNode &node, ParseNode* &int int ret = OB_SUCCESS; ParseNode *child_into_node = NULL; if (OB_LIKELY(node.type_ == T_SELECT)) { - if (NULL != node.children_[PARSE_SELECT_SET] && - NULL != node.children_[PARSE_SELECT_FORMER] && - NULL != node.children_[PARSE_SELECT_LATER]) { - if (OB_FAIL(SMART_CALL(get_select_into_node(*node.children_[PARSE_SELECT_FORMER], child_into_node, false))) || - NULL != child_into_node) { - ret = OB_SUCCESS == ret ? OB_ERR_SET_USAGE : ret; - LOG_WARN("invalid into clause", K(ret)); - } else { - child_into_node = get_select_into_node(*node.children_[PARSE_SELECT_LATER]); - if (!top_level && NULL != child_into_node) { + if (NULL == node.children_[PARSE_SELECT_SET]) { + into_node = get_select_into_node(node); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < node.children_[PARSE_SELECT_SET]->num_child_; i++) { + ParseNode *child_node = node.children_[PARSE_SELECT_SET]->children_[i]; + if (OB_FAIL(SMART_CALL(get_select_into_node(*child_node, child_into_node, false)))) { + LOG_WARN("failed to get select into node", K(ret)); + } else if (NULL != child_into_node) { + if (top_level && i == node.children_[PARSE_SELECT_SET]->num_child_ - 1) { + // select into is only allow to in last branch of set + into_node = child_into_node; + } else { ret = OB_ERR_SET_USAGE; LOG_WARN("invalid into clause", K(ret)); } - into_node = child_into_node; - } - } else { - into_node = get_select_into_node(node); + } else {/* it doesn't have into node */} + } } } return ret; diff --git a/src/sql/rewrite/ob_equal_analysis.cpp b/src/sql/rewrite/ob_equal_analysis.cpp index 06b458e27c..908209ac11 100644 --- a/src/sql/rewrite/ob_equal_analysis.cpp +++ b/src/sql/rewrite/ob_equal_analysis.cpp @@ -20,9 +20,7 @@ using namespace common; namespace sql { ObEqualAnalysis::ObEqualAnalysis() - : equal_set_alloc_(ObMemAttr(MTL_ID(), ObModIds::OB_SQL_OPTIMIZER_EQUAL_SETS)), - column_set_(), - equal_sets_() + : expr_idx_map_() { } @@ -30,49 +28,45 @@ ObEqualAnalysis::ObEqualAnalysis() int ObEqualAnalysis::init() { int ret = OB_SUCCESS; - if (OB_FAIL(column_set_.create(128, ObModIds::OB_SQL_OPTIMIZER_EQUAL_SETS, - ObModIds::OB_SQL_OPTIMIZER_EQUAL_SETS))) { + if (OB_FAIL(expr_idx_map_.create(128, ObModIds::OB_SQL_OPTIMIZER_EQUAL_SETS, + ObModIds::OB_SQL_OPTIMIZER_EQUAL_SETS))) { LOG_WARN("failed to create hash map", K(ret)); - } else { /*do nothing*/ } + } return ret; } ObEqualAnalysis::~ObEqualAnalysis() { - reset(); + destroy(); } -void ObEqualAnalysis::reset() +void ObEqualAnalysis::destroy() { - //The data structure has only the clear interface - column_set_.reuse(); - DLIST_REMOVE_ALL_NORET(p, equal_sets_) { - if (p != NULL) { - p->~ObEqualSet(); - equal_set_alloc_.free(p); - p = NULL; - } + if (expr_idx_map_.created()) { + expr_idx_map_.destroy(); } - equal_sets_.reset(); - //the allocator is not equal analysis enjoy alone, so can't reset allocator at here } -int ObEqualAnalysis::get_or_add_expr_idx(const ObRawExpr *expr, int64_t &expr_idx) +int ObEqualAnalysis::get_expr_idx(ObRawExpr *expr, int64_t &expr_idx) { int ret = OB_SUCCESS; expr_idx = -1; EqualSetKey key; key.expr_ = expr; - if (OB_SUCC(column_set_.get_refactored(key, expr_idx))) { + if (OB_SUCC(expr_idx_map_.get_refactored(key, expr_idx))) { /*do nothing*/ } else if (OB_HASH_NOT_EXIST != ret) { LOG_WARN("failed to get from hash map", K(ret), K(expr_idx)); } else { ret = OB_SUCCESS; - expr_idx = column_set_.size(); - if (OB_FAIL(column_set_.set_refactored(key, expr_idx))) { + expr_idx = expr_idx_map_.size(); + if (OB_FAIL(expr_idx_map_.set_refactored(key, expr_idx))) { expr_idx = -1; LOG_WARN("set expr index to column set failed", K(ret), K(expr_idx)); + } else if (OB_FAIL(parent_idx_.push_back(expr_idx))) { + LOG_WARN("failed to push back", K(expr_idx)); + } else if (OB_FAIL(exprs_.push_back(expr))) { + LOG_WARN("failed to push back", K(ret)); } } if (OB_SUCC(ret) && expr_idx < 0) { @@ -82,18 +76,59 @@ int ObEqualAnalysis::get_or_add_expr_idx(const ObRawExpr *expr, int64_t &expr_id return ret; } -int ObEqualAnalysis::feed_where_expr(const ObRawExpr *expr) +int ObEqualAnalysis::find_root_idx(const int64_t expr_idx, int64_t &root_idx) { int ret = OB_SUCCESS; - if (OB_ISNULL(expr) || - (T_OP_EQ == expr->get_expr_type() && - (OB_ISNULL(expr->get_param_expr(0)) - || OB_ISNULL(expr->get_param_expr(1))))) { + int64_t parent_idx = -1; + root_idx = expr_idx; + if (OB_UNLIKELY(root_idx < 0 || root_idx >= parent_idx_.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid expr idx", K(ret), K(root_idx)); + } + while (OB_SUCC(ret) && parent_idx_.at(root_idx) != root_idx) { + parent_idx = parent_idx_.at(root_idx); + if (OB_UNLIKELY(parent_idx < 0 || parent_idx >= parent_idx_.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid expr idx", K(ret), K(parent_idx)); + } else { + parent_idx_.at(root_idx) = parent_idx_.at(parent_idx); + root_idx = parent_idx; + } + } + if (OB_SUCC(ret)) { + parent_idx_.at(expr_idx) = root_idx; + } + return ret; +} + +int ObEqualAnalysis::union_expr(const int64_t l_idx, const int64_t r_idx) +{ + int ret = OB_SUCCESS; + int64_t l_root_idx = -1; + int64_t r_root_idx = -1; + if (l_idx == r_idx) { + // do nothing + } else if (OB_FAIL(find_root_idx(l_idx, l_root_idx))) { + LOG_WARN("find root idx failed", K(ret)); + } else if (OB_FAIL(find_root_idx(r_idx, r_root_idx))) { + LOG_WARN("find root idx failed", K(ret)); + } else if (l_root_idx == r_root_idx) { + // do nothing + } else { + parent_idx_[r_root_idx] = l_root_idx; + } + return ret; +} + +int ObEqualAnalysis::feed_where_expr(ObRawExpr *expr) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("expr is null", K(ret)); } else if (T_OP_EQ == expr->get_expr_type()) { /// only add pred like `c1 = c2` - const ObOpRawExpr *eq_expr = static_cast(expr); + ObOpRawExpr *eq_expr = static_cast(expr); if (OB_FAIL(add_equal_cond(*eq_expr))) { LOG_WARN("add equal condition failed", K(ret)); } else { @@ -110,77 +145,63 @@ int ObEqualAnalysis::feed_equal_sets(const EqualSets &input_equal_sets) int ret = OB_SUCCESS; for (int64_t i = 0; OB_SUCC(ret) && i < input_equal_sets.count(); ++i) { const EqualSet *eset = input_equal_sets.at(i); - ObExprEqualSet *equal_set = NULL; - //create new equal set - if (OB_ISNULL(eset)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get null equal set", K(ret)); - } else if (OB_ISNULL(equal_set = new_equal_set())) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_ERROR("create new equal set failed", K(ret)); - } + ObSEArray expr_idx_array; + int64_t min_expr_idx = INT64_MAX; for (int64_t j = 0; OB_SUCC(ret) && j < eset->count(); ++j) { int64_t expr_idx = 0; - const ObRawExpr *expr; + ObRawExpr *expr; if (OB_ISNULL(expr = eset->at(j))) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("expr is null", K(ret)); - } else if (OB_FAIL(get_or_add_expr_idx(expr, expr_idx))) { - LOG_WARN("get or add expr idx failed", K(ret)); - } else if (OB_FAIL(equal_set->add_expr(expr_idx, true, expr))) { - LOG_WARN("add expr to equal set failed", K(ret)); + LOG_WARN("unexpected null expr", K(ret)); + } else if (OB_FAIL(get_expr_idx(expr, expr_idx))) { + LOG_WARN("failed to get expr idx", K(ret), KPC(expr)); + } else if (OB_FAIL(expr_idx_array.push_back(expr_idx))) { + LOG_WARN("failed to push back expr idx", K(ret)); + } else { + min_expr_idx = MIN(min_expr_idx, expr_idx); + } + } + for (int64_t j = 0; OB_SUCC(ret) && j < expr_idx_array.count(); ++j) { + int64_t expr_idx = expr_idx_array.at(j); + if (OB_FAIL(union_expr(min_expr_idx, expr_idx))) { + LOG_WARN("failed to union expr", K(ret), K(min_expr_idx), K(expr_idx)); } } } return ret; } -int ObEqualAnalysis::add_equal_cond(const ObOpRawExpr &expr) +int ObEqualAnalysis::add_equal_cond(ObOpRawExpr &expr) { int ret = OB_SUCCESS; - ObExprEqualSet *equal_set = NULL; int64_t l_expr_idx = 0; int64_t r_expr_idx = 0; - + bool type_safe = false; if (OB_UNLIKELY(expr.get_expr_type() != T_OP_EQ) || OB_ISNULL(expr.get_param_expr(0)) || OB_ISNULL(expr.get_param_expr(1))) { ret = OB_INVALID_ARGUMENT; LOG_WARN("expr is invalid", K(expr)); - } else if (OB_FAIL(get_or_add_expr_idx(expr.get_param_expr(0), l_expr_idx))) { - LOG_WARN("get or add left expr idx failed", K(ret)); - } else if (OB_FAIL(get_or_add_expr_idx(expr.get_param_expr(1), r_expr_idx))) { - LOG_WARN("get or add right expr idx failed", K(ret)); - } else if (l_expr_idx != r_expr_idx) { - //左右两边是完全相等的表达式,例如c1=c1, sum(c1)=sum(c1),属于恒true范围,不具有传递关系,所以不加入集合中 - if (OB_FAIL(find_equal_set(l_expr_idx, expr.get_param_expr(1), equal_set))) { - LOG_WARN("find equal set failed", K(ret), K(l_expr_idx), K(*expr.get_param_expr(1))); - } else if (equal_set != NULL) { - if (!equal_set->has_expr(r_expr_idx)) { - if (OB_FAIL(equal_set->add_expr(r_expr_idx, true, expr.get_param_expr(1)))) { - LOG_WARN("add expr to equal set failed", K(ret)); - } - } - } else if (OB_FAIL(find_equal_set(r_expr_idx, expr.get_param_expr(0), equal_set))) { - LOG_WARN("find equal set failed", K(ret), K(r_expr_idx), K(*expr.get_param_expr(0))); - } else if (equal_set != NULL) { - if (!equal_set->has_expr(l_expr_idx)) { - if (OB_FAIL(equal_set->add_expr(l_expr_idx, true, expr.get_param_expr(0)))) { - LOG_WARN("add expr to equal set failed", K(ret)); - } - } - } - if (OB_SUCC(ret) && NULL == equal_set) { - //create new equal set - if (OB_ISNULL(equal_set = new_equal_set())) { - ret = OB_ALLOCATE_MEMORY_FAILED; - LOG_ERROR("create new equal set failed", K(ret)); - } else if (OB_FAIL(equal_set->add_expr(l_expr_idx, true, expr.get_param_expr(0)))) { - LOG_WARN("add expr to equal set failed", K(ret)); - } else if (OB_FAIL(equal_set->add_expr(r_expr_idx, true, expr.get_param_expr(1)))) { - LOG_WARN("add expr to equal set failed", K(ret)); - } - } + } else if (T_OP_ROW == expr.get_param_expr(0)->get_expr_type() || + T_OP_ROW == expr.get_param_expr(1)->get_expr_type() || + expr.get_param_expr(0)->same_as(*expr.get_param_expr(1))) { + // do nothing + } else if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive( + expr.get_param_expr(0)->get_result_type(), + expr.get_param_expr(1)->get_result_type(), + type_safe))) { + LOG_WARN("failed to check is equal transitive", K(ret), K(expr)); + } else if (!type_safe) { + // do nothting + } else if (OB_FAIL(get_expr_idx(expr.get_param_expr(0), l_expr_idx))) { + LOG_WARN("failed to get left expr idx", K(ret)); + } else if (OB_FAIL(get_expr_idx(expr.get_param_expr(1), r_expr_idx))) { + LOG_WARN("failed to get right expr idx", K(ret)); + } else if (OB_UNLIKELY(l_expr_idx == r_expr_idx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expr idx should not be same", K(ret), K(l_expr_idx), K(r_expr_idx), K(expr)); + } else if (OB_FAIL(union_expr(l_expr_idx, r_expr_idx))) { + LOG_WARN("failed to union expr", K(ret), K(l_expr_idx), K(r_expr_idx)); } return ret; } @@ -188,115 +209,73 @@ int ObEqualAnalysis::add_equal_cond(const ObOpRawExpr &expr) int ObEqualAnalysis::get_equal_sets(ObIAllocator *alloc, EqualSets &equal_sets) const { int ret = OB_SUCCESS; - ObSEArray raw_equal_set; - DLIST_FOREACH(equal_set, equal_sets_) { - raw_equal_set.reuse(); - for (ObExprEqualSet::ColumnIterator iter = equal_set->column_begin(); - OB_SUCC(ret) && iter != equal_set->column_end(); ++iter) { - if (OB_FAIL(raw_equal_set.push_back( - const_cast(iter.get_expr_info())))) { - LOG_WARN("push back equal expr info failed", K(ret)); - } - } - if (OB_SUCC(ret)) { - if (OB_FAIL(ObRawExprSetUtils::add_expr_set( - alloc, raw_equal_set, equal_sets))) { - LOG_WARN("failed to add expr set", K(ret)); - } - } + ObSEArray union_set_map; + ObSEArray set_count_list; + if (OB_ISNULL(alloc)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_UNLIKELY(exprs_.count() != parent_idx_.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected count", K(ret), K(exprs_.count()), K(parent_idx_.count())); } - return ret; -} - -ObExprEqualSet *ObEqualAnalysis::new_equal_set() -{ - void *ptr = NULL; - ObExprEqualSet *equal_set = NULL; - if (NULL != (ptr = equal_set_alloc_.alloc(sizeof(ObExprEqualSet)))) { - equal_set = new(ptr) ObExprEqualSet(); - if (!equal_sets_.add_last(equal_set)) { - LOG_WARN_RET(OB_ERR_UNEXPECTED, "add equal set failed"); - equal_set->~ObEqualSet(); - equal_set_alloc_.free(equal_set); - equal_set = NULL; - } - } - return equal_set; -} - -int ObEqualAnalysis::find_equal_set(int64_t expr_idx, const ObRawExpr *new_expr, ObExprEqualSet *&equal_set_ret) -{ - int ret = OB_SUCCESS; - const ObRawExpr* const *same_expr = NULL; - DLIST_FOREACH(equal_set, equal_sets_) { - if (OB_ISNULL(equal_set)) { + for (int64_t i = 0; OB_SUCC(ret) && i < parent_idx_.count(); ++i) { + int64_t root_idx = parent_idx_.at(i); + if (OB_UNLIKELY(root_idx < 0)) { ret = OB_ERR_UNEXPECTED; - LOG_ERROR("equal set is null"); - } else if ((same_expr = equal_set->get_expr(expr_idx)) != NULL) { - bool can_be = false; - if (OB_FAIL(expr_can_be_add_to_equal_set(*equal_set, *same_expr, new_expr, can_be))) { - LOG_WARN("check expr whether can be add to equal set failed", K(ret)); - } else if (can_be) { - equal_set_ret = equal_set; - break; + LOG_WARN("unexpected root_idx", K(ret), K(root_idx)); + } else if (root_idx >= union_set_map.count()) { + int64_t old_count = union_set_map.count(); + if (OB_FAIL(union_set_map.prepare_allocate(root_idx + 1))) { + LOG_WARN("failed to prepare allocate", K(ret)); + } else if (OB_FAIL(set_count_list.push_back(1))) { + LOG_WARN("failed to push back", K(ret)); + } else { + for (int64_t i = old_count; OB_SUCC(ret) && i < root_idx; ++i) { + union_set_map.at(i) = -1; + } + union_set_map.at(root_idx) = set_count_list.count() - 1; + } + } else if (-1 == union_set_map.at(root_idx)) { + if (OB_FAIL(set_count_list.push_back(1))) { + LOG_WARN("failed to push back", K(ret)); + } else { + union_set_map.at(root_idx) = set_count_list.count() - 1; + } + } else { + int64_t set_idx = union_set_map.at(root_idx); + ++set_count_list.at(set_idx); + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < set_count_list.count(); ++i) { + ObRawExprSet *expr_set = NULL; + void *ptr = NULL; + if (OB_UNLIKELY(set_count_list.at(i) < 2)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected set count", K(set_count_list), K(parent_idx_)); + } else if (OB_ISNULL(ptr = alloc->alloc(sizeof(ObRawExprSet)))) { + ret = OB_ALLOCATE_MEMORY_FAILED; + LOG_WARN("no memory to create ObRawExprSet", K(ret)); + } else { + expr_set = new(ptr) ObRawExprSet(); + expr_set->set_allocator(alloc); + if (OB_FAIL(expr_set->init(set_count_list.at(i)))) { + LOG_WARN("failed to init expr set", K(ret)); + } else if (OB_FAIL(equal_sets.push_back(expr_set))) { + LOG_WARN("failed to push back expr set", K(ret)); } } } - return ret; -} - -//检查equal set中的元素和要加入equal set中的元素的compare type是否都一致 -int ObEqualAnalysis::expr_can_be_add_to_equal_set(const ObExprEqualSet &equal_set, - const ObRawExpr *same_expr, - const ObRawExpr *new_expr, - bool &can_be) const -{ - can_be = true; - int ret = OB_SUCCESS; - //equal set中的元素至少是两个表达式 - if (equal_set.get_column_num() <= 1 || OB_ISNULL(same_expr) || OB_ISNULL(new_expr)) { - ret = OB_INVALID_ARGUMENT; - LOG_ERROR("arguments are invalid", K(equal_set.get_column_num()), K(same_expr), K(new_expr)); - } else { - for (ObExprEqualSet::ColumnIterator iter = equal_set.column_begin(); - OB_SUCC(ret) && can_be && iter != equal_set.column_end(); ++iter) { - const ObRawExpr *cur_expr = iter.get_expr_info(); - if (OB_ISNULL(cur_expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_ERROR("expr is null in equal set"); - } else if (cur_expr == same_expr) { - //do nothing - } else if (OB_FAIL(check_type_equivalent(*cur_expr, *same_expr, *new_expr, can_be))) { - LOG_WARN("failed to check type equivalent", K(ret)); - } - } - } - return ret; -} - -//检查两个equal set是否能够被合并成一个equal set -//能够被合并的规则是,两个equal set有相同的表达式,并且不相同的表达式的元素都在另一个equal set中的compare type都相同 -int ObEqualAnalysis::check_whether_can_be_merged(const ObExprEqualSet &equal_set, - const ObExprEqualSet &another_set, - bool &can_be) const -{ - can_be = true; - int ret = OB_SUCCESS; - const ObRawExpr* const *same_expr = NULL; - if (!equal_set.intersect_equal_set(another_set)) { - can_be = false; - } else { - for (ObExprEqualSet::ColumnIterator iter = another_set.column_begin(); - OB_ISNULL(same_expr) && iter != another_set.column_end(); ++iter) { - same_expr = equal_set.get_expr(iter.get_expr_idx()); - } - } - for (ObExprEqualSet::ColumnIterator iter = another_set.column_begin(); - OB_SUCC(ret) && can_be && iter != another_set.column_end(); ++iter) { - if (iter.get_expr_info() != *same_expr) { - if (OB_FAIL(expr_can_be_add_to_equal_set(equal_set, *same_expr, iter.get_expr_info(), can_be))) { - LOG_WARN("check expr whether can be add to equal set failed", K(ret)); - } + for (int64_t i = 0; OB_SUCC(ret) && i < parent_idx_.count(); ++i) { + int64_t root_idx = parent_idx_.at(i); + int64_t set_idx = union_set_map.at(root_idx); + if (OB_UNLIKELY(set_idx < 0 || set_idx >= equal_sets.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected set_idx", K(ret), K(root_idx)); + } else if (OB_ISNULL(equal_sets.at(set_idx))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null equal set", K(ret)); + } else if (OB_FAIL(equal_sets.at(set_idx)->push_back(exprs_.at(i)))) { + LOG_WARN("failed to push back expr", K(ret)); } } return ret; @@ -305,91 +284,11 @@ int ObEqualAnalysis::check_whether_can_be_merged(const ObExprEqualSet &equal_set int ObEqualAnalysis::finish_feed() { int ret = OB_SUCCESS; - // merge intersected sets - ObExprEqualSet *another_set = NULL; - DLIST_FOREACH(equal_set, equal_sets_) { - if (OB_ISNULL(equal_set)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("equal set is null", K(equal_set)); - } else { - another_set = equal_set->get_next(); + int64_t dummy_idx = 0; + for (int64_t i = 0; OB_SUCC(ret) && i < parent_idx_.count(); ++i) { + if (OB_FAIL(find_root_idx(i, dummy_idx))) { + LOG_WARN("failed to find root idx", K(ret)); } - while (OB_SUCC(ret) && equal_sets_.get_header() != another_set) { - bool can_be = false; - if (OB_ISNULL(another_set)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("equal set is null", K(another_set)); - } else if (OB_FAIL(check_whether_can_be_merged(*equal_set, - *another_set, - can_be))) { - LOG_WARN("check whether can be merged failed", K(ret)); - } else if (!can_be) { - another_set = another_set->get_next(); - } else { - // merge another_set into equal_set - for (ObExprEqualSet::ColumnIterator it = another_set->column_begin(); - OB_SUCC(ret) && it != another_set->column_end(); ++it) { - if (!equal_set->has_expr(it.get_expr_idx())) { - if (OB_FAIL(equal_set->add_expr(it.get_expr_idx(), it.get_flag(), it.get_expr_info()))) { - LOG_WARN("add expr to equal set failed", K(ret)); - } - } - } - if (OB_SUCC(ret)) { - ObExprEqualSet *tmp = another_set->get_next(); - equal_sets_.remove(another_set); - equal_set_alloc_.free(another_set); - another_set = tmp; - } - } - } - } - return ret; -} - -int ObEqualAnalysis::check_type_equivalent( - const ObRawExpr &cur_expr, const ObRawExpr &same_expr, - const ObRawExpr &new_expr, bool &can_be) -{ - int ret = OB_SUCCESS; - bool is_stack_overflow = false; - if (OB_FAIL(check_stack_overflow(is_stack_overflow))) { - LOG_WARN("failed to check stack overflow", K(ret), K(is_stack_overflow)); - } else if (is_stack_overflow) { - ret = OB_SIZE_OVERFLOW; - LOG_WARN("too deep recursive", K(ret), K(is_stack_overflow)); - } else if (T_OP_ROW == cur_expr.get_expr_type() - && T_OP_ROW == new_expr.get_expr_type() - && T_OP_ROW == same_expr.get_expr_type()) { - if (cur_expr.get_param_count() != same_expr.get_param_count() - || same_expr.get_param_count() != new_expr.get_param_count()) { - can_be = false; - } else { - for (int64_t i = 0; OB_SUCC(ret) && can_be && i < cur_expr.get_param_count(); i++) { - const ObRawExpr *c_cur = NULL; - const ObRawExpr *c_same = NULL; - const ObRawExpr *c_new = NULL; - if (OB_ISNULL(c_cur = cur_expr.get_param_expr(i)) - || OB_ISNULL(c_same = same_expr.get_param_expr(i)) - || OB_ISNULL(c_new = new_expr.get_param_expr(i))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("NULL expr", K(ret), K(c_cur), K(c_same), K(c_new)); - } else if (OB_FAIL(SMART_CALL(check_type_equivalent(*c_cur, *c_same, *c_new, can_be)))) { - LOG_WARN("failed to check type in row"); - } - } - } - } else if (T_OP_ROW != cur_expr.get_expr_type() - && T_OP_ROW != new_expr.get_expr_type() - && T_OP_ROW != same_expr.get_expr_type()) { - if (OB_FAIL(ObRelationalExprOperator::is_equivalent( - cur_expr.get_result_type(), - same_expr.get_result_type(), - new_expr.get_result_type(), can_be))) { - LOG_WARN("check is equivalent failed", K(ret)); - } - } else { - can_be = false; } return ret; } diff --git a/src/sql/rewrite/ob_equal_analysis.h b/src/sql/rewrite/ob_equal_analysis.h index eca7bceda5..47bb4b6b80 100644 --- a/src/sql/rewrite/ob_equal_analysis.h +++ b/src/sql/rewrite/ob_equal_analysis.h @@ -15,12 +15,10 @@ #include "sql/resolver/dml/ob_dml_stmt.h" #include "sql/resolver/expr/ob_raw_expr.h" -#include "sql/rewrite/ob_equal_set.h" namespace oceanbase { namespace sql { -typedef ObEqualSet ObExprEqualSet; // An algorithm class to generate all equal condition expression struct EqualSetKey { @@ -36,7 +34,7 @@ struct EqualSetKey { uint64_t result = 0; if (NULL != expr_) { - result = expr_->hash(result); + result = expr_->get_expr_hash(); } return result; } @@ -44,24 +42,22 @@ struct EqualSetKey const ObRawExpr *expr_; TO_STRING_KV(K_(expr)); }; + class ObEqualAnalysis { public: explicit ObEqualAnalysis(); virtual ~ObEqualAnalysis(); - void reset(); + void destroy(); int init(); // input int feed_equal_sets(const EqualSets &equal_sets); - int feed_where_expr(const ObRawExpr *expr); + int feed_where_expr(ObRawExpr *expr); int finish_feed(); // output int get_equal_sets(ObIAllocator *allocator, EqualSets &equal_sets) const; - TO_STRING_KV(K_(equal_sets)); - - static int check_type_equivalent(const ObRawExpr &cur_expr, const ObRawExpr &same_expr, - const ObRawExpr &new_expr, bool &can_be); + TO_STRING_KV(K_(parent_idx), K_(exprs)); static int compute_equal_set(ObIAllocator *allocator, const ObIArray &eset_conditions, @@ -81,30 +77,22 @@ public: const EqualSets &left_equal_sets, const EqualSets &right_equal_sets, EqualSets &output_equal_sets); -protected: +private: // types and constants typedef common::hash::ObHashMap ColumnSet; -protected: - // disallow copy - DISALLOW_COPY_AND_ASSIGN(ObEqualAnalysis); + common::hash::NoPthreadDefendMode> ExprIdxMap; // function members - ObExprEqualSet *new_equal_set(); - int find_equal_set(int64_t expr_idx, const ObRawExpr *new_expr, ObExprEqualSet *&equal_set_ret); - int add_equal_cond(const ObOpRawExpr &expr); - int get_or_add_expr_idx(const ObRawExpr *expr, int64_t &expr_idx); - int expr_can_be_add_to_equal_set(const ObExprEqualSet &equal_set, - const ObRawExpr *same_expr, - const ObRawExpr *new_expr, - bool &can_be) const; - int check_whether_can_be_merged(const ObExprEqualSet &equal_set, - const ObExprEqualSet &another_set, - bool &can_be) const; -protected: + int add_equal_cond(ObOpRawExpr &expr); + int get_expr_idx(ObRawExpr *expr, int64_t &expr_idx); + int find_root_idx(const int64_t expr_idx, int64_t &root_idx); + int union_expr(const int64_t l_idx, const int64_t r_idx); +private: // data members - common::ObArenaAllocator equal_set_alloc_; - ColumnSet column_set_; - common::ObDList equal_sets_; + ExprIdxMap expr_idx_map_; + common::ObSEArray parent_idx_; + common::ObSEArray exprs_; +private: + DISALLOW_COPY_AND_ASSIGN(ObEqualAnalysis); }; } // end namespace sql } // end namespace oceanbase diff --git a/src/sql/rewrite/ob_equal_set.h b/src/sql/rewrite/ob_equal_set.h deleted file mode 100644 index a868bb247f..0000000000 --- a/src/sql/rewrite/ob_equal_set.h +++ /dev/null @@ -1,109 +0,0 @@ -/** - * Copyright (c) 2021 OceanBase - * OceanBase CE is licensed under Mulan PubL v2. - * You can use this software according to the terms and conditions of the Mulan PubL v2. - * You may obtain a copy of Mulan PubL v2 at: - * http://license.coscl.org.cn/MulanPubL-2.0 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PubL v2 for more details. - */ - -#ifndef _OB_EQUAL_SET_H -#define _OB_EQUAL_SET_H -#include "lib/utility/ob_print_utils.h" -#include "lib/list/ob_dlist.h" -#include "lib/container/ob_se_array.h" -#include "lib/container/ob_bit_set.h" -#include "lib/hash/ob_iteratable_hashmap.h" -namespace oceanbase -{ -namespace sql -{ -// Set <{, , }, {1, 2}> means c1 = c2 and c2 = c3 and c3 in (1, 2) -template -class ObEqualSet: public common::ObDLinkBase > -{ - typedef typename common::hash::ObIteratableHashMap::const_iterator_t ColIter; -public: - struct ColumnIterator - { - public: - ColumnIterator(); - ColumnIterator(const ObEqualSet *equal_set, const ColIter &col_iter); - ~ColumnIterator(); - ColumnIterator(const ColumnIterator &other); - ColumnIterator &operator=(const ColumnIterator &other); - - bool operator==(const ColumnIterator &other) const; - bool operator!=(const ColumnIterator &other) const; - - ColumnIterator &operator++(); - bool get_flag() const; - int64_t get_expr_idx() const; - const COLUMN_INFO &get_expr_info() const; - private: - const ObEqualSet *equal_set_; - ColIter col_iter_; - }; -public: - ObEqualSet(); - virtual ~ObEqualSet(); - - int add_expr(int64_t expr_idx, bool flag, const COLUMN_INFO &payload); - int set_flag(int64_t expr_idx, bool flag); - bool has_expr(int64_t expr_idx) const; - const COLUMN_INFO *get_expr(int64_t expr_idx) const; - - int add_const(const CONST_INFO &obj); - bool has_const() const; - -// void reset(); - - int64_t get_column_num() const; - ColumnIterator column_begin() const - { - return ColumnIterator(this, exprs_.begin()); - } - ColumnIterator column_end() const - { - return ColumnIterator(this, exprs_.end()); - } - - int64_t get_const_num() const; - int get_const(int64_t idx, CONST_INFO &val) const; - - bool includes_equal_set(const ObEqualSet &other) const - { - return other.expr_bitmap_.is_subset(expr_bitmap_); - } - bool intersect_equal_set(const ObEqualSet &other) const; - common::ObIArray &get_constants() - { - return constants_; - } - TO_STRING_KV(N_COLUMN, exprs_, - N_CONST, constants_); -private: - // types and constants - static const int64_t COMMON_CONST_NUM = 64; - typedef common::ObSEArray Constants; - typedef common::hash::ObIteratableHashMap Expressions; -private: - // disallow copy - ObEqualSet(const ObEqualSet &other); - ObEqualSet &operator=(const ObEqualSet &other); - // function members -private: - // data members - Expressions exprs_; - common::ObBitSet flags_; // column flag - common::ObBitSet expr_bitmap_; - Constants constants_; // const values information -}; -} // end namespace sql -} // end namespace oceanbase - -#include "ob_equal_set.ipp" -#endif /* _OB_EQUAL_SET_H */ diff --git a/src/sql/rewrite/ob_equal_set.ipp b/src/sql/rewrite/ob_equal_set.ipp deleted file mode 100644 index d4bf2a1846..0000000000 --- a/src/sql/rewrite/ob_equal_set.ipp +++ /dev/null @@ -1,186 +0,0 @@ -/** - * Copyright (c) 2021 OceanBase - * OceanBase CE is licensed under Mulan PubL v2. - * You can use this software according to the terms and conditions of the Mulan PubL v2. - * You may obtain a copy of Mulan PubL v2 at: - * http://license.coscl.org.cn/MulanPubL-2.0 - * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, - * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, - * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. - * See the Mulan PubL v2 for more details. - */ - -namespace oceanbase -{ -namespace sql -{ -template -ObEqualSet::ObEqualSet() -{ -} -template -ObEqualSet::~ObEqualSet() -{ -} - -template -int ObEqualSet::add_expr(int64_t expr_idx, bool flag, const COLUMN_INFO &payload) -{ - int ret = common::OB_SUCCESS; - if (OB_UNLIKELY(expr_idx < 0)) { - ret = common::OB_INVALID_ARGUMENT; - SQL_REWRITE_LOG(WARN, "expr_idx is invalid", K(expr_idx)); - } else if (OB_FAIL(exprs_.set_refactored(expr_idx, payload))) { - SQL_REWRITE_LOG(WARN, "set exprs failed", K(ret)); - } else if (OB_FAIL(expr_bitmap_.add_member(static_cast(expr_idx)))) { - SQL_REWRITE_LOG(WARN, "add member failed", K(ret)); - } else { - if (flag) { - if (OB_FAIL(flags_.add_member(static_cast(expr_idx)))) { - SQL_REWRITE_LOG(WARN, "add member failed", K(ret)); - } - } - } - return ret; -} - -template -bool ObEqualSet::intersect_equal_set(const ObEqualSet &other) const -{ - return expr_bitmap_.overlap(other.expr_bitmap_); -} - -template -int ObEqualSet::set_flag(int64_t expr_idx, bool flag) -{ - int ret = common::OB_SUCCESS; - if (OB_UNLIKELY(expr_idx < 0)) { - ret = common::OB_INVALID_ARGUMENT; - SQL_REWRITE_LOG(WARN, "expr_idx is invalid", K(expr_idx)); - } else { - if (flag) { - if (OB_FAIL(flags_.add_member(static_cast(expr_idx)))) { - SQL_REWRITE_LOG(WARN, "add member failed", K(ret)); - } - } else { - if (OB_FAIL(flags_.del_member(static_cast(expr_idx)))) { - SQL_REWRITE_LOG(WARN, "del member failed", K(ret)); - } - } - } - return ret; -} - -template -bool ObEqualSet::has_expr(int64_t expr_idx) const -{ - return NULL != exprs_.get(expr_idx); -} - -template -const COLUMN_INFO *ObEqualSet::get_expr(int64_t expr_idx) const -{ - return exprs_.get(expr_idx); -} - -template -int ObEqualSet::add_const(const CONST_INFO &obj) -{ - return constants_.push_back(obj); -} -template -bool ObEqualSet::has_const() const -{ - return constants_.count() > 0; -} - -//template -//void ObEqualSet::reset() -//{ -// exprs_.reuse(); -// flags_.reset(); -// constants_.reset(); -// expr_bitmap_.reset(); -//} -template -int64_t ObEqualSet::get_column_num() const -{ - return exprs_.count(); -} -template -int64_t ObEqualSet::get_const_num() const -{ - return constants_.count(); -} -template -int ObEqualSet::get_const(int64_t idx, CONST_INFO &val) const -{ - return constants_.at(idx, val); -} -//////////////////////////////////////////////////////////////// -template -ObEqualSet::ColumnIterator::ColumnIterator() - : equal_set_(NULL), - col_iter_() -{ -} -template -ObEqualSet::ColumnIterator::ColumnIterator(const ObEqualSet *equal_set, - const ObEqualSet::ColIter &col_iter) - : equal_set_(equal_set), - col_iter_(col_iter) -{ -} -template -ObEqualSet::ColumnIterator::~ColumnIterator() -{ -} -template -ObEqualSet::ColumnIterator::ColumnIterator(const ObEqualSet::ColumnIterator &other) - : equal_set_(other.equal_set_), - col_iter_(other.col_iter_) -{ -} -template -typename ObEqualSet::ColumnIterator -&ObEqualSet::ColumnIterator::operator=(const ObEqualSet::ColumnIterator &other) -{ - if (this != &other) { - equal_set_ = other.equal_set_; - col_iter_ = other.col_iter_; - } - return *this; -} -template -bool ObEqualSet::ColumnIterator::operator==(const ObEqualSet::ColumnIterator &other) const -{ - return equal_set_ == other.equal_set_ && col_iter_ == other.col_iter_; -} -template -bool ObEqualSet::ColumnIterator::operator!=(const ObEqualSet::ColumnIterator &other) const -{ - return equal_set_ != other.equal_set_ || col_iter_ != other.col_iter_; -} -template -typename ObEqualSet::ColumnIterator &ObEqualSet::ColumnIterator::operator++() -{ - ++col_iter_; - return *this; -} -template -bool ObEqualSet::ColumnIterator::get_flag() const -{ - return equal_set_->flags_.has_member(static_cast((*col_iter_).first)); -} -template -int64_t ObEqualSet::ColumnIterator::get_expr_idx() const -{ - return (*col_iter_).first; -} -template -const COLUMN_INFO &ObEqualSet::ColumnIterator::get_expr_info() const -{ - return (*col_iter_).second; -} -} // end namespace sql -} // end namespace oceanbase diff --git a/src/sql/rewrite/ob_expand_aggregate_utils.cpp b/src/sql/rewrite/ob_expand_aggregate_utils.cpp index 7d8b255973..761f2a28c5 100644 --- a/src/sql/rewrite/ob_expand_aggregate_utils.cpp +++ b/src/sql/rewrite/ob_expand_aggregate_utils.cpp @@ -532,6 +532,8 @@ int ObExpandAggregateUtils::add_aggr_item(ObIArray &new_aggr_i if (OB_ISNULL(aggr_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(aggr_expr)); + } else if (OB_FAIL(aggr_expr->calc_hash())) { + LOG_WARN("failed to calc expr hash", K(ret)); } else { int64_t i = 0; for (; OB_SUCC(ret) && i < new_aggr_items.count(); ++i) { @@ -2253,7 +2255,9 @@ int ObExpandAggregateUtils::add_win_exprs(ObSelectStmt *select_stmt, if (OB_ISNULL(new_win_exprs.at(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret), K(new_win_exprs.at(i))); - } else if (OB_ISNULL(win_expr = select_stmt->get_same_win_func_item(new_win_exprs.at(i)))) { + } else if (OB_FAIL(select_stmt->get_same_win_func_item(new_win_exprs.at(i), win_expr))) { + LOG_WARN("failed to get same win func item", K(ret)); + } else if (OB_ISNULL(win_expr)) { if (OB_FAIL(select_stmt->add_window_func_expr(new_win_exprs.at(i)))) { LOG_WARN("failed to add window func expr", K(ret)); } diff --git a/src/sql/rewrite/ob_predicate_deduce.cpp b/src/sql/rewrite/ob_predicate_deduce.cpp index 1c8226c656..968550695b 100644 --- a/src/sql/rewrite/ob_predicate_deduce.cpp +++ b/src/sql/rewrite/ob_predicate_deduce.cpp @@ -17,6 +17,7 @@ #include "sql/optimizer/ob_optimizer_util.h" #include "sql/rewrite/ob_transform_utils.h" #include "sql/resolver/expr/ob_raw_expr_util.h" +#include "sql/resolver/expr/ob_shared_expr_resolver.h" using namespace oceanbase::sql; using namespace oceanbase::common; @@ -81,7 +82,7 @@ int ObPredicateDeduce::check_deduce_validity(ObRawExpr *cond, bool &is_valid) } int ObPredicateDeduce::deduce_simple_predicates(ObTransformerCtx &ctx, - ObIArray &result) + ObIArray &result) { int ret = OB_SUCCESS; ObArray chosen; @@ -352,6 +353,8 @@ int ObPredicateDeduce::create_simple_preds(ObTransformerCtx &ctx, ObRawExpr *pred = NULL; ObRawExprFactory *expr_factory = ctx.expr_factory_; ObSQLSessionInfo *session_info = ctx.session_info_; + ObQuestionmarkEqualCtx cmp_ctx(false); + ObSEArray tmp_exprs; if (OB_ISNULL(session_info) || OB_ISNULL(expr_factory)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("params are invalid", K(ret), K(session_info), K(expr_factory)); @@ -368,7 +371,7 @@ int ObPredicateDeduce::create_simple_preds(ObTransformerCtx &ctx, LOG_WARN("failed to create double op expr", K(ret)); } else if (OB_FAIL(pred->pull_relation_id())) { LOG_WARN("failed to pull relation id and levels", K(ret)); - } else if (OB_FAIL(output_exprs.push_back(pred))) { + } else if (OB_FAIL(tmp_exprs.push_back(pred))) { LOG_WARN("failed to push back pred", K(ret)); } } @@ -380,7 +383,7 @@ int ObPredicateDeduce::create_simple_preds(ObTransformerCtx &ctx, LOG_WARN("failed to create double op expr", K(ret)); } else if (OB_FAIL(pred->pull_relation_id())) { LOG_WARN("failed to pull relation id and levels", K(ret)); - } else if (OB_FAIL(output_exprs.push_back(pred))) { + } else if (OB_FAIL(tmp_exprs.push_back(pred))) { LOG_WARN("failed to push back pred", K(ret)); } } @@ -392,12 +395,27 @@ int ObPredicateDeduce::create_simple_preds(ObTransformerCtx &ctx, LOG_WARN("failed to create double op expr", K(ret)); } else if (OB_FAIL(pred->pull_relation_id())) { LOG_WARN("failed to pull relation id and levels", K(ret)); - } else if (OB_FAIL(output_exprs.push_back(pred))) { + } else if (OB_FAIL(tmp_exprs.push_back(pred))) { LOG_WARN("failed to push back pred", K(ret)); } } } } + for (int64_t i = 0; OB_SUCC(ret) && i < tmp_exprs.count(); ++i) { + bool find_same = false; + for (int64_t j = 0; OB_SUCC(ret) && !find_same && j < output_exprs.count(); ++j) { + if (OB_ISNULL(output_exprs.at(j))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expr is null", K(ret), K(j)); + } else if (tmp_exprs.at(i)->same_as(*output_exprs.at(j), &cmp_ctx)) { + find_same = true; + // no need to add constraints + } + } + if (OB_SUCC(ret) && !find_same && OB_FAIL(output_exprs.push_back(tmp_exprs.at(i)))) { + LOG_WARN("failed to push back expr", K(ret)); + } + } return ret; } diff --git a/src/sql/rewrite/ob_transform_aggr_subquery.cpp b/src/sql/rewrite/ob_transform_aggr_subquery.cpp index c6f0b0669c..942309eb03 100644 --- a/src/sql/rewrite/ob_transform_aggr_subquery.cpp +++ b/src/sql/rewrite/ob_transform_aggr_subquery.cpp @@ -180,8 +180,6 @@ int ObTransformAggrSubquery::transform_with_aggregation_first(ObDMLStmt *&stmt, if (OB_ISNULL(stmt) || OB_ISNULL(query_hint = stmt->get_stmt_hint().query_hint_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret), K(ctx_), K(query_hint)); - ret = OB_INVALID_ARGUMENT; - LOG_WARN("invalid params", K(ret), K(stmt)); } else if (stmt->is_hierarchical_query() || stmt->is_set_stmt() || !stmt->is_sel_del_upd()) { OPT_TRACE("hierarchical/set/insert/merge query can not transform"); } else if (OB_FAIL(stmt->is_hierarchical_for_update(is_hsfu))) { diff --git a/src/sql/rewrite/ob_transform_const_propagate.cpp b/src/sql/rewrite/ob_transform_const_propagate.cpp index aeefb8da65..147715166f 100644 --- a/src/sql/rewrite/ob_transform_const_propagate.cpp +++ b/src/sql/rewrite/ob_transform_const_propagate.cpp @@ -443,7 +443,7 @@ int ObTransformConstPropagate::do_transform(ObDMLStmt *stmt, if (OB_SUCC(ret) && !const_ctx.active_const_infos_.empty() && stmt->is_update_stmt()) { is_happened = false; ObUpdateStmt *upd_stmt = static_cast(stmt); - for (int64_t i = 0; OB_SUCC(ret) && i < upd_stmt->get_update_table_info().count(); ++i) { + for (int64_t i = 0; OB_SUCC(ret) && i < upd_stmt->get_update_table_info().count(); ++i) { ObUpdateTableInfo* table_info = upd_stmt->get_update_table_info().at(i); if (OB_ISNULL(table_info)) { ret = OB_ERR_UNEXPECTED; @@ -1916,6 +1916,7 @@ int ObTransformConstPropagate::recursive_collect_equal_pair_from_condition(ObDML } } if (OB_SUCC(ret) && is_valid) { + new_info.exclude_expr_ = expr; if (OB_FAIL(const_ctx.add_const_info(new_info))) { LOG_WARN("failed to push back", K(ret)); } diff --git a/src/sql/rewrite/ob_transform_distinct_aggregate.cpp b/src/sql/rewrite/ob_transform_distinct_aggregate.cpp new file mode 100644 index 0000000000..e764dc5734 --- /dev/null +++ b/src/sql/rewrite/ob_transform_distinct_aggregate.cpp @@ -0,0 +1,323 @@ +/** + * Copyright (c) 2024 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX SQL_REWRITE +#include "ob_transform_distinct_aggregate.h" +#include "sql/rewrite/ob_transform_utils.h" +#include "sql/resolver/expr/ob_raw_expr_util.h" +#include "sql/optimizer/ob_optimizer_util.h" + +using namespace oceanbase::sql; +using namespace oceanbase::common; + +/** + * @brief ObTransformDistinctAggregate::transform_one_stmt + * + * If all distinct aggregate functions have the same param expr, and all of the + * other aggregate functions are pre-aggregatable. We can do the deduplication + * and pre-aggregation in a subquery. + * + * e.g. + * select count(distinct c1), sum(c2) from t1 group by c3; + * -> + * select count(view1.c1), sum(view1.sum(c2)) + * from (select c1, c3, sum(c2) from t1 group by c1, c3) view1 + * group by c3; + */ +int ObTransformDistinctAggregate::transform_one_stmt(common::ObIArray &parent_stmts, + ObDMLStmt *&stmt, + bool &trans_happened) +{ + int ret = OB_SUCCESS; + bool is_valid = false; + trans_happened = false; + UNUSED(parent_stmts); + if (OB_FAIL(check_transform_validity(stmt, is_valid))) { + LOG_WARN("failed to check transform validity", K(ret)); + } else if (!is_valid) { + // do nothing + } else if (OB_FAIL(do_transform(static_cast(stmt), + trans_happened))) { + LOG_WARN("failed to transform distinct aggregate", K(ret)); + } else if (trans_happened && OB_FAIL(add_transform_hint(*stmt))) { + LOG_WARN("failed to add transform hint", K(ret)); + } + return ret; +} + +/** + * @brief ObTransformDistinctAggregate::check_transform_validity + * + * All of non-distinct aggregate functions should be pre-aggregatable, and + * all of distinct aggregate functions should have the same param expr. + */ +int ObTransformDistinctAggregate::check_transform_validity(const ObDMLStmt *stmt, + bool &is_valid) +{ + int ret = OB_SUCCESS; + const ObSelectStmt *select_stmt = NULL; + const ObRawExpr *distinct_expr = NULL; + is_valid = true; + if (OB_ISNULL(stmt) || OB_ISNULL(stmt->get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(stmt)); + } else if (!stmt->get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_3_5)) { + is_valid = false; + OPT_TRACE("can not do transform, optimizer feature version is lower than 4.3.5"); + } else if (!stmt->is_select_stmt()) { + is_valid = false; + OPT_TRACE("can not do transform, stmt is not a select stmt"); + } else if (OB_FALSE_IT(select_stmt = static_cast(stmt))) { + } else if (select_stmt->is_hierarchical_query() + || select_stmt->is_contains_assignment()) { + is_valid = false; + OPT_TRACE("can not do transform, stmt is a hierarchical query or contains assignment"); + } else if (select_stmt->get_aggr_item_size() <= 0 + || select_stmt->get_rollup_expr_size() != 0 + || select_stmt->get_grouping_sets_items_size() != 0 + || select_stmt->get_rollup_items_size() != 0 + || select_stmt->get_cube_items_size() != 0) { + is_valid = false; + OPT_TRACE("can not do transform, stmt has no aggregate or has rollup"); + } + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < select_stmt->get_aggr_item_size(); ++i) { + const ObAggFunRawExpr *aggr_expr = select_stmt->get_aggr_item(i); + if (OB_ISNULL(aggr_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("agg expr is null", K(ret), K(i)); + } else if (aggr_expr->is_param_distinct()) { + if (aggr_expr->get_real_param_count() != 1) { + is_valid = false; + OPT_TRACE("can not do transform, distinct aggregate has more than one param"); + } else if (OB_ISNULL(aggr_expr->get_real_param_exprs().at(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("param of distinct aggregate function is NULL", K(ret), KPC(aggr_expr)); + } else if (distinct_expr == NULL) { + distinct_expr = aggr_expr->get_real_param_exprs().at(0); + } else if (!distinct_expr->same_as(*aggr_expr->get_real_param_exprs().at(0))) { + is_valid = false; + OPT_TRACE("can not do transform, stmt has more than one distinct column"); + } + } else if (OB_FAIL(ObOptimizerUtil::check_aggr_can_pre_aggregate(aggr_expr, is_valid))) { + LOG_WARN("failed to check aggr can pre aggregate", K(ret), KPC(aggr_expr)); + } else if (!is_valid) { + OPT_TRACE("can not do transform, stmt has aggregate function that can not pre aggregate"); + } + } + if (OB_SUCC(ret) && is_valid && NULL == distinct_expr) { + is_valid = false; + OPT_TRACE("do not need to transform, stmt has no distinct aggregate function"); + } + return ret; +} + +int ObTransformDistinctAggregate::do_transform(ObSelectStmt *stmt, + bool &trans_happened) +{ + int ret = OB_SUCCESS; + ObSEArray non_distinct_aggr; + ObSEArray distinct_aggr; + ObSEArray from_tables; + ObSEArray semi_infos; + ObSEArray view_select_exprs; + ObSEArray view_group_exprs; + ObSEArray view_cond_exprs; + TableItem *view_table = NULL; + trans_happened = false; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(classify_aggr_exprs(stmt->get_aggr_items(), + non_distinct_aggr, + distinct_aggr))) { + LOG_WARN("failed to classify aggr exprs", K(ret)); + } else if (OB_UNLIKELY(distinct_aggr.empty() || NULL == distinct_aggr.at(0) + || 1 != distinct_aggr.at(0)->get_real_param_count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected distinct aggr", K(ret), K(distinct_aggr)); + } else if (OB_FAIL(construct_view_select_exprs(non_distinct_aggr, + distinct_aggr, + view_select_exprs))) { + LOG_WARN("failed to construct view select exprs", K(ret)); + } else if (OB_FAIL(append(view_group_exprs, stmt->get_group_exprs()))) { + LOG_WARN("failed to append group exprs", K(ret)); + } else if (OB_FAIL(append(view_group_exprs, distinct_aggr.at(0)->get_real_param_exprs()))) { + LOG_WARN("failed to append group exprs", K(ret)); + } else if (OB_FAIL(stmt->get_from_tables(from_tables))) { + LOG_WARN("failed to get from tables", K(ret)); + } else if (OB_FAIL(semi_infos.assign(stmt->get_semi_infos()))) { + LOG_WARN("failed to assign semi infos", K(ret)); + } else if (OB_FAIL(view_cond_exprs.assign(stmt->get_condition_exprs()))) { + LOG_WARN("failed to assign view cond exprs", K(ret)); + } else if (OB_FALSE_IT(stmt->get_condition_exprs().reset())) { + } else if (OB_FAIL(ObTransformUtils::replace_with_empty_view(ctx_, + stmt, + view_table, + from_tables, + &semi_infos))) { + LOG_WARN("failed to create empty view", K(ret)); + } else if (OB_FAIL(ObTransformUtils::create_inline_view(ctx_, + stmt, + view_table, + from_tables, + &view_cond_exprs, + &semi_infos, + &view_select_exprs, + &view_group_exprs))) { + LOG_WARN("failed to create inline view", K(ret)); + } else if (OB_FAIL(replace_aggr_func(stmt, view_table, distinct_aggr))) { + LOG_WARN("failed to replace aggregate functions", K(ret)); + } else { + trans_happened = true; + } + return ret; +} + +int ObTransformDistinctAggregate::classify_aggr_exprs(const ObIArray &aggr_exprs, + ObIArray &non_distinct_aggr, + ObIArray &distinct_aggr) +{ + int ret = OB_SUCCESS; + for (int64_t i = 0; OB_SUCC(ret) && i < aggr_exprs.count(); ++i) { + ObAggFunRawExpr *aggr_expr = aggr_exprs.at(i); + if (OB_ISNULL(aggr_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("aggr expr is null", K(ret), K(i)); + } else if (aggr_expr->is_param_distinct()) { + if (!distinct_aggr.empty() && + OB_FAIL(aggr_expr->get_real_param_exprs_for_update().assign(distinct_aggr.at(0)->get_real_param_exprs()))) { + LOG_WARN("failed to assign param exprs for distinct aggr", K(ret), KPC(aggr_expr)); + } else if (OB_FAIL(distinct_aggr.push_back(aggr_expr))) { + LOG_WARN("failed to push back distinct aggr", K(ret)); + } + } else { + if (OB_FAIL(non_distinct_aggr.push_back(aggr_expr))) { + LOG_WARN("failed to push back non distinct aggr", K(ret)); + } + } + } + return ret; +} + +/** + * @brief ObTransformDistinctAggregate::construct_view_select_exprs + * + * view select exprs = distinct columns + non distinct aggrs + */ +int ObTransformDistinctAggregate::construct_view_select_exprs(const ObIArray &non_distinct_aggr, + const ObIArray &distinct_aggr, + ObIArray &view_select_exprs) +{ + int ret = OB_SUCCESS; + if (OB_FAIL(ObOptimizerUtil::append_exprs_no_dup(view_select_exprs, + distinct_aggr.at(0)->get_real_param_exprs()))) { + LOG_WARN("failed to append distinct expr", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < non_distinct_aggr.count(); ++i) { + if (OB_FAIL(add_var_to_array_no_dup(view_select_exprs, static_cast(non_distinct_aggr.at(i))))) { + LOG_WARN("failed to add non distinct aggr expr", K(ret)); + } + } + return ret; +} + +/** + * @brief ObTransformDistinctAggregate::replace_aggr_func + * + * For non distinct aggr, wrap it with the final aggregate, + * For distinct aggr, remove distinct. + */ +int ObTransformDistinctAggregate::replace_aggr_func(ObSelectStmt *stmt, + TableItem *view_table, + const ObIArray &distinct_aggr) +{ + int ret = OB_SUCCESS; + ObSelectStmt *view_stmt = NULL; + ObSEArray view_exprs; + ObStmtExprReplacer replacer; + replacer.set_relation_scope(); + replacer.set_recursive(false); + if (OB_ISNULL(ctx_) || OB_ISNULL(ctx_->expr_factory_) + || OB_ISNULL(stmt) || OB_ISNULL(view_table) + || OB_UNLIKELY(!view_table->is_generated_table()) + || OB_ISNULL(view_stmt = view_table->ref_query_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(ctx_), K(stmt), K(view_table), K(view_stmt)); + } else if (OB_FAIL(view_stmt->get_select_exprs(view_exprs))) { + LOG_WARN("failed to get origin select exprs", K(ret)); + } else { + stmt->clear_aggr_item(); + } + // create replaced non distinct aggr + for (int64_t i = 0; OB_SUCC(ret) && i < view_exprs.count(); ++i) { + ObRawExpr *view_expr = view_exprs.at(i); + ObAggFunRawExpr *view_aggr_expr = NULL; + ObColumnRefRawExpr *column_expr = NULL; + ObAggFunRawExpr *new_aggr = NULL; + ObRawExpr *new_expr = NULL; + if (OB_ISNULL(view_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(i)); + } else if (!view_expr->is_aggr_expr()) { + // do nothing + } else if (OB_FALSE_IT(view_aggr_expr = static_cast(view_expr))) { + } else if (OB_ISNULL(column_expr = stmt->get_column_expr_by_id(view_table->table_id_, + OB_APP_MIN_COLUMN_ID + i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get column expr", K(ret), K(i), KPC(view_expr)); + } else if (OB_FAIL(ObOptimizerUtil::generate_pullup_aggr_expr(*ctx_->expr_factory_, + ctx_->session_info_, + view_aggr_expr->get_expr_type(), + column_expr, + new_aggr))) { + LOG_WARN("failed to build new aggregate funcion expr", K(ret)); + } else if (OB_FAIL(ObExpandAggregateUtils::add_aggr_item(stmt->get_aggr_items(), + new_aggr))) { + LOG_WARN("failed to add aggr item", K(ret), KPC(new_aggr)); + } else if (OB_FALSE_IT(new_expr = static_cast(new_aggr))) { + } else if (OB_FAIL(ObTransformUtils::add_cast_for_replace_if_need(*ctx_->expr_factory_, + view_expr, + new_expr, + ctx_->session_info_))) { + LOG_WARN("failed to add cast for new aggr expr", K(ret)); + } else if (OB_FAIL(replacer.add_replace_expr(column_expr, new_expr))) { + LOG_WARN("failed to add replace expr", K(ret)); + } + } + // create replaced distinct aggr + for (int64_t i = 0; OB_SUCC(ret) && i < distinct_aggr.count(); ++i) { + ObAggFunRawExpr *aggr = distinct_aggr.at(i); + ObAggFunRawExpr *new_aggr = NULL; + if (OB_ISNULL(aggr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(i)); + } else if (OB_FAIL(ctx_->expr_factory_->create_raw_expr(aggr->get_expr_type(), + new_aggr))) { + LOG_WARN("failed to create new aggr expr", K(ret)); + } else if (OB_ISNULL(new_aggr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("new aggr is null", K(ret)); + } else if (OB_FAIL(new_aggr->assign(*aggr))) { + LOG_WARN("failed to assign aggr expr", K(ret)); + } else if (OB_FALSE_IT(new_aggr->set_param_distinct(false))) { + } else if (OB_FAIL(ObExpandAggregateUtils::add_aggr_item(stmt->get_aggr_items(), + new_aggr))) { + LOG_WARN("failed to add aggr item", K(ret), KPC(new_aggr)); + } else if (OB_FAIL(replacer.add_replace_expr(aggr, new_aggr))) { + LOG_WARN("failed to add replace expr", K(ret)); + } + } + if (OB_SUCC(ret) && OB_FAIL(stmt->iterate_stmt_expr(replacer))) { + LOG_WARN("failed to iterate stmt expr", K(ret)); + } + return ret; +} \ No newline at end of file diff --git a/src/sql/rewrite/ob_transform_distinct_aggregate.h b/src/sql/rewrite/ob_transform_distinct_aggregate.h new file mode 100644 index 0000000000..097b8c7e02 --- /dev/null +++ b/src/sql/rewrite/ob_transform_distinct_aggregate.h @@ -0,0 +1,53 @@ +/** + * Copyright (c) 2024 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#ifndef _OB_TRANSFORM_DISTINCT_AGGREGATE_H +#define _OB_TRANSFORM_DISTINCT_AGGREGATE_H + +#include "sql/rewrite/ob_transform_rule.h" +#include "sql/resolver/dml/ob_select_stmt.h" + +namespace oceanbase +{ +namespace sql +{ + +class ObTransformDistinctAggregate : public ObTransformRule +{ +public: + explicit ObTransformDistinctAggregate(ObTransformerCtx *ctx) + : ObTransformRule(ctx, TransMethod::POST_ORDER, T_TRANSFORM_DISTINCT_AGG) {} + + virtual ~ObTransformDistinctAggregate() {} + + virtual int transform_one_stmt(common::ObIArray &parent_stmts, + ObDMLStmt *&stmt, + bool &trans_happened) override; +private: + int check_transform_validity(const ObDMLStmt *stmt, bool &is_valid); + int do_transform(ObSelectStmt *stmt, bool &trans_happened); + int classify_aggr_exprs(const ObIArray &aggr_exprs, + ObIArray &non_distinct_aggr, + ObIArray &distinct_aggr); + int construct_view_select_exprs(const ObIArray &non_distinct_aggr, + const ObIArray &distinct_aggr, + ObIArray &view_select_exprs); + int replace_aggr_func(ObSelectStmt *stmt, + TableItem *view_table, + const ObIArray &distinct_aggr); +private: + DISALLOW_COPY_AND_ASSIGN(ObTransformDistinctAggregate); +}; +} // namespace sql +} // namespace oceanbase + +#endif \ No newline at end of file diff --git a/src/sql/rewrite/ob_transform_groupby_pullup.cpp b/src/sql/rewrite/ob_transform_groupby_pullup.cpp index c59bb62fd3..49d853e94c 100644 --- a/src/sql/rewrite/ob_transform_groupby_pullup.cpp +++ b/src/sql/rewrite/ob_transform_groupby_pullup.cpp @@ -291,6 +291,7 @@ int ObTransformGroupByPullup::check_groupby_pullup_validity(ObDMLStmt *stmt, int ret = OB_SUCCESS; bool can_pullup = false; bool hint_valid = false; + bool is_valid_tables = false; if (OB_ISNULL(stmt) || OB_ISNULL(table)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("param has null", K(stmt), K(table), K(ret)); @@ -345,10 +346,11 @@ int ObTransformGroupByPullup::check_groupby_pullup_validity(ObDMLStmt *stmt, OPT_TRACE("view is not deterministic, can not transform"); } else if (OB_FALSE_IT(helper.need_merge_ = (NULL != myhint && myhint->enable_group_by_pull_up(ctx_->src_qb_name_)))) { - } else if (!helper.need_merge_ && stmt->get_table_size() > 1 && sub_stmt->get_table_size() > 1 && - stmt->get_table_size() + sub_stmt->get_table_size() - 1 > 10) { + } else if (!helper.need_merge_ && OB_FAIL(check_table_items(stmt, sub_stmt, is_valid_tables))) { + LOG_WARN("failed to check table items", K(ret)); + } else if (!helper.need_merge_ && !is_valid_tables) { // More than 10 tables may result in the inability to enumerate a valid join order. - OPT_TRACE("Too Many Table Items"); + OPT_TRACE("Too Many Table Items or more then one generated table"); } else if (OB_FAIL(valid_views.push_back(helper))) { LOG_WARN("failed to push back group stmt index", K(ret)); } else { @@ -662,6 +664,37 @@ int ObTransformGroupByPullup::find_null_propagate_column(ObRawExpr *condition, return ret; } +int ObTransformGroupByPullup::check_table_items(ObDMLStmt *stmt, + ObSelectStmt *child_stmt, + bool &is_valid) +{ + int ret = OB_SUCCESS; + is_valid = true; + if (OB_ISNULL(stmt) || OB_ISNULL(child_stmt) || OB_ISNULL(child_stmt->get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (stmt->get_table_size() > 1 && child_stmt->get_table_size() > 1 && + stmt->get_table_size() + child_stmt->get_table_size() - 1 > 10) { + is_valid = false; + } else if (stmt->get_query_ctx()->check_opt_compat_version( + COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, COMPAT_VERSION_4_3_5)) { + const TableItem *table = NULL; + int64_t non_basic_table_count = 0; + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < stmt->get_table_size(); ++i) { + if (OB_ISNULL(table = stmt->get_table_item(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table item is null", K(ret)); + } else if (!table->is_basic_table()) { + ++non_basic_table_count; + if (non_basic_table_count > 1) { + is_valid = false; + } + } + } + } + return ret; +} + /** * @brief ObTransformGroupByPullup::get_trans_view * get/create a select stmt for transformation @@ -1041,7 +1074,11 @@ int ObTransformGroupByPullup::need_transform(const common::ObIArrayhas_outline_data()) { - need_trans = !query_hint->global_hint_.disable_cost_based_transform(); + // TODO: sean.yyj make the priority of rule hint higher than cost based hint + if (OB_FAIL(ObTransformUtils::is_cost_based_trans_enable(ctx_, query_hint->global_hint_, + need_trans))) { + LOG_WARN("failed to check cost based transform enable", K(ret)); + } } else if (NULL == (trans_hint = query_hint->get_outline_trans_hint(ctx_->trans_list_loc_)) || !trans_hint->is_view_merge_hint() || !static_cast(trans_hint)->enable_group_by_pull_up(ctx_->src_qb_name_)) { @@ -1086,6 +1123,8 @@ int ObTransformGroupByPullup::check_original_plan_validity(ObLogicalOperator* ro double group_ndv = 1.0; double card = 1.0; bool has_stats = true; + bool is_inner_path = false; + const ObDMLStmt *parent_stmt = NULL; const ObSelectStmt *child_stmt = NULL; if (OB_ISNULL(root) || OB_ISNULL(ctx_) || @@ -1097,6 +1136,7 @@ int ObTransformGroupByPullup::check_original_plan_validity(ObLogicalOperator* ro } else if (OB_ISNULL(subplan) || parent_ops.empty()) { //do nothing } else if (OB_UNLIKELY(subplan->get_num_of_child() == 0) || + OB_ISNULL(parent_stmt = subplan->get_stmt()) || OB_ISNULL(subplan = subplan->get_child(ObLogicalOperator::first_child)) || OB_ISNULL(subplan->get_stmt()) || OB_UNLIKELY(!subplan->get_stmt()->is_select_stmt())) { @@ -1109,6 +1149,14 @@ int ObTransformGroupByPullup::check_original_plan_validity(ObLogicalOperator* ro } else if (!has_stats) { is_valid = false; OPT_TRACE("check original plan has statistics:", has_stats); + } else if (OB_FAIL(check_view_table_in_inner_path(parent_ops, *parent_stmt, + view_table_id, is_inner_path))) { + LOG_WARN("failed to check view table in inner path", K(ret)); + } else if (is_inner_path && + child_stmt->get_query_ctx()->check_opt_compat_version( + COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, COMPAT_VERSION_4_3_5)) { + is_valid = false; + OPT_TRACE("check original plan view table in inner path:", is_inner_path); } else if (OB_FAIL(extract_columns_in_join_conditions(parent_ops, view_table_id, column_exprs))) { @@ -1346,4 +1394,38 @@ int ObTransformGroupByPullup::check_all_table_has_statistics(ObLogicalOperator * } } return ret; +} + +int ObTransformGroupByPullup::check_view_table_in_inner_path( + ObIArray &parent_ops, + const ObDMLStmt &stmt, + uint64_t table_id, + bool &is_inner_path) +{ + int ret = OB_SUCCESS; + ObLogJoin *join_op = NULL; + is_inner_path = false; + for (int64_t i = 0; OB_SUCC(ret) && !is_inner_path && i < parent_ops.count(); ++i) { + if (OB_ISNULL(parent_ops.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (log_op_def::LOG_JOIN != parent_ops.at(i)->get_type()) { + // do nothing + } else if (OB_ISNULL(join_op = static_cast(parent_ops.at(i)))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("static cast failed", K(ret)); + } else if (NESTED_LOOP_JOIN == join_op->get_join_algo() && join_op->get_nl_params().count() > 0) { + ObLogicalOperator *right_table = join_op->get_right_table(); + ObSqlBitSet<> rel_ids; + if (OB_ISNULL(right_table)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(stmt.get_table_rel_ids(table_id, rel_ids))) { + LOG_WARN("failed to get table rel ids", K(ret)); + } else { + is_inner_path = right_table->get_table_set().is_superset(rel_ids); + } + } + } + return ret; } \ No newline at end of file diff --git a/src/sql/rewrite/ob_transform_groupby_pullup.h b/src/sql/rewrite/ob_transform_groupby_pullup.h index 350e603ff2..38df3019b4 100644 --- a/src/sql/rewrite/ob_transform_groupby_pullup.h +++ b/src/sql/rewrite/ob_transform_groupby_pullup.h @@ -126,6 +126,9 @@ private: ObIArray &columns, ObRawExpr *&null_propagate_column, bool &is_valid); + int check_table_items(ObDMLStmt *stmt, + ObSelectStmt *child_stmt, + bool &is_valid); int do_groupby_pull_up(ObSelectStmt *stmt, PullupHelper &helper, @@ -191,6 +194,10 @@ private: double &card); int check_all_table_has_statistics(ObLogicalOperator *op, bool &has_stats); + int check_view_table_in_inner_path(ObIArray &parent_ops, + const ObDMLStmt &stmt, + uint64_t table_id, + bool &is_inner_path); private: // help functions diff --git a/src/sql/rewrite/ob_transform_groupby_pushdown.cpp b/src/sql/rewrite/ob_transform_groupby_pushdown.cpp index 89e8ad3c24..32aeb99b37 100644 --- a/src/sql/rewrite/ob_transform_groupby_pushdown.cpp +++ b/src/sql/rewrite/ob_transform_groupby_pushdown.cpp @@ -44,10 +44,30 @@ using namespace oceanbase::common; * where v1.c1 = v2.c1 group by v1.c2; * */ -int ObTransformGroupByPushdown::transform_one_stmt(common::ObIArray &parent_stmts, - ObDMLStmt *&stmt, - bool &trans_happened) -{ +int ObTransformGroupByPushdown::transform_one_stmt( + common::ObIArray &parent_stmts, + ObDMLStmt *&stmt, + bool &trans_happened) { + int ret = OB_SUCCESS; + bool trans_pushdown_happened = false; + bool trans_pushdown_to_union_happened = false; + if (OB_FAIL(try_push_down_groupby_into_join(parent_stmts, stmt, + trans_pushdown_happened))) { + LOG_WARN("failed to transform one stmt groupby pushdown"); + } else if (trans_pushdown_happened) { + // do nothing + } else if (OB_FAIL(try_push_down_groupby_into_union( + parent_stmts, stmt, trans_pushdown_to_union_happened))) { + LOG_WARN("failed to transform one stmt groupby pushdown to union"); + } + trans_happened = trans_pushdown_happened | trans_pushdown_to_union_happened; + return ret; +} + +int ObTransformGroupByPushdown::try_push_down_groupby_into_join( + common::ObIArray &parent_stmts, + ObDMLStmt *&stmt, + bool &trans_happened) { int ret = OB_SUCCESS; trans_happened = false; ObSEArray params; @@ -66,7 +86,7 @@ int ObTransformGroupByPushdown::transform_one_stmt(common::ObIArrayis_select_stmt()) { // do nothing - } else if (OB_FAIL(check_groupby_push_down_validity( + } else if (OB_FAIL(check_push_down_into_join_validity( static_cast(stmt), is_valid))) { LOG_WARN("failed to check group by push down validity", K(ret)); } else if (!is_valid) { @@ -80,12 +100,12 @@ int ObTransformGroupByPushdown::transform_one_stmt(common::ObIArrayget_query_ctx()))) { LOG_WARN("failed to fill try trans helper", K(ret)); - } else if (OB_FAIL(do_groupby_push_down(static_cast(stmt), - params, - flattern_joined_tables, - trans_stmt, - push_down_ctx, - is_happened))) { + } else if (OB_FAIL(do_groupby_push_down_into_join(static_cast(stmt), + params, + flattern_joined_tables, + trans_stmt, + push_down_ctx, + is_happened))) { LOG_WARN("failed to transform stmt", K(ret)); } else if (!is_happened) { LOG_TRACE("is happened"); @@ -112,6 +132,939 @@ int ObTransformGroupByPushdown::transform_one_stmt(common::ObIArray &parent_stmts, + ObDMLStmt *&stmt, + bool &trans_happened) { + int ret = OB_SUCCESS; + bool is_valid = true; + ObSelectStmt *select_stmt = NULL; + ObSEArray, 4> trans_tables; + ObSEArray trans_table; + TableItem *single_trans_table = NULL; + ObSEArray param; + const ObGroupByPlacementHint *myhint = + static_cast( + stmt->get_stmt_hint().get_normal_hint(T_PLACE_GROUP_BY)); + ObTryTransHelper try_trans_helper; + ObSelectStmt *trans_stmt = NULL; + bool is_happened = false; + trans_happened = false; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (!stmt->is_select_stmt()) { + // do nothing + } else if ((OB_NOT_NULL(myhint) && myhint->is_disable_hint())) { + LOG_TRACE("hint disable"); + } else if (FALSE_IT(select_stmt = static_cast(stmt))) { + } else if (OB_FAIL(check_push_down_into_union_validity(select_stmt, is_valid))) { + LOG_WARN("failed to check group by push down to union validity", K(ret)); + } else if (!is_valid) { + LOG_TRACE("push down to union is not valid"); + } else if (OB_FAIL(try_trans_helper.fill_helper(stmt->get_query_ctx()))) { + LOG_WARN("failed to fill try trans helper", K(ret)); + } else if (OB_FAIL(get_union_pushdown_param(*select_stmt, param))) { + LOG_WARN("failed to get union param", K(ret)); + } else if (OB_FAIL(do_groupby_push_down_into_union(select_stmt, param, trans_stmt, is_happened))) { + LOG_WARN("failed to do groupby push down to union"); + } else if (!is_happened) { + LOG_TRACE("transformer not happened"); + } else if (OB_ISNULL(single_trans_table = select_stmt->get_table_item(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(trans_table.push_back(single_trans_table)) || + OB_FAIL(trans_tables.push_back(trans_table))) { + LOG_WARN("failed to push back", K(ret)); + } else { + if (trans_stmt == stmt) { + trans_happened = true; + } else if (OB_FAIL(accept_transform(parent_stmts, stmt, trans_stmt, + NULL != myhint && myhint->is_enable_hint(), + false, trans_happened, NULL /*TODO*/ ))) { + LOG_WARN("failed to accept transform", K(ret)); + } + } + if (OB_FAIL(ret) || !trans_happened) { + // do nothing + } else if (OB_FAIL(add_transform_hint(*stmt, &trans_tables))) { + LOG_WARN("failed to add transform hint", K(ret)); + } + + if (OB_SUCC(ret) && !trans_happened && try_trans_helper.is_filled() + && OB_FAIL(try_trans_helper.recover(stmt->get_query_ctx()))) { + LOG_WARN("failed to recover params", K(ret)); + } + return ret; +} + +int ObTransformGroupByPushdown::check_push_down_into_union_validity( + ObSelectStmt *stmt, + bool &is_valid) { + // TODO Perhaps a more careful check is needed + int ret = OB_SUCCESS; + bool has_rownum = false; + bool is_deterministic = false; + bool only_min_max = true; + ObSelectStmt *union_stmt = NULL; + ObSEArray child_stmts; + is_valid = true; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("stmt is null", K(ret), K(stmt)); + } else if (stmt->has_rollup() || + stmt->get_aggr_item_size() <= 0 || + stmt->is_hierarchical_query()) { + is_valid = false; + LOG_TRACE("invalid stmt for eager aggregation", K(is_valid)); + OPT_TRACE("invalid stmt for eager aggregation"); + } else if (OB_FAIL(stmt->has_rownum(has_rownum))) { + LOG_WARN("failed to check stmt has rownum", K(ret)); + } else if (has_rownum) { + is_valid = false; + OPT_TRACE("stmt contain rownum, can not transform"); + } else if (OB_FAIL(stmt->is_query_deterministic(is_deterministic))) { + LOG_WARN("failed to check stmt has rand", K(ret)); + } else if (!is_deterministic) { + is_valid = false; + OPT_TRACE("stmt has rand expr, can not transform"); + } else if (0 != stmt->get_condition_size()) { + is_valid = false; + OPT_TRACE("stmt has condition, can not transform"); + } else if (OB_FAIL(check_groupby_validity(*stmt, is_valid))) { + LOG_WARN("failed to check group by validity", K(ret)); + } else if (!is_valid) { + // do nothing + OPT_TRACE("not a valid group stmt, can not transform"); + } else if (OB_FAIL(check_collation_validity(*stmt, is_valid))) { + LOG_WARN("failed to check collation validity", K(ret)); + } else if (!is_valid) { + // do nothing + } else if (OB_FAIL(check_union_stmt_valid(*stmt, union_stmt, is_valid))) { + LOG_WARN("failed to check union stmt validity", K(ret)); + } else if (!is_valid) { + // do nothing + OPT_TRACE("union stmt not valid, can not transform"); + } else if (OB_FAIL(check_aggr_exprs_valid(*stmt, is_valid, only_min_max))) { + LOG_WARN("failed to check aggr exprs validity", K(ret)); + } else if (!is_valid) { + // do nothing + } else if (union_stmt->is_set_distinct() && !only_min_max) { + OPT_TRACE("child stmt is union distinct but there is sum or count " + "function, can not transform"); + is_valid = false; + } else if (OB_FAIL(check_child_stmts_valid(*union_stmt, child_stmts, is_valid))) { + LOG_WARN("failed to check child stmts validity", K(ret)); + } else { /* do nothing */ } + return ret; +} + +int ObTransformGroupByPushdown::check_union_stmt_valid(ObSelectStmt &stmt, + ObSelectStmt *&union_stmt, + bool &is_valid) { + int ret = OB_SUCCESS; + ObSEArray select_exprs; + TableItem *sub_query_table_item = NULL; + is_valid = true; + if (1 != stmt.get_from_item_size()) { + is_valid = false; + OPT_TRACE("stmt is not single from stmt, can not transform"); + } else if (1 != stmt.get_table_items().count()) { + is_valid = false; + OPT_TRACE("stmt is not single table stmt, can not transform"); + } else if (OB_ISNULL(sub_query_table_item = + stmt.get_table_item(stmt.get_from_item(0)))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (!sub_query_table_item->is_generated_table()) { + is_valid = false; + OPT_TRACE("stmt is not from a sub query, can not transform"); + } else if (OB_ISNULL(union_stmt = sub_query_table_item->ref_query_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (ObSelectStmt::UNION != union_stmt->get_set_op()) { + is_valid = false; + OPT_TRACE("child stmt type is not union, can not transform"); + } else if (union_stmt->has_recursive_cte()) { + is_valid = false; + OPT_TRACE("union stmt type is recursive cte, can not transform"); + } else if (union_stmt->has_limit() || union_stmt->has_order_by()) { + is_valid = false; + OPT_TRACE("union stmt has limit or orderby, can not transform"); + } else if (OB_FAIL(union_stmt->get_select_exprs(select_exprs))) { + LOG_WARN("failed to get select exprs", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < select_exprs.count(); ++i) { + ObRawExpr *expr = NULL; + if (OB_ISNULL(expr = select_exprs.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (!expr->is_set_op_expr()) { + is_valid = false; + } + } + return ret; +} + +int ObTransformGroupByPushdown::check_aggr_exprs_valid(ObSelectStmt &stmt, + bool &is_valid, + bool &only_min_max) { + int ret = OB_SUCCESS; + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < stmt.get_aggr_item_size(); ++i) { + ObAggFunRawExpr *aggr_expr = NULL; + ObRawExpr *child_expr = NULL; + if (OB_ISNULL(aggr_expr = stmt.get_aggr_item(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("params are invalid", K(ret), K(aggr_expr)); + } else if ((aggr_expr->get_expr_type() != T_FUN_SUM && + aggr_expr->get_expr_type() != T_FUN_COUNT && + aggr_expr->get_expr_type() != T_FUN_MIN && + aggr_expr->get_expr_type() != T_FUN_MAX) || + aggr_expr->is_param_distinct()) { + is_valid = false; + OPT_TRACE("invalid aggregation type for group by placement", aggr_expr); + LOG_TRACE("invalid aggregation type for group by placement", K(is_valid), + K(aggr_expr->get_expr_type()), K(aggr_expr->is_param_distinct())); + } else { + if (1 == aggr_expr->get_param_count()) { + if (OB_ISNULL(child_expr = aggr_expr->get_param_expr(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (!child_expr->is_column_ref_expr()) { + is_valid = false; + OPT_TRACE("exist invalid aggregation expr, do not transform"); + } else if (T_FUN_MIN != aggr_expr->get_expr_type() && + T_FUN_MAX != aggr_expr->get_expr_type()) { + only_min_max = false; + } + } else if (0 == aggr_expr->get_param_count() && + T_FUN_COUNT == aggr_expr->get_expr_type()) { + only_min_max = false; + } else { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid param of aggr func", K(ret), K(aggr_expr)); + } + } + } + return ret; +} + +int ObTransformGroupByPushdown::check_child_stmts_valid( + ObSelectStmt &union_stmt, + ObIArray &child_stmts, + bool &is_valid) { + int ret = OB_SUCCESS; + bool is_basic = false; + bool exist_basic_select = false; + if (OB_FAIL(union_stmt.get_child_stmts(child_stmts))) { + LOG_WARN("failed to get the child stmt of union stmt", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < child_stmts.count(); ++i) { + ObSelectStmt *child_stmt = NULL; + if (OB_ISNULL(child_stmt = child_stmts.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (child_stmt->is_set_stmt() || child_stmt->has_distinct() || + child_stmt->is_hierarchical_query()) { + is_valid = false; + } else if (OB_FAIL(is_basic_select_stmt(child_stmt, is_basic))) { + LOG_WARN("failed to check the child stmt of union stmt", K(ret)); + } else { + exist_basic_select |= is_basic; + } + } + if (OB_SUCC(ret) && is_valid && !exist_basic_select) { + LOG_TRACE("there is no basic select stmt, can not transform"); + OPT_TRACE("there is no basic select stmt, can not transform") + is_valid = false; + } + return ret; +} + +int ObTransformGroupByPushdown::is_basic_select_stmt(ObSelectStmt *stmt, bool &is_basic) { + // TODO may need more check + int ret = OB_SUCCESS; + ObSEArray select_exprs; + is_basic = true; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (stmt->has_limit() || stmt->has_group_by() || stmt->has_order_by() || + stmt->has_window_function() || stmt->has_distinct() || stmt->has_rollup() || + stmt->is_set_stmt() || stmt->is_hierarchical_query()) { + is_basic = false; + } else if (0 != stmt->get_aggr_item_size()) { + is_basic = false; + } else { /* do nothing */ } + return ret; +} + +int ObTransformGroupByPushdown::get_union_stmt(ObSelectStmt *parent_stmt, + ObSelectStmt *&union_stmt, + bool &got) { + int ret = OB_SUCCESS; + if (OB_ISNULL(parent_stmt)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument: parent stmt is null", K(ret)); + } else { + union_stmt = NULL; + TableItem *sub_query_table_item = NULL; + if (1 != parent_stmt->get_from_item_size() || + 1 != parent_stmt->get_table_items().count() || + OB_ISNULL(sub_query_table_item = parent_stmt->get_table_item( + parent_stmt->get_from_item(0))) || + !sub_query_table_item->is_generated_table() || + OB_ISNULL(union_stmt = sub_query_table_item->ref_query_) || + ObSelectStmt::UNION != union_stmt->get_set_op()) { + got = false; + } else { + got = true; + } + } + return ret; +} + +int ObTransformGroupByPushdown::get_union_pushdown_param( + ObSelectStmt &stmt, + ObIArray ¶m) { + int ret = OB_SUCCESS; + ObIArray &agg_exprs = stmt.get_aggr_items(); + ObSEArray group_cols; + ObColumnRefRawExpr *col_ref_expr = NULL; + ObSelectStmt *union_stmt = NULL; + bool got_union_stmt = false; + param.reset(); + if (OB_FAIL(get_union_stmt(&stmt, union_stmt, got_union_stmt))) { + LOG_WARN("failed to get union stmt"); + } else if (!got_union_stmt || OB_ISNULL(union_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("failed to get union stmt", K(ret)); + } + // extract from aggr + for (int64_t i = 0; OB_SUCC(ret) && i < agg_exprs.count(); ++i) { + ObAggFunRawExpr *agg_expr = NULL; + ObRawExpr *child_expr = NULL; + if (OB_ISNULL(agg_expr = agg_exprs.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("agg_expr is null", K(ret)); + } else if (0 == agg_expr->get_param_count() && + T_FUN_COUNT == agg_expr->get_expr_type()) { + if (OB_FAIL(param.push_back((UnionPushdownParam){ + OB_INVALID_ID, // col_id_ + agg_expr->get_expr_type(), // aggr_func_type_ + }))) { + LOG_WARN("failed to push back", K(ret)); + } + } else if (OB_UNLIKELY(1 != agg_expr->get_param_count()) || + OB_ISNULL(child_expr = agg_expr->get_param_expr(0)) || + OB_UNLIKELY(!child_expr->is_column_ref_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid agg_expr", K(ret)); + } else { + // ref to union stmt + uint64_t child_col_id = 0; + col_ref_expr = static_cast(child_expr); + if (OB_FAIL(get_col_id_of_child(*union_stmt, col_ref_expr->get_column_id(), + child_col_id))) { + LOG_WARN("failed to get col id of child", K(ret)); + } else if (OB_FAIL(param.push_back((UnionPushdownParam){ + child_col_id, // col_id_ + agg_expr->get_expr_type(), // aggr_func_type_ + }))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + // extract from group by expr + if (OB_SUCC(ret) && OB_FAIL(ObRawExprUtils::extract_column_exprs( + stmt.get_group_exprs(), group_cols))) { + LOG_WARN("failed to extract column from group expr", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < group_cols.count(); ++i) { + ObRawExpr *expr = NULL; + if (OB_ISNULL(expr = group_cols.at(i)) || + OB_UNLIKELY(!expr->is_column_ref_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected expr", K(ret), K(expr)); + } else { + col_ref_expr = static_cast(expr); + uint64_t child_col_id = 0; + if (OB_FAIL(get_col_id_of_child(*union_stmt, col_ref_expr->get_column_id(), + child_col_id))) { + LOG_WARN("failed to get col id of child", K(ret)); + } else if (OB_FAIL(param.push_back((UnionPushdownParam){ + child_col_id, // col_id_ + T_NULL, // aggr_func_type_ + }))) { + LOG_WARN("failed to push back to param", K(ret)); + } + } + } + return ret; +} + +int ObTransformGroupByPushdown::get_col_id_of_child(ObSelectStmt &union_stmt, + uint64_t union_col_id, + uint64_t &child_col_id) { + int ret = OB_SUCCESS; + ObSEArray select_exprs; + ObRawExpr *expr = NULL; + int64_t idx = union_col_id - OB_APP_MIN_COLUMN_ID; + if (idx < 0 || idx >= union_stmt.get_select_item_size()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid union col id", K(ret)); + } else if (OB_ISNULL(expr = union_stmt.get_select_item(idx).expr_) || + OB_UNLIKELY(!expr->is_set_op_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid select expr of union stmt", K(ret), K(expr)); + } else { + child_col_id = OB_APP_MIN_COLUMN_ID + static_cast(expr)->get_idx(); + } + return ret; +} + +int ObTransformGroupByPushdown::do_groupby_push_down_into_union( + ObSelectStmt *origin_stmt, + ObIArray ¶m, + ObSelectStmt *&trans_stmt, + bool &trans_happened) { + int ret = OB_SUCCESS; + bool is_basic = false; + bool got_union_stmt = false; + ObSelectStmt *union_stmt = NULL; + ObSEArray child_stmts; + const ObGroupByPlacementHint *myhint = + static_cast( + origin_stmt->get_stmt_hint().get_normal_hint(T_PLACE_GROUP_BY)); + if (OB_ISNULL(origin_stmt) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->expr_factory_) || + OB_ISNULL(ctx_->session_info_) || OB_ISNULL(ctx_->stmt_factory_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } + + if (OB_SUCC(ret)) { + // for scalar group by or enable_hint, we don't need to do cost verification + if (0 == origin_stmt->get_group_expr_size() || + (NULL != myhint && myhint->is_enable_hint())) { + trans_stmt = origin_stmt; + } else { + if (OB_FAIL(ctx_->stmt_factory_->create_stmt(trans_stmt))) { + LOG_WARN("failed to create stmt", K(ret)); + } else if (OB_FAIL(trans_stmt->deep_copy(*ctx_->stmt_factory_, + *ctx_->expr_factory_, + *origin_stmt))) { + LOG_WARN("failed to deep copy stmt", K(ret)); + } + } + } + // get union stmt and child stmts + if (OB_FAIL(ret)) { + } else if (OB_FAIL(get_union_stmt(trans_stmt, union_stmt, got_union_stmt))) { + LOG_WARN("failed to get union stmt"); + } else if (!got_union_stmt || OB_ISNULL(union_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid union stmt", K(ret)); + } else if (OB_FAIL(union_stmt->get_child_stmts(child_stmts))) { + LOG_WARN("failed to get child stmts of union"); + } + + // transform child stmts of union + for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) { + ObSelectStmt *child_stmt = child_stmts.at(i); + if (OB_ISNULL(child_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("child stmt of stmt is null", K(ret)); + } else if (OB_FAIL(is_basic_select_stmt(child_stmt, is_basic))) { + LOG_WARN("failed to check if child stmt is basic select stmt", K(ret)); + } else { + if (is_basic) { + // pushdown group by + if (OB_FAIL(transform_basic_child_stmt(child_stmt, param))) { + LOG_WARN("failed to transform basic child stmt of union", K(ret)); + } + } else { + // only change projection + if (OB_FAIL(transform_non_basic_child_stmt(child_stmt, param))) { + LOG_WARN("failed to transform non-basic child stmt of union", K(ret)); + } + } + } + } + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(transform_union_stmt(union_stmt, child_stmts))) { + LOG_WARN("failed to transform union stmt", K(ret)); + } else if (OB_FAIL(transform_parent_stmt_of_union(trans_stmt, union_stmt, param))) { + LOG_WARN("failed to transform parent stmt of union", K(ret)); + } else { + trans_happened = true; + } + return ret; +} + +int ObTransformGroupByPushdown::transform_basic_child_stmt( + ObSelectStmt *stmt, + ObIArray ¶ms) { + int ret = OB_SUCCESS; + ObSEArray exprs; + ObSEArray old_select_items; + ObRawExpr *new_expr = NULL; + // SelectItem select_item; + if (OB_ISNULL(stmt) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->session_info_) || + OB_ISNULL(ctx_->allocator_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid argument", K(ret), K(stmt), K(ctx_)); + } else if (OB_FAIL(stmt->get_select_exprs(exprs))) { + LOG_WARN("failed to get select exprs", K(ret)); + } else if (OB_FAIL(old_select_items.assign(stmt->get_select_items()))) { + LOG_WARN("failed to assign select items", K(ret)); + } else { + stmt->clear_select_item(); + } + + for (int64_t i = 0; OB_SUCC(ret) && i < params.count(); ++i) { + UnionPushdownParam ¶m = params.at(i); + if (OB_FAIL(get_new_select_expr_of_basic_child(param, exprs, new_expr))) { + LOG_WARN("failed to get new expr", K(ret)); + } else if (OB_FAIL(ObTransformUtils::create_select_item(*ctx_->allocator_, + new_expr, stmt))) { + LOG_WARN("failed to create select item", K(ret)); + } + if (OB_FAIL(ret)) { + // do nothing + } else if (new_expr->is_aggr_expr()) { + ObAggFunRawExpr *agg_expr = static_cast(new_expr); + if (OB_FAIL(stmt->add_agg_item(*agg_expr))) { + LOG_WARN("failed to add agg item", K(ret)); + } + } else if (OB_FAIL(stmt->add_group_expr(new_expr))) { + LOG_WARN("failed to add group expr"); + } else { + /* do nothing */ + } + } + if (OB_SUCC(ret) && OB_FAIL(stmt->formalize_stmt(ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt info", K(ret)); + } + return ret; +} + +int ObTransformGroupByPushdown::transform_non_basic_child_stmt( + ObSelectStmt *stmt, + ObIArray ¶ms) { + int ret = OB_SUCCESS; + ObSEArray old_exprs; + ObSEArray old_select_items; + ObRawExpr *new_expr = NULL; + if (OB_ISNULL(stmt) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->session_info_) || + OB_ISNULL(ctx_->allocator_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(stmt->get_select_exprs(old_exprs))) { + LOG_WARN("failed to get select exprs", K(ret)); + } else if (OB_FAIL(old_select_items.assign(stmt->get_select_items()))) { + LOG_WARN("failed to assign select items", K(ret)); + } else { + stmt->clear_select_item(); + } + for (int64_t i = 0; OB_SUCC(ret) && i < params.count(); ++i) { + UnionPushdownParam ¶m = params.at(i); + if (OB_UNLIKELY(param.col_id_ != OB_INVALID_ID && + param.col_id_ >= OB_APP_MIN_COLUMN_ID + old_exprs.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected col_id", K(ret), K(param), K(old_exprs)); + } else if (OB_FAIL(get_new_select_expr_of_non_basic_child(param, old_exprs, + new_expr))) { + LOG_WARN("failed to get new select item", K(ret)); + } else if (OB_ISNULL(new_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("new_expr is null", K(ret)); + } else if (OB_FAIL(ObTransformUtils::create_select_item(*ctx_->allocator_, + new_expr, stmt))) { + LOG_WARN("failed to create select item", K(ret)); + } + } + if (OB_SUCC(ret) && OB_FAIL(stmt->formalize_stmt(ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt info", K(ret)); + } + return ret; +} + +int ObTransformGroupByPushdown::transform_union_stmt( + ObSelectStmt *union_stmt, + ObIArray &child_stmts) { + int ret = OB_SUCCESS; + ObSEArray left_childs; + ObSEArray right_childs; + ObSEArray res_type; + // check ctx + if (OB_ISNULL(union_stmt) || OB_UNLIKELY(child_stmts.count() < 2) || + OB_ISNULL(ctx_) || OB_ISNULL(ctx_->allocator_) || + OB_ISNULL(ctx_->session_info_) || OB_ISNULL(ctx_->expr_factory_)) { + LOG_WARN("invalid argument", K(union_stmt), K(child_stmts)); + } else if (OB_FAIL(left_childs.push_back(child_stmts.at(0)))) { + LOG_WARN("failed to push back", K(ret)); + } + for (int64_t i = 1; OB_SUCC(ret) && i < child_stmts.count(); ++i) { + if (OB_FAIL(right_childs.push_back(child_stmts.at(i)))) { + LOG_WARN("failed to push back", K(ret)); + } + } + if (OB_FAIL(ret)) { + // do nothing + } else if (OB_FAIL(ObOptimizerUtil::gen_set_target_list(ctx_->allocator_, + ctx_->session_info_, + ctx_->expr_factory_, + left_childs, right_childs, + union_stmt))) { + // TODO tuliwei.tlw + // Here's the issue: If a view is created to represent this UNION statement + // and triggers a rewrite, the name of this UNION statement would vanish, + // meaning during an EXPLAIN, the name of the view would not be displayed. + LOG_WARN("failed to get set target list", K(ret)); + } else if (OB_FAIL(union_stmt->formalize_stmt(ctx_->session_info_))) { + LOG_WARN("failed to formalize union_stmt info", K(ret)); + } + return ret; +} + +int ObTransformGroupByPushdown::transform_parent_stmt_of_union( + ObSelectStmt *stmt, + ObSelectStmt *union_stmt, + ObIArray ¶m) { + int ret = OB_SUCCESS; + TableItem *table_item = NULL; + ObSEArray new_column_exprs; + ObSEArray old_aggr_exprs; + ObSEArray new_aggr_exprs; + ObSEArray aggr_col_exprs; + ObSEArray new_aggr_col_exprs; + if (OB_ISNULL(stmt) || OB_ISNULL(union_stmt) || OB_ISNULL(ctx_) || + OB_ISNULL(ctx_->expr_factory_) || OB_ISNULL(ctx_->session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_UNLIKELY(1 != stmt->get_from_item_size()) || + OB_ISNULL(table_item = stmt->get_table_item(stmt->get_from_item(0))) || + OB_UNLIKELY(!table_item->is_generated_table()) || + OB_UNLIKELY(table_item->ref_query_ != union_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid argument", K(ret), K(stmt->get_from_items()), K(table_item)); + } else if (FALSE_IT(stmt->clear_column_items())) { + } else if (OB_FAIL(ObTransformUtils::create_columns_for_view( + ctx_, *table_item, stmt, new_column_exprs))) { + LOG_WARN("failed to create columns for view", K(ret)); + } else if (OB_UNLIKELY(new_column_exprs.count() != param.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected count of new column expr", K(ret)); + } else if (OB_FAIL(get_new_aggr_exprs(param, new_column_exprs, + stmt->get_aggr_items(), + new_aggr_exprs))) { + LOG_WARN("failed to get new aggr exprs"); + } else if (OB_FAIL(ObRawExprUtils::extract_column_exprs( + stmt->get_group_exprs(), aggr_col_exprs))) { + LOG_WARN("failed to extract column exprs from group exprs", K(ret)); + } else if (OB_FAIL(get_new_aggr_col_exprs(aggr_col_exprs, param, + new_column_exprs, + new_aggr_col_exprs))) { + LOG_WARN("failed to get new aggr column exprs", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_aggr_item_size(); ++i) { + if (OB_FAIL(old_aggr_exprs.push_back(stmt->get_aggr_item(i)))) { + LOG_WARN("failed to push back", K(ret)); + } + } + if (OB_SUCC(ret) && OB_FAIL(replace_aggr_and_aggr_col_exprs( + stmt, old_aggr_exprs, new_aggr_exprs, aggr_col_exprs, + new_aggr_col_exprs))) { + LOG_WARN("failed to replace aggr and column exprs", K(ret)); + } + return ret; +} + +int ObTransformGroupByPushdown::get_new_select_expr_of_basic_child( + UnionPushdownParam ¶m, + ObIArray &old_exprs, + ObRawExpr *&new_expr) { + int ret = OB_SUCCESS; + ObRawExpr *child_expr = NULL; + if (OB_ISNULL(ctx_) || OB_ISNULL(ctx_->expr_factory_) || + OB_ISNULL(ctx_->session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_INVALID_ID == param.col_id_ /* count(*) */) { + ObAggFunRawExpr *count_expr = NULL; + if (T_FUN_COUNT != param.aggr_func_type_) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid aggr_func_type", K(param.aggr_func_type_)); + } else if (OB_FAIL(ObRawExprUtils::build_dummy_count_expr( + *ctx_->expr_factory_, ctx_->session_info_, count_expr))) { + LOG_WARN("failed to create new aggregation expr", K(ret)); + } else if (OB_ISNULL(count_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("null count expr", K(ret)); + } else { + new_expr = count_expr; + } + } else { + int64_t idx = param.col_id_ - OB_APP_MIN_COLUMN_ID; + ObAggFunRawExpr *agg_expr = NULL; + if (OB_ISNULL(child_expr = old_exprs.at(idx))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("child expr is null", K(ret)); + } else if (T_NULL == param.aggr_func_type_) { + new_expr = child_expr; + } else if (OB_FAIL(create_aggr_expr(ctx_, param.aggr_func_type_, + agg_expr, child_expr))) { + LOG_WARN("failed to build aggr expr", K(ret)); + } else if (OB_ISNULL(agg_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("agg expr is null", K(ret)); + } else { + new_expr = agg_expr; + } + } + return ret; +} + +int ObTransformGroupByPushdown::get_new_select_expr_of_non_basic_child( + UnionPushdownParam ¶m, + ObIArray &old_exprs, + ObRawExpr *&new_expr) { + int ret = OB_SUCCESS; + ObRawExpr *child_expr = NULL; + if (OB_ISNULL(ctx_) || OB_ISNULL(ctx_->expr_factory_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_INVALID_ID == param.col_id_ /* count(*) */) { + if (T_FUN_COUNT != param.aggr_func_type_) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid new column desc", K(param)); + } else { + ObConstRawExpr *const_expr = NULL; + ObRawExprUtils::build_const_int_expr(*ctx_->expr_factory_, ObIntType, 1, const_expr); + new_expr = static_cast(const_expr); + } + } else { + int64_t idx = param.col_id_ - OB_APP_MIN_COLUMN_ID; + if (OB_ISNULL(child_expr = old_exprs.at(idx))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("child expr is null", K(ret)); + } else if (param.aggr_func_type_ == T_NULL || + param.aggr_func_type_ == T_FUN_SUM || + param.aggr_func_type_ == T_FUN_MIN || + param.aggr_func_type_ == T_FUN_MAX) { + new_expr = child_expr; + } else if (param.aggr_func_type_ == T_FUN_COUNT) { + ObConstRawExpr *zero_expr = NULL; + ObConstRawExpr *one_expr = NULL; + ObRawExpr *is_not_null_expr = NULL; + if (OB_FAIL(ObRawExprUtils::build_const_int_expr( + *ctx_->expr_factory_, ObIntType, 0, zero_expr)) || + OB_ISNULL(zero_expr) || + OB_FAIL(ObRawExprUtils::build_const_int_expr( + *ctx_->expr_factory_, ObIntType, 1, one_expr)) || + OB_ISNULL(one_expr) || + OB_FAIL(ObRawExprUtils::build_is_not_null_expr( + *ctx_->expr_factory_, child_expr, true, is_not_null_expr)) || + OB_ISNULL(is_not_null_expr) || + OB_FAIL(ObRawExprUtils::build_case_when_expr( + *ctx_->expr_factory_, is_not_null_expr, one_expr, zero_expr, + new_expr))) { + if (OB_SUCC(ret)) { + // unexpected null + ret = OB_ERR_UNEXPECTED; + } + LOG_WARN("failed to build expr", K(ret)); + } + } else { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected aggr_func_type:", K(ret), K(param.aggr_func_type_)); + } + } + return ret; +} + +int ObTransformGroupByPushdown::get_new_aggr_exprs( + ObIArray ¶m, + ObIArray &new_column_exprs, + ObIArray &aggr_exprs, + ObIArray &new_aggr_exprs) { + int ret = OB_SUCCESS; + new_aggr_exprs.reset(); + for (int64_t i = 0; OB_SUCC(ret) && i < aggr_exprs.count(); ++i) { + ObAggFunRawExpr *aggr_expr = NULL; + ObAggFunRawExpr *new_aggr_expr = NULL; + if (OB_ISNULL(aggr_expr = aggr_exprs.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(get_new_aggr_expr(param, new_column_exprs, + aggr_expr, new_aggr_expr))) { + LOG_WARN("failed to get new aggr expr"); + } else if (OB_ISNULL(new_aggr_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(new_aggr_exprs.push_back(new_aggr_expr))) { + LOG_WARN("failed to push back", K(ret)); + } + } + return ret; +} + +int ObTransformGroupByPushdown::get_new_aggr_expr( + ObIArray ¶m, + ObIArray &new_column_exprs, + ObAggFunRawExpr *aggr_expr, + ObAggFunRawExpr *&new_aggr_expr) { + int ret = OB_SUCCESS; + ObItemType aggr_type = aggr_expr->get_expr_type(); + ObItemType new_aggr_type = + (T_FUN_COUNT == aggr_type) ? T_FUN_COUNT_SUM : aggr_type; + ObRawExpr *child_expr = NULL; + ObColumnRefRawExpr *new_column_expr = NULL; + uint64_t col_id = 0; + int64_t idx = 0; + if (OB_ISNULL(ctx_) || OB_ISNULL(ctx_->expr_factory_) || + OB_ISNULL(ctx_->session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (0 == aggr_expr->get_param_count()) { + if (T_FUN_COUNT != aggr_type) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid aggr param", K(ret)); + } else { + col_id = OB_INVALID_ID; + } + } else { + if (OB_UNLIKELY(1 != aggr_expr->get_param_count()) || + OB_ISNULL(child_expr = aggr_expr->get_param_expr(0)) || + OB_UNLIKELY(!child_expr->is_column_ref_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid aggr expr", K(ret), K(child_expr)); + } else { + col_id = static_cast(child_expr)->get_column_id(); + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(find_new_column_expr(param, new_column_exprs, aggr_type, + col_id, new_column_expr))) { + LOG_WARN("failed to find new column expr", K(ret)); + } else if (OB_ISNULL(new_column_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(create_aggr_expr(ctx_, new_aggr_type, new_aggr_expr, + new_column_expr))) { + LOG_WARN("failed to build common aggr exp", K(ret)); + } + } + return ret; +} + +int ObTransformGroupByPushdown::get_new_aggr_col_exprs( + ObIArray &aggr_col_exprs, + ObIArray ¶m, + ObIArray &new_column_exprs, + ObIArray &new_aggr_col_exprs) { + int ret = OB_SUCCESS; + new_aggr_col_exprs.reset(); + for (int64_t i = 0; OB_SUCC(ret) && i < aggr_col_exprs.count(); ++i) { + ObRawExpr *aggr_col_expr = NULL; + ObColumnRefRawExpr *new_column_expr = NULL; + uint64_t col_id = OB_INVALID_ID; + if (OB_ISNULL(aggr_col_expr = aggr_col_exprs.at(i)) || + OB_UNLIKELY(!aggr_col_expr->is_column_ref_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid aggr_col_expr", K(ret), K(aggr_col_expr)); + } else { + col_id = static_cast(aggr_col_expr)->get_column_id(); + if (OB_FAIL(find_new_column_expr(param, new_column_exprs, T_NULL, + col_id, new_column_expr))) { + } else if (OB_ISNULL(new_column_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(new_aggr_col_exprs.push_back(new_column_expr))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + return ret; +} + +int ObTransformGroupByPushdown::find_new_column_expr( + ObIArray ¶m, + ObIArray &new_column_exprs, + ObItemType type, + uint64_t col_id, + ObColumnRefRawExpr *&col_ref_expr) { + int ret = OB_SUCCESS; + col_ref_expr = NULL; + for (int64_t i = 0; OB_SUCC(ret) && i < param.count(); ++i) { + UnionPushdownParam &col = param.at(i); + if (type == col.aggr_func_type_ && col_id == col.col_id_) { + ObRawExpr *new_child_expr = NULL; + // get and check col expr + if (OB_ISNULL(new_child_expr = new_column_exprs.at(i)) || + OB_UNLIKELY(!new_child_expr->is_column_ref_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid new_child_expr", K(ret), K(new_child_expr)); + } else { + col_ref_expr = static_cast(new_child_expr); + // Theoretically, the index of param should correspond to the col_id. + // If this is not real in practice, a for loop search needs to be + // implemented here. + if (col_ref_expr->get_column_id() != i + OB_APP_MIN_COLUMN_ID) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected column id of column expr", K(ret)); + } + } + break; + } + } + return ret; +} + +int ObTransformGroupByPushdown::replace_aggr_and_aggr_col_exprs( + ObSelectStmt *stmt, + ObIArray &old_aggr_exprs, + ObIArray &new_aggr_exprs, + ObIArray &old_aggr_col_exprs, + ObIArray &new_aggr_col_exprs) { + int ret = OB_SUCCESS; + ObSEArray cast_new_aggr_exprs; + if (OB_ISNULL(stmt) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->session_info_) || + OB_ISNULL(ctx_->expr_factory_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (old_aggr_exprs.count() != new_aggr_exprs.count() || + old_aggr_col_exprs.count() != new_aggr_col_exprs.count()) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < old_aggr_exprs.count(); ++i) { + ObRawExpr *cast_expr = new_aggr_exprs.at(i); + if (OB_FAIL(ObTransformUtils::add_cast_for_replace_if_need( + *ctx_->expr_factory_, old_aggr_exprs.at(i), cast_expr, + ctx_->session_info_))) { + LOG_WARN("failed to add cast", K(ret)); + } else if (OB_FAIL(cast_new_aggr_exprs.push_back(cast_expr))) { + LOG_WARN("failed to push back"); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(stmt->replace_relation_exprs(old_aggr_exprs, + cast_new_aggr_exprs))) { + LOG_WARN("failed to replace aggr relation exprs", K(ret)); + } else if (OB_FAIL(stmt->replace_relation_exprs(old_aggr_col_exprs, + new_aggr_col_exprs))) { + LOG_WARN("failed to replace aggr col relation exprs", K(ret)); + } else if (OB_FAIL(ObTransformUtils::replace_exprs( + old_aggr_exprs, new_aggr_exprs, stmt->get_aggr_items()))) { + LOG_WARN("failed to replace aggr items", K(ret)); + } else if (OB_FAIL(stmt->formalize_stmt(ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt info", K(ret)); + } + return ret; +} + int ObTransformGroupByPushdown::get_tables_from_params(ObDMLStmt &stmt, ObIArray ¶ms, ObIArray> &trans_tables, @@ -160,7 +1113,7 @@ int ObTransformGroupByPushdown::adjust_transform_types(uint64_t &transform_types return ret; } -int ObTransformGroupByPushdown::check_groupby_push_down_validity(ObSelectStmt *stmt, +int ObTransformGroupByPushdown::check_push_down_into_join_validity(ObSelectStmt *stmt, bool &is_valid) { int ret = OB_SUCCESS; @@ -177,8 +1130,7 @@ int ObTransformGroupByPushdown::check_groupby_push_down_validity(ObSelectStmt *s is_valid = false; OPT_TRACE("do not rewrite inner table stmt with cost-based rule"); // do not rewrite inner table stmt with cost-based rule - } else if (stmt->has_window_function() || - stmt->has_rollup() || + } else if (stmt->has_rollup() || stmt->get_semi_infos().count() > 0 || stmt->get_subquery_exprs().count() > 0 || stmt->get_aggr_item_size() <= 0 || @@ -652,7 +1604,7 @@ int ObTransformGroupByPushdown::check_join_expr_validity(ObSelectStmt *stmt, return ret; } -int ObTransformGroupByPushdown::do_groupby_push_down(ObSelectStmt *stmt, +int ObTransformGroupByPushdown::do_groupby_push_down_into_join(ObSelectStmt *stmt, ObIArray ¶ms, ObIArray &flattern_joined_tables, ObSelectStmt *&trans_stmt, @@ -1018,6 +1970,8 @@ int ObTransformGroupByPushdown::transform_groupby_push_down(ObSelectStmt *stmt, LOG_WARN("failed to push back flags", K(ret)); } else if (OB_FAIL(new_table_items.push_back(new_table_item))) { LOG_WARN("push back new table item failed", K(ret)); + } else if (OB_FAIL(push_down_ctx.new_stmt_ids_.push_back(sub_stmt->get_stmt_id()))) { + LOG_WARN("failed to push back stmt id", K(ret)); } else { stmt->get_table_items().pop_back(); //replace join columns, replace group columns @@ -1598,7 +2552,9 @@ int ObTransformGroupByPushdown::is_expected_plan(ObLogPlan *plan, void *check_ct // do nothing } else if (OB_FAIL(check_nl_operator(plan->get_plan_root(), push_down_ctx, is_valid))) { LOG_WARN("check nl operator failed", K(ret)); - } + } else if (is_valid && OB_FAIL(check_cut_ratio(plan->get_plan_root(), push_down_ctx, is_valid))) { + LOG_WARN("failed to check cut ratio", K(ret)); + } return ret; } @@ -1656,6 +2612,120 @@ int ObTransformGroupByPushdown::has_group_by_op(ObLogicalOperator *op, bool &bre return ret; } +int ObTransformGroupByPushdown::check_cut_ratio(ObLogicalOperator *op, + ObCostBasedPushDownCtx *push_down_ctx, + bool &is_valid) +{ + int ret = OB_SUCCESS; + uint64_t version = 0; + ObSEArray invalid_stmts; + if (OB_ISNULL(op) || OB_ISNULL(op->get_stmt()) || OB_ISNULL(op->get_stmt()->get_query_ctx()) || + OB_ISNULL(push_down_ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (!op->get_stmt()->get_query_ctx()->check_opt_compat_version( + COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, COMPAT_VERSION_4_3_5)) { + // do nothing + } else if (OB_FAIL(invalid_stmts.prepare_allocate(push_down_ctx->new_stmt_ids_.count()))) { + LOG_WARN("failed to prepare array", K(ret)); + } else if (OB_FAIL(check_all_cut_ratio(op, push_down_ctx, false, invalid_stmts))) { + LOG_WARN("failed to check all cut ratio", K(ret)); + } else { + // Then invalid_stmts.at(i) is true only if the stmt exists and the cut ratio is invalid. + is_valid = false; + for (int64_t i = 0; OB_SUCC(ret) && !is_valid && i < invalid_stmts.count(); i++) { + is_valid = !invalid_stmts.at(i); + } + } + return ret; +} + +int ObTransformGroupByPushdown::check_all_cut_ratio(ObLogicalOperator *op, + ObCostBasedPushDownCtx *push_down_ctx, + bool is_in_cartesian, + ObIArray &invalid_stmts) +{ + int ret = OB_SUCCESS; + int64_t idx = -1; + if (OB_ISNULL(op) || OB_ISNULL(op->get_stmt()) || OB_ISNULL(push_down_ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("op is null", K(ret)); + } else if (ObOptimizerUtil::find_item(push_down_ctx->new_stmt_ids_, + op->get_stmt()->get_stmt_id(), &idx)) { + bool is_valid = false; + if (is_in_cartesian) { + // no nothing + } else if (OB_FAIL(check_single_cut_ratio(op, is_valid))) { + LOG_WARN("failed to check cut ratio", K(ret)); + } else if (!is_valid) { + invalid_stmts.at(idx) = true; + } + } else { + if (log_op_def::LOG_JOIN == op->get_type()) { + ObLogJoin *join = static_cast(op); + if (OB_ISNULL(join)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("static cast failed", K(ret)); + } else { + // pushdown group by into cartesian join is always better + is_in_cartesian = join->is_cartesian(); + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < op->get_num_of_child(); i++) { + if (OB_FAIL(SMART_CALL(check_all_cut_ratio(op->get_child(i), push_down_ctx, + is_in_cartesian, invalid_stmts)))) { + LOG_WARN("failed to check all cut ratio", K(ret)); + } + } + } + return ret; +} + +int ObTransformGroupByPushdown::check_single_cut_ratio(ObLogicalOperator *op, + bool &is_valid) +{ + int ret = OB_SUCCESS; + double cut_ratio = 1.0; + uint64_t nopushdown_cut_ratio = 1; + if (OB_ISNULL(op)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(compute_group_by_cut_ratio(op, cut_ratio))) { + LOG_WARN("failed to compute group by cut ratio", K(ret)); + } else if (OB_FAIL(ctx_->session_info_->get_sys_variable( + share::SYS_VAR__GROUPBY_NOPUSHDOWN_CUT_RATIO, nopushdown_cut_ratio))) { + LOG_WARN("failed to get session variable", K(ret)); + } else { + ObLogicalOperator *child_op = op->get_child(0); + is_valid = cut_ratio > nopushdown_cut_ratio; + LOG_TRACE("check trans plan cut ratio", K(is_valid), K(cut_ratio), K(nopushdown_cut_ratio)); + OPT_TRACE("check trans plan group by cut ratio", cut_ratio); + } + return ret; +} + +int ObTransformGroupByPushdown::compute_group_by_cut_ratio(ObLogicalOperator *op, + double &cut_ratio) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(op)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (log_op_def::LOG_SUBPLAN_SCAN == op->get_type() || op->get_num_of_child() != 1) { + // do nothing + } else if (OB_FAIL(SMART_CALL(compute_group_by_cut_ratio(op->get_child(0), cut_ratio)))) { + LOG_WARN("failed to compute group by cut ratio", K(ret)); + } else if (log_op_def::LOG_GROUP_BY != op->get_type()) { + } else if (OB_ISNULL(op->get_child(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected plan", K(ret)); + } else { + ObLogicalOperator *child_op = op->get_child(0); + cut_ratio *= child_op->get_card() / op->get_card(); + } + return ret; +} + int ObTransformGroupByPushdown::check_hint_valid(ObDMLStmt &stmt, ObIArray ¶ms, bool &hint_force_pushdown, @@ -1696,6 +2766,31 @@ int ObTransformGroupByPushdown::check_hint_valid(ObDMLStmt &stmt, return ret; } +int ObTransformGroupByPushdown::create_aggr_expr(ObTransformerCtx *ctx, + ObItemType type, + ObAggFunRawExpr *&agg_expr, + ObRawExpr *child_expr) { + int ret = OB_SUCCESS; + ObRawExprFactory *expr_factory = NULL; + if (OB_ISNULL(ctx) || OB_ISNULL(expr_factory = ctx->expr_factory_) || + OB_ISNULL(ctx->session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid argument", K(ret), K(ctx), K(expr_factory), K(agg_expr)); + } else if (OB_FAIL(expr_factory->create_raw_expr(type, agg_expr))) { + LOG_WARN("create raw expr failed", K(ret)); + } else if (OB_ISNULL(agg_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("invalid argument", K(ret), K(agg_expr)); + } else if (OB_FAIL(agg_expr->add_real_param_expr(child_expr))) { + LOG_WARN("failed to set partition exprs", K(ret)); + } else if (OB_FAIL(agg_expr->formalize(ctx->session_info_))) { + LOG_WARN("failed to formalize windown function", K(ret)); + } else if (OB_FAIL(agg_expr->pull_relation_id())) { + LOG_WARN("failed to pull relation id and levels", K(ret)); + } + return ret; +} + bool ObTransformGroupByPushdown::can_sum_trans_to_sum_count(const ObRawExpr *expr) { bool is_able = true; diff --git a/src/sql/rewrite/ob_transform_groupby_pushdown.h b/src/sql/rewrite/ob_transform_groupby_pushdown.h index 6821f7b55e..5f4b8aa28f 100644 --- a/src/sql/rewrite/ob_transform_groupby_pushdown.h +++ b/src/sql/rewrite/ob_transform_groupby_pushdown.h @@ -74,9 +74,106 @@ private: ObCostBasedPushDownCtx() {}; int64_t stmt_id_; ObSqlBitSet<> new_table_relids_; + ObSEArray new_stmt_ids_; }; - int check_groupby_push_down_validity(ObSelectStmt *stmt, bool &is_valid); + struct UnionPushdownParam { + uint64_t col_id_; + ObItemType aggr_func_type_; + TO_STRING_KV(K_(col_id), K_(aggr_func_type)); + }; + + int try_push_down_groupby_into_join(common::ObIArray &parent_stmts, + ObDMLStmt *&stmt, + bool &trans_happened); + + int try_push_down_groupby_into_union(common::ObIArray &parent_stmts, + ObDMLStmt *&stmt, + bool &trans_happened); + + int check_push_down_into_union_validity(ObSelectStmt *stmt, + bool &is_valid); + + int check_union_stmt_valid(ObSelectStmt &stmt, + ObSelectStmt *&union_stmt, + bool &is_valid); + + int check_aggr_exprs_valid(ObSelectStmt &stmt, + bool &is_valid, + bool &only_min_max); + + int check_child_stmts_valid(ObSelectStmt &union_stmt, + ObIArray &child_stmts, + bool &is_valid); + + int is_basic_select_stmt(ObSelectStmt *stmt, bool &is_basic); + + int get_union_stmt(ObSelectStmt *parent_stmt, + ObSelectStmt *&union_stmt, + bool &got); + + int get_union_pushdown_param(ObSelectStmt &stmt, + ObIArray ¶m); + + int get_col_id_of_child(ObSelectStmt &union_stmt, + uint64_t union_col_id, + uint64_t &child_col_id); + + int do_groupby_push_down_into_union(ObSelectStmt *origin_stmt, + ObIArray &new_colomns, + ObSelectStmt *&trans_stmt, + bool &trans_happend); + + int transform_basic_child_stmt(ObSelectStmt *stmt, + ObIArray &new_colomns); + + int transform_non_basic_child_stmt(ObSelectStmt *stmt, + ObIArray &new_colomns); + + int transform_union_stmt(ObSelectStmt *union_stmt, + ObIArray &child_stmts); + + int transform_parent_stmt_of_union(ObSelectStmt *stmt, + ObSelectStmt *union_stmt, + ObIArray &new_colomns); + + int get_new_select_expr_of_basic_child(UnionPushdownParam ¶m, + ObIArray &old_exprs, + ObRawExpr *&new_expr); + + int get_new_select_expr_of_non_basic_child(UnionPushdownParam ¶m, + ObIArray &old_exprs, + ObRawExpr *&new_expr); + + int get_new_aggr_exprs(ObIArray ¶m, + ObIArray &new_column_exprs, + ObIArray &aggr_exprs, + ObIArray &new_aggr_exprs); + + int get_new_aggr_expr(ObIArray ¶m, + ObIArray &new_column_exprs, + ObAggFunRawExpr *aggr_expr, + ObAggFunRawExpr *&new_aggr_expr); + + int get_new_aggr_col_exprs(ObIArray &aggr_col_exprs, + ObIArray ¶m, + ObIArray &new_column_exprs, + ObIArray &new_aggr_col_exprs); + + int find_new_column_expr(ObIArray ¶m, + ObIArray &new_column_exprs, + ObItemType type, + uint64_t col_id, + ObColumnRefRawExpr *&col_ref_exp); + + int replace_aggr_and_aggr_col_exprs( + ObSelectStmt *stmt, + ObIArray &old_aggr_exprs, + ObIArray &new_aggr_exprs, + ObIArray &old_aggr_col_exprs, + ObIArray &new_aggr_col_exprs); + + int check_push_down_into_join_validity(ObSelectStmt *stmt, bool &is_valid); int compute_push_down_param(ObSelectStmt *stmt, ObIArray ¶ms, @@ -107,7 +204,7 @@ private: JoinedTable &joined_table, ObSqlBitSet<> &table_set); - int do_groupby_push_down(ObSelectStmt *stmt, + int do_groupby_push_down_into_join(ObSelectStmt *stmt, ObIArray ¶ms, ObIArray &flattern_joined_tables, ObSelectStmt *&trans_stmt, @@ -171,12 +268,24 @@ private: int has_group_by_op(ObLogicalOperator *op, bool &bret); + int check_cut_ratio(ObLogicalOperator *op, + ObCostBasedPushDownCtx *push_down_ctx, + bool &is_valid); + int check_all_cut_ratio(ObLogicalOperator *op, + ObCostBasedPushDownCtx *push_down_ctx, + bool is_in_cartesian, + ObIArray &invalid_stmts); + int check_single_cut_ratio(ObLogicalOperator *op, + bool &is_valid); + int compute_group_by_cut_ratio(ObLogicalOperator *op, + double &cut_ratio); + int check_group_by_subset(ObRawExpr *expr, const ObIArray &group_exprs, bool &bret); int get_transed_table(ObIArray ¶ms, ObIArray &tables); int get_tables_from_params(ObDMLStmt &stmt, - ObIArray ¶ms, + ObIArray ¶ms, ObIArray> &trans_tables, bool disassemble_join = true); int check_hint_valid(ObDMLStmt &stmt, @@ -215,6 +324,11 @@ private: return num; } + // TODO 这个函数在更新的版本中已经存在于ObTransformUtils里面了,但是这个版本还没有 + // 所以先自己写一个,合并的时候再处理 + int create_aggr_expr(ObTransformerCtx *ctx, ObItemType type, + ObAggFunRawExpr *&agg_expr, ObRawExpr *child_expr); + }; } diff --git a/src/sql/rewrite/ob_transform_join_elimination.cpp b/src/sql/rewrite/ob_transform_join_elimination.cpp index d401a06654..25e19c9ad8 100644 --- a/src/sql/rewrite/ob_transform_join_elimination.cpp +++ b/src/sql/rewrite/ob_transform_join_elimination.cpp @@ -702,6 +702,7 @@ int ObTransformJoinElimination::check_transform_validity_outer_join( LOG_WARN("failed to get table ids", K(ret)); } else if (is_non_sens_dul_vals) { is_valid = true; + OPT_TRACE("is non sens dul vals"); } else if (OB_FAIL(stmt->get_table_rel_ids(*joined_table->left_table_, left_tables))) { LOG_WARN("failed to get table ids", K(ret)); } else if (OB_FAIL(ObTransformUtils::get_table_joined_exprs(left_tables, @@ -853,78 +854,85 @@ int ObTransformJoinElimination::extract_child_conditions(ObDMLStmt *stmt, } int ObTransformJoinElimination::eliminate_outer_join_in_joined_table(ObDMLStmt *stmt, - TableItem *&table_item, - const bool is_non_sens_dul_vals, - ObIArray &table_ids, - ObIArray &relation_exprs, - bool &trans_happen, - ObIArray> &trans_tables) + TableItem *&table_item, + const bool is_non_sens_dul_vals, + const bool is_root_table, + ObIArray &table_ids, + ObIArray &relation_exprs, + bool &trans_happen, + ObIArray> &trans_tables) { int ret = OB_SUCCESS; - bool is_stack_overflow = false; + JoinedTable *joined_table = NULL; + bool is_valid = false; + bool is_happened = false; + bool left_is_happend = false; + bool right_is_happend = false; trans_happen = false; if (OB_ISNULL(stmt) || OB_ISNULL(table_item)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt or joined table is null.", K(stmt), K(table_item), K(ret)); - } else if (OB_FAIL(check_stack_overflow(is_stack_overflow))) { - LOG_WARN("failed to check stack overflow", K(ret)); - } else if (is_stack_overflow) { - ret = OB_SIZE_OVERFLOW; - LOG_WARN("too deep recursive", K(ret), K(is_stack_overflow)); } else if (table_item->is_joined_table()) { - bool is_valid = false; - JoinedTable *joined_table = static_cast(table_item); - if (OB_FAIL(check_transform_validity_outer_join(stmt, - joined_table, - is_non_sens_dul_vals, - relation_exprs, - is_valid))) { + joined_table = static_cast(table_item); + // eliminate right branch + if (OB_ISNULL(joined_table->left_table_) || OB_ISNULL(joined_table->right_table_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("left child or right child is null.", K(ret)); + } else if (OB_FAIL(SMART_CALL(eliminate_outer_join_in_joined_table(stmt, + joined_table->right_table_, is_non_sens_dul_vals, false, + table_ids, relation_exprs, right_is_happend, trans_tables)))) { + LOG_WARN("failed to eliminate ouer join in joined table.", K(ret)); + } else if (!right_is_happend) { + /* do nothing */ + } else if (OB_FAIL(ObTransformUtils::adjust_single_table_ids(joined_table))) { + LOG_WARN("failed to construct single table ids.", K(ret)); + } else { + trans_happen = true; + LOG_TRACE("right branch transforms happened"); + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(check_transform_validity_outer_join(stmt, joined_table, is_non_sens_dul_vals, + relation_exprs, is_valid))) { LOG_WARN("failed to check transform validity outer join.", K(ret)); } else if (!is_valid) { - bool left_is_happend = false; - bool right_is_happend = false; - if (OB_FAIL(SMART_CALL(eliminate_outer_join_in_joined_table(stmt, - joined_table->right_table_, - is_non_sens_dul_vals, - table_ids, - relation_exprs, - right_is_happend, - trans_tables)))) { + // eliminate left branch + if (OB_FAIL(SMART_CALL(eliminate_outer_join_in_joined_table(stmt, joined_table->left_table_, + is_non_sens_dul_vals, false, table_ids, relation_exprs, + left_is_happend, trans_tables)))) { LOG_WARN("failed to eliminate ouer join in joined table.", K(ret)); - } else if (OB_FAIL(SMART_CALL(eliminate_outer_join_in_joined_table(stmt, - joined_table->left_table_, - is_non_sens_dul_vals, - table_ids, - relation_exprs, - left_is_happend, - trans_tables)))) { - LOG_WARN("failed to eliminate ouer join in joined table.", K(ret)); - } else if (!left_is_happend && !right_is_happend) { + } else if (!left_is_happend) { /* do nothing */ } else if (OB_FAIL(ObTransformUtils::adjust_single_table_ids(joined_table))) { LOG_WARN("failed to construct single table ids.", K(ret)); } else { trans_happen = true; } - } else if (OB_ISNULL(joined_table->left_table_) || OB_ISNULL(joined_table->right_table_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("left child or right child is null.", K(ret)); - } else if (OB_FAIL(SMART_CALL(eliminate_outer_join_in_joined_table(stmt, - joined_table->left_table_, - is_non_sens_dul_vals, - table_ids, - relation_exprs, - trans_happen, - trans_tables)))) { - LOG_WARN("failed to eliminate ouer join in joined table.", K(ret)); - } else if (OB_FAIL(construct_eliminated_table(stmt, joined_table->right_table_, trans_tables))) { + } else if (OB_FAIL(construct_eliminated_table(stmt, joined_table->right_table_, + trans_tables))) { LOG_WARN("failed to construct eliminated tables", K(ret)); - } else if (OB_FAIL(ObTransformUtils::remove_tables_from_stmt(stmt,joined_table->right_table_, + } else if (OB_FAIL(ObTransformUtils::remove_tables_from_stmt(stmt, joined_table->right_table_, table_ids))) { LOG_WARN("failed to remove table items.", K(ret)); } else { table_item = joined_table->left_table_; trans_happen = true; + relation_exprs.reset(); + if (is_root_table) { + if (OB_FAIL(stmt->remove_joined_table_item(joined_table))) { + LOG_WARN("failed to remove joined table item.", K(ret)); + } else if (table_item->is_joined_table() && + OB_FAIL(stmt->add_joined_table(static_cast(table_item)))) { + LOG_WARN("failed to add joined table item."); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(stmt->get_relation_exprs(relation_exprs))) { + LOG_WARN("failed to get relation exprs", K(ret)); + } else if (OB_FAIL(SMART_CALL(eliminate_outer_join_in_joined_table(stmt, table_item, + is_non_sens_dul_vals, is_root_table, table_ids, relation_exprs, + is_happened, trans_tables)))) { + LOG_WARN("failed to eliminate ouer join in joined table.", K(ret)); + } } } return ret; @@ -1258,81 +1266,6 @@ int ObTransformJoinElimination::left_join_can_be_eliminated(ObDMLStmt *stmt, return ret; } -// 1. stmt is generate table refquery in semi info right table -// 2. stmt is subquery is exists -// 2. stmt has distinct -int ObTransformJoinElimination::check_vaild_non_sens_dul_vals(ObIArray &parent_stmts, - ObDMLStmt *stmt, - bool &is_valid, - bool &need_add_limit_constraint) -{ - int ret = OB_SUCCESS; - is_valid = false; - need_add_limit_constraint = false; - if (OB_ISNULL(stmt)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (stmt->is_select_stmt()) { - ObSelectStmt *select_stmt = static_cast(stmt); - ObDMLStmt *parent_stmt = NULL; - bool has_rownum_expr = false; - bool has_state_func = false; - bool is_deterministic = false; - if (select_stmt->has_group_by() || - select_stmt->is_set_stmt() || - select_stmt->has_rollup() || - select_stmt->get_from_item_size() == 0 || - select_stmt->is_contains_assignment() || - select_stmt->has_window_function() || - select_stmt->has_sequence()) { - is_valid = false; - } else if (OB_FAIL(select_stmt->has_rownum(has_rownum_expr))) { - LOG_WARN("failed to check has rownum", K(ret)); - } else if (has_rownum_expr) { - is_valid = false; - } else if (OB_FAIL(select_stmt->is_query_deterministic(is_deterministic))) { - LOG_WARN("failed to check has rand", K(ret)); - } else if (!is_deterministic) { - is_valid = false; - } else if (select_stmt->is_distinct()) { - is_valid = true; - } - - if (OB_FAIL(ret) || is_valid || parent_stmts.empty()) { - /* do nothing */ - } else if (OB_ISNULL(parent_stmt = parent_stmts.at(parent_stmts.count() - 1).stmt_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (OB_FAIL(ObTransformUtils::check_stmt_is_non_sens_dul_vals(ctx_, parent_stmt, stmt, - is_valid, need_add_limit_constraint))) { - LOG_WARN("failed to check stmt is non sens dul vals", K(ret)); - } else if (is_valid) { - /* do nothing */ - } else if (!select_stmt->is_spj()) { - /* do nothing */ - } else if (parent_stmt->is_select_stmt() && - static_cast(parent_stmt)->is_set_distinct()) { - ObSelectStmt *sel_parent_stmt = static_cast(parent_stmt); - for (int i = 0; !is_valid && i < sel_parent_stmt->get_set_query().count(); ++i) { - is_valid = sel_parent_stmt->get_set_query(i) == select_stmt; - } - } else { - SemiInfo* semi = NULL; - TableItem *table = NULL; - for (int64_t i = 0; OB_SUCC(ret) && !is_valid && i < parent_stmt->get_semi_info_size(); ++i) { - if (OB_ISNULL(semi = parent_stmt->get_semi_infos().at(i)) || - OB_ISNULL(table = parent_stmt->get_table_item_by_id(semi->right_table_id_))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (table->ref_query_ == stmt) { - is_valid = true; - } - } - } - } - return ret; -} - int ObTransformJoinElimination::eliminate_outer_join(ObIArray &parent_stmts, ObDMLStmt *stmt, bool &trans_happened, @@ -1341,22 +1274,20 @@ int ObTransformJoinElimination::eliminate_outer_join(ObIArray & int ret = OB_SUCCESS; ObSEArray relation_exprs; bool is_non_sens_dul_vals = false; - bool need_add_limit_constraint = false; if (OB_ISNULL(stmt) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->schema_checker_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(stmt), K(ctx_), K(ret)); } else if (OB_FAIL(stmt->get_relation_exprs(relation_exprs))) { LOG_WARN("failed to get relations exprs all.", K(ret)); - } else if (OB_FAIL(check_vaild_non_sens_dul_vals(parent_stmts, stmt, is_non_sens_dul_vals, - need_add_limit_constraint))) { - LOG_WARN("failed to check valid", K(ret)); + } else if (OB_FAIL(stmt->check_from_dup_insensitive(is_non_sens_dul_vals))) { + LOG_WARN("failed to check from scope duplicate insensitive", K(ret)); } else { TableItem *table = NULL; bool is_happend = false; - common::ObArray joined_tables; ObSEArray table_ids; for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_from_item_size(); i++) { FromItem &from_item = stmt->get_from_item(i); + is_happend = false; if (!from_item.is_joined_) { /*do nothing*/ } else if (OB_ISNULL(table = stmt->get_joined_table(from_item.table_id_))) { @@ -1365,21 +1296,18 @@ int ObTransformJoinElimination::eliminate_outer_join(ObIArray & } else if (OB_FAIL(eliminate_outer_join_in_joined_table(stmt, table, is_non_sens_dul_vals, + true, table_ids, relation_exprs, is_happend, trans_tables))) { LOG_WARN("failed to eliminate outer join in from items.", K(ret)); - } else if (table->is_joined_table() && - OB_FAIL(joined_tables.push_back(static_cast(table)))) { - LOG_WARN("failed to push back joined tables", K(ret), K(table)); } else if (is_happend) { from_item.is_joined_ = table->is_joined_table(); from_item.table_id_ = table->table_id_; trans_happened = true; } } - if (OB_SUCC(ret) && trans_happened) { ObIArray &semi_infos = stmt->get_semi_infos(); for (int64_t i = 0; OB_SUCC(ret) && i < semi_infos.count(); ++i) { @@ -1395,12 +1323,6 @@ int ObTransformJoinElimination::eliminate_outer_join(ObIArray & } } if (OB_FAIL(ret)) { - } else if (need_add_limit_constraint &&// todo: need not add?? - OB_FAIL(ObTransformUtils::add_const_param_constraints(stmt->get_limit_expr(), - ctx_))) { - LOG_WARN("failed to add const param constraints", K(ret)); - } else if (OB_FAIL(stmt->get_joined_tables().assign(joined_tables))) { - LOG_WARN("failed to reset joined table container", K(ret)); } else if (OB_FAIL(stmt->rebuild_tables_hash())) { LOG_WARN("failed to rebuild table hash", K(ret)); } else if (OB_FAIL(stmt->update_column_item_rel_id())) { diff --git a/src/sql/rewrite/ob_transform_join_elimination.h b/src/sql/rewrite/ob_transform_join_elimination.h index ea9458a126..a264d36607 100644 --- a/src/sql/rewrite/ob_transform_join_elimination.h +++ b/src/sql/rewrite/ob_transform_join_elimination.h @@ -262,16 +262,12 @@ private: int eliminate_outer_join_in_joined_table(ObDMLStmt *stmt, TableItem *&table_item, const bool is_non_sens_dul_vals, + const bool is_root_table, ObIArray &removed_ids, ObIArray &relation_exprs, bool &trans_happen, ObIArray> &trans_tables); - int check_vaild_non_sens_dul_vals(ObIArray &parent_stmts, - ObDMLStmt *stmt, - bool &is_valid, - bool &need_add_limit_constraint); - int get_eliminable_tables(const ObDMLStmt *stmt, const ObIArray &conds, const ObIArray &candi_tables, diff --git a/src/sql/rewrite/ob_transform_pre_process.cpp b/src/sql/rewrite/ob_transform_pre_process.cpp index 547cb9edfe..161ad53fb8 100644 --- a/src/sql/rewrite/ob_transform_pre_process.cpp +++ b/src/sql/rewrite/ob_transform_pre_process.cpp @@ -10047,13 +10047,15 @@ int ObTransformPreProcess::expand_correlated_cte(ObDMLStmt *stmt, bool& trans_ha LOG_WARN("failed to check is correlated cte", K(ret)); } else if (!is_correlated) { //do nothing + } else if (OB_FAIL(ObTransformUtils::check_inline_temp_table_valid(temp_table_infos.at(i).temp_table_query_, can_expand))) { + LOG_WARN("failed to check expand temp table valid", K(ret)); } else if (OB_FAIL(temp_query->is_query_deterministic(can_expand))) { LOG_WARN("failed to check stmt is deterministic", K(ret)); } else if (!can_expand) { ret = OB_NOT_SUPPORTED; LOG_WARN("Correlated CTE Not Supported", K(ret)); LOG_USER_ERROR(OB_NOT_SUPPORTED, "Correlated CTE"); - } else if (OB_FAIL(ObTransformUtils::expand_temp_table(ctx_, temp_table_infos.at(i)))) { + } else if (OB_FAIL(ObTransformUtils::inline_temp_table(ctx_, temp_table_infos.at(i)))) { LOG_WARN("failed to extend temp table", K(ret)); } else { trans_happened = true; diff --git a/src/sql/rewrite/ob_transform_predicate_move_around.cpp b/src/sql/rewrite/ob_transform_predicate_move_around.cpp index 5903625de8..2193dad5e1 100644 --- a/src/sql/rewrite/ob_transform_predicate_move_around.cpp +++ b/src/sql/rewrite/ob_transform_predicate_move_around.cpp @@ -902,7 +902,6 @@ int ObTransformPredicateMoveAround::generate_pullup_predicates( ObIArray &output_pullup_preds) { int ret = OB_SUCCESS; - ObSEArray local_preds; ObSEArray filter_preds; if (OB_FAIL(gather_pullup_preds_from_semi_outer_join(select_stmt, filter_preds))) { LOG_WARN("failed to pullup preds from semi outer join", K(ret)); @@ -914,12 +913,8 @@ int ObTransformPredicateMoveAround::generate_pullup_predicates( LOG_WARN("failed to gather qualify filters", K(ret)); } else if (OB_FAIL(remove_simple_op_null_condition(select_stmt, filter_preds))) { LOG_WARN("fail to chck and remove const simple conditions", K(ret)); - } else if (OB_FAIL(append(local_preds, input_pullup_preds))) { - LOG_WARN("failed to append pullup predicates", K(ret)); - } else if (OB_FAIL(append(local_preds, filter_preds))) { - LOG_WARN("failed to append having and where conditions", K(ret)); - } else if (OB_FAIL(compute_pullup_predicates( - select_stmt, sel_ids, local_preds, output_pullup_preds))) { + } else if (OB_FAIL(compute_pullup_predicates(select_stmt, sel_ids, filter_preds, + input_pullup_preds, output_pullup_preds))) { LOG_WARN("failed to deduce exported predicates", K(ret)); } return ret; @@ -1018,12 +1013,14 @@ int ObTransformPredicateMoveAround::gather_pullup_preds_from_join_table(TableIte int ObTransformPredicateMoveAround::compute_pullup_predicates( ObSelectStmt &view, const ObIArray &select_list, - ObIArray &local_preds, + ObIArray &original_preds, + ObIArray &input_pullup_preds, ObIArray &pullup_preds) { int ret = OB_SUCCESS; ObSEArray select_exprs; ObSEArray deduced_preds; + bool is_transformed = false; pullup_preds.reset(); for (int64_t i = 0; OB_SUCC(ret) && i < select_list.count(); ++i) { int64_t idx = select_list.at(i); @@ -1040,12 +1037,12 @@ int ObTransformPredicateMoveAround::compute_pullup_predicates( } } if (OB_SUCC(ret)) { - if (OB_FAIL(transform_predicates( - view, local_preds, select_exprs, deduced_preds, true))) { + if (OB_FAIL(transform_predicates(view, original_preds, input_pullup_preds, select_exprs, + deduced_preds, is_transformed, true))) { LOG_WARN("failed to deduce predicates", K(ret)); } } - for (int64_t i = 0; OB_SUCC(ret) && i < deduced_preds.count(); ++i) { + for (int64_t i = 0; OB_SUCC(ret) && is_transformed && i < deduced_preds.count(); ++i) { // 0 for neither use valid select expr nor use invalid ones // 1 for only use valid select expr // -1 for use invalid select expr @@ -1347,8 +1344,13 @@ int ObTransformPredicateMoveAround::pushdown_predicates( SMART_VAR(PredsArray, all_old_preds) { ObIArray &from_items = stmt->get_from_items(); ObIArray &semi_infos = stmt->get_semi_infos(); + bool is_needed = false; if (OB_FAIL(store_all_preds(*stmt, all_old_preds))) { LOG_WARN("failed to store all preds", K(ret)); + } else if (OB_FAIL(check_need_transform_predicates(stmt->get_condition_exprs(), is_needed))) { + LOG_WARN("failed to check is need transform predicates", K(ret)); + } else if (!is_needed) { + /* do nothing */ } else if (OB_FAIL(gather_pullup_preds_from_semi_outer_join(*stmt, stmt->get_condition_exprs(), true))) { LOG_WARN("failed to pullup preds from semi outer join", K(ret)); } else if (OB_FAIL(pushdown_into_where(*stmt, *pullup_preds, candi_preds))) { @@ -1721,33 +1723,32 @@ int ObTransformPredicateMoveAround::remove_useless_equal_const_preds(ObSelectStm ObIArray &equal_const_preds) { int ret = OB_SUCCESS; + ObQuestionmarkEqualCtx cmp_ctx(false); for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); i++) { ObRawExpr *cur_expr = exprs.at(i); if (OB_ISNULL(cur_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null expr", K(ret), K(cur_expr)); - } else if (T_OP_EQ == cur_expr->get_expr_type()) { + } else if (T_OP_EQ == cur_expr->get_expr_type() || + T_OP_IS == cur_expr->get_expr_type()) { ObRawExpr *param_1 = cur_expr->get_param_expr(0); ObRawExpr *param_2 = cur_expr->get_param_expr(1); - bool is_not_null = false; + bool is_true = false; + bool is_false = false; if (OB_ISNULL(param_1) || OB_ISNULL(param_2)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("invalid param", K(ret)); - } else if (!param_1->is_const_expr() || - !param_2->is_const_expr() || - !param_1->same_as(*param_2)) { - - } else if (OB_FAIL(ObTransformUtils::is_expr_not_null( - ctx_, stmt, param_1, NULLABLE_SCOPE::NS_TOP, is_not_null))) { - LOG_WARN("failed to check expr not null", K(ret)); - } else if (!is_not_null) { - - } else if (OB_FAIL(equal_const_preds.push_back(cur_expr))) { + } else if (!param_1->is_const_expr() || !param_2->is_const_expr()) { + /* do nothing */ + } else if (OB_FAIL(ObTransformUtils::extract_const_bool_expr_result(ctx_, cur_expr, is_true, is_false))) { + LOG_WARN("fail to calc const expr", K(ret)); + } else if (is_true && OB_FAIL(equal_const_preds.push_back(cur_expr))) { LOG_WARN("failed to push back into useless equal const preds", K(ret)); } } } - if (OB_SUCC(ret) && OB_FAIL(ObOptimizerUtil::remove_item(exprs, equal_const_preds))) { + if (OB_SUCC(ret) && !equal_const_preds.empty() && + OB_FAIL(ObOptimizerUtil::remove_item(exprs, equal_const_preds))) { LOG_WARN("failed to remove equal const from exprs", K(ret)); } return ret; @@ -2049,6 +2050,7 @@ int ObTransformPredicateMoveAround::pushdown_into_having( ObSEArray all_columns; ObSEArray columns; ObSqlBitSet<> table_set; + bool is_needed = false; OPT_TRACE("try to pushdown",pushdown_preds, "into having"); if (sel_stmt.get_having_exprs().empty() && pushdown_preds.empty()) { // do nothing @@ -2064,19 +2066,17 @@ int ObTransformPredicateMoveAround::pushdown_into_having( LOG_WARN("failed to get related pullup preds", K(ret)); } else if (OB_FAIL(get_exprs_cnt_exec(sel_stmt, pullup_preds, input_preds))) { //exec param stored in pullup is useful certainly. LOG_WARN("get exec expr failed", K(ret)); - } else if (OB_FAIL(append(input_preds, sel_stmt.get_having_exprs()))) { - LOG_WARN("failed to append having predicates", K(ret)); } else if (OB_FAIL(append(input_preds, pushdown_preds))) { LOG_WARN("failed to append push down predicates", K(ret)); } else if (OB_FAIL(append(target_exprs, columns))) { LOG_WARN("failed to append column exprs", K(ret)); } else if (OB_FAIL(append(target_exprs, sel_stmt.get_aggr_items()))) { LOG_WARN("failed to append aggregation items", K(ret)); - } else if (OB_FAIL(transform_predicates(sel_stmt, - input_preds, - target_exprs, - new_having_exprs))) { + } else if (OB_FAIL(transform_predicates(sel_stmt, sel_stmt.get_having_exprs(), input_preds, + target_exprs, new_having_exprs, is_needed))) { LOG_WARN("failed to transform having predicates", K(ret)); + } else if (!is_needed) { + /* do nothing */ } else if (OB_FAIL(accept_predicates(sel_stmt, sel_stmt.get_having_exprs(), pullup_preds, @@ -2131,6 +2131,7 @@ int ObTransformPredicateMoveAround::pushdown_into_where(ObDMLStmt &stmt, ObSEArray all_columns; ObSEArray columns; ObSqlBitSet<> table_set; + bool is_needed = false; OPT_TRACE("try to transform where condition"); ObIArray &conditions = (stmt.is_insert_stmt() || stmt.is_merge_stmt()) ? static_cast(stmt).get_sharding_conditions() @@ -2151,10 +2152,11 @@ int ObTransformPredicateMoveAround::pushdown_into_where(ObDMLStmt &stmt, LOG_WARN("get exec expr failed", K(ret)); } else if (OB_FAIL(append(all_conds, predicates))) { LOG_WARN("failed to append push down predicates", K(ret)); - } else if (OB_FAIL(append(all_conds, conditions))) { - LOG_WARN("failed to append where conditions", K(ret)); - } else if (OB_FAIL(transform_predicates(stmt, all_conds, columns, new_conds))) { + } else if (OB_FAIL(transform_predicates(stmt, conditions, all_conds, columns, new_conds, + is_needed))) { LOG_WARN("failed to transform non-anti conditions", K(ret)); + } else if (!is_needed) { + /* do nothing */ } else if (OB_FAIL(accept_predicates(stmt, conditions, pullup_preds, @@ -2587,7 +2589,7 @@ int ObTransformPredicateMoveAround::pushdown_into_joined_table( ObSEArray new_preds; TableItem *filterable_table = NULL; ObSqlBitSet <>filter_table_set; - + bool is_needed = false; if (joined_table->is_left_join()) { filterable_table = joined_table->right_table_; } else if (joined_table->is_right_join()) { @@ -2606,17 +2608,16 @@ int ObTransformPredicateMoveAround::pushdown_into_joined_table( LOG_WARN("failed to push back predicates", K(ret)); } else if (OB_FAIL(append(properites, pushdown_preds))) { LOG_WARN("failed to append predicates", K(ret)); - } else if (OB_FAIL(append(all_preds, properites))) { - LOG_WARN("failed to append predicates", K(ret)); - } else if (OB_FAIL(append(all_preds, joined_table->join_conditions_))) { - LOG_WARN("failed to append join conditions", K(ret)); } else if (OB_FAIL(stmt->get_column_exprs(all_cols))) { LOG_WARN("failed to get all column exprs", K(ret)); } else if (OB_FAIL(ObTransformUtils::extract_table_exprs( *stmt, all_cols, *filterable_table, cols))) { LOG_WARN("failed to get related columns", K(ret)); - } else if (OB_FAIL(transform_predicates(*stmt, all_preds, cols, new_preds))) { + } else if (OB_FAIL(transform_predicates(*stmt, joined_table->join_conditions_, properites, cols, + new_preds, is_needed))) { LOG_WARN("failed to deduce predicates", K(ret)); + } else if (!is_needed) { + /* do nothing */ } else if (joined_table->is_inner_join()) { if (OB_FAIL(accept_predicates(*stmt, joined_table->join_conditions_, @@ -2625,29 +2626,13 @@ int ObTransformPredicateMoveAround::pushdown_into_joined_table( LOG_WARN("failed to accept predicate for joined table", K(ret)); } } else { - ObSEArray chosen_preds; - for (int64_t i = 0; OB_SUCC(ret) && i < joined_table->join_conditions_.count(); ++i) { - if (ObPredicateDeduce::find_equal_expr(chosen_preds, joined_table->join_conditions_.at(i))) { - //do nothing - } else if (OB_FAIL(chosen_preds.push_back(joined_table->join_conditions_.at(i)))) { - LOG_WARN("push back join condition failed", K(ret)); - } else {/*do nothing*/} - } - if (OB_SUCC(ret) && OB_FAIL(joined_table->join_conditions_.assign(chosen_preds))) { - LOG_WARN("assign join conditions failed", K(ret)); - } else {/*do nothing*/} - for (int64_t i = 0; OB_SUCC(ret) && i < new_preds.count(); ++i) { - if (OB_ISNULL(new_preds.at(i))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("new predicate is null", K(ret)); - } else if (!new_preds.at(i)->has_flag(CNT_COLUMN) || - !new_preds.at(i)->get_relation_ids().is_subset2(filter_table_set)) { - // do nothing - } else if (ObPredicateDeduce::find_equal_expr(all_preds, new_preds.at(i))) { - // do nothing - } else if (OB_FAIL(joined_table->join_conditions_.push_back(new_preds.at(i)))) { - LOG_WARN("failed to push back new predicate", K(ret)); - } + // left outer join | right outer join + if (OB_FAIL(accept_outjoin_predicates(*stmt, + joined_table->join_conditions_, + filter_table_set, + properites, + new_preds))) { + LOG_WARN("failed to accept outjoin predicates", K(ret)); } } } @@ -2854,6 +2839,7 @@ int ObTransformPredicateMoveAround::pushdown_into_semi_info(ObDMLStmt *stmt, ObSEArray new_preds; ObSEArray empty; ObSEArray pred_conditions; + bool is_needed = false; OPT_TRACE("try to transform semi conditions"); if (OB_ISNULL(stmt) || OB_ISNULL(semi_info) || OB_ISNULL(right_table = stmt->get_table_item_by_id(semi_info->right_table_id_))) { @@ -2875,14 +2861,15 @@ int ObTransformPredicateMoveAround::pushdown_into_semi_info(ObDMLStmt *stmt, LOG_WARN("failed to extract right table filters", K(ret)); } else if (OB_FAIL(all_preds.assign(properites))) { LOG_WARN("failed to assign predicates", K(ret)); - } else if (OB_FAIL(append(all_preds, semi_info->semi_conditions_))) { - LOG_WARN("failed to append join conditions", K(ret)); } else if (OB_FAIL(stmt->get_column_exprs(all_cols))) { LOG_WARN("failed to get all column exprs", K(ret)); } else if (OB_FAIL(ObTransformUtils::extract_table_exprs(*stmt, all_cols, right_rel_ids, cols))) { LOG_WARN("failed to get related columns", K(ret)); - } else if (OB_FAIL(transform_predicates(*stmt, all_preds, cols, new_preds))) { + } else if (OB_FAIL(transform_predicates(*stmt, semi_info->semi_conditions_, all_preds, cols, + new_preds, is_needed))) { LOG_WARN("failed to deduce predicates", K(ret)); + } else if (!is_needed) { + /* do nothing */ } else if (OB_FAIL(accept_predicates(*stmt, semi_info->semi_conditions_, properites, new_preds))) { LOG_WARN("failed to check different", K(ret)); @@ -3236,14 +3223,17 @@ int ObTransformPredicateMoveAround::rename_pushdown_predicates(ObDMLStmt &stmt, */ int ObTransformPredicateMoveAround::transform_predicates( ObDMLStmt &stmt, - common::ObIArray &input_preds, + common::ObIArray &original_preds, + common::ObIArray &other_preds, common::ObIArray &target_exprs, common::ObIArray &output_preds, + bool &is_happened, bool is_pullup /*= false*/) { int ret = OB_SUCCESS; + ObSEArray input_preds; ObSEArray valid_preds; - ObSEArray other_preds; + ObSEArray invalid_preds; ObSEArray simple_preds; ObSEArray general_preds; ObSEArray aggr_bound_preds; @@ -3252,6 +3242,14 @@ int ObTransformPredicateMoveAround::transform_predicates( if (OB_ISNULL(ctx_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("transform context is null", K(ret), K(ctx_)); + } else if (OB_FAIL(check_need_transform_predicates(original_preds, is_happened))) { + LOG_WARN("failed to check is need transform predicates", K(ret)); + } else if (!is_happened) { + /* do nothing */ + } else if (OB_FAIL(append(input_preds, original_preds))) { + LOG_WARN("failed to append", K(ret)); + } else if (OB_FAIL(append(input_preds, other_preds))) { + LOG_WARN("failed to append", K(ret)); } for (int64_t i = 0; OB_SUCC(ret) && i < input_preds.count(); ++i) { bool is_valid = false; @@ -3271,11 +3269,11 @@ int ObTransformPredicateMoveAround::transform_predicates( cast_expr, input_preds.at(i))))) { LOG_WARN("failed to push back preds", K(ret)); } - } else if (OB_FAIL(other_preds.push_back(input_preds.at(i)))) { + } else if (OB_FAIL(invalid_preds.push_back(input_preds.at(i)))) { LOG_WARN("failed to push back complex predicates", K(ret)); } } - while (OB_SUCC(ret) && visited.num_members() < valid_preds.count()) { + while (OB_SUCC(ret) && is_happened && visited.num_members() < valid_preds.count()) { // build a graph for comparing expr with the same comparing type ObPredicateDeduce deducer(stmt); for (int64_t i = 0; OB_SUCC(ret) && i < valid_preds.count(); ++i) { @@ -3292,7 +3290,7 @@ int ObTransformPredicateMoveAround::transform_predicates( if (OB_FAIL(deducer.deduce_simple_predicates(*ctx_, simple_preds))) { LOG_WARN("failed to deduce predicates for target", K(ret)); } else if (OB_FAIL(deducer.deduce_general_predicates( - *ctx_, target_exprs, other_preds, + *ctx_, target_exprs, invalid_preds, lossless_cast_preds, general_preds))) { LOG_WARN("failed to deduce special predicates", K(ret)); } else if (!is_pullup) { @@ -3305,10 +3303,10 @@ int ObTransformPredicateMoveAround::transform_predicates( } } } - if (OB_SUCC(ret)) { + if (OB_SUCC(ret) && is_happened) { if (OB_FAIL(output_preds.assign(simple_preds))) { LOG_WARN("failed to assign result", K(ret)); - } else if (OB_FAIL(append(output_preds, other_preds))) { + } else if (OB_FAIL(append(output_preds, invalid_preds))) { LOG_WARN("failed to append other predicates", K(ret)); } else if (OB_FAIL(append(output_preds, general_preds))) { LOG_WARN("failed to append speical predicates", K(ret)); @@ -3323,6 +3321,23 @@ int ObTransformPredicateMoveAround::transform_predicates( return ret; } +int ObTransformPredicateMoveAround::check_need_transform_predicates(ObIArray &exprs, + bool &is_needed) +{ + int ret = OB_SUCCESS; + ObSEArray true_exprs; + ObSEArray false_exprs; + if (OB_FAIL(ObTransformUtils::extract_const_bool_expr_info(ctx_, + exprs, + true_exprs, + false_exprs))) { + LOG_WARN("failed to extract const bool expr info", K(ret)); + } else { + is_needed = false_exprs.empty(); + } + return ret; +} + int ObTransformPredicateMoveAround::accept_predicates(ObDMLStmt &stmt, ObIArray &conds, ObIArray &properties, @@ -3359,6 +3374,52 @@ int ObTransformPredicateMoveAround::accept_predicates(ObDMLStmt &stmt, return ret; } +int ObTransformPredicateMoveAround::accept_outjoin_predicates(ObDMLStmt &stmt, + ObIArray &conds, + ObSqlBitSet <> &filter_table_set, + ObIArray &properties, + ObIArray &new_conds) +{ + int ret = OB_SUCCESS; + ObSEArray tmp_preds; + ObExprParamCheckContext context; + ObSEArray equal_param_constraints; + if (OB_ISNULL(stmt.get_query_ctx()) || OB_ISNULL(ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("init param check context failed", K(ret)); + } else if (OB_FAIL(equal_param_constraints.assign(stmt.get_query_ctx()->all_equal_param_constraints_)) || + OB_FAIL(append(equal_param_constraints, ctx_->equal_param_constraints_))) { + LOG_WARN("failed to fill equal param constraints", K(ret)); + } else { + context.init(&stmt.get_query_ctx()->calculable_items_, &equal_param_constraints); + for (int64_t i = 0; OB_SUCC(ret) && i < conds.count(); ++i) { + if (!ObPredicateDeduce::find_equal_expr(tmp_preds, conds.at(i)) && + OB_FAIL(tmp_preds.push_back(conds.at(i)))) { + LOG_WARN("push back join condition failed", K(ret)); + } + } + if (OB_SUCC(ret) && OB_FAIL(conds.assign(tmp_preds))) { + LOG_WARN("assign join conditions failed", K(ret)); + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < new_conds.count(); ++i) { + if (OB_ISNULL(new_conds.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("new predicate is null", K(ret)); + } else if (!new_conds.at(i)->has_flag(CNT_COLUMN) || + !new_conds.at(i)->get_relation_ids().is_subset2(filter_table_set)) { + // do nothing + } else if (ObPredicateDeduce::find_equal_expr(properties, new_conds.at(i), NULL, &context)) { + // the condition has been ensured + } else if (ObPredicateDeduce::find_equal_expr(conds, new_conds.at(i), NULL, &context)) { + // the condition has been chosen + } else if (OB_FAIL(conds.push_back(new_conds.at(i)))) { + LOG_WARN("failed to push back new predicate", K(ret)); + } + } + return ret; +} + int ObTransformPredicateMoveAround::extract_generalized_column(ObRawExpr *expr, ObIArray &output) { @@ -3619,8 +3680,7 @@ int ObTransformPredicateMoveAround::create_equal_exprs_for_insert(ObDelUpdStmt * } } } - } else if (OB_FAIL(ObRelationalExprOperator::is_equivalent( - target_exprs.at(i)->get_result_type(), + } else if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive( target_exprs.at(i)->get_result_type(), source_exprs.at(i)->get_result_type(), type_safe))) { diff --git a/src/sql/rewrite/ob_transform_predicate_move_around.h b/src/sql/rewrite/ob_transform_predicate_move_around.h index a9afd708d2..770172a03f 100644 --- a/src/sql/rewrite/ob_transform_predicate_move_around.h +++ b/src/sql/rewrite/ob_transform_predicate_move_around.h @@ -132,7 +132,8 @@ private: int compute_pullup_predicates(ObSelectStmt &view, const ObIArray &select_list, - ObIArray &local_preds, + ObIArray &original_preds, + ObIArray &input_pullup_preds, ObIArray &pull_up_preds); int check_expr_pullup_validity(ObRawExpr *expr, @@ -317,11 +318,18 @@ private: ObIArray &preds); int transform_predicates(ObDMLStmt &stmt, - ObIArray &input_preds, + ObIArray &original_preds, + ObIArray &other_preds, ObIArray &target_exprs, ObIArray &output_preds, + bool &is_happened, bool is_pullup = false); - + int check_need_transform_predicates(ObIArray &exprs, bool &is_needed); + int accept_outjoin_predicates(ObDMLStmt &stmt, + ObIArray &conds, + ObSqlBitSet <> &filter_table_set, + ObIArray &properties, + ObIArray &new_conds); int accept_predicates(ObDMLStmt &stmt, ObIArray &conds, ObIArray &properties, diff --git a/src/sql/rewrite/ob_transform_rule.cpp b/src/sql/rewrite/ob_transform_rule.cpp index 1ce7c73f98..1a8e24fb86 100644 --- a/src/sql/rewrite/ob_transform_rule.cpp +++ b/src/sql/rewrite/ob_transform_rule.cpp @@ -74,6 +74,9 @@ void ObTransformerCtx::reset() iteration_level_ = 0; mv_infos_.reset(); mv_stmt_gen_count_ = 0; + cbqt_policy_ = TransPolicy::DISABLE_TRANS; + complex_cbqt_table_num_ = 0; + max_table_num_ = 0; } int ObTransformerCtx::add_src_hash_val(const ObString &src_str) @@ -145,6 +148,7 @@ const char* ObTransformerCtx::get_trans_type_string(uint64_t trans_type) TRANS_TYPE_TO_STR(CONDITIONAL_AGGR_COALESCE) TRANS_TYPE_TO_STR(MV_REWRITE) TRANS_TYPE_TO_STR(LATE_MATERIALIZATION) + TRANS_TYPE_TO_STR(DISTINCT_AGGREGATE) default: return NULL; } } @@ -161,6 +165,8 @@ int ObTransformRule::transform(ObDMLStmt *&stmt, LOG_WARN("failed to transform stmt recursively", K(ret)); } else if (OB_FAIL(adjust_transform_types(transform_types))) { LOG_WARN("failed to adjust transform types", K(ret)); + } else if (OB_FAIL(update_trans_ctx(stmt))) { + LOG_WARN("failed to update trans ctx", K(ret)); } else { /*do nothing*/ } return ret; } @@ -310,6 +316,7 @@ int ObTransformRule::accept_transform(common::ObIArray &parent_ const int64_t check_try_times = 32; ObDMLStmt *tmp1 = NULL; ObDMLStmt *tmp2 = NULL; + bool ignore_cost = (OB_E(EventTable::EN_CBQT_IGNORE_COST) OB_SUCCESS) != OB_SUCCESS; cost_based_trans_tried_ = true; BEGIN_OPT_TRACE_EVA_COST; if (OB_UNLIKELY((OB_SUCCESS != (ret = TRY_CHECK_MEM_STATUS(check_try_times))))) { @@ -329,14 +336,14 @@ int ObTransformRule::accept_transform(common::ObIArray &parent_ check_ctx))) { LOG_WARN("failed to evaluate cost for the transformed stmt", K(ret)); } else if ((!check_original_plan && stmt_cost_ >= 0) || !is_expected) { - trans_happened = is_expected && trans_stmt_cost < stmt_cost_; + trans_happened = is_expected && (ignore_cost || trans_stmt_cost < stmt_cost_); } else if (OB_FAIL(evaluate_cost(parent_stmts, stmt, false, stmt_cost_, is_original_expected, check_original_plan ? check_ctx : NULL))) { LOG_WARN("failed to evaluate cost for the origin stmt", K(ret)); } else if (!is_original_expected) { trans_happened = is_original_expected; } else { - trans_happened = trans_stmt_cost < stmt_cost_; + trans_happened = ignore_cost || trans_stmt_cost < stmt_cost_; } if (stmt->get_query_ctx()->get_injected_random_status()) { trans_happened = true; @@ -350,10 +357,12 @@ int ObTransformRule::accept_transform(common::ObIArray &parent_ OPT_TRACE("reject transform because the cost is increased or the query plan is unexpected."); OPT_TRACE("before transform cost:", stmt_cost_); OPT_TRACE("after transform cost:", trans_stmt_cost); + OPT_TRACE("is ignore cost:", ignore_cost); OPT_TRACE("is expected plan:", is_expected); OPT_TRACE("is expected original plan:", is_original_expected); LOG_TRACE("reject transform because the cost is increased or the query plan is unexpected", - K_(ctx_->is_set_stmt_oversize), K_(stmt_cost), K(trans_stmt_cost), K(is_expected)); + K_(ctx_->is_set_stmt_oversize), K_(stmt_cost), K(trans_stmt_cost), K(ignore_cost), + K(is_expected), K(is_original_expected)); } else if (OB_FAIL(adjust_transformed_stmt(parent_stmts, trans_stmt, tmp1, tmp2))) { LOG_WARN("failed to adjust transformed stmt", K(ret)); } else if (force_accept) { @@ -406,6 +415,7 @@ int ObTransformRule::evaluate_cost(common::ObIArray &parent_stm ObDMLStmt *root_stmt = NULL; lib::ContextParam param; ObTransformerImpl trans(ctx_); + int64_t start_time_us = ObTimeUtil::current_time(); param.set_mem_attr(ctx_->session_info_->get_effective_tenant_id(), "CostBasedRewrit", ObCtxIds::DEFAULT_CTX_ID) @@ -808,6 +818,10 @@ int ObTransformRule::transform_self(common::ObIArray &parent_st } else if (OB_FAIL(stmt->formalize_stmt_expr_reference(ctx_->expr_factory_, ctx_->session_info_))) { LOG_WARN("failed to formalize stmt reference", K(ret)); + } else if (OB_FAIL(stmt->formalize_implicit_distinct())) { + LOG_WARN("failed to update implicit distinct", K(ret)); + } else if (OB_FAIL(update_max_table_num(stmt))) { + LOG_WARN("failed to update max table num", K(ret)); } else if ((!stmt->is_delete_stmt() && !stmt->is_update_stmt()) || stmt->has_instead_of_trigger()) { // do nothing @@ -1102,6 +1116,7 @@ int ObTransformRule::check_hint_status(const ObDMLStmt &stmt, bool &need_trans) const ObHint *myhint = get_hint(stmt.get_stmt_hint()); bool is_enable = (NULL != myhint && myhint->is_enable_hint()); bool is_disable = (NULL != myhint && myhint->is_disable_hint()); + bool enable_cost_rule = true; need_trans = false; if (OB_ISNULL(ctx_) || OB_ISNULL(query_hint = stmt.get_stmt_hint().query_hint_)) { @@ -1118,8 +1133,10 @@ int ObTransformRule::check_hint_status(const ObDMLStmt &stmt, bool &need_trans) LOG_WARN("failed to add used transform hint", K(ret)); } OPT_TRACE("hint reject current transform"); - } else if ((ALL_COST_BASED_RULES & (1L << get_transformer_type())) && - query_hint->global_hint_.disable_cost_based_transform()) { + } else if (OB_FAIL(ObTransformUtils::is_cost_based_trans_enable(ctx_, query_hint->global_hint_, + enable_cost_rule))) { + LOG_WARN("failed to check cost based transform enable", K(ret)); + } else if ((ALL_COST_BASED_RULES & (1L << get_transformer_type())) && !enable_cost_rule) { /* disable transform by NO_COST_BASED_QUERY_TRANSFORMATION hint */ } else { need_trans = true; @@ -1132,5 +1149,50 @@ int ObTransformRule::check_hint_status(const ObDMLStmt &stmt, bool &need_trans) return ret; } +int ObTransformRule::update_trans_ctx(ObDMLStmt *stmt) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(stmt) || OB_ISNULL(ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (trans_happened_) { + ObSEArray temp_table_infos; + ctx_->max_table_num_ = 0; + if (OB_FAIL(update_max_table_num(stmt))) { + LOG_WARN("failed to update max table num", K(ret)); + } else if (OB_FAIL(stmt->collect_temp_table_infos(temp_table_infos))) { + LOG_WARN("failed to collect temp table infos", K(ret)); + } + for(int64_t i = 0; OB_SUCC(ret) && i < temp_table_infos.count(); ++i) { + ObDMLStmt *child_stmt = temp_table_infos.at(i).temp_table_query_; + if (OB_FAIL(update_max_table_num(child_stmt))) { + LOG_WARN("failed to update max table num", K(ret)); + } + } + } + return ret; +} + +int ObTransformRule::update_max_table_num(ObDMLStmt *stmt) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(stmt) || OB_ISNULL(ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else { + ObSEArray child_stmts; + ctx_->max_table_num_ = MAX(ctx_->max_table_num_, stmt->get_table_size()); + if (OB_FAIL(stmt->get_child_stmts(child_stmts))) { + LOG_WARN("failed to get child stmts", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) { + if (OB_FAIL(SMART_CALL(update_max_table_num(child_stmts.at(i))))) { + LOG_WARN("failed to update max table num", K(ret)); + } + } + } + return ret; +} + } /* namespace sql */ } /* namespace oceanbase */ diff --git a/src/sql/rewrite/ob_transform_rule.h b/src/sql/rewrite/ob_transform_rule.h index 98a29a404a..8c0849fdf4 100644 --- a/src/sql/rewrite/ob_transform_rule.h +++ b/src/sql/rewrite/ob_transform_rule.h @@ -91,6 +91,13 @@ struct MvInfo { uint64_t mv_intersect_tbl_num_; // number of tables that appear in both mv and origin query, used for sort mv info }; +enum TransPolicy +{ + DISABLE_TRANS = 0, + LIMITED_TRANS = 1, + ENABLE_TRANS = 2, +}; + struct ObTransformerCtx { ObTransformerCtx() @@ -127,7 +134,12 @@ struct ObTransformerCtx push_down_filters_(), in_accept_transform_(false), iteration_level_(0), - mv_stmt_gen_count_(0) + mv_stmt_gen_count_(0), + cbqt_policy_(TransPolicy::DISABLE_TRANS), + complex_cbqt_table_num_(0), + max_table_num_(0), + inline_blacklist_(), + materialize_blacklist_() { } virtual ~ObTransformerCtx() {} @@ -198,6 +210,13 @@ struct ObTransformerCtx uint64_t iteration_level_; ObSEArray mv_infos_; // used to perform mv rewrite int64_t mv_stmt_gen_count_; + // used for cost based query transformation control + TransPolicy cbqt_policy_; + int64_t complex_cbqt_table_num_; + int64_t max_table_num_; + /* used for CTE inline && materialize */ + ObSEArray inline_blacklist_; + ObSEArray materialize_blacklist_; }; enum TransMethod @@ -247,6 +266,7 @@ enum TRANSFORM_TYPE { CONDITIONAL_AGGR_COALESCE , MV_REWRITE , LATE_MATERIALIZATION , + DISTINCT_AGGREGATE , TRANSFORM_TYPE_COUNT_PLUS_ONE , }; @@ -351,7 +371,8 @@ public: (1L << LEFT_JOIN_TO_ANTI) | (1L << COUNT_TO_EXISTS) | (1L << CONDITIONAL_AGGR_COALESCE) | - (1L << SEMI_TO_INNER); + (1L << SEMI_TO_INNER) | + (1L << DISTINCT_AGGREGATE); static const uint64_t ALL_COST_BASED_RULES = (1L << OR_EXPANSION) | (1L << WIN_MAGIC) | @@ -359,9 +380,21 @@ public: (1L << GROUPBY_PULLUP) | (1L << SUBQUERY_COALESCE) | (1L << SEMI_TO_INNER) | + (1L << TEMP_TABLE_OPTIMIZATION) | (1L << MV_REWRITE) | (1L << LATE_MATERIALIZATION); + static const uint64_t ALL_EXPR_LEVEL_HEURISTICS_RULES = + (1L << SIMPLIFY_EXPR) | + (1L << SIMPLIFY_DISTINCT) | + (1L << SIMPLIFY_WINFUNC) | + (1L << SIMPLIFY_ORDERBY) | + (1L << SIMPLIFY_LIMIT) | + (1L << PROJECTION_PRUNING) | + (1L << PREDICATE_MOVE_AROUND) | + (1L << JOIN_LIMIT_PUSHDOWN) | + (1L << CONST_PROPAGATE); + ObTransformRule(ObTransformerCtx *ctx, TransMethod transform_method, ObItemType hint_type = T_INVALID) @@ -521,6 +554,8 @@ private: void *check_ctx, bool is_trans_plan, bool& is_valid); + int update_trans_ctx(ObDMLStmt *stmt); + int update_max_table_num(ObDMLStmt *stmt); bool skip_move_trans_loc() const { diff --git a/src/sql/rewrite/ob_transform_semi_to_inner.cpp b/src/sql/rewrite/ob_transform_semi_to_inner.cpp index bd1810adf9..b4643b7f52 100644 --- a/src/sql/rewrite/ob_transform_semi_to_inner.cpp +++ b/src/sql/rewrite/ob_transform_semi_to_inner.cpp @@ -300,11 +300,6 @@ int ObTransformSemiToInner::do_transform_by_rewrite_form(ObDMLStmt* stmt, trans_param))) { LOG_WARN("failed to do transform (INNER)", K(ret)); // Just in case different parameters hit same plan, we need add const param constraint - } else if (!trans_param.need_add_limit_constraint_) { - // do nothing - } else if (OB_FAIL(ObTransformUtils::add_const_param_constraints( - stmt->get_limit_expr(), ctx_))) { - LOG_WARN("failed to add const param constriants", K(ret)); } } else if (trans_param.use_aggr_inner()) { if (OB_FAIL(do_transform_with_aggr(*stmt, semi_info, ctx, trans_param))) { @@ -335,29 +330,12 @@ int ObTransformSemiToInner::do_transform_by_rewrite_form(ObDMLStmt* stmt, if (OB_ISNULL(right_table)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(push_right_table_ids(right_table, ctx.view_table_id_))) { + LOG_WARN("fail to push back view table id", K(ret)); } else if (right_table->is_generated_table()) { - if (OB_ISNULL(right_stmt = right_table->ref_query_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null", K(ret)); - } else if (OB_FAIL(ctx.view_table_id_.push_back(semi_info->right_table_id_))) { - LOG_WARN("fail to push back view table id", K(ret)); - } else { - for (int64_t i = 0; OB_SUCC(ret) && i < right_stmt->get_table_items().count(); ++i) { - TableItem *inner_right_table = right_stmt->get_table_item(i); - if (OB_ISNULL(inner_right_table)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpect null table item", K(ret)); - } else if (OB_FAIL(ctx.view_table_id_.push_back(inner_right_table->table_id_))) { - LOG_WARN("fail to push back view table id", K(ret)); - } - } - } - if (OB_FAIL(ret)){ - } else if (OB_FAIL(find_basic_table(right_table->ref_query_, ctx.table_id_))) { + if (OB_FAIL(find_basic_table(right_table->ref_query_, ctx.table_id_))) { LOG_WARN("failed to find basic table", K(ret)); } - } else if (OB_FAIL(ctx.view_table_id_.push_back(semi_info->right_table_id_))) { - LOG_WARN("fail to push back view table id", K(ret)); } else { ctx.table_id_ = semi_info->right_table_id_; } @@ -515,7 +493,6 @@ int ObTransformSemiToInner::check_basic_validity(ObDMLStmt *root_stmt, bool is_all_left_filter = false; bool is_one_row = false; bool is_non_sens_dup_vals = false; - bool is_multi_join_cond = false; TableItem *right_table = NULL; bool can_add_deduplication = false; ObIArray & left_table_ids = semi_info.left_table_ids_; @@ -524,7 +501,6 @@ int ObTransformSemiToInner::check_basic_validity(ObDMLStmt *root_stmt, ObSEArray right_exprs; is_valid = false; need_check_cost = false; - bool need_add_limit_constraint = false; bool condition_match_index = ctx.hint_force_; int64_t cmp_join_conds_count = 0; int64_t invalid_conds_count = 0; @@ -554,61 +530,72 @@ int ObTransformSemiToInner::check_basic_validity(ObDMLStmt *root_stmt, left_exprs, right_exprs, is_all_left_filter, - is_multi_join_cond, + ctx.is_multi_join_cond_, cmp_join_conds_count, invalid_conds_count, other_conds_count))) { LOG_WARN("failed to check semi join condition", K(ret)); - } else if (OB_FAIL(check_right_table_output_one_row(*right_table, is_one_row))) { - LOG_WARN("failed to check right tables output one row", K(ret)); - } else if (is_one_row) { - is_valid = true; - trans_param.set_transform_flag(TO_INNER); - OPT_TRACE("semi join right table output most one row, no need distinct"); - } else if (OB_FAIL(ObTransformUtils::check_stmt_is_non_sens_dul_vals(ctx_, root_stmt, &stmt, - is_non_sens_dup_vals, - need_add_limit_constraint))) { - LOG_WARN("failed to check stmt is non sens dul vals", K(ret)); - } else if (is_non_sens_dup_vals) { - is_valid = true; - trans_param.set_transform_flag(TO_INNER); - trans_param.need_add_limit_constraint_ = need_add_limit_constraint; - OPT_TRACE("stmt isn't sensitive to result of subquery has duplicated values"); - LOG_TRACE("stmt isn't sensitive to result of subquery has duplicated values"); } else if (OB_FAIL(check_right_exprs_unique(stmt, right_table, right_exprs, is_unique))) { LOG_WARN("failed to check exprs unique on table items", K(ret)); } else if (is_unique) { is_valid = true; trans_param.set_transform_flag(TO_INNER); - LOG_TRACE("semi right table output is unique"); + trans_param.need_add_distinct_ = false; + need_check_cost = false; OPT_TRACE("semi right table output is unique"); - } else if (is_all_left_filter && (NULL == right_table->ref_query_ || + LOG_TRACE("semi right table output is unique"); + } else if (OB_FAIL(check_right_table_output_one_row(*right_table, is_one_row))) { + LOG_WARN("failed to check right tables output one row", K(ret)); + } else if (is_one_row) { + // constraint has already added in check_right_table_output_one_row() + is_valid = true; + trans_param.set_transform_flag(TO_INNER); + trans_param.need_add_distinct_ = false; + need_check_cost = false; + OPT_TRACE("semi join right table output most one row, no need distinct"); + LOG_TRACE("semi join right table output most one row, no need distinct"); + } else if (is_all_left_filter && (NULL == right_table->ref_query_ || NULL == right_table->ref_query_->get_limit_percent_expr())) { is_valid = true; - trans_param.right_table_need_add_limit_ = true; trans_param.set_transform_flag(TO_INNER); + trans_param.need_add_distinct_ = false; + trans_param.right_table_need_add_limit_ = true; + need_check_cost = false; OPT_TRACE("semi conditions are all left filters, will not add distinct, will add limit 1"); + LOG_TRACE("semi conditions are all left filters, will not add distinct, will add limit 1"); + } else if (OB_FAIL(stmt.check_from_dup_insensitive(is_non_sens_dup_vals))) { + LOG_WARN("failed to check from scope duplicate insensitive", K(ret)); + } else if (is_non_sens_dup_vals) { + if (OB_FAIL(non_sens_dul_vals_need_check_cost(stmt, semi_info, need_check_cost))) { + LOG_WARN("failed to check need check cost ", K(ret)); + } else { + is_valid = true; + trans_param.set_transform_flag(TO_INNER); + trans_param.need_add_distinct_ = false; + ctx.is_non_sens_dul_vals_ = true; + OPT_TRACE("stmt is insensitive to result of subquery has duplicated values"); + LOG_TRACE("stmt is insensitive to result of subquery has duplicated values"); + } } else if (invalid_conds_count > 0) { // do nothing } else if (cmp_join_conds_count < 2 && OB_FAIL(check_can_add_deduplication(left_exprs, right_exprs, can_add_deduplication))) { LOG_WARN("failed to check can add deduplication on right", K(ret)); - } else if (!is_multi_join_cond && !ctx.hint_force_ && + } else if (!ctx.is_multi_join_cond_ && !ctx.hint_force_ && OB_FAIL(check_join_condition_match_index(root_stmt, stmt, semi_info, semi_info.semi_conditions_, condition_match_index))) { LOG_WARN("failed to check join condition match index", K(ret)); - } else if (!is_multi_join_cond && !condition_match_index) { + } else if (!ctx.is_multi_join_cond_ && !condition_match_index) { // do nothing OPT_TRACE("semi condition not match index and is not multi join , will not transform"); } else if (cmp_join_conds_count == 0 && other_conds_count == 0 && can_add_deduplication) { // TO_INNER (distinct) : for cases when only standard equal join condition(s) exist + is_valid = true; trans_param.set_transform_flag(TO_INNER); trans_param.need_add_distinct_ = true; - ctx.is_multi_join_cond_ = is_multi_join_cond; need_check_cost = true; - is_valid = true; // when right table is from "dual", ban cost checking for adding distinct bool query_from_dual = false; ObSelectStmt *right_table_ref_query = NULL; @@ -624,7 +611,6 @@ int ObTransformSemiToInner::check_basic_validity(ObDMLStmt *root_stmt, is_valid = true; trans_param.set_transform_flag(TO_AGGR_INNER); trans_param.need_add_gby_ = (left_exprs.count() != 0); - ctx.is_multi_join_cond_ = is_multi_join_cond; need_check_cost = true; } else if (!stmt.has_for_update()) { // If there is FOR UPDATE, can not use TO_INNER_GBY @@ -643,10 +629,9 @@ int ObTransformSemiToInner::check_basic_validity(ObDMLStmt *root_stmt, // do nothing } else { is_valid = true; - trans_param.need_spj_view_ = !is_spj_stmt; trans_param.set_transform_flag(TO_INNER_GBY); + trans_param.need_spj_view_ = !is_spj_stmt; need_check_cost = true; - ctx.is_multi_join_cond_ = is_multi_join_cond; } } if (OB_SUCC(ret) && is_valid && need_check_cost && ctx_->in_accept_transform_) { @@ -655,6 +640,35 @@ int ObTransformSemiToInner::check_basic_validity(ObDMLStmt *root_stmt, return ret; } +int ObTransformSemiToInner::non_sens_dul_vals_need_check_cost(ObDMLStmt &stmt, + SemiInfo &semi_info, + bool &need_check_cost) { + int ret = OB_SUCCESS; + double expansion_rate_threshold = 2; + double expansion_rate = -1; + need_check_cost = true; + const TableItem *right_table; + ObSEArray column_ids; + ObSEArray column_ids_no_dup; + if (OB_ISNULL(right_table = stmt.get_table_item_by_id(semi_info.right_table_id_))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("semi right table is null", K(ret), K(right_table)); + } else if (!right_table->is_basic_table()) { + need_check_cost = true; + } else if (OB_FAIL(ObOptimizerUtil::extract_column_ids(semi_info.semi_conditions_, right_table->table_id_, column_ids))) { + LOG_WARN("failed to extract column ids", K(ret), K(semi_info)); + } else if (OB_FAIL(append_array_no_dup(column_ids_no_dup, column_ids))) { + LOG_WARN("failed to append array", K(ret)); + } else if (OB_FAIL(ObTransformUtils::calc_column_repeat_rate(ctx_, right_table, column_ids_no_dup, expansion_rate))){ + LOG_WARN("failed to calcuate column repeat rate", K(ret)); + } else if (expansion_rate < 1) { + need_check_cost = true; + } else { + need_check_cost = expansion_rate <= expansion_rate_threshold; + } + return ret; +} + int ObTransformSemiToInner::check_query_from_dual(ObSelectStmt *stmt, bool& query_from_dual/*=false*/) { int ret = OB_SUCCESS; ObSEArray child_stmts; @@ -1019,17 +1033,15 @@ int ObTransformSemiToInner::check_need_add_cast(const ObRawExpr *left_arg, if (OB_ISNULL(left_arg) || OB_ISNULL(right_arg)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("left arg and right arg should not be NULL", K(ret), K(left_arg), K(right_arg)); - } else if (OB_FAIL(ObRelationalExprOperator::is_equivalent(left_arg->get_result_type(), - left_arg->get_result_type(), - right_arg->get_result_type(), - is_valid))) { + } else if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive(left_arg->get_result_type(), + right_arg->get_result_type(), + is_valid))) { LOG_WARN("failed to check expr is equivalent", K(ret)); } else if (!is_valid) { LOG_TRACE("can not use left expr type as the (left, right) compare type", K(is_valid)); - } else if (OB_FAIL(ObRelationalExprOperator::is_equivalent(left_arg->get_result_type(), - right_arg->get_result_type(), - right_arg->get_result_type(), - is_equal))) { + } else if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive(left_arg->get_result_type(), + right_arg->get_result_type(), + is_equal))) { LOG_WARN("failed to check expr is equivalent", K(ret)); } else if (!is_equal) { need_add_cast = true; @@ -1098,7 +1110,19 @@ int ObTransformSemiToInner::do_transform(ObDMLStmt &stmt, LOG_WARN("failed to append semi conditions", K(ret)); } else if (OB_FAIL(stmt.add_from_item(semi_info->right_table_id_, false))) { LOG_WARN("failed to add from items", K(ret)); - } else if (!right_table_need_add_limit) { + } else if (OB_ISNULL(right_table = stmt.get_table_item_by_id(semi_info->right_table_id_))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("right table item is null", K(ret)); + } else if (OB_FAIL(push_right_table_ids(right_table, ctx.view_table_id_))) { + LOG_WARN("fail to push back view table id", K(ret)); + } else if (right_table->is_generated_table()) { + if (OB_FAIL(find_basic_table(right_table->ref_query_, ctx.table_id_))) { + LOG_WARN("failed to find basic table", K(ret)); + } + } else { + ctx.table_id_ = semi_info->right_table_id_; + } + if (OB_FAIL(ret) || !right_table_need_add_limit) { /* do nothing */ } else if (OB_FAIL(ObTransformUtils::add_limit_to_semi_right_table(&stmt, ctx_, semi_info))) { LOG_WARN("failed to add limit to semi right table", K(ret), K(stmt)); @@ -1141,8 +1165,32 @@ int ObTransformSemiToInner::do_transform(ObDMLStmt &stmt, LOG_WARN("failed to add from items", K(ret)); } else if (OB_FAIL(find_basic_table(ref_query, ctx.table_id_))) { LOG_WARN("failed to find basic table", K(ret)); - } else if (OB_FAIL(ctx.view_table_id_.push_back(view_table->table_id_))) { - LOG_WARN("fail to push back view table id"); + } else if (OB_FAIL(push_right_table_ids(view_table, ctx.view_table_id_))) { + LOG_WARN("fail to push back view table id", K(ret)); + } + return ret; +} + +int ObTransformSemiToInner::push_right_table_ids(TableItem* right_table, + ObIArray& view_table_ids) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(right_table)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null right table", K(ret)); + } else if (OB_FAIL(view_table_ids.push_back(right_table->table_id_))) { + LOG_WARN("fail to push back view table id", K(ret)); + } else if (right_table->is_generated_table()) { + ObSelectStmt* right_stmt = NULL; + if (OB_ISNULL(right_stmt = right_table->ref_query_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("right stmt is null", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < right_stmt->get_table_items().count(); ++i) { + if (OB_FAIL(push_right_table_ids(right_stmt->get_table_item(i), view_table_ids))) { + LOG_WARN("fail to push back view table id", K(ret), K(i)); + } + } } return ret; } @@ -1250,8 +1298,8 @@ int ObTransformSemiToInner::do_transform_with_aggr(ObDMLStmt& stmt, if (OB_FAIL(ret)) { } else if (OB_FAIL(find_basic_table(ref_query, ctx.table_id_))) { LOG_WARN("failed to find basic table", K(ret)); - } else if (OB_FAIL(ctx.view_table_id_.push_back(view_table->table_id_))) { - LOG_WARN("fail to push back view table id"); + } else if (OB_FAIL(push_right_table_ids(view_table, ctx.view_table_id_))) { + LOG_WARN("fail to push back view table id", K(ret)); } return ret; } @@ -1451,6 +1499,9 @@ int ObTransformSemiToInner::is_expected_plan(ObLogPlan *plan, void *check_ctx, b //do nothing } else if (ctx->is_multi_join_cond_) { is_valid = true; + } else if (ctx->is_non_sens_dul_vals_) { + // duplicate values insensitive will not add DISTINCT, can bypass expected plan check + is_valid = true; } else if (OB_FAIL(find_operator(plan->get_plan_root(), parents, ctx->table_id_, diff --git a/src/sql/rewrite/ob_transform_semi_to_inner.h b/src/sql/rewrite/ob_transform_semi_to_inner.h index 462eacb219..b6405f027d 100644 --- a/src/sql/rewrite/ob_transform_semi_to_inner.h +++ b/src/sql/rewrite/ob_transform_semi_to_inner.h @@ -25,11 +25,13 @@ struct ObCostBasedRewriteCtx { uint64_t table_id_; bool is_multi_join_cond_; bool hint_force_; + bool is_non_sens_dul_vals_; ObSEArray view_table_id_; ObCostBasedRewriteCtx() :table_id_(OB_INVALID_ID), is_multi_join_cond_(false), - hint_force_(false) + hint_force_(false), + is_non_sens_dul_vals_(false) {} }; @@ -50,9 +52,9 @@ protected: private: enum TransformFlag {TO_INNER = 1, TO_AGGR_INNER = 2, TO_INNER_GBY = 4}; struct TransformParam { - TransformParam() : transform_flag_(0), need_add_distinct_(false), need_add_limit_constraint_(false), - right_table_need_add_limit_(false), need_add_gby_(false), cmp_join_cond_(NULL), - cmp_right_expr_(NULL), need_spj_view_(false) {} + TransformParam() : transform_flag_(0), need_add_distinct_(false), + right_table_need_add_limit_(false), need_add_gby_(false), + cmp_join_cond_(NULL), cmp_right_expr_(NULL), need_spj_view_(false) {} void set_transform_flag(TransformFlag flag) { transform_flag_ |= flag; } @@ -62,7 +64,7 @@ private: bool use_inner_gby() { return (transform_flag_ & TO_INNER_GBY) != 0; } - TO_STRING_KV(K_(transform_flag), K_(need_add_distinct), K_(need_add_limit_constraint), K_(right_table_need_add_limit), K_(need_add_gby), K_(need_spj_view), K_(cmp_join_cond), K_(cmp_right_expr)); + TO_STRING_KV(K_(transform_flag), K_(need_add_distinct), K_(right_table_need_add_limit), K_(need_add_gby), K_(need_spj_view), K_(cmp_join_cond), K_(cmp_right_expr)); // record rewrite form, note that rewrite choices are mutually exclusive (select at most one) int64_t transform_flag_; @@ -76,10 +78,6 @@ private: // for INNER form, mark if a distinct view is needed to eliminate possible duplicates bool need_add_distinct_; - // for INNER form, whether const param constraint need to be added to context - // (plan cache only hits for certain const value in LIMIT clause) - bool need_add_limit_constraint_; - bool right_table_need_add_limit_; // for AGGR INNER form, group by clause is needed to deal with equal join conds @@ -136,6 +134,9 @@ private: ObIArray& right_exprs, bool& is_unique); + int push_right_table_ids(TableItem* right_table, + ObIArray& view_table_ids); + int check_semi_join_condition(ObDMLStmt& stmt, SemiInfo& semi_info, ObIArray& equal_left_exprs, @@ -220,10 +221,13 @@ private: int check_is_semi_condition(ObIArray &nl_params, ObIArray & table_ids, bool &is_valid); - int check_hint_valid(const ObDMLStmt &stmt, - const TableItem& table, - bool &force_trans, - bool &force_no_trans) const; + int check_hint_valid(const ObDMLStmt &stmt, + const TableItem& table, + bool &force_trans, + bool &force_no_trans) const; + int non_sens_dul_vals_need_check_cost(ObDMLStmt &stmt, + SemiInfo &semi_info, + bool &need_check_cost); private: DISALLOW_COPY_AND_ASSIGN(ObTransformSemiToInner); }; diff --git a/src/sql/rewrite/ob_transform_simplify_groupby.cpp b/src/sql/rewrite/ob_transform_simplify_groupby.cpp index aca2daaf8a..71be2aff76 100644 --- a/src/sql/rewrite/ob_transform_simplify_groupby.cpp +++ b/src/sql/rewrite/ob_transform_simplify_groupby.cpp @@ -50,6 +50,17 @@ int ObTransformSimplifyGroupby::transform_one_stmt(common::ObIArrayget_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_3_5)) { + // do nothing + } else if (OB_FAIL(remove_redundant_aggr(stmt, is_happened))) { + LOG_WARN("failed to remove redundant by group by expr", K(ret)); + } else { + trans_happened |= is_happened; + OPT_TRACE("remove redundant by group by expr:", is_happened); + LOG_TRACE("succeed to remove redundant by group by expr", K(is_happened)); + } + } if (OB_SUCC(ret)) { if (OB_FAIL(remove_aggr_distinct(stmt, is_happened))) { LOG_WARN("failed to remove aggr distinct", K(ret)); @@ -95,6 +106,15 @@ int ObTransformSimplifyGroupby::transform_one_stmt(common::ObIArray &valid_child_stmts) @@ -212,16 +233,7 @@ int ObTransformSimplifyGroupby::get_valid_child_stmts(ObSelectStmt *upper_stmt, ret = OB_ERR_UNEXPECTED; LOG_WARN("stmt is null", K(ret)); } else if (stmt->is_set_stmt()) { - if (ObSelectStmt::UNION != stmt->get_set_op() - || stmt->is_set_distinct() - || stmt->has_limit()) {//判断条件1 - is_valid = false; - } else { - ObIArray &child_stmts = stmt->get_set_query(); - for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) { - ret = SMART_CALL(get_valid_child_stmts(upper_stmt, child_stmts.at(i), valid_child_stmts)); - } - } + is_valid = false; } else if (!stmt->has_group_by() || stmt->has_rollup() || stmt->has_window_function()//判断条件1 @@ -645,6 +657,231 @@ int ObTransformSimplifyGroupby::remove_group_by_duplicates(ObDMLStmt *&stmt, boo return ret; } +/* remove aggregation functions if the following conditions are met: + * 1. The parameter of the aggregation function can be calculated by group by expr. + * 2. The value of aggregation function of each group can be determined. + */ +int ObTransformSimplifyGroupby::remove_redundant_aggr(ObDMLStmt *stmt, bool &trans_happened) { + int ret = OB_SUCCESS; + ObSelectStmt *select_stmt = NULL; + bool has_rownum = false; + bool is_unique = false; + ObArray new_exprs; + ObArray redundant_aggrs; + trans_happened = false; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("stmt is null", K(ret)); + } else if (OB_ISNULL(ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("ctx_ is null", K(ret)); + } else if (!stmt->is_select_stmt() || + FALSE_IT(select_stmt = static_cast(stmt))) { + } else if (select_stmt->get_group_expr_size() <= 0 || + select_stmt->has_rollup()) { // do not transform stmt containing rollup for now + } else if (OB_FAIL(inner_remove_redundant_aggr(*select_stmt, + redundant_aggrs, + new_exprs, + trans_happened))) { + LOG_WARN("failed to remove redundant aggrs that are determined by group by expr", K(ret)); + } + return ret; +} + +int ObTransformSimplifyGroupby::inner_remove_redundant_aggr( + ObSelectStmt &select_stmt, + ObIArray &redundant_aggrs, + ObIArray &new_exprs, + bool &trans_happened) +{ + int ret = OB_SUCCESS; + ObArray remaining_aggrs; // aggrs that can not be removed + for (int64_t i = 0; OB_SUCC(ret) && i < select_stmt.get_aggr_item_size(); ++i) { + bool can_remove = false; + ObRawExpr *new_expr = NULL; + ObAggFunRawExpr *aggr_expr = select_stmt.get_aggr_item(i); + if (OB_ISNULL(aggr_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null aggr", K(ret)); + } else if (OB_FAIL(check_can_remove_redundant_aggr(select_stmt, *aggr_expr, can_remove))) { + LOG_WARN("failed to check can remove redundant aggr"); + } else if (!can_remove) { + if (OB_FAIL(remaining_aggrs.push_back(aggr_expr))) { + LOG_WARN("failed to push back aggr expr to remaining aggrs", K(ret)); + } + } else if (OB_FAIL(simplify_redundant_aggr(select_stmt, *aggr_expr, new_expr))) { + LOG_WARN("failed to simplify redundant aggr", K(ret)); + } else if (OB_FAIL(new_exprs.push_back(new_expr))) { + LOG_WARN("failed to push back new expr", K(ret)); + } else if (OB_FAIL(redundant_aggrs.push_back(aggr_expr))) { + LOG_WARN("failed to push back redundant aggr", K(ret)); + } + } + // replace redundant aggr exprs, and remove them from aggr_items + if (OB_FAIL(ret) || redundant_aggrs.count() == 0) { // do nothing + } else if (OB_FAIL(select_stmt.replace_relation_exprs(redundant_aggrs, new_exprs))) { + LOG_WARN("failed to replace relation exprs", K(ret), K(select_stmt)); + } else { + // remove simplified aggr exprs from aggr_items of stmt + ObIArray &stmt_aggrs = select_stmt.get_aggr_items(); + if (OB_SUCC(ret)) { + stmt_aggrs.reset(); + if (OB_FAIL(stmt_aggrs.assign(remaining_aggrs))) { + LOG_WARN("failed to assign new aggr items", K(ret)); + } else { + trans_happened = true; + } + } + } + return ret; +} + +int ObTransformSimplifyGroupby::check_can_remove_redundant_aggr( + ObSelectStmt &select_stmt, + ObAggFunRawExpr &aggr_expr, + bool &can_remove) +{ + int ret = OB_SUCCESS; + can_remove = false; + ObItemType func_type = aggr_expr.get_expr_type(); + ObRawExpr *param_expr = NULL; + if (aggr_expr.get_param_count() == 0) { // do not rewrite count(*) + } else if (OB_ISNULL(param_expr = aggr_expr.get_param_expr(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null param of aggr"); + } else { + switch (func_type) { + case T_FUN_MAX: + case T_FUN_MIN: + case T_FUN_MEDIAN: + case T_FUN_SYS_BIT_OR: + case T_FUN_SYS_BIT_AND: { + can_remove = true; + break; + } + case T_FUN_SUM: { + can_remove = aggr_expr.is_param_distinct(); + break; + } + case T_FUN_GROUP_CONCAT: + case T_FUN_COUNT: { + // do not rewrite group_concat and count with multiple parameters for now + can_remove = aggr_expr.is_param_distinct() && (1 == aggr_expr.get_real_param_count()); + break; + } + default: { + break; + } + } + if (!can_remove) { // do nothing + // else, check if aggr parameter is calculable by group by expr + // if not, then the aggr can not be removed + } else if (OB_FAIL(ObOptimizerUtil::expr_calculable_by_exprs(param_expr, + select_stmt.get_group_exprs(), + true, // need_check_contain + true, // used_in_compare + can_remove))) { + LOG_WARN("failed to check if aggr expr can be calculated by group exprs", K(ret), K(aggr_expr)); + } + } + return ret; +} + +int ObTransformSimplifyGroupby::simplify_redundant_aggr( + ObSelectStmt &select_stmt, + ObAggFunRawExpr &aggr_expr, + ObRawExpr *&new_expr) +{ + int ret = OB_SUCCESS; + bool is_not_null = false; + ObItemType func_type = aggr_expr.get_expr_type(); + ObRawExpr *param_expr = aggr_expr.get_param_expr(0); + if (OB_ISNULL(param_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null param of aggr"); + } else { + switch (func_type) { + case T_FUN_MAX: + case T_FUN_MIN: + case T_FUN_MEDIAN: + case T_FUN_SUM: + case T_FUN_GROUP_CONCAT: { + // max/min/median -> expr + // sum/group_concat(distinct expr) -> expr + new_expr = param_expr; + break; + } + case T_FUN_SYS_BIT_OR: + case T_FUN_SYS_BIT_AND: { + // bit_and/bit_or(expr) + // 1. expr is not nullable -> expr + // 2. expr is nullable -> case when expr is not null then expr else uint64_max + ObConstRawExpr *const_u64_max_expr = NULL; + if (OB_FAIL(ObTransformUtils::is_expr_not_null(ctx_, + &select_stmt, + param_expr, + NULLABLE_SCOPE::NS_GROUPBY, + is_not_null))) { + LOG_WARN("failed to check if expr is not null", K(ret), K(aggr_expr)); + } else if (is_not_null) { + new_expr = param_expr; + } else if (OB_FAIL(ObTransformUtils::transform_bit_aggr_to_common_expr(select_stmt, + &aggr_expr, + ctx_, + new_expr))) { + LOG_WARN("failed to transform bit aggr to common expr", KR(ret), K(aggr_expr), + K(func_type), K(select_stmt)); + } + break; + } + case T_FUN_COUNT: { + // count(distinct expr) + // 1. expr is not nullable -> 1 + // 2. expr is nullable -> case when expr is not null then 1 else 0 + ObConstRawExpr *const_one = NULL; + ObConstRawExpr *const_zero = NULL; + if (OB_FAIL(ObTransformUtils::is_expr_not_null(ctx_, + &select_stmt, + param_expr, + NULLABLE_SCOPE::NS_GROUPBY, + is_not_null))) { + LOG_WARN("failed to check if expr is not null", K(ret), K(aggr_expr)); + } else if (OB_FAIL(ObTransformUtils::build_const_expr_for_count(*ctx_->expr_factory_, + 1, + const_one))) { + LOG_WARN("failed to build const one expr", K(ret)); + } else if (is_not_null) { + new_expr = const_one; + } else if (OB_FAIL(ObTransformUtils::build_const_expr_for_count(*ctx_->expr_factory_, + 0, + const_zero))) { + LOG_WARN("failed to build const zero expr", K(ret)); + } else if (OB_FAIL(ObTransformUtils::build_case_when_expr(select_stmt, + param_expr, + const_one, + const_zero, + new_expr, + ctx_))){ + LOG_WARN("failed to build case when expr", K(ret)); + } + break; + } + default: { + break; + } + } + if (OB_SUCC(ret) && !OB_ISNULL(new_expr)) { + if (OB_FAIL(ObTransformUtils::add_cast_for_replace_if_need(*ctx_->expr_factory_, + &aggr_expr, + new_expr, + ctx_->session_info_))) { + LOG_WARN("failed to add cast expr above simplified aggr expr", K(ret)); + } + } + } + return ret; +} + // try to remove distinct in aggr(distinct) and window_function(distinct) int ObTransformSimplifyGroupby::remove_aggr_distinct(ObDMLStmt *stmt, bool &trans_happened) { @@ -982,7 +1219,8 @@ int ObTransformSimplifyGroupby::get_valid_count_aggr(ObSelectStmt *select_stmt, if (OB_ISNULL(aggr = aggrs.at(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect null", K(ret), K(aggr)); - } else if (T_FUN_COUNT != aggr->get_expr_type() || 1 != aggr->get_real_param_exprs().count()) { + } else if (T_FUN_COUNT != aggr->get_expr_type() || + 1 != aggr->get_real_param_exprs().count()) { /* do nothing */ /* count(distinct 1, null) can not convert, count(1, null) do not convert now */ } else if (OB_ISNULL(param = aggr->get_param_expr(0))) { @@ -1875,7 +2113,8 @@ int ObTransformSimplifyGroupby::convert_group_by_to_distinct(ObDMLStmt *stmt, return ret; } -int ObTransformSimplifyGroupby::check_can_convert_to_distinct(ObSelectStmt *stmt, bool &can_convert) { +int ObTransformSimplifyGroupby::check_can_convert_to_distinct(ObSelectStmt *stmt, bool &can_convert) +{ int ret = OB_SUCCESS; bool has_rownum = false; can_convert = false; @@ -1943,4 +2182,432 @@ int ObTransformSimplifyGroupby::check_can_convert_to_distinct(ObSelectStmt *stmt } } return ret; -} \ No newline at end of file +} + +/** + * sum + * | map + * + -------> sum(c1) + count(c1) * const + * c1 const column_expr + * + * 1. the expr to transform must be like "sum(column_expr + const_expr)" (or cast(column_expr)) + * 2. if a column expr appear more than 3 times in such aggr expr, than transform + * + */ +int ObTransformSimplifyGroupby::split_const_in_aggr_func(ObDMLStmt *stmt, bool &trans_happened) { + int ret = OB_SUCCESS; + ObSelectStmt *select_stmt = NULL; + bool is_valid = false; + ObSEArray valid_column_exprs; + ObSEArray existed_sum_exprs; + ObSEArray existed_count_exprs; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("stmt is null", K(ret)); + } else if (!stmt->is_select_stmt() || + FALSE_IT(select_stmt = static_cast(stmt))){ + /*do nothing*/ + } else if (OB_FAIL(get_valid_column_exprs(*select_stmt, + valid_column_exprs, + existed_sum_exprs, + existed_count_exprs))) { + LOG_WARN("failed to fast check", K(ret)); + } else if (valid_column_exprs.count() == 0) { + /* do nothing */ + } else if (OB_FAIL(transform_split_const(*select_stmt, + valid_column_exprs, + existed_sum_exprs, + existed_count_exprs, + trans_happened))) { + LOG_WARN("failed to do transform", K(ret)); + } + return ret; +} + +bool ObTransformSimplifyGroupby::is_numeric(ObObjType type) +{ + bool aggr_is_valid = false; + switch (type) { + case common::ObTinyIntType: + case common::ObSmallIntType: + case common::ObMediumIntType: + case common::ObInt32Type: + case common::ObIntType: + case common::ObNumberType: + case common::ObDecimalIntType: { + aggr_is_valid = true; + break; + } + default: { + aggr_is_valid = false; + } + } + return aggr_is_valid; +} + +bool ObTransformSimplifyGroupby::is_column_or_cast_column_expr(ObRawExpr &expr) +{ + bool is_column = false; + if (expr.is_column_ref_expr() || + (expr.get_expr_type() == T_FUN_SYS_CAST && + expr.get_param_count() == 1 && + expr.get_param_expr(0)->is_column_ref_expr())) { + is_column = true; + } + return is_column; +} + +int ObTransformSimplifyGroupby::get_column_and_const_expr( + ObRawExpr *expr, + ObRawExpr *&column_expr, + ObRawExpr *&const_expr, + bool &is_add, + bool &column_is_left) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (expr->get_expr_type() == T_OP_ADD || + expr->get_expr_type() == T_OP_MINUS) { + ObRawExpr *left_expr = NULL; + ObRawExpr *right_expr = NULL; + if (expr->get_param_count() != 2 || + OB_ISNULL(left_expr = expr->get_param_expr(0)) || + OB_ISNULL(right_expr = expr->get_param_expr(1))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if ((!left_expr->is_const_expr() && !right_expr->is_const_expr()) || + (!is_column_or_cast_column_expr(*left_expr) && !is_column_or_cast_column_expr(*right_expr))) { + column_expr = NULL; + const_expr = NULL; + } else { + is_add = expr->get_expr_type() == T_OP_ADD; + if (is_column_or_cast_column_expr(*left_expr)) { + column_is_left = true; + column_expr = left_expr; + const_expr = right_expr; + } else { + column_is_left = false; + column_expr = right_expr; + const_expr = left_expr; + } + } + } else { + if (is_column_or_cast_column_expr(*expr)) { + column_expr = expr; + } else { + column_expr = NULL; + } + const_expr = NULL; + } + return ret; +} + +int ObTransformSimplifyGroupby::check_aggr_validity(ObAggFunRawExpr &aggr_expr, + ObRawExpr *&column_expr, + ObRawExpr *&const_expr, + bool &is_valid) +{ + int ret = OB_SUCCESS; + ObRawExpr *param_expr = NULL; + bool is_add = false; + bool column_is_left = false; + is_valid = false; + if (aggr_expr.get_expr_type() != T_FUN_SUM || + aggr_expr.is_param_distinct() || + aggr_expr.get_param_count() != 1) { + is_valid = false; + } else if (OB_ISNULL(param_expr = aggr_expr.get_param_expr(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (!is_numeric(param_expr->get_data_type())) { + is_valid = false; + } else if (OB_FAIL(get_column_and_const_expr( + param_expr, column_expr, const_expr, is_add, column_is_left))) { + LOG_WARN("failed to get column and const expr", K(ret)); + } else if (column_expr == NULL) { + is_valid = false; + } else { + is_valid = true; + } + return ret; +} + +/** + * step 1: check aggr validity + * step 2: count appear times of column expr + * step 3: check all count expr. for example, "sum(c1) + count(c1) + sum(c1 + 1)", should take use of "count(c1)" + * step 4: extract all column expr to rewrite + */ +int ObTransformSimplifyGroupby::get_valid_column_exprs( + ObSelectStmt &select_stmt, + ObIArray &valid_column_exprs, + ObIArray &existed_sum_exprs, + ObIArray &existed_count_exprs) +{ + int ret = OB_SUCCESS; + ObSEArray column_exprs; + ObSEArray column_count; + ObSEArray exist_column_only; /* whether expr like "sum(column_expr)" already exist */ + ObSEArray sum_exprs; + ObSEArray count_exprs; + for (int64_t i = 0; OB_SUCC(ret) && i < select_stmt.get_aggr_item_size(); ++i) { + ObAggFunRawExpr *aggr_expr = select_stmt.get_aggr_item(i); + ObRawExpr *column_expr = NULL; + ObRawExpr *const_expr = NULL; + bool is_valid = false; + // step 1: check aggr validity + if (OB_ISNULL(aggr_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(check_aggr_validity(*aggr_expr, column_expr, const_expr, is_valid))) { + LOG_WARN("failed to check aggr_validity", K(ret)); + } else if (!is_valid || OB_ISNULL(column_expr)) { + /* do nothing */ + } else { + // step 2: count appear times of column expr + // column only expr (expr like "sum(column_expr)") only count once and record in sum_exprs + bool is_column_only = (const_expr == NULL); + ObAggFunRawExpr *sum_expr = is_column_only ? aggr_expr : NULL; + int64_t idx = -1; + if (OB_FAIL(ObTransformUtils::get_expr_idx(column_exprs, column_expr, idx))) { + LOG_WARN("failed to get expr idx", K(ret)); + } else if (idx == -1) { + if (OB_FAIL(column_exprs.push_back(column_expr)) || + OB_FAIL(column_count.push_back(1)) || + OB_FAIL(exist_column_only.push_back(is_column_only)) || + OB_FAIL(sum_exprs.push_back(sum_expr)) || + OB_FAIL(count_exprs.push_back(NULL))) { + LOG_WARN("failed to push back", K(ret)); + } + } else { + if (is_column_only) { + if (!exist_column_only.at(idx)) { + column_count.at(idx)++; + exist_column_only.at(idx) = true; + sum_exprs.at(idx) = sum_expr; + } + } else { + column_count.at(idx)++; + } + } + } + } + + // step 3 + for (int64_t i = 0; OB_SUCC(ret) && i < column_exprs.count(); ++i) { + bool found = (count_exprs.at(i) != NULL); + for (int64_t j = 0; OB_SUCC(ret) && !found && j < select_stmt.get_aggr_item_size(); ++j) { + ObAggFunRawExpr *aggr_expr = select_stmt.get_aggr_item(j); + if (OB_ISNULL(aggr_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (aggr_expr->get_expr_type() == T_FUN_COUNT && + aggr_expr->get_param_count() == 1 && + aggr_expr->get_param_expr(0) == column_exprs.at(i)) { + found = true; + count_exprs.at(i) = aggr_expr; + column_count.at(i)++; + } + } + } + + valid_column_exprs.reset(); + for (int64_t i = 0; OB_SUCC(ret) && i < column_exprs.count(); ++i) { + if (column_count.at(i) > 2) { + if (OB_FAIL(valid_column_exprs.push_back(column_exprs.at(i))) || + OB_FAIL(existed_sum_exprs.push_back(sum_exprs.at(i))) || + OB_FAIL(existed_count_exprs.push_back(count_exprs.at(i)))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + return ret; +} + +int ObTransformSimplifyGroupby::get_split_result_expr( + ObSelectStmt &select_stmt, + ObAggFunRawExpr *aggr_expr, + ObAggFunRawExpr *&sum_expr, + ObAggFunRawExpr *&count_expr, + ObRawExpr *&result_expr) +{ + int ret = OB_SUCCESS; + ObRawExpr *param_expr = NULL; + ObRawExpr *column_expr = NULL; + ObRawExpr *const_expr = NULL; + bool is_add = false; + bool column_is_left = false; + if (OB_ISNULL(aggr_expr) || OB_ISNULL(ctx_) || + OB_ISNULL(ctx_->expr_factory_) || OB_ISNULL(ctx_->session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (aggr_expr->get_param_count() != 1 || + OB_ISNULL(param_expr = aggr_expr->get_param_expr(0))) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid aggr_expr", K(aggr_expr), K(ret)); + } else if (OB_FAIL(get_column_and_const_expr( + param_expr, column_expr, const_expr, is_add, column_is_left))) { + LOG_WARN("failed to get column and const expr", K(ret)); + } else if (OB_ISNULL(column_expr) || OB_ISNULL(const_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } + + if (OB_SUCC(ret) && sum_expr == NULL) { + if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(*ctx_->expr_factory_, + ctx_->session_info_, + T_FUN_SUM, + column_expr, + sum_expr))) { + LOG_WARN("failed to build common aggr expr", K(ret)); + } else if (OB_ISNULL(sum_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(select_stmt.add_agg_item(*sum_expr))) { + LOG_WARN("failed to add agg item", K(ret)); + } + } + if (OB_SUCC(ret) && count_expr == NULL) { + if (OB_FAIL(ObRawExprUtils::build_common_aggr_expr(*ctx_->expr_factory_, + ctx_->session_info_, + T_FUN_COUNT, + column_expr, + count_expr))) { + LOG_WARN("failed to build common aggr expr", K(ret)); + } else if (OB_ISNULL(count_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(select_stmt.add_agg_item(*count_expr))) { + LOG_WARN("failed to add agg item", K(ret)); + } + } + + if (OB_SUCC(ret)) { + ObExprResType res_type = aggr_expr->get_result_type(); + ObRawExpr *casted_const_expr = NULL; + ObOpRawExpr *mul_expr = NULL; /* count(column) * const */ + ObOpRawExpr *upper_expr = NULL; /* add expr or minus expr */ + ObRawExpr *casted_upper_expr = NULL; + if (OB_FAIL(ObRawExprUtils::try_add_cast_expr_above( + ctx_->expr_factory_, ctx_->session_info_, *const_expr, res_type, casted_const_expr))) { + LOG_WARN("failed to add cast", K(ret)); + } else if (OB_ISNULL(casted_const_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("casted const expr is null", K(ret)); + } else if (OB_FAIL(ObRawExprUtils::build_mul_expr( + *ctx_->expr_factory_, count_expr, casted_const_expr, mul_expr))) { + LOG_WARN("failed to build mul expr", K(ret)); + } else if (OB_ISNULL(mul_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("count mul const expr is null", K(ret)); + } else { + if (is_add) { + if (OB_FAIL(ObRawExprUtils::build_add_expr( + *ctx_->expr_factory_, sum_expr, mul_expr, upper_expr))) { + LOG_WARN("failed to build add expr", K(ret)); + } + } else if (column_is_left) { + if (OB_FAIL(ObRawExprUtils::build_minus_expr( + *ctx_->expr_factory_, sum_expr, mul_expr, upper_expr))) { + LOG_WARN("failed to build add expr", K(ret)); + } + } else /* column is right child*/ { + if (OB_FAIL(ObRawExprUtils::build_minus_expr( + *ctx_->expr_factory_, mul_expr, sum_expr, upper_expr))) { + LOG_WARN("failed to build add expr", K(ret)); + } + } + } + if (OB_FAIL(ret)){ + } else if (OB_ISNULL(upper_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("add expr is null", K(ret)); + } else if (OB_FAIL(upper_expr->formalize(ctx_->session_info_))) { + LOG_WARN("failed to formalize", K(ret)); + } else if (FALSE_IT(casted_upper_expr = upper_expr)) { + } else if (OB_FAIL(ObTransformUtils::add_cast_for_replace_if_need(*ctx_->expr_factory_, + aggr_expr, + casted_upper_expr, + ctx_->session_info_))) { + LOG_WARN("failed to add cast", K(ret)); + } else { + result_expr = casted_upper_expr; + } + } + return ret; +} + +int ObTransformSimplifyGroupby::transform_split_const( + ObSelectStmt &select_stmt, + ObIArray &valid_column_exprs, + ObIArray &sum_exprs, + ObIArray &count_exprs, + bool &trans_happened) +{ + int ret = OB_SUCCESS; + ObSEArray src_exprs; + ObSEArray dst_exprs; + trans_happened = false; + if (OB_ISNULL(ctx_) || OB_ISNULL(ctx_->session_info_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(count_exprs.reserve(sum_exprs.count()))) { + LOG_WARN("failed to reserve count exprs", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < sum_exprs.count(); ++i) { + if (OB_FAIL(count_exprs.push_back(NULL))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + + for (int64_t i = 0; OB_SUCC(ret) && i < select_stmt.get_aggr_item_size(); ++i) { + ObAggFunRawExpr *aggr_expr = select_stmt.get_aggr_item(i); + ObRawExpr *column_expr = NULL; + ObRawExpr *const_expr = NULL; + ObRawExpr *result_expr = NULL; + bool is_valid = false; + if (OB_ISNULL(aggr_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(check_aggr_validity(*aggr_expr, column_expr, const_expr, is_valid))) { + LOG_WARN("failed to check aggr_validity", K(ret)); + } else if (!is_valid || OB_ISNULL(column_expr) || const_expr == NULL || + !is_contain(valid_column_exprs, column_expr)) { + /* do nothing */ + } else { + int64_t idx = -1; + if (OB_FAIL(ObTransformUtils::get_expr_idx(valid_column_exprs, column_expr, idx))) { + LOG_WARN("failed to get expr idx", K(ret)); + } else if (idx == -1) { + /* do nothing */ + } else if (OB_FAIL(get_split_result_expr(select_stmt, + aggr_expr, + sum_exprs.at(idx), + count_exprs.at(idx), + result_expr))) { + LOG_WARN("failed to get split result expr", K(ret)); + } else if (OB_ISNULL(result_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(src_exprs.push_back(aggr_expr)) || + OB_FAIL(dst_exprs.push_back(result_expr))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + + if (OB_FAIL(ret)) { + } else if (OB_FAIL(select_stmt.replace_relation_exprs(src_exprs, dst_exprs))) { + LOG_WARN("failed to replace relation exprs", K(ret)); + } else if (OB_FAIL(select_stmt.formalize_stmt(ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt", K(ret)); + } else { + trans_happened = true; + } + return ret; +} + +// end of split const expr in aggr expr \ No newline at end of file diff --git a/src/sql/rewrite/ob_transform_simplify_groupby.h b/src/sql/rewrite/ob_transform_simplify_groupby.h index a73d0b1029..0c0191a1b3 100644 --- a/src/sql/rewrite/ob_transform_simplify_groupby.h +++ b/src/sql/rewrite/ob_transform_simplify_groupby.h @@ -63,6 +63,17 @@ private: int check_stmt_group_by_can_be_removed(ObSelectStmt *select_stmt, bool &can_be); int inner_remove_stmt_group_by(ObSelectStmt *select_stmt, bool &trans_happened); int remove_group_by_duplicates(ObDMLStmt *&stmt, bool &trans_happened); + int remove_redundant_aggr(ObDMLStmt *stmt, bool &trans_happened); + int inner_remove_redundant_aggr(ObSelectStmt &select_stmt, + ObIArray &aggrs_to_remove, + ObIArray &new_exprs, + bool &trans_happened); + int check_can_remove_redundant_aggr(ObSelectStmt &select_stmt, + ObAggFunRawExpr &aggr_expr, + bool &can_remove); + int simplify_redundant_aggr(ObSelectStmt &select_stmt, + ObAggFunRawExpr &aggr_expr, + ObRawExpr *&new_expr); int remove_aggr_distinct(ObDMLStmt *stmt, bool &trans_happened); int remove_aggr_duplicates(ObSelectStmt *select_stmt); int remove_win_func_duplicates(ObSelectStmt *select_stmt); @@ -110,6 +121,39 @@ private: ObIArray &vaild_having_exprs); int convert_group_by_to_distinct(ObDMLStmt *stmt, bool &trans_happened); int check_can_convert_to_distinct(ObSelectStmt *stmt, bool &can_convert); + + /** + * @brief: this function is for rewrite a bench mark scenario: + * select sum(2 * c1 + 4) from t1; + * to: + * select 2 * sum(c1) + 4 * count(c1) from t1; + */ + int split_const_in_aggr_func(ObDMLStmt * stmt, bool &trans_happened); + bool is_numeric(ObObjType type); + bool is_column_or_cast_column_expr(ObRawExpr &expr); + int check_aggr_validity(ObAggFunRawExpr &agg_expr, + ObRawExpr *&column_expr, + ObRawExpr *&const_expr, + bool &is_valid); + int get_column_and_const_expr(ObRawExpr *expr, + ObRawExpr *&column_expr, + ObRawExpr *&const_expr, + bool &is_add, + bool &column_is_left); + int get_split_result_expr(ObSelectStmt &select_stmt, + ObAggFunRawExpr *aggr_expr, + ObAggFunRawExpr *&sum_expr, + ObAggFunRawExpr *&count_expr, + ObRawExpr *&result_expr); + int get_valid_column_exprs(ObSelectStmt &select_stmt, + common::ObIArray &valid_column_exprs, + common::ObIArray &existed_sum_exprs, + common::ObIArray &existed_count_exprs); + int transform_split_const(ObSelectStmt &select_stmt, + common::ObIArray &valid_column_exprs, + common::ObIArray &sum_exprs, + common::ObIArray &count_exprs, + bool &trans_happened); }; } diff --git a/src/sql/rewrite/ob_transform_simplify_subquery.cpp b/src/sql/rewrite/ob_transform_simplify_subquery.cpp index 896670d5c8..758446ece6 100644 --- a/src/sql/rewrite/ob_transform_simplify_subquery.cpp +++ b/src/sql/rewrite/ob_transform_simplify_subquery.cpp @@ -687,17 +687,28 @@ int ObTransformSimplifySubquery::recursive_add_limit_for_exists_expr(ObRawExpr * ObSelectStmt *subquery = NULL; ObOpRawExpr *op = static_cast(expr); ObQueryRefRawExpr *subq_expr = static_cast(op->get_param_expr(0)); + bool has_limit_1 = true; + bool has_invalid_limit = true; if (OB_ISNULL(subq_expr) || OB_ISNULL(subquery = subq_expr->get_ref_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null ptr", K(ret), K(subq_expr), K(subquery)); - } else if (!subquery->has_limit() && !subquery->is_contains_assignment()) { - if (OB_FAIL(ObTransformUtils::set_limit_expr(subquery, ctx_))) { - LOG_WARN("add limit expr failed", K(*subquery), K(ret)); - } else { - trans_happened = true; - } + } else if (subquery->is_contains_assignment()) { + // do nothing + } else if (OB_FAIL(check_has_limit_1(subquery, has_limit_1))) { + LOG_WARN("failed to check subquery has limit 1", K(ret)); + } else if (has_limit_1) { + // do nothing, already has limit 1 + } else if (OB_FAIL(check_limit(expr->get_expr_type(), subquery, has_invalid_limit))) { + LOG_WARN("failed to check subquery has limit", K(ret)); + } else if (has_invalid_limit) { + // do nothing + } else if (!has_invalid_limit && NULL != subquery->get_limit_expr() && + OB_FAIL(ObTransformUtils::add_compare_int_constraint(ctx_, subquery->get_limit_expr(), T_OP_GE, 1))) { + LOG_WARN("failed to add const param constraints", K(ret)); + } else if (OB_FAIL(ObTransformUtils::set_limit_expr(subquery, ctx_))) { + LOG_WARN("add limit expr failed", KPC(subquery), K(ret)); } else { - /*do nothing*/ + trans_happened = true; } } } @@ -710,6 +721,7 @@ int ObTransformSimplifySubquery::transform_any_all(ObDMLStmt *stmt, bool &trans_ int ret = OB_SUCCESS; bool is_happened = false; ObSEArray relation_expr_pointers; + trans_happened = false; if (OB_ISNULL(stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("stmt is NULL", K(ret)); @@ -1132,6 +1144,7 @@ int ObTransformSimplifySubquery::transform_exists_query(ObDMLStmt *stmt, bool &t { int ret = OB_SUCCESS; ObSEArray relation_expr_pointers; + trans_happened = false; if (OB_ISNULL(stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("stmt is NULL", K(ret)); @@ -1261,16 +1274,28 @@ int ObTransformSimplifySubquery::eliminate_subquery(ObDMLStmt *stmt, LOG_WARN("failed to do trans empty table subquery as expr", K(ret)); } LOG_TRACE("finish to eliminate empty table subquery", K(ret)); - } else if (!can_be_eliminated) { - if (OB_FAIL(simplify_select_items(stmt, expr->get_expr_type(), subquery, false, trans_happened))) { + } else { + bool is_happened = false; + if (OB_FAIL(simplify_select_items(stmt, expr->get_expr_type(), subquery, false, is_happened))) { LOG_WARN("Simplify select items in EXISTS fails", K(ret)); - } else if (OB_FAIL(eliminate_groupby_in_exists(stmt, expr->get_expr_type(), - subquery, trans_happened))) { - LOG_WARN("Subquery elimination of group by in EXISTS fails", K(ret)); - //EXISTS, NOT EXISTS子查询中的order by可以消除 - } else if (subquery->get_order_items().count() > 0) { + } else if (is_happened) { + trans_happened |= is_happened; + LOG_TRACE("simplify select item happened", K(is_happened), K(trans_happened)); + } + if (OB_SUCC(ret)) { + is_happened = false; + if (OB_FAIL(eliminate_groupby_in_exists(stmt, expr->get_expr_type(), + subquery, is_happened))) { + LOG_WARN("Subquery elimination of group by in EXISTS fails", K(ret)); + } else if (is_happened) { + trans_happened |= is_happened; + LOG_TRACE("eliminate group by in exists happened", K(is_happened), K(trans_happened)); + } + } + if (OB_SUCC(ret) && subquery->get_order_items().count() > 0) { trans_happened = true; subquery->get_order_items().reset(); + LOG_TRACE("eliminate order by in exists happened", K(trans_happened)); } if (OB_SUCC(ret) && trans_happened) { subq_expr->set_output_column(subquery->get_select_item_size()); @@ -1375,7 +1400,17 @@ int ObTransformSimplifySubquery::select_items_can_be_simplified(const ObItemType stmt->get_select_item(0).expr_->is_const_raw_expr()) { // do nothing } else { - can_be_simplified = true; + bool is_all_const = true; + for (int64_t i = 0; OB_SUCC(ret) && is_all_const && i < stmt->get_select_item_size(); ++i) { + if (OB_ISNULL(stmt->get_select_item(i).expr_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("select item expr is null", K(ret)); + } else if (!stmt->get_select_item(i).expr_->is_const_raw_expr()) { + is_all_const = false; + } + } + // select_list is all const raw expr, do not simplify. otherwise it will rewrite not iter. + can_be_simplified = !is_all_const; } return ret; } @@ -1397,9 +1432,9 @@ int ObTransformSimplifySubquery::groupby_can_be_eliminated_in_exists(const ObIte // Only non-set stmt will be eliminated and do nothing for other DML stmts: // 1. set -> No elimination // 2. select 1 + floor(2) (table_size == 0) -> No elimination - } else if (stmt->has_group_by() - && 0 == stmt->get_aggr_item_size() - && !stmt->has_having()){ // No having, no limit, no aggr + } else if (0 < stmt->get_group_expr_size() && + 0 == stmt->get_aggr_item_size() && + !stmt->has_having()) { // No having, no limit, no aggr bool has_limit = false; if (OB_FAIL(check_limit(op_type, stmt, has_limit))) { LOG_WARN("failed to check subquery has unremovable limit", K(ret)); @@ -1410,48 +1445,44 @@ int ObTransformSimplifySubquery::groupby_can_be_eliminated_in_exists(const ObIte return ret; } -int ObTransformSimplifySubquery::groupby_can_be_eliminated_in_any_all(const ObSelectStmt *stmt, - bool &can_be_eliminated) const +// 当Any/all/in(subq)满足以下所有条件时,可消除group by子句: +// 1. 当前stmt不是set stmt +// 2. 没有having子句 +// 3. 没有limit子句 +// 4. 无聚集函数(select item中) +// 5. 非常量select item列,全部包含在group exprs中 +int ObTransformSimplifySubquery::eliminate_groupby_in_any_all(ObSelectStmt *stmt, + bool &trans_happened) { int ret = OB_SUCCESS; - can_be_eliminated = false; - // 当Any/all/in(subq)满足以下所有条件时,可消除group by子句: - // 1. 当前stmt不是set stmt - // 2. 没有having子句 - // 3. 没有limit子句 - // 4. 无聚集函数(select item中) - // 5. 非常量select item列,全部包含在group exprs中 - if (OB_ISNULL(stmt) || OB_ISNULL(stmt->get_query_ctx())) { + ObRawExpr *s_expr = NULL; + bool all_in_group_exprs = true; + trans_happened = false; + if (OB_ISNULL(stmt)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("stmt is NULL", K(ret)); - } else if (0 == stmt->get_table_size() || stmt->is_set_stmt()) { - // Only non-set stmt will be eliminated and do nothing for other DML stmts: - // 1. set -> No elimination - // 2. select 1 + floor(2) (table_size == 0) -> No elimination - } else if (stmt->is_values_table_query() && - !ObTransformUtils::is_enable_values_table_rewrite(stmt->get_query_ctx()->optimizer_features_enable_version_)) { + } else if (0 == stmt->get_table_size() || + stmt->is_set_stmt() || + 0 == stmt->get_group_expr_size() || + stmt->has_having() || + stmt->has_limit() || + 0 != stmt->get_aggr_item_size()) { /* do nothing */ - } else if (stmt->has_group_by() - && !stmt->has_having() - && !stmt->has_limit() - && 0 == stmt->get_aggr_item_size()) { - // Check if select list is involved in group exprs - ObRawExpr *s_expr = NULL; - bool all_in_group_exprs = true; + } else { for (int i = 0; OB_SUCC(ret) && all_in_group_exprs && i < stmt->get_select_item_size(); ++i) { if (OB_ISNULL(s_expr = stmt->get_select_item(i).expr_)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("select list expr is NULL", K(ret)); - } else if ((s_expr)->has_flag(CNT_COLUMN)) { - if (!ObOptimizerUtil::find_item(stmt->get_group_exprs(), s_expr)) { - all_in_group_exprs = false; - } else { /* do nothing */ } + } else if (s_expr->has_flag(CNT_COLUMN) && + !ObOptimizerUtil::find_item(stmt->get_group_exprs(), s_expr)) { + all_in_group_exprs = false; } else { /* do nothing */ } - } // for - if (OB_SUCCESS == ret && all_in_group_exprs) { - can_be_eliminated = true; - } else { /* do nothing */ } - } else { /* do nothing */ } + } + if (OB_SUCC(ret) && all_in_group_exprs) { + stmt->get_group_exprs().reset(); + trans_happened = true; + } + } return ret; } @@ -1462,7 +1493,7 @@ int ObTransformSimplifySubquery::eliminate_subquery_in_exists(ObDMLStmt *stmt, int ret = OB_SUCCESS; ObRawExprFactory *expr_factory = NULL; ObSelectStmt *subquery = NULL; - bool add_limit_constraint = false; + bool has_invalid_limit = false; if (OB_ISNULL(expr) || OB_ISNULL(ctx_) || OB_ISNULL(expr_factory = ctx_->expr_factory_) || OB_ISNULL(stmt) || OB_ISNULL(stmt->get_query_ctx())) { ret = OB_ERR_UNEXPECTED; @@ -1479,10 +1510,10 @@ int ObTransformSimplifySubquery::eliminate_subquery_in_exists(ObDMLStmt *stmt, } else if (subquery->is_values_table_query() && !ObTransformUtils::is_enable_values_table_rewrite(stmt->get_query_ctx()->optimizer_features_enable_version_)) { /* do nothing */ //Just in case different parameters hit same plan, firstly we need add const param constraint - } else if (OB_FAIL(need_add_limit_constraint(expr->get_expr_type(), subquery, add_limit_constraint))){ + } else if (OB_FAIL(check_limit(expr->get_expr_type(), subquery, has_invalid_limit))){ LOG_WARN("failed to check limit constraints", K(ret)); - } else if (add_limit_constraint && - OB_FAIL(ObTransformUtils::add_const_param_constraints(subquery->get_limit_expr(), ctx_))) { + } else if (!has_invalid_limit && NULL != subquery->get_limit_expr() && + OB_FAIL(ObTransformUtils::add_compare_int_constraint(ctx_, subquery->get_limit_expr(), T_OP_GE, 1))) { LOG_WARN("failed to add const param constraints", K(ret)); } else if (OB_FAIL(ObOptimizerUtil::remove_item(stmt->get_subquery_exprs(), subq_expr))) { LOG_WARN("remove expr failed", K(ret)); @@ -1510,104 +1541,101 @@ int ObTransformSimplifySubquery::simplify_select_items(ObDMLStmt *stmt, bool parent_is_set_query, bool &trans_happened) { - int ret = OB_SUCCESS; + int ret = OB_SUCCESS; + bool has_limit = false; + ObRawExprFactory *expr_factory = NULL; + bool can_be_simplified = false; + if (OB_ISNULL(subquery) || OB_ISNULL(stmt) || OB_ISNULL(ctx_) || + OB_ISNULL(expr_factory = ctx_->expr_factory_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("NULL pointer Error", KP(subquery), KP_(ctx), KP(expr_factory), K(ret)); + } else if (OB_FAIL(select_items_can_be_simplified(op_type, + subquery, + can_be_simplified))) { + LOG_WARN("Checking if select list can be eliminated in subquery failed", K(ret)); + } else if (!can_be_simplified) { + //do nothing + } else if (ObSelectStmt::UNION == subquery->get_set_op() && !subquery->is_recursive_union()) { + const ObIArray &child_stmts = subquery->get_set_query(); + for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) { + ObSelectStmt *child = child_stmts.at(i); + if (OB_FAIL(SMART_CALL(simplify_select_items(stmt, op_type, child, true, trans_happened)))) { + LOG_WARN("Simplify select list in EXISTS fails", K(ret)); + } + } + ObExprResType res_type; + res_type.set_type(ObIntType); + for(int64_t i = 0; OB_SUCC(ret) && i < subquery->get_select_item_size(); i++) { + SelectItem &select_item = subquery->get_select_item(i); + if(OB_ISNULL(select_item.expr_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null select expr", K(ret), K(select_item)); + } else { + select_item.expr_->set_result_type(res_type); + } + } bool has_limit = false; - ObRawExprFactory *expr_factory = NULL; - bool can_be_simplified = false; - if (OB_ISNULL(subquery) || OB_ISNULL(stmt) || OB_ISNULL(ctx_) || - OB_ISNULL(expr_factory = ctx_->expr_factory_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("NULL pointer Error", KP(subquery), KP_(ctx), KP(expr_factory), K(ret)); - } else if (OB_FAIL(select_items_can_be_simplified(op_type, - subquery, - can_be_simplified))) { - LOG_WARN("Checking if select list can be eliminated in subquery failed", K(ret)); - } else if (!can_be_simplified) { - //do nothing - } else if (ObSelectStmt::UNION == subquery->get_set_op() && !subquery->is_recursive_union()) { - const ObIArray &child_stmts = subquery->get_set_query(); - for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) { - ObSelectStmt *child = child_stmts.at(i); - if (OB_FAIL(SMART_CALL(simplify_select_items(stmt, op_type, child, true, trans_happened)))) { - LOG_WARN("Simplify select list in EXISTS fails", K(ret)); - } - } - ObExprResType res_type; - res_type.set_type(ObIntType); - for(int64_t i = 0; OB_SUCC(ret) && i < subquery->get_select_item_size(); i++) { - SelectItem &select_item = subquery->get_select_item(i); - if(OB_ISNULL(select_item.expr_)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null select expr", K(ret), K(select_item)); - } else { - select_item.expr_->set_result_type(res_type); - } - } - bool has_limit = false; - bool add_limit_constraint = false; - if (OB_FAIL(ret)){ - - } else if (OB_FAIL(check_limit(op_type, subquery, has_limit))) { - LOG_WARN("failed to check subquery has unremovable limit", K(ret)); - } else if(OB_FAIL(need_add_limit_constraint(op_type, subquery, add_limit_constraint))){ - LOG_WARN("failed to check limit constraints", K(ret)); - } else if(add_limit_constraint && - OB_FAIL(ObTransformUtils::add_const_param_constraints(subquery->get_limit_expr(), ctx_))) { - LOG_WARN("failed to add const param constraints", K(ret)); - } else if (!has_limit) { - subquery->assign_set_all(); - } - } else { - // Add single select item with const int 1 - int64_t const_value = 1; - ObSEArray aggr_items_in_having; - int max_select_item_size = parent_is_set_query ? subquery->get_select_item_size() : 1; - subquery->clear_select_item(); - //save aggr item in having - subquery->clear_aggr_item(); - if (OB_FAIL(ObTransformUtils::extract_aggr_expr(subquery->get_having_exprs(),aggr_items_in_having))) { - LOG_WARN("failed to get aggr items", K(ret)); - } else if (OB_FAIL(append_array_no_dup(subquery->get_aggr_items(),aggr_items_in_having))) { - LOG_WARN("failed to remove item", K(ret)); - } - // Clear distinct flag - subquery->assign_all(); - //reset window function - subquery->get_window_func_exprs().reset(); - for(int64_t i = 0; OB_SUCC(ret) && i < max_select_item_size; i++) { - ObConstRawExpr *c_expr = NULL; - if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*expr_factory, ObIntType, - const_value, c_expr))) { - LOG_WARN("failed to create expr", K(ret)); - } else if (OB_ISNULL(c_expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("create expr error in simplify select item", K(c_expr), K(ret)); - } else if (OB_FAIL(c_expr->formalize(ctx_->session_info_))) { - LOG_WARN("failed to formalize a new expr", K(ret)); - } else { - SelectItem select_item; - select_item.alias_name_ = "1"; - select_item.expr_name_ = "1"; - select_item.expr_ = c_expr; - if (OB_FAIL(subquery->add_select_item(select_item))) { - LOG_WARN("Failed to add select item", K(select_item), K(ret)); - //Just in case different parameters hit same plan,firstly we need add const param constraint - } else { - trans_happened = true; - } - } - } - bool add_limit_constraint = false; - if (OB_FAIL(ret)) { - - } else if(OB_FAIL(need_add_limit_constraint(op_type, subquery, add_limit_constraint))){ - LOG_WARN("failed to check limit constraints", K(ret)); - } else if(add_limit_constraint && - OB_FAIL(ObTransformUtils::add_const_param_constraints(subquery->get_limit_expr(), ctx_))) { - LOG_WARN("failed to add const param constraints", K(ret)); + if (OB_FAIL(ret)){ + // do nothing + } else if (OB_FAIL(check_limit(op_type, subquery, has_limit))) { + LOG_WARN("failed to check subquery has unremovable limit", K(ret)); + } else if(!has_limit && NULL != subquery->get_limit_expr() && + OB_FAIL(ObTransformUtils::add_compare_int_constraint(ctx_, subquery->get_limit_expr(), T_OP_GE, 1))) { + LOG_WARN("failed to add const param constraints", K(ret)); + } else if (!has_limit) { + subquery->assign_set_all(); + } + } else { + // Add single select item with const int 1 + int64_t const_value = 1; + ObSEArray aggr_items_in_having; + int max_select_item_size = parent_is_set_query ? subquery->get_select_item_size() : 1; + subquery->clear_select_item(); + //save aggr item in having + subquery->clear_aggr_item(); + if (OB_FAIL(ObTransformUtils::extract_aggr_expr(subquery->get_having_exprs(),aggr_items_in_having))) { + LOG_WARN("failed to get aggr items", K(ret)); + } else if (OB_FAIL(append_array_no_dup(subquery->get_aggr_items(),aggr_items_in_having))) { + LOG_WARN("failed to remove item", K(ret)); + } + // Clear distinct flag + subquery->assign_all(); + //reset window function + subquery->get_window_func_exprs().reset(); + for(int64_t i = 0; OB_SUCC(ret) && i < max_select_item_size; i++) { + ObConstRawExpr *c_expr = NULL; + if (OB_FAIL(ObRawExprUtils::build_const_int_expr(*expr_factory, ObIntType, + const_value, c_expr))) { + LOG_WARN("failed to create expr", K(ret)); + } else if (OB_ISNULL(c_expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("create expr error in simplify select item", K(c_expr), K(ret)); + } else if (OB_FAIL(c_expr->formalize(ctx_->session_info_))) { + LOG_WARN("failed to formalize a new expr", K(ret)); + } else { + SelectItem select_item; + select_item.alias_name_ = "1"; + select_item.expr_name_ = "1"; + select_item.expr_ = c_expr; + if (OB_FAIL(subquery->add_select_item(select_item))) { + LOG_WARN("Failed to add select item", K(select_item), K(ret)); + //Just in case different parameters hit same plan,firstly we need add const param constraint + } else { + trans_happened = true; } } - return ret; + } + bool has_invalid_limit = false; + if (OB_FAIL(ret)) { + // do nothing + } else if(OB_FAIL(check_limit(op_type, subquery, has_invalid_limit))) { + LOG_WARN("failed to check limit constraints", K(ret)); + } else if(!has_invalid_limit && NULL != subquery->get_limit_expr() && + OB_FAIL(ObTransformUtils::add_compare_int_constraint(ctx_, subquery->get_limit_expr(), T_OP_GE, 1))) { + LOG_WARN("failed to add const param constraints", K(ret)); + } + } + return ret; } int ObTransformSimplifySubquery::eliminate_groupby_in_exists(ObDMLStmt *stmt, const ObItemType op_type, @@ -1635,56 +1663,35 @@ int ObTransformSimplifySubquery::eliminate_groupby_in_exists(ObDMLStmt *stmt, } } else if (OB_FAIL(groupby_can_be_eliminated_in_exists(op_type, subquery, can_be_eliminated))) { LOG_WARN("Checking if group by can be eliminated in subquery in exists failed", K(ret)); - } else if (!can_be_eliminated) { - /*do nothing*/ - } else if (subquery->has_group_by()) { - // Eliminate group by - trans_happened = true; - bool add_limit_constraint = false; - //Just in case different parameters hit same plan, firstly we need add const param constraint - if(OB_FAIL(need_add_limit_constraint(op_type, subquery, add_limit_constraint))){ - LOG_WARN("failed to check limit constraints", K(ret)); - } else if (add_limit_constraint && - OB_FAIL(ObTransformUtils::add_const_param_constraints(subquery->get_limit_expr(), ctx_))) { - LOG_WARN("failed to add const param constraints", K(ret)); - } else { - subquery->get_group_exprs().reset(); - trans_happened = true; - } - } else { /* do nothing */ } - return ret; -} - -int ObTransformSimplifySubquery::eliminate_groupby_in_any_all(ObSelectStmt *&subquery, bool &trans_happened) -{ - int ret = OB_SUCCESS; - bool can_be_eliminated = false; - if (OB_ISNULL(subquery)) { - ret = OB_INVALID_ARGUMENT; - LOG_WARN("Subquery is NULL", K(ret)); - } else if (OB_FAIL(groupby_can_be_eliminated_in_any_all(subquery, can_be_eliminated))) { - LOG_WARN("Checking if group by can be eliminated in subquery failed", K(ret)); } else if (can_be_eliminated) { - if (subquery->has_group_by()) { - // Eliminate group by - trans_happened = true; + // Eliminate group by + bool has_invalid_limit = false; + //Just in case different parameters hit same plan, firstly we need add const param constraint + if(OB_FAIL(check_limit(op_type, subquery, has_invalid_limit))){ + LOG_WARN("failed to check limit constraints", K(ret)); + } else if (!has_invalid_limit && NULL != subquery->get_limit_expr() && + OB_FAIL(ObTransformUtils::add_compare_int_constraint(ctx_, subquery->get_limit_expr(), T_OP_GE, 1))) { + LOG_WARN("failed to add const param constraints", K(ret)); + } else { subquery->get_group_exprs().reset(); - } else { /* do nothing */ } + trans_happened = true; + } } else { /* do nothing */ } - return ret; } - int ObTransformSimplifySubquery::eliminate_groupby_distinct_in_any_all(ObRawExpr *expr, bool &trans_happened) { int ret = OB_SUCCESS; ObQueryRefRawExpr *subq_expr = NULL; ObSelectStmt *subquery = NULL; + bool is_happened = false; + trans_happened = false; if (OB_ISNULL(expr)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("get unexpected null", K(ret), K(expr)); } else if (!expr->has_flag(IS_WITH_ALL) && !expr->has_flag(IS_WITH_ANY)) { + /* do nothing */ } else if (OB_UNLIKELY(2 != expr->get_param_count()) || OB_UNLIKELY(!expr->get_param_expr(1)->is_query_ref_expr())) { ret = OB_ERR_UNEXPECTED; @@ -1696,22 +1703,31 @@ int ObTransformSimplifySubquery::eliminate_groupby_distinct_in_any_all(ObRawExpr } else if (OB_ISNULL(subquery = subq_expr->get_ref_stmt())) { ret = OB_INVALID_ARGUMENT; LOG_WARN("subquery stmt is NULL", K(ret)); - } else if (OB_FAIL(eliminate_groupby_in_any_all(subquery, trans_happened))) { - LOG_WARN("Subquery elimination of group by in ANY, ALL fails", K(ret)); - } else if (!subq_expr->get_exec_params().empty()) { - // correlated subquery - if (OB_FAIL(eliminate_distinct_in_any_all(subquery, trans_happened))) { - LOG_WARN("Subquery elimination of distinct in ANY, ALL fails", K(ret)); - } else {/*do nothing*/} + } else { + if (OB_FAIL(eliminate_groupby_in_any_all(subquery, is_happened))) { + LOG_WARN("Subquery elimination of group by in ANY, ALL fails", K(ret)); + } else { + trans_happened |= is_happened; + LOG_TRACE("eliminate group by in ANY, ALL happened", K(is_happened), K(trans_happened)); + } + if (OB_SUCC(ret) && !subq_expr->get_exec_params().empty()) { + is_happened = false; + if (OB_FAIL(eliminate_distinct_in_any_all(subquery, is_happened))) { + LOG_WARN("Subquery elimination of distinct in ANY, ALL fails", K(ret)); + } else { + trans_happened |= is_happened; + LOG_TRACE("eliminate distinct in ANY, ALL happened", K(is_happened), K(trans_happened)); + } + } } - return ret; } int ObTransformSimplifySubquery::eliminate_distinct_in_any_all(ObSelectStmt *subquery, - bool &trans_happened) + bool &trans_happened) { int ret = OB_SUCCESS; bool contain_rownum = false; + trans_happened = false; if (OB_ISNULL(subquery)) { ret = OB_INVALID_ARGUMENT; LOG_WARN("Subquery is NULL", K(ret)); @@ -1734,6 +1750,7 @@ int ObTransformSimplifySubquery::add_limit_for_any_all_subquery(ObRawExpr *expr, ObQueryRefRawExpr *subq_expr = NULL; ObSelectStmt *subquery = NULL; bool check_status = false; + trans_happened = false; if (OB_ISNULL(expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ret)); @@ -1790,50 +1807,9 @@ int ObTransformSimplifySubquery::check_need_add_limit(ObSelectStmt *subquery, bo return ret; } -int ObTransformSimplifySubquery::need_add_limit_constraint(const ObItemType op_type, - const ObSelectStmt *subquery, - bool &add_limit_constraint) const -{ - int ret = OB_SUCCESS; - ObPhysicalPlanCtx *plan_ctx = NULL; - bool is_const_select = false; - bool has_limit = false; - add_limit_constraint = false; - if (OB_ISNULL(subquery) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->exec_ctx_) || - OB_ISNULL(plan_ctx = ctx_->exec_ctx_->get_physical_plan_ctx())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(subquery), K(ctx_), K(ctx_->exec_ctx_), K(plan_ctx)); - } else if (OB_FAIL(check_const_select(*subquery, is_const_select))) { - LOG_WARN("failed to check const select", K(ret)); - } else if (op_type != T_OP_EXISTS && op_type != T_OP_NOT_EXISTS && !is_const_select) { - has_limit = subquery->has_limit(); - } else if (!subquery->has_limit() || - subquery->get_offset_expr() != NULL || - subquery->get_limit_percent_expr() != NULL) { - has_limit = subquery->has_limit(); - } else { - bool is_null_value = false; - int64_t limit_value = 0; - if (OB_FAIL(ObTransformUtils::get_limit_value(subquery->get_limit_expr(), - &plan_ctx->get_param_store(), - ctx_->exec_ctx_, - ctx_->allocator_, - limit_value, - is_null_value))) { - LOG_WARN("failed to get_limit_value", K(ret)); - } else if (!is_null_value && limit_value >= 1) { - has_limit = false; - //Just in case different parameters hit same plan, firstly we need add const param constraint - add_limit_constraint = true; - } else { - has_limit = true; - } - } - return ret; -} int ObTransformSimplifySubquery::check_limit(const ObItemType op_type, - const ObSelectStmt *subquery, - bool &has_limit) const + const ObSelectStmt *subquery, + bool &has_limit) const { int ret = OB_SUCCESS; ObPhysicalPlanCtx *plan_ctx = NULL; @@ -1875,6 +1851,25 @@ int ObTransformSimplifySubquery::check_limit(const ObItemType op_type, return ret; } +int ObTransformSimplifySubquery::check_has_limit_1(const ObSelectStmt *stmt, + bool &has_limit_1) const +{ + int ret = OB_SUCCESS; + has_limit_1 = false; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(stmt)); + } else if (NULL == stmt->get_limit_expr()) { + // do nothing + } else if (T_INT != stmt->get_limit_expr()->get_expr_type() + || 1 != static_cast(stmt->get_limit_expr())->get_value().get_int()) { + // do nothing + } else { + has_limit_1 = true; + } + return ret; +} + int ObTransformSimplifySubquery::check_const_select(const ObSelectStmt &stmt, bool &is_const_select) const { @@ -1989,6 +1984,7 @@ int ObTransformSimplifySubquery::transform_any_all_as_exists(ObDMLStmt *stmt, bo { int ret = OB_SUCCESS; bool is_happened = false; + trans_happened = false; if (OB_ISNULL(stmt) || OB_ISNULL(ctx_)) { ret = OB_ERR_UNEXPECTED; @@ -2181,7 +2177,7 @@ int ObTransformSimplifySubquery::do_trans_empty_table_subquery_as_expr(ObRawExpr int ret = OB_SUCCESS; ObQueryRefRawExpr* query_ref = NULL; ObSelectStmt* ref_stmt = NULL; - bool add_limit_constraint = false; + bool has_invalid_limit = false; ObSEArray conditions; ObRawExpr *out_expr = NULL; trans_happened = false; @@ -2199,10 +2195,10 @@ int ObTransformSimplifySubquery::do_trans_empty_table_subquery_as_expr(ObRawExpr } else if (OB_ISNULL(ref_stmt = query_ref->get_ref_stmt())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected ref stmt", K(ret)); - } else if (OB_FAIL(need_add_limit_constraint(expr->get_expr_type(), ref_stmt, add_limit_constraint))){ + } else if (OB_FAIL(check_limit(expr->get_expr_type(), ref_stmt, has_invalid_limit))){ LOG_WARN("failed to check limit constraints", K(ret)); - } else if (add_limit_constraint && - OB_FAIL(ObTransformUtils::add_const_param_constraints(ref_stmt->get_limit_expr(), ctx_))) { + } else if (!has_invalid_limit && NULL != ref_stmt->get_limit_expr() && + OB_FAIL(ObTransformUtils::add_compare_int_constraint(ctx_, ref_stmt->get_limit_expr(), T_OP_GE, 1))) { LOG_WARN("failed to add const param constraints", K(ret)); } else if (OB_FAIL(conditions.assign(ref_stmt->get_condition_exprs()))) { LOG_WARN("failed to assign condition exprs", K(ret)); diff --git a/src/sql/rewrite/ob_transform_simplify_subquery.h b/src/sql/rewrite/ob_transform_simplify_subquery.h index f2142422fd..b4a45359c1 100644 --- a/src/sql/rewrite/ob_transform_simplify_subquery.h +++ b/src/sql/rewrite/ob_transform_simplify_subquery.h @@ -163,7 +163,7 @@ private: * 4. 无聚集函数(select item中) * 5. 非常量select item列,全部包含在group exprs中 */ - int groupby_can_be_eliminated_in_any_all(const ObSelectStmt *stmt, bool &can_be_eliminated) const; + int eliminate_groupby_in_any_all(ObSelectStmt *stmt, bool &trans_happened); int eliminate_subquery_in_exists(ObDMLStmt *stmt, ObRawExpr *&expr, @@ -179,15 +179,13 @@ private: ObSelectStmt *&subquery, bool &trans_happened); int eliminate_groupby_distinct_in_any_all(ObRawExpr *expr, bool &trans_happened); - int eliminate_groupby_in_any_all(ObSelectStmt *&stmt, bool &trans_happened); int eliminate_distinct_in_any_all(ObSelectStmt *subquery,bool &trans_happened); int check_need_add_limit(ObSelectStmt *subquery, bool &need_add_limit); int check_limit(const ObItemType op_type, const ObSelectStmt *subquery, bool &has_limit) const; - int need_add_limit_constraint(const ObItemType op_type, - const ObSelectStmt *subquery, - bool &add_limit_constraint) const; + int check_has_limit_1(const ObSelectStmt *stmt, + bool &has_limit_1) const; int check_const_select(const ObSelectStmt &stmt, bool &is_const_select) const; int get_push_down_conditions(ObDMLStmt *stmt, JoinedTable *join_table, diff --git a/src/sql/rewrite/ob_transform_temp_table.cpp b/src/sql/rewrite/ob_transform_temp_table.cpp index fbb85635bb..fc8360cbdf 100644 --- a/src/sql/rewrite/ob_transform_temp_table.cpp +++ b/src/sql/rewrite/ob_transform_temp_table.cpp @@ -28,6 +28,9 @@ #include "sql/optimizer/ob_optimizer_context.h" #include "sql/optimizer/ob_log_plan.h" #include "ob_transform_min_max.h" +#include "sql/rewrite/ob_transformer_impl.h" +#include "sql/optimizer/ob_log_join.h" +#include "sql/optimizer/ob_log_subplan_scan.h" using namespace oceanbase::common; @@ -92,12 +95,12 @@ int ObTransformTempTable::transform_one_stmt(common::ObIArray & } } if (OB_SUCC(ret)) { - if (OB_FAIL(expand_temp_table(temp_table_infos, is_happened))) { - LOG_WARN("failed to expand temp table", K(ret)); + if (OB_FAIL(try_inline_temp_table(stmt, temp_table_infos, is_happened))) { + LOG_WARN("failed to inline temp table", K(ret)); } else { trans_happened |= is_happened; - OPT_TRACE("expand temp table:", is_happened); - LOG_TRACE("succeed to expand temp table", K(is_happened)); + OPT_TRACE("inline temp table:", is_happened); + LOG_TRACE("succeed to inline temp table", K(is_happened)); } } } @@ -136,6 +139,7 @@ int ObTransformTempTable::generate_with_clause(ObDMLStmt *&stmt, bool &trans_hap int ret = OB_SUCCESS; ObSEArray child_stmts; ObSEArray non_correlated_stmts; + ObSEArray view_stmts; ObArray temp_table_infos; hash::ObHashMap parent_map; trans_happened = false; @@ -156,6 +160,8 @@ int ObTransformTempTable::generate_with_clause(ObDMLStmt *&stmt, bool &trans_hap enable_temp_table_transform = is_hint_enabled; } if (OB_FAIL(ret)) { + } else if (ctx_->eval_cost_) { + OPT_TRACE("disable CTE extraction during cost evaluation"); } else if (ctx_->is_set_stmt_oversize_) { OPT_TRACE("stmt containt oversize set stmt"); } else if (!enable_temp_table_transform || ctx_->is_force_inline_) { @@ -167,11 +173,22 @@ int ObTransformTempTable::generate_with_clause(ObDMLStmt *&stmt, bool &trans_hap } else if (!ObOptimizerUtil::find_item(ctx_->temp_table_ignore_stmts_, stmt) && OB_FAIL(ObTransformUtils::get_all_child_stmts(stmt, child_stmts, &parent_map, &ctx_->temp_table_ignore_stmts_))) { LOG_WARN("failed to get all child stmts", K(ret)); - } else if (OB_FAIL(get_non_correlated_subquery(stmt, non_correlated_stmts))) { - LOG_WARN("failed to get non correlated subquery", K(ret)); - } else if (OB_FAIL(ObOptimizerUtil::intersect(child_stmts, non_correlated_stmts, child_stmts))) { - LOG_WARN("failed to intersect child stmts", K(ret)); - } else if (OB_FAIL(extract_common_subquery_as_cte(stmt, child_stmts, parent_map, trans_happened))) { + } else if (stmt->get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, COMPAT_VERSION_4_3_5)) { + if (OB_FAIL(get_all_view_stmts(stmt, view_stmts))) { + LOG_WARN("failed to get non correlated subquery", K(ret)); + } else if (OB_FAIL(ObOptimizerUtil::intersect(child_stmts, view_stmts, child_stmts))) { + LOG_WARN("failed to intersect child stmts", K(ret)); + } + } else { + if (OB_FAIL(get_non_correlated_subquery(stmt, non_correlated_stmts))) { + LOG_WARN("failed to get non correlated subquery", K(ret)); + } else if (OB_FAIL(ObOptimizerUtil::intersect(child_stmts, non_correlated_stmts, child_stmts))) { + LOG_WARN("failed to intersect child stmts", K(ret)); + } + } + + if (OB_FAIL(ret)) { + } else if (OB_FAIL(extract_common_table_expression(stmt, child_stmts, parent_map, trans_happened))) { LOG_WARN("failed to extract common subquery as cte", K(ret)); } else if (OB_FAIL(parent_map.destroy())) { LOG_WARN("failed to destroy map", K(ret)); @@ -181,11 +198,12 @@ int ObTransformTempTable::generate_with_clause(ObDMLStmt *&stmt, bool &trans_hap /** * @brief expand_temp_table - * 如果temp table只被引用一次或者temp table是一个简单的查询 - * 例如单表查询,那么需要展开temp table,还原成generate table + * 尝试基于规则和代价的 inline 判定 + * 规则:单表无聚合,只被引用一次,不满足物化条件... */ -int ObTransformTempTable::expand_temp_table(ObIArray &temp_table_info, - bool &trans_happened) +int ObTransformTempTable::try_inline_temp_table(ObDMLStmt *stmt, + ObIArray &temp_table_info, + bool &trans_happened) { int ret = OB_SUCCESS; trans_happened = false; @@ -204,56 +222,78 @@ int ObTransformTempTable::expand_temp_table(ObIArray &temp_table_ bool is_oversize_stmt = false; bool has_for_update = false; int64_t stmt_size = 0; - bool need_expand = false; - bool can_expand = true; - OPT_TRACE("try to expand temp table:", helper.temp_table_query_); + bool need_inline = false; + bool can_inline = true; + bool need_check_cost = false; + bool in_blacklist = false; + OPT_TRACE("try to inline temp table:", helper.temp_table_query_); if (OB_ISNULL(helper.temp_table_query_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect null ref query", K(helper), K(ret)); } else if (OB_FAIL(check_stmt_size(helper.temp_table_query_, stmt_size, is_oversize_stmt))) { LOG_WARN("check stmt size failed", K(ret)); - } else if (OB_FAIL(helper.temp_table_query_->is_query_deterministic(can_expand))) { + } else if (OB_FAIL(ObTransformUtils::check_inline_temp_table_valid(helper.temp_table_query_, can_inline))) { + LOG_WARN("failed to check inline temp table valid", K(ret)); + } else if (OB_FAIL(helper.temp_table_query_->is_query_deterministic(can_inline))) { LOG_WARN("failed to check stmt is deterministic", K(ret)); } else if (OB_FAIL(check_has_for_update(helper, has_for_update))) { LOG_WARN("failed to check has for update", K(ret)); - } else if (!can_expand) { + } else if (!can_inline) { // do nothing - OPT_TRACE("CTE can not be expanded"); + OPT_TRACE("CTE can not be inlined"); } else if (OB_FAIL(check_hint_allowed_trans(*helper.temp_table_query_, force_inline, force_materia))) { LOG_WARN("failed to check force materialize", K(ret)); } else if (force_inline) { - need_expand = true; + need_inline = true; OPT_TRACE("hint force inline CTE"); } else if (lib::is_oracle_mode() && has_for_update) { - need_expand = true; + need_inline = true; OPT_TRACE("stmt has FOR UPDATE, force inline CTE"); } else if (force_materia) { //do nothing OPT_TRACE("hint force materialize CTE"); } else if (is_oversize_stmt) { //do nothing - OPT_TRACE("CTE too large to expand"); + OPT_TRACE("CTE too large to inline"); } else if (ctx_->is_force_materialize_) { //do nothing OPT_TRACE("system variable force materialize CTE"); } else if (ctx_->is_force_inline_) { - need_expand = true; + need_inline = true; OPT_TRACE("system variable force inline CTE"); } else if (1 == helper.table_items_.count()) { - need_expand = true; + need_inline = true; OPT_TRACE("CTE`s refer once, force inline"); } else if (OB_FAIL(check_stmt_can_materialize(helper.temp_table_query_, true, can_materia))) { LOG_WARN("failed to check extract cte valid", K(ret)); } else if (!can_materia) { - need_expand = true; + need_inline = true; OPT_TRACE("transform rule force inline CTE"); + } else if (OB_FAIL(check_stmt_in_blacklist(helper.temp_table_query_, + ctx_->inline_blacklist_, + in_blacklist))) { + LOG_WARN("failed to check cte in blacklist", K(ret)); + } else if (in_blacklist) { + OPT_TRACE("reject inline CTE due to blacklist"); + } else if (ctx_->eval_cost_ || helper.temp_table_query_->is_recursive_union()) { + // only try inline by rule + } else { + need_check_cost = true; } - if (OB_SUCC(ret) && need_expand) { + + if (OB_FAIL(ret)) { + } else if (stmt->get_query_ctx()->check_opt_compat_version(COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, COMPAT_VERSION_4_3_5) && + need_check_cost && + OB_FAIL(check_inline_temp_table_by_cost(stmt, helper, need_inline))) { + LOG_WARN("failed to check inline temp table by cost", K(ret)); + } else if (!need_inline) { + // do nothing + } else { //深拷贝每一份查询,还原成generate table ObDMLStmt *orig_stmt = helper.temp_table_query_; - if (OB_FAIL(ObTransformUtils::expand_temp_table(ctx_, helper))) { + if (OB_FAIL(ObTransformUtils::inline_temp_table(ctx_, helper))) { LOG_WARN("failed to extend temp table", K(ret)); } else if (OB_FAIL(add_normal_temp_table_trans_hint(*orig_stmt, T_INLINE))) { LOG_WARN("failed to add transform hint", K(ret)); @@ -428,11 +468,11 @@ int ObTransformTempTable::check_has_for_update(const ObDMLStmt::TempTableInfo &h } /** - * @brief extract_common_subquery_as_cte + * @brief extract_common_table_expression * 比较当前stmt的所有child stmt, * 把所有相似的stmt分为一组,抽离最大的公共部分作为temp table */ -int ObTransformTempTable::extract_common_subquery_as_cte(ObDMLStmt *stmt, +int ObTransformTempTable::extract_common_table_expression(ObDMLStmt *stmt, ObIArray &stmts, hash::ObHashMap &parent_map, bool &trans_happened) @@ -453,7 +493,7 @@ int ObTransformTempTable::extract_common_subquery_as_cte(ObDMLStmt *stmt, //对每一组stmt抽离公共部分 for (int64_t i = 0; OB_SUCC(ret) && i < stmt_groups.count(); ++i) { bool is_happened = false; - if (OB_FAIL(inner_extract_common_subquery_as_cte(*stmt, + if (OB_FAIL(inner_extract_common_table_expression(*stmt, stmt_groups.at(i).stmts_, parent_map, is_happened))) { @@ -474,11 +514,11 @@ int ObTransformTempTable::extract_common_subquery_as_cte(ObDMLStmt *stmt, } /** - * @brief inner_extract_common_subquery_as_cte + * @brief inner_extract_common_table_expression * stmt之间两两比较,分成多个相似组, * 对每组相似stmt创建temp table */ -int ObTransformTempTable::inner_extract_common_subquery_as_cte(ObDMLStmt &root_stmt, +int ObTransformTempTable::inner_extract_common_table_expression(ObDMLStmt &root_stmt, ObIArray &stmts, hash::ObHashMap &parent_map, bool &trans_happened) @@ -1244,11 +1284,22 @@ int ObTransformTempTable::create_temp_table(ObDMLStmt &root_stmt, if (OB_SUCC(ret) && is_valid) { trans_happened = false; common::ObSEArray accept_stmts; - if (OB_FAIL(accept_cte_transform(root_stmt, temp_table, - origin_stmts, trans_stmts, - accept_stmts, parent_map, - !compare_info.hint_force_stmt_set_.empty(), - trans_happened))) { + ObString temp_query_name; + bool use_new_accept_func = root_stmt.get_query_ctx()->check_opt_compat_version( + COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, COMPAT_VERSION_4_3_5); + if (!use_new_accept_func && + OB_FAIL(accept_cte_transform(root_stmt, temp_table, + origin_stmts, trans_stmts, + accept_stmts, parent_map, + !compare_info.hint_force_stmt_set_.empty(), + trans_happened))) { + LOG_WARN("failed to accept transform", K(ret)); + } else if (use_new_accept_func && + OB_FAIL(accept_cte_transform_v2(root_stmt, temp_table, + origin_stmts, trans_stmts, + accept_stmts, parent_map, + !compare_info.hint_force_stmt_set_.empty(), + trans_happened))) { LOG_WARN("failed to accept transform", K(ret)); } else if (OB_FAIL(try_trans_helper.finish(trans_happened, root_stmt.get_query_ctx(), ctx_))) { LOG_WARN("failed to finish try_trans_helper", K(ret)); @@ -1257,6 +1308,10 @@ int ObTransformTempTable::create_temp_table(ObDMLStmt &root_stmt, LOG_WARN("failed to append equal param constraints", K(ret)); } else if (OB_FAIL(add_materialize_stmts(accept_stmts))) { LOG_WARN("failed to add stmts", K(ret)); + } else if (OB_FAIL(temp_table_query->get_qb_name(temp_query_name))) { + LOG_WARN("failed to get qb name", K(ret)); + } else if (OB_FAIL(ctx_->inline_blacklist_.push_back(temp_query_name))) { + LOG_WARN("failed to push back", K(ret)); } else { for (int64_t i = 0; OB_SUCC(ret) && i < compare_info.stmt_map_infos_.count(); i ++) { if (OB_FAIL(append(ctx_->equal_param_constraints_, @@ -2063,7 +2118,11 @@ int ObTransformTempTable::need_transform(const common::ObIArray is_normal_disabled_transform(stmt)) { need_trans = false; } else if (!query_hint->has_outline_data()) { - need_trans = true; + // TODO: sean.yyj make the priority of rule hint higher than cost based hint + if (OB_FAIL(ObTransformUtils::is_cost_based_trans_enable(ctx_, query_hint->global_hint_, + need_trans))) { + LOG_WARN("failed to check cost based transform enable", K(ret)); + } } else if (NULL == (trans_hint = query_hint->get_outline_trans_hint(ctx_->trans_list_loc_))) { /*do nothing*/ OPT_TRACE("outline reject transform"); @@ -2535,6 +2594,1147 @@ int ObTransformTempTable::evaluate_cte_cost(ObDMLStmt &root_stmt, return ret; } +int ObTransformTempTable::accept_cte_transform_v2(ObDMLStmt &origin_root_stmt, + TableItem *temp_table, + common::ObIArray &origin_stmts, + common::ObIArray &trans_stmts, + common::ObIArray &accept_stmts, + hash::ObHashMap &parent_map, + bool force_accept, + bool &trans_happened) +{ + int ret = OB_SUCCESS; + trans_happened = false; + cost_based_trans_tried_ = true; + ObDMLStmt *copy_inline_root; + ObDMLStmt *copy_materialize_root; + ObSEArray copy_inline_stmts; + ObSEArray copy_materialize_stmts; + ObSEArray stmt_ptrs; + ObSelectStmt *dummy_stmt = NULL; + ObSelectStmt *copy_cte_query = NULL; + ObTryTransHelper inline_trans_helper; + ObTryTransHelper materialize_trans_helper; + ObSEArray choosed_inline_idxs; + ObSEArray choosed_materialize_idxs; + if (OB_ISNULL(ctx_) || OB_UNLIKELY(origin_stmts.count() != trans_stmts.count()) || + OB_ISNULL(temp_table) || OB_ISNULL(temp_table->ref_query_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected param", K(ret), K(ctx_)); + } else if (OB_FAIL(get_stmt_pointers(origin_root_stmt, origin_stmts, parent_map, stmt_ptrs))) { + LOG_WARN("failed to get stmt pointers", K(ret)); + } else if (origin_stmts.count() != stmt_ptrs.count()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected stmt pointers", K(ret), K(origin_stmts.count()), K(stmt_ptrs.count())); + } else if (force_accept) { + OPT_TRACE("accept cte because of the hint"); + trans_happened = true; + for (int64_t i = 0; OB_SUCC(ret) && i < origin_stmts.count(); i++) { + if (OB_FAIL(stmt_ptrs.at(i).set(trans_stmts.at(i)))) { + LOG_WARN("failed to set ptr", K(ret)); + } else if (OB_FAIL(accept_stmts.push_back(origin_stmts.at(i)))) { + LOG_WARN("failed to push back", K(ret)); + } + OPT_TRACE("Materialize stmt :", trans_stmts.at(i)); + } + } else if (ctx_->is_set_stmt_oversize_) { + LOG_TRACE("not accept transform because large set stmt", K(ctx_->is_set_stmt_oversize_)); + } else if (OB_FAIL(pick_out_stmts_in_blacklist(ctx_->materialize_blacklist_, + origin_stmts, + trans_stmts, + stmt_ptrs))) { + LOG_WARN("failed to pick out stmts in blacklist", K(ret)); + } else if (origin_stmts.count() < 2) { + OPT_TRACE("reject materialize CTE due to blacklist"); + trans_happened = false; + } else if (OB_FAIL(inline_trans_helper.fill_helper(origin_root_stmt.get_query_ctx()))) { + LOG_WARN("failed to fill helper", K(ret)); + } else if (OB_FAIL(materialize_trans_helper.fill_helper(origin_root_stmt.get_query_ctx()))) { + LOG_WARN("failed to fill helper", K(ret)); + } else if (OB_FAIL(copy_and_replace_trans_root(origin_root_stmt, + origin_stmts, + NULL, + stmt_ptrs, + copy_inline_root, + copy_inline_stmts, + dummy_stmt, + false))) { + LOG_WARN("failed to prepare eval cte cost stmt", K(ret)); + } else if (OB_FAIL(copy_and_replace_trans_root(origin_root_stmt, + trans_stmts, + temp_table->ref_query_, + stmt_ptrs, + copy_materialize_root, + copy_materialize_stmts, + copy_cte_query, + true))) { + LOG_WARN("failed to prepare eval cte cost stmt", K(ret)); + } else if (OB_FAIL(evaluate_inline_materialize_costs(&origin_root_stmt, + true, + copy_inline_root, + copy_inline_stmts, + copy_materialize_root, + copy_materialize_stmts, + copy_cte_query, + choosed_inline_idxs, + choosed_materialize_idxs))) { + LOG_WARN("failed to evaluate inline materialize costs", K(ret)); + } else if (choosed_materialize_idxs.count() > 1) { + OPT_TRACE("accept materialize cte due to cost"); + trans_happened = true; + for (int64_t i = 0; OB_SUCC(ret) && i < choosed_materialize_idxs.count(); i++) { + int64_t stmt_idx = choosed_materialize_idxs.at(i); + if (OB_UNLIKELY(stmt_idx < 0 || stmt_idx >= origin_stmts.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected idx", K(ret), K(stmt_idx)); + } else if (OB_FAIL(stmt_ptrs.at(stmt_idx).set(trans_stmts.at(stmt_idx)))) { + LOG_WARN("failed to set ptr", K(ret)); + } else if (OB_FAIL(accept_stmts.push_back(origin_stmts.at(stmt_idx)))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } else { + OPT_TRACE("reject materialize cte due to cost"); + for (int64_t i = 0; OB_SUCC(ret) && i < origin_stmts.count(); i++) { + ObString qb_name; + if (OB_ISNULL(origin_stmts.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null stmt", K(ret)); + } else if (OB_FAIL(origin_stmts.at(i)->get_qb_name(qb_name))) { + LOG_WARN("failed to get qb name", K(ret)); + } else if (OB_FAIL(ctx_->materialize_blacklist_.push_back(qb_name))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + return ret; +} + +int ObTransformTempTable::evaluate_cte_cost_partially(ObDMLStmt *root_stmt, + ObIArray &stmts, + ObIArray &costs, + ObSelectStmt *cte_query, + double &temp_table_cost) +{ + int ret = OB_SUCCESS; + ObEvalCostHelper eval_cost_helper; + temp_table_cost = 0.0; + bool can_eval = false; + if (OB_ISNULL(ctx_) || OB_UNLIKELY(!ctx_->is_valid()) || OB_ISNULL(root_stmt) + || OB_ISNULL(ctx_->exec_ctx_->get_physical_plan_ctx()) + || OB_ISNULL(ctx_->exec_ctx_->get_stmt_factory()) + || OB_ISNULL(ctx_->exec_ctx_->get_stmt_factory()->get_query_ctx()) + || OB_ISNULL(root_stmt->get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("params are invalid", K(ret), K(ctx_), K(root_stmt)); + } else if (OB_FAIL(eval_cost_helper.fill_helper(*ctx_->exec_ctx_->get_physical_plan_ctx(), + *root_stmt->get_query_ctx(), *ctx_))) { + LOG_WARN("failed to fill eval cost helper", K(ret)); + } else { + BEGIN_OPT_TRACE_EVA_COST; + ctx_->eval_cost_ = true; + ParamStore ¶m_store = ctx_->exec_ctx_->get_physical_plan_ctx()->get_param_store_for_update(); + lib::ContextParam param; + ObTransformerImpl trans(ctx_); + bool trans_happended = false; + uint64_t trans_rules = ALL_EXPR_LEVEL_HEURISTICS_RULES; + param.set_mem_attr(ctx_->session_info_->get_effective_tenant_id(), + "TempTableCost", + ObCtxIds::DEFAULT_CTX_ID) + .set_properties(lib::USE_TL_PAGE_OPTIONAL) + .set_page_size(OB_MALLOC_NORMAL_BLOCK_SIZE); + if (OB_FAIL(trans.transform_rule_set(root_stmt, + trans_rules, + trans.get_max_iteration_count(), + trans_happended))) { + LOG_WARN("failed to transform heuristic rule", K(ret)); + } else if (OB_FAIL(check_evaluate_after_transform(root_stmt, stmts, can_eval))) { + LOG_WARN("failed to check after transform", K(ret)); + } else if (!can_eval) { + temp_table_cost = std::numeric_limits::max(); + for (int64_t i = 0; OB_SUCC(ret) && i < stmts.count(); i++) { + if (OB_FAIL(costs.push_back(0.0))) { + LOG_WARN("failed to push back", K(ret)); + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(eval_cost_helper.recover_context(*ctx_->exec_ctx_->get_physical_plan_ctx(), + *ctx_->exec_ctx_->get_stmt_factory()->get_query_ctx(), + *ctx_))) { + LOG_WARN("failed to recover context", K(ret)); + } else if (OB_FAIL(ObTransformUtils::free_stmt(*ctx_->stmt_factory_, root_stmt))) { + LOG_WARN("failed to free stmt", K(ret)); + } + } + } else { + CREATE_WITH_TEMP_CONTEXT(param) { + ObRawExprFactory tmp_expr_factory(CURRENT_CONTEXT->get_arena_allocator()); + HEAP_VAR(ObOptimizerContext, optctx, + ctx_->session_info_, + ctx_->exec_ctx_, + ctx_->sql_schema_guard_, + ctx_->opt_stat_mgr_, + CURRENT_CONTEXT->get_arena_allocator(), + &ctx_->exec_ctx_->get_physical_plan_ctx()->get_param_store(), + *ctx_->self_addr_, + GCTX.srv_rpc_proxy_, + root_stmt->get_query_ctx()->get_global_hint(), + tmp_expr_factory, + root_stmt, + false, + ctx_->exec_ctx_->get_stmt_factory()->get_query_ctx()) { + // optctx.set_only_ds_basic_stat(true); + ObOptimizer optimizer(optctx); + if (OB_FAIL(optimizer.get_cte_optimization_cost(*root_stmt, + cte_query, + stmts, + temp_table_cost, + costs))) { + LOG_WARN("failed to get cost", K(ret)); + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(eval_cost_helper.recover_context(*ctx_->exec_ctx_->get_physical_plan_ctx(), + *ctx_->exec_ctx_->get_stmt_factory()->get_query_ctx(), + *ctx_))) { + LOG_WARN("failed to recover context", K(ret)); + } else if (OB_FAIL(ObTransformUtils::free_stmt(*ctx_->stmt_factory_, root_stmt))) { + LOG_WARN("failed to free stmt", K(ret)); + } + } + } + } + END_OPT_TRACE_EVA_COST; + } + return ret; +} + +int ObTransformTempTable::evaluate_cte_cost_globally(ObDMLStmt *origin_root, + ObDMLStmt *root_stmt, + ObIArray &semi_join_stmt_ids, + bool need_check_plan, + double &global_cost) +{ + int ret = OB_SUCCESS; + ObSelectStmt *copy_cte_stmt = NULL; + ObEvalCostHelper eval_cost_helper; + common::ObSEArray copy_stmts; + if (OB_ISNULL(ctx_) || OB_UNLIKELY(!ctx_->is_valid()) || OB_ISNULL(root_stmt) || + OB_ISNULL(ctx_->exec_ctx_->get_physical_plan_ctx()) || + OB_ISNULL(ctx_->exec_ctx_->get_stmt_factory()) || + OB_ISNULL(ctx_->exec_ctx_->get_stmt_factory()->get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("params are invalid", K(ret), K(ctx_)); + } else if (OB_FAIL(eval_cost_helper.fill_helper(*ctx_->exec_ctx_->get_physical_plan_ctx(), + *root_stmt->get_query_ctx(), *ctx_))) { + LOG_WARN("failed to fill eval cost helper", K(ret)); + } else { + BEGIN_OPT_TRACE_EVA_COST; + ctx_->eval_cost_ = true; + ParamStore ¶m_store = ctx_->exec_ctx_->get_physical_plan_ctx()->get_param_store_for_update(); + lib::ContextParam param; + ObTransformerImpl trans(ctx_); + bool trans_happended = false; + uint64_t trans_rules = ALL_HEURISTICS_RULES | (1L << TEMP_TABLE_OPTIMIZATION); + param.set_mem_attr(ctx_->session_info_->get_effective_tenant_id(), + "TempTableCost", + ObCtxIds::DEFAULT_CTX_ID) + .set_properties(lib::USE_TL_PAGE_OPTIONAL) + .set_page_size(OB_MALLOC_NORMAL_BLOCK_SIZE); + if (OB_FAIL(add_semi_to_inner_hint_if_need(root_stmt, semi_join_stmt_ids))) { + LOG_WARN("failed to add semi to inner hint", K(ret)); + } else if (OB_FAIL(trans.transform_rule_set(root_stmt, + trans_rules, + trans.get_max_iteration_count(), + trans_happended))) { + LOG_WARN("failed to transform heuristic rule", K(ret)); + } else { + CREATE_WITH_TEMP_CONTEXT(param) { + ObRawExprFactory tmp_expr_factory(CURRENT_CONTEXT->get_arena_allocator()); + HEAP_VAR(ObOptimizerContext, optctx, + ctx_->session_info_, + ctx_->exec_ctx_, + ctx_->sql_schema_guard_, + ctx_->opt_stat_mgr_, + CURRENT_CONTEXT->get_arena_allocator(), + &ctx_->exec_ctx_->get_physical_plan_ctx()->get_param_store(), + *ctx_->self_addr_, + GCTX.srv_rpc_proxy_, + root_stmt->get_query_ctx()->get_global_hint(), + tmp_expr_factory, + root_stmt, + false, + ctx_->exec_ctx_->get_stmt_factory()->get_query_ctx()) { + ObOptimizer optimizer(optctx); + ObLogPlan *plan = NULL; + if (OB_FAIL(optimizer.get_optimization_cost(*root_stmt, plan, global_cost))) { + LOG_WARN("failed to get optimization cost", K(ret)); + } else if (need_check_plan && OB_NOT_NULL(plan)) { + ObSEArray blacklist; + if (OB_FAIL(gather_materialize_blacklist(plan->get_plan_root(), blacklist))) { + LOG_WARN("failed to gather materialize blacklist", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < blacklist.count(); ++i) { + ObDMLStmt *stmt = NULL; + ObString qb_name; + if (OB_FAIL(origin_root->get_stmt_by_stmt_id(blacklist.at(i), stmt))) { + LOG_WARN("failed to get stmt by stmt id", K(ret)); + } else if (OB_ISNULL(stmt)) { + // do nothing, may generate new stmt after rewrite + } else if (OB_FAIL(stmt->get_qb_name(qb_name))) { + LOG_WARN("failed to get qb name", K(ret)); + } else if (OB_FAIL(ctx_->materialize_blacklist_.push_back(qb_name))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + } + if (OB_SUCC(ret)) { + if (OB_FAIL(eval_cost_helper.recover_context(*ctx_->exec_ctx_->get_physical_plan_ctx(), + *ctx_->exec_ctx_->get_stmt_factory()->get_query_ctx(), + *ctx_))) { + LOG_WARN("failed to recover context", K(ret)); + } else if (OB_FAIL(ObTransformUtils::free_stmt(*ctx_->stmt_factory_, root_stmt))) { + LOG_WARN("failed to free stmt", K(ret)); + } + } + } + } + END_OPT_TRACE_EVA_COST; + } + return ret; +} + +int ObTransformTempTable::need_check_global_cte_cost(const ObDMLStmt *root_stmt, + const ObIArray &origin_stmts, + const hash::ObHashMap &parent_map, + const ObSelectStmt *temp_table_query, + ObIArray &semi_join_stmt_ids, + bool &check_global_cost) +{ + int ret = OB_SUCCESS; + check_global_cost = false; + if (OB_ISNULL(root_stmt) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->sql_schema_guard_) || + OB_ISNULL(temp_table_query)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("params are invalid", K(ret)); + } else { + // 1. can pushdown dynamic filter + for (int64_t i = 0; OB_SUCC(ret) && !check_global_cost && i < origin_stmts.count(); ++i) { + const ObSelectStmt *stmt = origin_stmts.at(i); + ObSEArray sel_idxs; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("stmt is null", K(ret)); + } else { + // collect idxs of select items that can match index + for (int64_t j = 0; OB_SUCC(ret) && j < stmt->get_select_item_size(); j++) { + bool match_index = false; + if (OB_FAIL(ObTransformUtils::check_select_item_match_index(root_stmt, + stmt, + ctx_->sql_schema_guard_, + j, + match_index))) { + LOG_WARN("failed to check select item match index", K(ret)); + } else if (!match_index) { + // do nothing + } else if (OB_FAIL(sel_idxs.push_back(j))) { + LOG_WARN("failed to push back", K(ret)); + } + } + } + // check the opportunity of pushing down dynamic filter to view through NLJ inner path + if (OB_SUCC(ret) && sel_idxs.count() > 0) { + bool use_for_join = false; + if (OB_FAIL(check_projected_cols_used_for_join(stmt, + parent_map, + sel_idxs, + semi_join_stmt_ids, + use_for_join))) { + LOG_WARN("failed to check projected cols used for join", K(ret)); + } else if (use_for_join) { + check_global_cost = true; + } + } + } + // 2. current temp table references another temp table(may inline after extraction) + for (int64_t i = 0; OB_SUCC(ret) && !check_global_cost && i < temp_table_query->get_table_size(); ++i) { + const TableItem *table_item = temp_table_query->get_table_items().at(i); + if (OB_ISNULL(table_item)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table item is null", K(ret)); + } else if (table_item->is_temp_table()) { + check_global_cost = true; + } + } + } + return ret; +} + + +/** + * @brief check_projected_cols_used_for_join + * check whether select items projected from the generated table are used for joins (pushdown dynamic filter) + * @param semi_join_stmt_ids refers to stmts that use target generated table as left table of semi join + */ +int ObTransformTempTable::check_projected_cols_used_for_join(const ObSelectStmt *stmt, + const hash::ObHashMap &parent_map, + const ObIArray &sel_idxs, + ObIArray &semi_join_stmt_ids, + bool &used_for_join) +{ + int ret = OB_SUCCESS; + uint64_t cur_table_id = OB_INVALID_ID; + ObDMLStmt *parent_stmt = NULL; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("params are invalid", K(ret)); + } else if (sel_idxs.count() == 0 || used_for_join) { + // do nothing + } else if (OB_FAIL(get_parent_stmt(stmt, parent_map, cur_table_id, parent_stmt))) { + LOG_WARN("failed to get parent stmt", K(ret)); + } else if (OB_ISNULL(parent_stmt)) { + // do nothing + } else if (parent_stmt->is_set_stmt()) { + if (OB_FAIL(SMART_CALL(check_projected_cols_used_for_join(static_cast(parent_stmt), + parent_map, + sel_idxs, + semi_join_stmt_ids, + used_for_join)))) { + LOG_WARN("failed to check projected cols used for join", K(ret)); + } + } else if (cur_table_id != OB_INVALID_ID) { + ObStmtExprGetter visitor; + ObSEArray tmp_conds; + ObSEArray join_col_exprs; + ObSEArray mapped_col_exprs; + bool can_filter_pushdown = false; + visitor.remove_all(); + visitor.add_scope(SCOPE_JOINED_TABLE); + visitor.add_scope(SCOPE_WHERE); + visitor.add_scope(SCOPE_SEMI_INFO); + parent_stmt->get_relation_exprs(tmp_conds, visitor); + // convert select item idxs to columns of parent stmt + for (int64_t i = 0; OB_SUCC(ret) && i < sel_idxs.count(); ++i) { + int64_t col_id = sel_idxs.at(i) + OB_APP_MIN_COLUMN_ID; + ColumnItem *col_item = NULL; + ObColumnRefRawExpr *col_expr = NULL; + if (OB_ISNULL(col_item = parent_stmt->get_column_item(cur_table_id, col_id))) { + // do nothing, unused cols are not in the stmt + } else if (OB_ISNULL(col_expr = col_item->get_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column expr is NULL", K(ret)); + } else if (OB_FAIL(mapped_col_exprs.push_back(col_expr))) { + LOG_WARN("failed to push back column expr", K(ret)); + } + } + // collect cols used in join conditions + for (int64_t i = 0; OB_SUCC(ret) && i < tmp_conds.count(); ++i) { + ObRawExpr *cond = NULL; + if (OB_ISNULL(cond = tmp_conds.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expr is NULL", K(ret)); + } else if (cond->get_relation_ids().num_members() < 2 && + !cond->has_flag(CNT_SUB_QUERY)) { + // do nothing + } else if (OB_FAIL(ObTransformUtils::get_simple_filter_column(parent_stmt, + cond, + cur_table_id, + join_col_exprs))) { + LOG_WARN("failed to get simple filter column", K(ret)); + } else if ((cond->has_flag(IS_WITH_ANY) || cond->has_flag(IS_WITH_ALL)) && + IS_SUBQUERY_COMPARISON_OP(cond->get_expr_type())) { + ObColumnRefRawExpr *col = NULL; + if (cond->get_param_count() != 2 || OB_ISNULL(cond->get_param_expr(0)) || + OB_ISNULL(cond->get_param_expr(1))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected expr", K(ret)); + } else if (cond->get_param_expr(0)->is_column_ref_expr()) { + col = static_cast(cond->get_param_expr(0)); + if (col->get_table_id() != cur_table_id) { + // do nothing + } else if (OB_FAIL(join_col_exprs.push_back(col))) { + LOG_WARN("failed to push back column expr", K(ret)); + } + } + } + } + // collect cols from candi join condition (subquery unnest) + for (int64_t i = 0; OB_SUCC(ret) && i < parent_stmt->get_subquery_expr_size(); ++i) { + ObQueryRefRawExpr *expr = parent_stmt->get_subquery_exprs().at(i); + if (OB_ISNULL(expr)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expr is NULL", K(ret)); + } else if (OB_FAIL(extract_pushdown_cols(*expr, cur_table_id, join_col_exprs))) { + LOG_WARN("failed to extract pushdown cols", K(ret)); + } + } + // check overlap of join_col_exprs and mapped_col_exprs + for (int64_t i = 0; OB_SUCC(ret) && !used_for_join && i < join_col_exprs.count(); ++i) { + ObColumnRefRawExpr* col = join_col_exprs.at(i); + if (OB_ISNULL(col)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null column expr", K(ret)); + } else if (ObOptimizerUtil::find_item(mapped_col_exprs, col)) { + used_for_join = true; + } + } + if (OB_FAIL(ret)) { + } else if (used_for_join) { + if (OB_FAIL(collect_semi_join_stmt_ids(*parent_stmt, + mapped_col_exprs, + cur_table_id, + semi_join_stmt_ids))) { + LOG_WARN("failed to collect semi join stmt ids", K(ret)); + } + } else if (parent_stmt->is_select_stmt()) { + // recursively check parent stmt if need + const ObSelectStmt *sel_stmt = static_cast(parent_stmt); + ObSEArray new_sel_idxs; + if (OB_FAIL(can_push_dynamic_filter_to_cols(sel_stmt, + mapped_col_exprs, + cur_table_id, + new_sel_idxs, + can_filter_pushdown))) { + LOG_WARN("failed to check filter pushdown to cols", K(ret)); + } else if (!can_filter_pushdown) { + // do nothing + } else if (OB_FAIL(SMART_CALL(check_projected_cols_used_for_join(sel_stmt, + parent_map, + new_sel_idxs, + semi_join_stmt_ids, + used_for_join)))) { + LOG_WARN("failed to check projected cols used for join", K(ret)); + } + } + } + return ret; +} + +int ObTransformTempTable::extract_pushdown_cols(const ObQueryRefRawExpr &query_ref, + uint64_t cur_table_id, + ObIArray &pushdown_cols) +{ + int ret = OB_SUCCESS; + ObColumnRefRawExpr *col = NULL; + for (int64_t j = 0; OB_SUCC(ret) && j < query_ref.get_exec_params().count(); j++) { + ObExecParamRawExpr *exec_param = query_ref.get_exec_params().at(j); + if (OB_ISNULL(exec_param) || OB_ISNULL(exec_param->get_ref_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("exec param is NULL", K(ret)); + } else if (!exec_param->get_ref_expr()->is_column_ref_expr()) { + // do nothing + } else if (OB_FALSE_IT(col = static_cast(exec_param->get_ref_expr()))) { + } else if (col->get_table_id() != cur_table_id) { + // do nothing + } else if (OB_FAIL(pushdown_cols.push_back(col))) { + LOG_WARN("failed to push back column expr", K(ret)); + } + } + return ret; +} + +int ObTransformTempTable::collect_semi_join_stmt_ids(const ObDMLStmt &parent_stmt, + const ObIArray &mapped_col_exprs, + uint64_t cur_table_id, + ObIArray &semi_join_stmt_ids) +{ + int ret = OB_SUCCESS; + // collect stmt id if generated table is on left side of semi join + bool found = false; + for (int64_t i = 0; OB_SUCC(ret) && !found && i < parent_stmt.get_semi_infos().count(); ++i) { + SemiInfo *semi_info = parent_stmt.get_semi_infos().at(i); + if (OB_ISNULL(semi_info)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("semi info is NULL", K(ret)); + } else if (!semi_info->is_semi_join()) { + // do nothing + } else if (!ObOptimizerUtil::find_item(semi_info->left_table_ids_, cur_table_id)) { + // do nothing + } else if (OB_FAIL(add_var_to_array_no_dup(semi_join_stmt_ids, parent_stmt.stmt_id_))) { + LOG_WARN("failed to add var to array no dup", K(ret)); + } else { + found = true; + } + } + // collect stmt id from any/all/exists subquery (candidate semi join) + for (int64_t i = 0; OB_SUCC(ret) && !found && i < parent_stmt.get_condition_size(); i++) { + ObRawExpr *cond = const_cast(parent_stmt.get_condition_expr(i)); + ObQueryRefRawExpr *query_ref = NULL; + ObSEArray candi_cols; + if (OB_ISNULL(cond)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("cond is NULL", K(ret)); + } else if (cond->get_expr_type() == T_OP_EXISTS) { + if (cond->get_param_count() != 1 || OB_ISNULL(cond->get_param_expr(0)) || + !cond->get_param_expr(0)->is_query_ref_expr()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected expr", K(ret)); + } else if (OB_FALSE_IT(query_ref = static_cast(cond->get_param_expr(0)))) { + } else if (OB_FAIL(extract_pushdown_cols(*query_ref, cur_table_id, candi_cols))) { + LOG_WARN("failed to extract pushdown cols", K(ret)); + } else { + for (int64_t j = 0; OB_SUCC(ret) && !found && j < candi_cols.count(); ++j) { + if (ObOptimizerUtil::find_item(mapped_col_exprs, candi_cols.at(j))) { + found = true; + if (OB_FAIL(add_var_to_array_no_dup(semi_join_stmt_ids, parent_stmt.stmt_id_))) { + LOG_WARN("failed to add var to array no dup", K(ret)); + } + } + } + } + } else if ((cond->has_flag(IS_WITH_ANY) || cond->has_flag(IS_WITH_ALL)) && + IS_SUBQUERY_COMPARISON_OP(cond->get_expr_type())) { + ObColumnRefRawExpr *col = NULL; + if (cond->get_param_count() != 2 || OB_ISNULL(cond->get_param_expr(0)) || + OB_ISNULL(cond->get_param_expr(1))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected expr", K(ret)); + } else if (cond->get_param_expr(0)->is_column_ref_expr() && + OB_FALSE_IT(col = static_cast(cond->get_param_expr(0))) && + OB_FAIL(candi_cols.push_back(col))) { + LOG_WARN("failed to push back column expr", K(ret)); + } else if (!cond->get_param_expr(1)->is_query_ref_expr()) { + // do nothing + } else if (OB_FALSE_IT(query_ref = static_cast(cond->get_param_expr(1)))) { + } else if (OB_FAIL(extract_pushdown_cols(*query_ref, cur_table_id, candi_cols))) { + LOG_WARN("failed to extract pushdown cols", K(ret)); + } else { + for (int64_t j = 0; OB_SUCC(ret) && !found && j < candi_cols.count(); ++j) { + if (ObOptimizerUtil::find_item(mapped_col_exprs, candi_cols.at(j))) { + found = true; + if (OB_FAIL(add_var_to_array_no_dup(semi_join_stmt_ids, parent_stmt.stmt_id_))) { + LOG_WARN("failed to add var to array no dup", K(ret)); + } + } + } + } + } + } + return ret; +} + +/** + * @brief can_push_dynamic_filter_to_cols + * check if any dynamic filter of select item can be pushed down to the input column set. + * NOTE: This is not a strict check, will miss some scenarios with group by and window functions. (fd, equal sets ...) + * @param col_exprs input column (sub)set of table item + * @param sel_idxs idxs of select items that can pushdown dynamic filter to input column set + */ +int ObTransformTempTable::can_push_dynamic_filter_to_cols(const ObSelectStmt *stmt, + const ObIArray &col_exprs, + uint64_t table_id, + ObIArray &sel_idxs, + bool &can_filter_pushdown) +{ + int ret = OB_SUCCESS; + bool has_rownum = false; + bool on_null_side = false; + ObSEArray tmp_col_exprs; + can_filter_pushdown = true; + sel_idxs.reuse(); + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("stmt is NULL", K(ret)); + } else if (OB_FAIL(stmt->has_rownum(has_rownum))) { + LOG_WARN("failed to check stmt has rownum", K(ret)); + } else if (OB_FAIL(ObOptimizerUtil::is_table_on_null_side(stmt, table_id, on_null_side))) { + LOG_WARN("failed to check table on null side", K(ret)); + } else if (stmt->is_hierarchical_query() || on_null_side || has_rownum || stmt->has_limit() || + stmt->has_sequence() || stmt->is_contains_assignment() || stmt->is_scala_group_by()) { + can_filter_pushdown = false; + } else if (OB_FAIL(append(tmp_col_exprs, col_exprs))) { + LOG_WARN("failed to assign column exprs", K(ret)); + } else if (stmt->get_group_exprs().count() > 0 && + OB_FAIL(ObOptimizerUtil::intersect_exprs(tmp_col_exprs, stmt->get_group_exprs(), tmp_col_exprs))) { + LOG_WARN("failed to intersect exprs", K(ret)); + } else if (stmt->has_window_function()) { + for (int64_t i = 0; OB_SUCC(ret) && !tmp_col_exprs.empty() && i < stmt->get_window_func_count(); ++i) { + const ObWinFunRawExpr *win_expr = NULL; + if (OB_ISNULL(win_expr = stmt->get_window_func_expr(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("window function expr is null", K(ret)); + } else if (OB_FAIL(ObOptimizerUtil::intersect_exprs(tmp_col_exprs, + win_expr->get_partition_exprs(), + tmp_col_exprs))) { + LOG_WARN("failed to intersect expr array", K(ret)); + } + } + } + if (OB_SUCC(ret) && can_filter_pushdown && !tmp_col_exprs.empty()) { + for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_select_items().count(); ++i) { + const SelectItem &sel_item = stmt->get_select_item(i); + if (OB_ISNULL(sel_item.expr_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("select item expr is NULL", K(ret)); + } else if (ObOptimizerUtil::find_item(tmp_col_exprs, sel_item.expr_)) { + if (OB_FAIL(sel_idxs.push_back(i))) { + LOG_WARN("failed to push back select item idx", K(ret)); + } + } + } + } + if (OB_SUCC(ret)) { + can_filter_pushdown &= !sel_idxs.empty(); + } + return ret; +} + +/** + * @brief get_parent_stmt + * @param table_id refers to the corresponding table id in parent_stmt, if stmt is a generated table query. + * otherwise, it equals to OB_INVALID_ID. + * @param parent_stmt returns NULL if stmt has no parent + */ +int ObTransformTempTable::get_parent_stmt(const ObSelectStmt *stmt, + const hash::ObHashMap &parent_map, + uint64_t &table_id, + ObDMLStmt *&parent_stmt) +{ + int ret = OB_SUCCESS; + table_id = OB_INVALID_ID; + parent_stmt = NULL; + ObParentDMLStmt parent; + uint64_t key = 0; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("stmt is NULL", K(ret)); + } else if (OB_FALSE_IT(key = reinterpret_cast(stmt))) { + } else if (OB_FAIL(parent_map.get_refactored(key, parent))) { + if (ret == OB_HASH_NOT_EXIST) { + ret = OB_SUCCESS; + } else { + LOG_WARN("failed to get value", K(ret)); + } + } else if (OB_ISNULL(parent_stmt = parent.stmt_)) { + // parent_stmt is null means stmt is a temp table query + // do nothing + } else { + // find generated table id + bool found = false; + for (int64_t i = 0; OB_SUCC(ret) && !found && i < parent_stmt->get_table_size(); ++i) { + const TableItem *table_item = NULL; + if (OB_ISNULL(table_item = parent_stmt->get_table_item(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("table item is NULL", K(ret)); + } else if (table_item->is_generated_table() && table_item->ref_query_ == stmt) { + table_id = table_item->table_id_; + found = true; + } + } + } + return ret; +} + +int ObTransformTempTable::add_semi_to_inner_hint_if_need(ObDMLStmt *copy_root_stmt, + ObIArray &semi_join_stmt_ids) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(copy_root_stmt) || OB_ISNULL(ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("copy_root_stmt is NULL", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < semi_join_stmt_ids.count(); ++i) { + ObDMLStmt *dml_stmt = NULL; + ObSelectStmt *sub_stmt = NULL; + ObString qb_name; + ObSemiToInnerHint *hint = NULL; + const ObQueryHint *query_hint = NULL; + if (OB_FAIL(copy_root_stmt->get_stmt_by_stmt_id(semi_join_stmt_ids.at(i), dml_stmt))) { + LOG_WARN("failed to get stmt by stmt id", K(ret)); + } else if (OB_ISNULL(dml_stmt) || !dml_stmt->is_select_stmt()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected stmt", K(ret)); + } else if (OB_FALSE_IT(sub_stmt = static_cast(dml_stmt))) { + } else if (OB_ISNULL(query_hint = sub_stmt->get_stmt_hint().query_hint_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret), K(query_hint)); + } else if (query_hint->has_outline_data() || query_hint->has_user_def_outline()) { + // do nothing + } else if (OB_FAIL(ObQueryHint::create_hint(ctx_->allocator_, T_SEMI_TO_INNER, hint))) { + LOG_WARN("failed to create hint", K(ret)); + } else if (OB_ISNULL(hint)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null", K(ret)); + } else if (OB_FAIL(sub_stmt->get_qb_name(qb_name))) { + LOG_WARN("failed to get qb name", K(ret)); + } else if (OB_FAIL(sub_stmt->get_stmt_hint().normal_hints_.push_back(hint))) { + LOG_WARN("failed to push back hint", K(ret)); + } + } + } + return ret; +} + +int ObTransformTempTable::check_inline_temp_table_by_cost(ObDMLStmt *root_stmt, + TempTableInfo &temp_table_info, + bool &need_inline) +{ + int ret = OB_SUCCESS; + ObSEArray inline_stmts; + ObSEArray copy_inline_stmts; + ObDMLStmt *inline_root = NULL; + ObSEArray materialize_stmts; + ObSEArray copy_materialize_stmts; + ObSelectStmt *packed_temp_table_query = NULL; + ObDMLStmt *materialize_root = NULL; + ObSelectStmt *copy_cte_stmt = NULL; + ObTryTransHelper trans_helper; + ObSelectStmt *dummy = NULL; + ObSEArray stmt_ptrs; + ObSEArray choosed_inline_idxs; + ObSEArray choosed_materialize_idxs; + OPT_TRACE("try cost based inline"); + if (OB_ISNULL(root_stmt) || OB_ISNULL(ctx_) || OB_ISNULL(ctx_->stmt_factory_) || + OB_ISNULL(temp_table_info.temp_table_query_) || OB_ISNULL(ctx_->expr_factory_) || + temp_table_info.table_items_.count() != temp_table_info.upper_stmts_.count()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("error unexpect", K(ret)); + } else if (OB_FAIL(trans_helper.fill_helper(root_stmt->get_query_ctx()))) { + LOG_WARN("failed to fill helper", K(ret)); + } else if(OB_FAIL(prepare_inline_materialize_stmts(root_stmt, + temp_table_info, + stmt_ptrs, + inline_stmts, + materialize_stmts, + packed_temp_table_query))) { + LOG_WARN("failed to prepare inline materialize stmts", K(ret)); + } + // to facilitate the copying and replacement of inline_stmts and materialize_stmts, + // temporarily change the table type from TEMP_TABLE to GENERATED_TABLE. + for (int64_t i = 0; OB_SUCC(ret) && i < temp_table_info.table_items_.count(); i++) { + if (OB_ISNULL(temp_table_info.table_items_.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null table item", K(ret)); + } else { + temp_table_info.table_items_.at(i)->type_ = TableItem::GENERATED_TABLE; + } + } + // deep copy root and replace inline_stmts and materialize_stmts + if (OB_FAIL(ret)) { + } else if (OB_FAIL(copy_and_replace_trans_root(*root_stmt, + inline_stmts, + NULL, + stmt_ptrs, + inline_root, + copy_inline_stmts, + dummy, + false))) { + LOG_WARN("failed to prepare eval cte cost stmt", K(ret)); + } else if (OB_FAIL(copy_and_replace_trans_root(*root_stmt, + materialize_stmts, + packed_temp_table_query, + stmt_ptrs, + materialize_root, + copy_materialize_stmts, + copy_cte_stmt, + false))) { + LOG_WARN("failed to prepare eval cte cost stmt", K(ret)); + } + // evaluate cost + if (OB_FAIL(ret)) { + } else if (OB_FAIL(evaluate_inline_materialize_costs(root_stmt, + false, + inline_root, + copy_inline_stmts, + materialize_root, + copy_materialize_stmts, + copy_cte_stmt, + choosed_inline_idxs, + choosed_materialize_idxs))) { + LOG_WARN("failed to evaluate inline materialize cost", K(ret)); + } else if (choosed_inline_idxs.count() > 0) { + need_inline = true; + OPT_TRACE("accept inline CTE due to cost"); + } else { + need_inline = false; + OPT_TRACE("reject inline CTE due to cost"); + ObString qb_name; + if (OB_FAIL(temp_table_info.temp_table_query_->get_qb_name(qb_name))) { + LOG_WARN("failed to get qb name", K(ret)); + } else if (OB_FAIL(ctx_->inline_blacklist_.push_back(qb_name))) { + LOG_WARN("failed to push back qb name", K(ret)); + } + } + // recover origin table item type back to TEMP_TABLE + for (int64_t i = 0; OB_SUCC(ret) && i < temp_table_info.table_items_.count(); i++) { + if (OB_ISNULL(temp_table_info.table_items_.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null table item", K(ret)); + } else { + temp_table_info.table_items_.at(i)->type_ = TableItem::TEMP_TABLE; + } + } + // recover context + if (OB_FAIL(ret)) { + } else if (OB_FAIL(trans_helper.recover(root_stmt->get_query_ctx()))) { + LOG_WARN("failed to recover helper", K(ret)); + } + // free inline_stmts and materialize_stmts + // note: inline_root, materialize_root, copy_inline_stmts and copy_materialize_stmts + // are already freed after cost evaluation + for (int64_t i = 0; OB_SUCC(ret) && i < inline_stmts.count(); ++i) { + if (OB_FAIL(ObTransformUtils::free_stmt(*ctx_->stmt_factory_, inline_stmts.at(i)))) { + LOG_WARN("failed to free stmt", K(ret)); + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < materialize_stmts.count(); ++i) { + if (OB_FAIL(ObTransformUtils::free_stmt(*ctx_->stmt_factory_, materialize_stmts.at(i)))) { + LOG_WARN("failed to free stmt", K(ret)); + } + } + return ret; +} + +int ObTransformTempTable::prepare_inline_materialize_stmts(ObDMLStmt *root_stmt, + TempTableInfo &temp_table_info, + ObIArray &stmt_ptrs, + ObIArray &inline_stmts, + ObIArray &materialize_stmts, + ObSelectStmt *&packed_temp_table_query) +{ + int ret = OB_SUCCESS; + ObDMLStmt *copied_temp_stmt = NULL; + ObSelectStmt *temp_view = NULL; + TableItem *temp_table = NULL; + if (OB_ISNULL(ctx_) || OB_ISNULL(ctx_->stmt_factory_) || OB_ISNULL(ctx_->expr_factory_) || + OB_ISNULL(ctx_->allocator_) || OB_ISNULL(temp_table_info.temp_table_query_) || OB_ISNULL(root_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null ctx", K(ret)); + } + + // prepare materialize stmts + if (OB_FAIL(ret)) { + } else if (OB_FAIL(ObTransformUtils::deep_copy_stmt(*ctx_->stmt_factory_, + *ctx_->expr_factory_, + temp_table_info.temp_table_query_, + copied_temp_stmt))) { + LOG_WARN("failed to deep copy stmt", K(ret)); + } else if (OB_ISNULL(copied_temp_stmt) || !copied_temp_stmt->is_select_stmt()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect stmt", K(ret)); + } else if (OB_FALSE_IT(temp_view = static_cast(copied_temp_stmt))) { + // 在 temp table query 上封一层视图(用以获取 temp table access 的代价) + } else if (ObTransformUtils::pack_stmt(ctx_, temp_view)) { + LOG_WARN("failed to create simple view", K(ret)); + } else if (1 != temp_view->get_table_size()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expect one table item in stmt", KPC(temp_view), K(ret)); + } else if (OB_ISNULL(temp_table = temp_view->get_table_item(0))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null table item", K(ret)); + } else if (!temp_table->is_generated_table()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expect generate table item", KPC(temp_table), K(ret)); + } else if (OB_ISNULL(temp_table->ref_query_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null ref query", K(ret)); + } else { + temp_table->type_ = TableItem::TEMP_TABLE; + packed_temp_table_query = temp_table->ref_query_; + if (OB_FAIL(temp_view->generate_view_name(*ctx_->allocator_, + temp_table->table_name_, + true))) { + LOG_WARN("failed to generate view name", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < temp_table_info.table_items_.count(); ++i) { + TableItem *table_item = temp_table_info.table_items_.at(i); + ObDMLStmt *materialize_stmt = NULL; + if (i == 0) { + materialize_stmt = temp_view; + if (OB_FAIL(materialize_stmts.push_back(static_cast(materialize_stmt)))) { + LOG_WARN("failed to push back stmt", K(ret)); + } + } else if (OB_FAIL(ObTransformUtils::deep_copy_stmt(*ctx_->stmt_factory_, + *ctx_->expr_factory_, + temp_view, + materialize_stmt))) { + LOG_WARN("failed to deep copy stmt", K(ret)); + } else if (OB_ISNULL(materialize_stmt) || !materialize_stmt->is_select_stmt()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect stmt", K(ret)); + } else if (OB_FAIL(materialize_stmt->recursive_adjust_statement_id(ctx_->allocator_, + ctx_->src_hash_val_, + i))) { + LOG_WARN("failed to recursive adjust statement id", K(ret)); + } else if (OB_FAIL(materialize_stmt->formalize_stmt(ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt", K(ret)); + } else if (OB_FAIL(materialize_stmt->update_stmt_table_id(ctx_->allocator_, *temp_view))) { + LOG_WARN("failed to update table id", K(ret)); + } else if (OB_FAIL(materialize_stmt->formalize_stmt_expr_reference(ctx_->expr_factory_, + ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt reference", K(ret)); + } else if (OB_FAIL(materialize_stmts.push_back(static_cast(materialize_stmt)))) { + LOG_WARN("failed to push back stmt", K(ret)); + } + } + } + + // prepare inline stmts + for (int64_t i = 0; OB_SUCC(ret) && i < temp_table_info.table_items_.count(); ++i) { + TableItem *table_item = temp_table_info.table_items_.at(i); + ObSelectStmtPointer stmt_ptr; + ObDMLStmt *materialize_stmt = NULL; + ObDMLStmt *inline_stmt = NULL; + if (OB_ISNULL(table_item) || OB_ISNULL(table_item->ref_query_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null", K(ret)); + } else if (OB_FAIL(stmt_ptr.add_ref(&table_item->ref_query_))) { + LOG_WARN("failed to add ref query", K(ret)); + } else if (OB_FAIL(stmt_ptrs.push_back(stmt_ptr))) { + LOG_WARN("failed to push back stmt ptr", K(ret)); + } else if (OB_FAIL(ObTransformUtils::deep_copy_stmt(*ctx_->stmt_factory_, + *ctx_->expr_factory_, + temp_table_info.temp_table_query_, + inline_stmt))) { + LOG_WARN("failed to deep copy stmt", K(ret)); + } else if (OB_ISNULL(inline_stmt) || !inline_stmt->is_select_stmt()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect stmt", K(ret)); + } else if (OB_FAIL(inline_stmt->recursive_adjust_statement_id(ctx_->allocator_, + ctx_->src_hash_val_, + i))) { + LOG_WARN("failed to recursive adjust statement id", K(ret)); + } else if (OB_FAIL(inline_stmt->update_stmt_table_id(ctx_->allocator_, *temp_table_info.temp_table_query_))) { + LOG_WARN("failed to update table id", K(ret)); + } else if (OB_FAIL(inline_stmt->formalize_stmt(ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt", K(ret)); + } else if (OB_FAIL(inline_stmt->formalize_stmt_expr_reference(ctx_->expr_factory_, + ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt reference", K(ret)); + } else if (OB_FAIL(inline_stmts.push_back(static_cast(inline_stmt)))) { + LOG_WARN("failed to push back stmt", K(ret)); + } + } + return ret; +} + +int ObTransformTempTable::evaluate_inline_materialize_costs(ObDMLStmt *origin_root, + bool need_check_plan, + ObDMLStmt *inline_root, + ObIArray ©_inline_stmts, + ObDMLStmt *materialize_root, + ObIArray ©_materialize_stmts, + ObSelectStmt *copy_cte_stmt, + ObIArray &choosed_inline_idxs, + ObIArray &choosed_materialize_idxs) +{ + int ret = OB_SUCCESS; + hash::ObHashMap parent_map; + ObSEArray dummy; + ObSEArray semi_join_stmt_ids; + bool check_global_cost = false; + if (OB_ISNULL(inline_root) || OB_ISNULL(materialize_root) || OB_ISNULL(ctx_) || + OB_ISNULL(copy_cte_stmt) || OB_UNLIKELY(copy_inline_stmts.count() != copy_materialize_stmts.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect error", K(ret)); + } else if (OB_FAIL(parent_map.create(128, "TempTable"))) { + LOG_WARN("failed to init stmt map", K(ret)); + } else if (OB_FAIL(ObTransformUtils::get_all_child_stmts(inline_root, dummy, &parent_map))) { + LOG_WARN("failed to get all child stmts", K(ret)); + } else if (OB_FAIL(need_check_global_cte_cost(inline_root, + copy_inline_stmts, + parent_map, + copy_cte_stmt, + semi_join_stmt_ids, + check_global_cost))) { + LOG_WARN("failed to check need global cost check", K(ret)); + } else if (OB_FAIL(parent_map.destroy())) { + LOG_WARN("failed to destroy map", K(ret)); + } + // evaluate cost globally + if (OB_SUCC(ret) && check_global_cost) { + double inline_global_cost = 0.0; + double materialize_global_cost = 0.0; + if (OB_FAIL(evaluate_cte_cost_globally(origin_root, + inline_root, + semi_join_stmt_ids, + need_check_plan, + inline_global_cost))) { + LOG_WARN("failed to evaluate cost for the origin stmt", K(ret)); + } else if (OB_FAIL(evaluate_cte_cost_globally(origin_root, + materialize_root, + semi_join_stmt_ids, + false, + materialize_global_cost))) { + LOG_WARN("failed to evaluate cost for the transform stmt", K(ret)); + } else { + OPT_TRACE("The global cost of inline stmt:", inline_global_cost); + OPT_TRACE("The global cost of materialize stmt:", materialize_global_cost); + if (materialize_global_cost >= inline_global_cost) { + for (int64_t i = 0; OB_SUCC(ret) && i < copy_inline_stmts.count(); ++i) { + if (OB_FAIL(choosed_inline_idxs.push_back(i))) { + LOG_WARN("failed to push back", K(ret)); + } + } + OPT_TRACE("choose `inline` due to global cost check"); + LOG_TRACE("choose `inline` due to global cost check", K(inline_global_cost), K(materialize_global_cost)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < copy_materialize_stmts.count(); ++i) { + if (OB_FAIL(choosed_materialize_idxs.push_back(i))) { + LOG_WARN("failed to push back", K(ret)); + } + } + OPT_TRACE("choose `materialize` due to global cost check"); + LOG_TRACE("choose `materialize` due to global cost check", K(inline_global_cost), K(materialize_global_cost)); + } + } + } + // evaluate cost partially + if (OB_SUCC(ret) && !check_global_cost) { + ObSEArray inline_costs; + ObSEArray materialize_costs; + double dummy = 0.0; + double cte_cost = 0.0; + double cte_profit = 0.0; + if (OB_FAIL(evaluate_cte_cost_partially(inline_root, + copy_inline_stmts, + inline_costs, + NULL, + dummy))) { + LOG_WARN("failed to evaluate cost for the origin stmt", K(ret)); + } else if (OB_FAIL(evaluate_cte_cost_partially(materialize_root, + copy_materialize_stmts, + materialize_costs, + copy_cte_stmt, + cte_cost))) { + LOG_WARN("failed to evaluate cost for the transform stmt", K(ret)); + } else if (OB_UNLIKELY(inline_costs.count() != materialize_costs.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected array size", K(inline_costs), K(materialize_costs)); + } else { + // accumulate materialize profit + for (int64_t i = 0; OB_SUCC(ret) && i < inline_costs.count(); i++) { + if (inline_costs.at(i) > materialize_costs.at(i)) { + cte_profit += inline_costs.at(i) - materialize_costs.at(i); + if (OB_FAIL(choosed_materialize_idxs.push_back(i))) { + LOG_WARN("failed to push back", K(ret)); + } + } else if (OB_FAIL(choosed_inline_idxs.push_back(i))) { + LOG_WARN("failed to push back", K(ret)); + } + } + OPT_TRACE("The cost of materialize cte :", cte_cost); + OPT_TRACE("The profit of materialize cte :", cte_profit); + // inline all references if the profit of materialize cte is less than the cost + if (OB_FAIL(ret)) { + } else if (cte_profit <= cte_cost || choosed_materialize_idxs.count() <= 1) { + if (OB_FAIL(append(choosed_inline_idxs, choosed_materialize_idxs))) { + LOG_WARN("failed to push back", K(ret)); + } else { + choosed_materialize_idxs.reset(); + OPT_TRACE("choose `inline` due to partial cost check"); + LOG_TRACE("choose `inline` due to partial cost check", K(cte_cost), K(cte_profit)); + } + } else { + OPT_TRACE("choose `materialize` due to partial cost check"); + LOG_TRACE("choose `materialize` due to partial cost check", K(cte_cost), K(cte_profit)); + } + } + } + return ret; +} + int ObTransformTempTable::prepare_eval_cte_cost_stmt(ObDMLStmt &root_stmt, ObIArray &trans_stmts, ObSelectStmt *cte_query, @@ -2638,5 +3838,261 @@ int ObTransformTempTable::prepare_eval_cte_cost_stmt(ObDMLStmt &root_stmt, return ret; } +int ObTransformTempTable::copy_and_replace_trans_root(ObDMLStmt &root_stmt, + ObIArray &trans_stmts, + ObSelectStmt *cte_query, + ObIArray &stmt_ptrs, + ObDMLStmt *&copied_stmt, + ObIArray &copied_trans_stmts, + ObSelectStmt *&copied_cte_query, + bool is_trans_stmt) +{ + int ret = OB_SUCCESS; + ObSEArray old_temp_table_stmts; + ObSEArray new_temp_table_stmts; + ObSEArray origin_stmts; + ObDMLStmt *copied_trans_stmt = NULL; + ObString cur_qb_name; + ObDMLStmt *temp = NULL; + hash::ObHashMap copy_stmt_map; + ObDMLStmt *dml_stmt_val = NULL; + if (OB_ISNULL(ctx_) || OB_UNLIKELY(!ctx_->is_valid()) || OB_ISNULL(root_stmt.get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("params are invalid", K(ret), K(ctx_), K(root_stmt.get_query_ctx())); + } else if (OB_FAIL(adjust_transformed_stmt(stmt_ptrs, trans_stmts, &origin_stmts))) { + LOG_WARN("failed to adjust transformed stmt", K(ret)); + } else if (OB_FAIL(ObTransformUtils::deep_copy_stmt(*ctx_->stmt_factory_, *ctx_->expr_factory_, + &root_stmt, copied_stmt))) { + LOG_WARN("failed to deep copy stmt", K(ret)); + } else if (OB_FAIL(deep_copy_temp_table(*copied_stmt, + *ctx_->stmt_factory_, + *ctx_->expr_factory_, + old_temp_table_stmts, + new_temp_table_stmts))) { + LOG_WARN("failed to deep copy temp table", K(ret)); + } else if (OB_FAIL(copy_stmt_map.create(128, "TempTable"))) { + LOG_WARN("failed to init stmt map", K(ret)); + } else if (OB_FAIL(ObTransformUtils::get_stmt_map_after_copy(&root_stmt, copied_stmt, copy_stmt_map))) { + LOG_WARN("failed to get stmt map", K(ret)); + } else if (NULL != cte_query) { + uint64_t key = reinterpret_cast(cte_query); + if (OB_FAIL(copy_stmt_map.get_refactored(key, dml_stmt_val))) { + LOG_WARN("failed to get hash map", K(ret)); + } else if (OB_ISNULL(dml_stmt_val) || OB_UNLIKELY(!dml_stmt_val->is_select_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected stmt", K(ret), KPC(dml_stmt_val)); + } else { + copied_cte_query = static_cast(dml_stmt_val); + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < trans_stmts.count(); i ++) { + dml_stmt_val = NULL; + uint64_t key = reinterpret_cast(trans_stmts.at(i)); + if (OB_FAIL(copy_stmt_map.get_refactored(key, dml_stmt_val))) { + LOG_WARN("failed to get stmt from hash map", K(ret)); + } else if (OB_ISNULL(dml_stmt_val) || OB_UNLIKELY(!dml_stmt_val->is_select_stmt())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected stmt", K(ret), KPC(dml_stmt_val)); + } else if (OB_FAIL(copied_trans_stmts.push_back(static_cast(dml_stmt_val)))) { + LOG_WARN("failed to push back", K(ret)); + } + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(copy_stmt_map.destroy())) { + LOG_WARN("failed to destroy map", K(ret)); + } else if (OB_FAIL(adjust_transformed_stmt(stmt_ptrs, origin_stmts, NULL))) { + LOG_WARN("failed to adjust transformed stmt", K(ret)); + } + if (OB_FAIL(ret)) { + } else if (OB_FAIL(copied_stmt->formalize_stmt(ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt", K(ret)); + } else if (OB_FAIL(copied_stmt->formalize_stmt_expr_reference(ctx_->expr_factory_, + ctx_->session_info_))) { + LOG_WARN("failed to formalize stmt", K(ret)); + } + return ret; +} + +int ObTransformTempTable::pick_out_stmts_in_blacklist(const ObIArray &blacklist, + ObIArray &origin_stmts, + ObIArray &trans_stmts, + ObIArray &stmt_ptrs) +{ + int ret = OB_SUCCESS; + ObSEArray picked_origin_stmts; + ObSEArray picked_trans_stmts; + ObSEArray picked_stmt_ptrs; + if (OB_UNLIKELY(origin_stmts.count() != trans_stmts.count() || + origin_stmts.count() != stmt_ptrs.count())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected stmt count", K(ret), K(origin_stmts.count()), K(trans_stmts.count()), K(stmt_ptrs.count())); + } + for (int64_t i = 0; OB_SUCC(ret) && i < origin_stmts.count(); i++) { + ObSelectStmt *origin_stmt = origin_stmts.at(i); + ObString qb_name; + if (OB_ISNULL(origin_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null stmt", K(ret)); + } else if (OB_FAIL(origin_stmt->get_qb_name(qb_name))) { + LOG_WARN("failed to get qb name", K(ret)); + } else if (ObOptimizerUtil::find_item(blacklist, qb_name)) { + //do nothing + } else if (OB_FAIL(picked_origin_stmts.push_back(origin_stmts.at(i)))) { + LOG_WARN("failed to push back", K(ret)); + } else if (OB_FAIL(picked_trans_stmts.push_back(trans_stmts.at(i)))) { + LOG_WARN("failed to push back", K(ret)); + } else if (OB_FAIL(picked_stmt_ptrs.push_back(stmt_ptrs.at(i)))) { + LOG_WARN("failed to push back", K(ret)); + } + } + if (OB_FAIL(ret) || origin_stmts.count() == picked_origin_stmts.count()) { + // do nothing + } else if (OB_FAIL(origin_stmts.assign(picked_origin_stmts))) { + LOG_WARN("failed to assign", K(ret)); + } else if (OB_FAIL(trans_stmts.assign(picked_trans_stmts))) { + LOG_WARN("failed to assign", K(ret)); + } else if (OB_FAIL(stmt_ptrs.assign(picked_stmt_ptrs))) { + LOG_WARN("failed to assign", K(ret)); + } + return ret; +} + +int ObTransformTempTable::gather_materialize_blacklist(ObLogicalOperator *op, + ObIArray &blacklist) +{ + int ret = OB_SUCCESS; + ObLogJoin *join_op = NULL; + ObLogSubPlanScan *subplan_scan_op = NULL; + if (OB_ISNULL(op)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null param", K(ret)); + } else if (log_op_def::LOG_JOIN != op->get_type()) { + // do nothing + } else if (OB_FALSE_IT(join_op = static_cast(op))) { + } else if (!join_op->is_nlj_with_param_down()) { + // do nothing + } else if (OB_ISNULL(join_op->get_right_table())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null param", K(ret)); + } else if (join_op->get_right_table()->get_type() != log_op_def::LOG_SUBPLAN_SCAN) { + // do nothing + } else if (OB_FALSE_IT(subplan_scan_op = static_cast(join_op->get_right_table()))) { + } else if (OB_FAIL(blacklist.push_back(subplan_scan_op->get_subquery_id()))) { + LOG_WARN("failed to push back", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < op->get_num_of_child(); ++i) { + if (OB_FAIL(SMART_CALL(gather_materialize_blacklist(op->get_child(i), blacklist)))) { + LOG_WARN("failed to inner gather materialize blacklist", K(ret)); + } + } + return ret; +} + +int ObTransformTempTable::get_all_view_stmts(ObDMLStmt *stmt, + ObIArray &view_stmts) +{ + int ret = OB_SUCCESS; + ObSEArray child_stmts; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null stmt", K(ret)); + } else if (stmt->is_set_stmt()) { + if (OB_FAIL(stmt->get_child_stmts(child_stmts))) { + LOG_WARN("failed to get child stmts", K(ret)); + } else if (OB_FAIL(append_array_no_dup(view_stmts, child_stmts))) { + LOG_WARN("failed to append array", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) { + if (OB_FAIL(SMART_CALL(get_all_view_stmts(child_stmts.at(i), view_stmts)))) { + LOG_WARN("failed to get all view stmts", K(ret)); + } + } + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < stmt->get_table_size(); i++) { + if (OB_ISNULL(stmt->get_table_item(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null table item", K(ret)); + } else if (!stmt->get_table_item(i)->is_generated_table() && + !stmt->get_table_item(i)->is_temp_table()) { + // do nothing + } else if (OB_FAIL(add_var_to_array_no_dup(view_stmts, stmt->get_table_item(i)->ref_query_))) { + LOG_WARN("failed to add var to array", K(ret)); + } else if (OB_FAIL(add_var_to_array_no_dup(child_stmts, stmt->get_table_item(i)->ref_query_))) { + LOG_WARN("failed to add var to array", K(ret)); + } + } + for (int64_t i = 0; OB_SUCC(ret) && i < child_stmts.count(); ++i) { + if (OB_FAIL(SMART_CALL(get_all_view_stmts(child_stmts.at(i), view_stmts)))) { + LOG_WARN("failed to get all view stmts", K(ret)); + } + } + } + return ret; +} + +int ObTransformTempTable::check_stmt_in_blacklist(const ObSelectStmt *stmt, + const ObIArray &blacklist, + bool &in_blacklist) +{ + int ret = OB_SUCCESS; + in_blacklist = false; + if (OB_ISNULL(ctx_) || OB_ISNULL(stmt) || OB_ISNULL(stmt->get_query_ctx())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null ctx", K(ret)); + } else { + const ObIArray &stmt_id_map = stmt->get_query_ctx()->get_query_hint().stmt_id_map_; + if (stmt->get_stmt_id() < 0 || stmt->get_stmt_id() >= stmt_id_map.count()) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect stmt id", K(ret), K(stmt->get_stmt_id()), K(stmt_id_map.count())); + } else { + const ObIArray &qb_names = stmt_id_map.at(stmt->get_stmt_id()).qb_names_; + for (int64_t i = 0; OB_SUCC(ret) && !in_blacklist && i < qb_names.count(); i++) { + if (ObOptimizerUtil::find_item(blacklist, qb_names.at(i))) { + in_blacklist = true; + } + } + } + } + return ret; +} + +int ObTransformTempTable::check_evaluate_after_transform(ObDMLStmt *root_stmt, + ObIArray &stmts, + bool &can_eval) +{ + int ret = OB_SUCCESS; + ObSEArray root_cte_infos; + ObSEArray all_ctes; + can_eval = true; + if (OB_ISNULL(root_stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null stmt", K(ret)); + } else if (OB_FAIL(root_stmt->collect_temp_table_infos(root_cte_infos))) { + LOG_WARN("failed to collect temp table infos", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < root_cte_infos.count(); ++i) { + if (OB_FAIL(all_ctes.push_back(root_cte_infos.at(i).temp_table_query_))) { + LOG_WARN("failed to add var to array", K(ret)); + } + } + } + for (int64_t i = 0; can_eval && OB_SUCC(ret) && i < stmts.count(); ++i) { + ObSEArray tmp_cte_infos; + if (OB_ISNULL(stmts.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpect null stmt", K(ret)); + } else if (OB_FAIL(stmts.at(i)->collect_temp_table_infos(tmp_cte_infos))) { + LOG_WARN("failed to collect temp table infos", K(ret)); + } else { + for (int64_t j = 0; can_eval && OB_SUCC(ret) && j < tmp_cte_infos.count(); ++j) { + if (!ObOptimizerUtil::find_item(all_ctes, tmp_cte_infos.at(j).temp_table_query_)) { + can_eval = false; + } + } + } + } + return ret; +} + }//namespace sql }//namespace oceanbase diff --git a/src/sql/rewrite/ob_transform_temp_table.h b/src/sql/rewrite/ob_transform_temp_table.h index 39ad534d2b..1b9cc42a2f 100644 --- a/src/sql/rewrite/ob_transform_temp_table.h +++ b/src/sql/rewrite/ob_transform_temp_table.h @@ -78,17 +78,13 @@ public: ObItemType trans_type_; }; - /** - * @brief expand_temp_table - * 如果temp table只被引用一次 - * 还原成generate table - */ - int expand_temp_table(ObIArray &temp_table_info, - bool &trans_happened); + int try_inline_temp_table(ObDMLStmt *root_stmt, + ObIArray &temp_table_infos, + bool &trans_happened); int check_stmt_size(ObDMLStmt *stmt, int64_t &total_size, bool &stmt_oversize); - int inner_expand_temp_table(ObDMLStmt::TempTableInfo &helper); + int inner_inline_temp_table(ObDMLStmt::TempTableInfo &helper); int check_stmt_can_materialize(ObSelectStmt *stmt, bool is_existing_cte, bool &is_valid); @@ -96,12 +92,12 @@ public: int generate_with_clause(ObDMLStmt *&stmt, bool &trans_happened); - int extract_common_subquery_as_cte(ObDMLStmt *stmt, + int extract_common_table_expression(ObDMLStmt *stmt, ObIArray &stmts, hash::ObHashMap &parent_map, bool &trans_happened); - int inner_extract_common_subquery_as_cte(ObDMLStmt &root_stmt, + int inner_extract_common_table_expression(ObDMLStmt &root_stmt, ObIArray &stmts, hash::ObHashMap &parent_map, bool &trans_happened); @@ -240,6 +236,14 @@ public: hash::ObHashMap &parent_map, bool force_accept, bool &trans_happened); + int accept_cte_transform_v2(ObDMLStmt &origin_root_stmt, + TableItem *temp_table, + common::ObIArray &origin_stmts, + common::ObIArray &trans_stmts, + common::ObIArray &accept_stmts, + hash::ObHashMap &parent_map, + bool force_accept, + bool &trans_happened); int prepare_eval_cte_cost_stmt(ObDMLStmt &root_stmt, ObIArray &trans_stmts, ObSelectStmt *cte_query, @@ -255,9 +259,86 @@ public: ObIArray &costs, TableItem *temp_table, double &temp_table_cost); + int evaluate_cte_cost_partially(ObDMLStmt *root_stmt, + ObIArray &stmts, + ObIArray &costs, + ObSelectStmt *cte_query, + double &temp_table_cost); + int evaluate_cte_cost_globally(ObDMLStmt *origin_root, + ObDMLStmt *root_stmt, + ObIArray &semi_join_stmt_ids, + bool need_check_plan, + double &global_cost); int adjust_transformed_stmt(ObIArray &stmt_ptrs, ObIArray &stmts, ObIArray *origin_stmts); + int need_check_global_cte_cost(const ObDMLStmt *root_stmt, + const ObIArray &origin_stmts, + const hash::ObHashMap &parent_map, + const ObSelectStmt *temp_table_query, + ObIArray &semi_join_stmt_ids, + bool &check_global_cost); + int get_parent_stmt(const ObSelectStmt *stmt, + const hash::ObHashMap &parent_map, + uint64_t &table_id, + ObDMLStmt *&parent_stmt); + int can_push_dynamic_filter_to_cols(const ObSelectStmt *sel_stmt, + const ObIArray &col_exprs, + uint64_t table_id, + ObIArray &sel_idxs, + bool &can_filter_pushdown); + int check_projected_cols_used_for_join(const ObSelectStmt *stmt, + const hash::ObHashMap &parent_map, + const ObIArray &sel_idxs, + ObIArray &semi_join_stmt_ids, + bool &used_for_join); + int extract_pushdown_cols(const ObQueryRefRawExpr &query_ref, + uint64_t cur_table_id, + ObIArray &pushdown_cols); + int collect_semi_join_stmt_ids(const ObDMLStmt &parent_stmt, + const ObIArray &mapped_col_exprs, + uint64_t cur_table_id, + ObIArray &semi_join_stmt_ids); + int add_semi_to_inner_hint_if_need(ObDMLStmt *copy_root_stmt, + ObIArray &semi_join_stmt_ids); + int check_inline_temp_table_by_cost(ObDMLStmt *root_stmt, + ObDMLStmt::TempTableInfo &temp_table_info, + bool &need_inline); + int prepare_inline_materialize_stmts(ObDMLStmt *root_stmt, + ObDMLStmt::TempTableInfo &temp_table_info, + ObIArray &stmt_ptrs, + ObIArray &inline_stmts, + ObIArray &materialize_stmts, + ObSelectStmt *&packed_temp_table_query); + int copy_and_replace_trans_root(ObDMLStmt &root_stmt, + ObIArray &trans_stmts, + ObSelectStmt *cte_query, + ObIArray &stmt_ptrs, + ObDMLStmt *&copied_stmt, + ObIArray &copied_trans_stmts, + ObSelectStmt *&copied_cte_query, + bool is_trans_stmt); + int evaluate_inline_materialize_costs(ObDMLStmt *origin_root, + bool need_check_plan, + ObDMLStmt *inline_root, + ObIArray ©_inline_stmts, + ObDMLStmt *materialize_root, + ObIArray ©_materialize_stmts, + ObSelectStmt *copy_cte_stmt, + ObIArray &choosed_inline_idxs, + ObIArray &choosed_materialize_idxs); + int pick_out_stmts_in_blacklist(const ObIArray &blacklist, + ObIArray &origin_stmts, + ObIArray &trans_stmts, + ObIArray &stmt_ptrs); + int gather_materialize_blacklist(ObLogicalOperator *op, ObIArray &blacklist); + int get_all_view_stmts(ObDMLStmt *stmt, ObIArray &view_stmts); + int check_stmt_in_blacklist(const ObSelectStmt *stmt, + const ObIArray &blacklist, + bool &in_blacklist); + int check_evaluate_after_transform(ObDMLStmt *root_stmt, + ObIArray &stmts, + bool &can_eval); private: ObArenaAllocator allocator_; TempTableTransParam *trans_param_; diff --git a/src/sql/rewrite/ob_transform_udt_utils.cpp b/src/sql/rewrite/ob_transform_udt_utils.cpp index 80b093495f..b651ac4504 100644 --- a/src/sql/rewrite/ob_transform_udt_utils.cpp +++ b/src/sql/rewrite/ob_transform_udt_utils.cpp @@ -272,6 +272,7 @@ int ObTransformUdtUtils::replace_udt_assignment_exprs(ObTransformerCtx *ctx, ObD ObExprResType res_type; res_type.set_varchar(); res_type.set_collation_type(CS_TYPE_UTF8MB4_BIN); + res_type.set_param(value_expr->get_result_type().get_param()); value_expr->set_result_type(res_type); } } diff --git a/src/sql/rewrite/ob_transform_utils.cpp b/src/sql/rewrite/ob_transform_utils.cpp index 091ed9ae11..a0f47b1bee 100644 --- a/src/sql/rewrite/ob_transform_utils.cpp +++ b/src/sql/rewrite/ob_transform_utils.cpp @@ -39,6 +39,7 @@ #include "sql/parser/ob_parser.h" #include "sql/rewrite/ob_transform_pre_process.h" #include "sql/rewrite/ob_expand_aggregate_utils.h" +#include "share/stat/ob_opt_stat_manager.h" namespace oceanbase { using namespace common; @@ -4077,146 +4078,6 @@ int ObTransformUtils::is_foreign_key_rely(ObSQLSessionInfo* session_info, return ret; } -int ObTransformUtils::check_stmt_limit_validity(ObTransformerCtx *ctx, - const ObSelectStmt *select_stmt, - bool &is_valid, - bool &need_add_const_constraint) -{ - int ret = OB_SUCCESS; - bool has_rownum = false; - ObPhysicalPlanCtx *plan_ctx = NULL; - is_valid = false; - if (OB_ISNULL(select_stmt) || OB_ISNULL(ctx) || OB_ISNULL(ctx->exec_ctx_) || - OB_ISNULL(plan_ctx = ctx->exec_ctx_->get_physical_plan_ctx())) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret), K(select_stmt), K(ctx), - K(ctx->exec_ctx_), K(plan_ctx)); - } else if (!select_stmt->has_limit() || - select_stmt->get_offset_expr() != NULL || - select_stmt->get_limit_percent_expr() != NULL) { - //do nothing - } else if (select_stmt->has_distinct() - || select_stmt->has_group_by() - || select_stmt->is_set_stmt() - || select_stmt->is_hierarchical_query() - || select_stmt->has_order_by() - || select_stmt->is_contains_assignment() - || select_stmt->has_window_function() - || select_stmt->has_sequence()) { - /*do nothing*/ - } else if (OB_FAIL(select_stmt->has_rownum(has_rownum))) { - LOG_WARN("failed to has rownum", K(ret)); - } else if (has_rownum) { - /*do nothing */ - } else { - bool is_null_value = false; - int64_t limit_value = 0; - if (OB_FAIL(ObTransformUtils::get_expr_int_value(select_stmt->get_limit_expr(), - &plan_ctx->get_param_store(), - ctx->exec_ctx_, - ctx->allocator_, - limit_value, - is_null_value))) { - LOG_WARN("failed to get_expr_int_value", K(ret)); - } else if (!is_null_value && limit_value >= 1) { - is_valid = true; - //Just in case different parameters hit same plan, firstly we need add const param constraint - need_add_const_constraint = true; - } - } - return ret; -} - -int ObTransformUtils::check_stmt_is_non_sens_dul_vals(ObTransformerCtx *ctx, - const ObDMLStmt *upper_stmt, - const ObDMLStmt *stmt, - bool &is_match, - bool &need_add_limit_constraint) -{ - int ret = OB_SUCCESS; - is_match = false; - need_add_limit_constraint = false; - if (OB_ISNULL(upper_stmt) || OB_ISNULL(stmt)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(upper_stmt), K(stmt), K(ret)); - } else { - for (int64_t i = 0; OB_SUCC(ret) && !is_match && i < upper_stmt->get_condition_size(); ++i) { - const ObRawExpr *cond_expr = upper_stmt->get_condition_expr(i); - if (OB_ISNULL(cond_expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null1", K(ret), K(cond_expr)); - } else if (OB_FAIL(check_stmt_is_non_sens_dul_vals_rec(ctx, - stmt, - cond_expr, - is_match, - need_add_limit_constraint))) { - LOG_WARN("failed to check semi join info", K(ret), K(*cond_expr)); - } else { - /*do nothing*/ - } - } - } - return ret; -} - -int ObTransformUtils::check_stmt_is_non_sens_dul_vals_rec(ObTransformerCtx *ctx, - const ObDMLStmt *stmt, - const ObRawExpr *expr, - bool &is_match, - bool &need_add_limit_constraint) -{ - int ret = OB_SUCCESS; - const ObRawExpr *param_expr = NULL; - const ObRawExpr *param_child = NULL; // child of param - if (OB_ISNULL(ctx) || OB_ISNULL(stmt) || OB_ISNULL(expr)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(ret)); - } else if (is_match) { - /*do nothing*/ - } else if (T_OP_EXISTS == expr->get_expr_type() || - T_OP_NOT_EXISTS == expr->get_expr_type()) { - if (OB_ISNULL(param_child = expr->get_param_expr(0))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null", K(param_child), K(ret)); - } else if (!param_child->is_query_ref_expr()) { - /*do nothing*/ - } else if (static_cast(param_child)->get_ref_stmt() == stmt) { - if (static_cast(param_child)->get_ref_stmt()->is_spj()) { - is_match = true; - } else if (OB_FAIL(check_stmt_limit_validity(ctx, - static_cast(param_child)->get_ref_stmt(), - is_match, - need_add_limit_constraint))) { - LOG_WARN("failed to check stmt limit validity", K(ret)); - } - } - } else if (expr->has_flag(IS_WITH_ALL) || - expr->has_flag(IS_WITH_ANY)) { - if (OB_ISNULL(param_expr = expr->get_param_expr(1))) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("NULL pointer error", K(param_expr), K(ret)); - } else if (!param_expr->is_query_ref_expr()) { - /*do nothing*/ - } else if (static_cast(param_expr)->get_ref_stmt() == stmt) { - is_match = static_cast(param_expr)->get_ref_stmt()->is_spj(); - } - } else { - for (int64_t i = 0; OB_SUCC(ret) && i < expr->get_param_count(); ++i) { - const ObRawExpr *param = expr->get_param_expr(i); - if (OB_ISNULL(param)) { - ret = OB_ERR_UNEXPECTED; - LOG_WARN("get unexpected null param", K(ret), K(*param)); - } else if (OB_FAIL(SMART_CALL(check_stmt_is_non_sens_dul_vals_rec(ctx, - stmt, - param, - is_match, - need_add_limit_constraint)))) { - LOG_WARN("failed to check semi join info recursively", K(ret), K(*param)); - } - } - } - return ret; -} int ObTransformUtils::check_exprs_unique(const ObDMLStmt &stmt, TableItem *table, const ObIArray &exprs, @@ -4549,6 +4410,7 @@ int ObTransformUtils::compute_set_stmt_property(const ObSelectStmt *stmt, check_helper.session_info_, stmt, set_exprs, equal_conds))) { LOG_WARN("failed to get equal set conditions", K(ret)); + } else if (FALSE_IT(res_info.equal_sets_.reuse())) { } else if (OB_FAIL(ObEqualAnalysis::compute_equal_set(check_helper.alloc_, equal_conds, tmp_equal_sets, res_info.equal_sets_))) { LOG_WARN("failed to compute compute equal set", K(ret)); @@ -5495,10 +5357,9 @@ int ObTransformUtils::get_table_joined_exprs(const ObSqlBitSet<> &source_ids, } else if (source_ids.is_superset2(child1->get_relation_ids()) && target_ids.is_superset2(child2->get_relation_ids())) { // child2 contain target exprs - if (OB_FAIL(ObRelationalExprOperator::is_equivalent(child1->get_result_type(), - child2->get_result_type(), - child2->get_result_type(), - is_valid))) { + if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive(child1->get_result_type(), + child2->get_result_type(), + is_valid))) { LOG_WARN("failed to check expr is equivalent", K(ret)); } else if (!is_valid) { LOG_TRACE("can not use child1 expr type as the (child1, child2) compare type"); @@ -5512,10 +5373,9 @@ int ObTransformUtils::get_table_joined_exprs(const ObSqlBitSet<> &source_ids, } else if (target_ids.is_superset2(child1->get_relation_ids()) && source_ids.is_superset2(child2->get_relation_ids())) { // child1 contain target column - if (OB_FAIL(ObRelationalExprOperator::is_equivalent(child2->get_result_type(), - child1->get_result_type(), - child1->get_result_type(), - is_valid))) { + if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive(child2->get_result_type(), + child1->get_result_type(), + is_valid))) { LOG_WARN("failed to check expr is equivalent", K(ret)); } else if (!is_valid) { LOG_TRACE("can not use child2 expr type as the (child2, child1) compare type"); @@ -5529,10 +5389,9 @@ int ObTransformUtils::get_table_joined_exprs(const ObSqlBitSet<> &source_ids, } else if (target_ids.is_superset2(child1->get_relation_ids()) && target_ids.is_superset2(child2->get_relation_ids())) { // child1 contain target column and child2 contain target column too. - if (OB_FAIL(ObRelationalExprOperator::is_equivalent(child1->get_result_type(), - child2->get_result_type(), - child2->get_result_type(), - is_valid))) { + if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive(child1->get_result_type(), + child2->get_result_type(), + is_valid))) { LOG_WARN("failed to check expr is equivalent", K(ret)); } else if (!is_valid) { LOG_TRACE("can not use child2 expr type as the (child2, child1) compare type"); @@ -5544,10 +5403,9 @@ int ObTransformUtils::get_table_joined_exprs(const ObSqlBitSet<> &source_ids, } else if (source_ids.is_superset2(child1->get_relation_ids()) && source_ids.is_superset2(child2->get_relation_ids())) { // child1 contain source column and child2 contain source column too. - if (OB_FAIL(ObRelationalExprOperator::is_equivalent(child2->get_result_type(), - child1->get_result_type(), - child1->get_result_type(), - is_valid))) { + if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive(child2->get_result_type(), + child1->get_result_type(), + is_valid))) { LOG_WARN("failed to check expr is equivalent", K(ret)); } else if (!is_valid) { LOG_TRACE("can not use child2 expr type as the (child2, child1) compare type"); @@ -5635,9 +5493,8 @@ int ObTransformUtils::is_equal_correlation(const ObIArray } } if (OB_SUCC(ret) && is_valid) { - if (OB_FAIL(ObRelationalExprOperator::is_equivalent( - left->get_result_type(), right->get_result_type(), - right->get_result_type(), is_valid))) { + if (OB_FAIL(ObRelationalExprOperator::is_equal_transitive( + left->get_result_type(), right->get_result_type(), is_valid))) { LOG_WARN("failed to check is expr result equivalent", K(ret)); } else if (!is_valid) { // left = right <=> group by right (right = right) @@ -10910,9 +10767,10 @@ int ObTransformUtils::replace_add_exprs_with_groupby_exprs(ObRawExpr *&expr_l, const ObObjParam &right_param = param_store.at(idx_right); if (!check_objparam_abs_equal(left_param, right_param)) { //do nothing. - } else if (OB_FAIL(add_neg_or_pos_constraint(trans_ctx, - static_cast(expr_r), - check_objparam_negative(right_param)))) { + } else if (OB_FAIL(add_compare_int_constraint(trans_ctx, + static_cast(expr_r), + check_objparam_negative(right_param) ? T_OP_LT : T_OP_GE, + 0))) { LOG_WARN("fail to add positive constraint to grouping sets"); } else if (check_objparam_negative(left_param) && !check_objparam_negative(right_param)) { // replace the expr with a T_OP_NEG expr who's child is groupby_exprs.at(k); @@ -10961,43 +10819,52 @@ bool ObTransformUtils::check_objparam_negative(const ObObjParam &obj1) { return is_neg; } -int ObTransformUtils::add_neg_or_pos_constraint(ObTransformerCtx *trans_ctx, - ObRawExpr *expr, - bool is_negative ) +int ObTransformUtils::add_compare_int_constraint(ObTransformerCtx *trans_ctx, + ObRawExpr *expr, + const ObItemType op_type, + int64_t val) { int ret = OB_SUCCESS; ObRawExprFactory *expr_factory = NULL; if (OB_ISNULL(trans_ctx) || OB_ISNULL(expr) || OB_ISNULL(trans_ctx->exec_ctx_)) { ret = OB_ERR_UNEXPECTED; - LOG_WARN("unexpected null expr", K(ret)); + LOG_WARN("unexpected null expr", K(ret), K(trans_ctx), K(expr)); } else if (OB_ISNULL(expr_factory = trans_ctx->exec_ctx_->get_expr_factory())) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null expr", K(ret)); - } else if (!expr->is_static_const_expr()) { + } else if (OB_UNLIKELY(T_OP_EQ != op_type + && T_OP_LE != op_type + && T_OP_LT != op_type + && T_OP_GE != op_type + && T_OP_GT != op_type + && T_OP_NE != op_type)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected op type", K(ret), K(op_type)); + } else if (OB_UNLIKELY(!expr->is_static_const_expr())) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("expr is not static const", K(ret), KPC(expr)); + } else if (!expr->has_flag(CNT_STATIC_PARAM)) { // do nothing } else { // construct expr >= 0; - ObConstRawExpr *zero_expr = NULL; + ObConstRawExpr *int_expr = NULL; ObOpRawExpr *true_expr = NULL; - if (OB_FAIL(expr_factory->create_raw_expr(T_INT, zero_expr))) { + if (OB_FAIL(expr_factory->create_raw_expr(T_INT, int_expr))) { LOG_WARN("create raw expr fail", K(ret)); - } else if (OB_ISNULL(zero_expr)) { + } else if (OB_ISNULL(int_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null expr", K(ret)); - } else if (!is_negative && OB_FAIL(expr_factory->create_raw_expr(T_OP_GE, true_expr))) { - LOG_WARN("create raw expr fail", K(ret)); - } else if (is_negative && OB_FAIL(expr_factory->create_raw_expr(T_OP_LT, true_expr))) { + } else if (OB_FAIL(expr_factory->create_raw_expr(op_type, true_expr))) { LOG_WARN("create raw expr fail", K(ret)); } else if (OB_ISNULL(true_expr)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpected null expr", K(ret)); - } else if (OB_FAIL(true_expr->set_param_exprs(static_cast(expr), - static_cast(zero_expr)))) { + } else if (OB_FAIL(true_expr->set_param_exprs(expr, int_expr))) { LOG_WARN("set param expr fail", K(ret)); } else { ObObj obj; - obj.set_int(ObIntType, 0); - zero_expr->set_value(obj); + obj.set_int(ObIntType, val); + int_expr->set_value(obj); } if (OB_SUCC(ret)) { @@ -12699,35 +12566,52 @@ int ObTransformUtils::extract_const_bool_expr_info(ObTransformerCtx *ctx, common::ObIArray &false_exprs) { int ret = OB_SUCCESS; + bool is_true = false; + bool is_false = false; + ObRawExpr *temp = NULL; if (OB_ISNULL(ctx)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("get unexpected null", K(ctx), K(ret)); } else { - ObObj result; - bool is_true = false; - bool is_valid = false; - ObRawExpr *temp = NULL; for (int64_t i = 0; OB_SUCC(ret) && i < exprs.count(); i++) { - is_valid = false; if (OB_ISNULL(temp = exprs.at(i))) { ret = OB_ERR_UNEXPECTED; LOG_WARN("null expr", K(ret)); - } else if (OB_FAIL(calc_const_expr_result(temp, ctx, result, is_valid))) { - LOG_WARN("fail to calc const expr", K(ret)); - } - if (OB_FAIL(ret) || !is_valid) { - } else if (OB_FAIL(ObObjEvaluator::is_true(result, is_true))) { - LOG_WARN("failed to get bool value", K(ret)); - } else if (!is_true && OB_FAIL(false_exprs.push_back(i))) { - LOG_WARN("failed to push back into array", K(ret)); + } else if (OB_FAIL(extract_const_bool_expr_result(ctx, temp, is_true, is_false))) { + LOG_WARN("failed to extract_const_bool_expr_result", K(ret)); } else if (is_true && OB_FAIL(true_exprs.push_back(i))) { LOG_WARN("failed to push back into array", K(ret)); + } else if (is_false && OB_FAIL(false_exprs.push_back(i))) { + LOG_WARN("failed to push back into array", K(ret)); } else { /*do nothing*/ } } } return ret; } + +int ObTransformUtils::extract_const_bool_expr_result(ObTransformerCtx *ctx, + ObRawExpr *expr, + bool &is_true, + bool &is_false) +{ + int ret = OB_SUCCESS; + ObObj result; + bool is_valid = false; + is_true = false; + is_false = false; + if (OB_FAIL(calc_const_expr_result(expr, ctx, result, is_valid))) { + LOG_WARN("fail to calc const expr", K(ret)); + } else if (!is_valid) { + /* do nothing */ + } else if (OB_FAIL(ObObjEvaluator::is_true(result, is_true))) { + LOG_WARN("failed to get bool value", K(ret)); + } else if (!is_true) { + is_false = true; + } + return ret; +} + int ObTransformUtils::calc_const_expr_result(ObRawExpr * expr, ObTransformerCtx *ctx, ObObj &result, @@ -14435,7 +14319,42 @@ int ObTransformUtils::get_stmt_map_after_copy(ObDMLStmt *origin_stmt, return ret; } -int ObTransformUtils::expand_temp_table(ObTransformerCtx *ctx, ObDMLStmt::TempTableInfo& table_info) +int ObTransformUtils::check_inline_temp_table_valid(ObSelectStmt *stmt, bool &is_valid) +{ + int ret = OB_SUCCESS; + ObSEArray exprs; + is_valid = true; + if (OB_ISNULL(stmt)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("unexpected null stmt", K(ret)); + } else if (OB_FAIL(stmt->get_relation_exprs(exprs))) { + LOG_WARN("failed to get relation exprs", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < exprs.count(); i++) { + if (OB_ISNULL(exprs.at(i))) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (exprs.at(i)->has_flag(CNT_RAND_FUNC) || + exprs.at(i)->has_flag(CNT_STATE_FUNC) || + exprs.at(i)->has_flag(CNT_DYNAMIC_USER_VARIABLE)) { + is_valid = false; + } + } + if (OB_SUCC(ret) && is_valid) { + ObSEArray child_stmts; + if (OB_FAIL(stmt->get_child_stmts(child_stmts))) { + LOG_WARN("failed to get child stmts", K(ret)); + } + for (int64_t i = 0; OB_SUCC(ret) && is_valid && i < child_stmts.count(); i++) { + if (OB_FAIL(SMART_CALL(check_inline_temp_table_valid(child_stmts.at(i), is_valid)))) { + LOG_WARN("failed to check expand temp table valid", K(ret)); + } + } + } + return ret; +} + +int ObTransformUtils::inline_temp_table(ObTransformerCtx *ctx, ObDMLStmt::TempTableInfo& table_info) { int ret = OB_SUCCESS; ObSelectStmt *temp_table_query = NULL; @@ -14447,6 +14366,7 @@ int ObTransformUtils::expand_temp_table(ObTransformerCtx *ctx, ObDMLStmt::TempTa for (int64_t j = 0; OB_SUCC(ret) && j < table_info.table_items_.count(); ++j) { TableItem *table = table_info.table_items_.at(j); ObDMLStmt *upper_stmt = table_info.upper_stmts_.at(j); + ObString qb_name; if (OB_ISNULL(table) || OB_ISNULL(upper_stmt)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect null table item", K(ret)); @@ -14493,6 +14413,10 @@ int ObTransformUtils::expand_temp_table(ObTransformerCtx *ctx, ObDMLStmt::TempTa } else if (OB_FAIL(upper_stmt->formalize_stmt_expr_reference(ctx->expr_factory_, ctx->session_info_))) { LOG_WARN("failed to formalize stmt reference", K(ret)); + } else if (OB_FAIL(child_stmt->get_qb_name(qb_name))) { + LOG_WARN("failed to get qb name", K(ret)); + } else if (OB_FAIL(ctx->materialize_blacklist_.push_back(qb_name))) { + LOG_WARN("failed to push back qb name", K(ret)); } else { table->ref_query_ = child_stmt; } @@ -15168,6 +15092,62 @@ int ObTransformUtils::recursive_check_pushdown_into_set_valid( return ret; } +int ObTransformUtils::calc_column_repeat_rate(ObTransformerCtx *ctx, + const TableItem *table, + const ObIArray &column_ids, + double &repeat_rate) +{ + int ret = OB_SUCCESS; + ObOptColumnStatHandle handle; + const ObTableSchema *table_schema = NULL; + ObGlobalTableStat table_stat; + double joint_ndv = 1; + repeat_rate = -1; + if (OB_ISNULL(ctx) || OB_ISNULL(ctx->schema_checker_) + || OB_ISNULL(ctx->opt_stat_mgr_) || OB_ISNULL(ctx->session_info_) + || OB_ISNULL(table)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret), K(ctx), K(table)); + } else if (!table->is_basic_table()) { + // do nothing + } else if (OB_FAIL(ctx->schema_checker_->get_table_schema( + ctx->session_info_->get_effective_tenant_id(), + table->ref_id_, table_schema))) { + LOG_WARN("get table schema failed", K(ret), KPC(table)); + } else if (OB_ISNULL(table_schema)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (OB_FAIL(ctx->opt_stat_mgr_->get_table_stat(ctx->session_info_->get_effective_tenant_id(), + table->ref_id_, + table_schema->is_partitioned_table() ? -1 : table->ref_id_, + 1, + table_stat))) { + LOG_WARN("get table stat failed", K(ret)); + } else { + for (int64_t i = 0; OB_SUCC(ret) && i < column_ids.count(); ++i) { + ObOptColumnStatHandle column_handle; + if (OB_FAIL(ctx->opt_stat_mgr_->get_column_stat(ctx->session_info_->get_effective_tenant_id(), + table->ref_id_, + table_schema->is_partitioned_table() ? -1 : table->ref_id_, + column_ids.at(i), + column_handle))) { + LOG_WARN("failed to get column stat", K(ret), K(i), K(column_ids.at(i))); + } else if (OB_ISNULL(column_handle.stat_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("column stat is NULL", K(ret)); + } else if (i == 0) { + joint_ndv *= column_handle.stat_->get_num_distinct(); + } else { + joint_ndv *= column_handle.stat_->get_num_distinct() / std::sqrt(2); + } + } + if (OB_SUCC(ret)) { + repeat_rate = max(table_stat.get_row_count() / joint_ndv, 1.0); + } + } + return ret; +} + int ObTransformUtils::check_child_projection_validity(const ObSelectStmt *child_stmt, ObRawExpr *expr, bool &is_valid) @@ -16024,12 +16004,12 @@ int ObTransformUtils::check_lateral_ref_outer_table(const ObDMLStmt *stmt, return ret; } -int ObTransformUtils::check_contain_correlated_lateral_table(ObDMLStmt *stmt, bool &is_contain) +int ObTransformUtils::check_contain_correlated_lateral_table(const ObDMLStmt *stmt, bool &is_contain) { int ret = OB_SUCCESS; is_contain = false; for (int i = 0; OB_SUCC(ret) && !is_contain && i < stmt->get_table_items().count(); ++i) { - TableItem *table = stmt->get_table_item(i); + const TableItem *table = stmt->get_table_item(i); if (OB_ISNULL(table)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("unexpect null table item", K(ret)); @@ -16776,6 +16756,24 @@ int ObTransformUtils::check_enable_global_parallel_execution(ObDMLStmt *stmt, return ret; } +int ObTransformUtils::is_cost_based_trans_enable(ObTransformerCtx *ctx, + const ObGlobalHint &global_hint, + bool &is_enabled) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(ctx)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("get unexpected null", K(ret)); + } else if (global_hint.disable_cost_based_transform()) { + is_enabled = false; + } else { + is_enabled = TransPolicy::ENABLE_TRANS == ctx->cbqt_policy_ || + (TransPolicy::LIMITED_TRANS == ctx->cbqt_policy_ && + !(ctx->complex_cbqt_table_num_ > 0 && ctx->max_table_num_ > ctx->complex_cbqt_table_num_)); + } + return ret; +} + int ObTransformUtils::check_const_select(ObTransformerCtx *ctx, const ObSelectStmt *stmt, bool &is_const_select) diff --git a/src/sql/rewrite/ob_transform_utils.h b/src/sql/rewrite/ob_transform_utils.h index 2c05f2e213..e3b160d66b 100644 --- a/src/sql/rewrite/ob_transform_utils.h +++ b/src/sql/rewrite/ob_transform_utils.h @@ -725,36 +725,6 @@ public: const share::schema::ObForeignKeyInfo *foreign_key_info, bool &is_rely); - - static int check_stmt_limit_validity(ObTransformerCtx *ctx, - const ObSelectStmt *select_stmt, - bool &is_valid, - bool &need_add_const_constraint); - - static int check_stmt_is_non_sens_dul_vals(ObTransformerCtx *ctx, - const ObDMLStmt *upper_stmt, - const ObDMLStmt *stmt, - bool &is_match, - bool &need_add_limit_constraint); - - - /** - * @brief - * to check if semi join can be transformed - * select * from t1 where c1 = 3 or exists (select 1 from t1 left join t2 on t1.c1 = t2.c1); - * ==> - * select * from t1 where c1 = 3 or exists (select 1 from t1); - * @param ctx - * @param stmt - * @param is_match - * @param need_add_limit_constraint - * @return int - */ - static int check_stmt_is_non_sens_dul_vals_rec(ObTransformerCtx *ctx, - const ObDMLStmt *stmt, - const ObRawExpr *expr, - bool &is_match, - bool &need_add_limit_constraint); /** * @brief check_exprs_unique * 检查 exprs 在 table 上是否有唯一性 @@ -1495,9 +1465,10 @@ public: bool &is_existed); static bool check_objparam_abs_equal(const ObObjParam &obj1, const ObObjParam &obj2); - static int add_neg_or_pos_constraint(ObTransformerCtx *trans_ctx, - ObRawExpr *expr, - bool is_negative = false); + static int add_compare_int_constraint(ObTransformerCtx *trans_ctx, + ObRawExpr *expr, + const ObItemType op_type, + int64_t val); static int add_equal_expr_value_constraint(ObTransformerCtx *trans_ctx, ObRawExpr *left, ObRawExpr *right); @@ -1696,6 +1667,10 @@ public: const common::ObIArray &exprs, common::ObIArray &true_exprs, common::ObIArray &false_exprs); + static int extract_const_bool_expr_result(ObTransformerCtx *ctx, + ObRawExpr *expr, + bool &is_true, + bool &is_false); /* extract exprs in all_exprs whoes indexs are in target_idx to target_exprs */ static int extract_target_exprs_by_idx(const ObIArray &all_exprs, const ObIArray &target_idx, @@ -1860,7 +1835,10 @@ public: static int check_group_by_subset(ObRawExpr *expr, const ObIArray &group_exprs, bool &bret); - static int expand_temp_table(ObTransformerCtx *ctx, ObDMLStmt::TempTableInfo& table_info); + + static int check_inline_temp_table_valid(ObSelectStmt *stmt, bool &is_valid); + + static int inline_temp_table(ObTransformerCtx *ctx, ObDMLStmt::TempTableInfo& table_info); static int get_stmt_map_after_copy(ObDMLStmt *origin_stmt, ObDMLStmt *new_stmt, @@ -1971,7 +1949,7 @@ public: const TableItem *table_item, bool &is_ref); - static int check_contain_correlated_lateral_table(ObDMLStmt *stmt, bool &is_contain); + static int check_contain_correlated_lateral_table(const ObDMLStmt *stmt, bool &is_contain); static int cartesian_tables_pre_split(ObSelectStmt *subquery, ObIArray &outer_conditions, @@ -2031,6 +2009,13 @@ public: ObSQLSessionInfo *session, ObQueryCtx *query_ctx, bool &enable_parallel); + static int calc_column_repeat_rate(ObTransformerCtx *ctx, + const TableItem *table, + const ObIArray &column_ids, + double &repeat_rate); + static int is_cost_based_trans_enable(ObTransformerCtx *ctx, + const ObGlobalHint &global_hint, + bool &is_enabled); static int check_const_select(ObTransformerCtx *ctx, const ObSelectStmt *stmt, bool &is_const_select); diff --git a/src/sql/rewrite/ob_transform_win_magic.cpp b/src/sql/rewrite/ob_transform_win_magic.cpp index 6d906b8e21..5327112a9a 100644 --- a/src/sql/rewrite/ob_transform_win_magic.cpp +++ b/src/sql/rewrite/ob_transform_win_magic.cpp @@ -566,13 +566,15 @@ int ObTransformWinMagic::get_view_to_trans(ObDMLStmt *&stmt, LOG_WARN("sanity check and init failed", K(ret)); } else if (OB_FAIL(check_view_valid_to_trans(rewrite_view, map_info, is_valid))) { LOG_WARN("check view valid to trans failed", K(ret)); + } else if (!is_valid) { + OPT_TRACE("view is invalid to trans"); } else if (OB_FAIL(check_stmt_and_view(stmt, rewrite_table, map_info, is_valid, trans_tables))) { LOG_WARN("check stmt and view failed", K(ret)); - } else if (is_valid) { + } else if (!is_valid) { + OPT_TRACE("can not transform"); + } else { drill_down_idx = i; //rewrite_view idx roll_up_idx = -1; - } else { - OPT_TRACE("can not transform"); } } } @@ -711,11 +713,10 @@ int ObTransformWinMagic::check_stmt_and_view(ObDMLStmt *stmt, ObSelectStmt *rewrite_view = NULL; int64_t match_count = 0; QueryRelation relation; - + is_valid = true; if (OB_ISNULL(stmt) || OB_ISNULL(rewrite_table) || OB_ISNULL(rewrite_view = rewrite_table->ref_query_)) { ret = OB_ERR_UNEXPECTED; LOG_WARN("pointer is null", K(ret)); - } else if (!is_valid) { } else if (OB_FAIL(check_hint_valid(*stmt, *rewrite_table, is_valid))) { LOG_WARN("check hint valid", K(ret)); } else if (!is_valid) { @@ -969,7 +970,7 @@ int ObTransformWinMagic::check_outer_stmt_conditions(ObDMLStmt *stmt, ret = OB_ERR_UNEXPECTED; LOG_WARN("pointer is null", K(ret)); } else if (roll_group_exprs.count() > drill_group_exprs.count() || - map.count() != roll_group_exprs.count()) { + roll_group_exprs.count() != map.count()) { is_valid = false; } else if (OB_FAIL(ObEqualAnalysis::compute_equal_set(ctx_->allocator_, stmt->get_condition_exprs(), equal_sets))) { LOG_WARN("compute equal set failed", K(ret)); diff --git a/src/sql/rewrite/ob_transformer_impl.cpp b/src/sql/rewrite/ob_transformer_impl.cpp index 277d9c649d..1539a80a5f 100644 --- a/src/sql/rewrite/ob_transformer_impl.cpp +++ b/src/sql/rewrite/ob_transformer_impl.cpp @@ -52,6 +52,7 @@ #include "sql/rewrite/ob_transform_decorrelate.h" #include "sql/rewrite/ob_transform_mv_rewrite_prepare.h" #include "sql/rewrite/ob_transform_late_materialization.h" +#include "sql/rewrite/ob_transform_distinct_aggregate.h" #include "common/ob_smart_call.h" #include "sql/engine/ob_exec_context.h" @@ -77,6 +78,8 @@ int ObTransformerImpl::transform(ObDMLStmt *&stmt) //dml write query will be executed in remote, do not need transform } else if (OB_FAIL(SMART_CALL(get_stmt_trans_info(stmt, true)))) { LOG_WARN("get_stmt_trans_info failed", K(ret)); + } else if (OB_FAIL(stmt->formalize_implicit_distinct())) { + LOG_WARN("failed to frommalize implicit distinct", K(ret)); } else if (OB_FAIL(do_transform_pre_precessing(stmt))) { LOG_WARN("failed to do transform pre_precessing", K(ret)); } else if (OB_FAIL(stmt->formalize_query_ref_exprs())) { @@ -129,6 +132,27 @@ int ObTransformerImpl::set_transformation_parameters(ObQueryCtx *query_ctx) } else if (OB_FAIL(session_info->is_force_temp_table_materialize(ctx_->is_force_materialize_))) { LOG_WARN("failed to check temp table force materialize", K(ret)); } + if (OB_FAIL(ret)) { + // do nothing + } else if (!query_ctx->check_opt_compat_version(COMPAT_VERSION_4_2_5, COMPAT_VERSION_4_3_0, + COMPAT_VERSION_4_3_5) || + query_ctx->get_query_hint().has_outline_data()) { + ctx_->cbqt_policy_ = TransPolicy::ENABLE_TRANS; + } else if (OB_FAIL(session_info->get_optimizer_cost_based_transformation(opt_param_val))) { + LOG_WARN("failed to get optimizer cost based transformation", K(ret)); + } else if (OB_FAIL(query_ctx->get_global_hint().opt_params_.get_integer_opt_param( + ObOptParamHint::OPTIMIZER_COST_BASED_TRANSFORMATION, opt_param_val))) { + LOG_WARN("failed to get integer opt param", K(ret)); + } else { + ctx_->cbqt_policy_ = static_cast(opt_param_val); + } + if (OB_SUCC(ret)) { + uint64_t tenant_id = session_info->get_effective_tenant_id(); + omt::ObTenantConfigGuard tenant_config(TENANT_CONF(tenant_id)); + if (tenant_config.is_valid()) { + ctx_->complex_cbqt_table_num_ = tenant_config->_complex_cbqt_table_num; + } + } return ret; } @@ -462,8 +486,13 @@ int ObTransformerImpl::transform_rule_set(ObDMLStmt *&stmt, LOG_TRACE("succeed to transform one iteration", K(i), K(need_next_iteration), K(ret)); OPT_TRACE("-- end ", i, " iteration"); } - if (OB_SUCC(ret) && i == max_iteration_count_) { - LOG_INFO("transformer ends without convergence", K(max_iteration_count_)); + if (OB_SUCC(ret) && need_next_iteration && i == max_iteration_count_) { + ret = OB_E(EventTable::EN_CHECK_REWRITE_ITER_CONVERGE) OB_SUCCESS; + if (OB_FAIL(ret)) { + LOG_WARN("transformer ends without convergence", K(ret), K(max_iteration_count_)); + } else { + LOG_INFO("transformer ends without convergence", K(max_iteration_count_)); + } } } return ret; @@ -493,6 +522,7 @@ int ObTransformerImpl::transform_rule_set_in_one_iteration(ObDMLStmt *&stmt, APPLY_RULE_IF_NEEDED(TEMP_TABLE_OPTIMIZATION, ObTransformTempTable); APPLY_RULE_IF_NEEDED(PROJECTION_PRUNING, ObTransformProjectPruning); APPLY_RULE_IF_NEEDED(CONST_PROPAGATE, ObTransformConstPropagate); + APPLY_RULE_IF_NEEDED(DISTINCT_AGGREGATE, ObTransformDistinctAggregate); APPLY_RULE_IF_NEEDED(SUBQUERY_COALESCE, ObTransformSubqueryCoalesce); APPLY_RULE_IF_NEEDED(SIMPLIFY_SET, ObTransformSimplifySet); APPLY_RULE_IF_NEEDED(VIEW_MERGE, ObTransformViewMerge); @@ -806,6 +836,10 @@ int ObTransformerImpl::finalize_exec_params(ObDMLStmt *stmt) int ObTransformerImpl::finalize_exec_params(ObDMLStmt *stmt, ObIArray & exec_params) { int ret = OB_SUCCESS; + if (OB_ISNULL(stmt) || OB_ISNULL(stmt->query_ctx_)) { + ret = OB_ERR_UNEXPECTED; + LOG_WARN("stmt or query ctx is null", K(ret)); + } for (int64_t j = 0; OB_SUCC(ret) && j < exec_params.count(); ++j) { ObExecParamRawExpr *exec_param = NULL; if (OB_ISNULL(exec_param = exec_params.at(j))) { @@ -814,8 +848,8 @@ int ObTransformerImpl::finalize_exec_params(ObDMLStmt *stmt, ObIArrayget_param_index() >= 0) { // do nothing } else { - exec_param->set_param_index(stmt->get_question_marks_count()); - stmt->increase_question_marks_count(); + exec_param->set_param_index(*stmt->query_ctx_); + exec_param->set_result_type(exec_param->get_ref_expr()->get_result_type()); } } return ret; diff --git a/src/sql/session/ob_basic_session_info.cpp b/src/sql/session/ob_basic_session_info.cpp index f37ec5edcc..8436900457 100644 --- a/src/sql/session/ob_basic_session_info.cpp +++ b/src/sql/session/ob_basic_session_info.cpp @@ -3903,6 +3903,12 @@ int ObBasicSessionInfo::get_sql_quote_show_create(bool &sql_quote_show_create) c { return get_bool_sys_var(SYS_VAR_SQL_QUOTE_SHOW_CREATE, sql_quote_show_create); } + +int ObBasicSessionInfo::get_optimizer_cost_based_transformation(int64_t &cbqt_policy) const +{ + int ret = get_int64_sys_var(SYS_VAR__OPTIMIZER_COST_BASED_TRANSFORMATION, cbqt_policy); + return ret; +} //////////////////////////////////////////////////////////////// int ObBasicSessionInfo::replace_user_variables(const ObSessionValMap &user_var_map) { diff --git a/src/sql/session/ob_basic_session_info.h b/src/sql/session/ob_basic_session_info.h index 6966d730c7..62173c6509 100644 --- a/src/sql/session/ob_basic_session_info.h +++ b/src/sql/session/ob_basic_session_info.h @@ -1074,6 +1074,7 @@ public: int get_name_case_mode(common::ObNameCaseMode &case_mode) const; int get_init_connect(common::ObString &str) const; int get_locale_name(common::ObString &str) const; + int get_optimizer_cost_based_transformation(int64_t &cbqt_policy) const; /// @} ///@{ user variables related: diff --git a/src/sql/session/ob_sql_session_info.cpp b/src/sql/session/ob_sql_session_info.cpp index f2824c7cdf..17517f4fd5 100644 --- a/src/sql/session/ob_sql_session_info.cpp +++ b/src/sql/session/ob_sql_session_info.cpp @@ -638,11 +638,11 @@ int ObSQLSessionInfo::get_spm_mode(int64_t &spm_mode) { int ret = OB_SUCCESS; spm_mode = get_sql_plan_management_mode(); - if (0 == spm_mode) { + if (SPM_MODE_DISABLE == spm_mode) { bool sysvar_use_baseline = false; get_use_plan_baseline(sysvar_use_baseline); if (sysvar_use_baseline) { - spm_mode = 1; + spm_mode = SPM_MODE_ONLINE_EVOLVE; } } return ret; diff --git a/src/sql/spm/ob_plan_baseline_mgr.h b/src/sql/spm/ob_plan_baseline_mgr.h index 3fadd70772..0d03fc8e7c 100644 --- a/src/sql/spm/ob_plan_baseline_mgr.h +++ b/src/sql/spm/ob_plan_baseline_mgr.h @@ -84,7 +84,7 @@ public: ObPlanBaselineMgr* baseline_mgr_; }; -typedef ObList task_result_list; +typedef ObList task_result_list; class ObPlanBaselineMgr { @@ -116,6 +116,8 @@ public: ObPlanCacheCtx& pc_ctx, ObPhysicalPlan* plan); int update_plan_baseline_statistic(EvolutionTaskResult& result); + int update_statistic_for_evolve(EvolutionTaskResult& result); + int update_statistic_for_confirm(EvolutionTaskResult& result); int accept_new_plan_baseline(ObSpmCacheCtx& spm_ctx, const ObAuditRecordData &audit_record); int force_accept_new_plan_baseline(ObSpmCacheCtx& spm_ctx, uint64_t plan_hash, const bool with_plan_hash); int sync_baseline_from_inner_table(); @@ -136,6 +138,7 @@ public: int purge_baselines(const uint64_t tenant_id, int64_t baseline_affected); int evict_plan_baseline(ObSpmCacheCtx& spm_ctx); int check_evolution_task(); + int handle_spm_evo_record(const uint64_t tenant_id); private: int init(uint64_t tenant_id); int init_mem_context(uint64_t tenant_id); diff --git a/src/sql/spm/ob_plan_baseline_sql_service.h b/src/sql/spm/ob_plan_baseline_sql_service.h index 714bfa3f94..84335c89a7 100644 --- a/src/sql/spm/ob_plan_baseline_sql_service.h +++ b/src/sql/spm/ob_plan_baseline_sql_service.h @@ -29,6 +29,7 @@ class ObMySQLProxy; namespace sql { +struct ObImportBaseline; class ObSpmBaselineLoader; class ObPlanBaselineSqlService @@ -61,7 +62,8 @@ public: const uint64_t tenant_id, const ObBaselineKey& key, ObPlanBaselineItem* baseline, - bool update_info); + bool update_info, + int64_t record_type = 0); int delete_baseline_item(ObMySQLTransaction& trans, const uint64_t tenant_id, @@ -117,7 +119,7 @@ public: ObString &output_str); int update_plan_baselines_result(const uint64_t tenant_id, - EvoResultUpdateTask& evo_res); + EvolutionTaskResult& evo_res); int update_baseline_item_evolving_result(ObMySQLTransaction& trans, const uint64_t tenant_id, @@ -136,10 +138,41 @@ public: const uint64_t tenant_id, const ObBaselineKey& key, const ObPlanBaselineItem& baseline_item); + + int import_plan_baseline(ObIAllocator& allocator, + const uint64_t tenant_id, + const uint64_t baseline_db_id, + ObIArray &baselines); + int insert_baseline_item(ObMySQLTransaction& trans, + ObIAllocator& allocator, + const uint64_t tenant_id, + const uint64_t baseline_db_id, + const ObImportBaseline* baseline); + int update_baseline_info(ObMySQLTransaction& trans, + ObIAllocator& allocator, + const uint64_t tenant_id, + const uint64_t baseline_db_id, + const ObImportBaseline* baseline); + + int batch_record_evolution_result(const uint64_t tenant_id, + ObIArray &evo_res_array); + int insert_spm_record(ObMySQLProxy *proxy, + const uint64_t tenant_id, + const ObBaselineKey& key, + int64_t record_type); + int delete_timeout_record(const uint64_t tenant_id, const uint64_t current_time); + + int update_baseline_item_verify_result(ObMySQLTransaction& trans, + const uint64_t tenant_id, + const ObBaselineKey& key, + const uint64_t& plan_hash, + const ObEvolutionStat &evo_stat, + int64_t& affected_rows); private: static const int64_t max_sql_text_size = 10 * 1024 * 1024; // 10M const static char *EMPTY_STR; bool inited_; + char ip_buff_[common::MAX_IP_ADDR_LENGTH] = {'\0'}; ObMySQLProxy* mysql_proxy_; }; diff --git a/src/sql/spm/ob_spm_define.h b/src/sql/spm/ob_spm_define.h index 8179737ab2..9fc521b417 100644 --- a/src/sql/spm/ob_spm_define.h +++ b/src/sql/spm/ob_spm_define.h @@ -25,6 +25,7 @@ namespace oceanbase { namespace sql { +class ObSqlPlanSet; enum PlanBaselineFlag { @@ -273,7 +274,8 @@ struct ObSpmCacheCtx : public ObILibCacheCtx evolution_plan_type_(OB_PHY_PLAN_UNINITIALIZED), select_plan_type_(INVALID_TYPE), baseline_exec_time_(0), - flags_(0) + flags_(0), + spm_mode_(SPM_MODE_DISABLE) { cache_node_empty_ = true; } @@ -351,6 +353,8 @@ struct ObSpmCacheCtx : public ObILibCacheCtx uint64_t reserved_: 55; }; }; + int64_t spm_mode_; + ObSqlPlanSet *evo_plan_set_; }; struct EvolutionTaskResult @@ -360,10 +364,16 @@ public: : key_(), accept_new_plan_(false), new_plan_hash_(0), - new_stat_() + new_stat_(), + status_(0), + start_time_(0), + end_time_(0), + spm_mode_(SPM_MODE_DISABLE) {} ~EvolutionTaskResult() {} -int deep_copy(common::ObIAllocator& allocator, const EvolutionTaskResult& other); + int deep_copy(common::ObIAllocator& allocator, const EvolutionTaskResult& other); + TO_STRING_KV(K_(key), K_(old_plan_hash_array), K_(old_stat_array), K_(new_plan_hash), + K_(new_stat), K_(start_time), K_(end_time), K_(status), K_(spm_mode)); public: ObBaselineKey key_; bool accept_new_plan_; @@ -373,23 +383,10 @@ public: // new plan statistics uint64_t new_plan_hash_; ObEvolutionStat new_stat_; -}; - -struct EvoResultUpdateTask -{ -public: - EvoResultUpdateTask() - : key_(), - plan_hash_(), - plan_stat_() - {} - ~EvoResultUpdateTask() {} - int init_task(common::ObIAllocator& allocator, const EvolutionTaskResult& evo_task_result); - TO_STRING_KV(K_(key), K_(plan_hash), K_(plan_stat)); -public: - ObBaselineKey key_; - common::ObSEArray plan_hash_; - common::ObSEArray plan_stat_; + int64_t status_; + int64_t start_time_; + int64_t end_time_; + int64_t spm_mode_; }; } // namespace sql end diff --git a/src/sql/spm/ob_spm_evolution_plan.h b/src/sql/spm/ob_spm_evolution_plan.h index 7f73b62756..a3d5e10b33 100644 --- a/src/sql/spm/ob_spm_evolution_plan.h +++ b/src/sql/spm/ob_spm_evolution_plan.h @@ -72,7 +72,8 @@ public: is_inited_(false), current_stage_cnt_(0), lazy_finished_(false), - lazy_better_(false) + lazy_better_(false), + spm_mode_(SPM_MODE_DISABLE) { } void reset(); @@ -119,8 +120,8 @@ private: static const int64_t DEFAULT_EVOLUTION_TIMEOUT_THRESHOLD = 3 * 60 * 60 * 1000L * 1000L; //3 hours static const int64_t DEFAULT_ERROR_COUNT_THRESHOLD = 3; - int get_plan_with_guard(ObPlanCacheCtx &ctx, - ObPhysicalPlan *&plan); + int online_evolve_get_plan_with_guard(ObPlanCacheCtx &ctx, + ObPhysicalPlan *&plan); int add_baseline_plan(ObPlanCacheCtx &ctx, ObPhysicalPlan &plan); int add_evolving_plan(ObPlanCacheCtx &ctx, @@ -151,7 +152,7 @@ private: ObPhysicalPlan *&plan); int64_t get_baseline_plan_error_cnt(); int64_t get_plan_finish_cnt(); - + int confirm_baseline_plan(); protected: ObSqlPlanSet *plan_set_; common::SpinRWLock ref_lock_; @@ -172,6 +173,7 @@ protected: int64_t current_stage_cnt_; bool lazy_finished_; bool lazy_better_; + int64_t spm_mode_; }; } //namespace sql end diff --git a/tools/deploy/init_for_ce.sql b/tools/deploy/init_for_ce.sql index cc82da8431..0fc1efed41 100644 --- a/tools/deploy/init_for_ce.sql +++ b/tools/deploy/init_for_ce.sql @@ -46,6 +46,7 @@ alter system set_tp tp_no = 1200, error_code = 4001, frequency = 1; alter system set_tp tp_no = 509, error_code = 4016, frequency = 1; alter system set_tp tp_no = 368, error_code = 4016, frequency = 1; alter system set_tp tp_no = 551, error_code = 5434, frequency = 1; +alter system set_tp tp_no = 558, error_code = 4016, frequency = 1; alter system set _enable_var_assign_use_das = true tenant = sys; alter system set _enable_var_assign_use_das = true tenant = all_user; diff --git a/tools/deploy/mysql_test/r/mysql/dist_nest_loop_simple.result b/tools/deploy/mysql_test/r/mysql/dist_nest_loop_simple.result index 748865a28b..a37eb2a0eb 100644 --- a/tools/deploy/mysql_test/r/mysql/dist_nest_loop_simple.result +++ b/tools/deploy/mysql_test/r/mysql/dist_nest_loop_simple.result @@ -256,39 +256,31 @@ Outputs & filters: range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true explain select /*+use_nl(t1 t2)*/ * from t1 left join t2 on t1.c1= t2.c1; Query Plan -===================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |29 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─NESTED-LOOP OUTER JOIN | |1 |25 | -|3 | ├─EXCHANGE IN DISTR | |1 |7 | -|4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|1 |6 | -|5 | │ └─PX PARTITION ITERATOR | |1 |5 | -|6 | │ └─TABLE FULL SCAN |t1 |1 |5 | -|7 | └─PX PARTITION ITERATOR | |1 |36 | -|8 | └─TABLE RANGE SCAN |t2 |1 |36 | -===================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |1 |24 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|1 |23 | +|2 | └─NESTED-LOOP OUTER JOIN | |1 |21 | +|3 | ├─PX PARTITION ITERATOR | |1 |5 | +|4 | │ └─TABLE FULL SCAN |t1 |1 |5 | +|5 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |1 |31 | +====================================================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 dop=1 2 - output([t1.c1], [t1.c2], [t1.c3], [t1.c4], [t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - conds(nil), nl_params_([t1.c1(:0)]), use_batch=false - 3 - output([PARTITION_ID], [t1.c1], [t1.c2], [t1.c3], [t1.c4]), filter(nil), rowset=16 - 4 - output([PARTITION_ID], [t1.c1], [t1.c2], [t1.c3], [t1.c4]), filter(nil), rowset=16 - (#keys=1, [t1.c1]), dop=1 - 5 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + conds(nil), nl_params_([t1.c1(:0)]), use_batch=true + 3 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 force partition granule - 6 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + 4 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 access([t1.c2], [t1.c3], [t1.c1], [t1.c4]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t1.c2], [t1.c3]), range(MIN,MIN ; MAX,MAX)always true - 7 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - affinitize, force partition granule - 8 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - access([t2.c1], [t2.c2], [t2.c3]), partitions(p[0-1]) + 5 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 + access([GROUP_ID], [t2.c1], [t2.c2], [t2.c3]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN ; MAX), range_cond([:0 = t2.c1]) @@ -333,153 +325,121 @@ Outputs & filters: range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true explain select /*+use_nl(t1 t2)*/ * from t1 left join t2 on t1.c1= t2.c1 and t1.c3= t2.c3; Query Plan -===================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |29 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─NESTED-LOOP OUTER JOIN | |1 |25 | -|3 | ├─EXCHANGE IN DISTR | |1 |7 | -|4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|1 |6 | -|5 | │ └─PX PARTITION ITERATOR | |1 |5 | -|6 | │ └─TABLE FULL SCAN |t1 |1 |5 | -|7 | └─PX PARTITION ITERATOR | |1 |36 | -|8 | └─TABLE RANGE SCAN |t2 |1 |36 | -===================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |1 |24 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|1 |23 | +|2 | └─NESTED-LOOP OUTER JOIN | |1 |21 | +|3 | ├─PX PARTITION ITERATOR | |1 |5 | +|4 | │ └─TABLE FULL SCAN |t1 |1 |5 | +|5 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |1 |31 | +====================================================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 dop=1 2 - output([t1.c1], [t1.c3], [t1.c2], [t1.c4], [t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - conds(nil), nl_params_([t1.c1(:0)], [t1.c3(:1)]), use_batch=false - 3 - output([PARTITION_ID], [t1.c1], [t1.c3], [t1.c2], [t1.c4]), filter(nil), rowset=16 - 4 - output([PARTITION_ID], [t1.c1], [t1.c3], [t1.c2], [t1.c4]), filter(nil), rowset=16 - (#keys=1, [t1.c1]), dop=1 - 5 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + conds(nil), nl_params_([t1.c1(:0)], [t1.c3(:1)]), use_batch=true + 3 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 force partition granule - 6 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + 4 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 access([t1.c2], [t1.c3], [t1.c1], [t1.c4]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t1.c2], [t1.c3]), range(MIN,MIN ; MAX,MAX)always true - 7 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - affinitize, force partition granule - 8 - output([t2.c1], [t2.c2], [t2.c3]), filter([:1 = t2.c3]), rowset=16 - access([t2.c1], [t2.c2], [t2.c3]), partitions(p[0-1]) + 5 - output([t2.c1], [t2.c2], [t2.c3]), filter([:1 = t2.c3]), rowset=16 + access([GROUP_ID], [t2.c1], [t2.c2], [t2.c3]), partitions(p[0-1]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN ; MAX), range_cond([:0 = t2.c1]) explain select /*+use_nl(t1 t2)*/ * from t1 join t2 on t1.c2= t2.c2; Query Plan -===================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |28 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |27 | -|2 | └─NESTED-LOOP JOIN | |1 |25 | -|3 | ├─EXCHANGE IN DISTR | |1 |6 | -|4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|1 |6 | -|5 | │ └─PX PARTITION ITERATOR | |1 |5 | -|6 | │ └─TABLE FULL SCAN |t2 |1 |5 | -|7 | └─PX PARTITION ITERATOR | |1 |36 | -|8 | └─TABLE RANGE SCAN |t1 |1 |36 | -===================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |1 |24 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|1 |23 | +|2 | └─NESTED-LOOP JOIN | |1 |21 | +|3 | ├─PX PARTITION ITERATOR | |1 |5 | +|4 | │ └─TABLE FULL SCAN |t2 |1 |5 | +|5 | └─DISTRIBUTED TABLE RANGE SCAN|t1 |1 |31 | +====================================================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 dop=1 2 - output([t2.c2], [t2.c1], [t2.c3], [t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 - conds(nil), nl_params_([t2.c2(:0)]), use_batch=false - 3 - output([PARTITION_ID], [t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 - 4 - output([PARTITION_ID], [t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 - (#keys=1, [t2.c2]), dop=1 - 5 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 + conds(nil), nl_params_([t2.c2(:0)]), use_batch=true + 3 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 force partition granule - 6 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 + 4 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 access([t2.c1], [t2.c2], [t2.c3]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true - 7 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 - affinitize, force partition granule - 8 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 - access([t1.c2], [t1.c3], [t1.c1], [t1.c4]), partitions(p[0-1]) + 5 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + access([GROUP_ID], [t1.c2], [t1.c3], [t1.c1], [t1.c4]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t1.c2], [t1.c3]), range(MIN ; MAX), range_cond([t1.c2 = :0]) explain select /*+use_nl(t1 t2)*/ * from t1 join t2 on t1.c1= t2.c1; Query Plan -===================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |29 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─NESTED-LOOP JOIN | |1 |25 | -|3 | ├─EXCHANGE IN DISTR | |1 |7 | -|4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|1 |6 | -|5 | │ └─PX PARTITION ITERATOR | |1 |5 | -|6 | │ └─TABLE FULL SCAN |t1 |1 |5 | -|7 | └─PX PARTITION ITERATOR | |1 |36 | -|8 | └─TABLE RANGE SCAN |t2 |1 |36 | -===================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |1 |24 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|1 |23 | +|2 | └─NESTED-LOOP JOIN | |1 |21 | +|3 | ├─PX PARTITION ITERATOR | |1 |5 | +|4 | │ └─TABLE FULL SCAN |t1 |1 |5 | +|5 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |1 |31 | +====================================================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 dop=1 2 - output([t1.c1], [t1.c2], [t1.c3], [t1.c4], [t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - conds(nil), nl_params_([t1.c1(:0)]), use_batch=false - 3 - output([PARTITION_ID], [t1.c1], [t1.c2], [t1.c3], [t1.c4]), filter(nil), rowset=16 - 4 - output([PARTITION_ID], [t1.c1], [t1.c2], [t1.c3], [t1.c4]), filter(nil), rowset=16 - (#keys=1, [t1.c1]), dop=1 - 5 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + conds(nil), nl_params_([t1.c1(:0)]), use_batch=true + 3 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 force partition granule - 6 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + 4 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 access([t1.c2], [t1.c3], [t1.c1], [t1.c4]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t1.c2], [t1.c3]), range(MIN,MIN ; MAX,MAX)always true - 7 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - affinitize, force partition granule - 8 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - access([t2.c1], [t2.c2], [t2.c3]), partitions(p[0-1]) + 5 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 + access([GROUP_ID], [t2.c1], [t2.c2], [t2.c3]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN ; MAX), range_cond([:0 = t2.c1]) explain select /*+use_nl(t1 t2)*/ * from t1 join t2 on t1.c2= t2.c2 and t1.c3= t2.c3; Query Plan -===================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |28 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |27 | -|2 | └─NESTED-LOOP JOIN | |1 |25 | -|3 | ├─EXCHANGE IN DISTR | |1 |6 | -|4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|1 |6 | -|5 | │ └─PX PARTITION ITERATOR | |1 |5 | -|6 | │ └─TABLE FULL SCAN |t2 |1 |5 | -|7 | └─PX PARTITION ITERATOR | |1 |36 | -|8 | └─TABLE GET |t1 |1 |36 | -===================================================================== +=============================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +--------------------------------------------------------------- +|0 |PX COORDINATOR | |1 |24 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|1 |23 | +|2 | └─NESTED-LOOP JOIN | |1 |21 | +|3 | ├─PX PARTITION ITERATOR| |1 |5 | +|4 | │ └─TABLE FULL SCAN |t2 |1 |5 | +|5 | └─DISTRIBUTED TABLE GET|t1 |1 |31 | +=============================================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t2.c1, t2.c2, t2.c3)]), filter(nil), rowset=16 dop=1 2 - output([t2.c2], [t2.c3], [t2.c1], [t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 - conds(nil), nl_params_([t2.c2(:0)], [t2.c3(:1)]), use_batch=false - 3 - output([PARTITION_ID], [t2.c2], [t2.c3], [t2.c1]), filter(nil), rowset=16 - 4 - output([PARTITION_ID], [t2.c2], [t2.c3], [t2.c1]), filter(nil), rowset=16 - (#keys=1, [t2.c2]), dop=1 - 5 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 + conds(nil), nl_params_([t2.c2(:0)], [t2.c3(:1)]), use_batch=true + 3 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 force partition granule - 6 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 + 4 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 access([t2.c1], [t2.c2], [t2.c3]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true - 7 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 - affinitize, force partition granule - 8 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 - access([t1.c2], [t1.c3], [t1.c1], [t1.c4]), partitions(p[0-1]) + 5 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + access([GROUP_ID], [t1.c2], [t1.c3], [t1.c1], [t1.c4]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t1.c2], [t1.c3]), range(MIN ; MAX), range_cond([t1.c2 = :0], [t1.c3 = :1]) @@ -583,23 +543,20 @@ Outputs & filters: range_key([t12.c1]), range(MIN ; MAX)always true explain select * from (select /*+use_nl(t11 t12)*/ t12.c1 from t11,t12 where t11.c1=t12.c1 limit 1) v order by v.c1; Query Plan -============================================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------------ -|0 |SORT | |1 |27 | -|1 |└─SUBPLAN SCAN |v |1 |27 | -|2 | └─LIMIT | |1 |27 | -|3 | └─PX COORDINATOR | |1 |27 | -|4 | └─EXCHANGE OUT DISTR |:EX10001|1 |26 | -|5 | └─LIMIT | |1 |26 | -|6 | └─NESTED-LOOP JOIN | |1 |26 | -|7 | ├─EXCHANGE IN DISTR | |1 |7 | -|8 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|1 |7 | -|9 | │ └─PX PARTITION ITERATOR | |1 |7 | -|10| │ └─TABLE FULL SCAN |t12 |1 |7 | -|11| └─PX PARTITION ITERATOR | |1 |90 | -|12| └─TABLE GET |t11 |1 |90 | -============================================================================= +======================================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +----------------------------------------------------------------------- +|0 |SORT | |1 |24 | +|1 |└─SUBPLAN SCAN |v |1 |23 | +|2 | └─LIMIT | |1 |23 | +|3 | └─PX COORDINATOR | |1 |23 | +|4 | └─EXCHANGE OUT DISTR |:EX10000|1 |23 | +|5 | └─LIMIT | |1 |23 | +|6 | └─NESTED-LOOP JOIN | |1 |23 | +|7 | ├─PX PARTITION ITERATOR| |1 |7 | +|8 | │ └─TABLE FULL SCAN |t12 |1 |7 | +|9 | └─DISTRIBUTED TABLE GET|t11 |1 |77 | +======================================================================= Outputs & filters: ------------------------------------- 0 - output([v.c1]), filter(nil), rowset=16 @@ -614,20 +571,15 @@ Outputs & filters: 5 - output([t12.c1]), filter(nil), rowset=16 limit(1), offset(nil) 6 - output([t12.c1]), filter(nil), rowset=16 - conds(nil), nl_params_([t12.c1(:0)]), use_batch=false - 7 - output([t12.c1], [PARTITION_ID]), filter(nil), rowset=16 - 8 - output([t12.c1], [PARTITION_ID]), filter(nil), rowset=16 - (#keys=1, [t12.c1]), dop=1 - 9 - output([t12.c1]), filter(nil), rowset=16 + conds(nil), nl_params_([t12.c1(:0)]), use_batch=true + 7 - output([t12.c1]), filter(nil), rowset=16 force partition granule - 10 - output([t12.c1]), filter(nil), rowset=16 + 8 - output([t12.c1]), filter(nil), rowset=16 access([t12.c1]), partitions(p[0-2]) is_index_back=false, is_global_index=false, range_key([t12.c1]), range(MIN ; MAX)always true - 11 - output(nil), filter(nil), rowset=16 - affinitize, force partition granule - 12 - output(nil), filter(nil), rowset=16 - access(nil), partitions(p[0-4]) + 9 - output(nil), filter(nil), rowset=16 + access([GROUP_ID]), partitions(p[0-4]) is_index_back=false, is_global_index=false, range_key([t11.c1]), range(MIN ; MAX), range_cond([t11.c1 = :0]) @@ -950,39 +902,31 @@ Outputs & filters: range_cond([t4.c1 = :0]) explain select /*+use_nl(t1 t4)*/ * from t1 left join t4 on t4.c1= t1.c1 and t4.c3 = t1.c4; Query Plan -===================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |29 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─NESTED-LOOP OUTER JOIN | |1 |25 | -|3 | ├─EXCHANGE IN DISTR | |1 |7 | -|4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|1 |6 | -|5 | │ └─PX PARTITION ITERATOR | |1 |5 | -|6 | │ └─TABLE FULL SCAN |t1 |1 |5 | -|7 | └─PX PARTITION ITERATOR | |1 |54 | -|8 | └─TABLE RANGE SCAN |t4 |1 |54 | -===================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |1 |25 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|1 |24 | +|2 | └─NESTED-LOOP OUTER JOIN | |1 |21 | +|3 | ├─PX PARTITION ITERATOR | |1 |5 | +|4 | │ └─TABLE FULL SCAN |t1 |1 |5 | +|5 | └─DISTRIBUTED TABLE RANGE SCAN|t4 |1 |46 | +====================================================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t4.c1, t4.c2, t4.c3, t4.c4)]), filter(nil), rowset=16 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c2, t1.c3, t1.c4, t4.c1, t4.c2, t4.c3, t4.c4)]), filter(nil), rowset=16 dop=1 2 - output([t1.c1], [t1.c4], [t1.c2], [t1.c3], [t4.c1], [t4.c2], [t4.c3], [t4.c4]), filter(nil), rowset=16 - conds(nil), nl_params_([t1.c1(:0)], [t1.c4(:1)]), use_batch=false - 3 - output([PARTITION_ID], [t1.c1], [t1.c4], [t1.c2], [t1.c3]), filter(nil), rowset=16 - 4 - output([PARTITION_ID], [t1.c1], [t1.c4], [t1.c2], [t1.c3]), filter(nil), rowset=16 - (#keys=1, [t1.c4]), dop=1 - 5 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + conds(nil), nl_params_([t1.c1(:0)], [t1.c4(:1)]), use_batch=true + 3 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 force partition granule - 6 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 + 4 - output([t1.c2], [t1.c3], [t1.c1], [t1.c4]), filter(nil), rowset=16 access([t1.c2], [t1.c3], [t1.c1], [t1.c4]), partitions(p[0-1]) is_index_back=false, is_global_index=false, range_key([t1.c2], [t1.c3]), range(MIN,MIN ; MAX,MAX)always true - 7 - output([t4.c1], [t4.c2], [t4.c3], [t4.c4]), filter(nil), rowset=16 - affinitize, force partition granule - 8 - output([t4.c1], [t4.c2], [t4.c3], [t4.c4]), filter([t4.c3 = :1]), rowset=16 - access([t4.c1], [t4.c2], [t4.c3], [t4.c4]), partitions(p0sp[0-2]) + 5 - output([t4.c1], [t4.c2], [t4.c3], [t4.c4]), filter([t4.c3 = :1]), rowset=16 + access([GROUP_ID], [t4.c1], [t4.c2], [t4.c3], [t4.c4]), partitions(p0sp[0-2]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t4.c1], [t4.c2], [t4.c3]), range(MIN ; MAX), range_cond([t4.c1 = :0]) @@ -1280,71 +1224,68 @@ Outputs & filters: range_cond([:0 = c.c1]) explain select /*+use_nl(a b) use_nl(b c)*/ * from t5 as a join (select c1, c3, sum(c2) as yyy, max(c4) from t4 group by c3 order by yyy limit 1) as b on a.c1 = b.c1 and a.c3 = b.c3 join t6 as c on b.c1=c.c1 and b.c3 = c.c3; Query Plan -================================================================================ -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |44 | -|1 |└─EXCHANGE OUT DISTR |:EX10002|1 |42 | -|2 | └─HASH JOIN | |1 |38 | -|3 | ├─PX PARTITION ITERATOR | |1 |7 | -|4 | │ └─TABLE FULL SCAN |c |1 |7 | -|5 | └─NESTED-LOOP JOIN | |1 |31 | -|6 | ├─EXCHANGE IN DISTR | |1 |12 | -|7 | │ └─EXCHANGE OUT DISTR (PKEY) |:EX10001|1 |11 | -|8 | │ └─SUBPLAN SCAN |b |1 |10 | -|9 | │ └─LIMIT | |1 |10 | -|10| │ └─EXCHANGE IN MERGE SORT DISTR| |1 |10 | -|11| │ └─EXCHANGE OUT DISTR |:EX10000|1 |9 | -|12| │ └─TOP-N SORT | |1 |7 | -|13| │ └─PX PARTITION ITERATOR | |1 |7 | -|14| │ └─HASH GROUP BY | |1 |7 | -|15| │ └─TABLE FULL SCAN |t4 |1 |7 | -|16| └─PX PARTITION ITERATOR | |1 |54 | -|17| └─TABLE RANGE SCAN |a |1 |54 | -================================================================================ +============================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------------------------------ +|0 |PX COORDINATOR | |1 |72 | +|1 |└─EXCHANGE OUT DISTR |:EX10002|1 |70 | +|2 | └─HASH JOIN | |1 |66 | +|3 | ├─EXCHANGE IN DISTR | |1 |12 | +|4 | │ └─EXCHANGE OUT DISTR (PKEY) |:EX10001|1 |11 | +|5 | │ └─SUBPLAN SCAN |b |1 |10 | +|6 | │ └─LIMIT | |1 |10 | +|7 | │ └─EXCHANGE IN MERGE SORT DISTR| |1 |10 | +|8 | │ └─EXCHANGE OUT DISTR |:EX10000|1 |9 | +|9 | │ └─TOP-N SORT | |1 |7 | +|10| │ └─PX PARTITION ITERATOR | |1 |7 | +|11| │ └─HASH GROUP BY | |1 |7 | +|12| │ └─TABLE FULL SCAN |t4 |1 |7 | +|13| └─NESTED-LOOP JOIN | |1 |54 | +|14| ├─PX PARTITION ITERATOR | |1 |7 | +|15| │ └─TABLE FULL SCAN |a |1 |7 | +|16| └─DISTRIBUTED TABLE RANGE SCAN |c |1 |46 | +============================================================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(a.c1, a.c2, a.c3, a.c4, b.c1, b.c3, b.yyy, b.max(c4), c.c1, c.c2, c.c3, c.c4)]), filter(nil), rowset=16 1 - output([INTERNAL_FUNCTION(a.c1, a.c2, a.c3, a.c4, b.c1, b.c3, b.yyy, b.max(c4), c.c1, c.c2, c.c3, c.c4)]), filter(nil), rowset=16 dop=1 - 2 - output([c.c1], [a.c1], [b.c3], [c.c3], [c.c2], [c.c4], [b.c1], [b.yyy], [b.max(c4)], [a.c2], [a.c3], [a.c4]), filter(nil), rowset=16 - equal_conds([c.c1 = a.c1], [b.c3 = c.c3]), other_conds(nil) - 3 - output([c.c1], [c.c2], [c.c3], [c.c4]), filter(nil), rowset=16 - affinitize, partition wise, force partition granule - 4 - output([c.c1], [c.c2], [c.c3], [c.c4]), filter(nil), rowset=16 - access([c.c1], [c.c2], [c.c3], [c.c4]), partitions(p0sp[0-2]) - is_index_back=false, is_global_index=false, - range_key([c.c1], [c.c2], [c.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true - 5 - output([a.c1], [b.c3], [b.c1], [b.yyy], [b.max(c4)], [a.c2], [a.c3], [a.c4]), filter(nil), rowset=16 - conds(nil), nl_params_([b.c1(:0)], [b.c3(:1)]), use_batch=false - 6 - output([b.c3], [PARTITION_ID], [b.c1], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 - 7 - output([b.c3], [PARTITION_ID], [b.c1], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 + 2 - output([b.c1], [c.c1], [b.c3], [c.c3], [a.c3], [b.yyy], [b.max(c4)], [a.c1], [a.c2], [a.c4], [c.c2], [c.c4]), filter(nil), rowset=16 + equal_conds([b.c1 = c.c1], [b.c3 = c.c3], [a.c3 = b.c3]), other_conds(nil) + 3 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 + 4 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 (#keys=1, [b.c3]), is_single, dop=1 - 8 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 + 5 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 access([b.c1], [b.c3], [b.yyy], [b.max(c4)]) - 9 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 6 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 limit(1), offset(nil) - 10 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 7 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 sort_keys([T_FUN_SUM(t4.c2), ASC]) - 11 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 8 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 dop=1 - 12 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 9 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 sort_keys([T_FUN_SUM(t4.c2), ASC]), topn(1) - 13 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 10 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 partition wise, force partition granule - 14 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 11 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 group([t4.c3]), agg_func([T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]) - 15 - output([t4.c1], [t4.c2], [t4.c3], [t4.c4]), filter(nil), rowset=16 + 12 - output([t4.c1], [t4.c2], [t4.c3], [t4.c4]), filter(nil), rowset=16 access([t4.c1], [t4.c2], [t4.c3], [t4.c4]), partitions(p0sp[0-2]) is_index_back=false, is_global_index=false, range_key([t4.c1], [t4.c2], [t4.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true - 16 - output([a.c1], [a.c2], [a.c3], [a.c4]), filter(nil), rowset=16 - affinitize, partition wise, force partition granule - 17 - output([a.c1], [a.c2], [a.c3], [a.c4]), filter([a.c3 = :1]), rowset=16 + 13 - output([c.c1], [c.c3], [a.c3], [a.c1], [a.c2], [a.c4], [c.c2], [c.c4]), filter(nil), rowset=16 + conds(nil), nl_params_([a.c1(:0)]), use_batch=true + 14 - output([a.c1], [a.c2], [a.c3], [a.c4]), filter(nil), rowset=16 + affinitize, force partition granule + 15 - output([a.c1], [a.c2], [a.c3], [a.c4]), filter(nil), rowset=16 access([a.c1], [a.c2], [a.c3], [a.c4]), partitions(p0sp[0-2]) - is_index_back=false, is_global_index=false, filter_before_indexback[false], - range_key([a.c1], [a.c2], [a.c3]), range(MIN ; MAX), - range_cond([a.c1 = :0]) + is_index_back=false, is_global_index=false, + range_key([a.c1], [a.c2], [a.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true + 16 - output([c.c1], [c.c2], [c.c3], [c.c4]), filter(nil), rowset=16 + access([GROUP_ID], [c.c1], [c.c2], [c.c3], [c.c4]), partitions(p0sp[0-2]) + is_index_back=false, is_global_index=false, + range_key([c.c1], [c.c2], [c.c3]), range(MIN ; MAX), + range_cond([c.c1 = :0]) explain select /*+use_nl(a b) use_nl(b c)*/ * from t5 as a join t6 as b on a.c1 = b.c1 and a.c3 = b.c3 join (select c1, c3, sum(c2) as yyy, max(c4) from t4 group by c3 order by yyy limit 1) as c on b.c1=c.c1 and b.c3 = c.c3; Query Plan ============================================================================== @@ -1475,30 +1416,27 @@ Outputs & filters: range_cond([:0 = c.c1]) explain select /*+use_nl(a b) use_nl(b c)*/ * from t5 as a left join (select c1, c3, sum(c2) as yyy, max(c4) from t4 group by c3 order by yyy limit 1) as b on a.c1 = b.c1 and a.c3 = b.c3 left join t6 as c on b.c1=c.c1 and b.c3 = c.c3; Query Plan -==================================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |48 | -|1 |└─EXCHANGE OUT DISTR |:EX10003|1 |46 | -|2 | └─HASH OUTER JOIN | |1 |42 | -|3 | ├─PX PARTITION ITERATOR | |1 |7 | -|4 | │ └─TABLE FULL SCAN |a |1 |7 | -|5 | └─EXCHANGE IN DISTR | |1 |35 | -|6 | └─EXCHANGE OUT DISTR (PKEY) |:EX10002|1 |34 | -|7 | └─NESTED-LOOP OUTER JOIN | |1 |31 | -|8 | ├─EXCHANGE IN DISTR | |1 |12 | -|9 | │ └─EXCHANGE OUT DISTR (PKEY) |:EX10001|1 |11 | -|10| │ └─SUBPLAN SCAN |b |1 |10 | -|11| │ └─LIMIT | |1 |10 | -|12| │ └─EXCHANGE IN MERGE SORT DISTR| |1 |10 | -|13| │ └─EXCHANGE OUT DISTR |:EX10000|1 |9 | -|14| │ └─TOP-N SORT | |1 |7 | -|15| │ └─PX PARTITION ITERATOR | |1 |7 | -|16| │ └─HASH GROUP BY | |1 |7 | -|17| │ └─TABLE FULL SCAN |t4 |1 |7 | -|18| └─PX PARTITION ITERATOR | |1 |54 | -|19| └─TABLE RANGE SCAN |c |1 |54 | -==================================================================================== +================================================================================ +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +-------------------------------------------------------------------------------- +|0 |PX COORDINATOR | |1 |74 | +|1 |└─EXCHANGE OUT DISTR |:EX10002|1 |72 | +|2 | └─HASH OUTER JOIN | |1 |68 | +|3 | ├─PX PARTITION ITERATOR | |1 |7 | +|4 | │ └─TABLE FULL SCAN |a |1 |7 | +|5 | └─EXCHANGE IN DISTR | |1 |61 | +|6 | └─EXCHANGE OUT DISTR (PKEY) |:EX10001|1 |60 | +|7 | └─NESTED-LOOP OUTER JOIN | |1 |57 | +|8 | ├─SUBPLAN SCAN |b |1 |10 | +|9 | │ └─LIMIT | |1 |10 | +|10| │ └─EXCHANGE IN MERGE SORT DISTR| |1 |10 | +|11| │ └─EXCHANGE OUT DISTR |:EX10000|1 |9 | +|12| │ └─TOP-N SORT | |1 |7 | +|13| │ └─PX PARTITION ITERATOR | |1 |7 | +|14| │ └─HASH GROUP BY | |1 |7 | +|15| │ └─TABLE FULL SCAN |t4 |1 |7 | +|16| └─DISTRIBUTED TABLE RANGE SCAN |c |1 |46 | +================================================================================ Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(a.c1, a.c2, a.c3, a.c4, b.c1, b.c3, b.yyy, b.max(c4), c.c1, c.c2, c.c3, c.c4)]), filter(nil), rowset=16 @@ -1514,34 +1452,29 @@ Outputs & filters: range_key([a.c1], [a.c2], [a.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true 5 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)], [c.c1], [c.c2], [c.c3], [c.c4]), filter(nil), rowset=16 6 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)], [c.c1], [c.c2], [c.c3], [c.c4]), filter(nil), rowset=16 - (#keys=1, [b.c3]), dop=1 - 7 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)], [c.c1], [c.c2], [c.c3], [c.c4]), filter(nil), rowset=16 - conds(nil), nl_params_([b.c1(:0)], [b.c3(:1)]), use_batch=false - 8 - output([b.c1], [b.c3], [PARTITION_ID], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 - 9 - output([b.c1], [b.c3], [PARTITION_ID], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 (#keys=1, [b.c3]), is_single, dop=1 - 10 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 + 7 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)], [c.c1], [c.c2], [c.c3], [c.c4]), filter(nil), rowset=16 + conds(nil), nl_params_([b.c1(:0)], [b.c3(:1)]), use_batch=true + 8 - output([b.c1], [b.c3], [b.yyy], [b.max(c4)]), filter(nil), rowset=16 access([b.c1], [b.c3], [b.yyy], [b.max(c4)]) - 11 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 9 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 limit(1), offset(nil) - 12 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 10 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 sort_keys([T_FUN_SUM(t4.c2), ASC]) - 13 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 11 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 dop=1 - 14 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 12 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 sort_keys([T_FUN_SUM(t4.c2), ASC]), topn(1) - 15 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 13 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 partition wise, force partition granule - 16 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 + 14 - output([t4.c1], [t4.c3], [T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]), filter(nil), rowset=16 group([t4.c3]), agg_func([T_FUN_SUM(t4.c2)], [T_FUN_MAX(t4.c4)]) - 17 - output([t4.c1], [t4.c2], [t4.c3], [t4.c4]), filter(nil), rowset=16 + 15 - output([t4.c1], [t4.c2], [t4.c3], [t4.c4]), filter(nil), rowset=16 access([t4.c1], [t4.c2], [t4.c3], [t4.c4]), partitions(p0sp[0-2]) is_index_back=false, is_global_index=false, range_key([t4.c1], [t4.c2], [t4.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true - 18 - output([c.c1], [c.c2], [c.c3], [c.c4]), filter(nil), rowset=16 - affinitize, force partition granule - 19 - output([c.c1], [c.c2], [c.c3], [c.c4]), filter([:1 = c.c3]), rowset=16 - access([c.c1], [c.c2], [c.c3], [c.c4]), partitions(p0sp[0-2]) + 16 - output([c.c1], [c.c2], [c.c3], [c.c4]), filter([:1 = c.c3]), rowset=16 + access([GROUP_ID], [c.c1], [c.c2], [c.c3], [c.c4]), partitions(p0sp[0-2]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([c.c1], [c.c2], [c.c3]), range(MIN ; MAX), range_cond([:0 = c.c1]) diff --git a/tools/deploy/mysql_test/r/mysql/information_schema.result b/tools/deploy/mysql_test/r/mysql/information_schema.result index 94fc1c47f7..8969ea3d8d 100644 --- a/tools/deploy/mysql_test/r/mysql/information_schema.result +++ b/tools/deploy/mysql_test/r/mysql/information_schema.result @@ -349,6 +349,7 @@ select * from information_schema.tables where table_schema in ('oceanbase', 'mys | def | oceanbase | DBA_OB_RSRC_IO_DIRECTIVES | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_SEQUENCE_OBJECTS | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_SERVICES | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | +| def | oceanbase | DBA_OB_SPM_EVO_RESULT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_STORAGE_IO_USAGE | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_SYS_VARIABLES | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_TABLEGROUPS | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | @@ -902,6 +903,7 @@ select * from information_schema.tables where table_schema in ('oceanbase', 'mys | def | oceanbase | __all_virtual_sesstat | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_shared_storage_quota | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_show_trace | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | +| def | oceanbase | __all_virtual_spm_evo_result | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_sql_audit | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_sql_monitor_statname | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_sql_plan | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | @@ -1938,6 +1940,7 @@ select * from information_schema.tables where table_schema in ('oceanbase', 'mys | def | oceanbase | DBA_OB_RSRC_IO_DIRECTIVES | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_SEQUENCE_OBJECTS | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_SERVICES | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | +| def | oceanbase | DBA_OB_SPM_EVO_RESULT | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_STORAGE_IO_USAGE | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_SYS_VARIABLES | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | DBA_OB_TABLEGROUPS | SYSTEM VIEW | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | @@ -2491,6 +2494,7 @@ select * from information_schema.tables where table_schema in ('oceanbase', 'mys | def | oceanbase | __all_virtual_sesstat | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_shared_storage_quota | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_show_trace | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | +| def | oceanbase | __all_virtual_spm_evo_result | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_sql_audit | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_sql_monitor_statname | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | | def | oceanbase | __all_virtual_sql_plan | SYSTEM TABLE | MEMORY | NULL | DYNAMIC | NULL | NULL | NULL | NULL | 0 | NULL | NULL | NULL | NULL | NULL | utf8mb4_general_ci | NULL | NULL | | FALSE | 0 | @@ -3279,6 +3283,10 @@ select * from information_schema.statistics where table_schema in ('oceanbase', | def | oceanbase | __all_spatial_reference_systems | 0 | oceanbase | PRIMARY | 1 | srs_id | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | | def | oceanbase | __all_spm_config | 0 | oceanbase | PRIMARY | 1 | tenant_id | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | | def | oceanbase | __all_spm_config | 0 | oceanbase | PRIMARY | 2 | name | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | +| def | oceanbase | __all_spm_evo_result | 0 | oceanbase | PRIMARY | 1 | tenant_id | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | +| def | oceanbase | __all_spm_evo_result | 0 | oceanbase | PRIMARY | 2 | record_time | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | +| def | oceanbase | __all_spm_evo_result | 0 | oceanbase | PRIMARY | 3 | svr_ip | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | +| def | oceanbase | __all_spm_evo_result | 0 | oceanbase | PRIMARY | 4 | svr_port | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | | def | oceanbase | __all_storage_ha_error_diagnose_history | 0 | oceanbase | PRIMARY | 1 | gmt_create | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | | def | oceanbase | __all_storage_ha_error_diagnose_history | 0 | oceanbase | PRIMARY | 2 | svr_ip | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | | def | oceanbase | __all_storage_ha_error_diagnose_history | 0 | oceanbase | PRIMARY | 3 | svr_port | A | NULL | NULL | NULL | | BTREE | VALID | | YES | NULL | diff --git a/tools/deploy/mysql_test/r/mysql/intersect.result b/tools/deploy/mysql_test/r/mysql/intersect.result index e0097db83c..8af7cb267c 100644 --- a/tools/deploy/mysql_test/r/mysql/intersect.result +++ b/tools/deploy/mysql_test/r/mysql/intersect.result @@ -122,7 +122,7 @@ Query Plan |2 |│ └─HASH EXCEPT DISTINCT | |1 |57 | |3 |│ ├─DISTRIBUTED TABLE FULL SCAN|t8(i_OkcN) |1 |28 | |4 |│ └─DISTRIBUTED TABLE FULL SCAN|t8(i_OkcN) |1 |28 | -|5 |└─DISTRIBUTED TABLE FULL SCAN |t8_alias1(i_ahayugXY)|1 |3 | +|5 |└─TABLE FULL SCAN |t8_alias1(i_ahayugXY)|1 |3 | ================================================================================== Outputs & filters: ------------------------------------- @@ -155,7 +155,7 @@ Query Plan |2 |│ └─HASH INTERSECT DISTINCT | |1 |57 | |3 |│ ├─DISTRIBUTED TABLE FULL SCAN|t8(i_OkcN) |1 |28 | |4 |│ └─DISTRIBUTED TABLE FULL SCAN|t8(i_OkcN) |1 |28 | -|5 |└─DISTRIBUTED TABLE FULL SCAN |t8_alias1(i_ahayugXY)|1 |3 | +|5 |└─TABLE FULL SCAN |t8_alias1(i_ahayugXY)|1 |3 | ================================================================================== Outputs & filters: ------------------------------------- diff --git a/tools/deploy/mysql_test/r/mysql/view_2.result b/tools/deploy/mysql_test/r/mysql/view_2.result index 5137d6ae83..fcc56b0647 100644 --- a/tools/deploy/mysql_test/r/mysql/view_2.result +++ b/tools/deploy/mysql_test/r/mysql/view_2.result @@ -482,7 +482,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t11] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:1 estimation method:[DYNAMIC SAMPLING FULL] t21: @@ -494,11 +494,13 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t21] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:1 estimation method:[DYNAMIC SAMPLING FULL] Plan Type: LOCAL + Parameters: + :0 => 10 Note: Degree of Parallelisim is 1 because of table property Expr Constraints: diff --git a/tools/deploy/mysql_test/test_suite/column_store_encoding/r/mysql/basic_cs_encoding.result b/tools/deploy/mysql_test/test_suite/column_store_encoding/r/mysql/basic_cs_encoding.result index 7e0e7c806c..46bba4996b 100644 --- a/tools/deploy/mysql_test/test_suite/column_store_encoding/r/mysql/basic_cs_encoding.result +++ b/tools/deploy/mysql_test/test_suite/column_store_encoding/r/mysql/basic_cs_encoding.result @@ -39,14 +39,14 @@ create table t4(a int) row_format = compressed with column group (all columns, e insert into t4 values (-1), (0); explain select /*+ LEADING(t4,t3) USE_NL(t3,t4) NO_USE_NL_MATERIALIZATION(t3) */ t3.a from t4,t3 where (t3.a >= t4.a + 31 and t3.a <= t4.a + 35) or (t3.a >= t4.a + 1 and t3.a <= t4.a + 5) order by t3.a; Query Plan -================================================================ -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ----------------------------------------------------------------- -|0 |SORT | |5 |35 | -|1 |└─NESTED-LOOP JOIN | |5 |35 | -|2 | ├─COLUMN TABLE FULL SCAN |t4 |2 |3 | -|3 | └─DISTRIBUTED TABLE RANGE SCAN|t3 |3 |16 | -================================================================ +========================================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +---------------------------------------------------------- +|0 |SORT | |5 |35 | +|1 |└─NESTED-LOOP JOIN | |5 |35 | +|2 | ├─COLUMN TABLE FULL SCAN|t4 |2 |3 | +|3 | └─TABLE RANGE SCAN |t3 |3 |16 | +========================================================== Outputs & filters: ------------------------------------- 0 - output([t3.a]), filter(nil), rowset=16 diff --git a/tools/deploy/mysql_test/test_suite/column_store_encoding/r/mysql/count_pushdown_cs_encoding.result b/tools/deploy/mysql_test/test_suite/column_store_encoding/r/mysql/count_pushdown_cs_encoding.result index 7505c17708..d07a651088 100644 --- a/tools/deploy/mysql_test/test_suite/column_store_encoding/r/mysql/count_pushdown_cs_encoding.result +++ b/tools/deploy/mysql_test/test_suite/column_store_encoding/r/mysql/count_pushdown_cs_encoding.result @@ -5,10 +5,10 @@ Query Plan =================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| --------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |5 | +|0 |SUBPLAN FILTER | |1 |21 | |1 |├─SCALAR GROUP BY | |1 |3 | |2 |│ └─TABLE FULL SCAN|x |1 |3 | -|3 |└─TABLE FULL SCAN |a |1 |3 | +|3 |└─TABLE FULL SCAN |a |1 |18 | =================================================== Outputs & filters: ------------------------------------- @@ -139,17 +139,23 @@ count(1) count(a) count(b) count(c) count(*) create table t3(a int, b int); explain select count(distinct a) from t3; Query Plan -================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |SCALAR GROUP BY | |1 |3 | -|1 |└─TABLE FULL SCAN|t3 |1 |3 | -================================================= +====================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------ +|0 |SCALAR GROUP BY | |1 |3 | +|1 |└─SUBPLAN SCAN |VIEW1|1 |3 | +|2 | └─HASH DISTINCT | |1 |3 | +|3 | └─TABLE FULL SCAN|t3 |1 |3 | +====================================================== Outputs & filters: ------------------------------------- - 0 - output([T_FUN_COUNT(distinct t3.a)]), filter(nil), rowset=16 - group(nil), agg_func([T_FUN_COUNT(distinct t3.a)]) - 1 - output([t3.a]), filter(nil), rowset=16 + 0 - output([T_FUN_COUNT(VIEW1.t3.a)]), filter(nil), rowset=16 + group(nil), agg_func([T_FUN_COUNT(VIEW1.t3.a)]) + 1 - output([VIEW1.t3.a]), filter(nil), rowset=16 + access([VIEW1.t3.a]) + 2 - output([t3.a]), filter(nil), rowset=16 + distinct([t3.a]) + 3 - output([t3.a]), filter(nil), rowset=16 access([t3.a]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t3.__pk_increment]), range(MIN ; MAX)always true diff --git a/tools/deploy/mysql_test/test_suite/executor/r/mysql/basic.result b/tools/deploy/mysql_test/test_suite/executor/r/mysql/basic.result index a1793a14fd..d58fe84405 100644 --- a/tools/deploy/mysql_test/test_suite/executor/r/mysql/basic.result +++ b/tools/deploy/mysql_test/test_suite/executor/r/mysql/basic.result @@ -2389,9 +2389,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |30 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |46 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | @@ -2431,9 +2431,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |30 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |46 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | @@ -2473,9 +2473,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |30 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |46 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | @@ -2515,9 +2515,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |30 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |46 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | @@ -4320,9 +4320,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |29 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |45 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | @@ -4362,9 +4362,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |29 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |45 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | @@ -4447,9 +4447,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |30 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |46 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | @@ -4489,9 +4489,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |30 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |46 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | @@ -4531,9 +4531,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |30 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |46 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | @@ -4573,9 +4573,9 @@ Query Plan ===================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |30 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|1 |28 | -|2 | └─HASH JOIN | |1 |24 | +|0 |PX COORDINATOR | |4 |46 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|4 |39 | +|2 | └─HASH JOIN | |4 |24 | |3 | ├─EXCHANGE IN DISTR | |4 |16 | |4 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|4 |14 | |5 | │ └─PX PARTITION ITERATOR | |4 |9 | diff --git a/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_filter_mysql.result b/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_filter_mysql.result index 781ce74a98..1b64ac69a7 100644 --- a/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_filter_mysql.result +++ b/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_filter_mysql.result @@ -133,11 +133,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(0 0)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where st_intersects(g, ST_GeomFromText('POINT(1 1)')); @@ -195,11 +197,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(1 1)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where st_intersects(g, ST_GeomFromText('LINESTRING(0 0,1 1)')); @@ -257,11 +261,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0,1 1)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where st_intersects(g, ST_GeomFromText('POLYGON((0 0, 10 0, 10 5, 0 5, 0 0))')); @@ -320,11 +326,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POLYGON((0 0, 10 0, 10 5, 0 5, 0 0))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where st_intersects(g, ST_GeomFromText('MULTIPOINT((0 0), (1 1))')); @@ -382,11 +390,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTIPOINT((0 0), (1 1))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where st_intersects(g, ST_GeomFromText('MULTILINESTRING((0 0, 1 1), (4 4, 5 5))')); @@ -445,11 +455,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTILINESTRING((0 0, 1 1), (4 4, 5 5))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where st_intersects(g, ST_GeomFromText('MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((2.5 2.5, 6 2.5, 6 6, 2.5 6, 2.5 2.5), (3.5 3, 4.5 3, 4.5 4.5, 3.5 4.5, 3.5 3)))')); @@ -508,11 +520,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((2.5 2.5, 6 2.5, 6 6, 2.5 6, 2.5 2.5), (3.5 3, 4.5 3, 4.5 4.5, 3.5 4.5, 3.5 3)))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where st_intersects(g, ST_GeomFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(2 2,3 3))')); @@ -570,11 +584,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(2 2,3 3))' Note: Degree of Parallelisim is 1 because of table property SET @line = ST_GeomFromText('LINESTRING(3 3,5 5)'); @@ -691,11 +707,14 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(0 0)' + :1 => 'POINT(1 1)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where st_intersects(g, ST_GeomFromText('POINT(0 0)')) and st_intersects(g, ST_GeomFromText('POINT(1 1)')); @@ -753,11 +772,14 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(0 0)' + :1 => 'POINT(1 1)' Note: Degree of Parallelisim is 1 because of table property drop table if exists t; @@ -1024,11 +1046,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[geom, geo_table2] pruned_index_name:[geo_table2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(3.0 3.0)' Note: Degree of Parallelisim is 1 because of table property SELECT k, k_plus_one FROM geo_table2 WHERE ST_Intersects(ST_GeomFromText('POINT(3.0 3.0)'), geom); @@ -1094,11 +1118,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[geom, geo_table2] pruned_index_name:[geo_table2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(3.0 3.0)' Note: Degree of Parallelisim is 1 because of table property drop table if exists geo_table; @@ -1180,11 +1206,14 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[geom, geo_table] pruned_index_name:[geo_table] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(400003 4000003)' + :1 => 26918 Note: Degree of Parallelisim is 1 because of table property drop table if exists t; @@ -1398,11 +1427,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(0 0)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where _st_covers(g, ST_GeomFromText('POINT(1 1)')); @@ -1460,11 +1491,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(1 1)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where _st_covers(g, ST_GeomFromText('LINESTRING(0 0,1 1)')); @@ -1522,11 +1555,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0,1 1)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where _st_covers(g, ST_GeomFromText('POLYGON((0 0, 10 0, 10 5, 0 5, 0 0))')); @@ -1586,11 +1621,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POLYGON((0 0, 10 0, 10 5, 0 5, 0 0))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where _st_covers(g, ST_GeomFromText('MULTIPOINT((0 0), (1 1))')); @@ -1648,11 +1685,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTIPOINT((0 0), (1 1))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where _st_covers(g, ST_GeomFromText('MULTILINESTRING((0 0, 1 1), (4 4, 5 5))')); @@ -1711,11 +1750,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTILINESTRING((0 0, 1 1), (4 4, 5 5))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where _st_covers(g, ST_GeomFromText('MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((2.5 2.5, 6 2.5, 6 6, 2.5 6, 2.5 2.5), (3.5 3, 4.5 3, 4.5 4.5, 3.5 4.5, 3.5 3)))')); @@ -1774,11 +1815,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((2.5 2.5, 6 2.5, 6 6, 2.5 6, 2.5 2.5), (3.5 3, 4.5 3, 4.5 4.5, 3.5 4.5, 3.5 3)))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where _st_covers(g, ST_GeomFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(2 2,3 3))')); @@ -1836,11 +1879,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(2 2,3 3))' Note: Degree of Parallelisim is 1 because of table property select /*+index(t idx)*/ st_astext(g) from t where ST_Within(g, ST_GeomFromText('POINT(0 0)')); @@ -2010,11 +2055,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(0 0)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Within(g, ST_GeomFromText('POINT(1 1)')); @@ -2072,11 +2119,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(1 1)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Within(g, ST_GeomFromText('LINESTRING(0 0,1 1)')); @@ -2134,11 +2183,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0,1 1)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Within(g, ST_GeomFromText('POLYGON((0 0, 10 0, 10 5, 0 5, 0 0))')); @@ -2197,11 +2248,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POLYGON((0 0, 10 0, 10 5, 0 5, 0 0))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Within(g, ST_GeomFromText('MULTIPOINT((0 0), (1 1))')); @@ -2259,11 +2312,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTIPOINT((0 0), (1 1))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Within(g, ST_GeomFromText('MULTILINESTRING((0 0, 1 1), (4 4, 5 5))')); @@ -2322,11 +2377,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTILINESTRING((0 0, 1 1), (4 4, 5 5))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Within(g, ST_GeomFromText('MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((2.5 2.5, 6 2.5, 6 6, 2.5 6, 2.5 2.5), (3.5 3, 4.5 3, 4.5 4.5, 3.5 4.5, 3.5 3)))')); @@ -2385,11 +2442,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((2.5 2.5, 6 2.5, 6 6, 2.5 6, 2.5 2.5), (3.5 3, 4.5 3, 4.5 4.5, 3.5 4.5, 3.5 3)))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Within(g, ST_GeomFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(2 2,3 3))')); @@ -2447,11 +2506,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(2 2,3 3))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Contains(g, ST_GeomFromText('POINT(0 0)')); @@ -2509,11 +2570,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(0 0)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Contains(g, ST_GeomFromText('POINT(1 1)')); @@ -2571,11 +2634,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(1 1)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Contains(g, ST_GeomFromText('LINESTRING(0 0,1 1)')); @@ -2633,11 +2698,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0,1 1)' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Contains(g, ST_GeomFromText('POLYGON((0 0, 10 0, 10 5, 0 5, 0 0))')); @@ -2697,11 +2764,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POLYGON((0 0, 10 0, 10 5, 0 5, 0 0))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Contains(g, ST_GeomFromText('MULTIPOINT((0 0), (1 1))')); @@ -2759,11 +2828,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTIPOINT((0 0), (1 1))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Contains(g, ST_GeomFromText('MULTILINESTRING((0 0, 1 1), (4 4, 5 5))')); @@ -2822,11 +2893,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTILINESTRING((0 0, 1 1), (4 4, 5 5))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Contains(g, ST_GeomFromText('MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((2.5 2.5, 6 2.5, 6 6, 2.5 6, 2.5 2.5), (3.5 3, 4.5 3, 4.5 4.5, 3.5 4.5, 3.5 3)))')); @@ -2885,11 +2958,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'MULTIPOLYGON (((0 0, 2 0, 2 2, 0 2, 0 0)), ((2.5 2.5, 6 2.5, 6 6, 2.5 6, 2.5 2.5), (3.5 3, 4.5 3, 4.5 4.5, 3.5 4.5, 3.5 3)))' Note: Degree of Parallelisim is 1 because of table property explain EXTENDED_NOADDR select /*+index(t idx)*/ st_astext(g) from t where ST_Contains(g, ST_GeomFromText('GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(2 2,3 3))')); @@ -2947,11 +3022,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'GEOMETRYCOLLECTION(POINT(0 0), LINESTRING(2 2,3 3))' Note: Degree of Parallelisim is 1 because of table property drop table geo_table; @@ -3031,11 +3108,14 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, t] pruned_index_name:[t] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'POINT(600000 3000000)' + :1 => 3825 Note: Degree of Parallelisim is 1 because of table property select /*+index(t idx)*/ st_astext(g) from t where st_intersects(g, ST_GeomFromText('LINESTRING(550000 2600000,600000 3000000)', 3825)); diff --git a/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_index2_mysql.result b/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_index2_mysql.result index 5350144437..82fc5832f0 100644 --- a/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_index2_mysql.result +++ b/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_index2_mysql.result @@ -247,11 +247,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, tt2] pruned_index_name:[idx] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0, 10 10, 20 25, 50 60)' Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select /*+index(tt2 idx)*/ st_astext(g) from tt2 where ST_Intersects(g,ST_GeomFromText('LINESTRING(0 0, 10 10, 20 25, 50 60)')); @@ -296,11 +298,13 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, tt2] pruned_index_name:[idx] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0, 10 10, 20 25, 50 60)' Note: Degree of Parallelisim is 1 because of table property drop table tt2; @@ -438,11 +442,14 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, tt2] unstable_index_name:[tt2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0, 10 10, 20 25, 50 60)' + :1 => 4326 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select /*+index(tt2 idx)*/ st_astext(g) from tt2 where ST_Intersects(g,ST_GeomFromText('LINESTRING(0 0, 10 10, 20 25, 50 60)', 4326)); @@ -577,11 +584,14 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, tt2] pruned_index_name:[tt2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0, 10 10, 20 25, 50 60)' + :1 => 4326 Note: Degree of Parallelisim is 1 because of table property insert into tt2 values (1, ST_GeomFromText('LINESTRING(0 0, 10 10, 20 25, 50 60)', 4326)); @@ -716,11 +726,14 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, tt2] unstable_index_name:[tt2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0, 10 10, 20 25, 50 60)' + :1 => 4326 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select /*+index(tt2 idx)*/ st_astext(g) from tt2 where ST_Intersects(g,ST_GeomFromText('LINESTRING(0 0, 10 10, 20 25, 50 60)', 4326)); @@ -855,11 +868,14 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[idx, tt2] pruned_index_name:[tt2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 'LINESTRING(0 0, 10 10, 20 25, 50 60)' + :1 => 4326 Note: Degree of Parallelisim is 1 because of table property drop table tt2; diff --git a/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_index_mysql.result b/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_index_mysql.result index 4c67d50cd2..b132ca831a 100644 --- a/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_index_mysql.result +++ b/tools/deploy/mysql_test/test_suite/geometry/r/mysql/geometry_index_mysql.result @@ -270,7 +270,7 @@ Query Plan ================================================ |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------ -|0 |TABLE FULL SCAN|t1(g)|2 |383 | +|0 |TABLE FULL SCAN|t1(g)|3 |384 | ================================================ Outputs & filters: ------------------------------------- @@ -295,7 +295,7 @@ Query Plan ================================================ |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------ -|0 |TABLE FULL SCAN|t1(g)|2 |383 | +|0 |TABLE FULL SCAN|t1(g)|3 |383 | ================================================ Outputs & filters: ------------------------------------- @@ -320,7 +320,7 @@ Query Plan ================================================ |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------ -|0 |TABLE FULL SCAN|t1(g)|2 |383 | +|0 |TABLE FULL SCAN|t1(g)|3 |384 | ================================================ Outputs & filters: ------------------------------------- @@ -345,7 +345,7 @@ Query Plan ================================================ |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------ -|0 |TABLE FULL SCAN|t1(g)|2 |383 | +|0 |TABLE FULL SCAN|t1(g)|3 |384 | ================================================ Outputs & filters: ------------------------------------- diff --git a/tools/deploy/mysql_test/test_suite/global_index/r/mysql/global_index_lookup_1.result b/tools/deploy/mysql_test/test_suite/global_index/r/mysql/global_index_lookup_1.result index 90882f237a..aa5b8ee434 100644 --- a/tools/deploy/mysql_test/test_suite/global_index/r/mysql/global_index_lookup_1.result +++ b/tools/deploy/mysql_test/test_suite/global_index/r/mysql/global_index_lookup_1.result @@ -629,20 +629,20 @@ Query Plan ================================================================ |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |93 | +|0 |SUBPLAN FILTER | |1 |88 | |1 |├─TABLE FULL SCAN |t1 |2 |3 | -|2 |└─DISTRIBUTED TABLE RANGE SCAN|t2(i1)|1 |46 | +|2 |└─DISTRIBUTED TABLE RANGE SCAN|t2(i1)|1 |43 | ================================================================ Outputs & filters: ------------------------------------- 0 - output([t1.a], [t1.b]), filter([(T_OP_EXISTS, subquery(1))]), rowset=16 - exec_params_([t1.b(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false + exec_params_([t1.b(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true 1 - output([t1.b], [t1.a]), filter(nil), rowset=16 access([t1.b], [t1.a]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t1.__pk_increment]), range(MIN ; MAX)always true 2 - output([1]), filter([t2.c > 0]), rowset=16 - access([t2.a], [t2.c]), partitions(p0) + access([GROUP_ID], [t2.a], [t2.c]), partitions(p0) is_index_back=true, is_global_index=true, filter_before_indexback[false], range_key([t2.b], [t2.a]), range(MIN,MIN ; MAX,MAX)always true, range_cond([:0 = t2.b]) diff --git a/tools/deploy/mysql_test/test_suite/groupby/r/mysql/group_by_basic.result b/tools/deploy/mysql_test/test_suite/groupby/r/mysql/group_by_basic.result index a88f629699..c116c047b7 100644 --- a/tools/deploy/mysql_test/test_suite/groupby/r/mysql/group_by_basic.result +++ b/tools/deploy/mysql_test/test_suite/groupby/r/mysql/group_by_basic.result @@ -361,8 +361,8 @@ insert into t1 (c1, c2, c3) values (2, 3, 2); insert into t1 (c1, c2, c3) values (2, 3, 3); select c2, avg(distinct c3) from t1 group by c2; c2 avg(distinct c3) -2 2.5000 1 1.5000 +2 2.5000 3 2.5000 select c1,c2, group_concat(distinct c3 order by c3 desc) from t1 group by c1,c2; c1 c2 group_concat(distinct c3 order by c3 desc) diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result index b6fe71e35e..f63d8b13a5 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/all_virtual_sys_parameter_stat.result @@ -310,6 +310,7 @@ _bloom_filter_ratio _cache_wash_interval _checkpoint_diagnose_preservation_count _chunk_row_store_mem_limit +_complex_cbqt_table_num _ctx_memory_limit _datafile_usage_lower_bound_percentage _datafile_usage_upper_bound_percentage diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_mysql.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_mysql.result index 435ee5f37b..02d5ac5c3a 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_mysql.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_mysql.result @@ -3132,7 +3132,7 @@ IM_IMCU_COUNT decimal(10,0) NO IM_BLOCK_COUNT decimal(10,0) NO IM_STAT_UPDATE_TIME datetime NO SCAN_RATE decimal(10,0) NO -SAMPLE_SIZE decimal(10,0) YES NULL +SAMPLE_SIZE decimal(20,0) YES NULL LAST_ANALYZED datetime(6) NO NULL GLOBAL_STATS varchar(3) NO USER_STATS varchar(3) NO @@ -7188,6 +7188,25 @@ CLIENT_INFO varchar(2048) NO select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.V$OB_KV_CLIENT_INFO limit 1); cnt 1 +desc oceanbase.DBA_OB_SPM_EVO_RESULT; +Field Type Null Key Default Extra +OWNER varchar(128) NO +RECORD_TIME timestamp(6) NO NULL +SVR_IP varchar(46) NO NULL +SVR_PORT bigint(20) NO NULL +SQL_ID varchar(32) NO NULL +TYPE varchar(32) NO +START_TIME timestamp(6) YES NULL +END_TIME timestamp(6) YES NULL +STATUS varchar(7) YES NULL +NEW_PLAN_BETTER tinyint(4) YES NULL +EVO_PLAN_EXEC_COUNT bigint(20) YES NULL +EVO_PLAN_CPU_TIME bigint(20) YES NULL +BASELINE_EXEC_COUNT bigint(20) YES NULL +BASELINE_CPU_TIME bigint(20) YES NULL +select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.DBA_OB_SPM_EVO_RESULT limit 1); +cnt +1 desc oceanbase.GV$OB_FUNCTION_IO_STAT; Field Type Null Key Default Extra SVR_IP varchar(46) NO NULL diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_sys.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_sys.result index 73df0689c2..eeca38c7c6 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_sys.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_sys_views_in_sys.result @@ -4577,7 +4577,7 @@ IM_IMCU_COUNT decimal(10,0) NO IM_BLOCK_COUNT decimal(10,0) NO IM_STAT_UPDATE_TIME datetime NO SCAN_RATE decimal(10,0) NO -SAMPLE_SIZE decimal(10,0) YES NULL +SAMPLE_SIZE decimal(20,0) YES NULL LAST_ANALYZED datetime(6) NO NULL GLOBAL_STATS varchar(3) NO USER_STATS varchar(3) NO @@ -10169,6 +10169,45 @@ CLIENT_INFO varchar(2048) NO select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.V$OB_KV_CLIENT_INFO limit 1); cnt 1 +desc oceanbase.DBA_OB_SPM_EVO_RESULT; +Field Type Null Key Default Extra +OWNER varchar(128) NO +RECORD_TIME timestamp(6) NO NULL +SVR_IP varchar(46) NO NULL +SVR_PORT bigint(20) NO NULL +SQL_ID varchar(32) NO NULL +TYPE varchar(32) NO +START_TIME timestamp(6) YES NULL +END_TIME timestamp(6) YES NULL +STATUS varchar(7) YES NULL +NEW_PLAN_BETTER tinyint(4) YES NULL +EVO_PLAN_EXEC_COUNT bigint(20) YES NULL +EVO_PLAN_CPU_TIME bigint(20) YES NULL +BASELINE_EXEC_COUNT bigint(20) YES NULL +BASELINE_CPU_TIME bigint(20) YES NULL +select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.DBA_OB_SPM_EVO_RESULT limit 1); +cnt +1 +desc oceanbase.CDB_OB_SPM_EVO_RESULT; +Field Type Null Key Default Extra +TENANT_ID bigint(20) NO NULL +OWNER varchar(128) NO +RECORD_TIME timestamp(6) NO NULL +SVR_IP varchar(46) NO NULL +SVR_PORT bigint(20) NO NULL +SQL_ID varchar(32) NO NULL +TYPE varchar(32) NO +START_TIME timestamp(6) YES NULL +END_TIME timestamp(6) YES NULL +STATUS varchar(7) YES NULL +NEW_PLAN_BETTER tinyint(4) YES NULL +EVO_PLAN_EXEC_COUNT bigint(20) YES NULL +EVO_PLAN_CPU_TIME bigint(20) YES NULL +BASELINE_EXEC_COUNT bigint(20) YES NULL +BASELINE_CPU_TIME bigint(20) YES NULL +select /*+QUERY_TIMEOUT(60000000)*/ count(*) as cnt from (select * from oceanbase.CDB_OB_SPM_EVO_RESULT limit 1); +cnt +1 desc oceanbase.GV$OB_FUNCTION_IO_STAT; Field Type Null Key Default Extra SVR_IP varchar(46) NO NULL diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_mysql.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_mysql.result index bc735e229a..81946faf57 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_mysql.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_mysql.result @@ -5258,6 +5258,26 @@ IF(count(*) >= 0, 1, 0) "oceanbase.__all_virtual_kv_group_commit_status runs in single server" IF(count(*) >= 0, 1, 0) 1 +desc oceanbase.__all_virtual_spm_evo_result; +Field Type Null Key Default Extra +tenant_id bigint(20) NO PRI NULL +record_time timestamp(6) NO PRI NULL +svr_ip varchar(46) NO PRI NULL +svr_port bigint(20) NO PRI NULL +database_id bigint(20) NO NULL +sql_id varchar(32) NO NULL +type bigint(20) NO NULL +start_time timestamp(6) YES NULL +end_time timestamp(6) YES NULL +status varchar(7) YES NULL +new_plan_better tinyint(4) YES NULL +evo_plan_exec_count bigint(20) YES NULL +evo_plan_cpu_time bigint(20) YES NULL +baseline_exec_count bigint(20) YES NULL +baseline_cpu_time bigint(20) YES NULL +select /*+QUERY_TIMEOUT(60000000)*/ IF(count(*) >= 0, 1, 0) from oceanbase.__all_virtual_spm_evo_result; +IF(count(*) >= 0, 1, 0) +1 desc oceanbase.__all_virtual_vector_index_info; Field Type Null Key Default Extra svr_ip varchar(46) NO NULL diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_sys.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_sys.result index c7c9c89fa3..0ea5436e9c 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_sys.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/desc_virtual_table_in_sys.result @@ -10008,6 +10008,26 @@ IF(count(*) >= 0, 1, 0) "oceanbase.__all_virtual_kv_group_commit_status runs in single server" IF(count(*) >= 0, 1, 0) 1 +desc oceanbase.__all_virtual_spm_evo_result; +Field Type Null Key Default Extra +tenant_id bigint(20) NO PRI NULL +record_time timestamp(6) NO PRI NULL +svr_ip varchar(46) NO PRI NULL +svr_port bigint(20) NO PRI NULL +database_id bigint(20) NO NULL +sql_id varchar(32) NO NULL +type bigint(20) NO NULL +start_time timestamp(6) YES NULL +end_time timestamp(6) YES NULL +status varchar(7) YES NULL +new_plan_better tinyint(4) YES NULL +evo_plan_exec_count bigint(20) YES NULL +evo_plan_cpu_time bigint(20) YES NULL +baseline_exec_count bigint(20) YES NULL +baseline_cpu_time bigint(20) YES NULL +select /*+QUERY_TIMEOUT(60000000)*/ IF(count(*) >= 0, 1, 0) from oceanbase.__all_virtual_spm_evo_result; +IF(count(*) >= 0, 1, 0) +1 desc oceanbase.__all_virtual_vector_index_info; Field Type Null Key Default Extra svr_ip varchar(46) NO NULL diff --git a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result index 3ebb58df06..242c7344c5 100644 --- a/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result +++ b/tools/deploy/mysql_test/test_suite/inner_table/r/mysql/inner_table_overall.result @@ -308,6 +308,7 @@ select 0xffffffffff & table_id, table_name, table_type, database_id, part_num fr 517 __all_storage_io_usage 0 201001 1 518 __all_mview_dep 0 201001 1 519 __all_scheduler_job_run_detail_v2 0 201001 1 +520 __all_spm_evo_result 0 201001 1 528 __all_ncomp_dll_v2 0 201001 1 10001 __tenant_virtual_all_table 2 201001 1 10002 __tenant_virtual_table_column 2 201001 1 @@ -780,6 +781,7 @@ select 0xffffffffff & table_id, table_name, table_type, database_id, part_num fr 12491 __all_virtual_log_transport_dest_stat 2 201001 1 12492 __all_virtual_ss_local_cache_info 2 201001 1 12493 __all_virtual_kv_group_commit_status 2 201001 1 +12495 __all_virtual_spm_evo_result 2 201001 1 12496 __all_virtual_vector_index_info 2 201001 1 12500 __all_virtual_kv_client_info 2 201001 1 12504 __all_virtual_function_io_stat 2 201001 1 @@ -1273,6 +1275,8 @@ select 0xffffffffff & table_id, table_name, table_type, database_id, part_num fr 21605 INNODB_SYS_FOREIGN_COLS 1 201002 1 21607 GV$OB_KV_CLIENT_INFO 1 201001 1 21608 V$OB_KV_CLIENT_INFO 1 201001 1 +21616 DBA_OB_SPM_EVO_RESULT 1 201001 1 +21617 CDB_OB_SPM_EVO_RESULT 1 201001 1 21620 GV$OB_FUNCTION_IO_STAT 1 201001 1 21621 V$OB_FUNCTION_IO_STAT 1 201001 1 21622 DBA_OB_TEMP_FILES 1 201001 1 diff --git a/tools/deploy/mysql_test/test_suite/join/r/mysql/anti_semi_join.result b/tools/deploy/mysql_test/test_suite/join/r/mysql/anti_semi_join.result index 944f13961f..e9421185e3 100644 --- a/tools/deploy/mysql_test/test_suite/join/r/mysql/anti_semi_join.result +++ b/tools/deploy/mysql_test/test_suite/join/r/mysql/anti_semi_join.result @@ -1352,9 +1352,9 @@ Query Plan ================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |SUBPLAN FILTER | |58 |287 | +|0 |SUBPLAN FILTER | |58 |2088 | |1 |├─TABLE FULL SCAN|xy_t1|116 |8 | -|2 |└─TABLE FULL SCAN|xy_t2|1 |3 | +|2 |└─TABLE FULL SCAN|xy_t2|1 |18 | ================================================== Outputs & filters: ------------------------------------- @@ -1594,13 +1594,13 @@ select * from xy_t4 where exists (select 1 from xy_t1 where xy_t4.c1 = xy_t1.c2) +------+------+ EXPLAIN select /*+ use_nl(xy_t4 xy_t1)*/ * from xy_t4 where exists (select 1 from xy_t1 where xy_t4.c1 = xy_t1.c2); Query Plan -======================================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------ -|0 |NESTED-LOOP SEMI JOIN | |2 |40 | -|1 |├─TABLE FULL SCAN |xy_t4 |2 |3 | -|2 |└─DISTRIBUTED TABLE RANGE SCAN|xy_t1(idx_c2)|1 |18 | -======================================================================= +=============================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +--------------------------------------------------------------- +|0 |NESTED-LOOP SEMI JOIN | |2 |40 | +|1 |├─TABLE FULL SCAN |xy_t4 |2 |3 | +|2 |└─TABLE RANGE SCAN |xy_t1(idx_c2)|1 |18 | +=============================================================== Outputs & filters: ------------------------------------- 0 - output([xy_t4.c1], [xy_t4.c2]), filter(nil), rowset=16 @@ -1719,13 +1719,13 @@ select * from xy_t2 where exists (select 1 from xy_t1 where xy_t2.c2 = xy_t1.c2) +------+------+ EXPLAIN select /*+ use_nl(xy_t2 xy_t1)*/ * from xy_t2 where exists (select 1 from xy_t1 where xy_t2.c2 = xy_t1.c2); Query Plan -======================================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------ -|0 |NESTED-LOOP SEMI JOIN | |8 |153 | -|1 |├─TABLE FULL SCAN |xy_t2(idx_c2)|8 |3 | -|2 |└─DISTRIBUTED TABLE RANGE SCAN|xy_t1(idx_c2)|1 |18 | -======================================================================= +=============================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +--------------------------------------------------------------- +|0 |NESTED-LOOP SEMI JOIN | |8 |153 | +|1 |├─TABLE FULL SCAN |xy_t2(idx_c2)|8 |3 | +|2 |└─TABLE RANGE SCAN |xy_t1(idx_c2)|1 |18 | +=============================================================== Outputs & filters: ------------------------------------- 0 - output([xy_t2.c1], [xy_t2.c2]), filter(nil), rowset=16 @@ -2224,9 +2224,9 @@ Query Plan ================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |SUBPLAN FILTER | |58 |287 | +|0 |SUBPLAN FILTER | |58 |2088 | |1 |├─TABLE FULL SCAN|xy_t1|116 |8 | -|2 |└─TABLE FULL SCAN|xy_t2|1 |3 | +|2 |└─TABLE FULL SCAN|xy_t2|1 |18 | ================================================== Outputs & filters: ------------------------------------- @@ -2468,13 +2468,13 @@ select * from xy_t4 where not exists (select 1 from xy_t1 where xy_t4.c1 = xy_t1 +------+------+ EXPLAIN select /*+ use_nl(xy_t4 xy_t1)*/ * from xy_t4 where not exists (select 1 from xy_t1 where xy_t4.c1 = xy_t1.c2); Query Plan -======================================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------ -|0 |NESTED-LOOP ANTI JOIN | |1 |40 | -|1 |├─TABLE FULL SCAN |xy_t4 |2 |3 | -|2 |└─DISTRIBUTED TABLE RANGE SCAN|xy_t1(idx_c2)|1 |18 | -======================================================================= +=============================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +--------------------------------------------------------------- +|0 |NESTED-LOOP ANTI JOIN | |1 |40 | +|1 |├─TABLE FULL SCAN |xy_t4 |2 |3 | +|2 |└─TABLE RANGE SCAN |xy_t1(idx_c2)|1 |18 | +=============================================================== Outputs & filters: ------------------------------------- 0 - output([xy_t4.c1], [xy_t4.c2]), filter(nil), rowset=16 @@ -2583,13 +2583,13 @@ select * from xy_t2 where not exists (select 1 from xy_t1 where xy_t2.c2 = xy_t1 +------+------+ EXPLAIN select /*+ use_nl(xy_t2 xy_t1)*/ * from xy_t2 where not exists (select 1 from xy_t1 where xy_t2.c2 = xy_t1.c2); Query Plan -======================================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------ -|0 |NESTED-LOOP ANTI JOIN | |1 |153 | -|1 |├─TABLE FULL SCAN |xy_t2(idx_c2)|8 |3 | -|2 |└─DISTRIBUTED TABLE RANGE SCAN|xy_t1(idx_c2)|1 |18 | -======================================================================= +=============================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +--------------------------------------------------------------- +|0 |NESTED-LOOP ANTI JOIN | |1 |153 | +|1 |├─TABLE FULL SCAN |xy_t2(idx_c2)|8 |3 | +|2 |└─TABLE RANGE SCAN |xy_t1(idx_c2)|1 |18 | +=============================================================== Outputs & filters: ------------------------------------- 0 - output([xy_t2.c1], [xy_t2.c2]), filter(nil), rowset=16 @@ -2676,7 +2676,7 @@ Query Plan |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------- |0 |SCALAR GROUP BY | |1 |34 | -|1 |└─HASH RIGHT SEMI JOIN | |45 |33 | +|1 |└─HASH RIGHT SEMI JOIN | |51 |33 | |2 | ├─TABLE FULL SCAN |xy_t3|12 |3 | |3 | └─HASH RIGHT SEMI JOIN | |51 |23 | |4 | ├─TABLE FULL SCAN |xy_t2|8 |3 | @@ -2714,7 +2714,7 @@ Query Plan |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------- |0 |SCALAR GROUP BY | |1 |34 | -|1 |└─HASH RIGHT SEMI JOIN | |45 |33 | +|1 |└─HASH RIGHT SEMI JOIN | |51 |33 | |2 | ├─TABLE FULL SCAN |xy_t3|12 |3 | |3 | └─HASH RIGHT SEMI JOIN | |51 |23 | |4 | ├─TABLE FULL SCAN |xy_t2|8 |3 | @@ -2751,11 +2751,11 @@ Query Plan ==================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------- -|0 |SCALAR GROUP BY | |1 |583 | -|1 |└─SUBPLAN FILTER | |42 |581 | +|0 |SCALAR GROUP BY | |1 |4168 | +|1 |└─SUBPLAN FILTER | |42 |4167 | |2 | ├─TABLE FULL SCAN|xy_t1|116 |8 | -|3 | ├─TABLE FULL SCAN|xy_t3|1 |3 | -|4 | └─TABLE FULL SCAN|xy_t2|1 |3 | +|3 | ├─TABLE FULL SCAN|xy_t3|1 |18 | +|4 | └─TABLE FULL SCAN|xy_t2|1 |18 | ==================================================== Outputs & filters: ------------------------------------- @@ -2828,11 +2828,11 @@ Query Plan ========================================================================= |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------- -|0 |SCALAR GROUP BY | |1 |4168 | -|1 |└─SUBPLAN FILTER | |42 |4167 | +|0 |SCALAR GROUP BY | |1 |3565 | +|1 |└─SUBPLAN FILTER | |42 |3563 | |2 | ├─TABLE FULL SCAN |xy_t1 |116 |8 | -|3 | ├─DISTRIBUTED TABLE RANGE SCAN|xy_t3(idx_c2)|1 |18 | -|4 | └─DISTRIBUTED TABLE RANGE SCAN|xy_t2(idx_c2)|1 |18 | +|3 | ├─DISTRIBUTED TABLE RANGE SCAN|xy_t3(idx_c2)|1 |16 | +|4 | └─DISTRIBUTED TABLE RANGE SCAN|xy_t2(idx_c2)|1 |16 | ========================================================================= Outputs & filters: ------------------------------------- @@ -3582,10 +3582,10 @@ Query Plan ==================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------- -|0 |SORT | |4 |22 | -|1 |└─SUBPLAN FILTER | |4 |22 | +|0 |SORT | |4 |147 | +|1 |└─SUBPLAN FILTER | |4 |146 | |2 | ├─TABLE FULL SCAN|xy_t1|8 |3 | -|3 | └─TABLE FULL SCAN|xy_t2|2 |3 | +|3 | └─TABLE FULL SCAN|xy_t2|2 |18 | ==================================================== Outputs & filters: ------------------------------------- @@ -3714,10 +3714,10 @@ Query Plan ==================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------- -|0 |SORT | |3 |16 | -|1 |└─SUBPLAN FILTER | |3 |15 | +|0 |SORT | |3 |93 | +|1 |└─SUBPLAN FILTER | |3 |92 | |2 | ├─TABLE FULL SCAN|xy_t2|5 |3 | -|3 | └─TABLE FULL SCAN|xy_t1|3 |3 | +|3 | └─TABLE FULL SCAN|xy_t1|3 |18 | ==================================================== Outputs & filters: ------------------------------------- @@ -3747,8 +3747,8 @@ Query Plan ==================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------- -|0 |SORT | |1 |7 | -|1 |└─HASH JOIN | |1 |7 | +|0 |SORT | |5 |8 | +|1 |└─HASH JOIN | |5 |7 | |2 | ├─TABLE FULL SCAN|xy_t2|5 |3 | |3 | └─TABLE FULL SCAN|xy_t1|8 |3 | ==================================================== @@ -3776,7 +3776,7 @@ Query Plan ================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |MERGE JOIN | |1 |6 | +|0 |MERGE JOIN | |5 |6 | |1 |├─TABLE FULL SCAN|xy_t2|5 |3 | |2 |└─TABLE FULL SCAN|xy_t1|8 |3 | ================================================== @@ -3803,9 +3803,9 @@ Query Plan ================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |SUBPLAN FILTER | |3 |15 | +|0 |SUBPLAN FILTER | |3 |92 | |1 |├─TABLE FULL SCAN|xy_t2|5 |3 | -|2 |└─TABLE FULL SCAN|xy_t1|3 |3 | +|2 |└─TABLE FULL SCAN|xy_t1|3 |18 | ================================================== Outputs & filters: ------------------------------------- @@ -3922,9 +3922,9 @@ Query Plan ================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |SUBPLAN FILTER | |3 |15 | +|0 |SUBPLAN FILTER | |3 |93 | |1 |├─TABLE FULL SCAN|xy_t2|5 |3 | -|2 |└─TABLE FULL SCAN|xy_t1|3 |3 | +|2 |└─TABLE FULL SCAN|xy_t1|3 |18 | ================================================== Outputs & filters: ------------------------------------- @@ -4069,10 +4069,10 @@ Query Plan ==================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------- -|0 |SORT | |4 |23 | -|1 |└─SUBPLAN FILTER | |4 |22 | +|0 |SORT | |4 |147 | +|1 |└─SUBPLAN FILTER | |4 |146 | |2 | ├─TABLE FULL SCAN|xy_t1|8 |3 | -|3 | └─TABLE FULL SCAN|xy_t2|1 |3 | +|3 | └─TABLE FULL SCAN|xy_t2|1 |18 | ==================================================== Outputs & filters: ------------------------------------- @@ -4216,10 +4216,10 @@ Query Plan ==================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------- -|0 |SORT | |3 |16 | -|1 |└─SUBPLAN FILTER | |3 |16 | +|0 |SORT | |3 |93 | +|1 |└─SUBPLAN FILTER | |3 |92 | |2 | ├─TABLE FULL SCAN|xy_t2|5 |3 | -|3 | └─TABLE FULL SCAN|xy_t1|1 |3 | +|3 | └─TABLE FULL SCAN|xy_t1|1 |18 | ==================================================== Outputs & filters: ------------------------------------- @@ -4315,13 +4315,13 @@ select /*+ use_merge(xy_t1 xy_t2)*/ c1, c2 from xy_t2 where not exists (select 1 +----+------+ EXPLAIN select /*+ use_nl(xy_t1 xy_t2)*/ c1, c2 from xy_t2 where not exists (select 1 from xy_t1 where xy_t1.c1 = xy_t2.c1 and xy_t1.c3 < xy_t2.c3) order by 1,2; Query Plan -======================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------- -|0 |NESTED-LOOP ANTI JOIN | |5 |97 | -|1 |├─TABLE FULL SCAN |xy_t2|5 |3 | -|2 |└─DISTRIBUTED TABLE GET|xy_t1|1 |18 | -======================================================== +======================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------- +|0 |NESTED-LOOP ANTI JOIN | |5 |97 | +|1 |├─TABLE FULL SCAN |xy_t2|5 |3 | +|2 |└─TABLE GET |xy_t1|1 |18 | +======================================================= Outputs & filters: ------------------------------------- 0 - output([xy_t2.c1], [xy_t2.c2]), filter(nil), rowset=16 @@ -4350,9 +4350,9 @@ Query Plan ======================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |SUBPLAN FILTER | |3 |93 | +|0 |SUBPLAN FILTER | |3 |80 | |1 |├─TABLE FULL SCAN |xy_t2|5 |3 | -|2 |└─DISTRIBUTED TABLE GET|xy_t1|1 |18 | +|2 |└─DISTRIBUTED TABLE GET|xy_t1|1 |16 | ======================================================== Outputs & filters: ------------------------------------- @@ -4385,8 +4385,8 @@ Query Plan ======================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |SORT | |4 |6 | -|1 |└─HASH RIGHT ANTI JOIN | |4 |6 | +|0 |SORT | |5 |6 | +|1 |└─HASH RIGHT ANTI JOIN | |5 |6 | |2 | ├─SUBPLAN SCAN |VIEW1|1 |3 | |3 | │ └─TABLE FULL SCAN |xy_t1|1 |3 | |4 | └─TABLE FULL SCAN |xy_t2|5 |3 | @@ -4422,8 +4422,8 @@ Query Plan ====================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------ -|0 |SORT | |4 |7 | -|1 |└─HASH ANTI JOIN | |4 |7 | +|0 |SORT | |5 |7 | +|1 |└─HASH ANTI JOIN | |5 |7 | |2 | ├─TABLE FULL SCAN |xy_t2|5 |3 | |3 | └─SUBPLAN SCAN |VIEW1|1 |3 | |4 | └─TABLE FULL SCAN|xy_t1|1 |3 | @@ -4459,8 +4459,8 @@ Query Plan ====================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------ -|0 |SORT | |4 |7 | -|1 |└─HASH ANTI JOIN | |4 |7 | +|0 |SORT | |5 |7 | +|1 |└─HASH ANTI JOIN | |5 |7 | |2 | ├─TABLE FULL SCAN |xy_t2|5 |3 | |3 | └─SUBPLAN SCAN |VIEW1|1 |3 | |4 | └─TABLE FULL SCAN|xy_t1|1 |3 | @@ -4496,9 +4496,9 @@ Query Plan ======================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |SUBPLAN FILTER | |3 |92 | +|0 |SUBPLAN FILTER | |3 |79 | |1 |├─TABLE FULL SCAN |xy_t2|5 |3 | -|2 |└─DISTRIBUTED TABLE GET|xy_t1|1 |18 | +|2 |└─DISTRIBUTED TABLE GET|xy_t1|1 |16 | ======================================================== Outputs & filters: ------------------------------------- diff --git a/tools/deploy/mysql_test/test_suite/join/r/mysql/join_merge.result b/tools/deploy/mysql_test/test_suite/join/r/mysql/join_merge.result index c75e25c1c5..7b8897a26f 100644 --- a/tools/deploy/mysql_test/test_suite/join/r/mysql/join_merge.result +++ b/tools/deploy/mysql_test/test_suite/join/r/mysql/join_merge.result @@ -288,7 +288,7 @@ Query Plan ===================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ----------------------------------------------------- -|0 |MERGE JOIN | |2 |12 | +|0 |MERGE JOIN | |4 |12 | |1 |├─MERGE JOIN | |6 |8 | |2 |│ ├─SORT | |6 |4 | |3 |│ │ └─TABLE FULL SCAN|aa |6 |3 | @@ -332,7 +332,7 @@ Query Plan ===================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ----------------------------------------------------- -|0 |MERGE JOIN | |2 |12 | +|0 |MERGE JOIN | |4 |12 | |1 |├─MERGE JOIN | |6 |8 | |2 |│ ├─SORT | |6 |4 | |3 |│ │ └─TABLE FULL SCAN|aa |6 |3 | @@ -889,7 +889,7 @@ Query Plan =================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------- -|0 |MERGE JOIN | |2 |50 | +|0 |MERGE JOIN | |4 |51 | |1 |├─MERGE JOIN | |5 |35 | |2 |│ ├─PX COORDINATOR MERGE SORT | |6 |18 | |3 |│ │ └─EXCHANGE OUT DISTR |:EX10000|6 |16 | @@ -960,7 +960,7 @@ Query Plan =================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------- -|0 |MERGE JOIN | |2 |50 | +|0 |MERGE JOIN | |4 |51 | |1 |├─MERGE JOIN | |5 |35 | |2 |│ ├─PX COORDINATOR MERGE SORT | |6 |18 | |3 |│ │ └─EXCHANGE OUT DISTR |:EX10000|6 |16 | @@ -1659,7 +1659,7 @@ Query Plan |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| --------------------------------------------------------- |0 |SORT | |13 |9 | -|1 |└─NESTED-LOOP OUTER JOIN | |13 |4 | +|1 |└─NESTED-LOOP OUTER JOIN | |13 |5 | |2 | ├─TABLE FULL SCAN |t2 |13 |3 | |3 | └─MATERIAL | |5 |4 | |4 | └─TABLE FULL SCAN |t7 |5 |3 | diff --git a/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null.result b/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null.result index 5886b332c1..c0966e645b 100644 --- a/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null.result +++ b/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null.result @@ -50,15 +50,14 @@ Query Plan ================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |MERGE JOIN | |0 |5 | +|0 |HASH JOIN | |0 |5 | |1 |├─TABLE RANGE SCAN|t1 |0 |3 | -|2 |└─TABLE RANGE SCAN|t2 |1 |3 | +|2 |└─TABLE RANGE SCAN|t2 |0 |3 | ================================================== Outputs & filters: ------------------------------------- 0 - output([t1.id], [t2.id]), filter(nil), rowset=16 equal_conds([t2.id = t1.id]), other_conds(nil) - merge_directions([ASC]) 1 - output([t1.id]), filter(nil), rowset=16 access([t1.id]), partitions(p0) is_index_back=false, is_global_index=false, @@ -67,8 +66,8 @@ Outputs & filters: 2 - output([t2.id]), filter(nil), rowset=16 access([t2.id]), partitions(p0) is_index_back=false, is_global_index=false, - range_key([t2.id]), range(200 ; MAX), - range_cond([t2.id > 200]) + range_key([t2.id]), range(MAX ; MIN)always false, + range_cond([t2.id > 200], [t2.id < 200]) select t1.id, t2.id from t1, t2 where t2.id = t1.id and t1.id>200 and t1.id<200; +----+----+ | id | id | @@ -80,15 +79,14 @@ Query Plan ================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |MERGE JOIN | |0 |5 | +|0 |HASH JOIN | |0 |5 | |1 |├─TABLE RANGE SCAN|a |0 |3 | -|2 |└─TABLE RANGE SCAN|b |1 |3 | +|2 |└─TABLE RANGE SCAN|b |0 |3 | ================================================== Outputs & filters: ------------------------------------- 0 - output([a.id], [b.id]), filter(nil), rowset=16 equal_conds([a.id = b.id]), other_conds(nil) - merge_directions([ASC]) 1 - output([a.id]), filter(nil), rowset=16 access([a.id]), partitions(p0) is_index_back=false, is_global_index=false, @@ -97,8 +95,8 @@ Outputs & filters: 2 - output([b.id]), filter(nil), rowset=16 access([b.id]), partitions(p0) is_index_back=false, is_global_index=false, - range_key([b.id]), range(200 ; MAX), - range_cond([b.id > 200]) + range_key([b.id]), range(MAX ; MIN)always false, + range_cond([b.id > 200], [b.id < 200]) select a.id , b.id from t1 a, t2 b where a.id = b.id and a.id>200 and a.id<200; +----+----+ | id | id | diff --git a/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null_joinon.result b/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null_joinon.result index c2f88c6d8f..acc63f71ed 100644 --- a/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null_joinon.result +++ b/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null_joinon.result @@ -52,15 +52,14 @@ Query Plan ================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |MERGE JOIN | |0 |5 | +|0 |HASH JOIN | |0 |5 | |1 |├─TABLE RANGE SCAN|t1 |0 |3 | -|2 |└─TABLE RANGE SCAN|t2 |1 |3 | +|2 |└─TABLE RANGE SCAN|t2 |0 |3 | ================================================== Outputs & filters: ------------------------------------- 0 - output([t1.id], [t2.id]), filter(nil), rowset=16 equal_conds([t2.id = t1.id]), other_conds(nil) - merge_directions([ASC]) 1 - output([t1.id]), filter(nil), rowset=16 access([t1.id]), partitions(p0) is_index_back=false, is_global_index=false, @@ -69,8 +68,8 @@ Outputs & filters: 2 - output([t2.id]), filter(nil), rowset=16 access([t2.id]), partitions(p0) is_index_back=false, is_global_index=false, - range_key([t2.id]), range(200 ; MAX), - range_cond([t2.id > 200]) + range_key([t2.id]), range(MAX ; MIN)always false, + range_cond([t2.id > 200], [t2.id < 200]) select t1.id, t2.id from t1 join t2 on t2.id = t1.id and t1.id>200 and t1.id<200; +----+----+ | id | id | @@ -82,15 +81,14 @@ Query Plan ================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |MERGE JOIN | |0 |5 | +|0 |HASH JOIN | |0 |5 | |1 |├─TABLE RANGE SCAN|a |0 |3 | -|2 |└─TABLE RANGE SCAN|b |1 |3 | +|2 |└─TABLE RANGE SCAN|b |0 |3 | ================================================== Outputs & filters: ------------------------------------- 0 - output([a.id], [b.id]), filter(nil), rowset=16 equal_conds([a.id = b.id]), other_conds(nil) - merge_directions([ASC]) 1 - output([a.id]), filter(nil), rowset=16 access([a.id]), partitions(p0) is_index_back=false, is_global_index=false, @@ -99,8 +97,8 @@ Outputs & filters: 2 - output([b.id]), filter(nil), rowset=16 access([b.id]), partitions(p0) is_index_back=false, is_global_index=false, - range_key([b.id]), range(200 ; MAX), - range_cond([b.id > 200]) + range_key([b.id]), range(MAX ; MIN)always false, + range_cond([b.id > 200], [b.id < 200]) select a.id , b.id from t1 a join t2 b on a.id = b.id and a.id>200 and a.id<200; +----+----+ | id | id | diff --git a/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null_joinon_where.result b/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null_joinon_where.result index 2d3c1c5223..c20fbee1e0 100644 --- a/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null_joinon_where.result +++ b/tools/deploy/mysql_test/test_suite/join/r/mysql/nested_loop_join_right_null_joinon_where.result @@ -52,25 +52,24 @@ Query Plan ================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |MERGE JOIN | |1 |5 | -|1 |├─TABLE RANGE SCAN|t1 |1 |3 | -|2 |└─TABLE RANGE SCAN|t2 |2 |3 | +|0 |HASH JOIN | |0 |5 | +|1 |├─TABLE RANGE SCAN|t1 |0 |3 | +|2 |└─TABLE RANGE SCAN|t2 |0 |3 | ================================================== Outputs & filters: ------------------------------------- 0 - output([t1.id], [t2.id]), filter(nil), rowset=16 equal_conds([t2.id = t1.id]), other_conds(nil) - merge_directions([ASC]) 1 - output([t1.id]), filter(nil), rowset=16 access([t1.id]), partitions(p0) is_index_back=false, is_global_index=false, - range_key([t1.id]), range(200 ; MAX), - range_cond([t1.id > 200]) + range_key([t1.id]), range(MAX ; MIN)always false, + range_cond([t1.id > 200], [t1.id < 200]) 2 - output([t2.id]), filter(nil), rowset=16 access([t2.id]), partitions(p0) is_index_back=false, is_global_index=false, - range_key([t2.id]), range(NULL ; 200), - range_cond([t2.id < 200]) + range_key([t2.id]), range(MAX ; MIN)always false, + range_cond([t2.id < 200], [t2.id > 200]) select t1.id, t2.id from t1 join t2 on t2.id = t1.id where t1.id>200 and t1.id<200; +----+----+ | id | id | @@ -82,25 +81,24 @@ Query Plan ================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |MERGE JOIN | |1 |5 | -|1 |├─TABLE RANGE SCAN|a |1 |3 | -|2 |└─TABLE RANGE SCAN|b |2 |3 | +|0 |HASH JOIN | |0 |5 | +|1 |├─TABLE RANGE SCAN|a |0 |3 | +|2 |└─TABLE RANGE SCAN|b |0 |3 | ================================================== Outputs & filters: ------------------------------------- 0 - output([a.id], [b.id]), filter(nil), rowset=16 equal_conds([a.id = b.id]), other_conds(nil) - merge_directions([ASC]) 1 - output([a.id]), filter(nil), rowset=16 access([a.id]), partitions(p0) is_index_back=false, is_global_index=false, - range_key([a.id]), range(200 ; MAX), - range_cond([a.id > 200]) + range_key([a.id]), range(MAX ; MIN)always false, + range_cond([a.id > 200], [a.id < 200]) 2 - output([b.id]), filter(nil), rowset=16 access([b.id]), partitions(p0) is_index_back=false, is_global_index=false, - range_key([b.id]), range(NULL ; 200), - range_cond([b.id < 200]) + range_key([b.id]), range(MAX ; MIN)always false, + range_cond([b.id < 200], [b.id > 200]) select a.id , b.id from t1 a join t2 b on a.id = b.id where a.id>200 and a.id<200; +----+----+ | id | id | diff --git a/tools/deploy/mysql_test/test_suite/pdml/r/mysql/pdml_update_part_global_index.result b/tools/deploy/mysql_test/test_suite/pdml/r/mysql/pdml_update_part_global_index.result index 27dd24df3c..ba33a1cdb7 100644 --- a/tools/deploy/mysql_test/test_suite/pdml/r/mysql/pdml_update_part_global_index.result +++ b/tools/deploy/mysql_test/test_suite/pdml/r/mysql/pdml_update_part_global_index.result @@ -39,10 +39,10 @@ Outputs & filters: dop=3 2 - output(nil), filter(nil) columns([{t1: ({t1_idx1: (t1.c2, t1.c1)})}]), partitions(p[0-3]), - column_values([column_conv(INT,PS:(11,0),NULL,cast(3, INT(-1, 0)))], [t1.c1]) + column_values([column_conv(INT,PS:(11,0),NULL,3)], [t1.c1]) 3 - output([PARTITION_ID], [t1.c1]), filter(nil), rowset=16 4 - output([PARTITION_ID], [t1.c1]), filter(nil), rowset=16 - (#keys=1, [column_conv(INT,PS:(11,0),NULL,cast(3, INT(-1, 0)))]), dop=3 + (#keys=1, [column_conv(INT,PS:(11,0),NULL,3)]), dop=3 5 - output([t1.c1]), filter(nil), rowset=16 6 - output([t1.c1]), filter(nil) table_columns([{t1: ({t1_idx1: (t1.c2, t1.c1)})}]), with_barrier @@ -52,7 +52,7 @@ Outputs & filters: 9 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 10 - output([t1.c1], [t1.c2]), filter(nil) table_columns([{t1: ({t1: (t1.c1, t1.c2, t1.c3)})}]), - update([t1.c2=column_conv(INT,PS:(11,0),NULL,cast(3, INT(-1, 0)))]) + update([t1.c2=column_conv(INT,PS:(11,0),NULL,3)]) 11 - output([t1.c1], [t1.c2], [PARTITION_ID], [t1.c3]), filter(nil), rowset=16 12 - output([t1.c1], [t1.c2], [PARTITION_ID], [t1.c3]), filter(nil), rowset=16 (#keys=1, [t1.c1]), dop=3 @@ -126,7 +126,7 @@ Outputs & filters: 9 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c1], [pindex.c2]), filter(nil), rowset=16 10 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c1], [pindex.c2]), filter(nil) table_columns([{pindex: ({pindex: (pindex.c1, pindex.c2, pindex.c3)})}]), - update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,cast(5, INT(-1, 0)))]) + update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,5)]) 11 - output([pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 12 - output([pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 (#keys=1, [pindex.c1]), dop=3 @@ -203,7 +203,7 @@ Outputs & filters: 9 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c1], [pindex.c2]), filter(nil), rowset=16 10 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c1], [pindex.c2]), filter(nil) table_columns([{pindex: ({pindex: (pindex.c1, pindex.c2, pindex.c3)})}]), - update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,cast(5, INT(-1, 0)))]) + update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,5)]) 11 - output([pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 12 - output([pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 (#keys=1, [pindex.c1]), dop=3 @@ -278,7 +278,7 @@ Outputs & filters: 9 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c1], [pindex.c2]), filter(nil), rowset=16 10 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c1], [pindex.c2]), filter(nil) table_columns([{pindex: ({pindex: (pindex.c1, pindex.c2, pindex.c3)})}]), - update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,cast(5, INT(-1, 0)))]) + update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,5)]) 11 - output([pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 12 - output([pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 (#keys=1, [pindex.c1]), dop=3 @@ -342,7 +342,7 @@ Outputs & filters: 9 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.__pk_increment], [pindex.c1], [pindex.c2]), filter(nil), rowset=16 10 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.__pk_increment], [pindex.c1], [pindex.c2]), filter(nil) table_columns([{pindex: ({pindex: (pindex.__pk_increment, pindex.c1, pindex.c2, pindex.c3)})}]), - update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,cast(5, INT(-1, 0)))]) + update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,5)]) 11 - output([pindex.__pk_increment], [pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 12 - output([pindex.__pk_increment], [pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 (#keys=1, [pindex.c1]), dop=3 @@ -419,7 +419,7 @@ Outputs & filters: 9 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.__pk_increment], [pindex.c1], [pindex.c2]), filter(nil), rowset=16 10 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.__pk_increment], [pindex.c1], [pindex.c2]), filter(nil) table_columns([{pindex: ({pindex: (pindex.__pk_increment, pindex.c1, pindex.c2, pindex.c3)})}]), - update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,cast(5, INT(-1, 0)))]) + update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,5)]) 11 - output([pindex.__pk_increment], [pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 12 - output([pindex.__pk_increment], [pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 (#keys=1, [pindex.c1]), dop=3 @@ -494,7 +494,7 @@ Outputs & filters: 9 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.__pk_increment], [pindex.c1], [pindex.c2]), filter(nil), rowset=16 10 - output([column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.__pk_increment], [pindex.c1], [pindex.c2]), filter(nil) table_columns([{pindex: ({pindex: (pindex.__pk_increment, pindex.c1, pindex.c2, pindex.c3)})}]), - update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,cast(5, INT(-1, 0)))]) + update([pindex.c2=column_conv(INT,PS:(11,0),NULL,pindex.c3)], [pindex.c3=column_conv(INT,PS:(11,0),NULL,5)]) 11 - output([pindex.__pk_increment], [pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 12 - output([pindex.__pk_increment], [pindex.c1], [pindex.c2], [PARTITION_ID], [pindex.c3]), filter(nil), rowset=16 (#keys=1, [pindex.c1]), dop=3 @@ -535,10 +535,10 @@ Outputs & filters: dop=2 2 - output(nil), filter(nil) columns([{pindex: ({idx_b: (pindex.b, pindex.a)})}]), partitions(p0), - column_values([column_conv(INT,PS:(11,0),NULL,cast(2, INT(-1, 0)))], [pindex.a]) + column_values([column_conv(INT,PS:(11,0),NULL,2)], [pindex.a]) 3 - output([pindex.a]), filter(nil), rowset=16 4 - output([pindex.a]), filter(nil), rowset=16 - (#keys=1, [column_conv(INT,PS:(11,0),NULL,cast(2, INT(-1, 0)))]), dop=2 + (#keys=1, [column_conv(INT,PS:(11,0),NULL,2)]), dop=2 5 - output([pindex.a]), filter(nil), rowset=16 6 - output([pindex.a]), filter(nil) table_columns([{pindex: ({idx_b: (pindex.b, pindex.a)})}]), with_barrier @@ -548,7 +548,7 @@ Outputs & filters: 9 - output([pindex.a], [pindex.b]), filter(nil), rowset=16 10 - output([pindex.a], [pindex.b]), filter(nil) table_columns([{pindex: ({pindex: (pindex.a, pindex.b)})}]), - update([pindex.b=column_conv(INT,PS:(11,0),NULL,cast(2, INT(-1, 0)))]) + update([pindex.b=column_conv(INT,PS:(11,0),NULL,2)]) 11 - output([pindex.a], [pindex.b], [PARTITION_ID]), filter(nil), rowset=16 12 - output([pindex.a], [pindex.b], [PARTITION_ID]), filter(nil), rowset=16 (#keys=1, [pindex.a]), dop=2 diff --git a/tools/deploy/mysql_test/test_suite/px/r/mysql/add_material.result b/tools/deploy/mysql_test/test_suite/px/r/mysql/add_material.result index 4b9281828f..1469df5466 100644 --- a/tools/deploy/mysql_test/test_suite/px/r/mysql/add_material.result +++ b/tools/deploy/mysql_test/test_suite/px/r/mysql/add_material.result @@ -11,20 +11,19 @@ select /*+ USE_PX parallel(3) */* from (select c1,count(c2) c2 from t1 group by c1)c) a join (select c1,count(*) c2 from t2 group by c1)b on a.c1=b.c1 ; Query Plan -================================================= -|ID|OPERATOR |NAME | -------------------------------------------------- -|0 |PX COORDINATOR | | -|1 |└─EXCHANGE OUT DISTR |:EX10001| -|2 | └─HASH JOIN | | -|3 | ├─PART JOIN FILTER CREATE |:RF0000 | -|4 | │ └─PX PARTITION ITERATOR | | -|5 | │ └─TABLE FULL SCAN |t2 | -|6 | └─EXCHANGE IN DISTR | | -|7 | └─EXCHANGE OUT DISTR (PKEY) |:EX10000| -|8 | └─PX BLOCK HASH JOIN-FILTER|:RF0000 | -|9 | └─TABLE FULL SCAN |t1 | -================================================= +=============================================== +|ID|OPERATOR |NAME | +----------------------------------------------- +|0 |PX COORDINATOR | | +|1 |└─EXCHANGE OUT DISTR |:EX10001| +|2 | └─HASH JOIN | | +|3 | ├─PX PARTITION ITERATOR | | +|4 | │ └─TABLE FULL SCAN |t1 | +|5 | └─EXCHANGE IN DISTR | | +|6 | └─EXCHANGE OUT DISTR (PKEY)|:EX10000| +|7 | └─PX BLOCK ITERATOR | | +|8 | └─TABLE FULL SCAN |t2 | +=============================================== Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(t1.c1, 1, t2.c1, cast(1, BIGINT(20, 0)))]), filter(nil), rowset=16 @@ -32,22 +31,20 @@ Outputs & filters: dop=3 2 - output([t1.c1], [t2.c1]), filter(nil), rowset=16 equal_conds([t1.c1 = t2.c1]), other_conds(nil) - 3 - output([t2.c1]), filter(nil), rowset=16 - RF_TYPE(bloom), RF_EXPR[calc_tablet_id(t2.c1)] - 4 - output([t2.c1]), filter(nil), rowset=16 + 3 - output([t1.c1]), filter(nil), rowset=16 affinitize - 5 - output([t2.c1]), filter(nil), rowset=16 - access([t2.c1]), partitions(p[0-5]) - is_index_back=false, is_global_index=false, - range_key([t2.c1]), range(MIN ; MAX)always true - 6 - output([t1.c1]), filter(nil), rowset=16 - 7 - output([t1.c1]), filter(nil), rowset=16 - (#keys=1, [t1.c1]), dop=3 - 8 - output([t1.c1]), filter(nil), rowset=16 - 9 - output([t1.c1]), filter(nil), rowset=16 + 4 - output([t1.c1]), filter(nil), rowset=16 access([t1.c1]), partitions(p[0-9]) is_index_back=false, is_global_index=false, range_key([t1.c1]), range(MIN ; MAX)always true + 5 - output([t2.c1]), filter(nil), rowset=16 + 6 - output([t2.c1]), filter(nil), rowset=16 + (#keys=1, [t2.c1]), dop=3 + 7 - output([t2.c1]), filter(nil), rowset=16 + 8 - output([t2.c1]), filter(nil), rowset=16 + access([t2.c1]), partitions(p[0-5]) + is_index_back=false, is_global_index=false, + range_key([t2.c1]), range(MIN ; MAX)always true select /*+ USE_PX parallel(3) */* from (select c1,count(*) over(partition by c1) c2 from (select c1,count(c2) c2 from t1 group by c1)c) a join @@ -100,8 +97,8 @@ Outputs & filters: equal_conds([a.c1 = b.c1]), other_conds(nil) 7 - output([b.c1]), filter(nil), rowset=16 RF_TYPE(bloom), RF_EXPR[calc_tablet_id(b.c1)] - 8 - output([b.c1]), filter(nil), rowset=16 - 9 - output([b.c1]), filter(nil), rowset=16 + 8 - output([b.c1], [calc_tablet_id(b.c1)]), filter(nil), rowset=16 + 9 - output([b.c1], [calc_tablet_id(b.c1)]), filter(nil), rowset=16 (#keys=1, [b.c1]), dop=3 10 - output([b.c1]), filter(nil), rowset=16 11 - output([b.c1]), filter(nil), rowset=16 diff --git a/tools/deploy/mysql_test/test_suite/px/r/mysql/alloc_material_for_producer_consumer_schedule_mode.result b/tools/deploy/mysql_test/test_suite/px/r/mysql/alloc_material_for_producer_consumer_schedule_mode.result index 0bd6dc8281..58401ae2f6 100644 --- a/tools/deploy/mysql_test/test_suite/px/r/mysql/alloc_material_for_producer_consumer_schedule_mode.result +++ b/tools/deploy/mysql_test/test_suite/px/r/mysql/alloc_material_for_producer_consumer_schedule_mode.result @@ -74,7 +74,7 @@ Query Plan |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------------------- |0 |PX COORDINATOR | |1 |6 | -|1 |└─EXCHANGE OUT DISTR |:EX10003|1 |5 | +|1 |└─EXCHANGE OUT DISTR |:EX10003|1 |6 | |2 | └─HASH GROUP BY | |1 |5 | |3 | └─EXCHANGE IN DISTR | |1 |5 | |4 | └─EXCHANGE OUT DISTR (HASH) |:EX10002|1 |5 | @@ -140,8 +140,8 @@ Query Plan =========================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------------- -|0 |PX COORDINATOR | |1 |6 | -|1 |└─EXCHANGE OUT DISTR |:EX10002|1 |5 | +|0 |PX COORDINATOR | |1 |7 | +|1 |└─EXCHANGE OUT DISTR |:EX10002|1 |6 | |2 | └─MERGE GROUP BY | |1 |4 | |3 | └─PARTITION SORT | |1 |4 | |4 | └─MERGE JOIN | |1 |4 | @@ -150,8 +150,8 @@ Query Plan |7 | │ └─EXCHANGE OUT DISTR (HASH)|:EX10000|1 |2 | |8 | │ └─PX BLOCK ITERATOR | |1 |2 | |9 | │ └─TABLE FULL SCAN |t1 |1 |2 | -|10| └─SORT | |1 |2 | -|11| └─EXCHANGE IN DISTR | |1 |2 | +|10| └─SORT | |1 |3 | +|11| └─EXCHANGE IN DISTR | |1 |3 | |12| └─EXCHANGE OUT DISTR (HASH)|:EX10001|1 |2 | |13| └─PX BLOCK ITERATOR | |1 |2 | |14| └─TABLE FULL SCAN |b |1 |2 | diff --git a/tools/deploy/mysql_test/test_suite/px/r/mysql/join_hash.result b/tools/deploy/mysql_test/test_suite/px/r/mysql/join_hash.result index ff58a9fd54..7001f95827 100644 --- a/tools/deploy/mysql_test/test_suite/px/r/mysql/join_hash.result +++ b/tools/deploy/mysql_test/test_suite/px/r/mysql/join_hash.result @@ -135,75 +135,51 @@ sid subject score tid name subject 64 MA 87 2 Mr Wang MA explain select /*+ USE_PX parallel(2) */ teacher.name, teacher.subject, avg(score) from score, teacher where teacher.subject = score.subject group by teacher.name, teacher.subject; Query Plan -=============================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------------------------- -|0 |PX COORDINATOR | |2 |28 | -|1 |└─EXCHANGE OUT DISTR |:EX10003|2 |26 | -|2 | └─HASH JOIN | |2 |23 | -|3 | ├─JOIN FILTER CREATE |:RF0000 |2 |13 | -|4 | │ └─EXCHANGE IN DISTR | |2 |13 | -|5 | │ └─EXCHANGE OUT DISTR (HASH) |:EX10001|2 |13 | -|6 | │ └─SUBPLAN SCAN |VIEW2 |2 |11 | -|7 | │ └─HASH GROUP BY | |2 |11 | -|8 | │ └─EXCHANGE IN DISTR | |2 |11 | -|9 | │ └─EXCHANGE OUT DISTR (HASH)|:EX10000|2 |10 | -|10| │ └─HASH GROUP BY | |2 |9 | -|11| │ └─PX BLOCK ITERATOR | |2 |9 | -|12| │ └─TABLE FULL SCAN |teacher |2 |9 | -|13| └─SUBPLAN SCAN |VIEW1 |3 |10 | -|14| └─HASH GROUP BY | |3 |10 | -|15| └─EXCHANGE IN DISTR | |3 |10 | -|16| └─EXCHANGE OUT DISTR (HASH) |:EX10002|3 |9 | -|17| └─HASH GROUP BY | |3 |7 | -|18| └─JOIN FILTER USE |:RF0000 |3 |7 | -|19| └─PX BLOCK ITERATOR | |3 |7 | -|20| └─TABLE FULL SCAN |score |3 |7 | -=============================================================================== +================================================================================ +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +-------------------------------------------------------------------------------- +|0 |PX COORDINATOR | |2 |33 | +|1 |└─EXCHANGE OUT DISTR |:EX10002|2 |32 | +|2 | └─HASH GROUP BY | |2 |30 | +|3 | └─EXCHANGE IN DISTR | |4 |29 | +|4 | └─EXCHANGE OUT DISTR (HASH) |:EX10001|4 |28 | +|5 | └─HASH GROUP BY | |4 |24 | +|6 | └─SHARED HASH JOIN | |28 |22 | +|7 | ├─EXCHANGE IN DISTR | |2 |10 | +|8 | │ └─EXCHANGE OUT DISTR (BC2HOST)|:EX10000|2 |10 | +|9 | │ └─PX BLOCK ITERATOR | |2 |9 | +|10| │ └─TABLE FULL SCAN |teacher |2 |9 | +|11| └─PX BLOCK ITERATOR | |28 |8 | +|12| └─TABLE FULL SCAN |score |28 |8 | +================================================================================ Outputs & filters: ------------------------------------- - 0 - output([INTERNAL_FUNCTION(VIEW2.teacher.name, VIEW2.teacher.subject, cast(cast(cast(cast(VIEW1.T_FUN_SUM(score.score) * cast(VIEW2.T_FUN_COUNT(*), - DECIMAL_INT(20, 0)), DECIMAL_INT(75, 0)), DECIMAL_INT(33, 0)), DECIMAL(33, 0)) / cast(cast(VIEW1.T_FUN_COUNT(score.score) * VIEW2.T_FUN_COUNT(*), BIGINT(20, - 0)), DECIMAL(20, 0)), DECIMAL(15, 4)))]), filter(nil), rowset=16 - 1 - output([INTERNAL_FUNCTION(VIEW2.teacher.name, VIEW2.teacher.subject, cast(cast(cast(cast(VIEW1.T_FUN_SUM(score.score) * cast(VIEW2.T_FUN_COUNT(*), - DECIMAL_INT(20, 0)), DECIMAL_INT(75, 0)), DECIMAL_INT(33, 0)), DECIMAL(33, 0)) / cast(cast(VIEW1.T_FUN_COUNT(score.score) * VIEW2.T_FUN_COUNT(*), BIGINT(20, - 0)), DECIMAL(20, 0)), DECIMAL(15, 4)))]), filter(nil), rowset=16 + 0 - output([INTERNAL_FUNCTION(teacher.name, teacher.subject, cast(cast(T_FUN_SUM(T_FUN_SUM(score.score)), DECIMAL(33, 0)) / cast(T_FUN_COUNT_SUM(T_FUN_COUNT(score.score)), + DECIMAL(20, 0)), DECIMAL(15, 4)))]), filter(nil), rowset=256 + 1 - output([INTERNAL_FUNCTION(teacher.name, teacher.subject, cast(cast(T_FUN_SUM(T_FUN_SUM(score.score)), DECIMAL(33, 0)) / cast(T_FUN_COUNT_SUM(T_FUN_COUNT(score.score)), + DECIMAL(20, 0)), DECIMAL(15, 4)))]), filter(nil), rowset=256 dop=2 - 2 - output([VIEW2.T_FUN_COUNT(*)], [VIEW2.teacher.subject], [VIEW2.teacher.name], [VIEW1.T_FUN_SUM(score.score)], [VIEW1.T_FUN_COUNT(score.score)]), filter(nil), rowset=16 - equal_conds([VIEW2.teacher.subject = VIEW1.score.subject]), other_conds(nil) - 3 - output([VIEW2.T_FUN_COUNT(*)], [VIEW2.teacher.subject], [VIEW2.teacher.name]), filter(nil), rowset=16 - RF_TYPE(in, range, bloom), RF_EXPR[VIEW2.teacher.subject] - 4 - output([VIEW2.T_FUN_COUNT(*)], [VIEW2.teacher.subject], [VIEW2.teacher.name]), filter(nil), rowset=16 - 5 - output([VIEW2.T_FUN_COUNT(*)], [VIEW2.teacher.subject], [VIEW2.teacher.name]), filter(nil), rowset=16 - (#keys=1, [VIEW2.teacher.subject]), dop=2 - 6 - output([VIEW2.teacher.subject], [VIEW2.teacher.name], [VIEW2.T_FUN_COUNT(*)]), filter(nil), rowset=16 - access([VIEW2.teacher.subject], [VIEW2.teacher.name], [VIEW2.T_FUN_COUNT(*)]) - 7 - output([teacher.subject], [teacher.name], [T_FUN_COUNT_SUM(T_FUN_COUNT(*))]), filter(nil), rowset=16 - group([teacher.subject], [teacher.name]), agg_func([T_FUN_COUNT_SUM(T_FUN_COUNT(*))]) - 8 - output([teacher.subject], [teacher.name], [T_FUN_COUNT(*)]), filter(nil), rowset=16 - 9 - output([teacher.subject], [teacher.name], [T_FUN_COUNT(*)]), filter(nil), rowset=16 - (#keys=2, [teacher.subject], [teacher.name]), dop=2 - 10 - output([teacher.subject], [teacher.name], [T_FUN_COUNT(*)]), filter(nil), rowset=16 - group([teacher.subject], [teacher.name]), agg_func([T_FUN_COUNT(*)]) - 11 - output([teacher.subject], [teacher.name]), filter(nil), rowset=16 - 12 - output([teacher.subject], [teacher.name]), filter(nil), rowset=16 + 2 - output([teacher.name], [teacher.subject], [T_FUN_SUM(T_FUN_SUM(score.score))], [T_FUN_COUNT_SUM(T_FUN_COUNT(score.score))]), filter(nil), rowset=256 + group([teacher.name], [teacher.subject]), agg_func([T_FUN_SUM(T_FUN_SUM(score.score))], [T_FUN_COUNT_SUM(T_FUN_COUNT(score.score))]) + 3 - output([teacher.name], [teacher.subject], [T_FUN_SUM(score.score)], [T_FUN_COUNT(score.score)]), filter(nil), rowset=256 + 4 - output([teacher.name], [teacher.subject], [T_FUN_SUM(score.score)], [T_FUN_COUNT(score.score)]), filter(nil), rowset=256 + (#keys=2, [teacher.name], [teacher.subject]), dop=2 + 5 - output([teacher.name], [teacher.subject], [T_FUN_SUM(score.score)], [T_FUN_COUNT(score.score)]), filter(nil), rowset=256 + group([teacher.name], [teacher.subject]), agg_func([T_FUN_SUM(score.score)], [T_FUN_COUNT(score.score)]) + 6 - output([score.score], [teacher.name], [teacher.subject]), filter(nil), rowset=256 + equal_conds([teacher.subject = score.subject]), other_conds(nil) + 7 - output([teacher.name], [teacher.subject]), filter(nil), rowset=256 + 8 - output([teacher.name], [teacher.subject]), filter(nil), rowset=256 + dop=2 + 9 - output([teacher.subject], [teacher.name]), filter(nil), rowset=256 + 10 - output([teacher.subject], [teacher.name]), filter(nil), rowset=256 access([teacher.subject], [teacher.name]), partitions(p[0-7]) is_index_back=false, is_global_index=false, range_key([teacher.tid]), range(MIN ; MAX)always true - 13 - output([VIEW1.score.subject], [VIEW1.T_FUN_SUM(score.score)], [VIEW1.T_FUN_COUNT(score.score)]), filter(nil), rowset=16 - access([VIEW1.score.subject], [VIEW1.T_FUN_SUM(score.score)], [VIEW1.T_FUN_COUNT(score.score)]) - 14 - output([score.subject], [T_FUN_SUM(T_FUN_SUM(score.score))], [T_FUN_COUNT_SUM(T_FUN_COUNT(score.score))]), filter(nil), rowset=16 - group([score.subject]), agg_func([T_FUN_SUM(T_FUN_SUM(score.score))], [T_FUN_COUNT_SUM(T_FUN_COUNT(score.score))]) - 15 - output([score.subject], [T_FUN_SUM(score.score)], [T_FUN_COUNT(score.score)]), filter(nil), rowset=16 - 16 - output([score.subject], [T_FUN_SUM(score.score)], [T_FUN_COUNT(score.score)]), filter(nil), rowset=16 - (#keys=1, [score.subject]), dop=2 - 17 - output([score.subject], [T_FUN_SUM(score.score)], [T_FUN_COUNT(score.score)]), filter(nil), rowset=16 - group([score.subject]), agg_func([T_FUN_SUM(score.score)], [T_FUN_COUNT(score.score)]) - 18 - output([score.subject], [score.score]), filter(nil), rowset=16 - 19 - output([score.subject], [score.score]), filter(nil), rowset=16 - 20 - output([score.subject], [score.score]), filter([RF_IN_FILTER(score.subject)], [RF_RANGE_FILTER(score.subject)], [RF_BLOOM_FILTER(score.subject)]), rowset=16 + 11 - output([score.subject], [score.score]), filter(nil), rowset=256 + 12 - output([score.subject], [score.score]), filter(nil), rowset=256 access([score.subject], [score.score]), partitions(p[0-5]) - is_index_back=false, is_global_index=false, filter_before_indexback[false,false,false], + is_index_back=false, is_global_index=false, range_key([score.sid], [score.subject]), range(MIN,MIN ; MAX,MAX)always true select /*+ USE_PX parallel(2) */ teacher.name, teacher.subject, avg(score) from score, teacher where teacher.subject = score.subject group by teacher.name, teacher.subject; name subject avg(score) diff --git a/tools/deploy/mysql_test/test_suite/px/r/mysql/unmatched_distribution.result b/tools/deploy/mysql_test/test_suite/px/r/mysql/unmatched_distribution.result index 1fa0f1e289..05ca119871 100644 --- a/tools/deploy/mysql_test/test_suite/px/r/mysql/unmatched_distribution.result +++ b/tools/deploy/mysql_test/test_suite/px/r/mysql/unmatched_distribution.result @@ -65,13 +65,12 @@ Query Plan |0 |PX COORDINATOR | |3 |8 | |1 |└─EXCHANGE OUT DISTR |:EX10001|3 |6 | |2 | └─HASH OUTER JOIN | |3 |4 | -|3 | ├─PART JOIN FILTER CREATE |:RF0000 |3 |1 | -|4 | │ └─PX BLOCK ITERATOR | |3 |1 | -|5 | │ └─TABLE FULL SCAN |t1 |3 |1 | -|6 | └─EXCHANGE IN DISTR | |2 |3 | -|7 | └─EXCHANGE OUT DISTR (BROADCAST)|:EX10000|2 |2 | -|8 | └─PX BLOCK HASH JOIN-FILTER |:RF0000 |2 |2 | -|9 | └─TABLE FULL SCAN |t2 |2 |2 | +|3 | ├─PX BLOCK ITERATOR | |3 |1 | +|4 | │ └─TABLE FULL SCAN |t1 |3 |1 | +|5 | └─EXCHANGE IN DISTR | |2 |3 | +|6 | └─EXCHANGE OUT DISTR (BROADCAST)|:EX10000|2 |2 | +|7 | └─PX BLOCK ITERATOR | |2 |2 | +|8 | └─TABLE FULL SCAN |t2 |2 |2 | ========================================================================== Outputs & filters: ------------------------------------- @@ -80,18 +79,16 @@ Outputs & filters: dop=4 2 - output([t1.c2], [t2.c2], [t1.c1], [t1.c3], [t2.c1], [t2.c3]), filter(nil), rowset=16 equal_conds([t1.c2 = t2.c2]), other_conds(nil) - 3 - output([t1.c2], [t1.c1], [t1.c3]), filter(nil), rowset=16 - RF_TYPE(bloom), RF_EXPR[calc_tablet_id(t1.c2, t1.c2)] + 3 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 4 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 - 5 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 access([t1.c1], [t1.c2], [t1.c3]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t1.c1], [t1.c2], [t1.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true + 5 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 6 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 - 7 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 dop=4 + 7 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 8 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - 9 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 access([t2.c1], [t2.c2], [t2.c3]), partitions(p0sp[0-1]) is_index_back=false, is_global_index=false, range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true @@ -111,13 +108,12 @@ Query Plan |0 |PX COORDINATOR | |3 |8 | |1 |└─EXCHANGE OUT DISTR |:EX10001|3 |6 | |2 | └─HASH OUTER JOIN | |3 |4 | -|3 | ├─PART JOIN FILTER CREATE |:RF0000 |3 |1 | -|4 | │ └─PX BLOCK ITERATOR | |3 |1 | -|5 | │ └─TABLE FULL SCAN |t1 |3 |1 | -|6 | └─EXCHANGE IN DISTR | |2 |3 | -|7 | └─EXCHANGE OUT DISTR (BROADCAST)|:EX10000|2 |2 | -|8 | └─PX BLOCK HASH JOIN-FILTER |:RF0000 |2 |2 | -|9 | └─TABLE FULL SCAN |t2 |2 |2 | +|3 | ├─PX BLOCK ITERATOR | |3 |1 | +|4 | │ └─TABLE FULL SCAN |t1 |3 |1 | +|5 | └─EXCHANGE IN DISTR | |2 |3 | +|6 | └─EXCHANGE OUT DISTR (BROADCAST)|:EX10000|2 |2 | +|7 | └─PX BLOCK ITERATOR | |2 |2 | +|8 | └─TABLE FULL SCAN |t2 |2 |2 | ========================================================================== Outputs & filters: ------------------------------------- @@ -126,18 +122,16 @@ Outputs & filters: dop=4 2 - output([t1.c2], [t2.c2], [t1.c1], [t1.c3], [t2.c1], [t2.c3]), filter(nil), rowset=16 equal_conds([t1.c2 = t2.c2]), other_conds(nil) - 3 - output([t1.c2], [t1.c1], [t1.c3]), filter(nil), rowset=16 - RF_TYPE(bloom), RF_EXPR[calc_tablet_id(t1.c2, t1.c2)] + 3 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 4 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 - 5 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 access([t1.c1], [t1.c2], [t1.c3]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t1.c1], [t1.c2], [t1.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true + 5 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 6 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 - 7 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 dop=4 + 7 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 8 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - 9 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 access([t2.c1], [t2.c2], [t2.c3]), partitions(p0sp[0-1]) is_index_back=false, is_global_index=false, range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true @@ -158,13 +152,12 @@ Query Plan |0 |PX COORDINATOR | |3 |8 | |1 |└─EXCHANGE OUT DISTR |:EX10001|3 |6 | |2 | └─HASH OUTER JOIN | |3 |4 | -|3 | ├─PART JOIN FILTER CREATE |:RF0000 |3 |1 | -|4 | │ └─PX BLOCK ITERATOR | |3 |1 | -|5 | │ └─TABLE FULL SCAN |t1 |3 |1 | -|6 | └─EXCHANGE IN DISTR | |2 |3 | -|7 | └─EXCHANGE OUT DISTR (BROADCAST)|:EX10000|2 |2 | -|8 | └─PX BLOCK HASH JOIN-FILTER |:RF0000 |2 |2 | -|9 | └─TABLE FULL SCAN |t2 |2 |2 | +|3 | ├─PX BLOCK ITERATOR | |3 |1 | +|4 | │ └─TABLE FULL SCAN |t1 |3 |1 | +|5 | └─EXCHANGE IN DISTR | |2 |3 | +|6 | └─EXCHANGE OUT DISTR (BROADCAST)|:EX10000|2 |2 | +|7 | └─PX BLOCK ITERATOR | |2 |2 | +|8 | └─TABLE FULL SCAN |t2 |2 |2 | ========================================================================== Outputs & filters: ------------------------------------- @@ -173,18 +166,16 @@ Outputs & filters: dop=4 2 - output([t1.c2], [t2.c2], [t1.c1], [t1.c3], [t2.c1], [t2.c3]), filter(nil), rowset=16 equal_conds([t1.c2 = t2.c2]), other_conds(nil) - 3 - output([t1.c2], [t1.c1], [t1.c3]), filter(nil), rowset=16 - RF_TYPE(bloom), RF_EXPR[calc_tablet_id(t1.c2, t1.c2)] + 3 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 4 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 - 5 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 access([t1.c1], [t1.c2], [t1.c3]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t1.c1], [t1.c2], [t1.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true + 5 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 6 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 - 7 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 dop=4 + 7 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 8 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - 9 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 access([t2.c1], [t2.c2], [t2.c3]), partitions(p0sp[0-1]) is_index_back=false, is_global_index=false, range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true @@ -204,13 +195,12 @@ Query Plan |0 |PX COORDINATOR | |3 |8 | |1 |└─EXCHANGE OUT DISTR |:EX10001|3 |6 | |2 | └─HASH OUTER JOIN | |3 |4 | -|3 | ├─PART JOIN FILTER CREATE |:RF0000 |3 |1 | -|4 | │ └─PX BLOCK ITERATOR | |3 |1 | -|5 | │ └─TABLE FULL SCAN |t1 |3 |1 | -|6 | └─EXCHANGE IN DISTR | |2 |3 | -|7 | └─EXCHANGE OUT DISTR (BROADCAST)|:EX10000|2 |2 | -|8 | └─PX BLOCK HASH JOIN-FILTER |:RF0000 |2 |2 | -|9 | └─TABLE FULL SCAN |t2 |2 |2 | +|3 | ├─PX BLOCK ITERATOR | |3 |1 | +|4 | │ └─TABLE FULL SCAN |t1 |3 |1 | +|5 | └─EXCHANGE IN DISTR | |2 |3 | +|6 | └─EXCHANGE OUT DISTR (BROADCAST)|:EX10000|2 |2 | +|7 | └─PX BLOCK ITERATOR | |2 |2 | +|8 | └─TABLE FULL SCAN |t2 |2 |2 | ========================================================================== Outputs & filters: ------------------------------------- @@ -219,18 +209,16 @@ Outputs & filters: dop=4 2 - output([t1.c2], [t2.c2], [t1.c1], [t1.c3], [t2.c1], [t2.c3]), filter(nil), rowset=16 equal_conds([t1.c2 = t2.c2]), other_conds(nil) - 3 - output([t1.c2], [t1.c1], [t1.c3]), filter(nil), rowset=16 - RF_TYPE(bloom), RF_EXPR[calc_tablet_id(t1.c2, t1.c2)] + 3 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 4 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 - 5 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 access([t1.c1], [t1.c2], [t1.c3]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t1.c1], [t1.c2], [t1.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true + 5 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 6 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 - 7 - output([t2.c2], [t2.c1], [t2.c3]), filter(nil), rowset=16 dop=4 + 7 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 8 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 - 9 - output([t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 access([t2.c1], [t2.c2], [t2.c3]), partitions(p0sp[0-1]) is_index_back=false, is_global_index=false, range_key([t2.c1], [t2.c2], [t2.c3]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true diff --git a/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_basic_mysql.result b/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_basic_mysql.result index 5befe8082f..e82e3d6a8a 100644 --- a/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_basic_mysql.result +++ b/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_basic_mysql.result @@ -627,7 +627,7 @@ Outputs & filters: access([t1.b], [t1.a], [t1.c]), partitions(p0) is_index_back=false, is_global_index=false, filter_before_indexback[false,false], range_key([t1.b], [t1.c], [t1.a], [t1.pk1]), range(100,100,MAX,MAX ; 100,MAX,100,MIN), - range_cond([t1.b = 100], [t1.c > 100], [t1.c > 0]) + range_cond([t1.b = 100], [t1.c > 100]) explain select a, b, c from t1 where b = 100 and a > 0 and a < 100 and c = 200; Query Plan ========================================================= @@ -1239,8 +1239,8 @@ Query Plan ============================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------- -|0 |HASH GROUP BY | |0 |3 | -|1 |└─NESTED-LOOP JOIN | |0 |3 | +|0 |MERGE GROUP BY | |1 |3 | +|1 |└─NESTED-LOOP JOIN | |1 |3 | |2 | ├─TABLE FULL SCAN |t1(idx_b_c_a)|1 |3 | |3 | └─MATERIAL | |1 |3 | |4 | └─TABLE FULL SCAN|t2 |1 |3 | @@ -1248,8 +1248,8 @@ Query Plan Outputs & filters: ------------------------------------- 0 - output([t1.a], [t1.b], [t1.c]), filter(nil), rowset=16 - group([t1.c], [t1.b]), agg_func(nil) - 1 - output([t1.c], [t1.b], [t1.a]), filter(nil), rowset=16 + group([t1.b], [t1.c]), agg_func(nil) + 1 - output([t1.b], [t1.c], [t1.a]), filter(nil), rowset=16 conds([t1.b != t2.x]), nl_params_(nil), use_batch=false 2 - output([t1.b], [t1.a], [t1.c]), filter(nil), rowset=16 access([t1.b], [t1.a], [t1.c]), partitions(p0) @@ -1500,42 +1500,43 @@ Outputs & filters: range_key([t3.a], [t3.b], [t3.c], [t3.pk1]), range(MIN,MIN,MIN,MIN ; MAX,MAX,MAX,MAX)always true explain select distinct a,b,c from t3 where d > any (select pk2 from t2); Query Plan -========================================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------------------- -|0 |MERGE DISTINCT | |1 |21 | -|1 |└─NESTED-LOOP SEMI JOIN | |1 |21 | -|2 | ├─TABLE FULL SCAN |t3(idx_a_b_c)|1 |3 | -|3 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |1 |18 | -========================================================================= +============================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------------- +|0 |MERGE DISTINCT | |1 |19 | +|1 |└─NESTED-LOOP JOIN | |1 |19 | +|2 | ├─TABLE FULL SCAN |t3(idx_a_b_c)|1 |3 | +|3 | └─TABLE RANGE SCAN|t2 |1 |16 | +============================================================= Outputs & filters: ------------------------------------- 0 - output([t3.a], [t3.b], [t3.c]), filter(nil), rowset=16 distinct([t3.a], [t3.b], [t3.c]) 1 - output([t3.a], [t3.b], [t3.c]), filter(nil), rowset=16 - conds(nil), nl_params_([t3.d(:0)]), use_batch=false + conds(nil), nl_params_([t3.d(:0)]), use_batch=true 2 - output([t3.d], [t3.a], [t3.b], [t3.c]), filter(nil), rowset=16 access([t3.d], [t3.a], [t3.b], [t3.c]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t3.a], [t3.b], [t3.c], [t3.pk1]), range(MIN,MIN,MIN,MIN ; MAX,MAX,MAX,MAX)always true 3 - output(nil), filter(nil), rowset=16 - access(nil), partitions(p0) + access([GROUP_ID]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.pk2]), range(MIN ; MAX), range_cond([:0 > t2.pk2]) explain select a, b, c from t1 where b = 100 and c < 100 and c > 100 order by c desc limit 0, 100; Query Plan -================================================================ -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ----------------------------------------------------------------- -|0 |TABLE FULL SCAN|t1(idx_b_c_a,Reverse)|0 |3 | -================================================================ +================================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +----------------------------------------------------------------- +|0 |TABLE RANGE SCAN|t1(idx_b_c_a,Reverse)|0 |3 | +================================================================= Outputs & filters: ------------------------------------- - 0 - output([t1.a], [t1.b], [t1.c]), filter([t1.c < 100], [t1.c > 100], [t1.b = 100]), rowset=16 + 0 - output([t1.a], [t1.b], [t1.c]), filter(nil), rowset=16 access([t1.b], [t1.c], [t1.a]), partitions(p0) - limit(100), offset(0), is_index_back=false, is_global_index=false, filter_before_indexback[false,false,false], - range_key([t1.b], [t1.c], [t1.a], [t1.pk1]), range(MAX,MAX,MAX,MAX ; MIN,MIN,MIN,MIN)always false + limit(100), offset(0), is_index_back=false, is_global_index=false, + range_key([t1.b], [t1.c], [t1.a], [t1.pk1]), range(MAX,MAX,MAX,MAX ; MIN,MIN,MIN,MIN)always false, + range_cond([t1.b = 100], [t1.c < 100], [t1.c > 100]) explain select a, b, c from t1 where b = 100 or (b = 200 and c = 300) order by c desc limit 0, 100; Query Plan ============================================================ @@ -3776,11 +3777,16 @@ Optimization Info: avaiable_index_name:[t10i1, t10i2, t10i3, t10] pruned_index_name:[t10i3] unstable_index_name:[t10] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t10 where c2 < 0 and c2 > 0 and c3 = 1; @@ -3826,26 +3832,32 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t10i1, t10i2, t10i3, t10] unstable_index_name:[t10] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t10 where c3 < 0 and c3 > 0 and c2 = 1; Query Plan -=============================================== -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------ -|0 |TABLE FULL SCAN|t10 |0 |3 | -=============================================== +====================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------ +|0 |TABLE RANGE SCAN|t10(t10i2)|0 |3 | +====================================================== Outputs & filters: ------------------------------------- - 0 - output([1]), filter([t10.c3 < 0], [t10.c3 > 0], [t10.c2 = 1]), rowset=16 - access([t10.c3], [t10.c2]), partitions(p0) - is_index_back=false, is_global_index=false, filter_before_indexback[false,false,false], - range_key([t10.pk]), range(MIN ; MAX)always true + 0 - output([1]), filter(nil), rowset=16 + access(nil), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([t10.c2], [t10.c3], [t10.pk]), range(MAX,MAX,MAX ; MIN,MIN,MIN)always false, + range_cond([t10.c3 < 0], [t10.c3 > 0], [t10.c2 = 1]) Used Hint: ------------------------------------- /*+ @@ -3859,7 +3871,7 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - FULL(@"SEL$1" "hualong"."t10"@"SEL$1") + INDEX(@"SEL$1" "hualong"."t10"@"SEL$1" "t10i2") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA */ @@ -3875,11 +3887,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t10i1, t10i2, t10i3, t10] pruned_index_name:[t10i3] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t10 where c2 < 0 and c2 > 0 and c4 = 2; @@ -3924,11 +3941,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t10i1, t10i2, t10i3, t10] pruned_index_name:[t10i3] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 2 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t10 where c3 < 0 and c3 > 0 and c4 = 2; @@ -3972,11 +3994,16 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t10i1, t10i2, t10i3, t10] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 2 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t10 where c2 < 0 and c2 > 0 and c3 = 1 order by c2; @@ -4023,29 +4050,32 @@ Optimization Info: avaiable_index_name:[t10i1, t10i2, t10i3, t10] pruned_index_name:[t10i1] unstable_index_name:[t10] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t10 where c3 < 0 and c3 > 0 and c2 = 1 order by c3; Query Plan -================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------- -|0 |SORT | |0 |3 | -|1 |└─TABLE FULL SCAN|t10 |0 |3 | -================================================= +====================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------ +|0 |TABLE RANGE SCAN|t10(t10i2)|0 |3 | +====================================================== Outputs & filters: ------------------------------------- 0 - output([1]), filter(nil), rowset=16 - sort_keys([t10.c3, ASC]) - 1 - output([t10.c3]), filter([t10.c3 < 0], [t10.c3 > 0], [t10.c2 = 1]), rowset=16 - access([t10.c3], [t10.c2]), partitions(p0) - is_index_back=false, is_global_index=false, filter_before_indexback[false,false,false], - range_key([t10.pk]), range(MIN ; MAX)always true + access(nil), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([t10.c2], [t10.c3], [t10.pk]), range(MAX,MAX,MAX ; MIN,MIN,MIN)always false, + range_cond([t10.c3 < 0], [t10.c3 > 0], [t10.c2 = 1]) Used Hint: ------------------------------------- /*+ @@ -4059,7 +4089,7 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - FULL(@"SEL$1" "hualong"."t10"@"SEL$1") + INDEX(@"SEL$1" "hualong"."t10"@"SEL$1" "t10i2") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA */ @@ -4075,11 +4105,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t10i1, t10i2, t10i3, t10] pruned_index_name:[t10i1, t10i3] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t10 where c2 < 0 and c2 > 0 and c4 = 2 order by c1; @@ -4127,11 +4162,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t10i1, t10i2, t10i3, t10] pruned_index_name:[t10i2, t10i3] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 2 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t10 where c3 < 0 and c3 > 0 and c4 = 2 order by c2; @@ -4179,11 +4219,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t10i1, t10i2, t10i3, t10] pruned_index_name:[t10i1, t10i3] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 2 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t10 where c3 < 0 and c3 > 0 and c4 = 2 order by c3; @@ -4231,11 +4276,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t10i1, t10i2, t10i3, t10] pruned_index_name:[t10i1, t10i2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 2 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t11 where pk < 0 and pk > 0; @@ -4280,11 +4330,15 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t11i1, t11] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t11 where c1 < 0 and c1 > 0; @@ -4329,11 +4383,15 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t11i1, t11] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t11 where pk < 0 and pk > 0 and c2 = 1; @@ -4379,11 +4437,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t11i1, t11] pruned_index_name:[t11i1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t11 where pk < 0 and pk > 0 and c2 = 1 order by pk; @@ -4429,11 +4492,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t11i1, t11] pruned_index_name:[t11i1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t11 where pk < 0 and pk > 0 and c2 = 1 order by c1; @@ -4481,11 +4549,16 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t11i1, t11] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t11 where pk < 0 and pk > 0 and c2 = 1 order by c2; @@ -4532,29 +4605,34 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t11i1, t11] pruned_index_name:[t11i1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property Expr Constraints: cast(1, INT(11, 0)) = 1 result is TRUE explain extended_noaddr select 1 from t11 where pk < 0 and pk > 0 and c1 = 1; Query Plan -================================================ -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------- -|0 |TABLE RANGE SCAN|t11 |0 |3 | -================================================ +====================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------ +|0 |TABLE RANGE SCAN|t11(t11i1)|0 |3 | +====================================================== Outputs & filters: ------------------------------------- - 0 - output([1]), filter([t11.c1 = 1]), rowset=16 - access([t11.c1]), partitions(p0) - is_index_back=false, is_global_index=false, filter_before_indexback[false], - range_key([t11.pk]), range(MAX ; MIN)always false, - range_cond([t11.pk < 0], [t11.pk > 0]) + 0 - output([1]), filter(nil), rowset=16 + access(nil), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([t11.c1], [t11.pk]), range(MAX,MAX ; MIN,MIN)always false, + range_cond([t11.pk < 0], [t11.pk > 0], [t11.c1 = 1]) Used Hint: ------------------------------------- /*+ @@ -4568,7 +4646,7 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - FULL(@"SEL$1" "hualong"."t11"@"SEL$1") + INDEX(@"SEL$1" "hualong"."t11"@"SEL$1" "t11i1") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA */ @@ -4583,26 +4661,32 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t11i1, t11] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t11 where pk < 0 and pk > 0 and c1 = 1 order by pk; Query Plan -===================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------ -|0 |TABLE FULL SCAN|t11(t11i1)|0 |3 | -===================================================== +====================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------ +|0 |TABLE RANGE SCAN|t11(t11i1)|0 |3 | +====================================================== Outputs & filters: ------------------------------------- - 0 - output([1]), filter([t11.pk < 0], [t11.pk > 0], [t11.c1 = 1]), rowset=16 - access([t11.pk], [t11.c1]), partitions(p0) - is_index_back=false, is_global_index=false, filter_before_indexback[false,false,false], - range_key([t11.c1], [t11.pk]), range(MAX,MAX ; MIN,MIN)always false + 0 - output([1]), filter(nil), rowset=16 + access(nil), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([t11.c1], [t11.pk]), range(MAX,MAX ; MIN,MIN)always false, + range_cond([t11.pk < 0], [t11.pk > 0], [t11.c1 = 1]) Used Hint: ------------------------------------- /*+ @@ -4632,27 +4716,32 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t11i1, t11] pruned_index_name:[t11] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t11 where pk < 0 and pk > 0 and c1 = 1 order by c1; Query Plan -================================================ -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------- -|0 |TABLE RANGE SCAN|t11 |0 |3 | -================================================ +====================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------ +|0 |TABLE RANGE SCAN|t11(t11i1)|0 |3 | +====================================================== Outputs & filters: ------------------------------------- - 0 - output([1]), filter([t11.c1 = 1]), rowset=16 - access([t11.c1]), partitions(p0) - is_index_back=false, is_global_index=false, filter_before_indexback[false], - range_key([t11.pk]), range(MAX ; MIN)always false, - range_cond([t11.pk < 0], [t11.pk > 0]) + 0 - output([1]), filter(nil), rowset=16 + access(nil), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([t11.c1], [t11.pk]), range(MAX,MAX ; MIN,MIN)always false, + range_cond([t11.pk < 0], [t11.pk > 0], [t11.c1 = 1]) Used Hint: ------------------------------------- /*+ @@ -4666,7 +4755,7 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - FULL(@"SEL$E230E5BA" "hualong"."t11"@"SEL$1") + INDEX(@"SEL$E230E5BA" "hualong"."t11"@"SEL$1" "t11i1") REPLACE_CONST(@"SEL$1") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA @@ -4682,11 +4771,16 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t11i1, t11] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property Expr Constraints: @@ -4737,11 +4831,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t11i1, t11] pruned_index_name:[t11i1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t12 where c2 < 0 and c2 > 0; @@ -4786,11 +4885,15 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t12i1, t12i2, t12] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select * from t12 where c2 < 0 and c2 > 0; @@ -4835,11 +4938,14 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t12i1, t12i2, t12] pruned_index_name:[t12i1, t12i2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 0 + :1 => 0 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select 1 from t12 where c2 < 0 and c2 > 0 and c3 = 1; @@ -4884,11 +4990,16 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t12i1, t12i2, t12] pruned_index_name:[t12i1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 1 + :1 => 0 + :2 => 0 + :3 => 1 Note: Degree of Parallelisim is 1 because of table property explain extended_noaddr select * from t12 where c2 < 0 and c2 > 0 and c3 = 1; @@ -4933,11 +5044,15 @@ Optimization Info: dop_method:Table DOP avaiable_index_name:[t12i1, t12i2, t12] pruned_index_name:[t12i1, t12i2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: LOCAL + Parameters: + :0 => 0 + :1 => 0 + :2 => 1 Note: Degree of Parallelisim is 1 because of table property set @@recyclebin = 'off'; diff --git a/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_business_mysql.result b/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_business_mysql.result index 643b2eea44..9002284fc6 100644 --- a/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_business_mysql.result +++ b/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_business_mysql.result @@ -211,8 +211,7 @@ Outputs & filters: luna_core_bidword_diagnose.click_p_1d, luna_core_bidword_diagnose.rankdown_cnt, luna_core_bidword_diagnose.subtype, luna_core_bidword_diagnose.imp_factor, luna_core_bidword_diagnose.click_factor)})}]), update([luna_core_bidword_diagnose.gmt_modified=column_conv(TIMESTAMP,PS:(19,0),NOT NULL,timestamp_nvl(cast(current_timestamp(), TIMESTAMP(-1, 0)), - cast(current_timestamp(), TIMESTAMP(19, 0))))], [luna_core_bidword_diagnose.updatepricetag=column_conv(BIGINT UNSIGNED,PS:(20,0),NULL,cast(8, BIGINT UNSIGNED(-1, - 0)))]) + cast(current_timestamp(), TIMESTAMP(19, 0))))], [luna_core_bidword_diagnose.updatepricetag=column_conv(BIGINT UNSIGNED,PS:(20,0),NULL,8)]) 1 - output([luna_core_bidword_diagnose.id], [luna_core_bidword_diagnose.custid], [luna_core_bidword_diagnose.gmt_modified], [luna_core_bidword_diagnose.updatepricetag], [luna_core_bidword_diagnose.gmt_create], [luna_core_bidword_diagnose.platform], [luna_core_bidword_diagnose.type], [luna_core_bidword_diagnose.realtimefilter], [luna_core_bidword_diagnose.offlineprice], [luna_core_bidword_diagnose.impression_p_7d], [luna_core_bidword_diagnose.impression_1d], [luna_core_bidword_diagnose.click_p_7d], @@ -258,8 +257,7 @@ Outputs & filters: luna_core_bidword_diagnose.click_p_1d, luna_core_bidword_diagnose.rankdown_cnt, luna_core_bidword_diagnose.subtype, luna_core_bidword_diagnose.imp_factor, luna_core_bidword_diagnose.click_factor)})}]), update([luna_core_bidword_diagnose.gmt_modified=column_conv(TIMESTAMP,PS:(19,0),NOT NULL,timestamp_nvl(cast(current_timestamp(), TIMESTAMP(-1, 0)), - cast(current_timestamp(), TIMESTAMP(19, 0))))], [luna_core_bidword_diagnose.updatepricetag=column_conv(BIGINT UNSIGNED,PS:(20,0),NULL,cast(8, BIGINT UNSIGNED(-1, - 0)))]) + cast(current_timestamp(), TIMESTAMP(19, 0))))], [luna_core_bidword_diagnose.updatepricetag=column_conv(BIGINT UNSIGNED,PS:(20,0),NULL,8)]) 1 - output([luna_core_bidword_diagnose.id], [luna_core_bidword_diagnose.custid], [luna_core_bidword_diagnose.gmt_modified], [luna_core_bidword_diagnose.updatepricetag], [luna_core_bidword_diagnose.gmt_create], [luna_core_bidword_diagnose.platform], [luna_core_bidword_diagnose.type], [luna_core_bidword_diagnose.realtimefilter], [luna_core_bidword_diagnose.offlineprice], [luna_core_bidword_diagnose.impression_p_7d], [luna_core_bidword_diagnose.impression_1d], [luna_core_bidword_diagnose.click_p_7d], @@ -305,8 +303,7 @@ Outputs & filters: luna_core_bidword_diagnose.click_p_1d, luna_core_bidword_diagnose.rankdown_cnt, luna_core_bidword_diagnose.subtype, luna_core_bidword_diagnose.imp_factor, luna_core_bidword_diagnose.click_factor)})}]), update([luna_core_bidword_diagnose.gmt_modified=column_conv(TIMESTAMP,PS:(19,0),NOT NULL,timestamp_nvl(cast(current_timestamp(), TIMESTAMP(-1, 0)), - cast(current_timestamp(), TIMESTAMP(19, 0))))], [luna_core_bidword_diagnose.updatepricetag=column_conv(BIGINT UNSIGNED,PS:(20,0),NULL,cast(8, BIGINT UNSIGNED(-1, - 0)))]) + cast(current_timestamp(), TIMESTAMP(19, 0))))], [luna_core_bidword_diagnose.updatepricetag=column_conv(BIGINT UNSIGNED,PS:(20,0),NULL,8)]) 1 - output([luna_core_bidword_diagnose.id], [luna_core_bidword_diagnose.custid], [luna_core_bidword_diagnose.gmt_modified], [luna_core_bidword_diagnose.updatepricetag], [luna_core_bidword_diagnose.gmt_create], [luna_core_bidword_diagnose.platform], [luna_core_bidword_diagnose.type], [luna_core_bidword_diagnose.realtimefilter], [luna_core_bidword_diagnose.offlineprice], [luna_core_bidword_diagnose.impression_p_7d], [luna_core_bidword_diagnose.impression_1d], [luna_core_bidword_diagnose.click_p_7d], @@ -702,16 +699,16 @@ KEY `WSJJDM_LOCAL` (`WSJJDM`, `WSJWSY`) LOCAL partition by key(`wsjjdm`, `wsjjzh`) partitions 31; explain select `WSJJDM`, `WSJWSY` from wfsydp where wsjjdm = '666888' order by `WSJJDM`, `WSJWSY` limit 0 , 181819; Query Plan -====================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ----------------------------------------------------------------------- -|0 |DISTRIBUTED TABLE RANGE SCAN|wfsydp(WSJJDM)|1 |3 | -====================================================================== +========================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------- +|0 |TABLE RANGE SCAN|wfsydp(WSJJDM)|1 |3 | +========================================================== Outputs & filters: ------------------------------------- 0 - output([wfsydp.WSJJDM], [wfsydp.WSJWSY]), filter(nil), rowset=16 access([wfsydp.WSJJDM], [wfsydp.WSJWSY]), partitions(p0) - limit(181819), offset(0), is_index_back=false, is_global_index=true, keep_ordering=true, + limit(181819), offset(0), is_index_back=false, is_global_index=true, range_key([wfsydp.WSJJDM], [wfsydp.WSJWSY], [wfsydp.WSJJZH], [wfsydp.WSDRDM], [wfsydp.WSJYZH]), range(666888,MIN,MIN,MIN,MIN ; 666888,MAX,MAX,MAX, MAX), range_cond([wfsydp.WSJJDM = '666888']) diff --git a/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_complicate_mysql.result b/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_complicate_mysql.result index 416a28f0b0..8f1e52e179 100644 --- a/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_complicate_mysql.result +++ b/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_complicate_mysql.result @@ -1502,14 +1502,14 @@ Outputs & filters: range_key([other.c2], [other.c3], [other.c1]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true explain select /*+use_nl(skyline_int other)*/tenant_id from skyline_int join other where skyline_int.v3 = other.c2 group by v3, v4; Query Plan -===================================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------------------------------- -|0 |MERGE GROUP BY | |1 |19 | -|1 |└─NESTED-LOOP JOIN | |1 |19 | -|2 | ├─TABLE FULL SCAN |skyline_int(idx_v3_v4_v2)|1 |3 | -|3 | └─DISTRIBUTED TABLE RANGE SCAN|other(idx_c2) |1 |16 | -===================================================================================== +========================================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------------------------- +|0 |MERGE GROUP BY | |1 |19 | +|1 |└─NESTED-LOOP JOIN | |1 |19 | +|2 | ├─TABLE FULL SCAN |skyline_int(idx_v3_v4_v2)|1 |3 | +|3 | └─TABLE RANGE SCAN|other(idx_c2) |1 |16 | +========================================================================= Outputs & filters: ------------------------------------- 0 - output([skyline_int.tenant_id]), filter(nil), rowset=16 @@ -1528,14 +1528,14 @@ Outputs & filters: range_cond([:0 = other.c2]) explain select /*+use_nl(skyline_int other)*/tenant_id from skyline_int join other where skyline_int.v3 = other.c2 group by v3, v4, v5; Query Plan -======================================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ----------------------------------------------------------------------------------------- -|0 |MERGE GROUP BY | |1 |19 | -|1 |└─NESTED-LOOP JOIN | |1 |19 | -|2 | ├─TABLE FULL SCAN |skyline_int(idx_v3_v4_v5_v2)|1 |3 | -|3 | └─DISTRIBUTED TABLE RANGE SCAN|other(idx_c2) |1 |16 | -======================================================================================== +============================================================================ +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------------- +|0 |MERGE GROUP BY | |1 |19 | +|1 |└─NESTED-LOOP JOIN | |1 |19 | +|2 | ├─TABLE FULL SCAN |skyline_int(idx_v3_v4_v5_v2)|1 |3 | +|3 | └─TABLE RANGE SCAN|other(idx_c2) |1 |16 | +============================================================================ Outputs & filters: ------------------------------------- 0 - output([skyline_int.tenant_id]), filter(nil), rowset=16 diff --git a/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_index_back_mysql.result b/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_index_back_mysql.result index a02548fb44..054545bc74 100644 --- a/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_index_back_mysql.result +++ b/tools/deploy/mysql_test/test_suite/skyline/r/mysql/skyline_index_back_mysql.result @@ -532,7 +532,7 @@ Outputs & filters: quality_item_info.block_id, quality_item_info.band_id, quality_item_info.brand_id, quality_item_info.pass_status, quality_item_info.pass_operator, quality_item_info.gmt_pass, quality_item_info.cat_id)})}]), update([quality_item_info.gmt_modified=column_conv(DATETIME,PS:(19,0),NOT NULL,current_timestamp())], [quality_item_info.pass_status=column_conv(INT, - PS:(11,0),NULL,cast(100, INT(-1, 0)))], [quality_item_info.gmt_pass=column_conv(DATETIME,PS:(19,0),NULL,current_timestamp())], [quality_item_info.pass_operator=column_conv(VARCHAR, + PS:(11,0),NULL,100)], [quality_item_info.gmt_pass=column_conv(DATETIME,PS:(19,0),NULL,current_timestamp())], [quality_item_info.pass_operator=column_conv(VARCHAR, utf8mb4_general_ci,length:64,NULL,'1')]) 1 - output([quality_item_info.id], [quality_item_info.gmt_modified], [quality_item_info.pass_status], [quality_item_info.gmt_pass], [quality_item_info.pass_operator], [quality_item_info.gmt_create], [quality_item_info.item_id], [quality_item_info.seller_id], [quality_item_info.seller_nick], [quality_item_info.status], @@ -561,7 +561,7 @@ Outputs & filters: quality_item_info.block_id, quality_item_info.band_id, quality_item_info.brand_id, quality_item_info.pass_status, quality_item_info.pass_operator, quality_item_info.gmt_pass, quality_item_info.cat_id)})}]), update([quality_item_info.gmt_modified=column_conv(DATETIME,PS:(19,0),NOT NULL,current_timestamp())], [quality_item_info.pass_status=column_conv(INT, - PS:(11,0),NULL,cast(100, INT(-1, 0)))], [quality_item_info.gmt_pass=column_conv(DATETIME,PS:(19,0),NULL,current_timestamp())], [quality_item_info.pass_operator=column_conv(VARCHAR, + PS:(11,0),NULL,100)], [quality_item_info.gmt_pass=column_conv(DATETIME,PS:(19,0),NULL,current_timestamp())], [quality_item_info.pass_operator=column_conv(VARCHAR, utf8mb4_general_ci,length:64,NULL,'1')]) 1 - output([quality_item_info.id], [quality_item_info.gmt_modified], [quality_item_info.pass_status], [quality_item_info.gmt_pass], [quality_item_info.pass_operator], [quality_item_info.gmt_create], [quality_item_info.item_id], [quality_item_info.seller_id], [quality_item_info.seller_nick], [quality_item_info.status], @@ -589,7 +589,7 @@ Outputs & filters: quality_item_info.block_id, quality_item_info.band_id, quality_item_info.brand_id, quality_item_info.pass_status, quality_item_info.pass_operator, quality_item_info.gmt_pass, quality_item_info.cat_id)})}]), update([quality_item_info.gmt_modified=column_conv(DATETIME,PS:(19,0),NOT NULL,current_timestamp())], [quality_item_info.pass_status=column_conv(INT, - PS:(11,0),NULL,cast(100, INT(-1, 0)))], [quality_item_info.gmt_pass=column_conv(DATETIME,PS:(19,0),NULL,current_timestamp())], [quality_item_info.pass_operator=column_conv(VARCHAR, + PS:(11,0),NULL,100)], [quality_item_info.gmt_pass=column_conv(DATETIME,PS:(19,0),NULL,current_timestamp())], [quality_item_info.pass_operator=column_conv(VARCHAR, utf8mb4_general_ci,length:64,NULL,'1')]) 1 - output([quality_item_info.id], [quality_item_info.gmt_modified], [quality_item_info.pass_status], [quality_item_info.gmt_pass], [quality_item_info.pass_operator], [quality_item_info.gmt_create], [quality_item_info.item_id], [quality_item_info.seller_id], [quality_item_info.seller_nick], [quality_item_info.status], diff --git a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_concat.result b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_concat.result index 90e2db6a53..d5379c91fb 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_concat.result +++ b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/expr_concat.result @@ -87,13 +87,13 @@ select group_concat(c1) from (select 'abcdefg' c1 union select '0123456789101234 +----------------------+ | group_concat(c1) | +----------------------+ -| 01234567891012345678 | +| abcdefg,012345678910 | +----------------------+ select group_concat(c1) from (select 'abcdefg' c1 union select '012345678910123456' c1)a; +----------------------+ | group_concat(c1) | +----------------------+ -| 012345678910123456,a | +| abcdefg,012345678910 | +----------------------+ drop table if exists t111_var; diff --git a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/hash_distinct.result b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/hash_distinct.result index 40d5e9e561..6c54d211e3 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/hash_distinct.result +++ b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/hash_distinct.result @@ -5948,25 +5948,28 @@ Outputs & filters: REPLACE INTO t1(c0) VALUES('rF0Lll5'); explain basic SELECT count(*) as rowCount FROM (SELECT /*+ USE_HASH (t1) */ DISTINCT t0.c0 AS t0c0, t0.c1 AS t0c1, t2.c0 AS t2c0, t1.c0 AS t1c0 FROM t0, t2, t1 WHERE t0.c1 ORDER BY t0.c0 DESC, t1.c0 DESC LIMIT 2147483647 OFFSET 0) as result WHERE concat(result.t0c0,'') IS NULL AND result.t0c1 = 398204275 AND result.t2c0 = 1489403758 AND concat(result.t1c0,'') = "q6h]zjLt)|[?S*C"; Query Plan -========================================================= -|ID|OPERATOR |NAME | ---------------------------------------------------------- -|0 |SCALAR GROUP BY | | -|1 |└─SUBPLAN SCAN |result | -|2 | └─LIMIT | | -|3 | └─TOP-N SORT | | -|4 | └─HASH DISTINCT | | -|5 | └─NESTED-LOOP JOIN CARTESIAN | | -|6 | ├─NESTED-LOOP JOIN CARTESIAN | | -|7 | │ ├─DISTRIBUTED TABLE FULL SCAN |t1(i430)| -|8 | │ └─MATERIAL | | -|9 | │ └─DISTRIBUTED TABLE FULL SCAN|t2(i950)| -|10| └─MATERIAL | | -|11| └─PX COORDINATOR | | -|12| └─EXCHANGE OUT DISTR |:EX10000| -|13| └─PX PARTITION ITERATOR | | -|14| └─TABLE FULL SCAN |t0 | -========================================================= +======================================================= +|ID|OPERATOR |NAME | +------------------------------------------------------- +|0 |SCALAR GROUP BY | | +|1 |└─SUBPLAN SCAN |result | +|2 | └─LIMIT | | +|3 | └─TOP-N SORT | | +|4 | └─HASH DISTINCT | | +|5 | └─NESTED-LOOP JOIN CARTESIAN | | +|6 | ├─NESTED-LOOP JOIN CARTESIAN | | +|7 | │ ├─TABLE FULL SCAN |t1(i430)| +|8 | │ └─MATERIAL | | +|9 | │ └─PX COORDINATOR | | +|10| │ └─EXCHANGE OUT DISTR |:EX10000| +|11| │ └─PX PARTITION ITERATOR| | +|12| │ └─TABLE FULL SCAN |t2(i950)| +|13| └─MATERIAL | | +|14| └─PX COORDINATOR | | +|15| └─EXCHANGE OUT DISTR |:EX20000| +|16| └─PX PARTITION ITERATOR | | +|17| └─TABLE FULL SCAN |t0 | +======================================================= Outputs & filters: ------------------------------------- 0 - output([T_FUN_COUNT(*)]), filter(nil), rowset=256 @@ -5990,40 +5993,48 @@ Outputs & filters: range_key([t1.__substr1_16], [t1.__pk_increment], [t1.c0]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true 8 - output([t2.c0]), filter(nil), rowset=256 9 - output([t2.c0]), filter(nil), rowset=256 + 10 - output([t2.c0]), filter(nil), rowset=256 + dop=1 + 11 - output([t2.c0]), filter(nil), rowset=256 + force partition granule + 12 - output([t2.c0]), filter(nil), rowset=256 access([t2.c0]), partitions(p[0-2]) is_index_back=false, is_global_index=true, range_key([t2.c0], [t2.__pk_increment]), range(MIN,MIN ; MAX,MAX)always true - 10 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 - 11 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 - 12 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 + 13 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 + 14 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 + 15 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 dop=1 - 13 - output([t0.c1], [t0.c0]), filter(nil), rowset=256 + 16 - output([t0.c1], [t0.c0]), filter(nil), rowset=256 force partition granule - 14 - output([t0.c1], [t0.c0]), filter([t0.c1]), rowset=256 + 17 - output([t0.c1], [t0.c0]), filter([t0.c1]), rowset=256 access([t0.c1], [t0.c0]), partitions(p[0-14]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t0.__pk_increment]), range(MIN ; MAX)always true EXPLAIN BASIC SELECT count(*) as rowCount FROM (SELECT /*+ USE_HASH (t1) */ DISTINCT t0.c0 AS t0c0, t0.c1 AS t0c1, t2.c0 AS t2c0, t1.c0 AS t1c0 FROM t0, t2, t1 WHERE t0.c1 ORDER BY t0.c0 DESC, t1.c0 DESC LIMIT 2147483647 OFFSET 0) as result WHERE concat(result.t0c0,'') IS NULL AND result.t0c1 = 398204275 AND result.t2c0 = 1489403758 AND concat(result.t1c0,'') = "q6h]zjLt)|[?S*C"; Query Plan -========================================================= -|ID|OPERATOR |NAME | ---------------------------------------------------------- -|0 |SCALAR GROUP BY | | -|1 |└─SUBPLAN SCAN |result | -|2 | └─LIMIT | | -|3 | └─TOP-N SORT | | -|4 | └─HASH DISTINCT | | -|5 | └─NESTED-LOOP JOIN CARTESIAN | | -|6 | ├─NESTED-LOOP JOIN CARTESIAN | | -|7 | │ ├─DISTRIBUTED TABLE FULL SCAN |t1(i430)| -|8 | │ └─MATERIAL | | -|9 | │ └─DISTRIBUTED TABLE FULL SCAN|t2(i950)| -|10| └─MATERIAL | | -|11| └─PX COORDINATOR | | -|12| └─EXCHANGE OUT DISTR |:EX10000| -|13| └─PX PARTITION ITERATOR | | -|14| └─TABLE FULL SCAN |t0 | -========================================================= +======================================================= +|ID|OPERATOR |NAME | +------------------------------------------------------- +|0 |SCALAR GROUP BY | | +|1 |└─SUBPLAN SCAN |result | +|2 | └─LIMIT | | +|3 | └─TOP-N SORT | | +|4 | └─HASH DISTINCT | | +|5 | └─NESTED-LOOP JOIN CARTESIAN | | +|6 | ├─NESTED-LOOP JOIN CARTESIAN | | +|7 | │ ├─TABLE FULL SCAN |t1(i430)| +|8 | │ └─MATERIAL | | +|9 | │ └─PX COORDINATOR | | +|10| │ └─EXCHANGE OUT DISTR |:EX10000| +|11| │ └─PX PARTITION ITERATOR| | +|12| │ └─TABLE FULL SCAN |t2(i950)| +|13| └─MATERIAL | | +|14| └─PX COORDINATOR | | +|15| └─EXCHANGE OUT DISTR |:EX20000| +|16| └─PX PARTITION ITERATOR | | +|17| └─TABLE FULL SCAN |t0 | +======================================================= Outputs & filters: ------------------------------------- 0 - output([T_FUN_COUNT(*)]), filter(nil), rowset=256 @@ -6047,16 +6058,21 @@ Outputs & filters: range_key([t1.__substr1_16], [t1.__pk_increment], [t1.c0]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true 8 - output([t2.c0]), filter(nil), rowset=256 9 - output([t2.c0]), filter(nil), rowset=256 + 10 - output([t2.c0]), filter(nil), rowset=256 + dop=1 + 11 - output([t2.c0]), filter(nil), rowset=256 + force partition granule + 12 - output([t2.c0]), filter(nil), rowset=256 access([t2.c0]), partitions(p[0-2]) is_index_back=false, is_global_index=true, range_key([t2.c0], [t2.__pk_increment]), range(MIN,MIN ; MAX,MAX)always true - 10 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 - 11 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 - 12 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 + 13 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 + 14 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 + 15 - output([t0.c0], [t0.c1]), filter(nil), rowset=256 dop=1 - 13 - output([t0.c1], [t0.c0]), filter(nil), rowset=256 + 16 - output([t0.c1], [t0.c0]), filter(nil), rowset=256 force partition granule - 14 - output([t0.c1], [t0.c0]), filter([t0.c1]), rowset=256 + 17 - output([t0.c1], [t0.c0]), filter([t0.c1]), rowset=256 access([t0.c1], [t0.c0]), partitions(p[0-14]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t0.__pk_increment]), range(MIN ; MAX)always true diff --git a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/merge_join.result b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/merge_join.result index efa64337af..719b4fc2b0 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/merge_join.result +++ b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/merge_join.result @@ -541,7 +541,7 @@ Query Plan =================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| --------------------------------------------------- -|0 |MERGE JOIN | |4 |8 | +|0 |MERGE JOIN | |9 |8 | |1 |├─SORT | |9 |4 | |2 |│ └─TABLE FULL SCAN|t2 |9 |3 | |3 |└─SORT | |10 |4 | @@ -799,7 +799,7 @@ Query Plan =================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| --------------------------------------------------- -|0 |MERGE JOIN | |4 |9 | +|0 |MERGE JOIN | |9 |9 | |1 |├─SORT | |10 |4 | |2 |│ └─TABLE FULL SCAN|t1 |10 |3 | |3 |└─SORT | |9 |4 | @@ -1057,7 +1057,7 @@ Query Plan =================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| --------------------------------------------------- -|0 |MERGE JOIN | |2 |7 | +|0 |MERGE JOIN | |4 |7 | |1 |├─TABLE FULL SCAN |pk_t|4 |3 | |2 |└─SORT | |9 |4 | |3 | └─TABLE FULL SCAN|t2 |9 |3 | diff --git a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/nested_loop_join.result b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/nested_loop_join.result index 2278e0c5b2..07478d8b7f 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/nested_loop_join.result +++ b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/nested_loop_join.result @@ -15,13 +15,13 @@ set _nlj_batching_enabled = false; EXPLAIN select /*+use_nl(t1 t2) leading(t1 t2)*/ * from t1, t2 where t1.c1 = t2.c1; Query Plan -======================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |NESTED-LOOP JOIN | |4 |96 | -|1 |├─TABLE FULL SCAN |t1 |5 |3 | -|2 |└─DISTRIBUTED TABLE GET|t2 |1 |18 | -======================================================= +================================================= +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------------- +|0 |NESTED-LOOP JOIN | |4 |96 | +|1 |├─TABLE FULL SCAN|t1 |5 |3 | +|2 |└─TABLE GET |t2 |1 |18 | +================================================= Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2], [t2.c1], [t2.c2]), filter(nil), rowset=16 @@ -84,7 +84,7 @@ Query Plan ------------------------------------------------------- |0 |NESTED-LOOP OUTER JOIN | |5 |96 | |1 |├─TABLE FULL SCAN |t1 |5 |3 | -|2 |└─DISTRIBUTED TABLE GET|t2 |1 |18 | +|2 |└─TABLE GET |t2 |1 |18 | ======================================================= Outputs & filters: ------------------------------------- @@ -321,13 +321,13 @@ select /*+use_nl(t1, t2)*/ * from t1 where exists (select 1 from t2 where t1.c1 EXPLAIN select /*+use_nl(t1, t2)*/ * from t1 where exists (select 1 from t2 where t1.c1 = t2.c1); Query Plan -======================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |NESTED-LOOP JOIN | |4 |96 | -|1 |├─TABLE FULL SCAN |t1 |5 |3 | -|2 |└─DISTRIBUTED TABLE GET|t2 |1 |18 | -======================================================= +================================================= +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------------- +|0 |NESTED-LOOP JOIN | |4 |96 | +|1 |├─TABLE FULL SCAN|t1 |5 |3 | +|2 |└─TABLE GET |t2 |1 |18 | +================================================= Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 @@ -384,13 +384,13 @@ select /*+use_nl(t1, t2)*/ * from t1 where not exists (select 1 from t2 where t1 EXPLAIN select /*+use_nl(t1, t2)*/ * from t1 where not exists (select 1 from t2 where t1.c1 = t2.c1); Query Plan -======================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |NESTED-LOOP ANTI JOIN | |1 |96 | -|1 |├─TABLE FULL SCAN |t1 |5 |3 | -|2 |└─DISTRIBUTED TABLE GET|t2 |1 |18 | -======================================================= +====================================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------------------ +|0 |NESTED-LOOP ANTI JOIN | |1 |96 | +|1 |├─TABLE FULL SCAN |t1 |5 |3 | +|2 |└─TABLE GET |t2 |1 |18 | +====================================================== Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 @@ -416,13 +416,13 @@ select /*+use_nl(t1, t2)*/ * from t1 where not exists (select 1 from t2 where t1 set _nlj_batching_enabled = true; EXPLAIN select /*+use_nl(t1 t2) leading(t1 t2)*/ * from t1, t2 where t1.c1 = t2.c1; Query Plan -======================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |NESTED-LOOP JOIN | |4 |83 | -|1 |├─TABLE FULL SCAN |t1 |5 |3 | -|2 |└─DISTRIBUTED TABLE GET|t2 |1 |16 | -======================================================= +================================================= +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------------- +|0 |NESTED-LOOP JOIN | |4 |83 | +|1 |├─TABLE FULL SCAN|t1 |5 |3 | +|2 |└─TABLE GET |t2 |1 |16 | +================================================= Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2], [t2.c1], [t2.c2]), filter(nil), rowset=16 @@ -483,7 +483,7 @@ Query Plan ------------------------------------------------------- |0 |NESTED-LOOP OUTER JOIN | |5 |83 | |1 |├─TABLE FULL SCAN |t1 |5 |3 | -|2 |└─DISTRIBUTED TABLE GET|t2 |1 |16 | +|2 |└─TABLE GET |t2 |1 |16 | ======================================================= Outputs & filters: ------------------------------------- @@ -719,13 +719,13 @@ select /*+use_nl(t1, t2)*/ * from t1 where exists (select 1 from t2 where t1.c1 EXPLAIN select /*+use_nl(t1, t2)*/ * from t1 where exists (select 1 from t2 where t1.c1 = t2.c1); Query Plan -======================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |NESTED-LOOP JOIN | |4 |83 | -|1 |├─TABLE FULL SCAN |t1 |5 |3 | -|2 |└─DISTRIBUTED TABLE GET|t2 |1 |16 | -======================================================= +================================================= +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------------- +|0 |NESTED-LOOP JOIN | |4 |83 | +|1 |├─TABLE FULL SCAN|t1 |5 |3 | +|2 |└─TABLE GET |t2 |1 |16 | +================================================= Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 @@ -782,13 +782,13 @@ select /*+use_nl(t1, t2)*/ * from t1 where not exists (select 1 from t2 where t1 EXPLAIN select /*+use_nl(t1, t2)*/ * from t1 where not exists (select 1 from t2 where t1.c1 = t2.c1); Query Plan -======================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |NESTED-LOOP ANTI JOIN | |1 |96 | -|1 |├─TABLE FULL SCAN |t1 |5 |3 | -|2 |└─DISTRIBUTED TABLE GET|t2 |1 |18 | -======================================================= +====================================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------------------ +|0 |NESTED-LOOP ANTI JOIN | |1 |96 | +|1 |├─TABLE FULL SCAN |t1 |5 |3 | +|2 |└─TABLE GET |t2 |1 |18 | +====================================================== Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 diff --git a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/px_basic.result b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/px_basic.result index 879a537e88..6ffcf09cce 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/px_basic.result +++ b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/px_basic.result @@ -283,21 +283,20 @@ select /*+ parallel(2) pq_distribute(a hash hash) NO_USE_HASH_AGGREGATION */ a.c ## broadcast shuffle EXPLAIN BASIC select /*+ parallel(2) pq_distribute(b broadcast none) */ * from t1 a, t2 b where a.c1=b.c2 order by a.c1,b.c1; Query Plan -=================================================== -|ID|OPERATOR |NAME | ---------------------------------------------------- -|0 |PX COORDINATOR MERGE SORT | | -|1 |└─EXCHANGE OUT DISTR |:EX10001| -|2 | └─SORT | | -|3 | └─HASH JOIN | | -|4 | ├─PART JOIN FILTER CREATE |:RF0000 | -|5 | │ └─PX PARTITION ITERATOR | | -|6 | │ └─TABLE FULL SCAN |b | -|7 | └─EXCHANGE IN DISTR | | -|8 | └─EXCHANGE OUT DISTR (PKEY) |:EX10000| -|9 | └─PX BLOCK HASH JOIN-FILTER|:RF0000 | -|10| └─TABLE FULL SCAN |a | -=================================================== +================================================= +|ID|OPERATOR |NAME | +------------------------------------------------- +|0 |PX COORDINATOR MERGE SORT | | +|1 |└─EXCHANGE OUT DISTR |:EX10001| +|2 | └─SORT | | +|3 | └─HASH JOIN | | +|4 | ├─PX PARTITION ITERATOR | | +|5 | │ └─TABLE FULL SCAN |b | +|6 | └─EXCHANGE IN DISTR | | +|7 | └─EXCHANGE OUT DISTR (PKEY)|:EX10000| +|8 | └─PX BLOCK ITERATOR | | +|9 | └─TABLE FULL SCAN |a | +================================================= Outputs & filters: ------------------------------------- 0 - output([INTERNAL_FUNCTION(a.c1, a.c2, b.c1, b.c2)]), filter(nil), rowset=16 @@ -308,19 +307,17 @@ Outputs & filters: sort_keys([a.c1, ASC], [b.c1, ASC]) 3 - output([a.c1], [b.c1], [b.c2], [a.c2]), filter(nil), rowset=16 equal_conds([a.c1 = b.c2]), other_conds(nil) - 4 - output([b.c1], [b.c2]), filter(nil), rowset=16 - RF_TYPE(bloom), RF_EXPR[calc_tablet_id(b.c2)] - 5 - output([b.c2], [b.c1]), filter(nil), rowset=16 + 4 - output([b.c2], [b.c1]), filter(nil), rowset=16 affinitize - 6 - output([b.c2], [b.c1]), filter(nil), rowset=16 + 5 - output([b.c2], [b.c1]), filter(nil), rowset=16 access([b.c2], [b.c1]), partitions(p[0-5]) is_index_back=false, is_global_index=false, range_key([b.__pk_increment]), range(MIN ; MAX)always true + 6 - output([a.c1], [a.c2]), filter(nil), rowset=16 7 - output([a.c1], [a.c2]), filter(nil), rowset=16 - 8 - output([a.c1], [a.c2]), filter(nil), rowset=16 (#keys=1, [a.c1]), dop=2 + 8 - output([a.c1], [a.c2]), filter(nil), rowset=16 9 - output([a.c1], [a.c2]), filter(nil), rowset=16 - 10 - output([a.c1], [a.c2]), filter(nil), rowset=16 access([a.c1], [a.c2]), partitions(p[0-4]) is_index_back=false, is_global_index=false, range_key([a.__pk_increment]), range(MIN ; MAX)always true diff --git a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/subplan_filter.result b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/subplan_filter.result index ed15897e69..8bc62dfc4f 100644 --- a/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/subplan_filter.result +++ b/tools/deploy/mysql_test/test_suite/static_engine/r/mysql/subplan_filter.result @@ -397,9 +397,9 @@ Query Plan ================================================= |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------- -|0 |SUBPLAN FILTER | |3 |10 | +|0 |SUBPLAN FILTER | |3 |56 | |1 |├─TABLE FULL SCAN|t1 |3 |3 | -|2 |└─TABLE FULL SCAN|t2 |1 |3 | +|2 |└─TABLE FULL SCAN|t2 |1 |18 | ================================================= Outputs & filters: ------------------------------------- @@ -426,9 +426,9 @@ Query Plan ================================================= |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |10 | +|0 |SUBPLAN FILTER | |1 |57 | |1 |├─TABLE FULL SCAN|t1 |3 |3 | -|2 |└─TABLE FULL SCAN|t2 |1 |3 | +|2 |└─TABLE FULL SCAN|t2 |1 |18 | ================================================= Outputs & filters: ------------------------------------- @@ -676,9 +676,9 @@ Query Plan ================================================= |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |10 | +|0 |SUBPLAN FILTER | |1 |57 | |1 |├─TABLE FULL SCAN|t1 |3 |3 | -|2 |└─TABLE FULL SCAN|t2 |1 |3 | +|2 |└─TABLE FULL SCAN|t2 |1 |18 | ================================================= Outputs & filters: ------------------------------------- @@ -894,24 +894,21 @@ select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2) ord EXPLAIN select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2) and exists(select 1 from t2 where t1.c1 = t2.c1) order by 1; Query Plan -============================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------- -|0 |SORT | |3 |2033 | -|1 |└─SUBPLAN FILTER | |3 |2033 | -|2 | ├─PX COORDINATOR | |5 |7 | -|3 | │ └─EXCHANGE OUT DISTR |:EX10000|5 |7 | -|4 | │ └─PX BLOCK ITERATOR| |5 |6 | -|5 | │ └─TABLE FULL SCAN|t1 |5 |6 | -|6 | ├─PX COORDINATOR | |5 |6 | -|7 | │ └─EXCHANGE OUT DISTR |:EX20000|5 |6 | -|8 | │ └─PX BLOCK ITERATOR| |5 |6 | -|9 | │ └─TABLE FULL SCAN|t2 |5 |6 | -|10| └─PX COORDINATOR | |1 |6 | -|11| └─EXCHANGE OUT DISTR |:EX30000|1 |6 | -|12| └─PX BLOCK ITERATOR| |1 |6 | -|13| └─TABLE FULL SCAN|t2 |1 |6 | -============================================================= +=================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------------------- +|0 |SORT | |3 |461 | +|1 |└─SUBPLAN FILTER | |3 |461 | +|2 | ├─PX COORDINATOR | |5 |7 | +|3 | │ └─EXCHANGE OUT DISTR |:EX10000|5 |7 | +|4 | │ └─PX BLOCK ITERATOR | |5 |6 | +|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | +|6 | ├─PX COORDINATOR | |5 |6 | +|7 | │ └─EXCHANGE OUT DISTR |:EX20000|5 |6 | +|8 | │ └─PX BLOCK ITERATOR | |5 |6 | +|9 | │ └─TABLE FULL SCAN |t2 |5 |6 | +|10| └─DISTRIBUTED TABLE FULL SCAN|t2 |1 |90 | +=================================================================== Outputs & filters: ------------------------------------- 0 - output([t1.c1]), filter(nil), rowset=16 @@ -934,11 +931,7 @@ Outputs & filters: access(nil), partitions(p[0-4]) is_index_back=false, is_global_index=false, range_key([t2.__pk_increment]), range(MIN ; MAX)always true - 10 - output([1]), filter(nil), rowset=16 - 11 - output(nil), filter(nil), rowset=16 - dop=2 - 12 - output(nil), filter(nil), rowset=16 - 13 - output(nil), filter([:0 = t2.c1]), rowset=16 + 10 - output([1]), filter([:0 = t2.c1]), rowset=16 access([t2.c1]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.__pk_increment]), range(MIN ; MAX)always true @@ -960,13 +953,13 @@ Query Plan =============================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------- -|0 |PX COORDINATOR MERGE SORT | |3 |20 | -|1 |└─EXCHANGE OUT DISTR |:EX10000|3 |20 | -|2 | └─SORT | |3 |19 | -|3 | └─PX PARTITION ITERATOR| |3 |19 | -|4 | └─SUBPLAN FILTER | |3 |19 | +|0 |PX COORDINATOR MERGE SORT | |3 |119 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|3 |118 | +|2 | └─SORT | |3 |118 | +|3 | └─PX PARTITION ITERATOR| |3 |118 | +|4 | └─SUBPLAN FILTER | |3 |118 | |5 | ├─TABLE FULL SCAN |t1 |5 |6 | -|6 | └─TABLE FULL SCAN |t2 |1 |6 | +|6 | └─TABLE FULL SCAN |t2 |1 |45 | =============================================================== Outputs & filters: ------------------------------------- @@ -1005,14 +998,14 @@ Query Plan =============================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------- -|0 |PX COORDINATOR MERGE SORT | |2 |33 | -|1 |└─EXCHANGE OUT DISTR |:EX10000|2 |33 | -|2 | └─SORT | |2 |33 | -|3 | └─PX PARTITION ITERATOR| |2 |33 | -|4 | └─SUBPLAN FILTER | |2 |33 | +|0 |PX COORDINATOR MERGE SORT | |2 |230 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|2 |230 | +|2 | └─SORT | |2 |230 | +|3 | └─PX PARTITION ITERATOR| |2 |230 | +|4 | └─SUBPLAN FILTER | |2 |230 | |5 | ├─TABLE FULL SCAN |t1 |5 |6 | -|6 | ├─TABLE FULL SCAN |t2 |1 |6 | -|7 | └─TABLE FULL SCAN |t2 |1 |6 | +|6 | ├─TABLE FULL SCAN |t2 |1 |45 | +|7 | └─TABLE FULL SCAN |t2 |1 |45 | =============================================================== Outputs & filters: ------------------------------------- @@ -1053,51 +1046,38 @@ select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2 wher EXPLAIN select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2 where t1.c1 = t2.c1) and exists(select 1 from t3 where t1.c1 = t3.c1) order by 1; Query Plan -============================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------- -|0 |SORT | |2 |4042 | -|1 |└─SUBPLAN FILTER | |2 |4042 | -|2 | ├─PX COORDINATOR | |5 |7 | -|3 | │ └─EXCHANGE OUT DISTR |:EX10000|5 |7 | -|4 | │ └─PX BLOCK ITERATOR| |5 |6 | -|5 | │ └─TABLE FULL SCAN|t1 |5 |6 | -|6 | ├─PX COORDINATOR | |1 |6 | -|7 | │ └─EXCHANGE OUT DISTR |:EX20000|1 |6 | -|8 | │ └─PX BLOCK ITERATOR| |1 |6 | -|9 | │ └─TABLE FULL SCAN|t2 |1 |6 | -|10| └─PX COORDINATOR | |1 |5 | -|11| └─EXCHANGE OUT DISTR |:EX30000|1 |5 | -|12| └─PX BLOCK ITERATOR| |1 |5 | -|13| └─TABLE FULL SCAN|t3 |1 |5 | -============================================================= +======================================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +----------------------------------------------------------------------- +|0 |PX COORDINATOR MERGE SORT | |2 |410 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|2 |409 | +|2 | └─SORT | |2 |409 | +|3 | └─SUBPLAN FILTER | |2 |409 | +|4 | ├─PX BLOCK ITERATOR | |5 |6 | +|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | +|6 | ├─DISTRIBUTED TABLE FULL SCAN|t2 |1 |90 | +|7 | └─DISTRIBUTED TABLE FULL SCAN|t3 |1 |72 | +======================================================================= Outputs & filters: ------------------------------------- - 0 - output([t1.c1]), filter(nil), rowset=16 + 0 - output([INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 sort_keys([t1.c1, ASC]) - 1 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))], [(T_OP_EXISTS, subquery(2))]), rowset=16 - exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 2 - output([t1.c1]), filter(nil), rowset=16 - 3 - output([t1.c1]), filter(nil), rowset=16 + 1 - output([t1.c1], [INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 dop=2 + 2 - output([t1.c1]), filter(nil), rowset=16 + sort_keys([t1.c1, ASC]) + 3 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))], [(T_OP_EXISTS, subquery(2))]), rowset=16 + exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 4 - output([t1.c1]), filter(nil), rowset=16 5 - output([t1.c1]), filter(nil), rowset=16 access([t1.c1]), partitions(p[0-4]) is_index_back=false, is_global_index=false, range_key([t1.__pk_increment]), range(MIN ; MAX)always true - 6 - output([1]), filter(nil), rowset=16 - 7 - output(nil), filter(nil), rowset=16 - dop=2 - 8 - output(nil), filter(nil), rowset=16 - 9 - output(nil), filter([:0 = t2.c1]), rowset=16 + 6 - output([1]), filter([:0 = t2.c1]), rowset=16 access([t2.c1]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.__pk_increment]), range(MIN ; MAX)always true - 10 - output([1]), filter(nil), rowset=16 - 11 - output(nil), filter(nil), rowset=16 - dop=2 - 12 - output(nil), filter(nil), rowset=16 - 13 - output(nil), filter([:1 = t3.c1]), rowset=16 + 7 - output([1]), filter([:1 = t3.c1]), rowset=16 access([t3.c1]), partitions(p[0-3]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t3.__pk_increment]), range(MIN ; MAX)always true @@ -1118,16 +1098,16 @@ Query Plan ======================================================================= |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ----------------------------------------------------------------------- -|0 |PX COORDINATOR MERGE SORT | |3 |23 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|3 |22 | -|2 | └─SORT | |3 |22 | -|3 | └─SUBPLAN FILTER | |3 |22 | +|0 |PX COORDINATOR MERGE SORT | |3 |121 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|3 |121 | +|2 | └─SORT | |3 |120 | +|3 | └─SUBPLAN FILTER | |3 |120 | |4 | ├─EXCHANGE IN DISTR | |5 |8 | |5 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|5 |8 | |6 | │ └─PX BLOCK ITERATOR | |5 |6 | |7 | │ └─TABLE FULL SCAN |t1 |5 |6 | -|8 | └─PX PARTITION ITERATOR | |1 |6 | -|9 | └─TABLE FULL SCAN |t2 |1 |6 | +|8 | └─PX PARTITION ITERATOR | |1 |45 | +|9 | └─TABLE FULL SCAN |t2 |1 |45 | ======================================================================= Outputs & filters: ------------------------------------- @@ -1167,68 +1147,48 @@ select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2 wher EXPLAIN select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2, t3 where t1.c1 = t2.c1) and exists(select 1 from t2 where t1.c2 = t2.c1) order by 1; Query Plan -============================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------------- -|0 |SORT | |2 |4044 | -|1 |└─SUBPLAN FILTER | |2 |4044 | -|2 | ├─PX COORDINATOR | |5 |9 | -|3 | │ └─EXCHANGE OUT DISTR |:EX10000|5 |8 | -|4 | │ └─PX BLOCK ITERATOR | |5 |6 | -|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | -|6 | ├─PX COORDINATOR | |5 |5 | -|7 | │ └─EXCHANGE OUT DISTR |:EX20001|5 |5 | -|8 | │ └─NESTED-LOOP JOIN CARTESIAN | |5 |5 | -|9 | │ ├─EXCHANGE IN DISTR | |5 |5 | -|10| │ │ └─EXCHANGE OUT DISTR (BROADCAST)|:EX20000|5 |5 | -|11| │ │ └─PX BLOCK ITERATOR | |5 |5 | -|12| │ │ └─TABLE FULL SCAN |t3 |5 |5 | -|13| │ └─MATERIAL | |1 |6 | -|14| │ └─PX BLOCK ITERATOR | |1 |6 | -|15| │ └─TABLE FULL SCAN |t2 |1 |6 | -|16| └─PX COORDINATOR | |1 |6 | -|17| └─EXCHANGE OUT DISTR |:EX30000|1 |6 | -|18| └─PX BLOCK ITERATOR | |1 |6 | -|19| └─TABLE FULL SCAN |t2 |1 |6 | -============================================================================== +=========================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +--------------------------------------------------------------------------- +|0 |PX COORDINATOR MERGE SORT | |2 |455 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|2 |455 | +|2 | └─SORT | |2 |454 | +|3 | └─SUBPLAN FILTER | |2 |454 | +|4 | ├─PX BLOCK ITERATOR | |5 |6 | +|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | +|6 | ├─NESTED-LOOP JOIN CARTESIAN | |5 |90 | +|7 | │ ├─DISTRIBUTED TABLE FULL SCAN |t2 |1 |90 | +|8 | │ └─MATERIAL | |5 |72 | +|9 | │ └─DISTRIBUTED TABLE FULL SCAN|t3 |5 |72 | +|10| └─DISTRIBUTED TABLE FULL SCAN |t2 |1 |90 | +=========================================================================== Outputs & filters: ------------------------------------- - 0 - output([t1.c1]), filter(nil), rowset=16 + 0 - output([INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 sort_keys([t1.c1, ASC]) - 1 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))], [(T_OP_EXISTS, subquery(2))]), rowset=16 - exec_params_([t1.c1(:0)], [t1.c2(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 2 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 - 3 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 + 1 - output([t1.c1], [INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 dop=2 + 2 - output([t1.c1]), filter(nil), rowset=16 + sort_keys([t1.c1, ASC]) + 3 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))], [(T_OP_EXISTS, subquery(2))]), rowset=16 + exec_params_([t1.c1(:0)], [t1.c2(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 4 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 5 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 access([t1.c1], [t1.c2]), partitions(p[0-4]) is_index_back=false, is_global_index=false, range_key([t1.__pk_increment]), range(MIN ; MAX)always true 6 - output([1]), filter(nil), rowset=16 - 7 - output(nil), filter(nil), rowset=16 - dop=2 - 8 - output(nil), filter(nil), rowset=16 conds(nil), nl_params_(nil), use_batch=false - 9 - output(nil), filter(nil), rowset=16 - 10 - output(nil), filter(nil), rowset=16 - dop=2 - 11 - output(nil), filter(nil), rowset=16 - 12 - output(nil), filter(nil), rowset=16 - access(nil), partitions(p[0-3]) - is_index_back=false, is_global_index=false, - range_key([t3.__pk_increment]), range(MIN ; MAX)always true - 13 - output(nil), filter(nil), rowset=16 - 14 - output(nil), filter(nil), rowset=16 - 15 - output(nil), filter([:0 = t2.c1]), rowset=16 + 7 - output(nil), filter([:0 = t2.c1]), rowset=16 access([t2.c1]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.__pk_increment]), range(MIN ; MAX)always true - 16 - output([1]), filter(nil), rowset=16 - 17 - output(nil), filter(nil), rowset=16 - dop=2 - 18 - output(nil), filter(nil), rowset=16 - 19 - output(nil), filter([:1 = t2.c1]), rowset=16 + 8 - output(nil), filter(nil), rowset=16 + 9 - output(nil), filter(nil), rowset=16 + access(nil), partitions(p[0-3]) + is_index_back=false, is_global_index=false, + range_key([t3.__pk_increment]), range(MIN ; MAX)always true + 10 - output([1]), filter([:1 = t2.c1]), rowset=16 access([t2.c1]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.__pk_increment]), range(MIN ; MAX)always true @@ -1248,80 +1208,53 @@ EXPLAIN select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from and exists(select 1 from t2 where t1.c2 = t2.c1) and exists(select 1 from t2 where t1.c2 = t2.c1) order by 1; Query Plan -============================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------------- -|0 |SORT | |2 |6064 | -|1 |└─SUBPLAN FILTER | |2 |6064 | -|2 | ├─PX COORDINATOR | |5 |9 | -|3 | │ └─EXCHANGE OUT DISTR |:EX10000|5 |8 | -|4 | │ └─PX BLOCK ITERATOR | |5 |6 | -|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | -|6 | ├─PX COORDINATOR | |5 |5 | -|7 | │ └─EXCHANGE OUT DISTR |:EX20001|5 |5 | -|8 | │ └─NESTED-LOOP JOIN CARTESIAN | |5 |5 | -|9 | │ ├─EXCHANGE IN DISTR | |5 |5 | -|10| │ │ └─EXCHANGE OUT DISTR (BROADCAST)|:EX20000|5 |5 | -|11| │ │ └─PX BLOCK ITERATOR | |5 |5 | -|12| │ │ └─TABLE FULL SCAN |t3 |5 |5 | -|13| │ └─MATERIAL | |1 |6 | -|14| │ └─PX BLOCK ITERATOR | |1 |6 | -|15| │ └─TABLE FULL SCAN |t2 |1 |6 | -|16| ├─PX COORDINATOR | |1 |6 | -|17| │ └─EXCHANGE OUT DISTR |:EX30000|1 |6 | -|18| │ └─PX BLOCK ITERATOR | |1 |6 | -|19| │ └─TABLE FULL SCAN |t2 |1 |6 | -|20| └─PX COORDINATOR | |1 |6 | -|21| └─EXCHANGE OUT DISTR |:EX40000|1 |6 | -|22| └─PX BLOCK ITERATOR | |1 |6 | -|23| └─TABLE FULL SCAN |t2 |1 |6 | -============================================================================== +=========================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +--------------------------------------------------------------------------- +|0 |PX COORDINATOR MERGE SORT | |2 |679 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|2 |679 | +|2 | └─SORT | |2 |678 | +|3 | └─SUBPLAN FILTER | |2 |678 | +|4 | ├─PX BLOCK ITERATOR | |5 |6 | +|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | +|6 | ├─NESTED-LOOP JOIN CARTESIAN | |5 |90 | +|7 | │ ├─DISTRIBUTED TABLE FULL SCAN |t2 |1 |90 | +|8 | │ └─MATERIAL | |5 |72 | +|9 | │ └─DISTRIBUTED TABLE FULL SCAN|t3 |5 |72 | +|10| ├─DISTRIBUTED TABLE FULL SCAN |t2 |1 |90 | +|11| └─DISTRIBUTED TABLE FULL SCAN |t2 |1 |90 | +=========================================================================== Outputs & filters: ------------------------------------- - 0 - output([t1.c1]), filter(nil), rowset=16 + 0 - output([INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 sort_keys([t1.c1, ASC]) - 1 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))], [(T_OP_EXISTS, subquery(2))], [(T_OP_EXISTS, subquery(3))]), rowset=16 - exec_params_([t1.c1(:0)], [t1.c2(:1)], [t1.c2(:2)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 2 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 - 3 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 + 1 - output([t1.c1], [INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 dop=2 + 2 - output([t1.c1]), filter(nil), rowset=16 + sort_keys([t1.c1, ASC]) + 3 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))], [(T_OP_EXISTS, subquery(2))], [(T_OP_EXISTS, subquery(3))]), rowset=16 + exec_params_([t1.c1(:0)], [t1.c2(:1)], [t1.c2(:2)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 4 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 5 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 access([t1.c1], [t1.c2]), partitions(p[0-4]) is_index_back=false, is_global_index=false, range_key([t1.__pk_increment]), range(MIN ; MAX)always true 6 - output([1]), filter(nil), rowset=16 - 7 - output(nil), filter(nil), rowset=16 - dop=2 - 8 - output(nil), filter(nil), rowset=16 conds(nil), nl_params_(nil), use_batch=false + 7 - output(nil), filter([:0 = t2.c1]), rowset=16 + access([t2.c1]), partitions(p[0-4]) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([t2.__pk_increment]), range(MIN ; MAX)always true + 8 - output(nil), filter(nil), rowset=16 9 - output(nil), filter(nil), rowset=16 - 10 - output(nil), filter(nil), rowset=16 - dop=2 - 11 - output(nil), filter(nil), rowset=16 - 12 - output(nil), filter(nil), rowset=16 access(nil), partitions(p[0-3]) is_index_back=false, is_global_index=false, range_key([t3.__pk_increment]), range(MIN ; MAX)always true - 13 - output(nil), filter(nil), rowset=16 - 14 - output(nil), filter(nil), rowset=16 - 15 - output(nil), filter([:0 = t2.c1]), rowset=16 + 10 - output([1]), filter([:1 = t2.c1]), rowset=16 access([t2.c1]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.__pk_increment]), range(MIN ; MAX)always true - 16 - output([1]), filter(nil), rowset=16 - 17 - output(nil), filter(nil), rowset=16 - dop=2 - 18 - output(nil), filter(nil), rowset=16 - 19 - output(nil), filter([:1 = t2.c1]), rowset=16 - access([t2.c1]), partitions(p[0-4]) - is_index_back=false, is_global_index=false, filter_before_indexback[false], - range_key([t2.__pk_increment]), range(MIN ; MAX)always true - 20 - output([1]), filter(nil), rowset=16 - 21 - output(nil), filter(nil), rowset=16 - dop=2 - 22 - output(nil), filter(nil), rowset=16 - 23 - output(nil), filter([:2 = t2.c1]), rowset=16 + 11 - output([1]), filter([:2 = t2.c1]), rowset=16 access([t2.c1]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.__pk_increment]), range(MIN ; MAX)always true @@ -1341,51 +1274,38 @@ select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2, t3 EXPLAIN select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2 where t1.c1 = t2.c1) and exists(select 1 from t3 where t1.c2 = t3.c1) order by 1; Query Plan -============================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------- -|0 |SORT | |2 |4043 | -|1 |└─SUBPLAN FILTER | |2 |4043 | -|2 | ├─PX COORDINATOR | |5 |9 | -|3 | │ └─EXCHANGE OUT DISTR |:EX10000|5 |8 | -|4 | │ └─PX BLOCK ITERATOR| |5 |6 | -|5 | │ └─TABLE FULL SCAN|t1 |5 |6 | -|6 | ├─PX COORDINATOR | |1 |6 | -|7 | │ └─EXCHANGE OUT DISTR |:EX20000|1 |6 | -|8 | │ └─PX BLOCK ITERATOR| |1 |6 | -|9 | │ └─TABLE FULL SCAN|t2 |1 |6 | -|10| └─PX COORDINATOR | |1 |5 | -|11| └─EXCHANGE OUT DISTR |:EX30000|1 |5 | -|12| └─PX BLOCK ITERATOR| |1 |5 | -|13| └─TABLE FULL SCAN|t3 |1 |5 | -============================================================= +======================================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +----------------------------------------------------------------------- +|0 |PX COORDINATOR MERGE SORT | |2 |410 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|2 |409 | +|2 | └─SORT | |2 |409 | +|3 | └─SUBPLAN FILTER | |2 |409 | +|4 | ├─PX BLOCK ITERATOR | |5 |6 | +|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | +|6 | ├─DISTRIBUTED TABLE FULL SCAN|t2 |1 |90 | +|7 | └─DISTRIBUTED TABLE FULL SCAN|t3 |1 |72 | +======================================================================= Outputs & filters: ------------------------------------- - 0 - output([t1.c1]), filter(nil), rowset=16 + 0 - output([INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 sort_keys([t1.c1, ASC]) - 1 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))], [(T_OP_EXISTS, subquery(2))]), rowset=16 - exec_params_([t1.c1(:0)], [t1.c2(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 2 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 - 3 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 + 1 - output([t1.c1], [INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 dop=2 + 2 - output([t1.c1]), filter(nil), rowset=16 + sort_keys([t1.c1, ASC]) + 3 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))], [(T_OP_EXISTS, subquery(2))]), rowset=16 + exec_params_([t1.c1(:0)], [t1.c2(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 4 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 5 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 access([t1.c1], [t1.c2]), partitions(p[0-4]) is_index_back=false, is_global_index=false, range_key([t1.__pk_increment]), range(MIN ; MAX)always true - 6 - output([1]), filter(nil), rowset=16 - 7 - output(nil), filter(nil), rowset=16 - dop=2 - 8 - output(nil), filter(nil), rowset=16 - 9 - output(nil), filter([:0 = t2.c1]), rowset=16 + 6 - output([1]), filter([:0 = t2.c1]), rowset=16 access([t2.c1]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.__pk_increment]), range(MIN ; MAX)always true - 10 - output([1]), filter(nil), rowset=16 - 11 - output(nil), filter(nil), rowset=16 - dop=2 - 12 - output(nil), filter(nil), rowset=16 - 13 - output(nil), filter([:1 = t3.c1]), rowset=16 + 7 - output([1]), filter([:1 = t3.c1]), rowset=16 access([t3.c1]), partitions(p[0-3]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t3.__pk_increment]), range(MIN ; MAX)always true @@ -1406,18 +1326,18 @@ Query Plan ======================================================================= |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ----------------------------------------------------------------------- -|0 |PX COORDINATOR MERGE SORT | |2 |30 | -|1 |└─EXCHANGE OUT DISTR |:EX10001|2 |30 | -|2 | └─SORT | |2 |30 | -|3 | └─SUBPLAN FILTER | |2 |30 | +|0 |PX COORDINATOR MERGE SORT | |2 |188 | +|1 |└─EXCHANGE OUT DISTR |:EX10001|2 |188 | +|2 | └─SORT | |2 |188 | +|3 | └─SUBPLAN FILTER | |2 |188 | |4 | ├─EXCHANGE IN DISTR | |5 |8 | |5 | │ └─EXCHANGE OUT DISTR (PKEY)|:EX10000|5 |8 | |6 | │ └─PX BLOCK ITERATOR | |5 |6 | |7 | │ └─TABLE FULL SCAN |t1 |5 |6 | -|8 | ├─PX PARTITION ITERATOR | |1 |5 | -|9 | │ └─TABLE FULL SCAN |t4 |1 |5 | -|10| └─PX PARTITION ITERATOR | |1 |5 | -|11| └─TABLE FULL SCAN |t3 |1 |5 | +|8 | ├─PX PARTITION ITERATOR | |1 |36 | +|9 | │ └─TABLE FULL SCAN |t4 |1 |36 | +|10| └─PX PARTITION ITERATOR | |1 |36 | +|11| └─TABLE FULL SCAN |t3 |1 |36 | ======================================================================= Outputs & filters: ------------------------------------- @@ -1463,46 +1383,36 @@ select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t4 wher ##bc2host EXPLAIN select /*+no_rewrite parallel(2)*/ (select c1 from t1 where t1.c1 = t2.c1 order by c2 limit 1) as ref0 from t2 order by 1; Query Plan -==================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |SORT | |5 |2028 | -|1 |└─SUBPLAN FILTER | |5 |2027 | -|2 | ├─PX COORDINATOR | |5 |7 | -|3 | │ └─EXCHANGE OUT DISTR |:EX10000|5 |7 | -|4 | │ └─PX BLOCK ITERATOR | |5 |6 | -|5 | │ └─TABLE FULL SCAN |t2 |5 |6 | -|6 | └─LIMIT | |1 |6 | -|7 | └─PX COORDINATOR MERGE SORT | |1 |6 | -|8 | └─EXCHANGE OUT DISTR |:EX20000|1 |6 | -|9 | └─TOP-N SORT | |1 |6 | -|10| └─PX BLOCK ITERATOR | |1 |6 | -|11| └─TABLE FULL SCAN |t1 |1 |6 | -==================================================================== +========================================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------------------------- +|0 |PX COORDINATOR MERGE SORT | |5 |232 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|5 |231 | +|2 | └─SORT | |5 |230 | +|3 | └─SUBPLAN FILTER | |5 |230 | +|4 | ├─PX BLOCK ITERATOR | |5 |6 | +|5 | │ └─TABLE FULL SCAN |t2 |5 |6 | +|6 | └─TOP-N SORT | |1 |90 | +|7 | └─DISTRIBUTED TABLE FULL SCAN|t1 |1 |90 | +========================================================================= Outputs & filters: ------------------------------------- - 0 - output([subquery(1)]), filter(nil), rowset=16 + 0 - output([INTERNAL_FUNCTION(subquery(1))]), filter(nil), rowset=16 sort_keys([subquery(1), ASC]) - 1 - output([subquery(1)]), filter(nil), rowset=16 - exec_params_([t2.c1(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 2 - output([t2.c1]), filter(nil), rowset=16 - 3 - output([t2.c1]), filter(nil), rowset=16 + 1 - output([subquery(1)], [INTERNAL_FUNCTION(subquery(1))]), filter(nil), rowset=16 dop=2 + 2 - output([subquery(1)]), filter(nil), rowset=16 + sort_keys([subquery(1), ASC]) + 3 - output([subquery(1)]), filter(nil), rowset=16 + exec_params_([t2.c1(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 4 - output([t2.c1]), filter(nil), rowset=16 5 - output([t2.c1]), filter(nil), rowset=16 access([t2.c1]), partitions(p[0-4]) is_index_back=false, is_global_index=false, range_key([t2.__pk_increment]), range(MIN ; MAX)always true 6 - output([t1.c1]), filter(nil), rowset=16 - limit(1), offset(nil) - 7 - output([t1.c1]), filter(nil), rowset=16 - sort_keys([t1.c2, ASC]) - 8 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 - dop=2 - 9 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 sort_keys([t1.c2, ASC]), topn(1) - 10 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 - 11 - output([t1.c1], [t1.c2]), filter([t1.c1 = :0]), rowset=16 + 7 - output([t1.c1], [t1.c2]), filter([t1.c1 = :0]), rowset=16 access([t1.c1], [t1.c2]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t1.__pk_increment]), range(MIN ; MAX)always true @@ -1519,39 +1429,33 @@ select /*+no_rewrite parallel(2)*/ (select c1 from t1 where t1.c1 = t2.c1 order EXPLAIN select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2 where t1.c2 = t2.c2) order by 1; Query Plan -============================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------- -|0 |SORT | |3 |2029 | -|1 |└─SUBPLAN FILTER | |3 |2029 | -|2 | ├─PX COORDINATOR | |5 |9 | -|3 | │ └─EXCHANGE OUT DISTR |:EX10000|5 |8 | -|4 | │ └─PX BLOCK ITERATOR| |5 |6 | -|5 | │ └─TABLE FULL SCAN|t1 |5 |6 | -|6 | └─PX COORDINATOR | |1 |6 | -|7 | └─EXCHANGE OUT DISTR |:EX20000|1 |6 | -|8 | └─PX BLOCK ITERATOR| |1 |6 | -|9 | └─TABLE FULL SCAN|t2 |1 |6 | -============================================================= +======================================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +----------------------------------------------------------------------- +|0 |PX COORDINATOR MERGE SORT | |3 |231 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|3 |230 | +|2 | └─SORT | |3 |230 | +|3 | └─SUBPLAN FILTER | |3 |230 | +|4 | ├─PX BLOCK ITERATOR | |5 |6 | +|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | +|6 | └─DISTRIBUTED TABLE FULL SCAN|t2 |1 |90 | +======================================================================= Outputs & filters: ------------------------------------- - 0 - output([t1.c1]), filter(nil), rowset=16 + 0 - output([INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 sort_keys([t1.c1, ASC]) - 1 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))]), rowset=16 - exec_params_([t1.c2(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 2 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 - 3 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 + 1 - output([t1.c1], [INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 dop=2 + 2 - output([t1.c1]), filter(nil), rowset=16 + sort_keys([t1.c1, ASC]) + 3 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))]), rowset=16 + exec_params_([t1.c2(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 4 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 5 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 access([t1.c1], [t1.c2]), partitions(p[0-4]) is_index_back=false, is_global_index=false, range_key([t1.__pk_increment]), range(MIN ; MAX)always true - 6 - output([1]), filter(nil), rowset=16 - 7 - output(nil), filter(nil), rowset=16 - dop=2 - 8 - output(nil), filter(nil), rowset=16 - 9 - output(nil), filter([:0 = t2.c2]), rowset=16 + 6 - output([1]), filter([:0 = t2.c2]), rowset=16 access([t2.c2]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.__pk_increment]), range(MIN ; MAX)always true @@ -1568,44 +1472,34 @@ select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2 wher EXPLAIN select /*+no_rewrite parallel(2)*/ c1 from t1 where exists(select 1 from t2, t3, t4 where t1.c2 = t2.c2 group by t1.c1) order by 1; Query Plan -====================================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------------------------- -|0 |SORT | |3 |2025 | -|1 |└─SUBPLAN FILTER | |3 |2025 | -|2 | ├─PX COORDINATOR | |5 |9 | -|3 | │ └─EXCHANGE OUT DISTR |:EX10000|5 |8 | -|4 | │ └─PX BLOCK ITERATOR | |5 |6 | -|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | -|6 | └─MERGE GROUP BY | |1 |5 | -|7 | └─PX COORDINATOR | |2 |5 | -|8 | └─EXCHANGE OUT DISTR |:EX20002|2 |5 | -|9 | └─MERGE GROUP BY | |2 |5 | -|10| └─NESTED-LOOP JOIN CARTESIAN | |25 |5 | -|11| ├─MATERIAL | |5 |5 | -|12| │ └─NESTED-LOOP JOIN CARTESIAN | |5 |5 | -|13| │ ├─EXCHANGE IN DISTR | |5 |5 | -|14| │ │ └─EXCHANGE OUT DISTR (BROADCAST)|:EX20000|5 |5 | -|15| │ │ └─PX BLOCK ITERATOR | |5 |5 | -|16| │ │ └─TABLE FULL SCAN |t3 |5 |5 | -|17| │ └─MATERIAL | |1 |6 | -|18| │ └─PX BLOCK ITERATOR | |1 |6 | -|19| │ └─TABLE FULL SCAN |t2 |1 |6 | -|20| └─MATERIAL | |5 |5 | -|21| └─EXCHANGE IN DISTR | |5 |5 | -|22| └─EXCHANGE OUT DISTR (BROADCAST) |:EX20001|5 |5 | -|23| └─PX BLOCK ITERATOR | |5 |5 | -|24| └─TABLE FULL SCAN |t4 |5 |5 | -====================================================================================== +=============================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------------------------------- +|0 |PX COORDINATOR MERGE SORT | |3 |233 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|3 |233 | +|2 | └─SORT | |3 |232 | +|3 | └─SUBPLAN FILTER | |3 |232 | +|4 | ├─PX BLOCK ITERATOR | |5 |6 | +|5 | │ └─TABLE FULL SCAN |t1 |5 |6 | +|6 | └─MERGE GROUP BY | |1 |91 | +|7 | └─NESTED-LOOP JOIN CARTESIAN | |25 |91 | +|8 | ├─NESTED-LOOP JOIN CARTESIAN | |5 |90 | +|9 | │ ├─DISTRIBUTED TABLE FULL SCAN |t2 |1 |90 | +|10| │ └─MATERIAL | |5 |72 | +|11| │ └─DISTRIBUTED TABLE FULL SCAN|t3 |5 |72 | +|12| └─MATERIAL | |5 |72 | +|13| └─DISTRIBUTED TABLE FULL SCAN |t4 |5 |72 | +=============================================================================== Outputs & filters: ------------------------------------- - 0 - output([t1.c1]), filter(nil), rowset=16 + 0 - output([INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 sort_keys([t1.c1, ASC]) - 1 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))]), rowset=16 - exec_params_([t1.c2(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 2 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 - 3 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 + 1 - output([t1.c1], [INTERNAL_FUNCTION(t1.c1)]), filter(nil), rowset=16 dop=2 + 2 - output([t1.c1]), filter(nil), rowset=16 + sort_keys([t1.c1, ASC]) + 3 - output([t1.c1]), filter([(T_OP_EXISTS, subquery(1))]), rowset=16 + exec_params_([t1.c2(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 4 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 5 - output([t1.c1], [t1.c2]), filter(nil), rowset=16 access([t1.c1], [t1.c2]), partitions(p[0-4]) @@ -1614,35 +1508,20 @@ Outputs & filters: 6 - output([1]), filter(nil), rowset=16 group(nil), agg_func(nil) 7 - output(nil), filter(nil), rowset=16 + conds(nil), nl_params_(nil), use_batch=false 8 - output(nil), filter(nil), rowset=16 - dop=2 - 9 - output(nil), filter(nil), rowset=16 - group(nil), agg_func(nil) - 10 - output(nil), filter(nil), rowset=16 conds(nil), nl_params_(nil), use_batch=false - 11 - output(nil), filter(nil), rowset=16 - 12 - output(nil), filter(nil), rowset=16 - conds(nil), nl_params_(nil), use_batch=false - 13 - output(nil), filter(nil), rowset=16 - 14 - output(nil), filter(nil), rowset=16 - dop=2 - 15 - output(nil), filter(nil), rowset=16 - 16 - output(nil), filter(nil), rowset=16 - access(nil), partitions(p[0-3]) - is_index_back=false, is_global_index=false, - range_key([t3.__pk_increment]), range(MIN ; MAX)always true - 17 - output(nil), filter(nil), rowset=16 - 18 - output(nil), filter(nil), rowset=16 - 19 - output(nil), filter([:0 = t2.c2]), rowset=16 + 9 - output(nil), filter([:0 = t2.c2]), rowset=16 access([t2.c2]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.__pk_increment]), range(MIN ; MAX)always true - 20 - output(nil), filter(nil), rowset=16 - 21 - output(nil), filter(nil), rowset=16 - 22 - output(nil), filter(nil), rowset=16 - dop=2 - 23 - output(nil), filter(nil), rowset=16 - 24 - output(nil), filter(nil), rowset=16 + 10 - output(nil), filter(nil), rowset=16 + 11 - output(nil), filter(nil), rowset=16 + access(nil), partitions(p[0-3]) + is_index_back=false, is_global_index=false, + range_key([t3.__pk_increment]), range(MIN ; MAX)always true + 12 - output(nil), filter(nil), rowset=16 + 13 - output(nil), filter(nil), rowset=16 access(nil), partitions(p[0-3]) is_index_back=false, is_global_index=false, range_key([t4.__pk_increment]), range(MIN ; MAX)always true @@ -1718,12 +1597,12 @@ Query Plan ====================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |18 |337 | -|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |334 | -|2 | └─SUBPLAN FILTER | |18 |328 | +|0 |PX COORDINATOR | |18 |290 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |287 | +|2 | └─SUBPLAN FILTER | |18 |281 | |3 | ├─PX PARTITION ITERATOR | |18 |5 | |4 | │ └─TABLE FULL SCAN |t1 |18 |5 | -|5 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | +|5 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | ====================================================================== Outputs & filters: ------------------------------------- @@ -1775,7 +1654,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -1787,7 +1666,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: @@ -1819,23 +1698,23 @@ select c1,c1 in (select c1 from t2 where t2.c1 >= t1.c1) as x from t1; +----+---+ EXPLAIN EXTENDED_NOADDR select c1, (select c1 from t2 where t2.c1 >= t1.c1 and t2.c2 > t1.c3 limit 1) as x from t1; Query Plan -====================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ----------------------------------------------------------------------- -|0 |PX COORDINATOR | |18 |346 | -|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |341 | -|2 | └─SUBPLAN FILTER | |18 |328 | -|3 | ├─PX PARTITION ITERATOR | |18 |6 | -|4 | │ └─TABLE FULL SCAN |t1 |18 |6 | -|5 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |1 |18 | -====================================================================== +=============================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +--------------------------------------------------------------- +|0 |SUBPLAN FILTER | |18 |346 | +|1 |├─PX COORDINATOR | |18 |23 | +|2 |│ └─EXCHANGE OUT DISTR |:EX10000|18 |18 | +|3 |│ └─PX PARTITION ITERATOR| |18 |6 | +|4 |│ └─TABLE FULL SCAN |t1 |18 |6 | +|5 |└─TABLE RANGE SCAN |t2 |1 |18 | +=============================================================== Outputs & filters: ------------------------------------- - 0 - output([INTERNAL_FUNCTION(t1.c1, subquery(1))]), filter(nil), rowset=256 - 1 - output([INTERNAL_FUNCTION(t1.c1, subquery(1))]), filter(nil), rowset=256 + 0 - output([t1.c1], [subquery(1)]), filter(nil), rowset=256 + exec_params_([t1.c1(:0)], [t1.c3(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false + 1 - output([t1.c1], [t1.c3]), filter(nil), rowset=256 + 2 - output([t1.c1], [t1.c3]), filter(nil), rowset=256 dop=1 - 2 - output([t1.c1], [subquery(1)]), filter(nil), rowset=256 - exec_params_([t1.c1(:0)], [t1.c3(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true 3 - output([t1.c1], [t1.c3]), filter(nil), rowset=256 force partition granule 4 - output([t1.c1], [t1.c3]), filter(nil), rowset=256 @@ -1843,7 +1722,7 @@ Outputs & filters: is_index_back=false, is_global_index=false, range_key([t1.c1]), range(MIN ; MAX)always true 5 - output([t2.c1]), filter([t2.c2 > cast(:1, DECIMAL_INT(10, 0))]), rowset=256 - access([GROUP_ID], [t2.c1], [t2.c2]), partitions(p0) + access([t2.c1], [t2.c2]), partitions(p0) limit(1), offset(nil), is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 >= :0]) @@ -1861,10 +1740,9 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - PQ_SUBQUERY(@"SEL$1" ("SEL$2") NONE ALL) + PQ_SUBQUERY(@"SEL$1" ("SEL$2") LOCAL LOCAL) FULL(@"SEL$1" "test"."t1"@"SEL$1") FULL(@"SEL$2" "test"."t2"@"SEL$2") - USE_DAS(@"SEL$2" "test"."t2"@"SEL$2") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA */ @@ -1879,7 +1757,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -1889,13 +1767,15 @@ Optimization Info: index_back_rows:0 output_rows:4 table_dop:1 - dop_method:DAS DOP + dop_method:Table DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: DISTRIBUTED + Parameters: + :0 => 1 Note: Degree of Parallelisim is 1 because of table property select c1, (select c1 from t2 where t2.c1 >= t1.c1 and t2.c2 > t1.c3 limit 1) as x from t1; @@ -1926,12 +1806,12 @@ Query Plan =============================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------- -|0 |PX COORDINATOR | |18 |337 | -|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |334 | -|2 | └─SUBPLAN FILTER | |18 |328 | +|0 |PX COORDINATOR | |18 |290 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |287 | +|2 | └─SUBPLAN FILTER | |18 |281 | |3 | ├─PX PARTITION ITERATOR| |18 |5 | |4 | │ └─TABLE FULL SCAN |t1 |18 |5 | -|5 | └─DISTRIBUTED TABLE GET|t2 |1 |18 | +|5 | └─DISTRIBUTED TABLE GET|t2 |1 |16 | =============================================================== Outputs & filters: ------------------------------------- @@ -1983,7 +1863,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -1995,7 +1875,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: @@ -2027,24 +1907,24 @@ select c1,c1 + (select c1 from t2 where t2.c1 = t1.c1) as x from t1; +----+----+ EXPLAIN EXTENDED_NOADDR select c1,c1 in (select c1 from t2 where t2.c1 >= t1.c1) and c1 in (select c2 from t2 where t2.c1 >= t1.c1) as x from t1; Query Plan -================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------- -|0 |SUBPLAN FILTER | |18 |660 | -|1 |├─PX COORDINATOR | |18 |14 | -|2 |│ └─EXCHANGE OUT DISTR |:EX10000|18 |11 | -|3 |│ └─PX PARTITION ITERATOR | |18 |5 | -|4 |│ └─TABLE FULL SCAN |t1 |18 |5 | -|5 |├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|6 |└─TABLE RANGE SCAN |t2 |8 |18 | -================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |18 |566 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |564 | +|2 | └─SUBPLAN FILTER | |18 |557 | +|3 | ├─PX PARTITION ITERATOR | |18 |5 | +|4 | │ └─TABLE FULL SCAN |t1 |18 |5 | +|5 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|6 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +====================================================================== Outputs & filters: ------------------------------------- - 0 - output([t1.c1], [t1.c1 = ANY(subquery(1)) AND cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2))]), filter(nil), rowset=256 - exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 1 - output([t1.c1]), filter(nil), rowset=256 - 2 - output([t1.c1]), filter(nil), rowset=256 + 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) AND cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)))]), filter(nil), rowset=256 + 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) AND cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)))]), filter(nil), rowset=256 dop=1 + 2 - output([t1.c1], [t1.c1 = ANY(subquery(1))], [cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2))]), filter(nil), rowset=256 + exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true 3 - output([t1.c1]), filter(nil), rowset=256 force partition granule 4 - output([t1.c1]), filter(nil), rowset=256 @@ -2052,12 +1932,12 @@ Outputs & filters: is_index_back=false, is_global_index=false, range_key([t1.c1]), range(MIN ; MAX)always true 5 - output([t2.c1]), filter(nil), rowset=256 - access([t2.c1]), partitions(p0) + access([GROUP_ID], [t2.c1]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 >= :0]) 6 - output([t2.c2]), filter(nil), rowset=256 - access([t2.c2]), partitions(p0) + access([GROUP_ID], [t2.c2]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 >= :1]) @@ -2076,11 +1956,12 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") LOCAL LOCAL) + PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") NONE ALL) FULL(@"SEL$1" "test"."t1"@"SEL$1") FULL(@"SEL$2" "test"."t2"@"SEL$2") USE_DAS(@"SEL$2" "test"."t2"@"SEL$2") FULL(@"SEL$3" "test"."t2"@"SEL$3") + USE_DAS(@"SEL$3" "test"."t2"@"SEL$3") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA */ @@ -2095,7 +1976,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2107,7 +1988,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2117,9 +1998,9 @@ Optimization Info: index_back_rows:0 output_rows:7 table_dop:1 - dop_method:Table DOP + dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: @@ -2151,24 +2032,24 @@ select c1,c1 in (select c1 from t2 where t2.c1 >= t1.c1) and c1 in (select c2 f +----+------+ EXPLAIN EXTENDED_NOADDR select c1,c1 in (select c1 from t2 where t2.c1 >= t1.c1) or c1 in (select c2 from t2 where t2.c1 >= t1.c1) as x from t1; Query Plan -================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------- -|0 |SUBPLAN FILTER | |18 |660 | -|1 |├─PX COORDINATOR | |18 |14 | -|2 |│ └─EXCHANGE OUT DISTR |:EX10000|18 |11 | -|3 |│ └─PX PARTITION ITERATOR | |18 |5 | -|4 |│ └─TABLE FULL SCAN |t1 |18 |5 | -|5 |├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|6 |└─TABLE RANGE SCAN |t2 |8 |18 | -================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |18 |566 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |564 | +|2 | └─SUBPLAN FILTER | |18 |557 | +|3 | ├─PX PARTITION ITERATOR | |18 |5 | +|4 | │ └─TABLE FULL SCAN |t1 |18 |5 | +|5 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|6 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +====================================================================== Outputs & filters: ------------------------------------- - 0 - output([t1.c1], [t1.c1 = ANY(subquery(1)) OR cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2))]), filter(nil), rowset=256 - exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 1 - output([t1.c1]), filter(nil), rowset=256 - 2 - output([t1.c1]), filter(nil), rowset=256 + 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) OR cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)))]), filter(nil), rowset=256 + 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) OR cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)))]), filter(nil), rowset=256 dop=1 + 2 - output([t1.c1], [t1.c1 = ANY(subquery(1))], [cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2))]), filter(nil), rowset=256 + exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true 3 - output([t1.c1]), filter(nil), rowset=256 force partition granule 4 - output([t1.c1]), filter(nil), rowset=256 @@ -2176,12 +2057,12 @@ Outputs & filters: is_index_back=false, is_global_index=false, range_key([t1.c1]), range(MIN ; MAX)always true 5 - output([t2.c1]), filter(nil), rowset=256 - access([t2.c1]), partitions(p0) + access([GROUP_ID], [t2.c1]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 >= :0]) 6 - output([t2.c2]), filter(nil), rowset=256 - access([t2.c2]), partitions(p0) + access([GROUP_ID], [t2.c2]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 >= :1]) @@ -2200,11 +2081,12 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") LOCAL LOCAL) + PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") NONE ALL) FULL(@"SEL$1" "test"."t1"@"SEL$1") FULL(@"SEL$2" "test"."t2"@"SEL$2") USE_DAS(@"SEL$2" "test"."t2"@"SEL$2") FULL(@"SEL$3" "test"."t2"@"SEL$3") + USE_DAS(@"SEL$3" "test"."t2"@"SEL$3") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA */ @@ -2219,7 +2101,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2231,7 +2113,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2241,9 +2123,9 @@ Optimization Info: index_back_rows:0 output_rows:7 table_dop:1 - dop_method:Table DOP + dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: @@ -2275,24 +2157,24 @@ select c1,c1 in (select c1 from t2 where t2.c1 >= t1.c1) or c1 in (select c2 fr +----+------+ EXPLAIN EXTENDED_NOADDR select c1,c1 in (select c1 from t2 where t2.c1 <= t1.c1) and c1 in (select c2 from t2 where t2.c1 <= t1.c1) as x from t1; Query Plan -================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------- -|0 |SUBPLAN FILTER | |18 |660 | -|1 |├─PX COORDINATOR | |18 |14 | -|2 |│ └─EXCHANGE OUT DISTR |:EX10000|18 |11 | -|3 |│ └─PX PARTITION ITERATOR | |18 |5 | -|4 |│ └─TABLE FULL SCAN |t1 |18 |5 | -|5 |├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|6 |└─TABLE RANGE SCAN |t2 |8 |18 | -================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |18 |566 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |564 | +|2 | └─SUBPLAN FILTER | |18 |557 | +|3 | ├─PX PARTITION ITERATOR | |18 |5 | +|4 | │ └─TABLE FULL SCAN |t1 |18 |5 | +|5 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|6 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +====================================================================== Outputs & filters: ------------------------------------- - 0 - output([t1.c1], [t1.c1 = ANY(subquery(1)) AND cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2))]), filter(nil), rowset=256 - exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 1 - output([t1.c1]), filter(nil), rowset=256 - 2 - output([t1.c1]), filter(nil), rowset=256 + 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) AND cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)))]), filter(nil), rowset=256 + 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) AND cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)))]), filter(nil), rowset=256 dop=1 + 2 - output([t1.c1], [t1.c1 = ANY(subquery(1))], [cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2))]), filter(nil), rowset=256 + exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true 3 - output([t1.c1]), filter(nil), rowset=256 force partition granule 4 - output([t1.c1]), filter(nil), rowset=256 @@ -2300,12 +2182,12 @@ Outputs & filters: is_index_back=false, is_global_index=false, range_key([t1.c1]), range(MIN ; MAX)always true 5 - output([t2.c1]), filter(nil), rowset=256 - access([t2.c1]), partitions(p0) + access([GROUP_ID], [t2.c1]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 <= :0]) 6 - output([t2.c2]), filter(nil), rowset=256 - access([t2.c2]), partitions(p0) + access([GROUP_ID], [t2.c2]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 <= :1]) @@ -2324,11 +2206,12 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") LOCAL LOCAL) + PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") NONE ALL) FULL(@"SEL$1" "test"."t1"@"SEL$1") FULL(@"SEL$2" "test"."t2"@"SEL$2") USE_DAS(@"SEL$2" "test"."t2"@"SEL$2") FULL(@"SEL$3" "test"."t2"@"SEL$3") + USE_DAS(@"SEL$3" "test"."t2"@"SEL$3") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA */ @@ -2343,7 +2226,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2355,7 +2238,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2365,9 +2248,9 @@ Optimization Info: index_back_rows:0 output_rows:7 table_dop:1 - dop_method:Table DOP + dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: @@ -2399,24 +2282,24 @@ select c1,c1 in (select c1 from t2 where t2.c1 <= t1.c1) and c1 in (select c2 f +----+------+ EXPLAIN EXTENDED_NOADDR select c1,c1 in (select c1 from t2 where t2.c1 <= t1.c1) or c1 in (select c2 from t2 where t2.c1 <= t1.c1) as x from t1; Query Plan -================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------- -|0 |SUBPLAN FILTER | |18 |660 | -|1 |├─PX COORDINATOR | |18 |14 | -|2 |│ └─EXCHANGE OUT DISTR |:EX10000|18 |11 | -|3 |│ └─PX PARTITION ITERATOR | |18 |5 | -|4 |│ └─TABLE FULL SCAN |t1 |18 |5 | -|5 |├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|6 |└─TABLE RANGE SCAN |t2 |8 |18 | -================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |18 |566 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |564 | +|2 | └─SUBPLAN FILTER | |18 |557 | +|3 | ├─PX PARTITION ITERATOR | |18 |5 | +|4 | │ └─TABLE FULL SCAN |t1 |18 |5 | +|5 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|6 | └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +====================================================================== Outputs & filters: ------------------------------------- - 0 - output([t1.c1], [t1.c1 = ANY(subquery(1)) OR cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2))]), filter(nil), rowset=256 - exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 1 - output([t1.c1]), filter(nil), rowset=256 - 2 - output([t1.c1]), filter(nil), rowset=256 + 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) OR cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)))]), filter(nil), rowset=256 + 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) OR cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)))]), filter(nil), rowset=256 dop=1 + 2 - output([t1.c1], [t1.c1 = ANY(subquery(1))], [cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2))]), filter(nil), rowset=256 + exec_params_([t1.c1(:0)], [t1.c1(:1)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true 3 - output([t1.c1]), filter(nil), rowset=256 force partition granule 4 - output([t1.c1]), filter(nil), rowset=256 @@ -2424,12 +2307,12 @@ Outputs & filters: is_index_back=false, is_global_index=false, range_key([t1.c1]), range(MIN ; MAX)always true 5 - output([t2.c1]), filter(nil), rowset=256 - access([t2.c1]), partitions(p0) + access([GROUP_ID], [t2.c1]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 <= :0]) 6 - output([t2.c2]), filter(nil), rowset=256 - access([t2.c2]), partitions(p0) + access([GROUP_ID], [t2.c2]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 <= :1]) @@ -2448,11 +2331,12 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") LOCAL LOCAL) + PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3") NONE ALL) FULL(@"SEL$1" "test"."t1"@"SEL$1") FULL(@"SEL$2" "test"."t2"@"SEL$2") USE_DAS(@"SEL$2" "test"."t2"@"SEL$2") FULL(@"SEL$3" "test"."t2"@"SEL$3") + USE_DAS(@"SEL$3" "test"."t2"@"SEL$3") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA */ @@ -2467,7 +2351,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2479,7 +2363,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2489,9 +2373,9 @@ Optimization Info: index_back_rows:0 output_rows:7 table_dop:1 - dop_method:Table DOP + dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: @@ -2523,25 +2407,25 @@ select c1,c1 in (select c1 from t2 where t2.c1 <= t1.c1) or c1 in (select c2 fr +----+------+ EXPLAIN EXTENDED_NOADDR select c1,c1 in (select c1 from t2 where t2.c1 <= t1.c1) and c1 in (select c2 from t2 where t2.c1 <= t1.c1) or c1 + (select c1 from t2 where t2.c1 = t1.c1) as x from t1; Query Plan -================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------- -|0 |SUBPLAN FILTER | |18 |983 | -|1 |├─PX COORDINATOR | |18 |14 | -|2 |│ └─EXCHANGE OUT DISTR |:EX10000|18 |11 | -|3 |│ └─PX PARTITION ITERATOR | |18 |5 | -|4 |│ └─TABLE FULL SCAN |t1 |18 |5 | -|5 |├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|6 |├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|7 |└─TABLE GET |t2 |1 |18 | -================================================================== +====================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +---------------------------------------------------------------------- +|0 |PX COORDINATOR | |18 |842 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |839 | +|2 | └─SUBPLAN FILTER | |18 |833 | +|3 | ├─PX PARTITION ITERATOR | |18 |5 | +|4 | │ └─TABLE FULL SCAN |t1 |18 |5 | +|5 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|6 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|7 | └─DISTRIBUTED TABLE GET |t2 |1 |16 | +====================================================================== Outputs & filters: ------------------------------------- - 0 - output([t1.c1], [t1.c1 = ANY(subquery(1)) AND cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)) OR BOOL(t1.c1 + subquery(3))]), filter(nil), rowset=256 - exec_params_([t1.c1(:0)], [t1.c1(:1)], [t1.c1(:2)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 1 - output([t1.c1]), filter(nil), rowset=256 - 2 - output([t1.c1]), filter(nil), rowset=256 + 0 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) AND cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)) OR BOOL(t1.c1 + subquery(3)))]), filter(nil), rowset=256 + 1 - output([INTERNAL_FUNCTION(t1.c1, t1.c1 = ANY(subquery(1)) AND cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2)) OR BOOL(t1.c1 + subquery(3)))]), filter(nil), rowset=256 dop=1 + 2 - output([t1.c1], [t1.c1 = ANY(subquery(1))], [cast(t1.c1, DECIMAL_INT(10, 0)) = ANY(subquery(2))], [subquery(3)]), filter(nil), rowset=256 + exec_params_([t1.c1(:0)], [t1.c1(:1)], [t1.c1(:2)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true 3 - output([t1.c1]), filter(nil), rowset=256 force partition granule 4 - output([t1.c1]), filter(nil), rowset=256 @@ -2549,17 +2433,17 @@ Outputs & filters: is_index_back=false, is_global_index=false, range_key([t1.c1]), range(MIN ; MAX)always true 5 - output([t2.c1]), filter(nil), rowset=256 - access([t2.c1]), partitions(p0) + access([GROUP_ID], [t2.c1]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 <= :0]) 6 - output([t2.c2]), filter(nil), rowset=256 - access([t2.c2]), partitions(p0) + access([GROUP_ID], [t2.c2]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 <= :1]) 7 - output([t2.c1]), filter(nil), rowset=256 - access([t2.c1]), partitions(p0) + access([GROUP_ID], [t2.c1]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 = :2]) @@ -2579,13 +2463,14 @@ Outline Data: ------------------------------------- /*+ BEGIN_OUTLINE_DATA - PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3" "SEL$4") LOCAL LOCAL) + PQ_SUBQUERY(@"SEL$1" ("SEL$2" "SEL$3" "SEL$4") NONE ALL) FULL(@"SEL$1" "test"."t1"@"SEL$1") FULL(@"SEL$2" "test"."t2"@"SEL$2") USE_DAS(@"SEL$2" "test"."t2"@"SEL$2") FULL(@"SEL$3" "test"."t2"@"SEL$3") USE_DAS(@"SEL$3" "test"."t2"@"SEL$3") FULL(@"SEL$4" "test"."t2"@"SEL$4") + USE_DAS(@"SEL$4" "test"."t2"@"SEL$4") OPTIMIZER_FEATURES_ENABLE('') END_OUTLINE_DATA */ @@ -2600,7 +2485,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2612,7 +2497,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2624,7 +2509,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2634,9 +2519,9 @@ Optimization Info: index_back_rows:0 output_rows:1 table_dop:1 - dop_method:Table DOP + dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: @@ -2672,18 +2557,18 @@ Query Plan ====================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |18 |2273 | -|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |2271 | -|2 | └─SUBPLAN FILTER | |18 |2264 | +|0 |PX COORDINATOR | |18 |1946 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |1943 | +|2 | └─SUBPLAN FILTER | |18 |1937 | |3 | ├─PX PARTITION ITERATOR | |18 |5 | |4 | │ └─TABLE FULL SCAN |t1 |18 |5 | -|5 | ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|6 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|7 | ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|8 | ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|9 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|10| ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|11| └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | +|5 | ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|6 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|7 | ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|8 | ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|9 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|10| ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|11| └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | ====================================================================== Outputs & filters: ------------------------------------- @@ -2787,7 +2672,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2799,7 +2684,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2811,7 +2696,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2823,7 +2708,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2835,7 +2720,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2847,7 +2732,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2859,7 +2744,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -2871,11 +2756,13 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: DISTRIBUTED + Parameters: + :0 => 10 Note: Degree of Parallelisim is 1 because of table property select c1,c1 in (select c1 from t2 where t2.c1=t1.c1) and c1 in (select c1 from t2 where t2.c1 <= t1.c1) or c1 + (select c1 from t2 where t2.c1 = t1.c1) as x, c1+(select c1 from t2 where t2.c1 = t1.c1) or c1 in (select c2 from t2 where t2.c1 <= t1.c1) as y,c1+(select c2 from t2 where t1.c1=t2.c1) > 10 and c1 in (select c1 from t2 where t1.c1>= t2.c1) as z from t1; @@ -2907,18 +2794,18 @@ Query Plan ====================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |18 |2274 | -|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |2271 | -|2 | └─SUBPLAN FILTER | |18 |2265 | +|0 |PX COORDINATOR | |18 |1946 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |1943 | +|2 | └─SUBPLAN FILTER | |18 |1937 | |3 | ├─PX PARTITION ITERATOR | |18 |5 | |4 | │ └─TABLE FULL SCAN |t1 |18 |5 | -|5 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|6 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|7 | ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|8 | ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|9 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|10| ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|11| └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | +|5 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|6 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|7 | ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|8 | ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|9 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|10| ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|11| └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | ====================================================================== Outputs & filters: ------------------------------------- @@ -3022,7 +2909,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3034,7 +2921,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3046,7 +2933,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3058,7 +2945,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3070,7 +2957,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3082,7 +2969,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3094,7 +2981,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3106,11 +2993,14 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: DISTRIBUTED + Parameters: + :0 => 30 + :1 => 10 Note: Degree of Parallelisim is 1 because of table property select c1,c1 in (select c1 from t2 where t2.c1>=t1.c1) and c1 in (select c1 from t2 where t2.c1 <= t1.c1) or c1 + (select c1 from t2 where t2.c1 = t1.c1) as x, c1+(select c1 from t2 where t2.c1 = t1.c1) > 30 or c1 in (select c2 from t2 where t2.c1 <= t1.c1) as y,c1+(select c2 from t2 where t1.c1=t2.c1) > 10 and c1 in (select c1 from t2 where t1.c1>= t2.c1) as z from t1; @@ -3142,18 +3032,18 @@ Query Plan ====================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ---------------------------------------------------------------------- -|0 |PX COORDINATOR | |18 |2274 | -|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |2271 | -|2 | └─SUBPLAN FILTER | |18 |2265 | +|0 |PX COORDINATOR | |18 |1946 | +|1 |└─EXCHANGE OUT DISTR |:EX10000|18 |1943 | +|2 | └─SUBPLAN FILTER | |18 |1937 | |3 | ├─PX PARTITION ITERATOR | |18 |5 | |4 | │ └─TABLE FULL SCAN |t1 |18 |5 | -|5 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|6 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|7 | ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|8 | ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|9 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | -|10| ├─DISTRIBUTED TABLE GET |t2 |1 |18 | -|11| └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |18 | +|5 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|6 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|7 | ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|8 | ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|9 | ├─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | +|10| ├─DISTRIBUTED TABLE GET |t2 |1 |16 | +|11| └─DISTRIBUTED TABLE RANGE SCAN|t2 |8 |16 | ====================================================================== Outputs & filters: ------------------------------------- @@ -3257,7 +3147,7 @@ Optimization Info: table_dop:1 dop_method:Table DOP avaiable_index_name:[t1] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3269,7 +3159,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3281,7 +3171,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3293,7 +3183,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3305,7 +3195,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3317,7 +3207,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3329,7 +3219,7 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] t2: @@ -3341,11 +3231,14 @@ Optimization Info: table_dop:1 dop_method:DAS DOP avaiable_index_name:[t2] - stats info:[version=0, is_locked=0, is_expired=0] + stats info:[version=1970-01-01 08:00:00.000000, is_locked=0, is_expired=0] dynamic sampling level:0 estimation method:[DEFAULT, STORAGE] Plan Type: DISTRIBUTED + Parameters: + :0 => 30 + :1 => 10 Note: Degree of Parallelisim is 1 because of table property select c1,c1 in (select c1 from t2 where t2.c1>=t1.c1) and c1 in (select c1 from t2 where t2.c1 <= t1.c1) or c1 + (select c1 from t2 where t2.c1 = t1.c1) as x, c1+(select c1 from t2 where t2.c1 = t1.c1) > 30 or c1 in (select c2 from t2 where t2.c1 <= t1.c1) as y,c1+(select c2 from t2 where t1.c1=t2.c1) > 10 and c1 in (select c1 from t2 where t1.c1>= t2.c1) as z from t1; diff --git a/tools/deploy/mysql_test/test_suite/subquery/r/mysql/optimizer_subquery_bug.result b/tools/deploy/mysql_test/test_suite/subquery/r/mysql/optimizer_subquery_bug.result index 0557a7afb9..d8d14de772 100644 --- a/tools/deploy/mysql_test/test_suite/subquery/r/mysql/optimizer_subquery_bug.result +++ b/tools/deploy/mysql_test/test_suite/subquery/r/mysql/optimizer_subquery_bug.result @@ -268,15 +268,15 @@ select /*+no_rewrite*/ sum((select sum(a) from t1)) from t1 group by b; ## test correlated subquery EXPLAIN select /*+no_rewrite*/ sum((select sum(a) from t1 as t2 where t2.a = t1.a)) from t1; Query Plan -=========================================================== -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------------------ -|0 |SCALAR GROUP BY | |1 |57 | -|1 |└─SUBPLAN FILTER | |3 |57 | -|2 | ├─TABLE FULL SCAN |t1 |3 |3 | -|3 | └─SCALAR GROUP BY | |1 |18 | -|4 | └─DISTRIBUTED TABLE GET|t2 |1 |18 | -=========================================================== +=================================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +--------------------------------------------------- +|0 |SCALAR GROUP BY | |1 |57 | +|1 |└─SUBPLAN FILTER | |3 |57 | +|2 | ├─TABLE FULL SCAN|t1 |3 |3 | +|3 | └─SCALAR GROUP BY| |1 |18 | +|4 | └─TABLE GET |t2 |1 |18 | +=================================================== Outputs & filters: ------------------------------------- 0 - output([T_FUN_SUM(subquery(1))]), filter(nil), rowset=16 @@ -302,15 +302,15 @@ select /*+no_rewrite*/ sum((select sum(a) from t1 as t2 where t2.a = t1.a)) from +------------------------------------------------------+ EXPLAIN select /*+no_rewrite*/ sum((select sum(a) from t1 as t2 where t2.a = t1.a)) from t1 group by b; Query Plan -=========================================================== -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------------------ -|0 |HASH GROUP BY | |3 |57 | -|1 |└─SUBPLAN FILTER | |3 |57 | -|2 | ├─TABLE FULL SCAN |t1 |3 |3 | -|3 | └─SCALAR GROUP BY | |1 |18 | -|4 | └─DISTRIBUTED TABLE GET|t2 |1 |18 | -=========================================================== +=================================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +--------------------------------------------------- +|0 |HASH GROUP BY | |3 |57 | +|1 |└─SUBPLAN FILTER | |3 |57 | +|2 | ├─TABLE FULL SCAN|t1 |3 |3 | +|3 | └─SCALAR GROUP BY| |1 |18 | +|4 | └─TABLE GET |t2 |1 |18 | +=================================================== Outputs & filters: ------------------------------------- 0 - output([T_FUN_SUM(subquery(1))]), filter(nil), rowset=16 @@ -724,14 +724,14 @@ SELECT a IN (SELECT a FROM t1 ) FROM t1 LIMIT 1; ## bug EXPLAIN select /*+no_rewrite*/ a, (select sum(b) from t2 where t1.a = t2.a) as agg from t1 having agg > 1 and agg < 3; Query Plan -========================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ---------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |57 | -|1 |├─TABLE FULL SCAN |t1 |3 |3 | -|2 |└─SCALAR GROUP BY | |1 |18 | -|3 | └─DISTRIBUTED TABLE GET|t2 |1 |18 | -========================================================= +================================================= +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------------- +|0 |SUBPLAN FILTER | |1 |57 | +|1 |├─TABLE FULL SCAN|t1 |3 |3 | +|2 |└─SCALAR GROUP BY| |1 |18 | +|3 | └─TABLE GET |t2 |1 |18 | +================================================= Outputs & filters: ------------------------------------- 0 - output([t1.a], [subquery(1)]), filter([subquery(1) > cast(1, DECIMAL_INT(33, 0))], [subquery(1) < cast(3, DECIMAL_INT(33, 0))]), rowset=16 @@ -924,19 +924,19 @@ Query Plan |0 |SUBPLAN FILTER | |1 |22 | |1 |├─SUBPLAN SCAN |VIEW5 |1 |20 | |2 |│ └─SCALAR GROUP BY | |1 |20 | -|3 |│ └─MERGE ANTI JOIN | |9 |19 | +|3 |│ └─MERGE ANTI JOIN | |9 |20 | |4 |│ ├─TABLE FULL SCAN |table10_bigint |10 |3 | -|5 |│ └─SORT | |1 |16 | -|6 |│ └─SUBPLAN SCAN |VIEW3 |1 |16 | -|7 |│ └─HASH RIGHT ANTI JOIN NA | |1 |16 | -|8 |│ ├─SUBPLAN SCAN |VIEW2 |1 |14 | -|9 |│ │ └─NESTED-LOOP JOIN | |1 |14 | -|10|│ │ ├─SUBPLAN SCAN |VIEW4 |1 |7 | -|11|│ │ │ └─SCALAR GROUP BY | |1 |7 | -|12|│ │ │ └─SUBPLAN SCAN |VIEW1 |1 |7 | -|13|│ │ │ └─TABLE FULL SCAN|table100_bigint|1 |7 | -|14|│ │ └─TABLE FULL SCAN |table100_bigint|100 |4 | -|15|│ └─TABLE FULL SCAN |table2_bigint |2 |3 | +|5 |│ └─SORT | |1 |17 | +|6 |│ └─SUBPLAN SCAN |VIEW3 |1 |17 | +|7 |│ └─HASH ANTI JOIN NA | |1 |17 | +|8 |│ ├─TABLE FULL SCAN |table2_bigint |2 |3 | +|9 |│ └─SUBPLAN SCAN |VIEW2 |3 |14 | +|10|│ └─NESTED-LOOP JOIN | |3 |14 | +|11|│ ├─SUBPLAN SCAN |VIEW4 |1 |7 | +|12|│ │ └─SCALAR GROUP BY | |1 |7 | +|13|│ │ └─SUBPLAN SCAN |VIEW1 |1 |7 | +|14|│ │ └─TABLE FULL SCAN|table100_bigint|1 |7 | +|15|│ └─TABLE FULL SCAN |table100_bigint|100 |4 | |16|└─TOP-N SORT | |1 |3 | |17| └─TABLE RANGE SCAN |table10_bigint |1 |3 | ================================================================================== @@ -961,29 +961,29 @@ Outputs & filters: access([VIEW3.pk]) 7 - output([table2_bigint.pk]), filter(nil), rowset=256 equal_conds([cast(table2_bigint.pk, DECIMAL_INT(20, 0)) = VIEW2.col_decimal_20_0]), other_conds(nil) - 8 - output([VIEW2.col_decimal_20_0]), filter(nil), rowset=256 - access([VIEW2.col_decimal_20_0]) - 9 - output([table100_bigint.col_decimal_20_0]), filter(nil), rowset=256 - conds([cast(coalesce(VIEW4.MIN(10), ROUND(FLOOR(62)), 1), DECIMAL_INT(22, 0)) = ROUND(ABS(ROUND(FLOOR(table100_bigint.col_decimal_20_0))))]), nl_params_(nil), - use_batch=false - 10 - output([VIEW4.MIN(10)]), filter(nil), rowset=256 - access([VIEW4.MIN(10)]) - 11 - output([T_FUN_MIN(10)]), filter(nil), rowset=256 - group(nil), agg_func([T_FUN_MIN(10)]) - 12 - output(nil), filter(nil), rowset=256 - access(nil) - 13 - output([1]), filter([table100_bigint.col_char_20 > cast(CONCAT(cast(table100_bigint.col_char_20, VARCHAR(1048576)), substr('nhizctdn', 1, 20)), CHAR(100))]), rowset=256 - access([table100_bigint.col_char_20]), partitions(p0) - limit(1), offset(nil), is_index_back=false, is_global_index=false, filter_before_indexback[false], - range_key([table100_bigint.pk]), range(MIN ; MAX)always true - 14 - output([table100_bigint.col_decimal_20_0]), filter(nil), rowset=256 - access([table100_bigint.col_decimal_20_0]), partitions(p0) - is_index_back=false, is_global_index=false, - range_key([table100_bigint.pk]), range(MIN ; MAX)always true - 15 - output([table2_bigint.pk]), filter(nil), rowset=256 + 8 - output([table2_bigint.pk]), filter(nil), rowset=256 access([table2_bigint.pk]), partitions(p0) is_index_back=false, is_global_index=false, range_key([table2_bigint.pk]), range(MIN ; MAX)always true + 9 - output([VIEW2.col_decimal_20_0]), filter(nil), rowset=256 + access([VIEW2.col_decimal_20_0]) + 10 - output([table100_bigint.col_decimal_20_0]), filter(nil), rowset=256 + conds([cast(coalesce(VIEW4.MIN(10), ROUND(FLOOR(62)), 1), DECIMAL_INT(22, 0)) = ROUND(ABS(ROUND(FLOOR(table100_bigint.col_decimal_20_0))))]), nl_params_(nil), + use_batch=false + 11 - output([VIEW4.MIN(10)]), filter(nil), rowset=256 + access([VIEW4.MIN(10)]) + 12 - output([T_FUN_MIN(10)]), filter(nil), rowset=256 + group(nil), agg_func([T_FUN_MIN(10)]) + 13 - output(nil), filter(nil), rowset=256 + access(nil) + 14 - output([1]), filter([table100_bigint.col_char_20 > cast(CONCAT(cast(table100_bigint.col_char_20, VARCHAR(1048576)), substr('nhizctdn', 1, 20)), CHAR(100))]), rowset=256 + access([table100_bigint.col_char_20]), partitions(p0) + limit(1), offset(nil), is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([table100_bigint.pk]), range(MIN ; MAX)always true + 15 - output([table100_bigint.col_decimal_20_0]), filter(nil), rowset=256 + access([table100_bigint.col_decimal_20_0]), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([table100_bigint.pk]), range(MIN ; MAX)always true 16 - output([table10_bigint.col_decimal_20_0]), filter(nil), rowset=256 sort_keys([table10_bigint.col_bigint, ASC], [table10_bigint.pk, DESC]), topn(1) 17 - output([table10_bigint.pk], [table10_bigint.col_decimal_20_0], [table10_bigint.col_bigint]), filter(nil), rowset=256 @@ -1004,14 +1004,14 @@ Query Plan ================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------ -|0 |SUBPLAN FILTER | |1 |7 | +|0 |SUBPLAN FILTER | |1 |39 | |1 |├─TABLE FULL SCAN |table300_bigint|1 |3 | -|2 |└─SUBPLAN FILTER | |1 |5 | -|3 | ├─SCALAR GROUP BY | |1 |3 | -|4 | │ └─SUBPLAN FILTER | |1 |3 | +|2 |└─SUBPLAN FILTER | |1 |36 | +|3 | ├─SCALAR GROUP BY | |1 |18 | +|4 | │ └─SUBPLAN FILTER | |1 |18 | |5 | │ ├─EXPRESSION | |1 |1 | -|6 | │ └─TABLE FULL SCAN|m(idx5) |1 |3 | -|7 | └─TABLE FULL SCAN |t(idx5) |1 |3 | +|6 | │ └─TABLE FULL SCAN|m(idx5) |1 |18 | +|7 | └─TABLE FULL SCAN |t(idx5) |1 |18 | ================================================================== Outputs & filters: ------------------------------------- @@ -1049,16 +1049,16 @@ Query Plan ============================================================= |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |9 | +|0 |SUBPLAN FILTER | |1 |56 | |1 |├─TABLE FULL SCAN |table1|1 |3 | -|2 |└─SUBPLAN FILTER | |1 |7 | -|3 | ├─SCALAR GROUP BY | |1 |5 | -|4 | │ └─SUBPLAN SCAN |VIEW1 |1 |5 | -|5 | │ └─SCALAR GROUP BY | |1 |5 | -|6 | │ └─SUBPLAN FILTER | |1 |5 | -|7 | │ ├─TABLE FULL SCAN|tt |1 |3 | -|8 | │ └─TABLE FULL SCAN|table3|1 |3 | -|9 | └─TABLE FULL SCAN |tt |1 |3 | +|2 |└─SUBPLAN FILTER | |1 |54 | +|3 | ├─SCALAR GROUP BY | |1 |36 | +|4 | │ └─SUBPLAN SCAN |VIEW1 |1 |36 | +|5 | │ └─SCALAR GROUP BY | |1 |36 | +|6 | │ └─SUBPLAN FILTER | |1 |36 | +|7 | │ ├─TABLE FULL SCAN|tt |1 |18 | +|8 | │ └─TABLE FULL SCAN|table3|1 |18 | +|9 | └─TABLE FULL SCAN |tt |1 |18 | ============================================================= Outputs & filters: ------------------------------------- @@ -1084,7 +1084,7 @@ Outputs & filters: range_key([tt.__pk_increment]), range(MIN ; MAX)always true 8 - output([1]), filter(nil), startup_filter([:0 != 99]), rowset=16 access(nil), partitions(p0) - limit(8), offset(nil), is_index_back=false, is_global_index=false, + limit(1), offset(nil), is_index_back=false, is_global_index=false, range_key([table3.__pk_increment]), range(MIN ; MAX)always true 9 - output([:1]), filter(nil), rowset=16 access(nil), partitions(p0) @@ -1105,13 +1105,13 @@ Query Plan ===================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ----------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |7 | +|0 |SUBPLAN FILTER | |1 |39 | |1 |├─SCALAR GROUP BY | |1 |3 | |2 |│ └─TABLE FULL SCAN |t2 |2 |3 | -|3 |└─SCALAR GROUP BY | |1 |5 | -|4 | └─SUBPLAN FILTER | |1 |5 | -|5 | ├─TABLE FULL SCAN|t1 |1 |3 | -|6 | └─TABLE FULL SCAN|t1 |1 |3 | +|3 |└─SCALAR GROUP BY | |1 |36 | +|4 | └─SUBPLAN FILTER | |1 |36 | +|5 | ├─TABLE FULL SCAN|t1 |1 |18 | +|6 | └─TABLE FULL SCAN|t1 |1 |18 | ===================================================== Outputs & filters: ------------------------------------- @@ -1287,17 +1287,17 @@ Query Plan =================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |2056 | +|0 |SUBPLAN FILTER | |1 |2451 | |1 |├─NESTED-LOOP OUTER JOIN | |5 |3 | |2 |│ ├─TABLE FULL SCAN |T11 |5 |3 | |3 |│ └─MATERIAL | |1 |3 | |4 |│ └─TABLE FULL SCAN |T12 |1 |3 | -|5 |└─SCALAR GROUP BY | |1 |13 | -|6 | └─PX COORDINATOR | |1 |13 | -|7 | └─EXCHANGE OUT DISTR |:EX10000|1 |12 | -|8 | └─MERGE GROUP BY | |1 |11 | -|9 | └─PX PARTITION ITERATOR| |5 |11 | -|10| └─TABLE FULL SCAN |T14 |5 |11 | +|5 |└─SCALAR GROUP BY | |1 |92 | +|6 | └─PX COORDINATOR | |1 |92 | +|7 | └─EXCHANGE OUT DISTR |:EX10000|1 |91 | +|8 | └─MERGE GROUP BY | |1 |90 | +|9 | └─PX PARTITION ITERATOR| |5 |90 | +|10| └─TABLE FULL SCAN |T14 |5 |90 | =================================================================== Outputs & filters: ------------------------------------- @@ -1346,9 +1346,9 @@ Query Plan ================================================= |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |7 | +|0 |SUBPLAN FILTER | |1 |39 | |1 |├─TABLE FULL SCAN|t1 |2 |3 | -|2 |└─TABLE FULL SCAN|t2 |1 |3 | +|2 |└─TABLE FULL SCAN|t2 |1 |18 | ================================================= Outputs & filters: ------------------------------------- @@ -1395,17 +1395,17 @@ FROM t2 WHERE v1.s_c2 >= t2.c2 and v1.c1 = t2.c1; Query Plan -==================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |NESTED-LOOP JOIN | |1 |28 | -|1 |├─SUBPLAN SCAN |v1 |1 |7 | -|2 |│ └─SUBPLAN FILTER | |1 |7 | -|3 |│ ├─TABLE FULL SCAN |t1 |1 |3 | -|4 |│ ├─TABLE FULL SCAN |t3 |1 |3 | -|5 |│ └─TABLE FULL SCAN |t3 |1 |3 | -|6 |└─DISTRIBUTED TABLE RANGE SCAN|t2(idx_c1)|1 |20 | -==================================================================== +=========================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +----------------------------------------------------------- +|0 |NESTED-LOOP JOIN | |1 |28 | +|1 |├─SUBPLAN SCAN |v1 |1 |7 | +|2 |│ └─SUBPLAN FILTER | |1 |7 | +|3 |│ ├─TABLE FULL SCAN|t1 |1 |3 | +|4 |│ ├─TABLE FULL SCAN|t3 |1 |3 | +|5 |│ └─TABLE FULL SCAN|t3 |1 |3 | +|6 |└─TABLE RANGE SCAN |t2(idx_c1)|1 |20 | +=========================================================== Outputs & filters: ------------------------------------- 0 - output([v1.c1], [v1.s_c1], [v1.s_c2], [t2.c1], [t2.c2]), filter(nil), rowset=16 diff --git a/tools/deploy/mysql_test/test_suite/subquery/r/mysql/spf_bug13044302.result b/tools/deploy/mysql_test/test_suite/subquery/r/mysql/spf_bug13044302.result index ff9bde63ef..391553a6cc 100644 --- a/tools/deploy/mysql_test/test_suite/subquery/r/mysql/spf_bug13044302.result +++ b/tools/deploy/mysql_test/test_suite/subquery/r/mysql/spf_bug13044302.result @@ -148,78 +148,84 @@ Outputs & filters: range_key([r.__pk_increment]), range(MIN ; MAX)always true explain select * from cb_dep_acctbal_54 s, cb_dep_acct_54 a where s.acctnbr = a.acctnbr and ((a.curracctstatcd != 'CLS' and exists(select 1 from cb_dep_acctbal_54 r where r.acctnbr = s.acctnbr)) or (a.curracctstatcd = 'CLS' and exists(select 1 from cb_dep_rxtnbal_54 r where r.acctnbr = a.acctnbr))); Query Plan -============================================================================= -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------------ -|0 |PX COORDINATOR | |2 |43 | -|1 |└─EXCHANGE OUT DISTR |:EX10003|2 |41 | -|2 | └─HASH UNION DISTINCT | |2 |38 | -|3 | ├─HASH JOIN | |1 |18 | -|4 | │ ├─PX PARTITION ITERATOR | |1 |11 | -|5 | │ │ └─TABLE FULL SCAN |a |1 |11 | -|6 | │ └─EXCHANGE IN DISTR | |3 |7 | -|7 | │ └─EXCHANGE OUT DISTR (PKEY) |:EX10000|3 |6 | -|8 | │ └─TABLE FULL SCAN |s |3 |3 | -|9 | └─EXCHANGE IN DISTR | |1 |20 | -|10| └─EXCHANGE OUT DISTR (PKEY) |:EX10002|1 |19 | -|11| └─MERGE JOIN | |1 |18 | -|12| ├─SORT | |1 |16 | -|13| │ └─HASH RIGHT SEMI JOIN | |1 |16 | -|14| │ ├─TABLE FULL SCAN |r |1 |3 | -|15| │ └─EXCHANGE IN DISTR | |2 |13 | -|16| │ └─EXCHANGE OUT DISTR |:EX10001|2 |12 | -|17| │ └─PX PARTITION ITERATOR| |2 |11 | -|18| │ └─TABLE FULL SCAN |a |2 |11 | -|19| └─TABLE FULL SCAN |s |3 |3 | -============================================================================= +=========================================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +--------------------------------------------------------------------------- +|0 |MERGE UNION DISTINCT | |2 |38 | +|1 |├─MERGE JOIN | |1 |18 | +|2 |│ ├─TABLE FULL SCAN |s |3 |3 | +|3 |│ └─SORT | |1 |16 | +|4 |│ └─HASH JOIN | |1 |16 | +|5 |│ ├─TABLE FULL SCAN |r |1 |3 | +|6 |│ └─PX COORDINATOR | |2 |13 | +|7 |│ └─EXCHANGE OUT DISTR |:EX10000|2 |12 | +|8 |│ └─PX PARTITION ITERATOR | |2 |11 | +|9 |│ └─TABLE FULL SCAN |a |2 |11 | +|10|└─SORT | |1 |20 | +|11| └─HASH JOIN | |1 |20 | +|12| ├─TABLE FULL SCAN |s |3 |3 | +|13| └─PX COORDINATOR | |1 |17 | +|14| └─EXCHANGE OUT DISTR |:EX20001|1 |16 | +|15| └─HASH JOIN | |1 |15 | +|16| ├─PX PARTITION ITERATOR | |1 |11 | +|17| │ └─TABLE FULL SCAN |a |1 |11 | +|18| └─EXCHANGE IN DISTR | |3 |4 | +|19| └─EXCHANGE OUT DISTR (PKEY)|:EX20000|3 |4 | +|20| └─TABLE FULL SCAN |r |3 |3 | +=========================================================================== Outputs & filters: ------------------------------------- - 0 - output([INTERNAL_FUNCTION(UNION([1]), UNION([2]), UNION([3]), UNION([4]), UNION([5]))]), filter(nil), rowset=16 - 1 - output([INTERNAL_FUNCTION(UNION([1]), UNION([2]), UNION([3]), UNION([4]), UNION([5]))]), filter(nil), rowset=16 - dop=1 - 2 - output([UNION([1])], [UNION([2])], [UNION([3])], [UNION([4])], [UNION([5])]), filter(nil), rowset=16 - 3 - output([s.acctnbr], [s.balcatcd], [s.baltypcd], [a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + 0 - output([UNION([1])], [UNION([2])], [UNION([3])], [UNION([4])], [UNION([5])]), filter(nil), rowset=16 + 1 - output([s.acctnbr], [s.balcatcd], [s.baltypcd], [a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 equal_conds([s.acctnbr = a.acctnbr]), other_conds(nil) - 4 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 - affinitize, force partition granule - 5 - output([a.acctnbr], [a.curracctstatcd]), filter([a.curracctstatcd != 'CLS']), rowset=16 - access([a.acctnbr], [a.curracctstatcd]), partitions(p[0-4]) - is_index_back=false, is_global_index=false, filter_before_indexback[false], - range_key([a.acctnbr]), range(MIN ; MAX)always true - 6 - output([s.acctnbr], [s.balcatcd], [s.baltypcd]), filter(nil), rowset=16 - 7 - output([s.acctnbr], [s.balcatcd], [s.baltypcd]), filter(nil), rowset=16 - (#keys=1, [s.acctnbr]), is_single, dop=1 - 8 - output([s.acctnbr], [s.balcatcd], [s.baltypcd]), filter(nil), rowset=16 + merge_directions([ASC]) + 2 - output([s.acctnbr], [s.balcatcd], [s.baltypcd]), filter(nil), rowset=16 access([s.acctnbr], [s.balcatcd], [s.baltypcd]), partitions(p0) is_index_back=false, is_global_index=false, range_key([s.acctnbr], [s.balcatcd], [s.baltypcd]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true - 9 - output([s.acctnbr], [s.balcatcd], [s.baltypcd], [a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 - 10 - output([s.acctnbr], [s.balcatcd], [s.baltypcd], [a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 - (#keys=1, [s.acctnbr]), is_single, dop=1 - 11 - output([s.acctnbr], [s.balcatcd], [s.baltypcd], [a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 - equal_conds([s.acctnbr = a.acctnbr]), other_conds(nil) - merge_directions([ASC]) - 12 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + 3 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 sort_keys([a.acctnbr, ASC]) - 13 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + 4 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 equal_conds([cast(r.acctnbr, DECIMAL(-1, -1)) = cast(a.acctnbr, DECIMAL(20, 0))]), other_conds(nil) - 14 - output([r.acctnbr]), filter(nil), rowset=16 + 5 - output([r.acctnbr]), filter(nil), rowset=16 access([r.acctnbr]), partitions(p0) is_index_back=false, is_global_index=false, range_key([r.__pk_increment]), range(MIN ; MAX)always true - 15 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 - 16 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + 6 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + 7 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 dop=1 - 17 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + 8 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 force partition granule - 18 - output([a.acctnbr], [a.curracctstatcd]), filter([a.curracctstatcd = 'CLS']), rowset=16 + 9 - output([a.acctnbr], [a.curracctstatcd]), filter([a.curracctstatcd = 'CLS']), rowset=16 access([a.acctnbr], [a.curracctstatcd]), partitions(p[0-4]) is_index_back=false, is_global_index=false, filter_before_indexback[false], range_key([a.acctnbr]), range(MIN ; MAX)always true - 19 - output([s.acctnbr], [s.balcatcd], [s.baltypcd]), filter(nil), rowset=16 + 10 - output([s.acctnbr], [s.balcatcd], [s.baltypcd], [a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + sort_keys([s.acctnbr, ASC], [s.balcatcd, ASC], [s.baltypcd, ASC]) + 11 - output([s.acctnbr], [s.balcatcd], [s.baltypcd], [a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + equal_conds([s.acctnbr = a.acctnbr]), other_conds(nil) + 12 - output([s.acctnbr], [s.balcatcd], [s.baltypcd]), filter(nil), rowset=16 access([s.acctnbr], [s.balcatcd], [s.baltypcd]), partitions(p0) is_index_back=false, is_global_index=false, range_key([s.acctnbr], [s.balcatcd], [s.baltypcd]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true + 13 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + 14 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + dop=1 + 15 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + equal_conds([a.acctnbr = r.acctnbr]), other_conds(nil) + 16 - output([a.acctnbr], [a.curracctstatcd]), filter(nil), rowset=16 + affinitize, force partition granule + 17 - output([a.acctnbr], [a.curracctstatcd]), filter([a.curracctstatcd != 'CLS']), rowset=16 + access([a.acctnbr], [a.curracctstatcd]), partitions(p[0-4]) + is_index_back=false, is_global_index=false, filter_before_indexback[false], + range_key([a.acctnbr]), range(MIN ; MAX)always true + 18 - output([r.acctnbr]), filter(nil), rowset=16 + 19 - output([r.acctnbr]), filter(nil), rowset=16 + (#keys=1, [r.acctnbr]), is_single, dop=1 + 20 - output([r.acctnbr]), filter(nil), rowset=16 + access([r.acctnbr]), partitions(p0) + is_index_back=false, is_global_index=false, + range_key([r.acctnbr], [r.balcatcd], [r.baltypcd]), range(MIN,MIN,MIN ; MAX,MAX,MAX)always true explain select * from cb_dep_acctbal_54 s, cb_dep_acct_54 a where s.acctnbr = a.acctnbr and (a.curracctstatcd != 'CLS' or (a.curracctstatcd = 'CLS' and exists(select 1 from cb_dep_rxtnbal_54 r where r.acctnbr = a.acctnbr))) group by s.acctnbr; Query Plan ========================================================================= @@ -234,7 +240,7 @@ Query Plan |6 | │ │ └─EXCHANGE OUT DISTR |:EX10000|2 |12 | |7 | │ │ └─PX PARTITION ITERATOR | |2 |11 | |8 | │ │ └─TABLE FULL SCAN |a |2 |11 | -|9 | │ └─HASH RIGHT SEMI JOIN | |1 |16 | +|9 | │ └─HASH JOIN | |1 |16 | |10| │ ├─TABLE FULL SCAN |r |1 |3 | |11| │ └─PX COORDINATOR | |2 |13 | |12| │ └─EXCHANGE OUT DISTR |:EX20000|2 |12 | @@ -296,7 +302,7 @@ Query Plan |6 | │ │ └─EXCHANGE OUT DISTR |:EX10000|2 |12 | |7 | │ │ └─PX PARTITION ITERATOR | |2 |11 | |8 | │ │ └─TABLE FULL SCAN |a |2 |11 | -|9 | │ └─HASH RIGHT SEMI JOIN | |1 |16 | +|9 | │ └─HASH JOIN | |1 |16 | |10| │ ├─TABLE FULL SCAN |r |1 |3 | |11| │ └─PX COORDINATOR | |2 |13 | |12| │ └─EXCHANGE OUT DISTR |:EX20000|2 |12 | diff --git a/tools/deploy/mysql_test/test_suite/subquery/r/mysql/subquery.result b/tools/deploy/mysql_test/test_suite/subquery/r/mysql/subquery.result index 3dc291e9bc..1132fc6e02 100644 --- a/tools/deploy/mysql_test/test_suite/subquery/r/mysql/subquery.result +++ b/tools/deploy/mysql_test/test_suite/subquery/r/mysql/subquery.result @@ -445,45 +445,45 @@ Outputs & filters: range_key([t1.c1]), range(MIN ; MAX)always true explain select * from t1 where t1.c2 = 5 or exists (select 1 from t2 where t1.c1 > t2.c1); Query Plan -============================================================== -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| --------------------------------------------------------------- -|0 |SUBPLAN FILTER | |2 |39 | -|1 |├─TABLE FULL SCAN |t1 |2 |3 | -|2 |└─DISTRIBUTED TABLE RANGE SCAN|t2 |1 |18 | -============================================================== +================================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +-------------------------------------------------- +|0 |SUBPLAN FILTER | |2 |39 | +|1 |├─TABLE FULL SCAN |t1 |2 |3 | +|2 |└─TABLE RANGE SCAN|t2 |1 |18 | +================================================== Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2], [t1.c3]), filter([t1.c2 = 5 OR (T_OP_EXISTS, subquery(1))]), rowset=16 - exec_params_([t1.c1(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true + exec_params_([t1.c1(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 1 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 access([t1.c1], [t1.c2], [t1.c3]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t1.c1]), range(MIN ; MAX)always true 2 - output([1]), filter(nil), rowset=16 - access([GROUP_ID]), partitions(p0) + access(nil), partitions(p0) limit(1), offset(nil), is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([:0 > t2.c1]) explain select * from t1 where t1.c2 = 5 or exists (select 1 from t2 where t1.c1 < t2.c1); Query Plan -============================================================== -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| --------------------------------------------------------------- -|0 |SUBPLAN FILTER | |2 |39 | -|1 |├─TABLE FULL SCAN |t1 |2 |3 | -|2 |└─DISTRIBUTED TABLE RANGE SCAN|t2 |1 |18 | -============================================================== +================================================== +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +-------------------------------------------------- +|0 |SUBPLAN FILTER | |2 |39 | +|1 |├─TABLE FULL SCAN |t1 |2 |3 | +|2 |└─TABLE RANGE SCAN|t2 |1 |18 | +================================================== Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2], [t1.c3]), filter([t1.c2 = 5 OR (T_OP_EXISTS, subquery(1))]), rowset=16 - exec_params_([t1.c1(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true + exec_params_([t1.c1(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 1 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 access([t1.c1], [t1.c2], [t1.c3]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t1.c1]), range(MIN ; MAX)always true 2 - output([1]), filter(nil), rowset=16 - access([GROUP_ID]), partitions(p0) + access(nil), partitions(p0) limit(1), offset(nil), is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([:0 < t2.c1]) @@ -497,12 +497,12 @@ Query Plan |2 |│ ├─TABLE FULL SCAN |t1 |2 |3 | |3 |│ └─MATERIAL | |2 |3 | |4 |│ └─TABLE FULL SCAN |t2 |2 |3 | -|5 |└─DISTRIBUTED TABLE GET |t2 |1 |18 | +|5 |└─TABLE GET |t2 |1 |18 | ============================================================= Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2], [t1.c3], [t2.c1], [t2.c2], [t2.c3]), filter([t1.c1 > (T_OP_EXISTS, subquery(1))]), rowset=16 - exec_params_([t1.c1(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=true + exec_params_([t1.c1(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false 1 - output([t1.c1], [t1.c2], [t1.c3], [t2.c1], [t2.c2], [t2.c3]), filter(nil), rowset=16 conds(nil), nl_params_(nil), use_batch=false 2 - output([t1.c1], [t1.c2], [t1.c3]), filter(nil), rowset=16 @@ -515,20 +515,20 @@ Outputs & filters: is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true 5 - output([1]), filter(nil), rowset=16 - access([GROUP_ID]), partitions(p0) + access(nil), partitions(p0) limit(1), offset(nil), is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 = :0]) explain select * from t1 where (select c1 from t2 limit 1)+1 in (select 2 from t3 where t1.c1=t3.c1); Query Plan -======================================================= -|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| -------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |41 | -|1 |├─TABLE FULL SCAN |t1 |2 |3 | -|2 |├─DISTRIBUTED TABLE GET|t3 |1 |18 | -|3 |└─TABLE FULL SCAN |t2 |1 |3 | -======================================================= +================================================= +|ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| +------------------------------------------------- +|0 |SUBPLAN FILTER | |1 |41 | +|1 |├─TABLE FULL SCAN|t1 |2 |3 | +|2 |├─TABLE GET |t3 |1 |18 | +|3 |└─TABLE FULL SCAN|t2 |1 |3 | +================================================= Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2], [t1.c3]), filter([:1 + 1 = ANY(subquery(1))]), rowset=16 @@ -551,10 +551,10 @@ Query Plan ======================================================= |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |21 | +|0 |SUBPLAN FILTER | |1 |18 | |1 |├─SCALAR GROUP BY | |1 |3 | |2 |│ └─TABLE FULL SCAN |t1 |2 |3 | -|3 |└─DISTRIBUTED TABLE GET|t2 |1 |18 | +|3 |└─DISTRIBUTED TABLE GET|t2 |1 |16 | ======================================================= Outputs & filters: ------------------------------------- @@ -612,7 +612,7 @@ Query Plan |2 |│ ├─TABLE FULL SCAN |t1 |2 |3 | |3 |│ └─TABLE FULL SCAN |t2 |2 |3 | |4 |└─MERGE SEMI JOIN | |1 |5 | -|5 | ├─NESTED-LOOP JOIN | |2 |3 | +|5 | ├─NESTED-LOOP JOIN | |3 |3 | |6 | │ ├─TABLE FULL SCAN |t2 |2 |3 | |7 | │ └─MATERIAL | |2 |3 | |8 | │ └─TABLE FULL SCAN|t1 |2 |3 | @@ -686,7 +686,7 @@ Query Plan ================================================= |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------- -|0 |MERGE JOIN | |1 |5 | +|0 |MERGE JOIN | |2 |5 | |1 |├─TABLE FULL SCAN|t2 |2 |3 | |2 |└─TABLE FULL SCAN|t1 |2 |3 | ================================================= @@ -708,8 +708,8 @@ Query Plan =================================================== |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| --------------------------------------------------- -|0 |MERGE JOIN | |1 |7 | -|1 |├─MERGE JOIN | |1 |5 | +|0 |MERGE JOIN | |2 |7 | +|1 |├─MERGE JOIN | |2 |5 | |2 |│ ├─TABLE FULL SCAN|t2 |2 |3 | |3 |│ └─TABLE FULL SCAN|t3 |2 |3 | |4 |└─TABLE FULL SCAN |t1 |2 |3 | @@ -736,22 +736,22 @@ Outputs & filters: range_key([t1.c1]), range(MIN ; MAX)always true explain select * from t1 where t1.c2 in (select avg(c1) from t2 where t2.c1 = t1.c1 union select count(1) from t3 where t3.c1 = t1.c1); Query Plan -==================================================================== -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| --------------------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |75 | -|1 |├─TABLE FULL SCAN |t1 |2 |3 | -|2 |└─LIMIT | |1 |36 | -|3 | └─SUBPLAN SCAN |VIEW1|1 |36 | -|4 | └─LIMIT | |1 |36 | -|5 | └─MERGE UNION DISTINCT | |1 |36 | -|6 | ├─LIMIT | |1 |18 | -|7 | │ └─SCALAR GROUP BY | |1 |18 | -|8 | │ └─DISTRIBUTED TABLE GET|t2 |1 |18 | -|9 | └─LIMIT | |1 |18 | -|10| └─SCALAR GROUP BY | |1 |18 | -|11| └─DISTRIBUTED TABLE GET|t3 |1 |18 | -==================================================================== +============================================================= +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +------------------------------------------------------------- +|0 |SUBPLAN FILTER | |1 |75 | +|1 |├─TABLE FULL SCAN |t1 |2 |3 | +|2 |└─LIMIT | |1 |36 | +|3 | └─SUBPLAN SCAN |VIEW1|1 |36 | +|4 | └─LIMIT | |1 |36 | +|5 | └─MERGE UNION DISTINCT| |1 |36 | +|6 | ├─LIMIT | |1 |18 | +|7 | │ └─SCALAR GROUP BY | |1 |18 | +|8 | │ └─TABLE GET |t2 |1 |18 | +|9 | └─LIMIT | |1 |18 | +|10| └─SCALAR GROUP BY | |1 |18 | +|11| └─TABLE GET |t3 |1 |18 | +============================================================= Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2], [t1.c3]), filter([(T_OP_EXISTS, subquery(1))]), rowset=16 @@ -774,7 +774,7 @@ Outputs & filters: group(nil), agg_func([T_FUN_SUM(t2.c1)], [T_FUN_COUNT(t2.c1)]) 8 - output([t2.c1]), filter(nil), rowset=16 access([t2.c1]), partitions(p0) - is_index_back=false, is_global_index=false, keep_ordering=true, + is_index_back=false, is_global_index=false, range_key([t2.c1]), range(MIN ; MAX)always true, range_cond([t2.c1 = :0]) 9 - output([cast(T_FUN_COUNT(*), DECIMAL(24, 4))]), filter(nil), rowset=16 @@ -783,23 +783,23 @@ Outputs & filters: group(nil), agg_func([T_FUN_COUNT(*)]) 11 - output(nil), filter(nil), rowset=16 access(nil), partitions(p0) - is_index_back=false, is_global_index=false, keep_ordering=true, + is_index_back=false, is_global_index=false, range_key([t3.c1]), range(MIN ; MAX)always true, range_cond([t3.c1 = :0]) explain select * from t1 where t1.c1 != (select c2 from t2 where t2.c1 = (select max(c2) from t3 where t3.c1 = t1.c1) order by t2.c2 limit 1); Query Plan -================================================================ -|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ----------------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |43 | -|1 |├─TABLE FULL SCAN |t1 |2 |3 | -|2 |└─LIMIT | |1 |21 | -|3 | └─MERGE JOIN | |1 |21 | -|4 | ├─SUBPLAN SCAN |VIEW1|1 |18 | -|5 | │ └─SCALAR GROUP BY | |1 |18 | -|6 | │ └─DISTRIBUTED TABLE GET|t3 |1 |18 | -|7 | └─TABLE FULL SCAN |t2 |2 |3 | -================================================================ +======================================================== +|ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| +-------------------------------------------------------- +|0 |SUBPLAN FILTER | |1 |75 | +|1 |├─TABLE FULL SCAN |t1 |2 |3 | +|2 |└─LIMIT | |1 |36 | +|3 | └─MERGE JOIN | |1 |36 | +|4 | ├─SUBPLAN SCAN |VIEW1|1 |18 | +|5 | │ └─SCALAR GROUP BY| |1 |18 | +|6 | │ └─TABLE GET |t3 |1 |18 | +|7 | └─TABLE FULL SCAN |t2 |2 |18 | +======================================================== Outputs & filters: ------------------------------------- 0 - output([t1.c1], [t1.c2], [t1.c3]), filter([t1.c1 != subquery(1)]), rowset=16 @@ -819,7 +819,7 @@ Outputs & filters: group(nil), agg_func([T_FUN_MAX(t3.c2)]) 6 - output([t3.c2]), filter(nil), rowset=16 access([t3.c2]), partitions(p0) - is_index_back=false, is_global_index=false, keep_ordering=true, + is_index_back=false, is_global_index=false, range_key([t3.c1]), range(MIN ; MAX)always true, range_cond([t3.c1 = :0]) 7 - output([t2.c1], [t2.c2]), filter(nil), rowset=16 @@ -1271,48 +1271,47 @@ Query Plan ======================================================= |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |7 | +|0 |SUBPLAN FILTER | |1 |5 | |1 |├─TABLE FULL SCAN |t1 |1 |3 | -|2 |└─LIMIT | |1 |5 | -|3 | └─SUBPLAN FILTER | |1 |5 | -|4 | ├─HASH GROUP BY | |1 |3 | -|5 | │ └─TABLE FULL SCAN|t2 |1 |3 | -|6 | └─TABLE FULL SCAN |t3 |1 |3 | +|2 |└─LIMIT | |1 |3 | +|3 | └─NESTED-LOOP JOIN | |1 |3 | +|4 | ├─TABLE FULL SCAN |t2 |1 |3 | +|5 | └─MATERIAL | |1 |3 | +|6 | └─TABLE FULL SCAN|t3 |1 |3 | ======================================================= Outputs & filters: ------------------------------------- 0 - output([t1.a], [t1.b]), filter(nil), rowset=16 - exec_params_(nil), onetime_exprs_([(T_OP_EXISTS, subquery(1))(:1)]), init_plan_idxs_(nil), use_batch=false - 1 - output([t1.a], [t1.b]), filter(nil), startup_filter([:1]), rowset=16 + exec_params_(nil), onetime_exprs_([(T_OP_EXISTS, subquery(1))(:0)]), init_plan_idxs_(nil), use_batch=false + 1 - output([t1.a], [t1.b]), filter(nil), startup_filter([:0]), rowset=16 access([t1.a], [t1.b]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t1.__pk_increment]), range(MIN ; MAX)always true 2 - output([1]), filter(nil), rowset=16 limit(1), offset(nil) - 3 - output(nil), filter([(T_OP_EXISTS, subquery(1))]), rowset=16 - exec_params_([T_FUN_MAX(t2.a)(:0)]), onetime_exprs_(nil), init_plan_idxs_(nil), use_batch=false - 4 - output([T_FUN_MAX(t2.a)]), filter(nil), rowset=16 - group([t2.a]), agg_func([T_FUN_MAX(t2.a)]) - 5 - output([t2.a]), filter(nil), rowset=16 + 3 - output(nil), filter(nil), rowset=16 + conds([t3.a > t2.a]), nl_params_(nil), use_batch=false + 4 - output([t2.a]), filter(nil), rowset=16 access([t2.a]), partitions(p0) is_index_back=false, is_global_index=false, range_key([t2.__pk_increment]), range(MIN ; MAX)always true - 6 - output([1]), filter([t3.a > :0]), rowset=16 + 5 - output([t3.a]), filter(nil), rowset=16 + 6 - output([t3.a]), filter(nil), rowset=16 access([t3.a]), partitions(p0) - limit(1), offset(nil), is_index_back=false, is_global_index=false, filter_before_indexback[false], + is_index_back=false, is_global_index=false, range_key([t3.__pk_increment]), range(MIN ; MAX)always true explain select * from t1 where exists ( select sum(a) from t2 group by a having exists (select * from t3 where t3.a > sum(t2.a))); Query Plan ======================================================= |ID|OPERATOR |NAME|EST.ROWS|EST.TIME(us)| ------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |7 | +|0 |SUBPLAN FILTER | |1 |23 | |1 |├─TABLE FULL SCAN |t1 |1 |3 | -|2 |└─LIMIT | |1 |5 | -|3 | └─SUBPLAN FILTER | |1 |5 | +|2 |└─LIMIT | |1 |21 | +|3 | └─SUBPLAN FILTER | |1 |21 | |4 | ├─HASH GROUP BY | |1 |3 | |5 | │ └─TABLE FULL SCAN|t2 |1 |3 | -|6 | └─TABLE FULL SCAN |t3 |1 |3 | +|6 | └─TABLE FULL SCAN |t3 |1 |18 | ======================================================= Outputs & filters: ------------------------------------- @@ -1848,18 +1847,18 @@ Query Plan ==================================================================================== |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| ------------------------------------------------------------------------------------ -|0 |SUBPLAN FILTER | |1 |9 | +|0 |SUBPLAN FILTER | |1 |57 | |1 |├─TABLE FULL SCAN |table0_hash_pk_parts_1_bigint|1 |3 | -|2 |└─SUBPLAN FILTER | |1 |7 | -|3 | ├─SCALAR GROUP BY | |1 |3 | -|4 | │ └─SUBPLAN SCAN |VIEW3 |1 |3 | -|5 | │ └─SCALAR GROUP BY | |1 |3 | -|6 | │ └─SUBPLAN SCAN |VIEW1 |1 |3 | -|7 | │ └─TABLE FULL SCAN|ff |1 |3 | -|8 | └─MERGE SEMI JOIN | |1 |5 | -|9 | ├─TABLE FULL SCAN |s(idx5) |1 |3 | -|10| └─SORT | |1 |3 | -|11| └─TABLE FULL SCAN |table0_hash_pk_parts_1_bigint|1 |3 | +|2 |└─SUBPLAN FILTER | |1 |54 | +|3 | ├─SCALAR GROUP BY | |1 |18 | +|4 | │ └─SUBPLAN SCAN |VIEW3 |1 |18 | +|5 | │ └─SCALAR GROUP BY | |1 |18 | +|6 | │ └─SUBPLAN SCAN |VIEW1 |1 |18 | +|7 | │ └─TABLE FULL SCAN|ff |1 |18 | +|8 | └─MERGE SEMI JOIN | |1 |36 | +|9 | ├─TABLE FULL SCAN |s(idx5) |1 |18 | +|10| └─SORT | |1 |18 | +|11| └─TABLE FULL SCAN |table0_hash_pk_parts_1_bigint|1 |18 | ==================================================================================== Outputs & filters: ------------------------------------- @@ -1926,17 +1925,17 @@ Query Plan ================================================================================ |ID|OPERATOR |NAME |EST.ROWS|EST.TIME(us)| -------------------------------------------------------------------------------- -|0 |SUBPLAN FILTER | |1 |9 | +|0 |SUBPLAN FILTER | |1 |57 | |1 |├─TABLE FULL SCAN |table0_hash_pk_parts_1_bigint|1 |3 | -|2 |└─SUBPLAN FILTER | |1 |7 | -|3 | ├─SCALAR GROUP BY | |1 |3 | -|4 | │ └─SUBPLAN FILTER | |1 |3 | +|2 |└─SUBPLAN FILTER | |1 |54 | +|3 | ├─SCALAR GROUP BY | |1 |18 | +|4 | │ └─SUBPLAN FILTER | |1 |18 | |5 | │ ├─EXPRESSION | |1 |1 | -|6 | │ └─TABLE FULL SCAN|ff(idx3) |1 |3 | -|7 | └─MERGE SEMI JOIN | |1 |5 | -|8 | ├─TABLE FULL SCAN |s(idx5) |1 |3 | -|9 | └─SORT | |1 |3 | -|10| └─TABLE FULL SCAN|table0_hash_pk_parts_1_bigint|1 |3 | +|6 | │ └─TABLE FULL SCAN|ff(idx3) |1 |18 | +|7 | └─MERGE SEMI JOIN | |1 |36 | +|8 | ├─TABLE FULL SCAN |s(idx5) |1 |18 | +|9 | └─SORT | |1 |18 | +|10| └─TABLE FULL SCAN|table0_hash_pk_parts_1_bigint|1 |18 | ================================================================================ Outputs & filters: ------------------------------------- diff --git a/tools/deploy/mysql_test/test_suite/update/r/mysql/update2.result b/tools/deploy/mysql_test/test_suite/update/r/mysql/update2.result index 19b64dd7ec..253a2e9150 100644 --- a/tools/deploy/mysql_test/test_suite/update/r/mysql/update2.result +++ b/tools/deploy/mysql_test/test_suite/update/r/mysql/update2.result @@ -61,12 +61,12 @@ update t1 set a=a+100 where a > 0; EXPLAIN BASIC update t1 set a=a+100 where a=1 and a=2; Query Plan -============================ -|ID|OPERATOR |NAME| ----------------------------- -|0 |UPDATE | | -|1 |└─TABLE RANGE SCAN|t1 | -============================ +===================== +|ID|OPERATOR |NAME| +--------------------- +|0 |UPDATE | | +|1 |└─TABLE GET|t1 | +===================== Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) @@ -338,16 +338,16 @@ Outputs & filters: update t1 set b=b+1 where a>0; EXPLAIN BASIC select * from t1; Query Plan -========================================= -|ID|OPERATOR |NAME | ------------------------------------------ -|0 |DISTRIBUTED TABLE FULL SCAN|t1(gkey)| -========================================= +============================= +|ID|OPERATOR |NAME | +----------------------------- +|0 |TABLE FULL SCAN|t1(gkey)| +============================= Outputs & filters: ------------------------------------- 0 - output([t1.a], [t1.b]), filter(nil), rowset=16 access([t1.a], [t1.b]), partitions(p0) - is_index_back=false, is_global_index=true, keep_ordering=true, + is_index_back=false, is_global_index=true, range_key([t1.b], [t1.a]), range(MIN,MIN ; MAX,MAX)always true select * from t1; +---+------+ @@ -405,16 +405,16 @@ Outputs & filters: update t1 set b=b+1 where a>0; EXPLAIN BASIC select * from t1; Query Plan -========================================= -|ID|OPERATOR |NAME | ------------------------------------------ -|0 |DISTRIBUTED TABLE FULL SCAN|t1(gkey)| -========================================= +============================= +|ID|OPERATOR |NAME | +----------------------------- +|0 |TABLE FULL SCAN|t1(gkey)| +============================= Outputs & filters: ------------------------------------- 0 - output([t1.a], [t1.b]), filter(nil), rowset=16 access([t1.a], [t1.b]), partitions(p0) - is_index_back=false, is_global_index=true, keep_ordering=true, + is_index_back=false, is_global_index=true, range_key([t1.b], [t1.a]), range(MIN,MIN ; MAX,MAX)always true select * from t1; +---+------+ @@ -448,18 +448,26 @@ Outputs & filters: insert into t1 values(1, 1), (2, 2), (3, 3), (4, 4), (5, 5); EXPLAIN BASIC update /*+index(t1 gkey)*/ t1 set b=b+1 where b>0 and b<5; Query Plan -============================================ -|ID|OPERATOR |NAME | --------------------------------------------- -|0 |DISTRIBUTED UPDATE | | -|1 |└─DISTRIBUTED TABLE RANGE SCAN|t1(gkey)| -============================================ +========================================= +|ID|OPERATOR |NAME | +----------------------------------------- +|0 |DISTRIBUTED UPDATE | | +|1 |└─PX COORDINATOR | | +|2 | └─EXCHANGE OUT DISTR |:EX10000| +|3 | └─PX PARTITION ITERATOR| | +|4 | └─TABLE RANGE SCAN |t1(gkey)| +========================================= Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.a, t1.b)}, {gkey: (t1.b, t1.a)})}]), update([t1.b=column_conv(INT,PS:(11,0),NULL,cast(t1.b + 1, INT(-1, 0)))]) 1 - output([t1.a], [t1.b]), filter(nil), rowset=16 + 2 - output([t1.a], [t1.b]), filter(nil), rowset=16 + dop=1 + 3 - output([t1.a], [t1.b]), filter(nil), rowset=16 + force partition granule + 4 - output([t1.a], [t1.b]), filter(nil), rowset=16 access([t1.a], [t1.b]), partitions(p[0-1]) is_index_back=false, is_global_index=true, range_key([t1.b], [t1.a]), range(0,MAX ; 5,MIN), @@ -724,8 +732,8 @@ Outputs & filters: 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.lfdnr, t1.ticket, t1.client, t1.replyto, t1.subject, t1.timestamp, t1.tstamp, t1.status, t1.type, t1.assignment, t1.fupcount, t1.parent, t1.activity, t1.priority, t1.cc, t1.bcc, t1.body, t1.comment, t1.header)})}]), - update([t1.status=column_conv(INT,PS:(3,0),NOT NULL,cast(1, INT(-1, 0)))], [t1.tstamp=column_conv(TIMESTAMP,PS:(19,0),NOT NULL,cast(current_timestamp(), - TIMESTAMP(19, 0)))]) + update([t1.status=column_conv(INT,PS:(3,0),NOT NULL,1)], [t1.tstamp=column_conv(TIMESTAMP,PS:(19,0),NOT NULL,cast(current_timestamp(), TIMESTAMP(19, + 0)))]) 1 - output([t1.lfdnr], [t1.status], [t1.tstamp], [t1.ticket], [t1.client], [t1.replyto], [t1.subject], [t1.timestamp], [t1.type], [t1.assignment], [t1.fupcount], [t1.parent], [t1.activity], [t1.priority], [t1.cc], [t1.bcc], [t1.body], [t1.comment], [t1.header]), filter(nil), rowset=16 access([t1.lfdnr], [t1.status], [t1.tstamp], [t1.ticket], [t1.client], [t1.replyto], [t1.subject], [t1.timestamp], [t1.type], [t1.assignment], [t1.fupcount], @@ -807,7 +815,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.a, t1.b)})}]), - update([t1.b=column_conv(INT,PS:(11,0),NOT NULL,cast(99, INT(-1, 0)))]) + update([t1.b=column_conv(INT,PS:(11,0),NOT NULL,99)]) 1 - output([t1.__pk_increment], [t1.a], [t1.b]), filter(nil), rowset=16 sort_keys([t1.b, ASC]), topn(1) 2 - output([t1.__pk_increment], [t1.b], [t1.a]), filter(nil), rowset=16 @@ -862,7 +870,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.a, t1.b)})}]), - update([t1.b=column_conv(INT,PS:(11,0),NOT NULL,cast(100, INT(-1, 0)))]) + update([t1.b=column_conv(INT,PS:(11,0),NOT NULL,100)]) 1 - output([t1.__pk_increment], [t1.a], [t1.b]), filter(nil), rowset=16 sort_keys([t1.b, DESC]), topn(2) 2 - output([t1.__pk_increment], [t1.b], [t1.a]), filter(nil), rowset=16 @@ -1008,7 +1016,8 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.id_param, t1.nom_option, t1.valid)})}]), - update([t1.nom_option=column_conv(CHAR,utf8mb4_general_ci,length:40,NOT NULL,cast(inner_trim(2, cast(' ', VARCHAR(1048576)), 'test'), CHAR(1048576)))]) + update([t1.nom_option=column_conv(CHAR,utf8mb4_general_ci,length:40,NOT NULL,cast(inner_trim(2, cast(' ', VARCHAR(1048576)), cast('test', VARCHAR(1048576))), + CHAR(1048576)))]) 1 - output([t1.__pk_increment], [t1.nom_option], [t1.id_param], [t1.valid]), filter([t1.valid = 1]), rowset=16 access([t1.__pk_increment], [t1.nom_option], [t1.id_param], [t1.valid]), partitions(p0) limit(1), offset(nil), is_index_back=true, is_global_index=false, filter_before_indexback[false], @@ -1374,7 +1383,8 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t2: ({t2: (t2.__pk_increment, t2.c1, t2.c2)}), hash_distinct}]), - update([t2.c2=column_conv(CHAR,utf8mb4_general_ci,length:6,NULL,cast(inner_trim(2, cast(' ', VARCHAR(1048576)), 't2c2-1'), CHAR(1048576)))]) + update([t2.c2=column_conv(CHAR,utf8mb4_general_ci,length:6,NULL,cast(inner_trim(2, cast(' ', VARCHAR(1048576)), cast('t2c2-1', VARCHAR(1048576))), + CHAR(1048576)))]) 1 - output([t2.__pk_increment], [t2.c1], [t2.c2]), filter(nil), rowset=16 equal_conds([t1.c1 = t2.c1]), other_conds(nil) 2 - output([t2.__pk_increment], [t2.c1], [t2.c2]), filter(nil), rowset=16 @@ -1400,7 +1410,8 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t2: ({t2: (t2.__pk_increment, t2.c1, t2.c2)}), hash_distinct}]), - update([t2.c2=column_conv(CHAR,utf8mb4_general_ci,length:6,NULL,cast(inner_trim(2, cast(' ', VARCHAR(1048576)), 't2c2-1'), CHAR(1048576)))]) + update([t2.c2=column_conv(CHAR,utf8mb4_general_ci,length:6,NULL,cast(inner_trim(2, cast(' ', VARCHAR(1048576)), cast('t2c2-1', VARCHAR(1048576))), + CHAR(1048576)))]) 1 - output([t2.__pk_increment], [t2.c1], [t2.c2]), filter(nil), rowset=16 equal_conds([t1.c1 = t2.c1]), other_conds(nil) 2 - output([t2.__pk_increment], [t2.c1], [t2.c2]), filter(nil), rowset=16 @@ -1855,7 +1866,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.a, t1.b)})}]), - update([t1.a=column_conv(INT,PS:(11,0),NULL,cast(9999, INT(-1, 0)))]) + update([t1.a=column_conv(INT,PS:(11,0),NULL,9999)]) 1 - output([t1.__pk_increment], [t1.a], [t1.b]), filter(nil), rowset=16 access([t1.__pk_increment], [t1.a], [t1.b]), partitions(p0) limit(1), offset(nil), is_index_back=true, is_global_index=false, @@ -1873,7 +1884,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.a, t1.b)})}]), - update([t1.b=column_conv(INT,PS:(11,0),NULL,cast(9999, INT(-1, 0)))]) + update([t1.b=column_conv(INT,PS:(11,0),NULL,9999)]) 1 - output([t1.__pk_increment], [t1.b], [t1.a]), filter(nil), rowset=16 access([t1.__pk_increment], [t1.b], [t1.a]), partitions(p0) limit(1), offset(nil), is_index_back=true, is_global_index=false, @@ -1965,7 +1976,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.a, t1.b)})}]), - update([t1.a=column_conv(INT,PS:(11,0),NULL,cast(t1.a + 10, INT(-1, 0)))], [t1.b=column_conv(INT,PS:(11,0),NULL,cast(1, INT(-1, 0)))]) + update([t1.a=column_conv(INT,PS:(11,0),NULL,cast(t1.a + 10, INT(-1, 0)))], [t1.b=column_conv(INT,PS:(11,0),NULL,1)]) 1 - output([t1.__pk_increment], [t1.a], [t1.b]), filter(nil), rowset=16 access([t1.__pk_increment], [t1.a], [t1.b]), partitions(p0) limit(3), offset(nil), is_index_back=true, is_global_index=false, @@ -1983,7 +1994,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.a, t1.b)})}]), - update([t1.a=column_conv(INT,PS:(11,0),NULL,cast(t1.a + 11, INT(-1, 0)))], [t1.b=column_conv(INT,PS:(11,0),NULL,cast(2, INT(-1, 0)))]) + update([t1.a=column_conv(INT,PS:(11,0),NULL,cast(t1.a + 11, INT(-1, 0)))], [t1.b=column_conv(INT,PS:(11,0),NULL,2)]) 1 - output([t1.__pk_increment], [t1.a], [t1.b]), filter(nil), rowset=16 access([t1.__pk_increment], [t1.a], [t1.b]), partitions(p0) limit(3), offset(nil), is_index_back=true, is_global_index=false, @@ -2001,7 +2012,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.a, t1.b)})}]), - update([t1.a=column_conv(INT,PS:(11,0),NULL,cast(t1.a + 12, INT(-1, 0)))], [t1.b=column_conv(INT,PS:(11,0),NULL,cast(3, INT(-1, 0)))]) + update([t1.a=column_conv(INT,PS:(11,0),NULL,cast(t1.a + 12, INT(-1, 0)))], [t1.b=column_conv(INT,PS:(11,0),NULL,3)]) 1 - output([t1.__pk_increment], [t1.a], [t1.b]), filter(nil), rowset=16 access([t1.__pk_increment], [t1.a], [t1.b]), partitions(p0) limit(3), offset(nil), is_index_back=true, is_global_index=false, @@ -2065,7 +2076,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.f1)})}]), - update([t1.f1=column_conv(DATE,PS:(10,0),NOT NULL,cast('2002-02-02', DATE(-1, -1)))]) + update([t1.f1=column_conv(DATE,PS:(10,0),NOT NULL,'2002-02-02')]) 1 - output([t1.__pk_increment], [t1.f1]), filter([t1.f1 = '0000-00-00']), rowset=16 access([t1.__pk_increment], [t1.f1]), partitions(p0) is_index_back=false, is_global_index=false, filter_before_indexback[false], @@ -2139,7 +2150,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t2: ({t2: (t2.__pk_increment, t2.f2)})}]), - update([t2.f2=column_conv(INT,PS:(11,0),NULL,cast(1, INT(-1, 0)))]) + update([t2.f2=column_conv(INT,PS:(11,0),NULL,1)]) 1 - output([t2.__pk_increment], [t2.f2]), filter(nil), rowset=16 access([t2.__pk_increment], [t2.f2]), partitions(p0) is_index_back=false, is_global_index=false, @@ -2157,7 +2168,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.f1)})}]), - update([t1.f1=column_conv(INT,PS:(11,0),NULL,cast(1, INT(-1, 0)))]) + update([t1.f1=column_conv(INT,PS:(11,0),NULL,1)]) 1 - output([t1.__pk_increment], [t1.f1]), filter([t1.f1 = 3]), rowset=16 access([t1.__pk_increment], [t1.f1]), partitions(p0) is_index_back=false, is_global_index=false, filter_before_indexback[false], @@ -2194,7 +2205,7 @@ Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.__pk_increment, t1.f1, t1.*f2)})}]), - update([t1.*f2=column_conv(INT,PS:(11,0),NULL,cast(1, INT(-1, 0)))]) + update([t1.*f2=column_conv(INT,PS:(11,0),NULL,1)]) 1 - output([t1.__pk_increment], [t1.*f2], [t1.f1]), filter(nil), rowset=16 access([t1.__pk_increment], [t1.*f2], [t1.f1]), partitions(p0) is_index_back=false, is_global_index=false, @@ -2307,11 +2318,11 @@ Outputs & filters: INSERT INTO t1 (user_id) VALUES ('user1'); EXPLAIN BASIC SELECT user_id FROM t1 WHERE request_id=9999999999999; Query Plan -========================== -|ID|OPERATOR |NAME| --------------------------- -|0 |TABLE RANGE SCAN|t1 | -========================== +=================== +|ID|OPERATOR |NAME| +------------------- +|0 |TABLE GET|t1 | +=================== Outputs & filters: ------------------------------------- 0 - output([t1.user_id]), filter(nil), rowset=16 @@ -2326,11 +2337,11 @@ SELECT user_id FROM t1 WHERE request_id=9999999999999; +---------+ EXPLAIN BASIC SELECT user_id FROM t1 WHERE request_id=999999999999999999999999999999; Query Plan -========================== -|ID|OPERATOR |NAME| --------------------------- -|0 |TABLE RANGE SCAN|t1 | -========================== +=================== +|ID|OPERATOR |NAME| +------------------- +|0 |TABLE GET|t1 | +=================== Outputs & filters: ------------------------------------- 0 - output([t1.user_id]), filter(nil), rowset=16 @@ -2345,17 +2356,17 @@ SELECT user_id FROM t1 WHERE request_id=999999999999999999999999999999; +---------+ EXPLAIN BASIC UPDATE t1 SET user_id=null WHERE request_id=9999999999999; Query Plan -============================ -|ID|OPERATOR |NAME| ----------------------------- -|0 |UPDATE | | -|1 |└─TABLE RANGE SCAN|t1 | -============================ +===================== +|ID|OPERATOR |NAME| +--------------------- +|0 |UPDATE | | +|1 |└─TABLE GET|t1 | +===================== Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.request_id, t1.user_id, t1.time_stamp, t1.ip_address)})}]), - update([t1.user_id=column_conv(VARCHAR,utf8mb4_general_ci,length:12,NULL,cast(NULL, VARCHAR(1048576)))]) + update([t1.user_id=column_conv(VARCHAR,utf8mb4_general_ci,length:12,NULL,NULL)]) 1 - output([t1.request_id], [t1.user_id], [t1.time_stamp], [t1.ip_address]), filter(nil), rowset=16 access([t1.request_id], [t1.user_id], [t1.time_stamp], [t1.ip_address]), partitions(p0) is_index_back=false, is_global_index=false, @@ -2364,17 +2375,17 @@ Outputs & filters: UPDATE t1 SET user_id=null WHERE request_id=9999999999999; EXPLAIN BASIC UPDATE t1 SET user_id=null WHERE request_id=999999999999999999999999999999; Query Plan -============================ -|ID|OPERATOR |NAME| ----------------------------- -|0 |UPDATE | | -|1 |└─TABLE RANGE SCAN|t1 | -============================ +===================== +|ID|OPERATOR |NAME| +--------------------- +|0 |UPDATE | | +|1 |└─TABLE GET|t1 | +===================== Outputs & filters: ------------------------------------- 0 - output(nil), filter(nil) table_columns([{t1: ({t1: (t1.request_id, t1.user_id, t1.time_stamp, t1.ip_address)})}]), - update([t1.user_id=column_conv(VARCHAR,utf8mb4_general_ci,length:12,NULL,cast(NULL, VARCHAR(1048576)))]) + update([t1.user_id=column_conv(VARCHAR,utf8mb4_general_ci,length:12,NULL,NULL)]) 1 - output([t1.request_id], [t1.user_id], [t1.time_stamp], [t1.ip_address]), filter(nil), rowset=16 access([t1.request_id], [t1.user_id], [t1.time_stamp], [t1.ip_address]), partitions(p0) is_index_back=false, is_global_index=false, @@ -2797,7 +2808,8 @@ Outputs & filters: table10_bigint.col_char_23_unique_index, table10_bigint.col_char_41_key, table10_bigint.col_char_38_unique_index, table10_bigint.col_char_44_unique_index, table10_bigint.col_bigint_key, table10_bigint.col_char_24_key, table10_bigint.col_char_27_key, table10_bigint.col_char_38_key, table10_bigint.col_char_47, table10_bigint.col_char_31_key, table10_bigint.col_char_34)})}]), - update([table10_bigint.col_char_20=column_conv(CHAR,utf8mb4_general_ci,length:20,NULL,cast(inner_trim(2, cast(' ', VARCHAR(1048576)), 'a'), CHAR(1048576)))]) + update([table10_bigint.col_char_20=column_conv(CHAR,utf8mb4_general_ci,length:20,NULL,cast(inner_trim(2, cast(' ', VARCHAR(1048576)), cast('a', VARCHAR(1048576))), + CHAR(1048576)))]) 1 - output([table10_bigint.pk], [table10_bigint.col_char_20], [table10_bigint.col_char_34_key], [table10_bigint.col_char_24], [table10_bigint.col_char_48_unique_index], [table10_bigint.col_char_26_unique_index], [table10_bigint.col_char_36], [table10_bigint.col_char_26], [table10_bigint.col_char_37], [table10_bigint.col_char_29_key], [table10_bigint.col_char_20_unique_index], [table10_bigint.col_char_39], [table10_bigint.col_char_23], [table10_bigint.col_char_28_key], [table10_bigint.col_char_45], @@ -3196,20 +3208,19 @@ Outputs & filters: gf_ar_mthly_bill.tp, gf_ar_mthly_bill.anl_dmsn4, gf_ar_mthly_bill.bill_mth, gf_ar_mthly_bill.bill_no)}, {idx_tnt_inst_id_inst_id_tp_anl_dmsn_2_bill_mth: (gf_ar_mthly_bill.tnt_inst_id, gf_ar_mthly_bill.inst_id, gf_ar_mthly_bill.tp, gf_ar_mthly_bill.anl_dmsn2, gf_ar_mthly_bill.bill_mth, gf_ar_mthly_bill.bill_no)})}]), - update([gf_ar_mthly_bill.bill_st=column_conv(VARCHAR,utf8mb4_bin,length:2,NOT NULL,cast('01', VARCHAR(1048576)))], [gf_ar_mthly_bill.gmt_pay=column_conv(TIMESTAMP, - PS:(25,6),NULL,cast('2021-05-17 12:09:35', TIMESTAMP(-1, -1)))], [gf_ar_mthly_bill.clcn_bsc_amt=column_conv(DECIMAL_INT,PS:(25,4),NULL,cast('123.12', DECIMAL_INT(25, - 4)))], [gf_ar_mthly_bill.bill_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,1)], [gf_ar_mthly_bill.rcvd_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,2)], [gf_ar_mthly_bill.tax_amt=column_conv(BIGINT, - PS:(20,0),NOT NULL,3)], [gf_ar_mthly_bill.exn_inf=column_conv(VARCHAR,utf8mb4_bin,length:4000,NULL,cast('123456', VARCHAR(1048576)))], [gf_ar_mthly_bill.anl_dmsn1=column_conv(VARCHAR, - utf8mb4_bin,length:1000,NULL,cast('123456', VARCHAR(1048576)))], [gf_ar_mthly_bill.anl_dmsn2=column_conv(VARCHAR,utf8mb4_bin,length:1000,NULL,cast('234567', - VARCHAR(1048576)))], [gf_ar_mthly_bill.anl_dmsn3=column_conv(VARCHAR,utf8mb4_bin,length:1000,NULL,cast('345678', VARCHAR(1048576)))], [gf_ar_mthly_bill.anl_dmsn4=column_conv(VARCHAR, - utf8mb4_bin,length:1000,NULL,cast('456789', VARCHAR(1048576)))], [gf_ar_mthly_bill.last_moder=column_conv(VARCHAR,utf8mb4_bin,length:32,NOT NULL,cast('ylc', - VARCHAR(1048576)))], [gf_ar_mthly_bill.adj_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,4)], [gf_ar_mthly_bill.svc_amt=column_conv(BIGINT,PS:(20,0),NULL,5)], - [gf_ar_mthly_bill.chk_st=column_conv(VARCHAR,utf8mb4_bin,length:2,NULL,cast('06', VARCHAR(1048576)))], [gf_ar_mthly_bill.inv_amt=column_conv(BIGINT,PS:(20, - 0),NULL,6)], [gf_ar_mthly_bill.writingoff_amt=column_conv(BIGINT,PS:(20,0),NULL,7)], [gf_ar_mthly_bill.wrtof_dtl_cnt=column_conv(BIGINT,PS:(20,0),NULL,9)], + update([gf_ar_mthly_bill.bill_st=column_conv(VARCHAR,utf8mb4_bin,length:2,NOT NULL,'01')], [gf_ar_mthly_bill.gmt_pay=column_conv(TIMESTAMP,PS:(25, + 6),NULL,'2021-05-17 12:09:35')], [gf_ar_mthly_bill.clcn_bsc_amt=column_conv(DECIMAL_INT,PS:(25,4),NULL,'123.12')], [gf_ar_mthly_bill.bill_amt=column_conv(BIGINT, + PS:(20,0),NOT NULL,1)], [gf_ar_mthly_bill.rcvd_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,2)], [gf_ar_mthly_bill.tax_amt=column_conv(BIGINT,PS:(20,0),NOT + NULL,3)], [gf_ar_mthly_bill.exn_inf=column_conv(VARCHAR,utf8mb4_bin,length:4000,NULL,'123456')], [gf_ar_mthly_bill.anl_dmsn1=column_conv(VARCHAR,utf8mb4_bin, + length:1000,NULL,'123456')], [gf_ar_mthly_bill.anl_dmsn2=column_conv(VARCHAR,utf8mb4_bin,length:1000,NULL,'234567')], [gf_ar_mthly_bill.anl_dmsn3=column_conv(VARCHAR, + utf8mb4_bin,length:1000,NULL,'345678')], [gf_ar_mthly_bill.anl_dmsn4=column_conv(VARCHAR,utf8mb4_bin,length:1000,NULL,'456789')], [gf_ar_mthly_bill.last_moder=column_conv(VARCHAR, + utf8mb4_bin,length:32,NOT NULL,'ylc')], [gf_ar_mthly_bill.adj_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,4)], [gf_ar_mthly_bill.svc_amt=column_conv(BIGINT, + PS:(20,0),NULL,5)], [gf_ar_mthly_bill.chk_st=column_conv(VARCHAR,utf8mb4_bin,length:2,NULL,'06')], [gf_ar_mthly_bill.inv_amt=column_conv(BIGINT,PS:(20,0), + NULL,6)], [gf_ar_mthly_bill.writingoff_amt=column_conv(BIGINT,PS:(20,0),NULL,7)], [gf_ar_mthly_bill.wrtof_dtl_cnt=column_conv(BIGINT,PS:(20,0),NULL,9)], [gf_ar_mthly_bill.to_wrtof_dtl_cnt=column_conv(BIGINT,PS:(20,0),NULL,8)], [gf_ar_mthly_bill.chking_amt=column_conv(BIGINT,PS:(20,0),NULL,10)], [gf_ar_mthly_bill.chked_amt=column_conv(BIGINT, PS:(20,0),NULL,11)], [gf_ar_mthly_bill.frz_amt=column_conv(BIGINT,PS:(20,0),NULL,12)], [gf_ar_mthly_bill.svc_bill_amt=column_conv(BIGINT,PS:(20,0),NULL, - 13)], [gf_ar_mthly_bill.gmt_modified=column_conv(TIMESTAMP,PS:(25,6),NOT NULL,timestamp_nvl(cast('2021-05-17 12:09:34', TIMESTAMP(-1, -1)), cast(current_timestamp(), - TIMESTAMP(25, 6))))]) + 13)], [gf_ar_mthly_bill.gmt_modified=column_conv(TIMESTAMP,PS:(25,6),NOT NULL,timestamp_nvl('2021-05-17 12:09:34', cast(current_timestamp(), TIMESTAMP(25, + 6))))]) 1 - output([gf_ar_mthly_bill.tnt_inst_id], [gf_ar_mthly_bill.bill_no], [column_conv(VARCHAR,utf8mb4_bin,length:4,NULL,substr(gf_ar_mthly_bill.bill_no, 23, 2))], [gf_ar_mthly_bill.bill_st], [gf_ar_mthly_bill.gmt_pay], [gf_ar_mthly_bill.clcn_bsc_amt], [gf_ar_mthly_bill.bill_amt], [gf_ar_mthly_bill.rcvd_amt], [gf_ar_mthly_bill.tax_amt], [gf_ar_mthly_bill.exn_inf], [gf_ar_mthly_bill.anl_dmsn1], [gf_ar_mthly_bill.anl_dmsn2], [gf_ar_mthly_bill.anl_dmsn3], [gf_ar_mthly_bill.anl_dmsn4], @@ -3374,20 +3385,19 @@ Outputs & filters: gf_ar_mthly_bill.tp, gf_ar_mthly_bill.anl_dmsn4, gf_ar_mthly_bill.bill_mth, gf_ar_mthly_bill.bill_no)}, {idx_tnt_inst_id_inst_id_tp_anl_dmsn_2_bill_mth: (gf_ar_mthly_bill.tnt_inst_id, gf_ar_mthly_bill.inst_id, gf_ar_mthly_bill.tp, gf_ar_mthly_bill.anl_dmsn2, gf_ar_mthly_bill.bill_mth, gf_ar_mthly_bill.bill_no)})}]), - update([gf_ar_mthly_bill.bill_st=column_conv(VARCHAR,utf8mb4_bin,length:2,NOT NULL,cast('01', VARCHAR(1048576)))], [gf_ar_mthly_bill.gmt_pay=column_conv(TIMESTAMP, - PS:(25,6),NULL,cast('2021-05-17 12:09:35', TIMESTAMP(-1, -1)))], [gf_ar_mthly_bill.clcn_bsc_amt=column_conv(DECIMAL_INT,PS:(25,4),NULL,cast('123.12', DECIMAL_INT(25, - 4)))], [gf_ar_mthly_bill.bill_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,1)], [gf_ar_mthly_bill.rcvd_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,2)], [gf_ar_mthly_bill.tax_amt=column_conv(BIGINT, - PS:(20,0),NOT NULL,3)], [gf_ar_mthly_bill.exn_inf=column_conv(VARCHAR,utf8mb4_bin,length:4000,NULL,cast('123456', VARCHAR(1048576)))], [gf_ar_mthly_bill.anl_dmsn1=column_conv(VARCHAR, - utf8mb4_bin,length:1000,NULL,cast('123456', VARCHAR(1048576)))], [gf_ar_mthly_bill.anl_dmsn2=column_conv(VARCHAR,utf8mb4_bin,length:1000,NULL,cast('234567', - VARCHAR(1048576)))], [gf_ar_mthly_bill.anl_dmsn3=column_conv(VARCHAR,utf8mb4_bin,length:1000,NULL,cast('345678', VARCHAR(1048576)))], [gf_ar_mthly_bill.anl_dmsn4=column_conv(VARCHAR, - utf8mb4_bin,length:1000,NULL,cast('456789', VARCHAR(1048576)))], [gf_ar_mthly_bill.last_moder=column_conv(VARCHAR,utf8mb4_bin,length:32,NOT NULL,cast('ylc', - VARCHAR(1048576)))], [gf_ar_mthly_bill.adj_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,4)], [gf_ar_mthly_bill.svc_amt=column_conv(BIGINT,PS:(20,0),NULL,5)], - [gf_ar_mthly_bill.chk_st=column_conv(VARCHAR,utf8mb4_bin,length:2,NULL,cast('06', VARCHAR(1048576)))], [gf_ar_mthly_bill.inv_amt=column_conv(BIGINT,PS:(20, - 0),NULL,6)], [gf_ar_mthly_bill.writingoff_amt=column_conv(BIGINT,PS:(20,0),NULL,7)], [gf_ar_mthly_bill.wrtof_dtl_cnt=column_conv(BIGINT,PS:(20,0),NULL,9)], + update([gf_ar_mthly_bill.bill_st=column_conv(VARCHAR,utf8mb4_bin,length:2,NOT NULL,'01')], [gf_ar_mthly_bill.gmt_pay=column_conv(TIMESTAMP,PS:(25, + 6),NULL,'2021-05-17 12:09:35')], [gf_ar_mthly_bill.clcn_bsc_amt=column_conv(DECIMAL_INT,PS:(25,4),NULL,'123.12')], [gf_ar_mthly_bill.bill_amt=column_conv(BIGINT, + PS:(20,0),NOT NULL,1)], [gf_ar_mthly_bill.rcvd_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,2)], [gf_ar_mthly_bill.tax_amt=column_conv(BIGINT,PS:(20,0),NOT + NULL,3)], [gf_ar_mthly_bill.exn_inf=column_conv(VARCHAR,utf8mb4_bin,length:4000,NULL,'123456')], [gf_ar_mthly_bill.anl_dmsn1=column_conv(VARCHAR,utf8mb4_bin, + length:1000,NULL,'123456')], [gf_ar_mthly_bill.anl_dmsn2=column_conv(VARCHAR,utf8mb4_bin,length:1000,NULL,'234567')], [gf_ar_mthly_bill.anl_dmsn3=column_conv(VARCHAR, + utf8mb4_bin,length:1000,NULL,'345678')], [gf_ar_mthly_bill.anl_dmsn4=column_conv(VARCHAR,utf8mb4_bin,length:1000,NULL,'456789')], [gf_ar_mthly_bill.last_moder=column_conv(VARCHAR, + utf8mb4_bin,length:32,NOT NULL,'ylc')], [gf_ar_mthly_bill.adj_amt=column_conv(BIGINT,PS:(20,0),NOT NULL,4)], [gf_ar_mthly_bill.svc_amt=column_conv(BIGINT, + PS:(20,0),NULL,5)], [gf_ar_mthly_bill.chk_st=column_conv(VARCHAR,utf8mb4_bin,length:2,NULL,'06')], [gf_ar_mthly_bill.inv_amt=column_conv(BIGINT,PS:(20,0), + NULL,6)], [gf_ar_mthly_bill.writingoff_amt=column_conv(BIGINT,PS:(20,0),NULL,7)], [gf_ar_mthly_bill.wrtof_dtl_cnt=column_conv(BIGINT,PS:(20,0),NULL,9)], [gf_ar_mthly_bill.to_wrtof_dtl_cnt=column_conv(BIGINT,PS:(20,0),NULL,8)], [gf_ar_mthly_bill.chking_amt=column_conv(BIGINT,PS:(20,0),NULL,10)], [gf_ar_mthly_bill.chked_amt=column_conv(BIGINT, PS:(20,0),NULL,11)], [gf_ar_mthly_bill.frz_amt=column_conv(BIGINT,PS:(20,0),NULL,12)], [gf_ar_mthly_bill.svc_bill_amt=column_conv(BIGINT,PS:(20,0),NULL, - 13)], [gf_ar_mthly_bill.gmt_modified=column_conv(TIMESTAMP,PS:(25,6),NOT NULL,timestamp_nvl(cast('2021-05-17 12:09:34', TIMESTAMP(-1, -1)), cast(current_timestamp(), - TIMESTAMP(25, 6))))]) + 13)], [gf_ar_mthly_bill.gmt_modified=column_conv(TIMESTAMP,PS:(25,6),NOT NULL,timestamp_nvl('2021-05-17 12:09:34', cast(current_timestamp(), TIMESTAMP(25, + 6))))]) 1 - output([gf_ar_mthly_bill.tnt_inst_id], [gf_ar_mthly_bill.bill_no], [column_conv(VARCHAR,utf8mb4_bin,length:4,NULL,substr(gf_ar_mthly_bill.bill_no, 23, 2))], [gf_ar_mthly_bill.bill_st], [gf_ar_mthly_bill.gmt_pay], [gf_ar_mthly_bill.clcn_bsc_amt], [gf_ar_mthly_bill.bill_amt], [gf_ar_mthly_bill.rcvd_amt], [gf_ar_mthly_bill.tax_amt], [gf_ar_mthly_bill.exn_inf], [gf_ar_mthly_bill.anl_dmsn1], [gf_ar_mthly_bill.anl_dmsn2], [gf_ar_mthly_bill.anl_dmsn3], [gf_ar_mthly_bill.anl_dmsn4], diff --git a/unittest/sql/optimizer/test_optimizer_utils.cpp b/unittest/sql/optimizer/test_optimizer_utils.cpp index 6b1f490571..3c2f72c91d 100644 --- a/unittest/sql/optimizer/test_optimizer_utils.cpp +++ b/unittest/sql/optimizer/test_optimizer_utils.cpp @@ -154,7 +154,7 @@ int TestOptimizerUtils::generate_logical_plan(ObResultSet &result, //ObIAllocato memory_parser = allocator_.total() - memory_parser; memory_resolver = allocator_.total(); - resolver_ctx.query_ctx_->question_marks_count_ = param_store.count(); + resolver_ctx.query_ctx_->set_questionmark_count(param_store.count()); ObPhysicalPlanCtx *pctx = exec_ctx_.get_physical_plan_ctx(); if (OB_SUCC(ret)) { pctx->set_original_param_cnt(pctx->get_param_store().count()); diff --git a/unittest/sql/parser/test_sql_fast_parser.cpp b/unittest/sql/parser/test_sql_fast_parser.cpp index 14b6b04d2f..62f62d0577 100644 --- a/unittest/sql/parser/test_sql_fast_parser.cpp +++ b/unittest/sql/parser/test_sql_fast_parser.cpp @@ -34,6 +34,14 @@ extern "C" sleep(120); } } + extern int ob_backtrace_c(void **buffer, int size) + { + return 0; + } + extern char *parray_c(char *buf, int64_t len, int64_t *array, int size) + { + return NULL; + } } using namespace oceanbase::common; diff --git a/unittest/sql/resolver/expr/test_raw_expr_resolver.result b/unittest/sql/resolver/expr/test_raw_expr_resolver.result index 5e1ea84d4d..4c216a0ce7 100644 --- a/unittest/sql/resolver/expr/test_raw_expr_resolver.result +++ b/unittest/sql/resolver/expr/test_raw_expr_resolver.result @@ -54,7 +54,8 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 }, { "item_type":"T_NUMBER", @@ -84,7 +85,8 @@ ], "value": { "DECIMAL":"1" - } + }, + "expr_hash":0 }, { "item_type":"T_VARCHAR", @@ -116,9 +118,11 @@ "VARCHAR":"\", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } [1] '1' like '1' { @@ -178,7 +182,8 @@ "VARCHAR":"1", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 }, { "item_type":"T_VARCHAR", @@ -210,7 +215,8 @@ "VARCHAR":"1", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 }, { "item_type":"T_VARCHAR", @@ -242,9 +248,11 @@ "VARCHAR":"\", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } [2] 2 in (1, 2, 3) { @@ -304,7 +312,8 @@ ], "value": { "BIGINT":2 - } + }, + "expr_hash":0 }, { "item_type":"T_OP_ROW", @@ -361,7 +370,8 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -391,7 +401,8 @@ ], "value": { "BIGINT":2 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -421,11 +432,14 @@ ], "value": { "BIGINT":3 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [3] 2 not in (1, 2, 3) { @@ -485,7 +499,8 @@ ], "value": { "BIGINT":2 - } + }, + "expr_hash":0 }, { "item_type":"T_OP_ROW", @@ -542,7 +557,8 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -572,7 +588,8 @@ ], "value": { "BIGINT":2 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -602,11 +619,14 @@ ], "value": { "BIGINT":3 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [4] 1 or 1 { @@ -694,9 +714,11 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_OP_BOOL", @@ -754,11 +776,14 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [5] 100 and 0 { @@ -844,9 +869,11 @@ ], "value": { "BIGINT":100 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_OP_BOOL", @@ -904,11 +931,14 @@ ], "value": { "BIGINT":0 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [6] 100 or 0 and 100 { @@ -996,9 +1026,11 @@ ], "value": { "BIGINT":100 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_OP_AND", @@ -1083,9 +1115,11 @@ ], "value": { "BIGINT":0 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_OP_BOOL", @@ -1143,13 +1177,17 @@ ], "value": { "BIGINT":100 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [7] case name when 'sam' then 'yong' when 'lee' then 'handsome' else 'good' end { @@ -1224,7 +1262,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, "default": { "item_type":"T_VARCHAR", @@ -1256,7 +1295,8 @@ "VARCHAR":"good", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 }, "when": [ { @@ -1289,7 +1329,8 @@ "VARCHAR":"sam", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 }, { "item_type":"T_VARCHAR", @@ -1321,7 +1362,8 @@ "VARCHAR":"lee", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 } ], "then": [ @@ -1355,7 +1397,8 @@ "VARCHAR":"yong", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 }, { "item_type":"T_VARCHAR", @@ -1387,10 +1430,12 @@ "VARCHAR":"handsome", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 } ], - "decode":false + "decode":false, + "expr_hash":0 } [8] case when 1>0 then 'true' else 'false' end { @@ -1450,7 +1495,8 @@ "VARCHAR":"false", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 }, "when": [ { @@ -1508,7 +1554,8 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -1538,9 +1585,11 @@ ], "value": { "BIGINT":0 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } ], "then": [ @@ -1574,10 +1623,12 @@ "VARCHAR":"true", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 } ], - "decode":false + "decode":false, + "expr_hash":0 } [9] now() { @@ -1618,7 +1669,8 @@ "dblink_id":-1, "local_session_var": { }, "local_session_var_id":-1, - "mview_id":-1 + "mview_id":-1, + "expr_hash":0 } [10] utc_timestamp() { @@ -1659,7 +1711,8 @@ "dblink_id":-1, "local_session_var": { }, "local_session_var_id":-1, - "mview_id":-1 + "mview_id":-1, + "expr_hash":0 } [11] floor(3.14) { @@ -1720,7 +1773,8 @@ ], "value": { "DECIMAL":"3.14" - } + }, + "expr_hash":0 } ], "enum_set_values": [ @@ -1729,7 +1783,8 @@ "dblink_id":-1, "local_session_var": { }, "local_session_var_id":-1, - "mview_id":-1 + "mview_id":-1, + "expr_hash":0 } [12] count(*) { @@ -1773,7 +1828,8 @@ "type":0 }, "expr_in_inner_stmt":false, - "pl_agg_udf_expr":null + "pl_agg_udf_expr":null, + "expr_hash":0 } [13] max(c1) { @@ -1851,7 +1907,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 } ], "distinct":false, @@ -1866,7 +1923,8 @@ "type":0 }, "expr_in_inner_stmt":false, - "pl_agg_udf_expr":null + "pl_agg_udf_expr":null, + "expr_hash":0 } [14] c1 in (select t1 from table1) { @@ -1943,7 +2001,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_REF_QUERY", @@ -1981,9 +2040,11 @@ "enum_set_values": [ ], "children": [ - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [15] 1=(select c1 from table1 where c2>20) { @@ -2042,7 +2103,8 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 }, { "item_type":"T_REF_QUERY", @@ -2080,9 +2142,11 @@ "enum_set_values": [ ], "children": [ - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [16] (t1,t2)=(select c1, c2 from table1) { @@ -2185,7 +2249,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_REF_COLUMN", @@ -2233,9 +2298,11 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_REF_QUERY", @@ -2273,9 +2340,11 @@ "enum_set_values": [ ], "children": [ - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [17] 10 { @@ -2306,7 +2375,8 @@ ], "value": { "BIGINT":10 - } + }, + "expr_hash":0 } [18] @@auto_increment_increment { @@ -2369,7 +2439,8 @@ "VARCHAR":"auto_increment_increment", "collation":"utf8mb4_general_ci", "coercibility":"SYSCONST" - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -2399,7 +2470,8 @@ ], "value": { "BIGINT":0 - } + }, + "expr_hash":0 } ], "enum_set_values": [ @@ -2408,7 +2480,8 @@ "dblink_id":-1, "local_session_var": { }, "local_session_var_id":-1, - "mview_id":-1 + "mview_id":-1, + "expr_hash":0 } [19] @a { @@ -2473,7 +2546,8 @@ "coercibility":"IMPLICIT" }, "is_contain_assign":false, - "query_has_udf":false + "query_has_udf":false, + "expr_hash":0 } ], "enum_set_values": [ @@ -2482,7 +2556,8 @@ "dblink_id":-1, "local_session_var": { }, "local_session_var_id":-1, - "mview_id":-1 + "mview_id":-1, + "expr_hash":0 } [20] c1 { @@ -2531,7 +2606,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 } [21] 10+10 { @@ -2589,7 +2665,8 @@ ], "value": { "BIGINT":10 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -2619,9 +2696,11 @@ ], "value": { "BIGINT":10 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } [22] not 10 { @@ -2709,11 +2788,14 @@ ], "value": { "BIGINT":10 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [23] c1+c2=c3+c4 { @@ -2815,7 +2897,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_REF_COLUMN", @@ -2863,9 +2946,11 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_OP_ADD", @@ -2939,7 +3024,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_REF_COLUMN", @@ -2987,11 +3073,14 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [24] c1=3 { @@ -3068,7 +3157,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_INT", @@ -3098,9 +3188,11 @@ ], "value": { "BIGINT":3 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } [25] c1>1 { @@ -3177,7 +3269,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_INT", @@ -3207,9 +3300,11 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } [26] c1 > c2 { @@ -3284,7 +3379,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_REF_COLUMN", @@ -3332,9 +3428,11 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 } - ] + ], + "expr_hash":0 } [27] c1 in (1,2,3,4) { @@ -3413,7 +3511,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_OP_ROW", @@ -3470,7 +3569,8 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -3500,7 +3600,8 @@ ], "value": { "BIGINT":2 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -3530,7 +3631,8 @@ ], "value": { "BIGINT":3 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -3560,11 +3662,14 @@ ], "value": { "BIGINT":4 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [28] c1 between 2 and 10 { @@ -3668,7 +3773,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_INT", @@ -3698,9 +3804,11 @@ ], "value": { "BIGINT":2 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_OP_LE", @@ -3776,7 +3884,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_INT", @@ -3806,11 +3915,14 @@ ], "value": { "BIGINT":10 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [29] 10+10+c1 { @@ -3896,7 +4008,8 @@ ], "value": { "BIGINT":10 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -3926,9 +4039,11 @@ ], "value": { "BIGINT":10 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_REF_COLUMN", @@ -3976,9 +4091,11 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 } - ] + ], + "expr_hash":0 } [30] c1 = 1 + 2 { @@ -4056,7 +4173,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_OP_ADD", @@ -4113,7 +4231,8 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -4143,11 +4262,14 @@ ], "value": { "BIGINT":2 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [31] c1 between 10+10 and 30 { @@ -4253,7 +4375,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_OP_ADD", @@ -4310,7 +4433,8 @@ ], "value": { "BIGINT":10 - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -4340,11 +4464,14 @@ ], "value": { "BIGINT":10 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_OP_LE", @@ -4420,7 +4547,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_INT", @@ -4450,11 +4578,14 @@ ], "value": { "BIGINT":30 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [32] 1+c1 > ? and 'abc' || c2 = 'def' { @@ -4600,7 +4731,8 @@ ], "value": { "BIGINT":1 - } + }, + "expr_hash":0 }, { "item_type":"T_REF_COLUMN", @@ -4648,9 +4780,11 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_QUESTIONMARK", @@ -4682,9 +4816,11 @@ ], "value": { "UNKNOWN":0 - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_OP_BOOL", @@ -4744,11 +4880,14 @@ "VARCHAR":"abc", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 }, { "item_type":"T_OP_EQ", @@ -4824,7 +4963,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_VARCHAR", @@ -4856,11 +4996,14 @@ "VARCHAR":"def", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [33] binary binary 'abc' collate utf8_general_ci collate utf8_bin { @@ -5013,7 +5156,8 @@ "VARCHAR":"abc", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 }, { "item_type":"T_INT", @@ -5043,7 +5187,8 @@ ], "value": { "BIGINT":45 - } + }, + "expr_hash":0 } ], "enum_set_values": [ @@ -5052,7 +5197,8 @@ "dblink_id":-1, "local_session_var": { }, "local_session_var_id":-1, - "mview_id":-1 + "mview_id":-1, + "expr_hash":0 }, { "item_type":"T_INT", @@ -5082,7 +5228,8 @@ ], "value": { "BIGINT":46 - } + }, + "expr_hash":0 } ], "enum_set_values": [ @@ -5091,7 +5238,8 @@ "dblink_id":-1, "local_session_var": { }, "local_session_var_id":-1, - "mview_id":-1 + "mview_id":-1, + "expr_hash":0 }, { "item_type":"T_INT", @@ -5121,7 +5269,8 @@ ], "value": { "BIGINT":-4290838506 - } + }, + "expr_hash":0 } ], "enum_set_values": [ @@ -5130,7 +5279,8 @@ "dblink_id":-1, "local_session_var": { }, "local_session_var_id":-1, - "mview_id":-1 + "mview_id":-1, + "expr_hash":0 }, { "item_type":"T_INT", @@ -5160,7 +5310,8 @@ ], "value": { "BIGINT":-4290838506 - } + }, + "expr_hash":0 } ], "enum_set_values": [ @@ -5169,7 +5320,8 @@ "dblink_id":-1, "local_session_var": { }, "local_session_var_id":-1, - "mview_id":-1 + "mview_id":-1, + "expr_hash":0 } [34] X not like Y { @@ -5274,7 +5426,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_REF_COLUMN", @@ -5322,7 +5475,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_VARCHAR", @@ -5354,11 +5508,14 @@ "VARCHAR":"\", "collation":"utf8mb4_general_ci", "coercibility":"COERCIBLE" - } + }, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } [35] Z not regexp A { @@ -5461,7 +5618,8 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 }, { "item_type":"T_REF_COLUMN", @@ -5509,9 +5667,12 @@ "is_mul_key_column":false, "is_strict_json_column":0, "srs_id":-1, - "udt_set_id":0 + "udt_set_id":0, + "expr_hash":0 } - ] + ], + "expr_hash":0 } - ] + ], + "expr_hash":0 } diff --git a/unittest/sql/rewrite/CMakeLists.txt b/unittest/sql/rewrite/CMakeLists.txt index b2fe186369..c44b899d6b 100644 --- a/unittest/sql/rewrite/CMakeLists.txt +++ b/unittest/sql/rewrite/CMakeLists.txt @@ -4,5 +4,6 @@ function(rewrite_unittest case) endfunction() rewrite_unittest(test_query_range) +rewrite_unittest(test_raw_expr_equal) # Fix me: disable for now #rewrite_unittest(test_transformer) diff --git a/unittest/sql/rewrite/test_raw_expr_equal.cpp b/unittest/sql/rewrite/test_raw_expr_equal.cpp new file mode 100644 index 0000000000..fa2db93b1d --- /dev/null +++ b/unittest/sql/rewrite/test_raw_expr_equal.cpp @@ -0,0 +1,288 @@ +/** + * Copyright (c) 2021 OceanBase + * OceanBase CE is licensed under Mulan PubL v2. + * You can use this software according to the terms and conditions of the Mulan PubL v2. + * You may obtain a copy of Mulan PubL v2 at: + * http://license.coscl.org.cn/MulanPubL-2.0 + * THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND, + * EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT, + * MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE. + * See the Mulan PubL v2 for more details. + */ + +#define USING_LOG_PREFIX SQL +#include +#define protected public +#define private public +#include "sql/test_sql_utils.h" +#include "common/object/ob_obj_type.h" +#include "lib/utility/ob_test_util.h" +#include "sql/ob_sql_init.h" +#include "sql/engine/expr/ob_expr_result_type_util.h" +#include "sql/resolver/expr/ob_raw_expr_util.h" +#include "lib/string/ob_sql_string.h" +#undef protected +#undef private +using namespace oceanbase; +using namespace oceanbase::common; +using namespace oceanbase::lib; +using namespace oceanbase::sql; +using namespace oceanbase::share::schema; + +const int64_t BUF_LEN = 102400; +class ObRawExprEqualTest: public test::TestSqlUtils, public ::testing::Test +{ +public: + + ObRawExprEqualTest() {}; + virtual ~ObRawExprEqualTest() {}; + virtual void SetUp(); + virtual void TearDown(); + int set_equal_param_exprs(ObOpRawExpr *eq_expr, ObRawExpr *param1, ObRawExpr *param2); + int free_cast_expr(ObOpRawExpr *eq_expr); +}; + +void ObRawExprEqualTest::SetUp() +{ + init(); +} + +void ObRawExprEqualTest::TearDown() +{ +} + +int ObRawExprEqualTest::set_equal_param_exprs(ObOpRawExpr *eq_expr, ObRawExpr *param1, ObRawExpr *param2) +{ + int ret = OB_SUCCESS; + if (OB_ISNULL(eq_expr) || OB_ISNULL(param1) || OB_ISNULL(param2)) { + ret = OB_INVALID_ARGUMENT; + LOG_WARN("invalid argument", K(ret), K(eq_expr), K(param1), K(param2)); + } else if (FALSE_IT(eq_expr->get_param_exprs().reset())) { + // do nothing + } else if (OB_FAIL(eq_expr->set_param_exprs(param1, param2))) { + LOG_WARN("failed to set param exprs", K(ret)); + } else if (OB_FAIL(eq_expr->formalize(&session_info_))) { + LOG_WARN("failed to formalize expr", K(ret)); + } + return ret; +} + +class ObExprResTypeIterator +{ +public: + ObExprResTypeIterator(); + ~ObExprResTypeIterator() {} + + int next(ObExprResType &res_type); +private: + int set_res_type(ObExprResType &res_type); + int update_type_idx(); +private: + const static int64_t COLLATION_TYPE_COUNT = 8; + const static int64_t DOUBLE_SCALE_COUNT = 4; + const static ObCollationType COLLATION_TYPES[COLLATION_TYPE_COUNT]; + const static int64_t DOUBLE_SCALES[DOUBLE_SCALE_COUNT]; +private: + ObObjType type_; + int64_t sub_type_idx_; +}; + +ObExprResTypeIterator::ObExprResTypeIterator() + : type_(ObTinyIntType), + sub_type_idx_(0) +{ +} + +const ObCollationType ObExprResTypeIterator::COLLATION_TYPES[COLLATION_TYPE_COUNT] = { + CS_TYPE_UTF8MB4_GENERAL_CI, + CS_TYPE_UTF8MB4_BIN, + CS_TYPE_LATIN1_BIN, + CS_TYPE_GBK_CHINESE_CI, + CS_TYPE_GBK_BIN, + CS_TYPE_UTF16_GENERAL_CI, + CS_TYPE_UTF16_BIN, + CS_TYPE_BINARY +}; + +const int64_t ObExprResTypeIterator::DOUBLE_SCALES[DOUBLE_SCALE_COUNT] = { + SCALE_UNKNOWN_YET, + 0, + 10, + OB_MAX_DOUBLE_FLOAT_SCALE +}; + +int ObExprResTypeIterator::next(ObExprResType &res_type) +{ + int ret = OB_SUCCESS; + res_type.reset(); + if (ObMaxType == type_) { + ret = OB_ITER_END; + } else if (OB_FAIL(set_res_type(res_type))) { + LOG_WARN("failed to set res type", K(ret)); + } else if (OB_FAIL(update_type_idx())) { + LOG_WARN("failed to update type idx", K(ret)); + } + return ret; +} + +int ObExprResTypeIterator::set_res_type(ObExprResType &res_type) +{ + int ret = OB_SUCCESS; + res_type.set_type(type_); + res_type.set_precision(ObAccuracy::DDL_DEFAULT_ACCURACY[type_].precision_); + res_type.set_scale(ObAccuracy::DDL_DEFAULT_ACCURACY[type_].scale_); + res_type.set_collation_type(CS_TYPE_BINARY); + res_type.set_collation_level(ObRawExprUtils::get_column_collation_level(type_)); + if (ob_is_nstring(type_)) { + res_type.set_collation_type(CS_TYPE_UTF16_BIN); + res_type.set_length(100); + } else if (ob_is_string_or_lob_type(type_)) { + res_type.set_collation_type(COLLATION_TYPES[sub_type_idx_]); + res_type.set_length(100); + } else if (ob_is_double_type(type_)) { + res_type.set_scale(DOUBLE_SCALES[sub_type_idx_]); + } + return ret; +} + +int ObExprResTypeIterator::update_type_idx() +{ + int ret = OB_SUCCESS; + ++sub_type_idx_; + if ((ob_is_string_or_lob_type(type_) && !ob_is_nstring(type_) + && sub_type_idx_ < 1) || + (ob_is_double_type(type_) && sub_type_idx_ < 1)) { + // do nothing + } else { + type_ = static_cast(type_ + 1); + sub_type_idx_ = 0; + } + return ret; +} + +TEST_F(ObRawExprEqualTest, equal_compare_func) +{ + int ret = OB_SUCCESS; + ObExprResType type1; + ObExprResType type2; + ObExprResTypeIterator iter1; + while (OB_SUCC(ret)) { + ObExprResTypeIterator iter2; + if (OB_FAIL(iter1.next(type1))) { + LOG_WARN("failed to iter type A", K(ret)); + break; + } + while (OB_SUCC(ret)) { + if (OB_FAIL(iter2.next(type2))) { + LOG_WARN("failed to iter type B", K(ret)); + break; + } else { + bool has_lob_header = type1.has_lob_header() || type2.has_lob_header(); + auto func_ptr = ObExprCmpFuncsHelper::get_eval_expr_cmp_func(type1.get_type(), + type2.get_type(), + type1.get_precision(), + type2.get_precision(), + type1.get_scale(), + type2.get_scale(), + CO_EQ, + lib::is_oracle_mode(), + CS_TYPE_BINARY, + has_lob_header); + bool has_cmp_func = NULL != func_ptr; + ObObjType equal_type = ObMaxType; + ASSERT_EQ(OB_SUCCESS, ObExprResultTypeUtil::get_relational_equal_type( + equal_type, type1.get_type(), type2.get_type())); + bool can_deduce_equal = ObMaxType != equal_type; + if (can_deduce_equal && !has_cmp_func) { + EXPECT_EQ(can_deduce_equal, has_cmp_func); + fprintf(stdout, "unexpected cmp func %d %d %d %d %d\n", + type1.get_type(), type1.get_collation_type(), + type2.get_type(), type2.get_collation_type(), + equal_type); + LOG_WARN("unexpected cmp func", K(type1.get_type()), K(type2.get_type()), KP(func_ptr)); + } + } + } + if (OB_ITER_END == ret) { + ret = OB_SUCCESS; + } + } + EXPECT_EQ(OB_ITER_END, ret); +} + +TEST_F(ObRawExprEqualTest, type_comparable) +{ + int ret = OB_SUCCESS; + ObExprResTypeIterator iter1; + ObColumnRefRawExpr *expr1 = NULL; + ObColumnRefRawExpr *expr2 = NULL; + ObOpRawExpr *eq_expr = NULL; + ASSERT_EQ(OB_SUCCESS, expr_factory_.create_raw_expr(T_REF_COLUMN, expr1)); + ASSERT_EQ(OB_SUCCESS, expr_factory_.create_raw_expr(T_REF_COLUMN, expr2)); + bool can_compare = true; + ObObjType equal_type = ObMaxType; + const ObExprResType &type1 = expr1->get_result_type(); + const ObExprResType &type2 = expr2->get_result_type(); + while (OB_SUCC(ret)) { + ObExprResTypeIterator iter2; + ObArenaAllocator allocator; + ObRawExprFactory expr_factory(allocator); + ASSERT_EQ(OB_SUCCESS, expr_factory.create_raw_expr(T_OP_EQ, eq_expr)); + if (OB_FAIL(iter1.next(expr1->result_type_))) { + LOG_WARN("failed to iter type A", K(ret)); + break; + } + while (OB_SUCC(ret)) + { + can_compare = true; + if (OB_FAIL(iter2.next(expr2->result_type_))) { + LOG_WARN("failed to iter type B", K(ret)); + break; + } else if (OB_FAIL(set_equal_param_exprs(eq_expr, expr1, expr2))) { + LOG_WARN("failed to set equal param exprs", K(ret)); + // unable to compare, just continue + ret = OB_SUCCESS; + can_compare = false; + } else if (eq_expr->get_param_expr(0) != expr1 || eq_expr->get_param_expr(1) != expr2) { + can_compare = false; + } + ASSERT_EQ(OB_SUCCESS, ObExprResultTypeUtil::get_relational_equal_type(equal_type, + type1.get_type(), type2.get_type())); + if (!can_compare && ObMaxType != equal_type) { + EXPECT_EQ(ObMaxType, equal_type); + fprintf(stdout, "unexpected equal type %d %d %d %d %d\n", + type1.get_type(), type1.get_collation_type(), + type2.get_type(), type2.get_collation_type(), + equal_type); + LOG_INFO("unexpected equal type", K(can_compare), K(equal_type), + K(type1), K(type2), KPC(eq_expr)); + } + } + if (OB_ITER_END == ret) { + ret = OB_SUCCESS; + } + } + EXPECT_EQ(OB_ITER_END, ret); +} + +int main(int argc, char **argv) +{ + int ret = 0; + system("rm -rf test_raw_expr_equal.log*"); + OB_LOGGER.set_file_name("test_raw_expr_equal.log", true); + if(argc >= 2) { + OB_LOGGER.set_log_level(argv[1]); + } else { + OB_LOGGER.set_log_level("INFO"); + } + init_sql_factories(); + ContextParam param; + param.set_mem_attr(1001, "Transformer", ObCtxIds::WORK_AREA) + .set_page_size(OB_MALLOC_BIG_BLOCK_SIZE); + + ::testing::InitGoogleTest(&argc,argv); + CREATE_WITH_TEMP_CONTEXT(param) { + ret = RUN_ALL_TESTS(); + } + return ret; +} diff --git a/unittest/sql/rewrite/test_transformer.cpp b/unittest/sql/rewrite/test_transformer.cpp index 8be15a6f1a..1fa9e9547b 100644 --- a/unittest/sql/rewrite/test_transformer.cpp +++ b/unittest/sql/rewrite/test_transformer.cpp @@ -239,7 +239,7 @@ int TestRewrite::parse_resolve_transform(std::ofstream &of_result, } if (OB_SUCC(ret)) { - resolver_ctx.query_ctx_->question_marks_count_ = param_store.count(); + resolver_ctx.query_ctx_->set_questionmark_count(param_store.count()); ObResolver resolver(resolver_ctx); ObStmt *stmt_tree = NULL; @@ -407,7 +407,7 @@ int TestRewrite::parse_resolve( } if (OB_SUCC(ret)) { - resolver_ctx.query_ctx_->question_marks_count_ = param_store.count(); + resolver_ctx.query_ctx_->set_questionmark_count(param_store.count()); ObResolver resolver(resolver_ctx); ObStmt *stmt_tree = NULL; diff --git a/unittest/sql/test_sql_utils.cpp b/unittest/sql/test_sql_utils.cpp index 23b4228241..4b9f008777 100644 --- a/unittest/sql/test_sql_utils.cpp +++ b/unittest/sql/test_sql_utils.cpp @@ -437,7 +437,7 @@ void TestSqlUtils::do_resolve( resolver_ctx.expr_factory_ = &expr_factory_; resolver_ctx.stmt_factory_ = &stmt_factory_; resolver_ctx.query_ctx_ = stmt_factory_.get_query_ctx(); - resolver_ctx.query_ctx_->question_marks_count_ = param_store.count(); + resolver_ctx.query_ctx_->set_questionmark_count(param_store.count()); ObResolver resolver(resolver_ctx); ret = resolver.resolve(ObResolver::IS_NOT_PREPARED_STMT, *parse_result.result_tree_->children_[0], stmt); if (OB_SUCC(ret)) {