From 5f462f96266c193ea13bd2aa0a13c181c1d0919c Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jul 2007 14:42:06 +0400 Subject: Add a test case for Bug#27248 Triggers: error if insert affects temporary table. The bug itself is yet another manifestation of Bug 26141. mysql-test/r/trigger.result: Update results. mysql-test/t/trigger.test: Add a test case for Bug#27248 Triggers: error if insert affects temporary table --- mysql-test/r/trigger.result | 28 ++++++++++++++++++++++++++++ mysql-test/t/trigger.test | 23 +++++++++++++++++++++++ 2 files changed, 51 insertions(+) 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/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 -- cgit v1.2.1 From c0277a1192d0526ea76968196584e7d2b5a51203 Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jul 2007 16:22:05 +0400 Subject: A fix and a test case for Bug#26104 Bug on foreign key class constructor. Fix the typo in the constructor. Cover a semantic check that previously never worked with a test. mysql-test/r/create.result: Update results (Bug#26104) mysql-test/r/innodb.result: Update results. mysql-test/t/create.test: Add a test case for Bug#26104 Bug on foreign key class constructor mysql-test/t/innodb.test: Return a new error number (MySQL error instead of internal InnoDB error). sql/sql_class.h: A fix for Bug#26104 Bug on foreign key class constructor -- fix the typo in the constructor --- mysql-test/r/create.result | 16 ++++++++++++++++ mysql-test/r/innodb.result | 2 +- mysql-test/t/create.test | 19 +++++++++++++++++++ mysql-test/t/innodb.test | 2 +- sql/sql_class.h | 2 +- 5 files changed, 38 insertions(+), 3 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/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/sql/sql_class.h b/sql/sql_class.h index a5cbc21684f..1c52afb5bc5 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -450,7 +450,7 @@ public: Table_ident *table, List &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) {} -- cgit v1.2.1 From 6981af6ff53d63254284a4b6a5370c17075793bc Mon Sep 17 00:00:00 2001 From: unknown Date: Wed, 18 Jul 2007 17:09:03 +0400 Subject: Add a test case for Bug#22427 create table if not exists + stored function results in inconsistent behavior. The bug itself was fixed by the patch for bug 20662. mysql-test/r/sp-prelocking.result: Update results (Bug#22427) mysql-test/t/sp-prelocking.test: Add a test case for Bug#22427 create table if not exists + stored function results in inconsistent behavior --- mysql-test/r/sp-prelocking.result | 22 ++++++++++++++++++++++ mysql-test/t/sp-prelocking.test | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+) 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/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 -- cgit v1.2.1 From e81e55e78306643031e237c884c48f1d3d7b76c6 Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 19:28:00 +0400 Subject: A fix for Bug#29431 killing an insert delayed thread causes crash No test case, since the bug requires a stress case with 30 INSERT DELAYED threads and 1 killer thread to repeat. The patch is verified manually. Review fixes. The server that is running DELAYED inserts would deadlock itself or crash under high load if some of the delayed threads were KILLed in the meanwhile. The fix is to change internal lock acquisition order of delayed inserts subsystem and to ensure that Delayed_insert::table_list::db does not point to volatile memory in some cases. For details, please see a comment for sql_insert.cc. sql/sql_insert.cc: A fix for Bug#29431 killing an insert delayed thread causes crash 1) The deadlock was caused by different lock acquisition order between delayed_get_table and handle_delayed_insert. delayed_get_table would: - acquire LOCK_delayed_create - create a new Delayed_insert instance - acquire instance mutex (di->mutex) - "lock the instance in memory" by increasing di->locked_in_memory variable - start the delayed thread - release di->mutex - let the delayed thread open the delayed table - discover that the delayed thread was killed - try to unlock() the delayed insert instance in memory - in Delayed_insert::unlock() do * lock LOCK_delayed_insert * decrease locks_in_memory and discover it's 0 * attempt to lock di->mutex to broadcast di->cond condition <-- deadlock here Meanwhile, the delayed thread would * lock di->mutex * open the table * get killed * not notice that and attempt to lock LOCK_delayed_insert to register itself in the delayed insert list <-- deadlock here. Simply put, delayed_get_table used to lock LOCK_delayed_insert and then di->mutex, and handle_delayed_insert would lock di->mutex and then LOCK_delayed_insert. Fixed by moving registration in the list of delayed insert threads from handle_delayed_insert to delayed_get_table - so that now handle_delayed_insert doesn't need to acquire LOCK_delayed_insert mutex. 2) di->table_list.db was copied by-pointer from table_list.db of the first producer -- the one who initiated creation of the delayed insert thread. This producer might be long gone when the member is needed (handle_delayed_insert:open_ltable), e.g. by having been killed with KILL CONNECTION statement. Fixed by using a pointer to the consumer's deep copy of THD::db. 3) In find_handler, we shouldn't assume that Delayed_insert object already (or still) has a table opened all the time it is present in the delayed insert list. E.g. it's not the case when Delayed_insert decided to terminate, closed the table, but haven't yet unregistered from the list (see the end of handle_delayed_insert). --- sql/sql_insert.cc | 36 ++++++++++++++++++++++++++++-------- 1 file changed, 28 insertions(+), 8 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 73f8c5e4418..1a8cacd4f8e 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1705,8 +1705,8 @@ Delayed_insert *find_handler(THD *thd, TABLE_LIST *table_list) Delayed_insert *tmp; while ((tmp=it++)) { - if (!strcmp(tmp->thd.db,table_list->db) && - !strcmp(table_list->table_name,tmp->table->s->table_name)) + if (!strcmp(table_list->db, tmp->table_list.db) && + !strcmp(table_list->table_name, tmp->table_list.table_name)) { tmp->lock(); break; @@ -1739,7 +1739,27 @@ 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 @@ -1788,7 +1808,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) goto end_create; } tmp->table_list= *table_list; // Needed to open table + /* Replace volatile strings with local copies */ tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query; + tmp->table_list.db= tmp->thd.db; tmp->lock(); pthread_mutex_lock(&tmp->mutex); if ((error=pthread_create(&tmp->thd.real_id,&connection_attrib, @@ -1834,6 +1856,9 @@ bool delayed_get_table(THD *thd, TABLE_LIST *table_list) tmp->unlock(); goto end_create; } + pthread_mutex_lock(&LOCK_delayed_insert); + delayed_threads.append(tmp); + pthread_mutex_unlock(&LOCK_delayed_insert); } pthread_mutex_unlock(&LOCK_delayed_create); } @@ -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); -- cgit v1.2.1 From 62eb5f17945972c1c1f6a78c95440c71afc7d7bc Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 19:36:52 +0400 Subject: Rename all references to 'Delayed_insert' instances from 'tmp' to 'di' for consistency. --- sql/sql_insert.cc | 100 +++++++++++++++++++++++++++--------------------------- 1 file changed, 50 insertions(+), 50 deletions(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 1a8cacd4f8e..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 it(delayed_threads); - Delayed_insert *tmp; - while ((tmp=it++)) + Delayed_insert *di; + while ((di= it++)) { - if (!strcmp(table_list->db, tmp->table_list.db) && - !strcmp(table_list->table_name, tmp->table_list.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; } @@ -1766,14 +1766,14 @@ 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 @@ -1787,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(); @@ -1798,30 +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 + di->table_list= *table_list; // Needed to open table /* Replace volatile strings with local copies */ - tmp->table_list.alias= tmp->table_list.table_name= tmp->thd.query; - tmp->table_list.db= tmp->thd.db; - 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.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; @@ -1829,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 @@ -1845,34 +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(tmp); + 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: @@ -2102,26 +2102,26 @@ void kill_delayed_threads(void) VOID(pthread_mutex_lock(&LOCK_delayed_insert)); // For unlink from list I_List_iterator 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 -- cgit v1.2.1 From 93de616578d601d49dfee8927bdd539da94dc69f Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 19:56:07 +0400 Subject: A post-merge fix --- mysql-test/r/create.result | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index cdbb767dd9f..de25fb754e4 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -1516,6 +1516,22 @@ 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 CREATE TABLE t1 (a int, b int); insert into t1 values (1,1),(1,2); -- cgit v1.2.1 From 6c24dd7f0cdc3d996610c4cfc8181d25c5f580fe Mon Sep 17 00:00:00 2001 From: unknown Date: Thu, 19 Jul 2007 21:10:19 +0400 Subject: A follow-up fix for Bug#29431 "killing an insert delayed thread causes crash" in 5.1 sql/sql_insert.cc: Additional safety fix: do not assume we already have a share in get_local_table. --- sql/sql_insert.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 903300c0402..b362835412a 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -1961,7 +1961,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) my_ptrdiff_t adjust_ptrs; Field **field,**org_field, *found_next_number_field; TABLE *copy; - TABLE_SHARE *share= table->s; + TABLE_SHARE *share; uchar *bitmap; DBUG_ENTER("Delayed_insert::get_local_table"); @@ -1985,6 +1985,7 @@ TABLE *Delayed_insert::get_local_table(THD* client_thd) goto error; } } + share= table->s; /* Allocate memory for the TABLE object, the field pointers array, and -- cgit v1.2.1 From 7a99db0b7308f1636bbc7fafe36b478968497e50 Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 19:46:13 +0400 Subject: Remove obvious comments. --- sql/sql_base.cc | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) 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) { -- cgit v1.2.1 From 16711062954bd202973339ac73382b435d209d9d Mon Sep 17 00:00:00 2001 From: unknown Date: Fri, 20 Jul 2007 19:52:25 +0400 Subject: Fix the coding style. sql/sql_lex.cc: Fix the style. sql/sql_lex.h: Fix the style. --- sql/sql_lex.cc | 18 +++++++++--------- sql/sql_lex.h | 44 ++++++++++++++++++++++---------------------- 2 files changed, 31 insertions(+), 31 deletions(-) diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc index 9f69e7dee05..e493dc05047 100644 --- a/sql/sql_lex.cc +++ b/sql/sql_lex.cc @@ -124,7 +124,7 @@ Lex_input_stream::Lex_input_stream(THD *thd, m_tok_start_prev(NULL), m_buf(buffer), m_buf_length(length), - m_echo(true), + m_echo(TRUE), m_cpp_tok_start(NULL), m_cpp_tok_start_prev(NULL), m_cpp_tok_end(NULL), @@ -1200,7 +1200,7 @@ int MYSQLlex(void *arg, void *yythd) { lip->in_comment= DISCARD_COMMENT; /* Accept '/' '*' '!', but do not keep this marker. */ - lip->set_echo(false); + lip->set_echo(FALSE); lip->yySkip(); lip->yySkip(); lip->yySkip(); @@ -1233,7 +1233,7 @@ int MYSQLlex(void *arg, void *yythd) if (version <= MYSQL_VERSION_ID) { /* Expand the content of the special comment as real code */ - lip->set_echo(true); + lip->set_echo(TRUE); state=MY_LEX_START; break; } @@ -1241,7 +1241,7 @@ int MYSQLlex(void *arg, void *yythd) else { state=MY_LEX_START; - lip->set_echo(true); + lip->set_echo(TRUE); break; } } @@ -1261,7 +1261,7 @@ int MYSQLlex(void *arg, void *yythd) if (! lip->eof()) lip->yySkip(); // remove last '/' state = MY_LEX_START; // Try again - lip->set_echo(true); + lip->set_echo(TRUE); break; case MY_LEX_END_LONG_COMMENT: if ((lip->in_comment != NO_COMMENT) && lip->yyPeek() == '/') @@ -1272,7 +1272,7 @@ int MYSQLlex(void *arg, void *yythd) lip->set_echo(lip->in_comment == PRESERVE_COMMENT); lip->yySkipn(2); /* And start recording the tokens again */ - lip->set_echo(true); + lip->set_echo(TRUE); lip->in_comment=NO_COMMENT; state=MY_LEX_START; } @@ -1297,7 +1297,7 @@ int MYSQLlex(void *arg, void *yythd) lip->found_semicolon= lip->get_ptr(); thd->server_status|= SERVER_MORE_RESULTS_EXISTS; lip->next_state= MY_LEX_END; - lip->set_echo(true); + lip->set_echo(TRUE); return (END_OF_INPUT); } state= MY_LEX_CHAR; // Return ';' @@ -1309,9 +1309,9 @@ int MYSQLlex(void *arg, void *yythd) if (lip->eof()) { lip->yyUnget(); // Reject the last '\0' - lip->set_echo(false); + lip->set_echo(FALSE); lip->yySkip(); - lip->set_echo(true); + lip->set_echo(TRUE); lip->next_state=MY_LEX_END; // Mark for next loop return(END_OF_INPUT); } diff --git a/sql/sql_lex.h b/sql/sql_lex.h index 4ac59fbacde..9ac7f2835f0 100644 --- a/sql/sql_lex.h +++ b/sql/sql_lex.h @@ -1239,19 +1239,19 @@ public: } /** Get the raw query buffer. */ - const char* get_buf() + const char *get_buf() { return m_buf; } /** Get the pre-processed query buffer. */ - const char* get_cpp_buf() + const char *get_cpp_buf() { return m_cpp_buf; } /** Get the end of the raw query buffer. */ - const char* get_end_of_query() + const char *get_end_of_query() { return m_end_of_query; } @@ -1279,43 +1279,43 @@ public: } /** Get the token start position, in the raw buffer. */ - const char* get_tok_start() + const char *get_tok_start() { return m_tok_start; } /** Get the token start position, in the pre-processed buffer. */ - const char* get_cpp_tok_start() + const char *get_cpp_tok_start() { return m_cpp_tok_start; } /** Get the token end position, in the raw buffer. */ - const char* get_tok_end() + const char *get_tok_end() { return m_tok_end; } /** Get the token end position, in the pre-processed buffer. */ - const char* get_cpp_tok_end() + const char *get_cpp_tok_end() { return m_cpp_tok_end; } /** Get the previous token start position, in the raw buffer. */ - const char* get_tok_start_prev() + const char *get_tok_start_prev() { return m_tok_start_prev; } /** Get the current stream pointer, in the raw buffer. */ - const char* get_ptr() + const char *get_ptr() { return m_ptr; } /** Get the current stream pointer, in the pre-processed buffer. */ - const char* get_cpp_ptr() + const char *get_cpp_ptr() { return m_cpp_ptr; } @@ -1365,22 +1365,22 @@ public: private: /** Pointer to the current position in the raw input stream. */ - const char* m_ptr; + const char *m_ptr; /** Starting position of the last token parsed, in the raw buffer. */ - const char* m_tok_start; + const char *m_tok_start; /** Ending position of the previous token parsed, in the raw buffer. */ - const char* m_tok_end; + const char *m_tok_end; /** End of the query text in the input stream, in the raw buffer. */ - const char* m_end_of_query; + const char *m_end_of_query; /** Starting position of the previous token parsed, in the raw buffer. */ - const char* m_tok_start_prev; + const char *m_tok_start_prev; /** Begining of the query text in the input stream, in the raw buffer. */ - const char* m_buf; + const char *m_buf; /** Length of the raw buffer. */ uint m_buf_length; @@ -1389,28 +1389,28 @@ private: bool m_echo; /** Pre-processed buffer. */ - char* m_cpp_buf; + char *m_cpp_buf; /** Pointer to the current position in the pre-processed input stream. */ - char* m_cpp_ptr; + char *m_cpp_ptr; /** Starting position of the last token parsed, in the pre-processed buffer. */ - const char* m_cpp_tok_start; + const char *m_cpp_tok_start; /** Starting position of the previous token parsed, in the pre-procedded buffer. */ - const char* m_cpp_tok_start_prev; + const char *m_cpp_tok_start_prev; /** Ending position of the previous token parsed, in the pre-processed buffer. */ - const char* m_cpp_tok_end; + const char *m_cpp_tok_end; /** UTF8-body buffer created during parsing. */ char *m_body_utf8; @@ -1433,7 +1433,7 @@ public: Position of ';' in the stream, to delimit multiple queries. This delimiter is in the raw buffer. */ - const char* found_semicolon; + const char *found_semicolon; /** SQL_MODE = IGNORE_SPACE. */ bool ignore_space; -- cgit v1.2.1