diff options
Diffstat (limited to 'sql/table.cc')
-rw-r--r-- | sql/table.cc | 107 |
1 files changed, 48 insertions, 59 deletions
diff --git a/sql/table.cc b/sql/table.cc index a8eeeb53d72..b8ed7a99156 100644 --- a/sql/table.cc +++ b/sql/table.cc @@ -46,6 +46,10 @@ #include "sql_show.h" #include "opt_trace.h" #include "sql_db.h" // get_default_db_collation +#include "sql_update.h" // class Sql_cmd_update +#include "sql_delete.h" // class Sql_cmd_delete + + /* For MySQL 5.7 virtual fields */ #define MYSQL57_GENERATED_FIELD 128 @@ -942,39 +946,6 @@ static uint enum_value_with_check(THD *thd, TABLE_SHARE *share, } -/** - Check if a collation has changed number - - @param mysql_version - @param current collation number - - @retval new collation number (same as current collation number of no change) -*/ - -static uint upgrade_collation(ulong mysql_version, uint cs_number) -{ - if (mysql_version >= 50300 && mysql_version <= 50399) - { - switch (cs_number) { - case 149: return MY_PAGE2_COLLATION_ID_UCS2; // ucs2_crotian_ci - case 213: return MY_PAGE2_COLLATION_ID_UTF8; // utf8_crotian_ci - } - } - if ((mysql_version >= 50500 && mysql_version <= 50599) || - (mysql_version >= 100000 && mysql_version <= 100005)) - { - switch (cs_number) { - case 149: return MY_PAGE2_COLLATION_ID_UCS2; // ucs2_crotian_ci - case 213: return MY_PAGE2_COLLATION_ID_UTF8; // utf8_crotian_ci - case 214: return MY_PAGE2_COLLATION_ID_UTF32; // utf32_croatian_ci - case 215: return MY_PAGE2_COLLATION_ID_UTF16; // utf16_croatian_ci - case 245: return MY_PAGE2_COLLATION_ID_UTF8MB4;// utf8mb4_croatian_ci - } - } - return cs_number; -} - - void Column_definition_attributes::frm_pack_basic(uchar *buff) const { int2store(buff + 3, length); @@ -1034,7 +1005,7 @@ bool Column_definition_attributes::frm_unpack_charset(TABLE_SHARE *share, const uchar *buff) { uint cs_org= buff[14] + (((uint) buff[11]) << 8); - uint cs_new= upgrade_collation(share->mysql_version, cs_org); + uint cs_new= Charset::upgrade_collation_id(share->mysql_version, cs_org); if (cs_org != cs_new) share->incompatible_version|= HA_CREATE_USED_CHARSET; if (cs_new && !(charset= get_charset(cs_new, MYF(0)))) @@ -1894,7 +1865,7 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, if (!frm_image[32]) // New frm file in 3.23 { uint cs_org= (((uint) frm_image[41]) << 8) + (uint) frm_image[38]; - uint cs_new= upgrade_collation(share->mysql_version, cs_org); + uint cs_new= Charset::upgrade_collation_id(share->mysql_version, cs_org); if (cs_org != cs_new) share->incompatible_version|= HA_CREATE_USED_CHARSET; @@ -3110,6 +3081,9 @@ int TABLE_SHARE::init_from_binary_frm_image(THD *thd, bool write, goto err; field= key_part->field= share->field[key_part->fieldnr-1]; + if (Charset::collation_changed_order(share->mysql_version, + field->charset()->number)) + share->incompatible_version|= HA_CREATE_USED_CHARSET; key_part->type= field->key_type(); if (field->invisible > INVISIBLE_USER && !field->vers_sys_field()) @@ -3572,7 +3546,6 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write, char *sql_copy; handler *file; LEX *old_lex; - Query_arena *arena, backup; LEX tmp_lex; KEY *unused1; uint unused2; @@ -3599,11 +3572,6 @@ int TABLE_SHARE::init_from_sql_statement_string(THD *thd, bool write, old_lex= thd->lex; thd->lex= &tmp_lex; - arena= thd->stmt_arena; - if (arena->is_conventional()) - arena= 0; - else - thd->set_n_backup_active_arena(arena, &backup); /* THD::reset_db() does not set THD::db_charset, @@ -3655,8 +3623,6 @@ ret: lex_end(thd->lex); thd->reset_db(&db_backup); thd->lex= old_lex; - if (arena) - thd->restore_active_arena(arena, &backup); reenable_binlog(thd); thd->variables.character_set_client= old_cs; if (unlikely(thd->is_error() || error)) @@ -6886,6 +6852,9 @@ bool TABLE_LIST::prepare_security(THD *thd) #ifndef DBUG_OFF void TABLE_LIST::set_check_merged() { + if (is_view()) + return; + DBUG_ASSERT(derived); /* It is not simple to check all, but at least this should be checked: @@ -6903,7 +6872,7 @@ void TABLE_LIST::set_check_materialized() DBUG_ENTER("TABLE_LIST::set_check_materialized"); SELECT_LEX_UNIT *derived= this->derived; if (view) - derived= &view->unit; + derived= this->derived= &view->unit; DBUG_ASSERT(derived); DBUG_ASSERT(!derived->is_excluded()); if (!derived->first_select()->exclude_from_table_unique_test) @@ -7213,10 +7182,9 @@ void Field_iterator_table_ref::set_field_iterator() table_ref->alias.str)); } /* This is a merge view, so use field_translation. */ - else if (table_ref->field_translation && - !table_ref->is_materialized_derived()) + else if (!table_ref->is_materialized_derived() && + table_ref->is_merged_derived() && table_ref->field_translation) { - DBUG_ASSERT(table_ref->is_merged_derived()); field_it= &view_field_it; DBUG_PRINT("info", ("field_it for '%s' is Field_iterator_view", table_ref->alias.str)); @@ -9303,7 +9271,7 @@ bool TABLE::check_period_overlaps(const KEY &key, return false; uint kp_len= key.key_part[part_nr].length; if (f->cmp_prefix(f->ptr_in_record(lhs), f->ptr_in_record(rhs), - kp_len) != 0) + kp_len / f->charset()->mbmaxlen) != 0) return false; } @@ -9722,8 +9690,13 @@ void TABLE_LIST::wrap_into_nested_join(List<TABLE_LIST> &join_list) static inline bool derived_table_optimization_done(TABLE_LIST *table) { - return table->derived && - (table->derived->is_excluded() || + SELECT_LEX_UNIT *derived= (table->derived ? + table->derived : + (table->view ? + &table->view->unit: + NULL)); + return derived && + (derived->is_excluded() || table->is_materialized_derived()); } @@ -9785,20 +9758,36 @@ bool TABLE_LIST::init_derived(THD *thd, bool init_view) set_derived(); } - if (!is_view() && - !derived_table_optimization_done(this)) + if (!derived_table_optimization_done(this)) { /* A subquery might be forced to be materialized due to a side-effect. */ - bool forced_no_merge_for_update_delete= - belong_to_view ? belong_to_view->updating : - !unit->outer_select()->outer_select(); - if (!is_materialized_derived() && first_select->is_mergeable() && - (unit->outer_select() && !unit->outer_select()->with_rownum) && + if (!is_materialized_derived() && unit->can_be_merged() && + /* + Following is special case of + SELECT * FROM (<limited-select>) WHERE ROWNUM() <= nnn + */ + (unit->outer_select() && + !(unit->outer_select()->with_rownum && + unit->outer_select()->table_list.elements == 1 && + (thd->lex->sql_command == SQLCOM_SELECT || + !unit->outer_select()->is_query_topmost(thd)) && + !is_view())) && + (!thd->lex->with_rownum || (!first_select->group_list.elements && !first_select->order_list.elements)) && - optimizer_flag(thd, OPTIMIZER_SWITCH_DERIVED_MERGE) && - !thd->lex->can_not_use_merged(forced_no_merge_for_update_delete) && + (is_view() || + optimizer_flag(thd, OPTIMIZER_SWITCH_DERIVED_MERGE)) && + !thd->lex->can_not_use_merged() && + !(!is_view() && + (thd->lex->sql_command == SQLCOM_UPDATE_MULTI || + thd->lex->sql_command == SQLCOM_DELETE_MULTI || + (thd->lex->sql_command == SQLCOM_UPDATE && + (((Sql_cmd_update *) thd->lex->m_sql_cmd)->is_multitable() || + thd->lex->query_tables->is_multitable())) || + (thd->lex->sql_command == SQLCOM_DELETE && + (((Sql_cmd_delete *) thd->lex->m_sql_cmd)->is_multitable() || + thd->lex->query_tables->is_multitable())))) && !is_recursive_with_table()) set_merged_derived(); else |