summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--mysql-test/r/update.result14
-rw-r--r--mysql-test/suite/innodb/r/innodb_bug54044.result3
-rw-r--r--mysql-test/suite/innodb/r/innodb_mysql.result8
-rw-r--r--mysql-test/suite/innodb/t/innodb_bug54044.test11
-rw-r--r--mysql-test/suite/innodb/t/innodb_mysql.test14
-rw-r--r--mysql-test/t/update.test20
-rw-r--r--sql/filesort.cc4
-rw-r--r--sql/opt_range.h6
-rw-r--r--sql/sql_delete.cc3
-rw-r--r--sql/sql_select.cc32
-rw-r--r--sql/sql_table.cc20
-rw-r--r--sql/sql_update.cc12
-rw-r--r--storage/innobase/dict/dict0crea.c18
-rw-r--r--storage/innobase/handler/ha_innodb.cc24
-rw-r--r--storage/innobase/os/os0file.c12
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 ?