diff options
-rw-r--r-- | mysql-test/r/update.result | 14 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb_bug54044.result | 3 | ||||
-rw-r--r-- | mysql-test/suite/innodb/r/innodb_mysql.result | 8 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_bug54044.test | 11 | ||||
-rw-r--r-- | mysql-test/suite/innodb/t/innodb_mysql.test | 14 | ||||
-rw-r--r-- | mysql-test/t/update.test | 20 | ||||
-rw-r--r-- | sql/filesort.cc | 4 | ||||
-rw-r--r-- | sql/opt_range.h | 6 | ||||
-rw-r--r-- | sql/sql_delete.cc | 3 | ||||
-rw-r--r-- | sql/sql_select.cc | 32 | ||||
-rw-r--r-- | sql/sql_table.cc | 20 | ||||
-rw-r--r-- | sql/sql_update.cc | 12 | ||||
-rw-r--r-- | storage/innobase/dict/dict0crea.c | 18 | ||||
-rw-r--r-- | storage/innobase/handler/ha_innodb.cc | 24 | ||||
-rw-r--r-- | storage/innobase/os/os0file.c | 12 |
15 files changed, 164 insertions, 37 deletions
diff --git a/mysql-test/r/update.result b/mysql-test/r/update.result index 6c3f54fca38..05ab1b71018 100644 --- a/mysql-test/r/update.result +++ b/mysql-test/r/update.result @@ -527,3 +527,17 @@ ERROR HY000: You are using safe update mode and you tried to update a table with SET SESSION sql_safe_updates = DEFAULT; DROP TABLE t1; DROP VIEW v1; +# +# Bug#54734 assert in Diagnostics_area::set_ok_status +# +DROP TABLE IF EXISTS t1, not_exists; +DROP FUNCTION IF EXISTS f1; +DROP VIEW IF EXISTS v1; +CREATE TABLE t1 (PRIMARY KEY(pk)) AS SELECT 1 AS pk; +CREATE FUNCTION f1() RETURNS INTEGER RETURN (SELECT 1 FROM not_exists); +CREATE VIEW v1 AS SELECT pk FROM t1 WHERE f1() = 13; +UPDATE v1 SET pk = 7 WHERE pk > 0; +ERROR HY000: View 'test.v1' references invalid table(s) or column(s) or function(s) or definer/invoker of view lack rights to use them +DROP VIEW v1; +DROP FUNCTION f1; +DROP TABLE t1; diff --git a/mysql-test/suite/innodb/r/innodb_bug54044.result b/mysql-test/suite/innodb/r/innodb_bug54044.result new file mode 100644 index 00000000000..90ab812f2ae --- /dev/null +++ b/mysql-test/suite/innodb/r/innodb_bug54044.result @@ -0,0 +1,3 @@ +CREATE TEMPORARY TABLE table_54044 ENGINE = INNODB +AS SELECT IF(NULL IS NOT NULL, NULL, NULL); +ERROR HY000: Can't create table 'test.table_54044' (errno: -1) diff --git a/mysql-test/suite/innodb/r/innodb_mysql.result b/mysql-test/suite/innodb/r/innodb_mysql.result index b418b62ec90..9a677f83080 100644 --- a/mysql-test/suite/innodb/r/innodb_mysql.result +++ b/mysql-test/suite/innodb/r/innodb_mysql.result @@ -2538,6 +2538,14 @@ ORDER BY f1 DESC LIMIT 5; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range f2,f4 f4 1 NULL 11 Using where DROP TABLE t1; +# +# Bug#54117 crash in thr_multi_unlock, temporary table +# +CREATE TEMPORARY TABLE t1(a INT) ENGINE = InnoDB; +LOCK TABLES t1 READ; +ALTER TABLE t1 COMMENT 'test'; +UNLOCK TABLES; +DROP TABLE t1; End of 5.1 tests # # Test for bug #39932 "create table fails if column for FK is in different diff --git a/mysql-test/suite/innodb/t/innodb_bug54044.test b/mysql-test/suite/innodb/t/innodb_bug54044.test new file mode 100644 index 00000000000..a6722ed6399 --- /dev/null +++ b/mysql-test/suite/innodb/t/innodb_bug54044.test @@ -0,0 +1,11 @@ +# This is the test for bug #54044. Special handle MYSQL_TYPE_NULL type +# during create table, so it will not trigger assertion failure. + +--source include/have_innodb.inc + +# This 'create table' operation should fail because of +# using NULL datatype +--error ER_CANT_CREATE_TABLE +CREATE TEMPORARY TABLE table_54044 ENGINE = INNODB + AS SELECT IF(NULL IS NOT NULL, NULL, NULL); + diff --git a/mysql-test/suite/innodb/t/innodb_mysql.test b/mysql-test/suite/innodb/t/innodb_mysql.test index fcd54075ecc..495d5c014ce 100644 --- a/mysql-test/suite/innodb/t/innodb_mysql.test +++ b/mysql-test/suite/innodb/t/innodb_mysql.test @@ -737,6 +737,20 @@ ORDER BY f1 DESC LIMIT 5; DROP TABLE t1; + +--echo # +--echo # Bug#54117 crash in thr_multi_unlock, temporary table +--echo # + +CREATE TEMPORARY TABLE t1(a INT) ENGINE = InnoDB; + +LOCK TABLES t1 READ; +ALTER TABLE t1 COMMENT 'test'; +UNLOCK TABLES; + +DROP TABLE t1; + + --echo End of 5.1 tests diff --git a/mysql-test/t/update.test b/mysql-test/t/update.test index f6708828a6b..c515f8873d8 100644 --- a/mysql-test/t/update.test +++ b/mysql-test/t/update.test @@ -483,3 +483,23 @@ UPDATE IGNORE v1 SET a = 1; SET SESSION sql_safe_updates = DEFAULT; DROP TABLE t1; DROP VIEW v1; + +--echo # +--echo # Bug#54734 assert in Diagnostics_area::set_ok_status +--echo # + +--disable_warnings +DROP TABLE IF EXISTS t1, not_exists; +DROP FUNCTION IF EXISTS f1; +DROP VIEW IF EXISTS v1; +--enable_warnings + +CREATE TABLE t1 (PRIMARY KEY(pk)) AS SELECT 1 AS pk; +CREATE FUNCTION f1() RETURNS INTEGER RETURN (SELECT 1 FROM not_exists); +CREATE VIEW v1 AS SELECT pk FROM t1 WHERE f1() = 13; +--error ER_VIEW_INVALID +UPDATE v1 SET pk = 7 WHERE pk > 0; + +DROP VIEW v1; +DROP FUNCTION f1; +DROP TABLE t1; diff --git a/sql/filesort.cc b/sql/filesort.cc index 2398785a038..b98a7f780f4 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -511,6 +511,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, volatile THD::killed_state *killed= &thd->killed; handler *file; MY_BITMAP *save_read_set, *save_write_set; + bool skip_record; DBUG_ENTER("find_all_keys"); DBUG_PRINT("info",("using: %s", (select ? select->quick ? "ranges" : "where": @@ -603,7 +604,8 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, } if (error == 0) param->examined_rows++; - if (error == 0 && (!select || select->skip_record() == 0)) + if (!error && (!select || + (!select->skip_record(thd, &skip_record) && !skip_record))) { if (idx == param->keys) { diff --git a/sql/opt_range.h b/sql/opt_range.h index 0d4000002b0..33b3d561ad8 100644 --- a/sql/opt_range.h +++ b/sql/opt_range.h @@ -825,7 +825,11 @@ class SQL_SELECT :public Sql_alloc { tmp.set_all(); return test_quick_select(thd, tmp, 0, limit, force_quick_range) < 0; } - inline bool skip_record() { return cond ? cond->val_int() == 0 : 0; } + inline bool skip_record(THD *thd, bool *skip_record) + { + *skip_record= cond ? cond->val_int() == FALSE : FALSE; + return thd->is_error(); + } int test_quick_select(THD *thd, key_map keys, table_map prev_tables, ha_rows limit, bool force_quick_range); }; diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index c94ea1302c8..00666bc85b4 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -59,6 +59,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, bool const_cond_result; ha_rows deleted= 0; bool reverse= FALSE; + bool skip_record; ORDER *order= (ORDER *) ((order_list && order_list->elements) ? order_list->first : NULL); uint usable_index= MAX_KEY; @@ -298,7 +299,7 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, { thd->examined_row_count++; // thd->is_error() is tested to disallow delete row on error - if (!(select && select->skip_record())&& ! thd->is_error() ) + if (!select || (!select->skip_record(thd, &skip_record) && !skip_record)) { if (table->triggers && diff --git a/sql/sql_select.cc b/sql/sql_select.cc index 11378ac0d11..74d05780f81 100644 --- a/sql/sql_select.cc +++ b/sql/sql_select.cc @@ -11941,38 +11941,30 @@ flush_cached_records(JOIN *join,JOIN_TAB *join_tab,bool skip_last) SQL_SELECT *select=join_tab->select; if (rc == NESTED_LOOP_OK) { - bool consider_record= !join_tab->cache.select || - !join_tab->cache.select->skip_record(); - - /* - Check for error: skip_record() can execute code by calling - Item_subselect::val_*. We need to check for errors (if any) - after such call. - */ - if (join->thd->is_error()) + bool skip_record= FALSE; + if (join_tab->cache.select && + join_tab->cache.select->skip_record(join->thd, &skip_record)) { reset_cache_write(&join_tab->cache); return NESTED_LOOP_ERROR; } - if (consider_record) + if (!skip_record) { uint i; reset_cache_read(&join_tab->cache); for (i=(join_tab->cache.records- (skip_last ? 1 : 0)) ; i-- > 0 ;) { read_cached_record(join_tab); - if (!select || !select->skip_record()) + skip_record= FALSE; + if (select && select->skip_record(join->thd, &skip_record)) { - /* - Check for error: skip_record() can execute code by calling - Item_subselect::val_*. We need to check for errors (if any) - after such call. - */ - if (join->thd->is_error()) - rc= NESTED_LOOP_ERROR; - else - rc= (join_tab->next_select)(join,join_tab+1,0); + reset_cache_write(&join_tab->cache); + return NESTED_LOOP_ERROR; + } + if (!skip_record) + { + rc= (join_tab->next_select)(join,join_tab+1,0); if (rc != NESTED_LOOP_OK && rc != NESTED_LOOP_NO_MORE_ROWS) { reset_cache_write(&join_tab->cache); diff --git a/sql/sql_table.cc b/sql/sql_table.cc index fa9f9b7f633..d28b4859ab5 100644 --- a/sql/sql_table.cc +++ b/sql/sql_table.cc @@ -7339,12 +7339,22 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name, if (table->s->tmp_table != NO_TMP_TABLE) { /* Close lock if this is a transactional table */ - if (thd->lock && - ! (thd->locked_tables_mode == LTM_LOCK_TABLES || - thd->locked_tables_mode == LTM_PRELOCKED_UNDER_LOCK_TABLES)) + if (thd->lock) { - mysql_unlock_tables(thd, thd->lock); - thd->lock=0; + if (thd->locked_tables_mode != LTM_LOCK_TABLES && + thd->locked_tables_mode != LTM_PRELOCKED_UNDER_LOCK_TABLES) + { + mysql_unlock_tables(thd, thd->lock); + thd->lock=0; + } + else + { + /* + If LOCK TABLES list is not empty and contains this table, + unlock the table and remove the table from this list. + */ + mysql_lock_remove(thd, thd->lock, table); + } } /* Remove link to old table and rename the new one */ close_temporary_table(thd, table, 1, 1); diff --git a/sql/sql_update.cc b/sql/sql_update.cc index 25c1fd6fa1e..c52467531a9 100644 --- a/sql/sql_update.cc +++ b/sql/sql_update.cc @@ -477,7 +477,14 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { thd->examined_row_count++; - if (!(select && select->skip_record())) + bool skip_record= FALSE; + if (select && select->skip_record(thd, &skip_record)) + { + error= 1; + table->file->unlock_row(); + break; + } + if (!skip_record) { if (table->file->was_semi_consistent_read()) continue; /* repeat the read of the same row if it still exists */ @@ -584,7 +591,8 @@ int mysql_update(THD *thd, while (!(error=info.read_record(&info)) && !thd->killed) { thd->examined_row_count++; - if (!(select && select->skip_record())) + bool skip_record; + if (!select || (!select->skip_record(thd, &skip_record) && !skip_record)) { if (table->file->was_semi_consistent_read()) continue; /* repeat the read of the same row if it still exists */ diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c index f185371bfca..09353c45c8c 100644 --- a/storage/innobase/dict/dict0crea.c +++ b/storage/innobase/dict/dict0crea.c @@ -240,17 +240,29 @@ dict_build_table_def_step( ibool is_path; mtr_t mtr; ulint space = 0; + ibool file_per_table; ut_ad(mutex_own(&(dict_sys->mutex))); table = node->table; - dict_hdr_get_new_id(&table->id, NULL, - srv_file_per_table ? &space : NULL); + /* Cache the global variable "srv_file_per_table" to + a local variable before using it. Please note + "srv_file_per_table" is not under dict_sys mutex + protection, and could be changed while executing + this function. So better to cache the current value + to a local variable, and all future reference to + "srv_file_per_table" should use this local variable. */ + file_per_table = srv_file_per_table; + + dict_hdr_get_new_id(&table->id, NULL, NULL); thr_get_trx(thr)->table_id = table->id; - if (srv_file_per_table) { + if (file_per_table) { + /* Get a new space id if srv_file_per_table is set */ + dict_hdr_get_new_id(NULL, NULL, &space); + if (UNIV_UNLIKELY(space == ULINT_UNDEFINED)) { return(DB_ERROR); } diff --git a/storage/innobase/handler/ha_innodb.cc b/storage/innobase/handler/ha_innodb.cc index f5227add6f1..716b7bbbd56 100644 --- a/storage/innobase/handler/ha_innodb.cc +++ b/storage/innobase/handler/ha_innodb.cc @@ -4128,6 +4128,11 @@ get_innobase_type_from_mysql_type( case MYSQL_TYPE_BLOB: case MYSQL_TYPE_LONG_BLOB: return(DATA_BLOB); + case MYSQL_TYPE_NULL: + /* MySQL currently accepts "NULL" datatype, but will + reject such datatype in the next release. We will cope + with it and not trigger assertion failure in 5.1 */ + break; default: ut_error; } @@ -6175,7 +6180,22 @@ create_table_def( field = form->field[i]; col_type = get_innobase_type_from_mysql_type(&unsigned_type, - field); + field); + + if (!col_type) { + push_warning_printf( + (THD*) trx->mysql_thd, + MYSQL_ERROR::WARN_LEVEL_WARN, + ER_CANT_CREATE_TABLE, + "Error creating table '%s' with " + "column '%s'. Please check its " + "column type and try to re-create " + "the table with an appropriate " + "column type.", + table->name, (char*) field->field_name); + goto err_col; + } + if (field->null_ptr) { nulls_allowed = 0; } else { @@ -6233,7 +6253,7 @@ create_table_def( if (dict_col_name_is_reserved(field->field_name)){ my_error(ER_WRONG_COLUMN_NAME, MYF(0), field->field_name); - +err_col: dict_mem_table_free(table); trx_commit_for_mysql(trx); diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index 7c502d616d3..a7117386608 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -1445,7 +1445,11 @@ try_again: /* When srv_file_per_table is on, file creation failure may not be critical to the whole instance. Do not crash the server in - case of unknown errors. */ + case of unknown errors. + Please note "srv_file_per_table" is a global variable with + no explicit synchronization protection. It could be + changed during this execution path. It might not have the + same value as the one when building the table definition */ if (srv_file_per_table) { retry = os_file_handle_error_no_exit(name, create_mode == OS_FILE_CREATE ? @@ -1532,7 +1536,11 @@ try_again: /* When srv_file_per_table is on, file creation failure may not be critical to the whole instance. Do not crash the server in - case of unknown errors. */ + case of unknown errors. + Please note "srv_file_per_table" is a global variable with + no explicit synchronization protection. It could be + changed during this execution path. It might not have the + same value as the one when building the table definition */ if (srv_file_per_table) { retry = os_file_handle_error_no_exit(name, create_mode == OS_FILE_CREATE ? |