diff options
Diffstat (limited to 'sql/table.cc')
-rw-r--r-- | sql/table.cc | 73 |
1 files changed, 55 insertions, 18 deletions
diff --git a/sql/table.cc b/sql/table.cc index 2031d27b549..18be06c0b95 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -44,6 +44,7 @@ #include "sql_cte.h" #include "ha_sequence.h" #include "sql_show.h" +#include <atomic> /* For MySQL 5.7 virtual fields */ #define MYSQL57_GENERATED_FIELD 128 @@ -79,7 +80,7 @@ LEX_CSTRING MYSQL_PROC_NAME= {STRING_WITH_LEN("proc")}; */ static LEX_CSTRING parse_vcol_keyword= { STRING_WITH_LEN("PARSE_VCOL_EXPR ") }; -static int64 last_table_id; +static std::atomic<ulong> last_table_id; /* Functions defined in this file */ @@ -324,7 +325,8 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, share->can_do_row_logging= 1; if (share->table_category == TABLE_CATEGORY_LOG) share->no_replicate= 1; - if (my_strnncoll(table_alias_charset, (uchar*) db, 6, + if (key_length > 6 && + my_strnncoll(table_alias_charset, (const uchar*) key, 6, (const uchar*) "mysql", 6) == 0) share->not_usable_by_query_cache= 1; @@ -343,8 +345,8 @@ TABLE_SHARE *alloc_table_share(const char *db, const char *table_name, */ do { - share->table_map_id=(ulong) my_atomic_add64_explicit(&last_table_id, 1, - MY_MEMORY_ORDER_RELAXED); + share->table_map_id= + last_table_id.fetch_add(1, std::memory_order_relaxed); } while (unlikely(share->table_map_id == ~0UL)); } DBUG_RETURN(share); @@ -431,6 +433,7 @@ void TABLE_SHARE::destroy() ha_share= NULL; // Safety } + delete_stat_values_for_table_share(this); delete sequence; free_root(&stats_cb.mem_root, MYF(0)); stats_cb.stats_can_be_read= FALSE; @@ -2183,7 +2186,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, keyinfo= share->key_info; uint primary_key= my_strcasecmp(system_charset_info, share->keynames.type_names[0], primary_key_name) ? MAX_KEY : 0; - KEY* key_first_info; + KEY* key_first_info= NULL; if (primary_key >= MAX_KEY && keyinfo->flags & HA_NOSAME) { @@ -2471,7 +2474,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (!(key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART | HA_BIT_PART)) && key_part->type != HA_KEYTYPE_FLOAT && - key_part->type == HA_KEYTYPE_DOUBLE) + key_part->type != HA_KEYTYPE_DOUBLE) key_part->key_part_flag|= HA_CAN_MEMCMP; } keyinfo->usable_key_parts= usable_parts; // Filesort @@ -3162,10 +3165,12 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, { enum open_frm_error error; uint records, i, bitmap_size, bitmap_count; + const char *tmp_alias; bool error_reported= FALSE; uchar *record, *bitmaps; Field **field_ptr; uint8 save_context_analysis_only= thd->lex->context_analysis_only; + TABLE_SHARE::enum_v_keys check_set_initialized= share->check_set_initialized; DBUG_ENTER("open_table_from_share"); DBUG_PRINT("enter",("name: '%s.%s' form: %p", share->db.str, share->table_name.str, outparam)); @@ -3189,8 +3194,14 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, init_sql_alloc(&outparam->mem_root, "table", TABLE_ALLOC_BLOCK_SIZE, 0, MYF(0)); - if (outparam->alias.copy(alias->str, alias->length, table_alias_charset)) + /* + We have to store the original alias in mem_root as constraints and virtual + functions may store pointers to it + */ + if (!(tmp_alias= strmake_root(&outparam->mem_root, alias->str, alias->length))) goto err; + + outparam->alias.set(tmp_alias, alias->length, table_alias_charset); outparam->quick_keys.init(); outparam->covering_keys.init(); outparam->intersect_keys.init(); @@ -3279,6 +3290,8 @@ enum open_frm_error open_table_from_share(THD *thd, TABLE_SHARE *share, } (*field_ptr)= 0; // End marker + DEBUG_SYNC(thd, "TABLE_after_field_clone"); + outparam->vers_write= share->versioned; if (share->found_next_number_field) @@ -3527,6 +3540,16 @@ partititon_err: } outparam->mark_columns_used_by_virtual_fields(); + if (!check_set_initialized && + share->check_set_initialized == TABLE_SHARE::V_KEYS) + { + // copy PART_INDIRECT_KEY_FLAG that was set meanwhile by *some* thread + for (uint i= 0 ; i < share->fields ; i++) + { + if (share->field[i]->flags & PART_INDIRECT_KEY_FLAG) + outparam->field[i]->flags|= PART_INDIRECT_KEY_FLAG; + } + } if (db_stat) { @@ -4614,7 +4637,7 @@ void TABLE::init(THD *thd, TABLE_LIST *tl) s->table_name.str, tl->alias.str); /* Fix alias if table name changes. */ - if (strcmp(alias.c_ptr(), tl->alias.str)) + if (!alias.alloced_length() || strcmp(alias.c_ptr(), tl->alias.str)) alias.copy(tl->alias.str, tl->alias.length, alias.charset()); tablenr= thd->current_tablenr++; @@ -6209,7 +6232,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_ nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col); } - DBUG_ASSERT(!nj_col->table_field || + DBUG_ASSERT(!nj_col->table_field || !nj_col->table_field->field || nj_col->table_ref->table == nj_col->table_field->field->table); /* @@ -6258,7 +6281,7 @@ Field_iterator_table_ref::get_or_create_column_ref(THD *thd, TABLE_LIST *parent_ RETURN # Pointer to a column of a natural join (or its operand) - NULL No memory to allocate the column + NULL We didn't originally have memory to allocate the column */ Natural_join_column * @@ -6274,7 +6297,7 @@ Field_iterator_table_ref::get_natural_column_ref() */ nj_col= natural_join_it.column_ref(); DBUG_ASSERT(nj_col && - (!nj_col->table_field || + (!nj_col->table_field || !nj_col->table_field->field || nj_col->table_ref->table == nj_col->table_field->field->table)); return nj_col; } @@ -6848,6 +6871,7 @@ void TABLE::mark_columns_used_by_virtual_fields(void) { MY_BITMAP *save_read_set; Field **vfield_ptr; + TABLE_SHARE::enum_v_keys v_keys= TABLE_SHARE::NO_V_KEYS; /* If there is virtual fields are already initialized */ if (s->check_set_initialized) @@ -6886,11 +6910,14 @@ void TABLE::mark_columns_used_by_virtual_fields(void) for (uint i= 0 ; i < s->fields ; i++) { if (bitmap_is_set(&tmp_set, i)) - field[i]->flags|= PART_INDIRECT_KEY_FLAG; + { + s->field[i]->flags|= PART_INDIRECT_KEY_FLAG; + v_keys= TABLE_SHARE::V_KEYS; + } } bitmap_clear_all(&tmp_set); } - s->check_set_initialized= 1; + s->check_set_initialized= v_keys; if (s->tmp_table == NO_TMP_TABLE) mysql_mutex_unlock(&s->LOCK_share); } @@ -7098,6 +7125,14 @@ void TABLE::create_key_part_by_field(KEY_PART_INFO *key_part_info, The function checks whether a possible key satisfies the constraints imposed on the keys of any temporary table. + We need to filter out BLOB columns here, because ref access optimizer creates + KEYUSE objects for equalities for non-key columns for two puproses: + 1. To discover possible keys for derived_with_keys optimization + 2. To do hash joins + For the purpose of #1, KEYUSE objects are not created for "blob_column=..." . + However, they might be created for #2. In order to catch that case, we filter + them out here. + @return TRUE if the key is valid @return FALSE otherwise */ @@ -7113,11 +7148,12 @@ bool TABLE::check_tmp_key(uint key, uint key_parts, { uint fld_idx= next_field_no(arg); reg_field= field + fld_idx; + if ((*reg_field)->type() == MYSQL_TYPE_BLOB) + return FALSE; uint fld_store_len= (uint16) (*reg_field)->key_length(); if ((*reg_field)->real_maybe_null()) fld_store_len+= HA_KEY_NULL_LENGTH; - if ((*reg_field)->type() == MYSQL_TYPE_BLOB || - (*reg_field)->real_type() == MYSQL_TYPE_VARCHAR || + if ((*reg_field)->real_type() == MYSQL_TYPE_VARCHAR || (*reg_field)->type() == MYSQL_TYPE_GEOMETRY) fld_store_len+= HA_KEY_BLOB_LENGTH; key_len+= fld_store_len; @@ -8327,7 +8363,7 @@ int TABLE_LIST::fetch_number_of_rows() } if (is_materialized_derived() && !fill_me) { - table->file->stats.records= ((select_unit*)(get_unit()->result))->records; + table->file->stats.records= get_unit()->result->est_records; set_if_bigger(table->file->stats.records, 2); table->used_stat_records= table->file->stats.records; } @@ -8550,7 +8586,8 @@ bool TR_table::update(ulonglong start_id, ulonglong end_id) return true; store(FLD_BEGIN_TS, thd->transaction_time()); - timeval end_time= {thd->query_start(), long(thd->query_start_sec_part())}; + thd->set_time(); + timeval end_time= {thd->query_start(), int(thd->query_start_sec_part())}; store(FLD_TRX_ID, start_id); store(FLD_COMMIT_ID, end_id); store(FLD_COMMIT_TS, end_time); @@ -8631,7 +8668,7 @@ bool TR_table::query(MYSQL_TIME &commit_time, bool backwards) if (res > 0) { MYSQL_TIME commit_ts; - if ((*this)[FLD_COMMIT_TS]->get_date(&commit_ts, 0)) + if ((*this)[FLD_COMMIT_TS]->get_date(&commit_ts, date_mode_t(0))) { found= false; break; |