diff --git a/mysql-test/suite/ctc/r/ctc_dml_ignore.result b/mysql-test/suite/ctc/r/ctc_dml_ignore.result index 64db8a99bac71c0a4212e27c0292b50c3be55fa9..03867bb9af6e2fde05fd4813d63d66dbd54e7ea0 100644 --- a/mysql-test/suite/ctc/r/ctc_dml_ignore.result +++ b/mysql-test/suite/ctc/r/ctc_dml_ignore.result @@ -432,6 +432,42 @@ drop trigger if exists trg_bug28502_bd; drop trigger if exists trg_bug28502_ad; drop table t1, t1_op_log; drop view v1; +CREATE TABLE `t1` ( +a int, +b int, +KEY `idx_a` (a), +KEY `idx_b` (b) +); +insert into t1(a, b) values(2, 3), (1, 3), (1, 3); +set global ctc_select_prefetch = 0; +select /*+ INDEX_MERGE(t1 idx_a, idx_b) */ count(*) from t1 where a = 1 and b = 3; +count(*) +2 +set global ctc_select_prefetch = 1; +select /*+ INDEX_MERGE(t1 idx_a, idx_b) */ count(*) from t1 where a = 1 and b = 3; +count(*) +2 +create table t2( +id int, +char_col char(20), +enum_col enum('x-small','small','medium','large','x-large'), +primary key (id), +key idx_char_col (char_col), +key idx_enum_col (enum_col)); +insert into t2 values(84, 'apple', 'x-large'), (417, 'apple' , 'x-large'), (439, 'qpple', 'x-large'), (847, 'apple', 'x-large'); +select count(*) from t2 where enum_col = 'x-large' and char_col = 'apple'; +count(*) +3 +set global ctc_select_prefetch = 0; +select /*+ INDEX_MERGE(t2 idx_char_col,idx_enum_col) */ count(*) from t2 where enum_col = 'x-large' and char_col = 'apple'; +count(*) +3 +set global ctc_select_prefetch = 1; +select /*+ INDEX_MERGE(t2 idx_char_col,idx_enum_col) */ count(*) from t2 where enum_col = 'x-large' and char_col = 'apple'; +count(*) +3 +drop table t1; +drop table t2; create database db_trigger; use db_trigger; SET @old_sql_mode := @@sql_mode ; diff --git a/mysql-test/suite/ctc/t/ctc_dml_ignore.test b/mysql-test/suite/ctc/t/ctc_dml_ignore.test index 3da3a32485c4f22cc4280d13166eba13e9cf447a..ad89b1a060916877c50fdcf2cfe7e3d087051a69 100644 --- a/mysql-test/suite/ctc/t/ctc_dml_ignore.test +++ b/mysql-test/suite/ctc/t/ctc_dml_ignore.test @@ -192,6 +192,35 @@ drop trigger if exists trg_bug28502_ad; drop table t1, t1_op_log; drop view v1; +CREATE TABLE `t1` ( + a int, + b int, + KEY `idx_a` (a), + KEY `idx_b` (b) +); +insert into t1(a, b) values(2, 3), (1, 3), (1, 3); +set global ctc_select_prefetch = 0; +select /*+ INDEX_MERGE(t1 idx_a, idx_b) */ count(*) from t1 where a = 1 and b = 3; +set global ctc_select_prefetch = 1; +select /*+ INDEX_MERGE(t1 idx_a, idx_b) */ count(*) from t1 where a = 1 and b = 3; + +create table t2( + id int, + char_col char(20), + enum_col enum('x-small','small','medium','large','x-large'), + primary key (id), + key idx_char_col (char_col), + key idx_enum_col (enum_col)); +insert into t2 values(84, 'apple', 'x-large'), (417, 'apple' , 'x-large'), (439, 'qpple', 'x-large'), (847, 'apple', 'x-large'); +select count(*) from t2 where enum_col = 'x-large' and char_col = 'apple'; +set global ctc_select_prefetch = 0; +select /*+ INDEX_MERGE(t2 idx_char_col,idx_enum_col) */ count(*) from t2 where enum_col = 'x-large' and char_col = 'apple'; +set global ctc_select_prefetch = 1; +select /*+ INDEX_MERGE(t2 idx_char_col,idx_enum_col) */ count(*) from t2 where enum_col = 'x-large' and char_col = 'apple'; + +drop table t1; +drop table t2; + create database db_trigger; use db_trigger; SET @old_sql_mode := @@sql_mode ; diff --git a/storage/ctc/ctc_stats.cc b/storage/ctc/ctc_stats.cc index 6d3f77df3c2e98f715c2f3b201bc7f2e70525785..3dc78ba95b259a89d594f135ed8d99d033c6ab88 100644 --- a/storage/ctc/ctc_stats.cc +++ b/storage/ctc/ctc_stats.cc @@ -121,7 +121,7 @@ bool ctc_stats::get_statistics_enabled() { void ctc_stats::set_statistics_enabled(const bool enabled) { if (enabled && !m_statistics_enabled.load()) { - for (int i = 0; i < CTC_FUNC_TYPE_NUMBER; i++) { + for (int i = 0; i < EVENT_TYPE_COUNT; i++) { for (int hash_id = 0; hash_id < EVENT_TRACKING_GROUP; hash_id++) { m_calls[i][hash_id] = 0; m_use_time[i][hash_id] = 0; @@ -134,7 +134,6 @@ void ctc_stats::set_statistics_enabled(const bool enabled) { void ctc_stats::gather_stats(const enum EVENT_TRACKING type, const uint64_t start_cycles) { if (clock_frequency == 0) { - ctc_log_error("[TSE STATS] clock frequency is not initialized."); return; } uint64_t use_time = rdtsc() - start_cycles; diff --git a/storage/ctc/ctc_util.cc b/storage/ctc/ctc_util.cc index 4a739d2aabf49b86147c09e54dd815dc5272eaae..93529dadd5102a16b6afecfe0f9ad398f584efca 100644 --- a/storage/ctc/ctc_util.cc +++ b/storage/ctc/ctc_util.cc @@ -848,4 +848,19 @@ longlong get_session_variable_int_value_with_range(THD *thd, return default_value; } return var_value; +} + +int32_t ctc_cmp_cantian_rowid(const rowid_t *rowid1, const rowid_t *rowid2) { + int32_t result = rowid1->file > rowid2->file ? 1 : (rowid1->file < rowid2->file ? (-1) : 0); + if (result != 0) { + return result; + } + + result = rowid1->page > rowid2->page ? 1 : (rowid1->page < rowid2->page ? (-1) : 0); + if (result != 0) { + return result; + } + + result = rowid1->slot > rowid2->slot ? 1 : (rowid1->slot < rowid2->slot ? (-1) : 0); + return result; } \ No newline at end of file diff --git a/storage/ctc/ctc_util.h b/storage/ctc/ctc_util.h index 12216ffd7baba7bbae981df6c07313dc411fe3fb..2b207d5d8ba72f556ef66d56cd3500b3d341ddfc 100644 --- a/storage/ctc/ctc_util.h +++ b/storage/ctc/ctc_util.h @@ -36,7 +36,11 @@ static unordered_set mysql_system_db{"information_schema", "mysql", "per #define CTC_GET_THD_DB_NAME(thd) (thd->db().str == NULL) ? nullptr : const_cast(thd->db().str) -#define CBO_STRING_MAX_LEN 16 +#ifndef WITH_CANTIAN + #define CBO_STRING_MAX_LEN 16 +#else + #define CBO_STRING_MAX_LEN 64 +#endif #define OFFSET_VARCHAR_TYPE 2 @@ -45,6 +49,52 @@ static unordered_set mysql_system_db{"information_schema", "mysql", "per #define SESSION_VARIABLE_VALUE_MAX_CREATE_INDEX_PARALLELISM 10 #define SESSION_VARIABLE_VALUE_DEFAULT_CREATE_INDEX_PARALLELISM -1 +#define ROWID_FILE_BITS 10 +#define ROWID_PAGE_BITS 30 +#define ROWID_SLOT_BITS 12 +#define ROWID_UNUSED_BITS 12 +#define ROWID_VALUE_BITS 52 +#pragma pack(4) +// cantian Row ID type identify a physical position of a row +typedef union st_rowid { + struct { + uint64_t value : ROWID_VALUE_BITS; + uint64_t unused1 : ROWID_UNUSED_BITS; + }; + + struct { + uint64_t file : ROWID_FILE_BITS; // file + uint64_t page : ROWID_PAGE_BITS; // page + uint64_t slot : ROWID_SLOT_BITS; // slot number + uint64_t unused2 : ROWID_UNUSED_BITS; + }; + + struct { + uint64_t vmid : 32; // virtual memory page id, dynamic view item, ... + uint64_t vm_slot : 16; // slot of virtual memory page, sub item + uint64_t vm_tag : 16; + }; + + struct { + uint32_t tenant_id : 16; + uint32_t curr_ts_num : 16; + uint32_t ts_id; + }; + + struct { + uint32_t group_id; + uint32_t attr_id; + }; + + struct { + uint32_t pos; + uint32_t bucket_id : 16; + uint32_t sub_id : 16; + }; +} rowid_t; +#pragma pack() + +int32_t ctc_cmp_cantian_rowid(const rowid_t *rowid1, const rowid_t *rowid2); void ctc_split_normalized_name(const char *file_name, char db[], size_t db_buf_len, char name[], size_t name_buf_len, bool *is_tmp_table); void ctc_copy_name(char to_name[], const char from_name[], size_t to_buf_len); diff --git a/storage/ctc/datatype_cnvrtr.cc b/storage/ctc/datatype_cnvrtr.cc index ecd12e92b20b2334eed61e10f8edadfe6253d5a0..614167d9e06e1a86e2d0591692401640986a39af 100644 --- a/storage/ctc/datatype_cnvrtr.cc +++ b/storage/ctc/datatype_cnvrtr.cc @@ -1760,7 +1760,10 @@ void copy_column_data_to_mysql(field_info_t *field_info, const field_cnvrt_aux_t { if (!bitmap_is_set(field_info->field->table->read_set, field_info->field->field_index()) && tch.sql_command == SQLCOM_SELECT) { - return; + ha_ctc *const ctc_handler = dynamic_cast(field_info->field->table->file); + if (!ctc_handler->m_ror_intersect) { + return; + } } uchar *src = NULL; uint16_t src_len = 0; diff --git a/storage/ctc/ha_ctc.cc b/storage/ctc/ha_ctc.cc index 2b07df8e826f3e3e9f6101eb78bfa31c8df677a8..fa2b3d6afb0f9b1064e441a08efa1cff8bac411a 100644 --- a/storage/ctc/ha_ctc.cc +++ b/storage/ctc/ha_ctc.cc @@ -2991,6 +2991,20 @@ bool ha_ctc::is_record_buffer_wanted(ha_rows *const max_rows) const { return false; } +void ha_ctc::set_ror_intersect() { +#ifdef FEATURE_X_FOR_MYSQL_32 + if (table->reginfo.qep_tab && table->reginfo.qep_tab->access_path() && + table->reginfo.qep_tab->access_path()->type == AccessPath::ROWID_INTERSECTION) { + m_ror_intersect = true; + } +#elif defined(FEATURE_X_FOR_MYSQL_26) + if (table->reginfo.qep_tab && table->reginfo.qep_tab->quick() && + table->reginfo.qep_tab->quick()->get_type() == QUICK_SELECT_I::QS_TYPE_ROR_INTERSECT) { + m_ror_intersect = true; + } +#endif +} + // @ref set_record_buffer int ha_ctc::set_prefetch_buffer() { if (m_rec_buf) { @@ -3189,6 +3203,7 @@ int ha_ctc::rnd_init(bool) { return 0; } + set_ror_intersect(); ct_errno_t ret = (ct_errno_t)set_prefetch_buffer(); if (ret != CT_SUCCESS) { END_RECORD_STATS(EVENT_TYPE_RND_INIT) @@ -3662,6 +3677,7 @@ int ha_ctc::rnd_end() { int ha_ctc::index_init(uint index, bool sorted) { DBUG_TRACE; BEGIN_RECORD_STATS + set_ror_intersect(); ct_errno_t ret = (ct_errno_t)set_prefetch_buffer(); if (ret != CT_SUCCESS) { return ret; @@ -3699,6 +3715,11 @@ int ha_ctc::index_end() { return ret; } +int ha_ctc::cmp_ref(const uchar *ref1, const uchar *ref2) const { + DBUG_TRACE; + return ctc_cmp_cantian_rowid((const rowid_t *)ref1, (const rowid_t *)ref2); +} + int ha_ctc::process_cantian_record(uchar *buf, record_info_t *record_info, ct_errno_t ct_ret, int rc_ret) { int ret = CT_SUCCESS; check_error_code_to_mysql(ha_thd(), &ct_ret); @@ -3731,6 +3752,7 @@ EXTER_ATTACK int ha_ctc::index_read(uchar *buf, const uchar *key, uint key_len, reset_rec_buf(); } + m_is_covering_index = m_ror_intersect ? false : m_is_covering_index; m_action = m_is_covering_index ? EXP_CURSOR_ACTION_INDEX_ONLY : EXP_CURSOR_ACTION_SELECT; if (m_select_lock == lock_mode::EXCLUSIVE_LOCK) { enum_sql_command sql_command = (enum_sql_command)thd_sql_command(ha_thd()); @@ -3901,6 +3923,8 @@ int ha_ctc::index_prev(uchar *buf) { int ha_ctc::index_first(uchar *buf) { DBUG_TRACE; ha_statistic_increment(&System_status_var::ha_read_first_count); + m_tch.cursor_addr = INVALID_VALUE64; + m_tch.cursor_valid = false; int error = index_read(buf, nullptr, 0, HA_READ_AFTER_KEY); /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */ if (error == HA_ERR_KEY_NOT_FOUND) { diff --git a/storage/ctc/ha_ctc.h b/storage/ctc/ha_ctc.h index 3cd3482feb8ecba5869f3edfb1b040a3312847d5..03da965d8c52d867bb5e8506cc97ce9aa0702b24 100644 --- a/storage/ctc/ha_ctc.h +++ b/storage/ctc/ha_ctc.h @@ -36,6 +36,7 @@ #include "sql/dd/types/schema.h" #include "sql/dd/types/object_table_definition.h" #include "sql/dd/string_type.h" +#include "sql/sql_optimizer.h" #include "clientbuild/include/mysql_version.h" #pragma GCC visibility push(default) @@ -491,6 +492,8 @@ public: int index_end() override; + int cmp_ref(const uchar *ref1, const uchar *ref2) const override; + int index_read(uchar *buf, const uchar *key, uint key_len, ha_rkey_function find_flag) override; int index_read_last(uchar *buf, const uchar *key_ptr, uint key_len) override; @@ -855,6 +858,10 @@ public: virtual int get_cbo_stats_4share(); + bool m_ror_intersect = false; + + void set_ror_intersect(); + /** Pointer to Cond pushdown */ ctc_conds *m_cond = nullptr; Item *m_pushed_conds = nullptr;