diff options
Diffstat (limited to 'sql/handler.cc')
-rw-r--r-- | sql/handler.cc | 136 |
1 files changed, 119 insertions, 17 deletions
diff --git a/sql/handler.cc b/sql/handler.cc index 733e77b6397..cbb951cd450 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -263,7 +263,7 @@ handler *get_ha_partition(partition_info *part_info) DBUG_ENTER("get_ha_partition"); if ((partition= new ha_partition(partition_hton, part_info))) { - if (partition->initialise_partition(current_thd->mem_root)) + if (partition->initialize_partition(current_thd->mem_root)) { delete partition; partition= 0; @@ -373,7 +373,12 @@ int ha_finalize_handlerton(st_plugin_int *plugin) handlerton *hton= (handlerton *)plugin->data; DBUG_ENTER("ha_finalize_handlerton"); - switch (hton->state) { + /* hton can be NULL here, if ha_initialize_handlerton() failed. */ + if (!hton) + goto end; + + switch (hton->state) + { case SHOW_OPTION_NO: case SHOW_OPTION_DISABLED: break; @@ -400,8 +405,16 @@ int ha_finalize_handlerton(st_plugin_int *plugin) } } + /* + In case a plugin is uninstalled and re-installed later, it should + reuse an array slot. Otherwise the number of uninstall/install + cycles would be limited. + */ + hton2plugin[hton->slot]= NULL; + my_free((uchar*)hton, MYF(0)); + end: DBUG_RETURN(0); } @@ -436,6 +449,7 @@ int ha_initialize_handlerton(st_plugin_int *plugin) case SHOW_OPTION_YES: { uint tmp; + ulong fslot; /* now check the db_type for conflict */ if (hton->db_type <= DB_TYPE_UNKNOWN || hton->db_type >= DB_TYPE_DEFAULT || @@ -460,7 +474,31 @@ int ha_initialize_handlerton(st_plugin_int *plugin) tmp= hton->savepoint_offset; hton->savepoint_offset= savepoint_alloc_size; savepoint_alloc_size+= tmp; - hton->slot= total_ha++; + + /* + In case a plugin is uninstalled and re-installed later, it should + reuse an array slot. Otherwise the number of uninstall/install + cycles would be limited. So look for a free slot. + */ + DBUG_PRINT("plugin", ("total_ha: %lu", total_ha)); + for (fslot= 0; fslot < total_ha; fslot++) + { + if (!hton2plugin[fslot]) + break; + } + if (fslot < total_ha) + hton->slot= fslot; + else + { + if (total_ha >= MAX_HA) + { + sql_print_error("Too many plugins loaded. Limit is %lu. " + "Failed on '%s'", (ulong) MAX_HA, plugin->name.str); + goto err; + } + hton->slot= total_ha++; + } + hton2plugin[hton->slot]=plugin; if (hton->prepare) total_ha_2pc++; @@ -1240,7 +1278,12 @@ int ha_rollback_trans(THD *thd, bool all) trans->ha_list= 0; trans->no_2pc=0; if (is_real_trans) - thd->transaction.xid_state.xid.null(); + { + if (thd->transaction_rollback_request) + thd->transaction.xid_state.rm_error= thd->main_da.sql_errno(); + else + thd->transaction.xid_state.xid.null(); + } if (all) { thd->variables.tx_isolation=thd->session_tx_isolation; @@ -2164,7 +2207,12 @@ prev_insert_id(ulonglong nr, struct system_variables *variables) - In both cases, the reserved intervals are remembered in thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based binlogging; the last reserved interval is remembered in - auto_inc_interval_for_cur_row. + auto_inc_interval_for_cur_row. The number of reserved intervals is + remembered in auto_inc_intervals_count. It differs from the number of + elements in thd->auto_inc_intervals_in_cur_stmt_for_binlog() because the + latter list is cumulative over all statements forming one binlog event + (when stored functions and triggers are used), and collapses two + contiguous intervals in one (see its append() method). The idea is that generated auto_increment values are predictable and independent of the column values in the table. This is needed to be @@ -2248,8 +2296,6 @@ int handler::update_auto_increment() handler::estimation_rows_to_insert was set by handler::ha_start_bulk_insert(); if 0 it means "unknown". */ - uint nb_already_reserved_intervals= - thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements(); ulonglong nb_desired_values; /* If an estimation was given to the engine: @@ -2261,17 +2307,17 @@ int handler::update_auto_increment() start, starting from AUTO_INC_DEFAULT_NB_ROWS. Don't go beyond a max to not reserve "way too much" (because reservation means potentially losing unused values). + Note that in prelocked mode no estimation is given. */ - if (nb_already_reserved_intervals == 0 && - (estimation_rows_to_insert > 0)) + if ((auto_inc_intervals_count == 0) && (estimation_rows_to_insert > 0)) nb_desired_values= estimation_rows_to_insert; else /* go with the increasing defaults */ { /* avoid overflow in formula, with this if() */ - if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS) + if (auto_inc_intervals_count <= AUTO_INC_DEFAULT_NB_MAX_BITS) { - nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * - (1 << nb_already_reserved_intervals); + nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS * + (1 << auto_inc_intervals_count); set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX); } else @@ -2284,7 +2330,7 @@ int handler::update_auto_increment() &nb_reserved_values); if (nr == ~(ulonglong) 0) DBUG_RETURN(HA_ERR_AUTOINC_READ_FAILED); // Mark failure - + /* That rounding below should not be needed when all engines actually respect offset and increment in get_auto_increment(). But they don't @@ -2295,7 +2341,7 @@ int handler::update_auto_increment() */ nr= compute_next_insert_id(nr-1, variables); } - + if (table->s->next_number_keypart == 0) { /* We must defer the appending until "nr" has been possibly truncated */ @@ -2339,8 +2385,9 @@ int handler::update_auto_increment() { auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values, variables->auto_increment_increment); + auto_inc_intervals_count++; /* Row-based replication does not need to store intervals in binlog */ - if (!thd->current_stmt_binlog_row_based) + if (mysql_bin_log.is_open() && !thd->current_stmt_binlog_row_based) thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(), auto_inc_interval_for_cur_row.values(), variables->auto_increment_increment); @@ -2460,6 +2507,7 @@ void handler::ha_release_auto_increment() release_auto_increment(); insert_id_for_cur_row= 0; auto_inc_interval_for_cur_row.replace(0, 0, 0); + auto_inc_intervals_count= 0; if (next_insert_id > 0) { next_insert_id= 0; @@ -2712,8 +2760,56 @@ bool handler::get_error_message(int error, String* buf) } +/** + Check for incompatible collation changes. + + @retval + HA_ADMIN_NEEDS_UPGRADE Table may have data requiring upgrade. + @retval + 0 No upgrade required. +*/ + +int handler::check_collation_compatibility() +{ + ulong mysql_version= table->s->mysql_version; + + if (mysql_version < 50124) + { + KEY *key= table->key_info; + KEY *key_end= key + table->s->keys; + for (; key < key_end; key++) + { + KEY_PART_INFO *key_part= key->key_part; + KEY_PART_INFO *key_part_end= key_part + key->key_parts; + for (; key_part < key_part_end; key_part++) + { + if (!key_part->fieldnr) + continue; + Field *field= table->field[key_part->fieldnr - 1]; + uint cs_number= field->charset()->number; + if ((mysql_version < 50048 && + (cs_number == 11 || /* ascii_general_ci - bug #29499, bug #27562 */ + cs_number == 41 || /* latin7_general_ci - bug #29461 */ + cs_number == 42 || /* latin7_general_cs - bug #29461 */ + cs_number == 20 || /* latin7_estonian_cs - bug #29461 */ + cs_number == 21 || /* latin2_hungarian_ci - bug #29461 */ + cs_number == 22 || /* koi8u_general_ci - bug #29461 */ + cs_number == 23 || /* cp1251_ukrainian_ci - bug #29461 */ + cs_number == 26)) || /* cp1250_general_ci - bug #29461 */ + (mysql_version < 50124 && + (cs_number == 33 || /* utf8_general_ci - bug #27877 */ + cs_number == 35))) /* ucs2_general_ci - bug #27877 */ + return HA_ADMIN_NEEDS_UPGRADE; + } + } + } + return 0; +} + + int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt) { + int error; KEY *keyinfo, *keyend; KEY_PART_INFO *keypart, *keypartend; @@ -2742,6 +2838,10 @@ int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt) } if (table->s->frm_version != FRM_VER_TRUE_VARCHAR) return HA_ADMIN_NEEDS_ALTER; + + if ((error= check_collation_compatibility())) + return error; + return check_for_upgrade(check_opt); } @@ -3244,8 +3344,8 @@ handler::ha_create_handler_files(const char *name, const char *old_name, int handler::ha_change_partitions(HA_CREATE_INFO *create_info, const char *path, - ulonglong *copied, - ulonglong *deleted, + ulonglong * const copied, + ulonglong * const deleted, const uchar *pack_frm_data, size_t pack_frm_len) { @@ -4334,6 +4434,8 @@ static int write_locked_table_maps(THD *thd) (long) thd, (long) thd->lock, (long) thd->locked_tables, (long) thd->extra_lock)); + DBUG_PRINT("debug", ("get_binlog_table_maps(): %d", thd->get_binlog_table_maps())); + if (thd->get_binlog_table_maps() == 0) { MYSQL_LOCK *locks[3]; |