diff options
-rw-r--r-- | mysql-test/r/partition_myisam.result | 2 | ||||
-rw-r--r-- | mysql-test/r/partition_not_blackhole.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/percona/percona_innodb_fake_changes.result | 2 | ||||
-rw-r--r-- | mysql-test/suite/percona/percona_innodb_fake_changes.test | 2 | ||||
-rw-r--r-- | mysql-test/t/partition_myisam.test | 2 | ||||
-rw-r--r-- | mysql-test/t/partition_not_blackhole.test | 2 | ||||
-rw-r--r-- | sql/handler.cc | 85 | ||||
-rw-r--r-- | sql/sql_table.cc | 28 |
8 files changed, 68 insertions, 57 deletions
diff --git a/mysql-test/r/partition_myisam.result b/mysql-test/r/partition_myisam.result index 80b3a9511ea..bb1a7b19a9d 100644 --- a/mysql-test/r/partition_myisam.result +++ b/mysql-test/r/partition_myisam.result @@ -90,7 +90,7 @@ ERROR HY000: Failed to read from the .par file # Note that it is currently impossible to drop a partitioned table # without the .par file DROP TABLE t1; -ERROR 42S02: Unknown table 'test.t1' +ERROR HY000: Got error 1 "Operation not permitted" from storage engine partition # # Bug#50392: insert_id is not reset for partitioned tables # auto_increment on duplicate entry diff --git a/mysql-test/r/partition_not_blackhole.result b/mysql-test/r/partition_not_blackhole.result index 923d70c0ad6..7759f947c32 100644 --- a/mysql-test/r/partition_not_blackhole.result +++ b/mysql-test/r/partition_not_blackhole.result @@ -11,6 +11,6 @@ t1 SHOW CREATE TABLE t1; ERROR HY000: Incorrect information in file: './test/t1.frm' DROP TABLE t1; -ERROR 42S02: Unknown table 'test.t1' +ERROR HY000: Got error 1 "Operation not permitted" from storage engine partition t1.frm t1.par diff --git a/mysql-test/suite/percona/percona_innodb_fake_changes.result b/mysql-test/suite/percona/percona_innodb_fake_changes.result index 95f0c07cd11..1b870fdbb92 100644 --- a/mysql-test/suite/percona/percona_innodb_fake_changes.result +++ b/mysql-test/suite/percona/percona_innodb_fake_changes.result @@ -45,7 +45,7 @@ BEGIN; CREATE TABLE t2 (a INT) ENGINE=InnoDB; ERROR HY000: Can't create table `test`.`t2` (errno: 131 "Command not supported by database") DROP TABLE t1; -ERROR 42S02: Unknown table 'test.t1' +ERROR HY000: Storage engine InnoDB of the table `test`.`t1` doesn't have this option TRUNCATE TABLE t1; ERROR HY000: Got error 131 "Command not supported by database" during COMMIT ALTER TABLE t1 ENGINE=MyISAM; diff --git a/mysql-test/suite/percona/percona_innodb_fake_changes.test b/mysql-test/suite/percona/percona_innodb_fake_changes.test index 5fa3ecc7b63..67f5450ba45 100644 --- a/mysql-test/suite/percona/percona_innodb_fake_changes.test +++ b/mysql-test/suite/percona/percona_innodb_fake_changes.test @@ -38,7 +38,7 @@ SET innodb_fake_changes=1; BEGIN; --error 1005 CREATE TABLE t2 (a INT) ENGINE=InnoDB; ---error 1051 +--error 1031 DROP TABLE t1; --error 1180 TRUNCATE TABLE t1; diff --git a/mysql-test/t/partition_myisam.test b/mysql-test/t/partition_myisam.test index a33b9e19fbf..bce0c6f009c 100644 --- a/mysql-test/t/partition_myisam.test +++ b/mysql-test/t/partition_myisam.test @@ -123,7 +123,7 @@ CHECK TABLE t1; SELECT * FROM t1; --echo # Note that it is currently impossible to drop a partitioned table --echo # without the .par file ---error ER_BAD_TABLE_ERROR +--error ER_GET_ERRNO DROP TABLE t1; --remove_file $MYSQLD_DATADIR/test/t1.frm --remove_file $MYSQLD_DATADIR/test/t1#P#p0.MYI diff --git a/mysql-test/t/partition_not_blackhole.test b/mysql-test/t/partition_not_blackhole.test index 7352aeaa230..3731d659ad0 100644 --- a/mysql-test/t/partition_not_blackhole.test +++ b/mysql-test/t/partition_not_blackhole.test @@ -19,7 +19,7 @@ SHOW TABLES; --replace_result $MYSQLD_DATADIR ./ --error ER_NOT_FORM_FILE SHOW CREATE TABLE t1; ---error ER_BAD_TABLE_ERROR +--error ER_GET_ERRNO DROP TABLE t1; --list_files $MYSQLD_DATADIR/test t1* --remove_file $MYSQLD_DATADIR/test/t1.frm diff --git a/sql/handler.cc b/sql/handler.cc index 70bce6f3963..1f8daf3927b 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -2298,9 +2298,11 @@ handle_condition(THD *, } -/** @brief - This should return ENOENT if the file doesn't exists. - The .frm file will be deleted only if we return 0 or ENOENT +/** delete a table in the engine + + @note + ENOENT and HA_ERR_NO_SUCH_TABLE are not considered errors. + The .frm file will be deleted only if we return 0. */ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, const char *db, const char *alias, bool generate_warning) @@ -2315,47 +2317,66 @@ int ha_delete_table(THD *thd, handlerton *table_type, const char *path, /* table_type is NULL in ALTER TABLE when renaming only .frm files */ if (table_type == NULL || table_type == view_pseudo_hton || ! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type))) - DBUG_RETURN(HA_ERR_NO_SUCH_TABLE); + DBUG_RETURN(0); bzero((char*) &dummy_table, sizeof(dummy_table)); bzero((char*) &dummy_share, sizeof(dummy_share)); dummy_table.s= &dummy_share; path= get_canonical_filename(file, path, tmp_path); - if ((error= file->ha_delete_table(path)) && generate_warning) + if ((error= file->ha_delete_table(path))) { /* - Because file->print_error() use my_error() to generate the error message - we use an internal error handler to intercept it and store the text - in a temporary buffer. Later the message will be presented to user - as a warning. + it's not an error if the table doesn't exist in the engine. + warn the user, but still report DROP being a success */ - Ha_delete_table_error_handler ha_delete_table_error_handler; - - /* Fill up strucutures that print_error may need */ - dummy_share.path.str= (char*) path; - dummy_share.path.length= strlen(path); - dummy_share.normalized_path= dummy_share.path; - dummy_share.db.str= (char*) db; - dummy_share.db.length= strlen(db); - dummy_share.table_name.str= (char*) alias; - dummy_share.table_name.length= strlen(alias); - dummy_table.alias.set(alias, dummy_share.table_name.length, - table_alias_charset); + bool intercept= error == ENOENT || error == HA_ERR_NO_SUCH_TABLE; - file->change_table_ptr(&dummy_table, &dummy_share); - - thd->push_internal_handler(&ha_delete_table_error_handler); - file->print_error(error, 0); + if (!intercept || generate_warning) + { + /* + Because file->print_error() use my_error() to generate the error message + we use an internal error handler to intercept it and store the text + in a temporary buffer. Later the message will be presented to user + as a warning. + */ + Ha_delete_table_error_handler ha_delete_table_error_handler; + + /* Fill up strucutures that print_error may need */ + dummy_share.path.str= (char*) path; + dummy_share.path.length= strlen(path); + dummy_share.normalized_path= dummy_share.path; + dummy_share.db.str= (char*) db; + dummy_share.db.length= strlen(db); + dummy_share.table_name.str= (char*) alias; + dummy_share.table_name.length= strlen(alias); + dummy_table.alias.set(alias, dummy_share.table_name.length, + table_alias_charset); + + file->change_table_ptr(&dummy_table, &dummy_share); + +#if MYSQL_VERSION_ID > 100105 + // XXX as an ugly 10.0-only hack we intercept HA_ERR_ROW_IS_REFERENCED, + // to report it under the old historical error number. +#error remove HA_ERR_ROW_IS_REFERENCED, use ME_JUST_WARNING instead of a handler +#endif + if (intercept || error == HA_ERR_ROW_IS_REFERENCED) + thd->push_internal_handler(&ha_delete_table_error_handler); - thd->pop_internal_handler(); + file->print_error(error, 0); - /* - XXX: should we convert *all* errors to warnings here? - What if the error is fatal? - */ - push_warning(thd, Sql_condition::WARN_LEVEL_WARN, error, - ha_delete_table_error_handler.buff); + if (intercept || error == HA_ERR_ROW_IS_REFERENCED) + { + thd->pop_internal_handler(); + if (error == HA_ERR_ROW_IS_REFERENCED) + my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0)); + else + push_warning(thd, Sql_condition::WARN_LEVEL_WARN, error, + ha_delete_table_error_handler.buff); + } + } + if (intercept) + error= 0; } delete file; diff --git a/sql/sql_table.cc b/sql/sql_table.cc index 3a7930f6963..20cfccaa3d9 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -2201,15 +2201,13 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, char path[FN_REFLEN + 1], wrong_tables_buff[160], *alias= NULL; String wrong_tables(wrong_tables_buff, sizeof(wrong_tables_buff)-1, system_charset_info); - uint path_length= 0; + uint path_length= 0, errors= 0; int error= 0; int non_temp_tables_count= 0; - bool foreign_key_error=0; bool non_tmp_error= 0; bool trans_tmp_table_deleted= 0, non_trans_tmp_table_deleted= 0; bool non_tmp_table_deleted= 0; bool is_drop_tmp_if_exists_added= 0; - bool one_table= tables->next_local == 0; bool was_view= 0; String built_query; String built_trans_tmp_query, built_non_trans_tmp_query; @@ -2495,12 +2493,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, error= ha_delete_table(thd, table_type, path, db, table->table_name, !dont_log_query); - if (error == HA_ERR_ROW_IS_REFERENCED) - { - /* the table is referenced by a foreign key constraint */ - foreign_key_error= 1; - } - if (!error || error == ENOENT || error == HA_ERR_NO_SUCH_TABLE) + if (!error) { int frm_delete_error, trigger_drop_error= 0; /* Delete the table definition file */ @@ -2518,11 +2511,8 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, if (trigger_drop_error || (frm_delete_error && frm_delete_error != ENOENT)) error= 1; - else if (!frm_delete_error || !error || if_exists) - { - error= 0; + else if (frm_delete_error && if_exists) thd->clear_error(); - } } non_tmp_error= error ? TRUE : non_tmp_error; } @@ -2533,6 +2523,7 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, wrong_tables.append(db); wrong_tables.append('.'); wrong_tables.append(table->table_name); + errors++; } else { @@ -2556,14 +2547,13 @@ int mysql_rm_table_no_locks(THD *thd, TABLE_LIST *tables, bool if_exists, err: if (wrong_tables.length()) { - if (one_table && was_view) + DBUG_ASSERT(errors); + if (errors == 1 && was_view) my_printf_error(ER_IT_IS_A_VIEW, ER(ER_IT_IS_A_VIEW), MYF(0), wrong_tables.c_ptr_safe()); - else if (!foreign_key_error) + else if (errors > 1 || !thd->is_error()) my_printf_error(ER_BAD_TABLE_ERROR, ER(ER_BAD_TABLE_ERROR), MYF(0), wrong_tables.c_ptr_safe()); - else - my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0)); error= 1; } @@ -2614,8 +2604,8 @@ err: /* Chop of the last comma */ built_query.chop(); built_query.append(" /* generated by server */"); - int error_code = (non_tmp_error ? - (foreign_key_error ? ER_ROW_IS_REFERENCED : ER_BAD_TABLE_ERROR) : 0); + int error_code = non_tmp_error ? thd->get_stmt_da()->sql_errno() + : 0; error |= thd->binlog_query(THD::STMT_QUERY_TYPE, built_query.ptr(), built_query.length(), |