summaryrefslogtreecommitdiff
path: root/sql/table.cc
diff options
context:
space:
mode:
Diffstat (limited to 'sql/table.cc')
-rw-r--r--sql/table.cc73
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;