diff --git a/storage/ctc/ha_ctc.cc b/storage/ctc/ha_ctc.cc index b10ef7048cd17e080ccba1cb84278b9c2e740596..ca2d8a4c8eeab3a39e45ef3af508828f7afb93f1 100644 --- a/storage/ctc/ha_ctc.cc +++ b/storage/ctc/ha_ctc.cc @@ -3185,6 +3185,45 @@ EXTER_ATTACK int ha_ctc::rnd_pos(uchar *buf, uchar *pos) { return ret; } +/* +The given SQL command may require the use of statistics information. +*/ +bool requires_stats_info(enum_sql_command sql_command) { + switch (sql_command) { + case SQLCOM_DELETE: + case SQLCOM_SELECT: + case SQLCOM_UPDATE: + case SQLCOM_DELETE_MULTI: + case SQLCOM_UPDATE_MULTI: + return true; + default: + return false; + } +} + +/* +Handle the statistics are empty case, +prevent full-table scan by query_sql with where_cond +*/ +ct_errno_t ha_ctc::handle_cbo_stats_empty(THD* thd) { + ct_errno_t ret = CT_SUCCESS; + if (stats.records == 0 && requires_stats_info(thd->lex->sql_command) && + thd->lex->query_block->where_cond() != nullptr) { + std::lock_guard lock(analyze_mutex); + if (stats.records == 0) { + ret = (ct_errno_t)analyze(thd, nullptr); + if (ret != CT_SUCCESS) { + ctc_log_error("sql %s execute analyze failed!", thd->query().str); + return ret; + } + ctc_log_system("sql %s handle empty cbo statistics.", thd->query().str); + ret = (ct_errno_t)get_cbo_stats_4share(); + info_low(); + } + } + return ret; +} + /** @brief ::info() is used to return information to the optimizer. See my_base.h for @@ -3262,9 +3301,16 @@ int ha_ctc::info(uint flag) { END_RECORD_STATS(EVENT_TYPE_GET_CBO) return convert_ctc_error_code_to_mysql(ret); } + + info_low(); + + ret = handle_cbo_stats_empty(thd); + if (ret != CT_SUCCESS) { + END_RECORD_STATS(EVENT_TYPE_GET_CBO) + return convert_ctc_error_code_to_mysql(ret); + } } - info_low(); if (stats.records < 2) { /* This is a lie, but you don't want the optimizer to see zero or 1 */ stats.records = 3; diff --git a/storage/ctc/ha_ctc.h b/storage/ctc/ha_ctc.h index 44399d56bb7064af5f88dbc8ed91bc21f5123433..467677abd761669f5a25f609d887f84c0571fed9 100644 --- a/storage/ctc/ha_ctc.h +++ b/storage/ctc/ha_ctc.h @@ -956,6 +956,9 @@ public: virtual void free_cbo_stats(); virtual int get_cbo_stats_4share(); + + std::mutex analyze_mutex; + virtual ct_errno_t handle_cbo_stats_empty(THD* thd); bool m_ror_intersect = false; diff --git a/storage/ctc/ha_ctcpart.cc b/storage/ctc/ha_ctcpart.cc index 0db2188f254ede51cc9ed63b19c07220b4a7125b..62799463248849452c215cc8d380d6941b1d4c7b 100644 --- a/storage/ctc/ha_ctcpart.cc +++ b/storage/ctc/ha_ctcpart.cc @@ -961,27 +961,36 @@ int ha_ctcpart::analyze(THD *thd, HA_CHECK_OPT *opt) { return 0; } Alter_info *const alter_info = get_thd()->lex->alter_info; - if ((alter_info->flags & Alter_info::ALTER_ADMIN_PARTITION) == 0 || - (alter_info->flags & Alter_info::ALTER_ALL_PARTITION)) { - m_tch.part_id = INVALID_PART_ID; - m_part_share->need_fetch_cbo = true; - return ha_ctc::analyze(thd, opt); - } int ret; uint32_t used_parts; uint32_t *part_ids = nullptr; uint32_t *subpart_ids = nullptr; - bool memory_allocated = false; - if (!m_part_info->set_read_partitions(&alter_info->partition_names)) { - memory_allocated = get_used_partitions(m_part_info, &part_ids, &subpart_ids, &used_parts); - if(!memory_allocated){ - ctc_log_error("Failed to allocate memory !"); - return HA_ERR_OUT_OF_MEM; + if (alter_info != nullptr) { + if ((alter_info->flags & Alter_info::ALTER_ADMIN_PARTITION) == 0 || + (alter_info->flags & Alter_info::ALTER_ALL_PARTITION)) { + m_tch.part_id = INVALID_PART_ID; + m_part_share->need_fetch_cbo = true; + return ha_ctc::analyze(thd, opt); + } + bool memory_allocated = false; + if (!m_part_info->set_read_partitions(&alter_info->partition_names)) { + memory_allocated = get_used_partitions(m_part_info, &part_ids, &subpart_ids, &used_parts); + if(!memory_allocated){ + ctc_log_error("Failed to allocate memory !"); + return HA_ERR_OUT_OF_MEM; + } + } else { + ctc_log_error("no partition alter !"); + return HA_ERR_GENERIC; } } else { - ctc_log_error("no partition alter !"); - return HA_ERR_GENERIC; + my_free(part_ids); + my_free(subpart_ids); + m_tch.part_id = INVALID_PART_ID; + m_part_share->need_fetch_cbo = true; + return ha_ctc::analyze(thd, opt); } + if (m_part_info->num_parts == used_parts) { m_tch.part_id = INVALID_PART_ID; my_free(part_ids);