diff options
author | unknown <dlenev@mysql.com> | 2006-03-29 14:55:04 +0400 |
---|---|---|
committer | unknown <dlenev@mysql.com> | 2006-03-29 14:55:04 +0400 |
commit | 1b458888549010439c591f0c5fff895b49c34dfd (patch) | |
tree | 1af94a5bd45eb1b1bdcb4c2628ca43fc83cde54c | |
parent | 53595c7020a0b00ead7fb35f923352cb5b30cd0a (diff) | |
parent | 1d166b17600e4db8a90ba3458db4bc743f155ef5 (diff) | |
download | mariadb-git-1b458888549010439c591f0c5fff895b49c34dfd.tar.gz |
Merge bk-internal.mysql.com:/home/bk/mysql-5.0-runtime
into mysql.com:/home/dlenev/mysql-5.0-bg17764
mysql-test/r/trigger.result:
Auto merged
mysql-test/t/trigger.test:
Auto merged
sql/sql_insert.cc:
Auto merged
-rw-r--r-- | mysql-test/r/trigger.result | 24 | ||||
-rw-r--r-- | mysql-test/t/trigger.test | 34 | ||||
-rw-r--r-- | sql/sql_insert.cc | 23 | ||||
-rw-r--r-- | sql/sql_load.cc | 5 |
4 files changed, 77 insertions, 9 deletions
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result index 009cde1b747..828db549b05 100644 --- a/mysql-test/r/trigger.result +++ b/mysql-test/r/trigger.result @@ -2,6 +2,7 @@ drop table if exists t1, t2, t3, t4; drop view if exists v1; drop database if exists mysqltest; drop function if exists f1; +drop function if exists f2; drop procedure if exists p1; create table t1 (i int); create trigger trg before insert on t1 for each row set @a:=1; @@ -928,3 +929,26 @@ create trigger t1_bi before insert on t1 for each row return 0; ERROR 42000: RETURN is only allowed in a FUNCTION insert into t1 values (1); drop table t1; +create table t1 (a varchar(64), b int); +create table t2 like t1; +create trigger t1_ai after insert on t1 for each row +set @a:= (select max(a) from t1); +insert into t1 (a) values +("Twas"),("brillig"),("and"),("the"),("slithy"),("toves"), +("Did"),("gyre"),("and"),("gimble"),("in"),("the"),("wabe"); +create trigger t2_ai after insert on t2 for each row +set @a:= (select max(a) from t2); +insert into t2 select * from t1; +load data infile '../std_data_ln/words.dat' into table t1 (a); +drop trigger t1_ai; +drop trigger t2_ai; +create function f1() returns int return (select max(b) from t1); +insert into t1 values +("All",f1()),("mimsy",f1()),("were",f1()),("the",f1()),("borogoves",f1()), +("And",f1()),("the",f1()),("mome", f1()),("raths",f1()),("outgrabe",f1()); +create function f2() returns int return (select max(b) from t2); +insert into t2 select a, f2() from t1; +load data infile '../std_data_ln/words.dat' into table t1 (a) set b:= f1(); +drop table t1; +drop function f1; +drop function f2; diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test index 05a52007eeb..c5925bbd9d5 100644 --- a/mysql-test/t/trigger.test +++ b/mysql-test/t/trigger.test @@ -7,6 +7,7 @@ drop table if exists t1, t2, t3, t4; drop view if exists v1; drop database if exists mysqltest; drop function if exists f1; +drop function if exists f2; drop procedure if exists p1; --enable_warnings @@ -1080,3 +1081,36 @@ create table t1 (i int); create trigger t1_bi before insert on t1 for each row return 0; insert into t1 values (1); drop table t1; + +# Test for bug #17764 "Trigger crashes MyISAM table" +# +# Table was reported as crashed when it was subject table of trigger invoked +# by insert statement which was executed with enabled bulk insert mode (which +# is actually set of optimizations enabled by handler::start_bulk_insert()) +# and this trigger also explicitly referenced it. +# The same problem arose when table to which bulk insert was done was also +# referenced in function called by insert statement. +create table t1 (a varchar(64), b int); +create table t2 like t1; +create trigger t1_ai after insert on t1 for each row + set @a:= (select max(a) from t1); +insert into t1 (a) values + ("Twas"),("brillig"),("and"),("the"),("slithy"),("toves"), + ("Did"),("gyre"),("and"),("gimble"),("in"),("the"),("wabe"); +create trigger t2_ai after insert on t2 for each row + set @a:= (select max(a) from t2); +insert into t2 select * from t1; +load data infile '../std_data_ln/words.dat' into table t1 (a); +drop trigger t1_ai; +drop trigger t2_ai; +# Test that the problem for functions is fixed as well +create function f1() returns int return (select max(b) from t1); +insert into t1 values + ("All",f1()),("mimsy",f1()),("were",f1()),("the",f1()),("borogoves",f1()), + ("And",f1()),("the",f1()),("mome", f1()),("raths",f1()),("outgrabe",f1()); +create function f2() returns int return (select max(b) from t2); +insert into t2 select a, f2() from t1; +load data infile '../std_data_ln/words.dat' into table t1 (a) set b:= f1(); +drop table t1; +drop function f1; +drop function f2; diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index b6ff0ecc216..ad9606acb83 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -405,11 +405,15 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, let's *try* to start bulk inserts. It won't necessary start them as values_list.elements should be greater than some - handler dependent - threshold. + We should not start bulk inserts if this statement uses + functions or invokes triggers since they may access + to the same table and therefore should not see its + inconsistent state created by this optimization. So we call start_bulk_insert to perform nesessary checks on values_list.elements, and - if nothing else - to initialize the code to make the call of end_bulk_insert() below safe. */ - if (lock_type != TL_WRITE_DELAYED) + if (lock_type != TL_WRITE_DELAYED && !thd->prelocked_mode) table->file->start_bulk_insert(values_list.elements); thd->no_trans_update= 0; @@ -535,7 +539,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list, else #endif { - if (table->file->end_bulk_insert() && !error) + if (!thd->prelocked_mode && table->file->end_bulk_insert() && !error) { table->file->print_error(my_errno,MYF(0)); error=1; @@ -2190,7 +2194,7 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) lex->current_select->options|= OPTION_BUFFER_RESULT; lex->current_select->join->select_options|= OPTION_BUFFER_RESULT; } - else + else if (!thd->prelocked_mode) { /* We must not yet prepare the result table if it is the same as one of the @@ -2198,6 +2202,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) indexes on the result table, which may be used during the select, if it is the same table (Bug #6034). Do the preparation after the select phase in select_insert::prepare2(). + We won't start bulk inserts at all if this statement uses functions or + should invoke triggers since they may access to the same table too. */ table->file->start_bulk_insert((ha_rows) 0); } @@ -2238,7 +2244,8 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u) int select_insert::prepare2(void) { DBUG_ENTER("select_insert::prepare2"); - if (thd->lex->current_select->options & OPTION_BUFFER_RESULT) + if (thd->lex->current_select->options & OPTION_BUFFER_RESULT && + !thd->prelocked_mode) table->file->start_bulk_insert((ha_rows) 0); DBUG_RETURN(0); } @@ -2341,7 +2348,8 @@ void select_insert::send_error(uint errcode,const char *err) */ DBUG_VOID_RETURN; } - table->file->end_bulk_insert(); + if (!thd->prelocked_mode) + table->file->end_bulk_insert(); /* If at least one row has been inserted/modified and will stay in the table (the table doesn't have transactions) (example: we got a duplicate key @@ -2376,7 +2384,7 @@ bool select_insert::send_eof() int error,error2; DBUG_ENTER("select_insert::send_eof"); - error=table->file->end_bulk_insert(); + error= (!thd->prelocked_mode) ? table->file->end_bulk_insert():0; table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY); /* @@ -2459,7 +2467,8 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) thd->cuted_fields=0; if (info.ignore || info.handle_duplicates != DUP_ERROR) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - table->file->start_bulk_insert((ha_rows) 0); + if (!thd->prelocked_mode) + table->file->start_bulk_insert((ha_rows) 0); thd->no_trans_update= 0; thd->abort_on_warning= (!info.ignore && (thd->variables.sql_mode & diff --git a/sql/sql_load.cc b/sql/sql_load.cc index cc724c102a4..0a667c887ef 100644 --- a/sql/sql_load.cc +++ b/sql/sql_load.cc @@ -356,7 +356,8 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, if (ignore || handle_duplicates == DUP_REPLACE) table->file->extra(HA_EXTRA_IGNORE_DUP_KEY); - table->file->start_bulk_insert((ha_rows) 0); + if (!thd->prelocked_mode) + table->file->start_bulk_insert((ha_rows) 0); table->copy_blobs=1; thd->no_trans_update= 0; @@ -373,7 +374,7 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list, error= read_sep_field(thd, info, table_list, fields_vars, set_fields, set_values, read_info, *enclosed, skip_lines, ignore); - if (table->file->end_bulk_insert() && !error) + if (!thd->prelocked_mode && table->file->end_bulk_insert() && !error) { table->file->print_error(my_errno, MYF(0)); error= 1; |