diff options
author | kostja@bodhi.(none) <> | 2007-07-24 22:57:26 +0400 |
---|---|---|
committer | kostja@bodhi.(none) <> | 2007-07-24 22:57:26 +0400 |
commit | 4c208499a409d9e558ca019e9e101115d801bab7 (patch) | |
tree | 0c08dbb0f6adf471efce8ca848950431c0a9380c | |
parent | 9d247f296a8086f6379a32cece568ada279f9f8c (diff) | |
parent | 2ecd75ef24297389c2052bfedb7e25c83ff5760a (diff) | |
download | mariadb-git-4c208499a409d9e558ca019e9e101115d801bab7.tar.gz |
Merge bk-internal.mysql.com:/home/bk/mysql-5.0
into bodhi.(none):/opt/local/work/mysql-5.0-runtime
-rw-r--r-- | mysql-test/r/create.result | 16 | ||||
-rw-r--r-- | mysql-test/r/innodb.result | 2 | ||||
-rw-r--r-- | mysql-test/r/sp-prelocking.result | 22 | ||||
-rw-r--r-- | mysql-test/r/trigger.result | 28 | ||||
-rw-r--r-- | mysql-test/t/create.test | 19 | ||||
-rw-r--r-- | mysql-test/t/innodb.test | 2 | ||||
-rw-r--r-- | mysql-test/t/sp-prelocking.test | 23 | ||||
-rw-r--r-- | mysql-test/t/trigger.test | 23 | ||||
-rw-r--r-- | sql/sql_base.cc | 6 | ||||
-rw-r--r-- | sql/sql_class.h | 2 | ||||
-rw-r--r-- | sql/sql_insert.cc | 128 |
11 files changed, 211 insertions, 60 deletions
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index e692dbf3938..a1843573794 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1503,4 +1503,20 @@ t1 CREATE TABLE `t1` ( `c17` int(11) default NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 drop table t1; + +Bug #26104 Bug on foreign key class constructor + +Check that ref_columns is initalized correctly in the constructor +and semantic checks in mysql_prepare_table work. + +We do not need a storage engine that supports foreign keys +for this test, as the checks are purely syntax-based, and the +syntax is supported for all engines. + +drop table if exists t1,t2; +create table t1(a int not null, b int not null, primary key (a, b)); +create table t2(a int not null, b int not null, c int not null, primary key (a), +foreign key fk_bug26104 (b,c) references t1(a)); +ERROR 42000: Incorrect foreign key definition for 'fk_bug26104': Key reference and table reference don't match +drop table t1; End of 5.0 tests diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index 80b46e5098a..6082a30bce3 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1648,7 +1648,7 @@ t2 CREATE TABLE `t2` ( ) ENGINE=InnoDB DEFAULT CHARSET=latin1 drop table t2; create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; -ERROR HY000: Can't create table './test/t2' (errno: 150) +ERROR 42000: Incorrect foreign key definition for 't1_id_fk': Key reference and table reference don't match create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb; show create table t2; Table Create Table diff --git a/mysql-test/r/sp-prelocking.result b/mysql-test/r/sp-prelocking.result index 5eac54803f0..c19bd1abd26 100644 --- a/mysql-test/r/sp-prelocking.result +++ b/mysql-test/r/sp-prelocking.result @@ -267,4 +267,26 @@ drop table bug_27907_logs; insert into bug_27907_t1(a) values (1); ERROR 42S02: Table 'test.bug_27907_logs' doesn't exist drop table bug_27907_t1; + +Bug#22427 create table if not exists + stored function results in +inconsistent behavior + +Add a test case, the bug itself was fixed by the patch for +Bug#20662 + +drop table if exists t1; +drop function if exists f_bug22427; +create table t1 (i int); +insert into t1 values (1); +create function f_bug22427() returns int return (select max(i) from t1); +select f_bug22427(); +f_bug22427() +1 +create table if not exists t1 select f_bug22427() as i; +Warnings: +Note 1050 Table 't1' already exists +create table t1 select f_bug22427() as i; +ERROR 42S01: Table 't1' already exists +drop table t1; +drop function f_bug22427; End of 5.0 tests diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 4b18e525e62..a07318435f6 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -1933,4 +1933,32 @@ Before UPDATE, new=multi-UPDATE, SET for t2, but the trigger is fired, old=multi After UPDATE, new=multi-UPDATE, SET for t2, but the trigger is fired, old=multi-UPDATE drop view v1; drop table t1, t2, t1_op_log; + +Bug#27248 Triggers: error if insert affects temporary table + +The bug was fixed by the fix for Bug#26141 + +drop table if exists t1; +drop temporary table if exists t2; +create table t1 (s1 int); +create temporary table t2 (s1 int); +create trigger t1_bi before insert on t1 for each row insert into t2 values (0); +create trigger t1_bd before delete on t1 for each row delete from t2; +insert into t1 values (0); +insert into t1 values (0); +select * from t1; +s1 +0 +0 +select * from t2; +s1 +0 +0 +delete from t1; +select * from t1; +s1 +select * from t2; +s1 +drop table t1; +drop temporary table t2; End of 5.0 tests diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index 99f3fea416a..a6679cd674a 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -1118,5 +1118,24 @@ show create table t1; drop table t1; +--echo +--echo Bug #26104 Bug on foreign key class constructor +--echo +--echo Check that ref_columns is initalized correctly in the constructor +--echo and semantic checks in mysql_prepare_table work. +--echo +--echo We do not need a storage engine that supports foreign keys +--echo for this test, as the checks are purely syntax-based, and the +--echo syntax is supported for all engines. +--echo +--disable_warnings +drop table if exists t1,t2; +--enable_warnings + +create table t1(a int not null, b int not null, primary key (a, b)); +--error ER_WRONG_FK_DEF +create table t2(a int not null, b int not null, c int not null, primary key (a), +foreign key fk_bug26104 (b,c) references t1(a)); +drop table t1; --echo End of 5.0 tests diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index a9679c01071..04dfa1d0836 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -1180,7 +1180,7 @@ drop table t2; # Clean up filename -- embedded server reports whole path without .frm, # regular server reports relative path with .frm (argh!) --replace_result \\ / $MYSQL_TEST_DIR . /var/master-data/ / t2.frm t2 ---error 1005 +--error ER_WRONG_FK_DEF create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb; # bug#3749 diff --git a/mysql-test/t/sp-prelocking.test b/mysql-test/t/sp-prelocking.test index ec5b7fbad7c..60e97260839 100644 --- a/mysql-test/t/sp-prelocking.test +++ b/mysql-test/t/sp-prelocking.test @@ -333,4 +333,27 @@ insert into bug_27907_t1(a) values (1); drop table bug_27907_t1; +--echo +--echo Bug#22427 create table if not exists + stored function results in +--echo inconsistent behavior +--echo +--echo Add a test case, the bug itself was fixed by the patch for +--echo Bug#20662 +--echo +--disable_warnings +drop table if exists t1; +drop function if exists f_bug22427; +--enable_warnings +create table t1 (i int); +insert into t1 values (1); +create function f_bug22427() returns int return (select max(i) from t1); +select f_bug22427(); +# Until this bug was fixed, the following emitted error +# ERROR 1213: Deadlock found when trying to get lock +create table if not exists t1 select f_bug22427() as i; +--error ER_TABLE_EXISTS_ERROR +create table t1 select f_bug22427() as i; +drop table t1; +drop function f_bug22427; + --echo End of 5.0 tests diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index a6390036322..2f62ad38621 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -2194,4 +2194,27 @@ drop table t1, t2, t1_op_log; # # TODO: test LOAD DATA INFILE +# +--echo +--echo Bug#27248 Triggers: error if insert affects temporary table +--echo +--echo The bug was fixed by the fix for Bug#26141 +--echo +--disable_warnings +drop table if exists t1; +drop temporary table if exists t2; +--enable_warnings +create table t1 (s1 int); +create temporary table t2 (s1 int); +create trigger t1_bi before insert on t1 for each row insert into t2 values (0); +create trigger t1_bd before delete on t1 for each row delete from t2; +insert into t1 values (0); +insert into t1 values (0); +select * from t1; +select * from t2; +delete from t1; +select * from t1; +select * from t2; +drop table t1; +drop temporary table t2; --echo End of 5.0 tests diff --git a/sql/sql_base.cc b/sql/sql_base.cc index bf1c6d7cb0d..3860dfa1ded 100644 --- a/sql/sql_base.cc +++ b/sql/sql_base.cc @@ -62,11 +62,11 @@ Prelock_error_handler::handle_error(uint sql_errno, if (sql_errno == ER_NO_SUCH_TABLE) { m_handled_errors++; - return TRUE; // 'TRUE', as per coding style + return TRUE; } m_unhandled_errors++; - return FALSE; // 'FALSE', as per coding style + return FALSE; } @@ -2674,7 +2674,7 @@ int open_tables(THD *thd, TABLE_LIST **start, uint *counter, uint flags) */ for (tables= *start; tables ;tables= tables->next_global) { - safe_to_ignore_table= FALSE; // 'FALSE', as per coding style + safe_to_ignore_table= FALSE; if (tables->lock_type == TL_WRITE_DEFAULT) { diff --git a/sql/sql_class.h b/sql/sql_class.h index 445a3ce437c..058f130d4e7 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -450,7 +450,7 @@ public: Table_ident *table, List<key_part_spec> &ref_cols, uint delete_opt_arg, uint update_opt_arg, uint match_opt_arg) :Key(FOREIGN_KEY, name_arg, HA_KEY_ALG_UNDEF, 0, cols), - ref_table(table), ref_columns(cols), + ref_table(table), ref_columns(ref_cols), delete_opt(delete_opt_arg), update_opt(update_opt_arg), match_opt(match_opt_arg) {} diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 73f8c5e4418..19c9360b0ed 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1702,18 +1702,18 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) thd->proc_info="waiting for delay_list"; pthread_mutex_lock(&LOCK_delayed_insert); // Protect master list I_List_iterator<Delayed_insert> it(delayed_threads); - Delayed_insert *tmp; - while ((tmp=it++)) + Delayed_insert *di; + while ((di= it++)) { - if (!strcmp(tmp->thd.db,table_list->db) && - !strcmp(table_list->table_name,tmp->table->s->table_name)) + if (!strcmp(table_list->db, di->table_list.db) && + !strcmp(table_list->table_name, di->table_list.table_name)) { - tmp->lock(); + di->lock(); break; } } pthread_mutex_unlock(&LOCK_delayed_insert); // For unlink from list - return tmp; + return di; } @@ -1739,21 +1739,41 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) Two latter cases indicate a request for lock upgrade. XXX: why do we regard INSERT DELAYED into a view as an error and - do not simply a lock upgrade? + do not simply perform a lock upgrade? + + TODO: The approach with using two mutexes to work with the + delayed thread list -- LOCK_delayed_insert and + LOCK_delayed_create -- is redundant, and we only need one of + them to protect the list. The reason we have two locks is that + we do not want to block look-ups in the list while we're waiting + for the newly created thread to open the delayed table. However, + this wait itself is redundant -- we always call get_local_table + later on, and there wait again until the created thread acquires + a table lock. + + As is redundant the concept of locks_in_memory, since we already + have another counter with similar semantics - tables_in_use, + both of them are devoted to counting the number of producers for + a given consumer (delayed insert thread), only at different + stages of producer-consumer relationship. + + 'dead' and 'status' variables in Delayed_insert are redundant + too, since there is already 'di->thd.killed' and + di->stacked_inserts. */ static bool delayed_get_table(THD *thd, TABLE_LIST *table_list) { int error; - Delayed_insert *tmp; + Delayed_insert *di; DBUG_ENTER("delayed_get_table"); /* Must be set in the parser */ DBUG_ASSERT(table_list->db); /* Find the thread which handles this table. */ - if (!(tmp=find_handler(thd,table_list))) + if (!(di= find_handler(thd, table_list))) { /* No match. Create a new thread to handle the table, but @@ -1767,9 +1787,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) The first search above was done without LOCK_delayed_create. Another thread might have created the handler in between. Search again. */ - if (! (tmp= find_handler(thd, table_list))) + if (! (di= find_handler(thd, table_list))) { - if (!(tmp=new Delayed_insert())) + if (!(di= new Delayed_insert())) { my_error(ER_OUTOFMEMORY,MYF(0),sizeof(Delayed_insert)); thd->fatal_error(); @@ -1778,28 +1798,30 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) pthread_mutex_lock(&LOCK_thread_count); thread_count++; pthread_mutex_unlock(&LOCK_thread_count); - tmp->thd.set_db(table_list->db, strlen(table_list->db)); - tmp->thd.query= my_strdup(table_list->table_name,MYF(MY_WME)); - if (tmp->thd.db == NULL || tmp->thd.query == NULL) + di->thd.set_db(table_list->db, strlen(table_list->db)); + di->thd.query= my_strdup(table_list->table_name, MYF(MY_WME)); + if (di->thd.db == NULL || di->thd.query == NULL) { /* The error is reported */ - delete tmp; + delete di; thd->fatal_error(); goto end_create; } - tmp->table_list= *table_list; // Needed to open table - tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query; - tmp->lock(); - pthread_mutex_lock(&tmp->mutex); - if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib, - handle_delayed_insert,(void*) tmp))) + di->table_list= *table_list; // Needed to open table + /* Replace volatile strings with local copies */ + di->table_list.alias= di->table_list.table_name= di->thd.query; + di->table_list.db= di->thd.db; + di->lock(); + pthread_mutex_lock(&di->mutex); + if ((error= pthread_create(&di->thd.real_id, &connection_attrib, + handle_delayed_insert, (void*) di))) { DBUG_PRINT("error", ("Can't create thread to handle delayed insert (error %d)", error)); - pthread_mutex_unlock(&tmp->mutex); - tmp->unlock(); - delete tmp; + pthread_mutex_unlock(&di->mutex); + di->unlock(); + delete di; my_error(ER_CANT_CREATE_THREAD, MYF(0), error); thd->fatal_error(); goto end_create; @@ -1807,15 +1829,15 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) /* Wait until table is open */ thd->proc_info="waiting for handler open"; - while (!tmp->thd.killed && !tmp->table && !thd->killed) + while (!di->thd.killed && !di->table && !thd->killed) { - pthread_cond_wait(&tmp->cond_client,&tmp->mutex); + pthread_cond_wait(&di->cond_client, &di->mutex); } - pthread_mutex_unlock(&tmp->mutex); + pthread_mutex_unlock(&di->mutex); thd->proc_info="got old table"; - if (tmp->thd.killed) + if (di->thd.killed) { - if (tmp->thd.net.report_error) + if (di->thd.net.report_error) { /* Copy the error message. Note that we don't treat fatal @@ -1823,31 +1845,34 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) main thread. Use of my_message will enable stored procedures continue handlers. */ - my_message(tmp->thd.net.last_errno, tmp->thd.net.last_error, + my_message(di->thd.net.last_errno, di->thd.net.last_error, MYF(0)); } - tmp->unlock(); + di->unlock(); goto end_create; } if (thd->killed) { - tmp->unlock(); + di->unlock(); goto end_create; } + pthread_mutex_lock(&LOCK_delayed_insert); + delayed_threads.append(di); + pthread_mutex_unlock(&LOCK_delayed_insert); } pthread_mutex_unlock(&LOCK_delayed_create); } - pthread_mutex_lock(&tmp->mutex); - table_list->table= tmp->get_local_table(thd); - pthread_mutex_unlock(&tmp->mutex); + pthread_mutex_lock(&di->mutex); + table_list->table= di->get_local_table(thd); + pthread_mutex_unlock(&di->mutex); if (table_list->table) { DBUG_ASSERT(thd->net.report_error == 0); - thd->di=tmp; + thd->di= di; } /* Unlock the delayed insert object after its last access. */ - tmp->unlock(); + di->unlock(); DBUG_RETURN(table_list->table == NULL); end_create: @@ -2077,26 +2102,26 @@ void kill_delayed_threads(void) VOID(pthread_mutex_lock(&LOCK_delayed_insert)); // For unlink from list I_List_iterator<Delayed_insert> it(delayed_threads); - Delayed_insert *tmp; - while ((tmp=it++)) + Delayed_insert *di; + while ((di= it++)) { - tmp->thd.killed= THD::KILL_CONNECTION; - if (tmp->thd.mysys_var) + di->thd.killed= THD::KILL_CONNECTION; + if (di->thd.mysys_var) { - pthread_mutex_lock(&tmp->thd.mysys_var->mutex); - if (tmp->thd.mysys_var->current_cond) + pthread_mutex_lock(&di->thd.mysys_var->mutex); + if (di->thd.mysys_var->current_cond) { /* We need the following test because the main mutex may be locked in handle_delayed_insert() */ - if (&tmp->mutex != tmp->thd.mysys_var->current_mutex) - pthread_mutex_lock(tmp->thd.mysys_var->current_mutex); - pthread_cond_broadcast(tmp->thd.mysys_var->current_cond); - if (&tmp->mutex != tmp->thd.mysys_var->current_mutex) - pthread_mutex_unlock(tmp->thd.mysys_var->current_mutex); + if (&di->mutex != di->thd.mysys_var->current_mutex) + pthread_mutex_lock(di->thd.mysys_var->current_mutex); + pthread_cond_broadcast(di->thd.mysys_var->current_cond); + if (&di->mutex != di->thd.mysys_var->current_mutex) + pthread_mutex_unlock(di->thd.mysys_var->current_mutex); } - pthread_mutex_unlock(&tmp->thd.mysys_var->mutex); + pthread_mutex_unlock(&di->thd.mysys_var->mutex); } } VOID(pthread_mutex_unlock(&LOCK_delayed_insert)); // For unlink from list @@ -2176,11 +2201,6 @@ pthread_handler_t handle_delayed_insert(void *arg) } di->table->copy_blobs=1; - /* One can now use this */ - pthread_mutex_lock(&LOCK_delayed_insert); - delayed_threads.append(di); - pthread_mutex_unlock(&LOCK_delayed_insert); - /* Tell client that the thread is initialized */ pthread_cond_signal(&di->cond_client); |