diff options
Diffstat (limited to 'sql/ha_innobase.cc')
-rw-r--r-- | sql/ha_innobase.cc | 223 |
1 files changed, 179 insertions, 44 deletions
diff --git a/sql/ha_innobase.cc b/sql/ha_innobase.cc index 104aaf8886c..2a25224e641 100644 --- a/sql/ha_innobase.cc +++ b/sql/ha_innobase.cc @@ -155,7 +155,23 @@ convert_error_code_to_mysql( } else if (error == (int) DB_DEADLOCK) { - return(1000000); + return(HA_ERR_LOCK_DEADLOCK); + + } else if (error == (int) DB_LOCK_WAIT_TIMEOUT) { + + return(1000001); + + } else if (error == (int) DB_NO_REFERENCED_ROW) { + + return(1000010); + + } else if (error == (int) DB_ROW_IS_REFERENCED) { + + return(1000011); + + } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) { + + return(1000012); } else if (error == (int) DB_OUT_OF_FILE_SPACE) { @@ -172,7 +188,6 @@ convert_error_code_to_mysql( } else if (error == (int) DB_TOO_BIG_RECORD) { return(HA_ERR_TO_BIG_ROW); - } else { dbug_assert(0); @@ -214,7 +229,7 @@ innobase_mysql_print_thd( } if (thd->query) { - printf(" %0.100s", thd->query); + printf("\n%0.100s", thd->query); } printf("\n"); @@ -521,7 +536,7 @@ innobase_init(void) static char current_dir[3]; int err; bool ret; - + DBUG_ENTER("innobase_init"); if (specialflag & SPECIAL_NO_PRIOR) { @@ -548,8 +563,9 @@ innobase_init(void) "to the [mysqld] section of init parameters in your my.cnf\n" "or my.ini. If you want to use InnoDB tables, add for example,\n" "innodb_data_file_path = /mysql/data/ibdata1:20M\n" - "More information on setting the parameters you find in the\n" - "manual.\n"); + "But to get good performance you should adjust for your hardware\n" + "the InnoDB stratup options listed in section 7.6 at\n" + "http://www.mysql.com/doc/\n"); innodb_skip=1; DBUG_RETURN(FALSE); // Continue without innobase @@ -597,6 +613,16 @@ innobase_init(void) srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout; + if (strcmp(default_charset_info->name, "latin1") == 0) { + /* Store the character ordering table to InnoDB. + For non-latin1 charsets we use the MySQL comparison + functions, and consequently we do not need to know + the ordering internally in InnoDB. */ + + memcpy(srv_latin1_ordering, + default_charset_info->sort_order, 256); + } + err = innobase_start_or_create_for_mysql(); if (err != DB_SUCCESS) { @@ -645,7 +671,7 @@ innobase_flush_logs(void) DBUG_ENTER("innobase_flush_logs"); - log_make_checkpoint_at(ut_dulint_max, TRUE); + log_flush_up_to(ut_dulint_max, LOG_WAIT_ONE_GROUP); DBUG_RETURN(result); } @@ -878,10 +904,10 @@ ha_innobase::open( if (NULL == (ib_table = dict_table_get(norm_name, NULL))) { fprintf(stderr, -"Cannot find table %s from the internal data dictionary\n" -"of InnoDB though the .frm file for the table exists. Maybe you have deleted\n" -"and created again an InnoDB database but forgotten to delete the\n" -"corresponding .frm files of old InnoDB tables?\n", +"InnoDB: Cannot find table %s from the internal data dictionary\n" +"InnoDB: of InnoDB though the .frm file for the table exists. Maybe you\n" +"InnoDB: have deleted and recreated InnoDB data files but have forgotten\n" +"InnoDB: to delete the corresponding .frm files of InnoDB tables?\n", norm_name); free_share(share); @@ -1401,8 +1427,36 @@ ha_innobase::write_row( current value and the value supplied by the user, if the auto_inc counter is already initialized for the table */ + + /* We have to use the transactional lock mechanism + on the auto-inc counter of the table to ensure + that replication and roll-forward of the binlog + exactly imitates also the given auto-inc values. + The lock is released at each SQL statement's + end. */ + + error = row_lock_table_autoinc_for_mysql(prebuilt); + + if (error != DB_SUCCESS) { + + error = convert_error_code_to_mysql(error); + goto func_exit; + } + dict_table_autoinc_update(prebuilt->table, auto_inc); } else { + if (!prebuilt->trx->auto_inc_lock) { + + error = row_lock_table_autoinc_for_mysql( + prebuilt); + if (error != DB_SUCCESS) { + + error = convert_error_code_to_mysql( + error); + goto func_exit; + } + } + auto_inc = dict_table_autoinc_get(prebuilt->table); /* If auto_inc is now != 0 the autoinc counter @@ -1460,7 +1514,7 @@ ha_innobase::write_row( /* Tell InnoDB server that there might be work for utility threads: */ - +func_exit: innobase_active_small(); DBUG_RETURN(error); @@ -1737,7 +1791,7 @@ ha_innobase::index_init( } /********************************************************************** -?????????????????????????????????? */ +Currently does nothing. */ int ha_innobase::index_end(void) @@ -2299,6 +2353,15 @@ ha_innobase::external_lock( trx_search_latch_release_if_reserved(trx); } + if (trx->auto_inc_lock) { + + /* If we had reserved the auto-inc lock for + some table in this SQL statement, we release + it now */ + + row_unlock_table_autoinc_for_mysql(trx); + } + if (!(thd->options & (OPTION_NOT_AUTO_COMMIT | OPTION_BEGIN))) { innobase_commit(thd, trx); @@ -2461,7 +2524,9 @@ ha_innobase::create( const char* name, /* in: table name */ TABLE* form, /* in: information on table columns and indexes */ - HA_CREATE_INFO* create_info) /* in: ??????? */ + HA_CREATE_INFO* create_info) /* in: more information of the + created table, contains also the + create statement string */ { int error; dict_table_t* innobase_table; @@ -2552,6 +2617,19 @@ ha_innobase::create( } } + error = row_table_add_foreign_constraints(trx, + create_info->create_statement, norm_name); + + error = convert_error_code_to_mysql(error); + + if (error) { + trx_commit_for_mysql(trx); + + trx_free_for_mysql(trx); + + DBUG_RETURN(error); + } + trx_commit_for_mysql(trx); innobase_table = dict_table_get(norm_name, NULL); @@ -2572,8 +2650,8 @@ ha_innobase::create( Drops a table from an InnoDB database. Before calling this function, MySQL calls innobase_commit to commit the transaction of the current user. Then the current user cannot have locks set on the table. Drop table -operation inside InnoDB will wait sleeping in a loop until no other -user has locks on the table. */ +operation inside InnoDB will remove all locks any user has on the table +inside InnoDB. */ int ha_innobase::delete_table( @@ -2615,6 +2693,53 @@ ha_innobase::delete_table( DBUG_RETURN(error); } +/********************************************************************* +Removes all tables in the named database inside InnoDB. */ + +int +innobase_drop_database( +/*===================*/ + /* out: error number */ + char* path) /* in: database path; inside InnoDB the name + of the last directory in the path is used as + the database name: for example, in 'mysql/data/test' + the database name is 'test' */ +{ + ulint len = 0; + trx_t* trx; + char* ptr; + int error; + char namebuf[10000]; + + ptr = strend(path) - 2; + + while (ptr >= path && *ptr != '\\' && *ptr != '/') { + ptr--; + len++; + } + + ptr++; + + memcpy(namebuf, ptr, len); + namebuf[len] = '/'; + namebuf[len + 1] = '\0'; + + trx = trx_allocate_for_mysql(); + + error = row_drop_database_for_mysql(namebuf, trx); + + /* Tell the InnoDB server that there might be work for + utility threads: */ + + srv_active_wake_master_thread(); + + trx_free_for_mysql(trx); + + error = convert_error_code_to_mysql(error); + + return(error); +} + /************************************************************************* Renames an InnoDB table. */ @@ -2751,12 +2876,13 @@ improve the algorithm of filesort.cc. */ ha_rows ha_innobase::estimate_number_of_rows(void) /*======================================*/ - /* out: upper bound of rows, currently 32-bit int - or uint */ + /* out: upper bound of rows */ { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - dict_table_t* ib_table; - + dict_index_t* index; + ulonglong estimate; + ulonglong data_file_length; + if (prebuilt->trx) { prebuilt->trx->op_info = "estimating upper bound of table size"; @@ -2764,21 +2890,21 @@ ha_innobase::estimate_number_of_rows(void) DBUG_ENTER("info"); - ib_table = prebuilt->table; - - dict_update_statistics(ib_table); - - data_file_length = ((ulonglong) - ib_table->stat_clustered_index_size) - * UNIV_PAGE_SIZE; + dict_update_statistics(prebuilt->table); - /* The minimum clustered index record size is 20 bytes */ + index = dict_table_get_first_index_noninline(prebuilt->table); + + data_file_length = ((ulonglong) index->stat_n_leaf_pages) + * UNIV_PAGE_SIZE; + /* Calculate a minimum length for a clustered index record */ + estimate = data_file_length / dict_index_calc_min_rec_len(index); + if (prebuilt->trx) { prebuilt->trx->op_info = ""; } - - return((ha_rows) (1000 + data_file_length / 20)); + + return((ha_rows) estimate); } /************************************************************************* @@ -2793,10 +2919,10 @@ ha_innobase::scan_time() { row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; - /* In the following formula we assume that scanning 5 pages + /* In the following formula we assume that scanning 10 pages takes the same time as a disk seek: */ - return((double) (1 + prebuilt->table->stat_clustered_index_size / 5)); + return((double) (prebuilt->table->stat_clustered_index_size / 10)); } /************************************************************************* @@ -2811,8 +2937,9 @@ ha_innobase::info( row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt; dict_table_t* ib_table; dict_index_t* index; - uint rec_per_key; - uint i; + ulong rec_per_key; + ulong j; + ulong i; DBUG_ENTER("info"); @@ -2830,7 +2957,7 @@ ha_innobase::info( } if (flag & HA_STATUS_VARIABLE) { - records = ib_table->stat_n_rows; + records = (ha_rows)ib_table->stat_n_rows; deleted = 0; data_file_length = ((ulonglong) ib_table->stat_clustered_index_size) @@ -2856,16 +2983,24 @@ ha_innobase::info( } for (i = 0; i < table->keys; i++) { - if (index->stat_n_diff_key_vals == 0) { - rec_per_key = records; - } else { - rec_per_key = records / - index->stat_n_diff_key_vals; + for (j = 0; j < table->key_info[i].key_parts; j++) { + + if (index->stat_n_diff_key_vals[j + 1] == 0) { + + rec_per_key = records; + } else { + rec_per_key = (ulong)(records / + index->stat_n_diff_key_vals[j + 1]); + } + + if (rec_per_key == 0) { + rec_per_key = 1; + } + + table->key_info[i].rec_per_key[j] + = rec_per_key; } - - table->key_info[i].rec_per_key[ - table->key_info[i].key_parts - 1] - = rec_per_key; + index = dict_table_get_next_index_noninline(index); } } |