mirror of
https://github.com/MariaDB/server.git
synced 2025-01-29 18:20:07 +01:00
Merge dl145k.mysql.com:/data0/mkindahl/bkroot/mysql-5.1
into dl145k.mysql.com:/data0/mkindahl/bk/mysql-5.1-new-rpl
This commit is contained in:
commit
406d50db06
65 changed files with 3606 additions and 1542 deletions
|
@ -587,7 +587,7 @@ extern gptr _my_memdup(const byte *from,uint length,
|
|||
const char *sFile, uint uLine,myf MyFlag);
|
||||
extern my_string _my_strdup(const char *from, const char *sFile, uint uLine,
|
||||
myf MyFlag);
|
||||
extern char *_my_strndup(const byte *from, uint length,
|
||||
extern char *_my_strndup(const char *from, uint length,
|
||||
const char *sFile, uint uLine,
|
||||
myf MyFlag);
|
||||
|
||||
|
|
|
@ -49,3 +49,35 @@ show binlog events in 'master-bin.000001' from 102;
|
|||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events in 'master-bin.000002' from 102;
|
||||
|
||||
# Test of a too big SET INSERT_ID: see if the truncated value goes
|
||||
# into binlog (right), or the too big value (wrong); we look at the
|
||||
# binlog further down with SHOW BINLOG EVENTS.
|
||||
reset master;
|
||||
create table t1 (id tinyint auto_increment primary key);
|
||||
set insert_id=128;
|
||||
insert into t1 values(null);
|
||||
select * from t1;
|
||||
drop table t1;
|
||||
|
||||
# Test of binlogging of INSERT_ID with INSERT DELAYED
|
||||
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
||||
# First, avoid BUG#20627:
|
||||
set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
|
||||
# Verify that only one INSERT_ID event is binlogged.
|
||||
insert delayed into t1 values (207);
|
||||
|
||||
# We use sleeps between statements, that's the only way to get a
|
||||
# repeatable binlog in a normal test run and under Valgrind.
|
||||
# It may be that the "binlog missing rows" of BUG#20821 shows up
|
||||
# here.
|
||||
sleep 2;
|
||||
insert delayed into t1 values (null);
|
||||
sleep 2;
|
||||
insert delayed into t1 values (300);
|
||||
sleep 2; # time for the delayed queries to reach disk
|
||||
select * from t1;
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/
|
||||
show binlog events from 102;
|
||||
drop table t1;
|
||||
|
|
|
@ -29,7 +29,7 @@ insert into t1 values(1);
|
|||
insert into t2 select * from t1;
|
||||
commit;
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -43,7 +43,7 @@ insert into t2 select * from t1;
|
|||
# should say some changes to non-transact1onal tables couldn't be rolled back
|
||||
rollback;
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -59,7 +59,7 @@ insert into t2 select * from t1;
|
|||
rollback to savepoint my_savepoint;
|
||||
commit;
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -77,7 +77,7 @@ insert into t1 values(7);
|
|||
commit;
|
||||
select a from t1 order by a; # check that savepoints work :)
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -99,7 +99,7 @@ connection con2;
|
|||
# so SHOW BINLOG EVENTS may come before con1 does the loggin. To be sure that
|
||||
# logging has been done, we use a user lock.
|
||||
select get_lock("a",10);
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -111,7 +111,7 @@ reset master;
|
|||
insert into t1 values(9);
|
||||
insert into t2 select * from t1;
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -124,13 +124,13 @@ reset master;
|
|||
insert into t1 values(10); # first make t1 non-empty
|
||||
begin;
|
||||
insert into t2 select * from t1;
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
insert into t1 values(11);
|
||||
commit;
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -149,7 +149,7 @@ insert into t1 values(12);
|
|||
insert into t2 select * from t1;
|
||||
commit;
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -162,7 +162,7 @@ insert into t1 values(13);
|
|||
insert into t2 select * from t1;
|
||||
rollback;
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -178,7 +178,7 @@ insert into t2 select * from t1;
|
|||
rollback to savepoint my_savepoint;
|
||||
commit;
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -196,7 +196,7 @@ insert into t1 values(18);
|
|||
commit;
|
||||
select a from t1 order by a; # check that savepoints work :)
|
||||
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
@ -257,7 +257,7 @@ insert into t2 values (3);
|
|||
disconnect con2;
|
||||
connection con3;
|
||||
select get_lock("lock1",60);
|
||||
--replace_column 5 #
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
do release_lock("lock1");
|
||||
|
@ -324,6 +324,7 @@ CREATE TEMPORARY TABLE IF NOT EXISTS t2 (primary key (a)) engine=innodb select *
|
|||
ROLLBACK;
|
||||
SELECT * from t2;
|
||||
DROP TABLE t1,t2;
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/ /\/\* xid=.* \*\//\/* xid= *\//
|
||||
show binlog events from 102;
|
||||
|
||||
|
|
|
@ -104,9 +104,47 @@ select * from t1;
|
|||
|
||||
sync_slave_with_master;
|
||||
select * from t1;
|
||||
|
||||
# Test for BUG#20524 "auto_increment_* not observed when inserting
|
||||
# a too large value". When an autogenerated value was bigger than the
|
||||
# maximum possible value of the field, it was truncated to that max
|
||||
# possible value, without being "rounded down" to still honour
|
||||
# auto_increment_* variables.
|
||||
|
||||
connection master;
|
||||
drop table t1;
|
||||
create table t1 (a tinyint not null auto_increment primary key) engine=myisam;
|
||||
insert into t1 values(103);
|
||||
set auto_increment_increment=11;
|
||||
set auto_increment_offset=4;
|
||||
insert into t1 values(null);
|
||||
insert into t1 values(null);
|
||||
--error 1062
|
||||
insert into t1 values(null);
|
||||
select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t1 order by a;
|
||||
|
||||
# same but with a larger value
|
||||
create table t2 (a tinyint unsigned not null auto_increment primary key) engine=myisam;
|
||||
set auto_increment_increment=10;
|
||||
set auto_increment_offset=1;
|
||||
set insert_id=1000;
|
||||
insert into t2 values(null);
|
||||
select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t2 order by a;
|
||||
|
||||
# An offset so big that even first value does not fit
|
||||
create table t3 like t1;
|
||||
set auto_increment_increment=1000;
|
||||
set auto_increment_offset=700;
|
||||
insert into t3 values(null);
|
||||
select * from t3 order by a;
|
||||
sync_slave_with_master;
|
||||
select * from t1 order by a;
|
||||
select * from t2 order by a;
|
||||
select * from t3 order by a;
|
||||
|
||||
connection master;
|
||||
|
||||
drop table t1;
|
||||
drop table t1,t2,t3;
|
||||
|
||||
# End cleanup
|
||||
sync_slave_with_master;
|
||||
|
|
|
@ -144,6 +144,23 @@ insert into t1 (last_id) values (bug15728());
|
|||
# This should be exactly one greater than in the previous call.
|
||||
select last_insert_id();
|
||||
|
||||
# BUG#20339 - stored procedure using LAST_INSERT_ID() does not
|
||||
# replicate statement-based
|
||||
--disable_warnings
|
||||
drop procedure if exists foo;
|
||||
--enable_warnings
|
||||
delimiter |;
|
||||
create procedure foo()
|
||||
begin
|
||||
declare res int;
|
||||
insert into t2 (last_id) values (bug15728());
|
||||
insert into t1 (last_id) values (bug15728());
|
||||
end|
|
||||
delimiter ;|
|
||||
call foo();
|
||||
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
save_master_pos;
|
||||
connection slave;
|
||||
sync_with_master;
|
||||
|
@ -153,8 +170,107 @@ connection master;
|
|||
|
||||
drop function bug15728;
|
||||
drop function bug15728_insert;
|
||||
drop table t1, t2;
|
||||
drop table t1;
|
||||
drop procedure foo;
|
||||
|
||||
# test of BUG#20188 REPLACE or ON DUPLICATE KEY UPDATE in
|
||||
# auto_increment breaks binlog
|
||||
|
||||
create table t1 (n int primary key auto_increment not null,
|
||||
b int, unique(b));
|
||||
|
||||
# First, test that we do not call restore_auto_increment() too early
|
||||
# in write_record():
|
||||
set sql_log_bin=0;
|
||||
insert into t1 values(null,100);
|
||||
replace into t1 values(null,50),(null,100),(null,150);
|
||||
select * from t1 order by n;
|
||||
truncate table t1;
|
||||
set sql_log_bin=1;
|
||||
|
||||
insert into t1 values(null,100);
|
||||
select * from t1 order by n;
|
||||
sync_slave_with_master;
|
||||
# make slave's table autoinc counter bigger
|
||||
insert into t1 values(null,200),(null,300);
|
||||
delete from t1 where b <> 100;
|
||||
# check that slave's table content is identical to master
|
||||
select * from t1 order by n;
|
||||
# only the auto_inc counter differs.
|
||||
|
||||
connection master;
|
||||
replace into t1 values(null,100),(null,350);
|
||||
select * from t1 order by n;
|
||||
sync_slave_with_master;
|
||||
select * from t1 order by n;
|
||||
|
||||
# Same test as for REPLACE, but for ON DUPLICATE KEY UPDATE
|
||||
|
||||
# We first check that if we update a row using a value larger than the
|
||||
# table's counter, the counter for next row is bigger than the
|
||||
# after-value of the updated row.
|
||||
connection master;
|
||||
insert into t1 values (NULL,400),(3,500),(NULL,600) on duplicate key UPDATE n=1000;
|
||||
select * from t1 order by n;
|
||||
sync_slave_with_master;
|
||||
select * from t1 order by n;
|
||||
|
||||
# and now test for the bug:
|
||||
connection master;
|
||||
drop table t1;
|
||||
create table t1 (n int primary key auto_increment not null,
|
||||
b int, unique(b));
|
||||
insert into t1 values(null,100);
|
||||
select * from t1 order by n;
|
||||
sync_slave_with_master;
|
||||
insert into t1 values(null,200),(null,300);
|
||||
delete from t1 where b <> 100;
|
||||
select * from t1 order by n;
|
||||
|
||||
connection master;
|
||||
insert into t1 values(null,100),(null,350) on duplicate key update n=2;
|
||||
select * from t1 order by n;
|
||||
sync_slave_with_master;
|
||||
select * from t1 order by n;
|
||||
|
||||
connection master;
|
||||
drop table t1;
|
||||
|
||||
# End of 5.0 tests
|
||||
|
||||
# Test for BUG#20341 "stored function inserting into one
|
||||
# auto_increment puts bad data in slave"
|
||||
|
||||
truncate table t2;
|
||||
create table t1 (id tinyint primary key); # no auto_increment
|
||||
|
||||
delimiter |;
|
||||
create function insid() returns int
|
||||
begin
|
||||
insert into t2 (last_id) values (0);
|
||||
return 0;
|
||||
end|
|
||||
delimiter ;|
|
||||
set sql_log_bin=0;
|
||||
insert into t2 (id) values(1),(2),(3);
|
||||
delete from t2;
|
||||
set sql_log_bin=1;
|
||||
#inside SELECT, then inside INSERT
|
||||
select insid();
|
||||
set sql_log_bin=0;
|
||||
insert into t2 (id) values(5),(6),(7);
|
||||
delete from t2 where id>=5;
|
||||
set sql_log_bin=1;
|
||||
insert into t1 select insid();
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
|
||||
sync_slave_with_master;
|
||||
select * from t1;
|
||||
select * from t2;
|
||||
|
||||
connection master;
|
||||
drop table t1, t2;
|
||||
drop function insid;
|
||||
|
||||
sync_slave_with_master;
|
||||
|
|
|
@ -20,8 +20,11 @@ connection slave;
|
|||
reset master;
|
||||
connection master;
|
||||
|
||||
select last_insert_id();
|
||||
create table t1(a int not null auto_increment, b int, primary key(a) );
|
||||
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
|
||||
# verify that LAST_INSERT_ID() is set by LOAD DATA INFILE
|
||||
select last_insert_id();
|
||||
|
||||
create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60));
|
||||
load data infile '../std_data_ln/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines;
|
||||
|
|
|
@ -37,6 +37,23 @@ sub collect_test_cases ($) {
|
|||
|
||||
opendir(TESTDIR, $testdir) or mtr_error("Can't open dir \"$testdir\": $!");
|
||||
|
||||
# ----------------------------------------------------------------------
|
||||
# Disable some tests listed in disabled.def
|
||||
# ----------------------------------------------------------------------
|
||||
my %disabled;
|
||||
if ( open(DISABLED, "$testdir/disabled.def" ) )
|
||||
{
|
||||
while ( <DISABLED> )
|
||||
{
|
||||
chomp;
|
||||
if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
|
||||
{
|
||||
$disabled{$1}= $2;
|
||||
}
|
||||
}
|
||||
close DISABLED;
|
||||
}
|
||||
|
||||
if ( @::opt_cases )
|
||||
{
|
||||
foreach my $tname ( @::opt_cases ) { # Run in specified order, no sort
|
||||
|
@ -100,30 +117,13 @@ sub collect_test_cases ($) {
|
|||
}
|
||||
}
|
||||
|
||||
collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,{},
|
||||
collect_one_test_case($testdir,$resdir,$tname,$elem,$cases,\%disabled,
|
||||
$component_id);
|
||||
}
|
||||
closedir TESTDIR;
|
||||
}
|
||||
else
|
||||
{
|
||||
# ----------------------------------------------------------------------
|
||||
# Disable some tests listed in disabled.def
|
||||
# ----------------------------------------------------------------------
|
||||
my %disabled;
|
||||
if ( ! $::opt_ignore_disabled_def and open(DISABLED, "$testdir/disabled.def" ) )
|
||||
{
|
||||
while ( <DISABLED> )
|
||||
{
|
||||
chomp;
|
||||
if ( /^\s*(\S+)\s*:\s*(.*?)\s*$/ )
|
||||
{
|
||||
$disabled{$1}= $2;
|
||||
}
|
||||
}
|
||||
close DISABLED;
|
||||
}
|
||||
|
||||
foreach my $elem ( sort readdir(TESTDIR) ) {
|
||||
my $component_id= undef;
|
||||
my $tname= undef;
|
||||
|
@ -414,20 +414,35 @@ sub collect_one_test_case($$$$$$$) {
|
|||
}
|
||||
|
||||
# FIXME why this late?
|
||||
my $marked_as_disabled= 0;
|
||||
if ( $disabled->{$tname} )
|
||||
{
|
||||
$tinfo->{'skip'}= 1;
|
||||
$tinfo->{'disable'}= 1; # Sub type of 'skip'
|
||||
$tinfo->{'comment'}= $disabled->{$tname} if $disabled->{$tname};
|
||||
$marked_as_disabled= 1;
|
||||
$tinfo->{'comment'}= $disabled->{$tname};
|
||||
}
|
||||
|
||||
if ( -f $disabled_file )
|
||||
{
|
||||
$tinfo->{'skip'}= 1;
|
||||
$tinfo->{'disable'}= 1; # Sub type of 'skip'
|
||||
$marked_as_disabled= 1;
|
||||
$tinfo->{'comment'}= mtr_fromfile($disabled_file);
|
||||
}
|
||||
|
||||
# If test was marked as disabled, either opt_enable_disabled is off and then
|
||||
# we skip this test, or it is on and then we run this test but warn
|
||||
|
||||
if ( $marked_as_disabled )
|
||||
{
|
||||
if ( $::opt_enable_disabled )
|
||||
{
|
||||
$tinfo->{'dont_skip_though_disabled'}= 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
$tinfo->{'skip'}= 1;
|
||||
$tinfo->{'disable'}= 1; # Sub type of 'skip'
|
||||
}
|
||||
}
|
||||
|
||||
if ( $component_id eq 'im' )
|
||||
{
|
||||
if ( $::glob_use_embedded_server )
|
||||
|
|
|
@ -10,6 +10,7 @@ sub mtr_report_test_name($);
|
|||
sub mtr_report_test_passed($);
|
||||
sub mtr_report_test_failed($);
|
||||
sub mtr_report_test_skipped($);
|
||||
sub mtr_report_test_not_skipped_though_disabled($);
|
||||
|
||||
sub mtr_show_failed_diff ($);
|
||||
sub mtr_report_stats ($);
|
||||
|
@ -100,6 +101,23 @@ sub mtr_report_test_skipped ($) {
|
|||
}
|
||||
}
|
||||
|
||||
sub mtr_report_tests_not_skipped_though_disabled ($) {
|
||||
my $tests= shift;
|
||||
|
||||
if ( $::opt_enable_disabled )
|
||||
{
|
||||
my @disabled_tests= grep {$_->{'dont_skip_though_disabled'}} @$tests;
|
||||
if ( @disabled_tests )
|
||||
{
|
||||
print "\nTest(s) which will be run though they are marked as disabled:\n";
|
||||
foreach my $tinfo ( sort {$a->{'name'} cmp $b->{'name'}} @disabled_tests )
|
||||
{
|
||||
printf " %-20s : %s\n", $tinfo->{'name'}, $tinfo->{'comment'};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
sub mtr_report_test_passed ($) {
|
||||
my $tinfo= shift;
|
||||
|
||||
|
|
|
@ -216,6 +216,7 @@ our $opt_extern;
|
|||
our $opt_fast;
|
||||
our $opt_force;
|
||||
our $opt_reorder;
|
||||
our $opt_enable_disabled;
|
||||
|
||||
our $opt_gcov;
|
||||
our $opt_gcov_err;
|
||||
|
@ -290,7 +291,7 @@ our $opt_user_test;
|
|||
our $opt_valgrind= 0;
|
||||
our $opt_valgrind_mysqld= 0;
|
||||
our $opt_valgrind_mysqltest= 0;
|
||||
our $default_valgrind_options= "-v --show-reachable=yes";
|
||||
our $default_valgrind_options= "--show-reachable=yes";
|
||||
our $opt_valgrind_options;
|
||||
our $opt_valgrind_path;
|
||||
|
||||
|
@ -665,6 +666,7 @@ sub command_line_setup () {
|
|||
'netware' => \$opt_netware,
|
||||
'old-master' => \$opt_old_master,
|
||||
'reorder' => \$opt_reorder,
|
||||
'enable-disabled' => \$opt_enable_disabled,
|
||||
'script-debug' => \$opt_script_debug,
|
||||
'sleep=i' => \$opt_sleep,
|
||||
'socket=s' => \$opt_socket,
|
||||
|
@ -1799,12 +1801,12 @@ sub run_suite () {
|
|||
|
||||
mtr_print_thick_line();
|
||||
|
||||
mtr_report("Finding Tests in the '$suite' suite");
|
||||
|
||||
mtr_timer_start($glob_timers,"suite", 60 * $opt_suite_timeout);
|
||||
|
||||
mtr_report("Starting Tests in the '$suite' suite");
|
||||
|
||||
mtr_report_tests_not_skipped_though_disabled($tests);
|
||||
|
||||
mtr_print_header();
|
||||
|
||||
foreach my $tinfo ( @$tests )
|
||||
|
@ -3278,9 +3280,16 @@ sub run_check_testcase ($) {
|
|||
}
|
||||
|
||||
|
||||
sub generate_cmdline_mysqldump ($) {
|
||||
my($info) = @_;
|
||||
return
|
||||
"$exe_mysqldump --no-defaults -uroot " .
|
||||
"--port=$info->[0]->{'path_myport'} " .
|
||||
"--socket=$info->[0]->{'path_mysock'} --password=";
|
||||
}
|
||||
|
||||
sub run_mysqltest ($) {
|
||||
my $tinfo= shift;
|
||||
|
||||
my $cmdline_mysqlcheck= "$exe_mysqlcheck --no-defaults -uroot " .
|
||||
"--port=$master->[0]->{'path_myport'} " .
|
||||
"--socket=$master->[0]->{'path_mysock'} --password=";
|
||||
|
@ -3290,17 +3299,15 @@ sub run_mysqltest ($) {
|
|||
" --debug=d:t:A,$opt_vardir_trace/log/mysqlcheck.trace";
|
||||
}
|
||||
|
||||
my $cmdline_mysqldump= "$exe_mysqldump --no-defaults -uroot " .
|
||||
"--port=$master->[0]->{'path_myport'} " .
|
||||
"--socket=$master->[0]->{'path_mysock'} --password=";
|
||||
|
||||
my $cmdline_mysqldumpslave= "$exe_mysqldump --no-defaults -uroot " .
|
||||
"--socket=$slave->[0]->{'path_mysock'} --password=";
|
||||
my $cmdline_mysqldump= generate_cmdline_mysqldump $master;
|
||||
my $cmdline_mysqldumpslave= generate_cmdline_mysqldump $slave;
|
||||
|
||||
if ( $opt_debug )
|
||||
{
|
||||
$cmdline_mysqldump .=
|
||||
" --debug=d:t:A,$opt_vardir_trace/log/mysqldump.trace";
|
||||
" --debug=d:t:A,$opt_vardir_trace/log/mysqldump-master.trace";
|
||||
$cmdline_mysqldumpslave .=
|
||||
" --debug=d:t:A,$opt_vardir_trace/log/mysqldump-slave.trace";
|
||||
}
|
||||
|
||||
my $cmdline_mysqlslap;
|
||||
|
@ -3357,6 +3364,12 @@ sub run_mysqltest ($) {
|
|||
"--port=$master->[0]->{'path_myport'} " .
|
||||
"--socket=$master->[0]->{'path_mysock'}";
|
||||
|
||||
if ( $opt_debug )
|
||||
{
|
||||
$cmdline_mysql_client_test .=
|
||||
" --debug=d:t:A,$opt_vardir_trace/log/mysql_client_test.trace";
|
||||
}
|
||||
|
||||
if ( $glob_use_embedded_server )
|
||||
{
|
||||
$cmdline_mysql_client_test.=
|
||||
|
|
|
@ -153,7 +153,7 @@ insert into t1 set i = null;
|
|||
ERROR 23000: Duplicate entry '255' for key 'PRIMARY'
|
||||
select last_insert_id();
|
||||
last_insert_id()
|
||||
0
|
||||
255
|
||||
drop table t1;
|
||||
create table t1 (i tinyint unsigned not null auto_increment, key (i));
|
||||
insert into t1 set i = 254;
|
||||
|
@ -181,7 +181,7 @@ insert into t1 values (NULL, 10);
|
|||
ERROR 23000: Duplicate entry '10' for key 'b'
|
||||
select last_insert_id();
|
||||
last_insert_id()
|
||||
0
|
||||
2
|
||||
drop table t1;
|
||||
create table t1(a int auto_increment,b int null,primary key(a));
|
||||
SET SQL_MODE=NO_AUTO_VALUE_ON_ZERO;
|
||||
|
@ -446,3 +446,57 @@ INSERT INTO t1 VALUES(1, 1);
|
|||
ALTER TABLE t1 CHANGE t1 t1 INT(10) auto_increment;
|
||||
ERROR 23000: ALTER TABLE causes auto_increment resequencing, resulting in duplicate entry '1' for key 'PRIMARY'
|
||||
DROP TABLE t1;
|
||||
CREATE TABLE `t2` (
|
||||
`k` int(11) NOT NULL auto_increment,
|
||||
`a` int(11) default NULL,
|
||||
`c` int(11) default NULL,
|
||||
PRIMARY KEY (`k`),
|
||||
UNIQUE KEY `idx_1` (`a`)
|
||||
) ENGINE=InnoDB;
|
||||
insert into t2 ( a ) values ( 6 ) on duplicate key update c =
|
||||
ifnull( c,
|
||||
0 ) + 1;
|
||||
insert into t2 ( a ) values ( 7 ) on duplicate key update c =
|
||||
ifnull( c,
|
||||
0 ) + 1;
|
||||
select last_insert_id();
|
||||
last_insert_id()
|
||||
2
|
||||
select * from t2;
|
||||
k a c
|
||||
1 6 NULL
|
||||
2 7 NULL
|
||||
insert into t2 ( a ) values ( 6 ) on duplicate key update c =
|
||||
ifnull( c,
|
||||
0 ) + 1;
|
||||
select last_insert_id();
|
||||
last_insert_id()
|
||||
1
|
||||
select * from t2;
|
||||
k a c
|
||||
1 6 1
|
||||
2 7 NULL
|
||||
insert ignore into t2 values (null,6,1),(10,8,1);
|
||||
select last_insert_id();
|
||||
last_insert_id()
|
||||
1
|
||||
insert ignore into t2 values (null,6,1),(null,8,1),(null,15,1),(null,20,1);
|
||||
select last_insert_id();
|
||||
last_insert_id()
|
||||
11
|
||||
select * from t2;
|
||||
k a c
|
||||
1 6 1
|
||||
2 7 NULL
|
||||
10 8 1
|
||||
11 15 1
|
||||
12 20 1
|
||||
drop table t2;
|
||||
create table t1 (a int primary key auto_increment, b int, c int, d timestamp default current_timestamp, unique(b),unique(c));
|
||||
insert into t1 values(null,1,1,now());
|
||||
insert into t1 values(null,0,0,null);
|
||||
replace into t1 values(null,1,0,null);
|
||||
select last_insert_id();
|
||||
last_insert_id()
|
||||
3
|
||||
drop table t1;
|
||||
|
|
|
@ -235,3 +235,37 @@ master-bin.000001 # Rotate 1 # master-bin.000002;pos=4
|
|||
show binlog events in 'master-bin.000002' from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000002 # Query 1 # use `test`; drop table t1
|
||||
reset master;
|
||||
create table t1 (id tinyint auto_increment primary key);
|
||||
set insert_id=128;
|
||||
insert into t1 values(null);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'id' at row 1
|
||||
select * from t1;
|
||||
id
|
||||
127
|
||||
drop table t1;
|
||||
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
||||
set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
|
||||
insert delayed into t1 values (207);
|
||||
insert delayed into t1 values (null);
|
||||
insert delayed into t1 values (300);
|
||||
select * from t1;
|
||||
a
|
||||
207
|
||||
208
|
||||
300
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; drop table t1
|
||||
master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
drop table t1;
|
||||
|
|
|
@ -8,12 +8,12 @@ insert into t2 select * from t1;
|
|||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 209 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 243 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 282 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 316 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -25,12 +25,12 @@ Warnings:
|
|||
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 209 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 243 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 282 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 316 Query 1 # use `test`; ROLLBACK
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; ROLLBACK
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -45,16 +45,16 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
|||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 209 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 243 Query 1 # use `test`; savepoint my_savepoint
|
||||
master-bin.000001 328 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 367 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 401 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 440 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 479 Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 576 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; savepoint my_savepoint
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -74,18 +74,18 @@ a
|
|||
7
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 209 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 243 Query 1 # use `test`; savepoint my_savepoint
|
||||
master-bin.000001 328 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 367 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 401 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 440 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 479 Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 576 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 615 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 649 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; savepoint my_savepoint
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -100,12 +100,12 @@ get_lock("a",10)
|
|||
1
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 209 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 243 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 282 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 316 Query 1 # use `test`; ROLLBACK
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; ROLLBACK
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -113,11 +113,11 @@ insert into t1 values(9);
|
|||
insert into t2 select * from t1;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 141 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 175 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 202 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 241 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -126,24 +126,24 @@ begin;
|
|||
insert into t2 select * from t1;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 141 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 175 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 202 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 241 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
insert into t1 values(11);
|
||||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 141 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 175 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 202 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 241 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 275 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 343 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 382 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 416 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
alter table t2 engine=INNODB;
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
|
@ -154,12 +154,12 @@ insert into t2 select * from t1;
|
|||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 209 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 243 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 282 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 316 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -181,10 +181,10 @@ rollback to savepoint my_savepoint;
|
|||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 209 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 243 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -202,12 +202,12 @@ a
|
|||
18
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 209 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 243 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 282 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 316 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
alter table t2 engine=MyISAM;
|
||||
|
@ -254,28 +254,28 @@ get_lock("lock1",60)
|
|||
1
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 209 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 243 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 282 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 316 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 343 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 382 Delete_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 421 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 448 Query 1 # use `test`; alter table t2 engine=MyISAM
|
||||
master-bin.000001 539 Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 578 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 612 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 639 Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 678 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 712 Query 1 # use `test`; drop table t1,t2
|
||||
master-bin.000001 791 Query 1 # use `test`; create table t0 (n int)
|
||||
master-bin.000001 877 Table_map 1 # table_id: # (test.t0)
|
||||
master-bin.000001 916 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 950 Table_map 1 # table_id: # (test.t0)
|
||||
master-bin.000001 989 Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 1023 Query 1 # use `test`; create table t2 (n int) engine=innodb
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Delete_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; alter table t2 engine=MyISAM
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; drop table t1,t2
|
||||
master-bin.000001 # Query 1 # use `test`; create table t0 (n int)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t0)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t0)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; create table t2 (n int) engine=innodb
|
||||
do release_lock("lock1");
|
||||
drop table t0,t2;
|
||||
set autocommit=0;
|
||||
|
@ -357,83 +357,55 @@ a b
|
|||
DROP TABLE t1,t2;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Table_map 1 142 table_id: # (test.t1)
|
||||
master-bin.000001 142 Write_rows 1 189 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 189 Query 1 257 use `test`; BEGIN
|
||||
master-bin.000001 257 Query 1 182 use `test`; CREATE TABLE `t2` (
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL DEFAULT '0',
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=InnoDB
|
||||
master-bin.000001 439 Table_map 1 222 table_id: # (test.t2)
|
||||
master-bin.000001 479 Write_rows 1 260 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 517 Xid 1 544 COMMIT /* xid= */
|
||||
master-bin.000001 544 Query 1 630 use `test`; DROP TABLE if exists t2
|
||||
master-bin.000001 630 Table_map 1 670 table_id: # (test.t1)
|
||||
master-bin.000001 670 Write_rows 1 708 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 708 Query 1 776 use `test`; BEGIN
|
||||
master-bin.000001 776 Query 1 192 use `test`; CREATE TEMPORARY TABLE `t2` (
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE if exists t2
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE IF EXISTS t2
|
||||
master-bin.000001 # Query 1 # use `test`; CREATE TABLE t2 (a int, b int, primary key (a)) engine=innodb
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL DEFAULT '0',
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=InnoDB
|
||||
master-bin.000001 968 Query 1 1039 use `test`; ROLLBACK
|
||||
master-bin.000001 1039 Query 1 1125 use `test`; DROP TABLE IF EXISTS t2
|
||||
master-bin.000001 1125 Query 1 1249 use `test`; CREATE TABLE t2 (a int, b int, primary key (a)) engine=innodb
|
||||
master-bin.000001 1249 Table_map 1 1289 table_id: # (test.t1)
|
||||
master-bin.000001 1289 Write_rows 1 1327 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 1327 Query 1 1395 use `test`; BEGIN
|
||||
master-bin.000001 1395 Query 1 182 use `test`; CREATE TABLE `t2` (
|
||||
`a` int(11) NOT NULL DEFAULT '0',
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=InnoDB
|
||||
master-bin.000001 1577 Table_map 1 222 table_id: # (test.t2)
|
||||
master-bin.000001 1617 Write_rows 1 260 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 1655 Xid 1 1682 COMMIT /* xid= */
|
||||
master-bin.000001 1682 Query 1 80 use `test`; TRUNCATE table t2
|
||||
master-bin.000001 1762 Xid 1 1789 COMMIT /* xid= */
|
||||
master-bin.000001 1789 Table_map 1 1829 table_id: # (test.t1)
|
||||
master-bin.000001 1829 Write_rows 1 1867 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 1867 Query 1 1935 use `test`; BEGIN
|
||||
master-bin.000001 1935 Table_map 1 40 table_id: # (test.t2)
|
||||
master-bin.000001 1975 Write_rows 1 78 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 2013 Xid 1 2040 COMMIT /* xid= */
|
||||
master-bin.000001 2040 Query 1 2116 use `test`; DROP TABLE t2
|
||||
master-bin.000001 2116 Table_map 1 2156 table_id: # (test.t1)
|
||||
master-bin.000001 2156 Write_rows 1 2194 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 2194 Table_map 1 2234 table_id: # (test.t1)
|
||||
master-bin.000001 2234 Write_rows 1 2272 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 2272 Table_map 1 2312 table_id: # (test.t1)
|
||||
master-bin.000001 2312 Write_rows 1 2350 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 2350 Query 1 2418 use `test`; BEGIN
|
||||
master-bin.000001 2418 Query 1 192 use `test`; CREATE TEMPORARY TABLE `t2` (
|
||||
`a` int(11) NOT NULL DEFAULT '0',
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=InnoDB
|
||||
master-bin.000001 2610 Xid 1 2637 COMMIT /* xid= */
|
||||
master-bin.000001 2637 Table_map 1 2677 table_id: # (test.t1)
|
||||
master-bin.000001 2677 Write_rows 1 2715 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 2715 Query 1 2783 use `test`; BEGIN
|
||||
master-bin.000001 2783 Query 1 192 use `test`; CREATE TEMPORARY TABLE `t2` (
|
||||
`a` int(11) NOT NULL DEFAULT '0',
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=InnoDB
|
||||
master-bin.000001 2975 Query 1 3046 use `test`; ROLLBACK
|
||||
master-bin.000001 3046 Query 1 80 use `test`; TRUNCATE table t2
|
||||
master-bin.000001 3126 Xid 1 3153 COMMIT /* xid= */
|
||||
master-bin.000001 3153 Table_map 1 3193 table_id: # (test.t1)
|
||||
master-bin.000001 3193 Write_rows 1 3231 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 3231 Query 1 3299 use `test`; BEGIN
|
||||
master-bin.000001 3299 Query 1 192 use `test`; CREATE TEMPORARY TABLE `t2` (
|
||||
`a` int(11) NOT NULL DEFAULT '0',
|
||||
`b` int(11) DEFAULT NULL,
|
||||
PRIMARY KEY (`a`)
|
||||
) ENGINE=InnoDB
|
||||
master-bin.000001 3491 Xid 1 3518 COMMIT /* xid= */
|
||||
master-bin.000001 3518 Query 1 3622 use `test`; DROP TABLE `t1` /* generated by server */
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; TRUNCATE table t2
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE t2
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; TRUNCATE table t2
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Table_map 1 # table_id: # (test.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE `t1` /* generated by server */
|
||||
reset master;
|
||||
create table t1 (a int) engine=innodb;
|
||||
create table t2 (a int) engine=myisam;
|
||||
|
|
|
@ -145,3 +145,35 @@ master-bin.000001 # Rotate 1 # master-bin.000002;pos=4
|
|||
show binlog events in 'master-bin.000002' from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000002 # Query 1 # use `test`; drop table t1
|
||||
reset master;
|
||||
create table t1 (id tinyint auto_increment primary key);
|
||||
set insert_id=128;
|
||||
insert into t1 values(null);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'id' at row 1
|
||||
select * from t1;
|
||||
id
|
||||
127
|
||||
drop table t1;
|
||||
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
|
||||
set @@session.auto_increment_increment=1, @@session.auto_increment_offset=1;
|
||||
insert delayed into t1 values (207);
|
||||
insert delayed into t1 values (null);
|
||||
insert delayed into t1 values (300);
|
||||
select * from t1;
|
||||
a
|
||||
207
|
||||
208
|
||||
300
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query 1 # use `test`; create table t1 (id tinyint auto_increment primary key)
|
||||
master-bin.000001 # Intvar 1 # INSERT_ID=127
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(null)
|
||||
master-bin.000001 # Query 1 # use `test`; drop table t1
|
||||
master-bin.000001 # Query 1 # use `test`; create table t1 (a int not null auto_increment, primary key (a)) engine=myisam
|
||||
master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (207)
|
||||
master-bin.000001 # Intvar 1 # INSERT_ID=208
|
||||
master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (null)
|
||||
master-bin.000001 # Query 1 # use `test`; insert delayed into t1 values (300)
|
||||
drop table t1;
|
||||
|
|
|
@ -8,10 +8,10 @@ insert into t2 select * from t1;
|
|||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Query 1 # use `test`; insert into t1 values(1)
|
||||
master-bin.000001 257 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 351 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(1)
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -23,10 +23,10 @@ Warnings:
|
|||
Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Query 1 # use `test`; insert into t1 values(2)
|
||||
master-bin.000001 257 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 351 Query 1 # use `test`; ROLLBACK
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(2)
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; ROLLBACK
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -41,13 +41,13 @@ Warning 1196 Some non-transactional changed tables couldn't be rolled back
|
|||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Query 1 # use `test`; insert into t1 values(3)
|
||||
master-bin.000001 257 Query 1 # use `test`; savepoint my_savepoint
|
||||
master-bin.000001 342 Query 1 # use `test`; insert into t1 values(4)
|
||||
master-bin.000001 429 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 523 Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 620 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(3)
|
||||
master-bin.000001 # Query 1 # use `test`; savepoint my_savepoint
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(4)
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -67,14 +67,14 @@ a
|
|||
7
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Query 1 # use `test`; insert into t1 values(5)
|
||||
master-bin.000001 257 Query 1 # use `test`; savepoint my_savepoint
|
||||
master-bin.000001 342 Query 1 # use `test`; insert into t1 values(6)
|
||||
master-bin.000001 429 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 523 Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 620 Query 1 # use `test`; insert into t1 values(7)
|
||||
master-bin.000001 707 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(5)
|
||||
master-bin.000001 # Query 1 # use `test`; savepoint my_savepoint
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(6)
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; rollback to savepoint my_savepoint
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(7)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -89,10 +89,10 @@ get_lock("a",10)
|
|||
1
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Query 1 # use `test`; insert into t1 values(8)
|
||||
master-bin.000001 257 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 351 Query 1 # use `test`; ROLLBACK
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(8)
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; ROLLBACK
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -100,9 +100,9 @@ insert into t1 values(9);
|
|||
insert into t2 select * from t1;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; insert into t1 values(9)
|
||||
master-bin.000001 189 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 216 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(9)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 select * from t1
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -111,19 +111,19 @@ begin;
|
|||
insert into t2 select * from t1;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; insert into t1 values(10)
|
||||
master-bin.000001 190 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 217 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(10)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 select * from t1
|
||||
insert into t1 values(11);
|
||||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; insert into t1 values(10)
|
||||
master-bin.000001 190 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 217 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 311 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 379 Query 1 # use `test`; insert into t1 values(11)
|
||||
master-bin.000001 467 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(10)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(11)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
alter table t2 engine=INNODB;
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
|
@ -134,10 +134,10 @@ insert into t2 select * from t1;
|
|||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Query 1 # use `test`; insert into t1 values(12)
|
||||
master-bin.000001 258 Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 352 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(12)
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 select * from t1
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -159,9 +159,9 @@ rollback to savepoint my_savepoint;
|
|||
commit;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Query 1 # use `test`; insert into t1 values(14)
|
||||
master-bin.000001 258 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(14)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
reset master;
|
||||
|
@ -179,10 +179,10 @@ a
|
|||
18
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Query 1 # use `test`; insert into t1 values(16)
|
||||
master-bin.000001 258 Query 1 # use `test`; insert into t1 values(18)
|
||||
master-bin.000001 346 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(16)
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(18)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
delete from t1;
|
||||
delete from t2;
|
||||
alter table t2 engine=MyISAM;
|
||||
|
@ -229,29 +229,29 @@ get_lock("lock1",60)
|
|||
1
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 170 Query 1 # use `test`; insert into t1 values(16)
|
||||
master-bin.000001 258 Query 1 # use `test`; insert into t1 values(18)
|
||||
master-bin.000001 346 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 373 Query 1 # use `test`; delete from t1
|
||||
master-bin.000001 450 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 477 Query 1 # use `test`; delete from t2
|
||||
master-bin.000001 554 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 581 Query 1 # use `test`; alter table t2 engine=MyISAM
|
||||
master-bin.000001 672 Query 1 # use `test`; insert into t1 values (1)
|
||||
master-bin.000001 760 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 787 Query 1 # use `test`; insert into t2 values (20)
|
||||
master-bin.000001 876 Query 1 # use `test`; drop table t1,t2
|
||||
master-bin.000001 955 Query 1 # use `test`; create temporary table ti (a int) engine=innodb
|
||||
master-bin.000001 1065 Query 1 # use `test`; insert into ti values(1)
|
||||
master-bin.000001 1152 Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 1179 Query 1 # use `test`; create temporary table t1 (a int) engine=myisam
|
||||
master-bin.000001 1289 Query 1 # use `test`; insert t1 values (1)
|
||||
master-bin.000001 1372 Query 1 # use `test`; create table t0 (n int)
|
||||
master-bin.000001 1458 Query 1 # use `test`; insert t0 select * from t1
|
||||
master-bin.000001 1547 Query 1 # use `test`; insert into t0 select GET_LOCK("lock1",null)
|
||||
master-bin.000001 1654 Query 1 # use `test`; create table t2 (n int) engine=innodb
|
||||
master-bin.000001 1754 Query 1 # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti`
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(16)
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values(18)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; delete from t1
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; delete from t2
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; alter table t2 engine=MyISAM
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t1 values (1)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t2 values (20)
|
||||
master-bin.000001 # Query 1 # use `test`; drop table t1,t2
|
||||
master-bin.000001 # Query 1 # use `test`; create temporary table ti (a int) engine=innodb
|
||||
master-bin.000001 # Query 1 # use `test`; insert into ti values(1)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; create temporary table t1 (a int) engine=myisam
|
||||
master-bin.000001 # Query 1 # use `test`; insert t1 values (1)
|
||||
master-bin.000001 # Query 1 # use `test`; create table t0 (n int)
|
||||
master-bin.000001 # Query 1 # use `test`; insert t0 select * from t1
|
||||
master-bin.000001 # Query 1 # use `test`; insert into t0 select GET_LOCK("lock1",null)
|
||||
master-bin.000001 # Query 1 # use `test`; create table t2 (n int) engine=innodb
|
||||
master-bin.000001 # Query 1 # use `test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `test`.`t1`,`test`.`ti`
|
||||
do release_lock("lock1");
|
||||
drop table t0,t2;
|
||||
set autocommit=0;
|
||||
|
@ -333,28 +333,28 @@ a b
|
|||
DROP TABLE t1,t2;
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 102 Query 1 198 use `test`; INSERT INTO t1 values (1,1),(1,2)
|
||||
master-bin.000001 198 Query 1 284 use `test`; DROP TABLE if exists t2
|
||||
master-bin.000001 284 Query 1 374 use `test`; INSERT INTO t1 values (3,3)
|
||||
master-bin.000001 374 Query 1 460 use `test`; DROP TABLE IF EXISTS t2
|
||||
master-bin.000001 460 Query 1 584 use `test`; CREATE TABLE t2 (a int, b int, primary key (a)) engine=innodb
|
||||
master-bin.000001 584 Query 1 674 use `test`; INSERT INTO t1 VALUES (4,4)
|
||||
master-bin.000001 674 Query 1 80 use `test`; TRUNCATE table t2
|
||||
master-bin.000001 754 Xid 1 781 COMMIT /* xid= */
|
||||
master-bin.000001 781 Query 1 871 use `test`; INSERT INTO t1 VALUES (5,5)
|
||||
master-bin.000001 871 Query 1 947 use `test`; DROP TABLE t2
|
||||
master-bin.000001 947 Query 1 1037 use `test`; INSERT INTO t1 values (6,6)
|
||||
master-bin.000001 1037 Query 1 1171 use `test`; CREATE TEMPORARY TABLE t2 (a int, b int, primary key (a)) engine=innodb
|
||||
master-bin.000001 1171 Query 1 1261 use `test`; INSERT INTO t1 values (7,7)
|
||||
master-bin.000001 1261 Query 1 1351 use `test`; INSERT INTO t1 values (8,8)
|
||||
master-bin.000001 1351 Query 1 1441 use `test`; INSERT INTO t1 values (9,9)
|
||||
master-bin.000001 1441 Query 1 80 use `test`; TRUNCATE table t2
|
||||
master-bin.000001 1521 Xid 1 1548 COMMIT /* xid= */
|
||||
master-bin.000001 1548 Query 1 1640 use `test`; INSERT INTO t1 values (10,10)
|
||||
master-bin.000001 1640 Query 1 1708 use `test`; BEGIN
|
||||
master-bin.000001 1708 Query 1 94 use `test`; INSERT INTO t2 values (100,100)
|
||||
master-bin.000001 1802 Xid 1 1829 COMMIT /* xid= */
|
||||
master-bin.000001 1829 Query 1 1908 use `test`; DROP TABLE t1,t2
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 values (1,1),(1,2)
|
||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE if exists t2
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 values (3,3)
|
||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE IF EXISTS t2
|
||||
master-bin.000001 # Query 1 # use `test`; CREATE TABLE t2 (a int, b int, primary key (a)) engine=innodb
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES (4,4)
|
||||
master-bin.000001 # Query 1 # use `test`; TRUNCATE table t2
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 VALUES (5,5)
|
||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE t2
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 values (6,6)
|
||||
master-bin.000001 # Query 1 # use `test`; CREATE TEMPORARY TABLE t2 (a int, b int, primary key (a)) engine=innodb
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 values (7,7)
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 values (8,8)
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 values (9,9)
|
||||
master-bin.000001 # Query 1 # use `test`; TRUNCATE table t2
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t1 values (10,10)
|
||||
master-bin.000001 # Query 1 # use `test`; BEGIN
|
||||
master-bin.000001 # Query 1 # use `test`; INSERT INTO t2 values (100,100)
|
||||
master-bin.000001 # Xid 1 # COMMIT /* xid= */
|
||||
master-bin.000001 # Query 1 # use `test`; DROP TABLE t1,t2
|
||||
reset master;
|
||||
create table t1 (a int) engine=innodb;
|
||||
create table t2 (a int) engine=myisam;
|
||||
|
|
|
@ -353,3 +353,18 @@ select row_count();
|
|||
row_count()
|
||||
1
|
||||
drop table t1;
|
||||
create table t1 (id int primary key auto_increment, data int, unique(data));
|
||||
insert ignore into t1 values(NULL,100),(NULL,110),(NULL,120);
|
||||
insert ignore into t1 values(NULL,10),(NULL,20),(NULL,110),(NULL,120),(NULL,100),(NULL,90);
|
||||
insert ignore into t1 values(NULL,130),(NULL,140),(500,110),(550,120),(450,100),(NULL,150);
|
||||
select * from t1 order by id;
|
||||
id data
|
||||
1 100
|
||||
2 110
|
||||
3 120
|
||||
4 10
|
||||
5 20
|
||||
6 90
|
||||
7 130
|
||||
8 140
|
||||
9 150
|
||||
|
|
|
@ -183,3 +183,47 @@ a
|
|||
32
|
||||
42
|
||||
drop table t1;
|
||||
create table t1 (a tinyint not null auto_increment primary key) engine=myisam;
|
||||
insert into t1 values(103);
|
||||
set auto_increment_increment=11;
|
||||
set auto_increment_offset=4;
|
||||
insert into t1 values(null);
|
||||
insert into t1 values(null);
|
||||
insert into t1 values(null);
|
||||
ERROR 23000: Duplicate entry '125' for key 'PRIMARY'
|
||||
select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t1 order by a;
|
||||
a mod(a-@@auto_increment_offset,@@auto_increment_increment)
|
||||
103 0
|
||||
114 0
|
||||
125 0
|
||||
create table t2 (a tinyint unsigned not null auto_increment primary key) engine=myisam;
|
||||
set auto_increment_increment=10;
|
||||
set auto_increment_offset=1;
|
||||
set insert_id=1000;
|
||||
insert into t2 values(null);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'a' at row 1
|
||||
select a, mod(a-@@auto_increment_offset,@@auto_increment_increment) from t2 order by a;
|
||||
a mod(a-@@auto_increment_offset,@@auto_increment_increment)
|
||||
251 0
|
||||
create table t3 like t1;
|
||||
set auto_increment_increment=1000;
|
||||
set auto_increment_offset=700;
|
||||
insert into t3 values(null);
|
||||
Warnings:
|
||||
Warning 1264 Out of range value for column 'a' at row 1
|
||||
select * from t3 order by a;
|
||||
a
|
||||
127
|
||||
select * from t1 order by a;
|
||||
a
|
||||
103
|
||||
114
|
||||
125
|
||||
select * from t2 order by a;
|
||||
a
|
||||
251
|
||||
select * from t3 order by a;
|
||||
a
|
||||
127
|
||||
drop table t1,t2,t3;
|
||||
|
|
16
mysql-test/r/rpl_insert.result
Normal file
16
mysql-test/r/rpl_insert.result
Normal file
|
@ -0,0 +1,16 @@
|
|||
stop slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
reset master;
|
||||
reset slave;
|
||||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
CREATE SCHEMA IF NOT EXISTS mysqlslap;
|
||||
USE mysqlslap;
|
||||
CREATE TABLE t1 (id INT, name VARCHAR(64));
|
||||
SELECT COUNT(*) FROM mysqlslap.t1;
|
||||
COUNT(*)
|
||||
5000
|
||||
SELECT COUNT(*) FROM mysqlslap.t1;
|
||||
COUNT(*)
|
||||
5000
|
||||
DROP SCHEMA IF EXISTS mysqlslap;
|
|
@ -117,6 +117,14 @@ insert into t1 (last_id) values (bug15728());
|
|||
select last_insert_id();
|
||||
last_insert_id()
|
||||
5
|
||||
drop procedure if exists foo;
|
||||
create procedure foo()
|
||||
begin
|
||||
declare res int;
|
||||
insert into t2 (last_id) values (bug15728());
|
||||
insert into t1 (last_id) values (bug15728());
|
||||
end|
|
||||
call foo();
|
||||
select * from t1;
|
||||
id last_id
|
||||
1 0
|
||||
|
@ -124,10 +132,126 @@ id last_id
|
|||
3 2
|
||||
4 1
|
||||
5 4
|
||||
6 3
|
||||
select * from t2;
|
||||
id last_id
|
||||
1 3
|
||||
2 4
|
||||
3 5
|
||||
select * from t1;
|
||||
id last_id
|
||||
1 0
|
||||
2 1
|
||||
3 2
|
||||
4 1
|
||||
5 4
|
||||
6 3
|
||||
select * from t2;
|
||||
id last_id
|
||||
1 3
|
||||
2 4
|
||||
3 5
|
||||
drop function bug15728;
|
||||
drop function bug15728_insert;
|
||||
drop table t1;
|
||||
drop procedure foo;
|
||||
create table t1 (n int primary key auto_increment not null,
|
||||
b int, unique(b));
|
||||
set sql_log_bin=0;
|
||||
insert into t1 values(null,100);
|
||||
replace into t1 values(null,50),(null,100),(null,150);
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
2 50
|
||||
3 100
|
||||
4 150
|
||||
truncate table t1;
|
||||
set sql_log_bin=1;
|
||||
insert into t1 values(null,100);
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
1 100
|
||||
insert into t1 values(null,200),(null,300);
|
||||
delete from t1 where b <> 100;
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
1 100
|
||||
replace into t1 values(null,100),(null,350);
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
2 100
|
||||
3 350
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
2 100
|
||||
3 350
|
||||
insert into t1 values (NULL,400),(3,500),(NULL,600) on duplicate key UPDATE n=1000;
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
2 100
|
||||
4 400
|
||||
1000 350
|
||||
1001 600
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
2 100
|
||||
4 400
|
||||
1000 350
|
||||
1001 600
|
||||
drop table t1;
|
||||
create table t1 (n int primary key auto_increment not null,
|
||||
b int, unique(b));
|
||||
insert into t1 values(null,100);
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
1 100
|
||||
insert into t1 values(null,200),(null,300);
|
||||
delete from t1 where b <> 100;
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
1 100
|
||||
insert into t1 values(null,100),(null,350) on duplicate key update n=2;
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
2 100
|
||||
3 350
|
||||
select * from t1 order by n;
|
||||
n b
|
||||
2 100
|
||||
3 350
|
||||
drop table t1;
|
||||
truncate table t2;
|
||||
create table t1 (id tinyint primary key);
|
||||
create function insid() returns int
|
||||
begin
|
||||
insert into t2 (last_id) values (0);
|
||||
return 0;
|
||||
end|
|
||||
set sql_log_bin=0;
|
||||
insert into t2 (id) values(1),(2),(3);
|
||||
delete from t2;
|
||||
set sql_log_bin=1;
|
||||
select insid();
|
||||
insid()
|
||||
0
|
||||
set sql_log_bin=0;
|
||||
insert into t2 (id) values(5),(6),(7);
|
||||
delete from t2 where id>=5;
|
||||
set sql_log_bin=1;
|
||||
insert into t1 select insid();
|
||||
select * from t1;
|
||||
id
|
||||
0
|
||||
select * from t2;
|
||||
id last_id
|
||||
4 0
|
||||
8 0
|
||||
select * from t1;
|
||||
id
|
||||
0
|
||||
select * from t2;
|
||||
id last_id
|
||||
4 0
|
||||
8 0
|
||||
drop table t1, t2;
|
||||
drop function insid;
|
||||
|
|
|
@ -5,8 +5,14 @@ reset slave;
|
|||
drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
|
||||
start slave;
|
||||
reset master;
|
||||
select last_insert_id();
|
||||
last_insert_id()
|
||||
0
|
||||
create table t1(a int not null auto_increment, b int, primary key(a) );
|
||||
load data infile '../std_data_ln/rpl_loaddata.dat' into table t1;
|
||||
select last_insert_id();
|
||||
last_insert_id()
|
||||
1
|
||||
create temporary table t2 (day date,id int(9),category enum('a','b','c'),name varchar(60));
|
||||
load data infile '../std_data_ln/rpl_loaddata2.dat' into table t2 fields terminated by ',' optionally enclosed by '%' escaped by '@' lines terminated by '\n##\n' starting by '>' ignore 1 lines;
|
||||
create table t3 (day date,id int(9),category enum('a','b','c'),name varchar(60));
|
||||
|
@ -22,7 +28,7 @@ day id category name
|
|||
2003-03-22 2416 a bbbbb
|
||||
show master status;
|
||||
File Position Binlog_Do_DB Binlog_Ignore_DB
|
||||
slave-bin.000001 1276
|
||||
slave-bin.000001 1248
|
||||
drop table t1;
|
||||
drop table t2;
|
||||
drop table t3;
|
||||
|
@ -33,7 +39,7 @@ set global sql_slave_skip_counter=1;
|
|||
start slave;
|
||||
show slave status;
|
||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
|
||||
# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1793 # # master-bin.000001 Yes Yes # 0 0 1793 # None 0 No #
|
||||
# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1765 # # master-bin.000001 Yes Yes # 0 0 1765 # None 0 No #
|
||||
set sql_log_bin=0;
|
||||
delete from t1;
|
||||
set sql_log_bin=1;
|
||||
|
@ -43,7 +49,7 @@ change master to master_user='test';
|
|||
change master to master_user='root';
|
||||
show slave status;
|
||||
Slave_IO_State Master_Host Master_User Master_Port Connect_Retry Master_Log_File Read_Master_Log_Pos Relay_Log_File Relay_Log_Pos Relay_Master_Log_File Slave_IO_Running Slave_SQL_Running Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table Replicate_Ignore_Table Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno Last_Error Skip_Counter Exec_Master_Log_Pos Relay_Log_Space Until_Condition Until_Log_File Until_Log_Pos Master_SSL_Allowed Master_SSL_CA_File Master_SSL_CA_Path Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master
|
||||
# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1828 # # master-bin.000001 No No # 0 0 1828 # None 0 No #
|
||||
# 127.0.0.1 root MASTER_PORT 1 master-bin.000001 1800 # # master-bin.000001 No No # 0 0 1800 # None 0 No #
|
||||
set global sql_slave_skip_counter=1;
|
||||
start slave;
|
||||
set sql_log_bin=0;
|
||||
|
|
|
@ -71,8 +71,8 @@ a
|
|||
250
|
||||
251
|
||||
400
|
||||
401
|
||||
1000
|
||||
1001
|
||||
******* Select from Slave *************
|
||||
|
||||
select * from t1 ORDER BY a;
|
||||
|
@ -83,8 +83,8 @@ a
|
|||
250
|
||||
251
|
||||
400
|
||||
401
|
||||
1000
|
||||
1001
|
||||
drop table t1;
|
||||
create table t1 (a int not null auto_increment, primary key (a)) engine=NDB;
|
||||
insert into t1 values (NULL),(5),(NULL),(NULL);
|
||||
|
@ -120,8 +120,6 @@ a
|
|||
502
|
||||
503
|
||||
600
|
||||
603
|
||||
604
|
||||
610
|
||||
611
|
||||
******* Select from Slave *************
|
||||
|
@ -137,8 +135,6 @@ a
|
|||
502
|
||||
503
|
||||
600
|
||||
603
|
||||
604
|
||||
610
|
||||
611
|
||||
drop table t1;
|
||||
|
|
|
@ -178,6 +178,7 @@ CREATE TABLE t8 LIKE t4;
|
|||
CREATE TABLE t9 LIKE tt4;
|
||||
CREATE TEMPORARY TABLE tt5 LIKE t4;
|
||||
CREATE TEMPORARY TABLE tt6 LIKE tt4;
|
||||
CREATE TEMPORARY TABLE tt7 SELECT 1;
|
||||
**** On Master ****
|
||||
SHOW CREATE TABLE t8;
|
||||
Table t8
|
||||
|
|
|
@ -17,8 +17,10 @@ Log_name Pos Event_type Server_id End_log_pos Info
|
|||
master-bin.000001 4 Format_desc 1 102 Server ver: VERSION, Binlog ver: 4
|
||||
master-bin.000001 102 Query 1 222 use `test`; create table t1(a int not null primary key) engine=myisam
|
||||
master-bin.000001 222 Table_map 1 261 table_id: # (test.t1)
|
||||
master-bin.000001 261 Write_rows 1 305 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 305 Query 1 380 use `test`; flush tables
|
||||
master-bin.000001 261 Write_rows 1 295 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 295 Table_map 1 334 table_id: # (test.t1)
|
||||
master-bin.000001 334 Write_rows 1 373 table_id: # flags: STMT_END_F
|
||||
master-bin.000001 373 Query 1 448 use `test`; flush tables
|
||||
SELECT * FROM t1 ORDER BY a;
|
||||
a
|
||||
1
|
||||
|
|
|
@ -18,18 +18,18 @@ select @@global.binlog_format, @@session.binlog_format;
|
|||
ROW ROW
|
||||
CREATE TABLE t1 (a varchar(100));
|
||||
prepare stmt1 from 'insert into t1 select concat(UUID(),?)';
|
||||
set @string="emergency";
|
||||
insert into t1 values("work");
|
||||
set @string="emergency_1_";
|
||||
insert into t1 values("work_2_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values(concat(UUID(),"work"));
|
||||
insert into t1 values(concat(UUID(),"work_3_"));
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 select "yesterday";
|
||||
create temporary table tmp(a char(3));
|
||||
insert into tmp values("see");
|
||||
insert into t1 values(concat("for_4_",UUID()));
|
||||
insert into t1 select "yesterday_5_";
|
||||
create temporary table tmp(a char(100));
|
||||
insert into tmp values("see_6_");
|
||||
set binlog_format=statement;
|
||||
ERROR HY000: Cannot switch out of the row-based binary log format when the session has open temporary tables
|
||||
insert into t1 select * from tmp;
|
||||
|
@ -55,16 +55,16 @@ select @@global.binlog_format, @@session.binlog_format;
|
|||
@@global.binlog_format @@session.binlog_format
|
||||
STATEMENT STATEMENT
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
set @string="emergency";
|
||||
insert into t1 values("work");
|
||||
set @string="emergency_7_";
|
||||
insert into t1 values("work_8_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values("work");
|
||||
insert into t1 values("work_9_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
insert into t1 values("for");
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values("for_10_");
|
||||
insert into t1 select "yesterday_11_";
|
||||
set binlog_format=default;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
@@global.binlog_format @@session.binlog_format
|
||||
|
@ -75,16 +75,16 @@ select @@global.binlog_format, @@session.binlog_format;
|
|||
@@global.binlog_format @@session.binlog_format
|
||||
STATEMENT STATEMENT
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
set @string="emergency";
|
||||
insert into t1 values("work");
|
||||
set @string="emergency_12_";
|
||||
insert into t1 values("work_13_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values("work");
|
||||
insert into t1 values("work_14_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
insert into t1 values("for");
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values("for_15_");
|
||||
insert into t1 select "yesterday_16_";
|
||||
set binlog_format=mixed;
|
||||
select @@global.binlog_format, @@session.binlog_format;
|
||||
@@global.binlog_format @@session.binlog_format
|
||||
|
@ -94,40 +94,40 @@ select @@global.binlog_format, @@session.binlog_format;
|
|||
@@global.binlog_format @@session.binlog_format
|
||||
MIXED MIXED
|
||||
prepare stmt1 from 'insert into t1 select concat(UUID(),?)';
|
||||
set @string="emergency";
|
||||
insert into t1 values("work");
|
||||
set @string="emergency_17_";
|
||||
insert into t1 values("work_18_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values(concat(UUID(),"work"));
|
||||
insert into t1 values(concat(UUID(),"work_19_"));
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values(concat("for_20_",UUID()));
|
||||
insert into t1 select "yesterday_21_";
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values(concat(UUID(),"work"));
|
||||
insert into t1 values(concat(UUID(),"work_22_"));
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 select "yesterday";
|
||||
create table t2 select UUID();
|
||||
insert into t1 values(concat("for_23_",UUID()));
|
||||
insert into t1 select "yesterday_24_";
|
||||
create table t2 select rpad(UUID(),100,' ');
|
||||
create table t3 select 1 union select UUID();
|
||||
create table t4 select * from t1 where 3 in (select 1 union select 2 union select UUID() union select 3);
|
||||
create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
|
||||
insert into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4);
|
||||
create procedure foo()
|
||||
begin
|
||||
insert into t1 values("work");
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values("work_25_");
|
||||
insert into t1 values(concat("for_26_",UUID()));
|
||||
insert into t1 select "yesterday_27_";
|
||||
end|
|
||||
create procedure foo2()
|
||||
begin
|
||||
insert into t1 values(concat("emergency",UUID()));
|
||||
insert into t1 values("work");
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 values(concat("emergency_28_",UUID()));
|
||||
insert into t1 values("work_29_");
|
||||
insert into t1 values(concat("for_30_",UUID()));
|
||||
set session binlog_format=row; # accepted for stored procs
|
||||
insert into t1 values("more work");
|
||||
insert into t1 values("more work_31_");
|
||||
set session binlog_format=mixed;
|
||||
end|
|
||||
create function foo3() returns bigint unsigned
|
||||
|
@ -136,32 +136,231 @@ set session binlog_format=row; # rejected for stored funcs
|
|||
insert into t1 values("alarm");
|
||||
return 100;
|
||||
end|
|
||||
create procedure foo4(x varchar(100))
|
||||
begin
|
||||
insert into t1 values(concat("work_250_",x));
|
||||
insert into t1 select "yesterday_270_";
|
||||
end|
|
||||
call foo();
|
||||
call foo2();
|
||||
call foo4("hello");
|
||||
call foo4(UUID());
|
||||
call foo4("world");
|
||||
select foo3();
|
||||
ERROR HY000: Cannot change the binary logging format inside a stored function or trigger
|
||||
select * from t1 where a="alarm";
|
||||
a
|
||||
drop function foo3;
|
||||
create function foo3() returns bigint unsigned
|
||||
begin
|
||||
insert into t1 values("foo3_32_");
|
||||
call foo();
|
||||
return 100;
|
||||
end|
|
||||
insert into t2 select foo3();
|
||||
prepare stmt1 from 'insert into t2 select foo3()';
|
||||
execute stmt1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
create function foo4() returns bigint unsigned
|
||||
begin
|
||||
insert into t2 select foo3();
|
||||
return 100;
|
||||
end|
|
||||
select foo4();
|
||||
foo4()
|
||||
100
|
||||
prepare stmt1 from 'select foo4()';
|
||||
execute stmt1;
|
||||
foo4()
|
||||
100
|
||||
execute stmt1;
|
||||
foo4()
|
||||
100
|
||||
deallocate prepare stmt1;
|
||||
create function foo5() returns bigint unsigned
|
||||
begin
|
||||
insert into t2 select UUID();
|
||||
return 100;
|
||||
end|
|
||||
select foo5();
|
||||
foo5()
|
||||
100
|
||||
prepare stmt1 from 'select foo5()';
|
||||
execute stmt1;
|
||||
foo5()
|
||||
100
|
||||
execute stmt1;
|
||||
foo5()
|
||||
100
|
||||
deallocate prepare stmt1;
|
||||
create function foo6(x varchar(100)) returns bigint unsigned
|
||||
begin
|
||||
insert into t2 select x;
|
||||
return 100;
|
||||
end|
|
||||
select foo6("foo6_1_");
|
||||
foo6("foo6_1_")
|
||||
100
|
||||
select foo6(concat("foo6_2_",UUID()));
|
||||
foo6(concat("foo6_2_",UUID()))
|
||||
100
|
||||
prepare stmt1 from 'select foo6(concat("foo6_3_",UUID()))';
|
||||
execute stmt1;
|
||||
foo6(concat("foo6_3_",UUID()))
|
||||
100
|
||||
execute stmt1;
|
||||
foo6(concat("foo6_3_",UUID()))
|
||||
100
|
||||
deallocate prepare stmt1;
|
||||
create view v1 as select uuid();
|
||||
create table t11 (data varchar(255));
|
||||
insert into t11 select * from v1;
|
||||
insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11');
|
||||
prepare stmt1 from "insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')";
|
||||
execute stmt1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
create trigger t11_bi before insert on t11 for each row
|
||||
begin
|
||||
set NEW.data = concat(NEW.data,UUID());
|
||||
end|
|
||||
insert into t11 values("try_560_");
|
||||
insert delayed into t2 values("delay_1_");
|
||||
insert delayed into t2 values(concat("delay_2_",UUID()));
|
||||
insert delayed into t2 values("delay_6_");
|
||||
insert delayed into t2 values(rand());
|
||||
set @a=2.345;
|
||||
insert delayed into t2 values(@a);
|
||||
create table t20 select * from t1;
|
||||
create table t21 select * from t2;
|
||||
create table t22 select * from t3;
|
||||
drop table t1,t2,t3;
|
||||
create table t1 (a int primary key auto_increment, b varchar(100));
|
||||
create table t2 (a int primary key auto_increment, b varchar(100));
|
||||
create table t3 (b varchar(100));
|
||||
create function f (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
insert into t1 values(null,x);
|
||||
insert into t2 values(null,x);
|
||||
return 1;
|
||||
end|
|
||||
select f("try_41_");
|
||||
f("try_41_")
|
||||
1
|
||||
use mysqltest1;
|
||||
insert into t2 values(2,null),(3,null),(4,null);
|
||||
delete from t2 where a>=2;
|
||||
select f("try_42_");
|
||||
f("try_42_")
|
||||
1
|
||||
insert into t2 values(3,null),(4,null);
|
||||
delete from t2 where a>=3;
|
||||
prepare stmt1 from 'select f(?)';
|
||||
set @string="try_43_";
|
||||
insert into t1 values(null,"try_44_");
|
||||
execute stmt1 using @string;
|
||||
f(?)
|
||||
1
|
||||
deallocate prepare stmt1;
|
||||
create table t12 select * from t1;
|
||||
drop table t1;
|
||||
create table t1 (a int, b varchar(100), key(a));
|
||||
select f("try_45_");
|
||||
f("try_45_")
|
||||
1
|
||||
create table t13 select * from t1;
|
||||
drop table t1;
|
||||
create table t1 (a int primary key auto_increment, b varchar(100));
|
||||
drop function f;
|
||||
create table t14 (unique (a)) select * from t2;
|
||||
truncate table t2;
|
||||
create function f1 (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
insert into t1 values(null,x);
|
||||
return 1;
|
||||
end|
|
||||
create function f2 (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
insert into t2 values(null,x);
|
||||
return 1;
|
||||
end|
|
||||
select f1("try_46_"),f2("try_47_");
|
||||
f1("try_46_") f2("try_47_")
|
||||
1 1
|
||||
insert into t2 values(2,null),(3,null),(4,null);
|
||||
delete from t2 where a>=2;
|
||||
select f1("try_48_"),f2("try_49_");
|
||||
f1("try_48_") f2("try_49_")
|
||||
1 1
|
||||
insert into t3 values(concat("try_50_",f1("try_51_"),f2("try_52_")));
|
||||
drop function f2;
|
||||
create function f2 (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
declare y int;
|
||||
insert into t1 values(null,x);
|
||||
set y = (select count(*) from t2);
|
||||
return y;
|
||||
end|
|
||||
select f1("try_53_"),f2("try_54_");
|
||||
f1("try_53_") f2("try_54_")
|
||||
1 3
|
||||
drop function f2;
|
||||
create trigger t1_bi before insert on t1 for each row
|
||||
begin
|
||||
insert into t2 values(null,"try_55_");
|
||||
end|
|
||||
insert into t1 values(null,"try_56_");
|
||||
alter table t1 modify a int, drop primary key;
|
||||
insert into t1 values(null,"try_57_");
|
||||
CREATE TEMPORARY TABLE t15 SELECT UUID();
|
||||
create table t16 like t15;
|
||||
INSERT INTO t16 SELECT * FROM t15;
|
||||
insert into t16 values("try_65_");
|
||||
drop table t15;
|
||||
insert into t16 values("try_66_");
|
||||
select count(*) from t1;
|
||||
count(*)
|
||||
36
|
||||
7
|
||||
select count(*) from t2;
|
||||
count(*)
|
||||
1
|
||||
5
|
||||
select count(*) from t3;
|
||||
count(*)
|
||||
2
|
||||
1
|
||||
select count(*) from t4;
|
||||
count(*)
|
||||
29
|
||||
select count(*) from t5;
|
||||
count(*)
|
||||
58
|
||||
select count(*) from t11;
|
||||
count(*)
|
||||
8
|
||||
select count(*) from t20;
|
||||
count(*)
|
||||
66
|
||||
select count(*) from t21;
|
||||
count(*)
|
||||
19
|
||||
select count(*) from t22;
|
||||
count(*)
|
||||
2
|
||||
select count(*) from t12;
|
||||
count(*)
|
||||
4
|
||||
select count(*) from t13;
|
||||
count(*)
|
||||
1
|
||||
select count(*) from t14;
|
||||
count(*)
|
||||
4
|
||||
select count(*) from t16;
|
||||
count(*)
|
||||
3
|
||||
show binlog events from 102;
|
||||
Log_name Pos Event_type Server_id End_log_pos Info
|
||||
master-bin.000001 # Query 1 # drop database if exists mysqltest1
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysql.proc)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # create database mysqltest1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE t1 (a varchar(100))
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
|
@ -178,78 +377,71 @@ master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
|||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_8_")
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_9_")
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F375F COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_10_")
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_11_"
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_13_")
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_14_")
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31325F COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for_15_")
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_16_"
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work_18_")
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for")
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday"
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("for")
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday"
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday"
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_21_"
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E6379 COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # User var 1 # @`string`=_latin1 0x656D657267656E63795F31375F COLLATE latin1_swedish_ci
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select @'string'
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday"
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_24_"
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t2` (
|
||||
`UUID()` varchar(36) CHARACTER SET utf8 NOT NULL DEFAULT ''
|
||||
`rpad(UUID(),100,' ')` varchar(100) CHARACTER SET utf8 NOT NULL DEFAULT ''
|
||||
)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; COMMIT
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t3` (
|
||||
`1` varbinary(108) NOT NULL DEFAULT ''
|
||||
)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; COMMIT
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t4` (
|
||||
`a` varchar(100) DEFAULT NULL
|
||||
)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t4)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; COMMIT
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t5)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo()
|
||||
begin
|
||||
insert into t1 values("work");
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values("work_25_");
|
||||
insert into t1 values(concat("for_26_",UUID()));
|
||||
insert into t1 select "yesterday_27_";
|
||||
end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo2()
|
||||
begin
|
||||
insert into t1 values(concat("emergency",UUID()));
|
||||
insert into t1 values("work");
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 values(concat("emergency_28_",UUID()));
|
||||
insert into t1 values("work_29_");
|
||||
insert into t1 values(concat("for_30_",UUID()));
|
||||
set session binlog_format=row; # accepted for stored procs
|
||||
insert into t1 values("more work");
|
||||
insert into t1 values("more work_31_");
|
||||
set session binlog_format=mixed;
|
||||
end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned
|
||||
|
@ -258,15 +450,213 @@ set session binlog_format=row; # rejected for stored funcs
|
|||
insert into t1 values("alarm");
|
||||
return 100;
|
||||
end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday"
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values("work")
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` procedure foo4(x varchar(100))
|
||||
begin
|
||||
insert into t1 values(concat("work_250_",x));
|
||||
insert into t1 select "yesterday_270_";
|
||||
end
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',_latin1'hello')))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_"
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(concat("work_250_", NAME_CONST('x',_latin1'world')))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 select "yesterday_270_"
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop function foo3
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo3() returns bigint unsigned
|
||||
begin
|
||||
insert into t1 values("foo3_32_");
|
||||
call foo();
|
||||
return 100;
|
||||
end
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo4() returns bigint unsigned
|
||||
begin
|
||||
insert into t2 select foo3();
|
||||
return 100;
|
||||
end
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo5() returns bigint unsigned
|
||||
begin
|
||||
insert into t2 select UUID();
|
||||
return 100;
|
||||
end
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function foo6(x varchar(100)) returns bigint unsigned
|
||||
begin
|
||||
insert into t2 select x;
|
||||
return 100;
|
||||
end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `foo6`(_latin1'foo6_1_')
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE ALGORITHM=UNDEFINED DEFINER=`root`@`localhost` SQL SECURITY DEFINER VIEW `v1` AS select uuid()
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t11 (data varchar(255))
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t11_bi before insert on t11 for each row
|
||||
begin
|
||||
set NEW.data = concat(NEW.data,UUID());
|
||||
end
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t11)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t20 select * from t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t21 select * from t2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t22 select * from t3
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1,t2,t3
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t2 (a int primary key auto_increment, b varchar(100))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t3 (b varchar(100))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
insert into t1 values(null,x);
|
||||
insert into t2 values(null,x);
|
||||
return 1;
|
||||
end
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Intvar 1 # INSERT_ID=3
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_44_")
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t12 select * from t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int, b varchar(100), key(a))
|
||||
master-bin.000001 # Intvar 1 # INSERT_ID=4
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f`(_latin1'try_45_')
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t13 select * from t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop table t1
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t1 (a int primary key auto_increment, b varchar(100))
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop function f
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; create table t14 (unique (a)) select * from t2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; truncate table t2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f1 (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
insert into t1 values(null,x);
|
||||
return 1;
|
||||
end
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f2 (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
insert into t2 values(null,x);
|
||||
return 1;
|
||||
end
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t3)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` function f2 (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
declare y int;
|
||||
insert into t1 values(null,x);
|
||||
set y = (select count(*) from t2);
|
||||
return y;
|
||||
end
|
||||
master-bin.000001 # Intvar 1 # INSERT_ID=4
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f1`(_latin1'try_53_')
|
||||
master-bin.000001 # Intvar 1 # INSERT_ID=5
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; SELECT `f2`(_latin1'try_54_')
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; drop function f2
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE DEFINER=`root`@`localhost` trigger t1_bi before insert on t1 for each row
|
||||
begin
|
||||
insert into t2 values(null,"try_55_");
|
||||
end
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t1)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t2)
|
||||
master-bin.000001 # Write_rows 1 # table_id: #
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; alter table t1 modify a int, drop primary key
|
||||
master-bin.000001 # Intvar 1 # INSERT_ID=5
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t1 values(null,"try_57_")
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; CREATE TABLE `t16` (
|
||||
`UUID()` varchar(36) CHARACTER SET utf8 NOT NULL DEFAULT ''
|
||||
)
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Table_map 1 # table_id: # (mysqltest1.t16)
|
||||
master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F
|
||||
master-bin.000001 # Query 1 # use `mysqltest1`; insert into t16 values("try_66_")
|
||||
drop database mysqltest1;
|
||||
|
|
|
@ -76,16 +76,11 @@ drop table t1,t2;
|
|||
create temporary table t3 (f int);
|
||||
create temporary table t4 (f int);
|
||||
create table t5 (f int);
|
||||
drop table if exists t999;
|
||||
create temporary table t999 (f int);
|
||||
LOAD DATA INFILE "./tmp/bl_dump_thread_id" into table t999;
|
||||
drop table t999;
|
||||
insert into t4 values (1);
|
||||
kill `select id from information_schema.processlist where command='Binlog Dump'`;
|
||||
select id from information_schema.processlist where command='Binlog Dump' into @id;
|
||||
kill @id;
|
||||
insert into t5 select * from t4;
|
||||
select * from t5 /* must be 1 after reconnection */;
|
||||
f
|
||||
1
|
||||
drop temporary table t4;
|
||||
drop table t5;
|
||||
set @@session.pseudo_thread_id=100;
|
||||
|
@ -93,6 +88,7 @@ create temporary table t101 (id int);
|
|||
create temporary table t102 (id int);
|
||||
set @@session.pseudo_thread_id=200;
|
||||
create temporary table t201 (id int);
|
||||
create temporary table `t``201` (id int);
|
||||
create temporary table `#sql_not_user_table202` (id int);
|
||||
set @@session.pseudo_thread_id=300;
|
||||
create temporary table t301 (id int);
|
||||
|
|
|
@ -303,3 +303,50 @@ INSERT INTO t1 VALUES(1, 1);
|
|||
--error ER_DUP_ENTRY
|
||||
ALTER TABLE t1 CHANGE t1 t1 INT(10) auto_increment;
|
||||
DROP TABLE t1;
|
||||
|
||||
# Fix for BUG#19243 "wrong LAST_INSERT_ID() after ON DUPLICATE KEY
|
||||
# UPDATE": now LAST_INSERT_ID() will return the id of the updated
|
||||
# row.
|
||||
CREATE TABLE `t2` (
|
||||
`k` int(11) NOT NULL auto_increment,
|
||||
`a` int(11) default NULL,
|
||||
`c` int(11) default NULL,
|
||||
PRIMARY KEY (`k`),
|
||||
UNIQUE KEY `idx_1` (`a`)
|
||||
) ENGINE=InnoDB;
|
||||
insert into t2 ( a ) values ( 6 ) on duplicate key update c =
|
||||
ifnull( c,
|
||||
0 ) + 1;
|
||||
insert into t2 ( a ) values ( 7 ) on duplicate key update c =
|
||||
ifnull( c,
|
||||
0 ) + 1;
|
||||
select last_insert_id();
|
||||
select * from t2;
|
||||
insert into t2 ( a ) values ( 6 ) on duplicate key update c =
|
||||
ifnull( c,
|
||||
0 ) + 1;
|
||||
select last_insert_id();
|
||||
select * from t2;
|
||||
|
||||
# Test of LAST_INSERT_ID() when autogenerated will fail:
|
||||
# last_insert_id() should not change
|
||||
insert ignore into t2 values (null,6,1),(10,8,1);
|
||||
select last_insert_id();
|
||||
# First and second autogenerated will fail, last_insert_id() should
|
||||
# point to third
|
||||
insert ignore into t2 values (null,6,1),(null,8,1),(null,15,1),(null,20,1);
|
||||
select last_insert_id();
|
||||
select * from t2;
|
||||
|
||||
drop table t2;
|
||||
|
||||
# Test of REPLACE when it does INSERT+DELETE and not UPDATE:
|
||||
# see if it sets LAST_INSERT_ID() ok
|
||||
create table t1 (a int primary key auto_increment, b int, c int, d timestamp default current_timestamp, unique(b),unique(c));
|
||||
insert into t1 values(null,1,1,now());
|
||||
insert into t1 values(null,0,0,null);
|
||||
# this will delete two rows
|
||||
replace into t1 values(null,1,0,null);
|
||||
select last_insert_id();
|
||||
|
||||
drop table t1;
|
||||
|
|
|
@ -29,7 +29,6 @@ rpl_ndb_ddl : BUG#18946 result file needs update + test needs to ch
|
|||
rpl_ndb_innodb2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
|
||||
#rpl_ndb_log : BUG#18947 2006-03-21 tomas CRBR: order in binlog of create table and insert (on different table) not determ
|
||||
rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fails on DELETE FROM statement
|
||||
rpl_switch_stm_row_mixed : BUG#18590 2006-03-28 brian
|
||||
rpl_row_blob_innodb : BUG#18980 2006-04-10 kent Test fails randomly
|
||||
rpl_row_func003 : BUG#19074 2006-13-04 andrei test failed
|
||||
rpl_sp : BUG#16456 2006-02-16 jmiller
|
||||
|
|
|
@ -234,3 +234,10 @@ select row_count();
|
|||
insert into t1 values (5, 5) on duplicate key update data= data + 10;
|
||||
select row_count();
|
||||
drop table t1;
|
||||
|
||||
# Test of INSERT IGNORE and re-using auto_increment values
|
||||
create table t1 (id int primary key auto_increment, data int, unique(data));
|
||||
insert ignore into t1 values(NULL,100),(NULL,110),(NULL,120);
|
||||
insert ignore into t1 values(NULL,10),(NULL,20),(NULL,110),(NULL,120),(NULL,100),(NULL,90);
|
||||
insert ignore into t1 values(NULL,130),(NULL,140),(500,110),(550,120),(450,100),(NULL,150);
|
||||
select * from t1 order by id;
|
||||
|
|
29
mysql-test/t/rpl_insert.test
Normal file
29
mysql-test/t/rpl_insert.test
Normal file
|
@ -0,0 +1,29 @@
|
|||
|
||||
#
|
||||
# Bug#20821: INSERT DELAYED fails to write some rows to binlog
|
||||
#
|
||||
|
||||
--source include/master-slave.inc
|
||||
--source include/not_embedded.inc
|
||||
--source include/not_windows.inc
|
||||
|
||||
--disable_warnings
|
||||
CREATE SCHEMA IF NOT EXISTS mysqlslap;
|
||||
USE mysqlslap;
|
||||
--enable_warnings
|
||||
|
||||
CREATE TABLE t1 (id INT, name VARCHAR(64));
|
||||
|
||||
let $query = "INSERT DELAYED INTO t1 VALUES (1, 'Dr. No'), (2, 'From Russia With Love'), (3, 'Goldfinger'), (4, 'Thunderball'), (5, 'You Only Live Twice')";
|
||||
--exec $MYSQL_SLAP --silent --concurrency=5 --iterations=200 --query=$query --delimiter=";"
|
||||
|
||||
--sleep 10
|
||||
|
||||
SELECT COUNT(*) FROM mysqlslap.t1;
|
||||
sync_slave_with_master;
|
||||
SELECT COUNT(*) FROM mysqlslap.t1;
|
||||
|
||||
connection master;
|
||||
DROP SCHEMA IF EXISTS mysqlslap;
|
||||
sync_slave_with_master;
|
||||
|
|
@ -97,6 +97,7 @@ CREATE TABLE t8 LIKE t4;
|
|||
CREATE TABLE t9 LIKE tt4;
|
||||
CREATE TEMPORARY TABLE tt5 LIKE t4;
|
||||
CREATE TEMPORARY TABLE tt6 LIKE tt4;
|
||||
CREATE TEMPORARY TABLE tt7 SELECT 1;
|
||||
--echo **** On Master ****
|
||||
--query_vertical SHOW CREATE TABLE t8
|
||||
--query_vertical SHOW CREATE TABLE t9
|
||||
|
|
|
@ -15,22 +15,22 @@ select @@global.binlog_format, @@session.binlog_format;
|
|||
CREATE TABLE t1 (a varchar(100));
|
||||
|
||||
prepare stmt1 from 'insert into t1 select concat(UUID(),?)';
|
||||
set @string="emergency";
|
||||
insert into t1 values("work");
|
||||
set @string="emergency_1_";
|
||||
insert into t1 values("work_2_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values(concat(UUID(),"work"));
|
||||
insert into t1 values(concat(UUID(),"work_3_"));
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values(concat("for_4_",UUID()));
|
||||
insert into t1 select "yesterday_5_";
|
||||
|
||||
# verify that temp tables prevent a switch to SBR
|
||||
create temporary table tmp(a char(3));
|
||||
insert into tmp values("see");
|
||||
create temporary table tmp(a char(100));
|
||||
insert into tmp values("see_6_");
|
||||
--error ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR
|
||||
set binlog_format=statement;
|
||||
insert into t1 select * from tmp;
|
||||
|
@ -47,18 +47,18 @@ show session variables like "binlog_format%";
|
|||
select @@global.binlog_format, @@session.binlog_format;
|
||||
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
set @string="emergency";
|
||||
insert into t1 values("work");
|
||||
set @string="emergency_7_";
|
||||
insert into t1 values("work_8_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values("work");
|
||||
insert into t1 values("work_9_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
insert into t1 values("for");
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values("for_10_");
|
||||
insert into t1 select "yesterday_11_";
|
||||
|
||||
# test SET DEFAULT (=statement at this point of test)
|
||||
set binlog_format=default;
|
||||
|
@ -69,18 +69,18 @@ set global binlog_format=default;
|
|||
select @@global.binlog_format, @@session.binlog_format;
|
||||
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
set @string="emergency";
|
||||
insert into t1 values("work");
|
||||
set @string="emergency_12_";
|
||||
insert into t1 values("work_13_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values("work");
|
||||
insert into t1 values("work_14_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
insert into t1 values("for");
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values("for_15_");
|
||||
insert into t1 select "yesterday_16_";
|
||||
|
||||
# and now the mixed mode
|
||||
|
||||
|
@ -90,53 +90,52 @@ set global binlog_format=mixed;
|
|||
select @@global.binlog_format, @@session.binlog_format;
|
||||
|
||||
prepare stmt1 from 'insert into t1 select concat(UUID(),?)';
|
||||
set @string="emergency";
|
||||
insert into t1 values("work");
|
||||
set @string="emergency_17_";
|
||||
insert into t1 values("work_18_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values(concat(UUID(),"work"));
|
||||
insert into t1 values(concat(UUID(),"work_19_"));
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values(concat("for_20_",UUID()));
|
||||
insert into t1 select "yesterday_21_";
|
||||
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values(concat(UUID(),"work"));
|
||||
insert into t1 values(concat(UUID(),"work_22_"));
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values(concat("for_23_",UUID()));
|
||||
insert into t1 select "yesterday_24_";
|
||||
|
||||
# Test of CREATE TABLE SELECT
|
||||
|
||||
create table t2 select UUID();
|
||||
create table t2 select rpad(UUID(),100,' ');
|
||||
create table t3 select 1 union select UUID();
|
||||
create table t4 select * from t1 where 3 in (select 1 union select 2 union select UUID() union select 3);
|
||||
create table t5 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
|
||||
# what if UUID() is first:
|
||||
insert into t5 select UUID() from t1 where 3 in (select 1 union select 2 union select 3 union select * from t4);
|
||||
|
||||
# inside a stored procedure (inside a function or trigger won't
|
||||
# work)
|
||||
# inside a stored procedure
|
||||
|
||||
delimiter |;
|
||||
create procedure foo()
|
||||
begin
|
||||
insert into t1 values("work");
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 select "yesterday";
|
||||
insert into t1 values("work_25_");
|
||||
insert into t1 values(concat("for_26_",UUID()));
|
||||
insert into t1 select "yesterday_27_";
|
||||
end|
|
||||
create procedure foo2()
|
||||
begin
|
||||
insert into t1 values(concat("emergency",UUID()));
|
||||
insert into t1 values("work");
|
||||
insert into t1 values(concat("for",UUID()));
|
||||
insert into t1 values(concat("emergency_28_",UUID()));
|
||||
insert into t1 values("work_29_");
|
||||
insert into t1 values(concat("for_30_",UUID()));
|
||||
set session binlog_format=row; # accepted for stored procs
|
||||
insert into t1 values("more work");
|
||||
insert into t1 values("more work_31_");
|
||||
set session binlog_format=mixed;
|
||||
end|
|
||||
create function foo3() returns bigint unsigned
|
||||
|
@ -145,15 +144,130 @@ begin
|
|||
insert into t1 values("alarm");
|
||||
return 100;
|
||||
end|
|
||||
create procedure foo4(x varchar(100))
|
||||
begin
|
||||
insert into t1 values(concat("work_250_",x));
|
||||
insert into t1 select "yesterday_270_";
|
||||
end|
|
||||
delimiter ;|
|
||||
call foo();
|
||||
call foo2();
|
||||
call foo4("hello");
|
||||
call foo4(UUID());
|
||||
call foo4("world");
|
||||
|
||||
# test that can't SET in a stored function
|
||||
--error ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT
|
||||
select foo3();
|
||||
select * from t1 where a="alarm";
|
||||
|
||||
# Tests of stored functions/triggers/views for BUG#20930 "Mixed
|
||||
# binlogging mode does not work with stored functions, triggers,
|
||||
# views"
|
||||
|
||||
# Function which calls procedure
|
||||
drop function foo3;
|
||||
delimiter |;
|
||||
create function foo3() returns bigint unsigned
|
||||
begin
|
||||
insert into t1 values("foo3_32_");
|
||||
call foo();
|
||||
return 100;
|
||||
end|
|
||||
delimiter ;|
|
||||
insert into t2 select foo3();
|
||||
|
||||
prepare stmt1 from 'insert into t2 select foo3()';
|
||||
execute stmt1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
# Test if stored function calls stored function which calls procedure
|
||||
# which requires row-based.
|
||||
|
||||
delimiter |;
|
||||
create function foo4() returns bigint unsigned
|
||||
begin
|
||||
insert into t2 select foo3();
|
||||
return 100;
|
||||
end|
|
||||
delimiter ;|
|
||||
select foo4();
|
||||
|
||||
prepare stmt1 from 'select foo4()';
|
||||
execute stmt1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
# A simple stored function
|
||||
delimiter |;
|
||||
create function foo5() returns bigint unsigned
|
||||
begin
|
||||
insert into t2 select UUID();
|
||||
return 100;
|
||||
end|
|
||||
delimiter ;|
|
||||
select foo5();
|
||||
|
||||
prepare stmt1 from 'select foo5()';
|
||||
execute stmt1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
# A simple stored function where UUID() is in the argument
|
||||
delimiter |;
|
||||
create function foo6(x varchar(100)) returns bigint unsigned
|
||||
begin
|
||||
insert into t2 select x;
|
||||
return 100;
|
||||
end|
|
||||
delimiter ;|
|
||||
select foo6("foo6_1_");
|
||||
select foo6(concat("foo6_2_",UUID()));
|
||||
|
||||
prepare stmt1 from 'select foo6(concat("foo6_3_",UUID()))';
|
||||
execute stmt1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
|
||||
# Test of views using UUID()
|
||||
|
||||
create view v1 as select uuid();
|
||||
create table t11 (data varchar(255));
|
||||
insert into t11 select * from v1;
|
||||
# Test of querying INFORMATION_SCHEMA which parses the view's body,
|
||||
# to verify that it binlogs statement-based (is not polluted by
|
||||
# the parsing of the view's body).
|
||||
insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11');
|
||||
prepare stmt1 from "insert into t11 select TABLE_NAME from INFORMATION_SCHEMA.TABLES where TABLE_SCHEMA='mysqltest1' and TABLE_NAME IN ('v1','t11')";
|
||||
execute stmt1;
|
||||
execute stmt1;
|
||||
deallocate prepare stmt1;
|
||||
|
||||
# Test of triggers with UUID()
|
||||
delimiter |;
|
||||
create trigger t11_bi before insert on t11 for each row
|
||||
begin
|
||||
set NEW.data = concat(NEW.data,UUID());
|
||||
end|
|
||||
delimiter ;|
|
||||
insert into t11 values("try_560_");
|
||||
|
||||
# Test that INSERT DELAYED works in mixed mode (BUG#20649)
|
||||
insert delayed into t2 values("delay_1_");
|
||||
insert delayed into t2 values(concat("delay_2_",UUID()));
|
||||
insert delayed into t2 values("delay_6_");
|
||||
|
||||
# Test for BUG#20633 (INSERT DELAYED RAND()/user_variable does not
|
||||
# replicate fine in statement-based ; we test that in mixed mode it
|
||||
# works).
|
||||
insert delayed into t2 values(rand());
|
||||
set @a=2.345;
|
||||
insert delayed into t2 values(@a);
|
||||
|
||||
sleep 4; # time for the delayed inserts to reach disk
|
||||
|
||||
# If you want to do manual testing of the mixed mode regarding UDFs (not
|
||||
# testable automatically as quite platform- and compiler-dependent),
|
||||
# you just need to set the variable below to 1, and to
|
||||
|
@ -164,30 +278,181 @@ if ($you_want_to_test_UDF)
|
|||
{
|
||||
CREATE FUNCTION metaphon RETURNS STRING SONAME 'udf_example.so';
|
||||
prepare stmt1 from 'insert into t1 select metaphon(?)';
|
||||
set @string="emergency";
|
||||
insert into t1 values("work");
|
||||
set @string="emergency_133_";
|
||||
insert into t1 values("work_134_");
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
prepare stmt1 from 'insert into t1 select ?';
|
||||
insert into t1 values(metaphon("work"));
|
||||
insert into t1 values(metaphon("work_135_"));
|
||||
execute stmt1 using @string;
|
||||
deallocate prepare stmt1;
|
||||
insert into t1 values(metaphon("for"));
|
||||
insert into t1 select "yesterday";
|
||||
create table t6 select metaphon("for");
|
||||
create table t7 select 1 union select metaphon("for");
|
||||
create table t8 select * from t1 where 3 in (select 1 union select 2 union select metaphon("for") union select 3);
|
||||
insert into t1 values(metaphon("for_136_"));
|
||||
insert into t1 select "yesterday_137_";
|
||||
create table t6 select metaphon("for_138_");
|
||||
create table t7 select 1 union select metaphon("for_139_");
|
||||
create table t8 select * from t1 where 3 in (select 1 union select 2 union select metaphon("for_140_") union select 3);
|
||||
create table t9 select * from t1 where 3 in (select 1 union select 2 union select curdate() union select 3);
|
||||
}
|
||||
|
||||
create table t20 select * from t1; # save for comparing later
|
||||
create table t21 select * from t2;
|
||||
create table t22 select * from t3;
|
||||
drop table t1,t2,t3;
|
||||
|
||||
# This tests the fix to
|
||||
# BUG#19630 stored function inserting into two auto_increment breaks statement-based binlog
|
||||
# We verify that under the mixed binlog mode, a stored function
|
||||
# modifying at least two tables having an auto_increment column,
|
||||
# is binlogged row-based. Indeed in statement-based binlogging,
|
||||
# only the auto_increment value generated for the first table
|
||||
# is recorded in the binlog, the value generated for the 2nd table
|
||||
# lacking.
|
||||
|
||||
create table t1 (a int primary key auto_increment, b varchar(100));
|
||||
create table t2 (a int primary key auto_increment, b varchar(100));
|
||||
create table t3 (b varchar(100));
|
||||
delimiter |;
|
||||
create function f (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
insert into t1 values(null,x);
|
||||
insert into t2 values(null,x);
|
||||
return 1;
|
||||
end|
|
||||
delimiter ;|
|
||||
select f("try_41_");
|
||||
# Two operations which compensate each other except that their net
|
||||
# effect is that they advance the auto_increment counter of t2 on slave:
|
||||
sync_slave_with_master;
|
||||
use mysqltest1;
|
||||
insert into t2 values(2,null),(3,null),(4,null);
|
||||
delete from t2 where a>=2;
|
||||
|
||||
connection master;
|
||||
# this is the call which didn't replicate well
|
||||
select f("try_42_");
|
||||
sync_slave_with_master;
|
||||
|
||||
# now use prepared statement and test again, just to see that the RBB
|
||||
# mode isn't set at PREPARE but at EXECUTE.
|
||||
|
||||
insert into t2 values(3,null),(4,null);
|
||||
delete from t2 where a>=3;
|
||||
|
||||
connection master;
|
||||
prepare stmt1 from 'select f(?)';
|
||||
set @string="try_43_";
|
||||
insert into t1 values(null,"try_44_"); # should be SBB
|
||||
execute stmt1 using @string; # should be RBB
|
||||
deallocate prepare stmt1;
|
||||
sync_slave_with_master;
|
||||
|
||||
# verify that if only one table has auto_inc, it does not trigger RBB
|
||||
# (we'll check in binlog further below)
|
||||
|
||||
connection master;
|
||||
create table t12 select * from t1; # save for comparing later
|
||||
drop table t1;
|
||||
create table t1 (a int, b varchar(100), key(a));
|
||||
select f("try_45_");
|
||||
|
||||
# restore table's key
|
||||
create table t13 select * from t1;
|
||||
drop table t1;
|
||||
create table t1 (a int primary key auto_increment, b varchar(100));
|
||||
|
||||
# now test if it's two functions, each of them inserts in one table
|
||||
|
||||
drop function f;
|
||||
# we need a unique key to have sorting of rows by mysqldump
|
||||
create table t14 (unique (a)) select * from t2;
|
||||
truncate table t2;
|
||||
delimiter |;
|
||||
create function f1 (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
insert into t1 values(null,x);
|
||||
return 1;
|
||||
end|
|
||||
create function f2 (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
insert into t2 values(null,x);
|
||||
return 1;
|
||||
end|
|
||||
delimiter ;|
|
||||
select f1("try_46_"),f2("try_47_");
|
||||
|
||||
sync_slave_with_master;
|
||||
insert into t2 values(2,null),(3,null),(4,null);
|
||||
delete from t2 where a>=2;
|
||||
|
||||
connection master;
|
||||
# Test with SELECT and INSERT
|
||||
select f1("try_48_"),f2("try_49_");
|
||||
insert into t3 values(concat("try_50_",f1("try_51_"),f2("try_52_")));
|
||||
sync_slave_with_master;
|
||||
|
||||
# verify that if f2 does only read on an auto_inc table, this does not
|
||||
# switch to RBB
|
||||
connection master;
|
||||
drop function f2;
|
||||
delimiter |;
|
||||
create function f2 (x varchar(100)) returns int deterministic
|
||||
begin
|
||||
declare y int;
|
||||
insert into t1 values(null,x);
|
||||
set y = (select count(*) from t2);
|
||||
return y;
|
||||
end|
|
||||
delimiter ;|
|
||||
select f1("try_53_"),f2("try_54_");
|
||||
sync_slave_with_master;
|
||||
|
||||
# And now, a normal statement with a trigger (no stored functions)
|
||||
|
||||
connection master;
|
||||
drop function f2;
|
||||
delimiter |;
|
||||
create trigger t1_bi before insert on t1 for each row
|
||||
begin
|
||||
insert into t2 values(null,"try_55_");
|
||||
end|
|
||||
delimiter ;|
|
||||
insert into t1 values(null,"try_56_");
|
||||
# and now remove one auto_increment and verify SBB
|
||||
alter table t1 modify a int, drop primary key;
|
||||
insert into t1 values(null,"try_57_");
|
||||
sync_slave_with_master;
|
||||
|
||||
# Test for BUG#20499 "mixed mode with temporary table breaks binlog"
|
||||
# Slave used to have only 2 rows instead of 3.
|
||||
connection master;
|
||||
CREATE TEMPORARY TABLE t15 SELECT UUID();
|
||||
create table t16 like t15;
|
||||
INSERT INTO t16 SELECT * FROM t15;
|
||||
# we'll verify that this one is done RBB
|
||||
insert into t16 values("try_65_");
|
||||
drop table t15;
|
||||
# we'll verify that this one is done SBB
|
||||
insert into t16 values("try_66_");
|
||||
sync_slave_with_master;
|
||||
|
||||
# and now compare:
|
||||
|
||||
connection master;
|
||||
|
||||
# first check that data on master is sensible
|
||||
select count(*) from t1;
|
||||
select count(*) from t2;
|
||||
select count(*) from t3;
|
||||
select count(*) from t4;
|
||||
select count(*) from t5;
|
||||
select count(*) from t11;
|
||||
select count(*) from t20;
|
||||
select count(*) from t21;
|
||||
select count(*) from t22;
|
||||
select count(*) from t12;
|
||||
select count(*) from t13;
|
||||
select count(*) from t14;
|
||||
select count(*) from t16;
|
||||
if ($you_want_to_test_UDF)
|
||||
{
|
||||
select count(*) from t6;
|
||||
|
@ -196,21 +461,46 @@ if ($you_want_to_test_UDF)
|
|||
select count(*) from t9;
|
||||
}
|
||||
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/
|
||||
show binlog events from 102;
|
||||
sync_slave_with_master;
|
||||
# as we're using UUID we don't SELECT but use "diff" like in rpl_row_UUID
|
||||
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql
|
||||
--exec $MYSQL_DUMP_SLAVE --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql
|
||||
|
||||
connection master;
|
||||
drop database mysqltest1;
|
||||
sync_slave_with_master;
|
||||
|
||||
# Let's compare. Note: If they match test will pass, if they do not match
|
||||
# the test will show that the diff statement failed and not reject file
|
||||
# will be created. You will need to go to the mysql-test dir and diff
|
||||
# the files your self to see what is not matching
|
||||
|
||||
--exec diff $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql;
|
||||
|
||||
connection master;
|
||||
--replace_column 2 # 5 #
|
||||
--replace_regex /table_id: [0-9]+/table_id: #/
|
||||
show binlog events from 102;
|
||||
|
||||
# Now test that mysqlbinlog works fine on a binlog generated by the
|
||||
# mixed mode
|
||||
|
||||
# BUG#11312 "DELIMITER is not written to the binary log that causes
|
||||
# syntax error" makes that mysqlbinlog will fail if we pass it the
|
||||
# text of queries; this forces us to use --base64-output here.
|
||||
|
||||
# BUG#20929 "BINLOG command causes invalid free plus assertion
|
||||
# failure" makes mysqld segfault when receiving --base64-output
|
||||
|
||||
# So I can't enable this piece of test
|
||||
# SIGH
|
||||
|
||||
if ($enable_when_11312_or_20929_fixed)
|
||||
{
|
||||
--exec $MYSQL_BINLOG --base64-output $MYSQLTEST_VARDIR/log/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_mixed.sql
|
||||
drop database mysqltest1;
|
||||
--exec $MYSQL < $MYSQLTEST_VARDIR/tmp/mysqlbinlog_mixed.sql
|
||||
--exec $MYSQL_DUMP --compact --order-by-primary --skip-extended-insert --no-create-info mysqltest1 > $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql
|
||||
# the old mysqldump output on slave is the same as what it was on
|
||||
# master before restoring on master.
|
||||
--exec diff $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_master.sql $MYSQLTEST_VARDIR/tmp/rpl_switch_stm_row_mixed_slave.sql;
|
||||
}
|
||||
|
||||
drop database mysqltest1;
|
||||
sync_slave_with_master;
|
||||
|
|
|
@ -142,11 +142,8 @@ create temporary table t4 (f int);
|
|||
create table t5 (f int);
|
||||
sync_with_master;
|
||||
# find dumper's $id
|
||||
source include/get_binlog_dump_thread_id.inc;
|
||||
insert into t4 values (1);
|
||||
# a hint how to do that in 5.1
|
||||
--replace_result $id "`select id from information_schema.processlist where command='Binlog Dump'`"
|
||||
eval kill $id; # to stimulate reconnection by slave w/o timeout
|
||||
select id from information_schema.processlist where command='Binlog Dump' into @id;
|
||||
kill @id; # to stimulate reconnection by slave w/o timeout
|
||||
insert into t5 select * from t4;
|
||||
save_master_pos;
|
||||
|
||||
|
@ -170,7 +167,7 @@ create temporary table t101 (id int);
|
|||
create temporary table t102 (id int);
|
||||
set @@session.pseudo_thread_id=200;
|
||||
create temporary table t201 (id int);
|
||||
#create temporary table `t``201` (id int);
|
||||
create temporary table `t``201` (id int);
|
||||
# emulate internal temp table not to come to binlog
|
||||
create temporary table `#sql_not_user_table202` (id int);
|
||||
set @@session.pseudo_thread_id=300;
|
||||
|
@ -203,4 +200,4 @@ select * from t1;
|
|||
connection master;
|
||||
drop table t1;
|
||||
|
||||
# End of 5.0 tests
|
||||
# End of 5.1 tests
|
||||
|
|
|
@ -525,8 +525,9 @@ char *_my_strdup(const char *from, const char *filename, uint lineno,
|
|||
} /* _my_strdup */
|
||||
|
||||
|
||||
char *_my_strndup(const char *from, uint length, const char *filename,
|
||||
uint lineno, myf MyFlags)
|
||||
char *_my_strndup(const char *from, uint length,
|
||||
const char *filename, uint lineno,
|
||||
myf MyFlags)
|
||||
{
|
||||
gptr ptr;
|
||||
if ((ptr=_mymalloc(length+1,filename,lineno,MyFlags)) != 0)
|
||||
|
|
|
@ -631,7 +631,8 @@ static int parse_url(FEDERATED_SHARE *share, TABLE *table,
|
|||
DBUG_PRINT("info", ("String: '%.*s'", table->s->connect_string.length,
|
||||
table->s->connect_string.str));
|
||||
share->scheme= my_strndup(table->s->connect_string.str,
|
||||
table->s->connect_string.length, MYF(0));
|
||||
table->s->connect_string.length,
|
||||
MYF(0));
|
||||
|
||||
share->connect_string_length= table->s->connect_string.length;
|
||||
DBUG_PRINT("info",("parse_url alloced share->scheme %lx", share->scheme));
|
||||
|
@ -1702,14 +1703,15 @@ int ha_federated::write_row(byte *buf)
|
|||
This method ensures that last_insert_id() works properly. What it simply does
|
||||
is calls last_insert_id() on the foreign database immediately after insert
|
||||
(if the table has an auto_increment field) and sets the insert id via
|
||||
thd->insert_id(ID) (as well as storing thd->prev_insert_id)
|
||||
thd->insert_id(ID)).
|
||||
*/
|
||||
void ha_federated::update_auto_increment(void)
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
DBUG_ENTER("ha_federated::update_auto_increment");
|
||||
|
||||
thd->insert_id(mysql->last_used_con->insert_id);
|
||||
thd->first_successful_insert_id_in_cur_stmt=
|
||||
mysql->last_used_con->insert_id;
|
||||
DBUG_PRINT("info",("last_insert_id %d", stats.auto_increment_value));
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
|
|
|
@ -2473,9 +2473,7 @@ int ha_ndbcluster::write_row(byte *record)
|
|||
|
||||
m_skip_auto_increment= FALSE;
|
||||
update_auto_increment();
|
||||
/* Ensure that handler is always called for auto_increment values */
|
||||
thd->next_insert_id= 0;
|
||||
m_skip_auto_increment= !auto_increment_column_changed;
|
||||
m_skip_auto_increment= (insert_id_for_cur_row == 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -5263,7 +5263,7 @@ int ha_partition::cmp_ref(const byte *ref1, const byte *ref2)
|
|||
MODULE auto increment
|
||||
****************************************************************************/
|
||||
|
||||
void ha_partition::restore_auto_increment()
|
||||
void ha_partition::restore_auto_increment(ulonglong)
|
||||
{
|
||||
DBUG_ENTER("ha_partition::restore_auto_increment");
|
||||
|
||||
|
|
|
@ -811,7 +811,7 @@ public:
|
|||
auto_increment_column_changed
|
||||
-------------------------------------------------------------------------
|
||||
*/
|
||||
virtual void restore_auto_increment();
|
||||
virtual void restore_auto_increment(ulonglong prev_insert_id);
|
||||
virtual void get_auto_increment(ulonglong offset, ulonglong increment,
|
||||
ulonglong nb_desired_values,
|
||||
ulonglong *first_value,
|
||||
|
|
367
sql/handler.cc
367
sql/handler.cc
|
@ -1514,7 +1514,10 @@ int handler::read_first_row(byte * buf, uint primary_key)
|
|||
}
|
||||
|
||||
/*
|
||||
Generate the next auto-increment number based on increment and offset
|
||||
Generate the next auto-increment number based on increment and offset:
|
||||
computes the lowest number
|
||||
- strictly greater than "nr"
|
||||
- of the form: auto_increment_offset + N * auto_increment_increment
|
||||
|
||||
In most cases increment= offset= 1, in which case we get:
|
||||
1,2,3,4,5,...
|
||||
|
@ -1523,8 +1526,10 @@ int handler::read_first_row(byte * buf, uint primary_key)
|
|||
*/
|
||||
|
||||
inline ulonglong
|
||||
next_insert_id(ulonglong nr,struct system_variables *variables)
|
||||
compute_next_insert_id(ulonglong nr,struct system_variables *variables)
|
||||
{
|
||||
if (variables->auto_increment_increment == 1)
|
||||
return (nr+1); // optimization of the formula below
|
||||
nr= (((nr+ variables->auto_increment_increment -
|
||||
variables->auto_increment_offset)) /
|
||||
(ulonglong) variables->auto_increment_increment);
|
||||
|
@ -1533,6 +1538,58 @@ next_insert_id(ulonglong nr,struct system_variables *variables)
|
|||
}
|
||||
|
||||
|
||||
void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr)
|
||||
{
|
||||
/*
|
||||
If we have set THD::next_insert_id previously and plan to insert an
|
||||
explicitely-specified value larger than this, we need to increase
|
||||
THD::next_insert_id to be greater than the explicit value.
|
||||
*/
|
||||
if ((next_insert_id > 0) && (nr >= next_insert_id))
|
||||
set_next_insert_id(compute_next_insert_id(nr, &table->in_use->variables));
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Computes the largest number X:
|
||||
- smaller than or equal to "nr"
|
||||
- of the form: auto_increment_offset + N * auto_increment_increment
|
||||
where N>=0.
|
||||
|
||||
SYNOPSIS
|
||||
prev_insert_id
|
||||
nr Number to "round down"
|
||||
variables variables struct containing auto_increment_increment and
|
||||
auto_increment_offset
|
||||
|
||||
RETURN
|
||||
The number X if it exists, "nr" otherwise.
|
||||
*/
|
||||
|
||||
inline ulonglong
|
||||
prev_insert_id(ulonglong nr, struct system_variables *variables)
|
||||
{
|
||||
if (unlikely(nr < variables->auto_increment_offset))
|
||||
{
|
||||
/*
|
||||
There's nothing good we can do here. That is a pathological case, where
|
||||
the offset is larger than the column's max possible value, i.e. not even
|
||||
the first sequence value may be inserted. User will receive warning.
|
||||
*/
|
||||
DBUG_PRINT("info",("auto_increment: nr: %lu cannot honour "
|
||||
"auto_increment_offset: %lu",
|
||||
nr, variables->auto_increment_offset));
|
||||
return nr;
|
||||
}
|
||||
if (variables->auto_increment_increment == 1)
|
||||
return nr; // optimization of the formula below
|
||||
nr= (((nr - variables->auto_increment_offset)) /
|
||||
(ulonglong) variables->auto_increment_increment);
|
||||
return (nr * (ulonglong) variables->auto_increment_increment +
|
||||
variables->auto_increment_offset);
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Update the auto_increment field if necessary
|
||||
|
||||
|
@ -1546,7 +1603,7 @@ next_insert_id(ulonglong nr,struct system_variables *variables)
|
|||
|
||||
IMPLEMENTATION
|
||||
|
||||
Updates columns with type NEXT_NUMBER if:
|
||||
Updates the record's Field of type NEXT_NUMBER if:
|
||||
|
||||
- If column value is set to NULL (in which case
|
||||
auto_increment_field_not_null is 0)
|
||||
|
@ -1554,25 +1611,31 @@ next_insert_id(ulonglong nr,struct system_variables *variables)
|
|||
set. In the future we will only set NEXT_NUMBER fields if one sets them
|
||||
to NULL (or they are not included in the insert list).
|
||||
|
||||
In those cases, we check if the currently reserved interval still has
|
||||
values we have not used. If yes, we pick the smallest one and use it.
|
||||
Otherwise:
|
||||
|
||||
There are two different cases when the above is true:
|
||||
- If a list of intervals has been provided to the statement via SET
|
||||
INSERT_ID or via an Intvar_log_event (in a replication slave), we pick the
|
||||
first unused interval from this list, consider it as reserved.
|
||||
|
||||
- thd->next_insert_id == 0 (This is the normal case)
|
||||
In this case we set the set the column for the first row to the value
|
||||
next_insert_id(get_auto_increment(column))) which is normally
|
||||
max-used-column-value +1.
|
||||
- Otherwise we set the column for the first row to the value
|
||||
next_insert_id(get_auto_increment(column))) which is usually
|
||||
max-used-column-value+1.
|
||||
We call get_auto_increment() for the first row in a multi-row
|
||||
statement. get_auto_increment() will tell us the interval of values it
|
||||
reserved for us.
|
||||
|
||||
We call get_auto_increment() only for the first row in a multi-row
|
||||
statement. For the following rows we generate new numbers based on the
|
||||
last used number.
|
||||
- In both cases, for the following rows we use those reserved values without
|
||||
calling the handler again (we just progress in the interval, computing
|
||||
each new value from the previous one). Until we have exhausted them, then
|
||||
we either take the next provided interval or call get_auto_increment()
|
||||
again to reserve a new interval.
|
||||
|
||||
- thd->next_insert_id != 0. This happens when we have read an Intvar event
|
||||
of type INSERT_ID_EVENT from the binary log or when one has used SET
|
||||
INSERT_ID=#.
|
||||
|
||||
In this case we will set the column to the value of next_insert_id.
|
||||
The next row will be given the id
|
||||
next_insert_id(next_insert_id)
|
||||
- In both cases, the reserved intervals are remembered in
|
||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog if statement-based
|
||||
binlogging; the last reserved interval is remembered in
|
||||
auto_inc_interval_for_cur_row.
|
||||
|
||||
The idea is that generated auto_increment values are predictable and
|
||||
independent of the column values in the table. This is needed to be
|
||||
|
@ -1583,7 +1646,13 @@ next_insert_id(ulonglong nr,struct system_variables *variables)
|
|||
inserts a column with a higher value than the last used one, we will
|
||||
start counting from the inserted value.
|
||||
|
||||
thd->next_insert_id is cleared after it's been used for a statement.
|
||||
This function's "outputs" are: the table's auto_increment field is filled
|
||||
with a value, thd->next_insert_id is filled with the value to use for the
|
||||
next row, if a value was autogenerated for the current row it is stored in
|
||||
thd->insert_id_for_cur_row, if get_auto_increment() was called
|
||||
thd->auto_inc_interval_for_cur_row is modified, if that interval is not
|
||||
present in thd->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
|
||||
this list.
|
||||
|
||||
TODO
|
||||
|
||||
|
@ -1600,7 +1669,8 @@ next_insert_id(ulonglong nr,struct system_variables *variables)
|
|||
|
||||
bool handler::update_auto_increment()
|
||||
{
|
||||
ulonglong nr;
|
||||
ulonglong nr, nb_reserved_values;
|
||||
bool append= FALSE;
|
||||
THD *thd= table->in_use;
|
||||
struct system_variables *variables= &thd->variables;
|
||||
bool auto_increment_field_not_null;
|
||||
|
@ -1608,10 +1678,10 @@ bool handler::update_auto_increment()
|
|||
DBUG_ENTER("handler::update_auto_increment");
|
||||
|
||||
/*
|
||||
We must save the previous value to be able to restore it if the
|
||||
row was not inserted
|
||||
next_insert_id is a "cursor" into the reserved interval, it may go greater
|
||||
than the interval, but not smaller.
|
||||
*/
|
||||
thd->prev_insert_id= thd->next_insert_id;
|
||||
DBUG_ASSERT(next_insert_id >= auto_inc_interval_for_cur_row.minimum());
|
||||
auto_increment_field_not_null= table->auto_increment_field_not_null;
|
||||
table->auto_increment_field_not_null= FALSE; // to reset for next row
|
||||
|
||||
|
@ -1619,134 +1689,143 @@ bool handler::update_auto_increment()
|
|||
auto_increment_field_not_null &&
|
||||
thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO)
|
||||
{
|
||||
/*
|
||||
The user did specify a value for the auto_inc column, we don't generate
|
||||
a new value, write it down.
|
||||
*/
|
||||
auto_increment_column_changed=0;
|
||||
|
||||
/*
|
||||
Update next_insert_id if we had already generated a value in this
|
||||
statement (case of INSERT VALUES(null),(3763),(null):
|
||||
the last NULL needs to insert 3764, not the value of the first NULL plus
|
||||
1).
|
||||
*/
|
||||
if (thd->clear_next_insert_id && nr >= thd->next_insert_id)
|
||||
{
|
||||
if (variables->auto_increment_increment != 1)
|
||||
nr= next_insert_id(nr, variables);
|
||||
else
|
||||
nr++;
|
||||
thd->next_insert_id= nr;
|
||||
DBUG_PRINT("info",("next_insert_id: %lu", (ulong) nr));
|
||||
}
|
||||
adjust_next_insert_id_after_explicit_value(nr);
|
||||
insert_id_for_cur_row= 0; // didn't generate anything
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
if (!(nr= thd->next_insert_id))
|
||||
{
|
||||
ulonglong nb_desired_values= 1, nb_reserved_values;
|
||||
#ifdef TO_BE_ENABLED_SOON
|
||||
/*
|
||||
Reserved intervals will be stored in "THD::auto_inc_intervals".
|
||||
handler::estimation_rows_to_insert will be the argument passed by
|
||||
handler::ha_start_bulk_insert().
|
||||
*/
|
||||
uint estimation_known= test(estimation_rows_to_insert > 0);
|
||||
uint nb_already_reserved_intervals= thd->auto_inc_intervals.nb_elements();
|
||||
/*
|
||||
If an estimation was given to the engine:
|
||||
- use it.
|
||||
- if we already reserved numbers, it means the estimation was
|
||||
not accurate, then we'll reserve 2*AUTO_INC_DEFAULT_NB_VALUES the 2nd
|
||||
time, twice that the 3rd time etc.
|
||||
If no estimation was given, use those increasing defaults from the
|
||||
start, starting from AUTO_INC_DEFAULT_NB_VALUES.
|
||||
Don't go beyond a max to not reserve "way too much" (because reservation
|
||||
means potentially losing unused values).
|
||||
*/
|
||||
if (nb_already_reserved_intervals == 0 && estimation_known)
|
||||
nb_desired_values= estimation_rows_to_insert;
|
||||
else /* go with the increasing defaults */
|
||||
{
|
||||
/* avoid overflow in formula, with this if() */
|
||||
if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
|
||||
{
|
||||
nb_desired_values= AUTO_INC_DEFAULT_NB_VALUES *
|
||||
(1 << nb_already_reserved_intervals);
|
||||
set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
|
||||
}
|
||||
else
|
||||
nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
|
||||
}
|
||||
#endif
|
||||
/* This call ignores all its parameters but nr, currently */
|
||||
get_auto_increment(variables->auto_increment_offset,
|
||||
variables->auto_increment_increment,
|
||||
nb_desired_values, &nr,
|
||||
&nb_reserved_values);
|
||||
if (nr == ~(ulonglong) 0)
|
||||
result= 1; // Mark failure
|
||||
|
||||
/*
|
||||
That should not be needed when engines actually use offset and increment
|
||||
above.
|
||||
*/
|
||||
if (variables->auto_increment_increment != 1)
|
||||
nr= next_insert_id(nr-1, variables);
|
||||
/*
|
||||
Update next row based on the found value. This way we don't have to
|
||||
call the handler for every generated auto-increment value on a
|
||||
multi-row statement
|
||||
*/
|
||||
thd->next_insert_id= nr;
|
||||
if ((nr= next_insert_id) >= auto_inc_interval_for_cur_row.maximum())
|
||||
{
|
||||
/* next_insert_id is beyond what is reserved, so we reserve more. */
|
||||
const Discrete_interval *forced=
|
||||
thd->auto_inc_intervals_forced.get_next();
|
||||
if (forced != NULL)
|
||||
{
|
||||
nr= forced->minimum();
|
||||
nb_reserved_values= forced->values();
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
handler::estimation_rows_to_insert was set by
|
||||
handler::ha_start_bulk_insert(); if 0 it means "unknown".
|
||||
*/
|
||||
uint nb_already_reserved_intervals=
|
||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements();
|
||||
ulonglong nb_desired_values;
|
||||
/*
|
||||
If an estimation was given to the engine:
|
||||
- use it.
|
||||
- if we already reserved numbers, it means the estimation was
|
||||
not accurate, then we'll reserve 2*AUTO_INC_DEFAULT_NB_ROWS the 2nd
|
||||
time, twice that the 3rd time etc.
|
||||
If no estimation was given, use those increasing defaults from the
|
||||
start, starting from AUTO_INC_DEFAULT_NB_ROWS.
|
||||
Don't go beyond a max to not reserve "way too much" (because
|
||||
reservation means potentially losing unused values).
|
||||
*/
|
||||
if (nb_already_reserved_intervals == 0 &&
|
||||
(estimation_rows_to_insert > 0))
|
||||
nb_desired_values= estimation_rows_to_insert;
|
||||
else /* go with the increasing defaults */
|
||||
{
|
||||
/* avoid overflow in formula, with this if() */
|
||||
if (nb_already_reserved_intervals <= AUTO_INC_DEFAULT_NB_MAX_BITS)
|
||||
{
|
||||
nb_desired_values= AUTO_INC_DEFAULT_NB_ROWS *
|
||||
(1 << nb_already_reserved_intervals);
|
||||
set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
|
||||
}
|
||||
else
|
||||
nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
|
||||
}
|
||||
/* This call ignores all its parameters but nr, currently */
|
||||
get_auto_increment(variables->auto_increment_offset,
|
||||
variables->auto_increment_increment,
|
||||
nb_desired_values, &nr,
|
||||
&nb_reserved_values);
|
||||
if (nr == ~(ulonglong) 0)
|
||||
result= 1; // Mark failure
|
||||
|
||||
/*
|
||||
That rounding below should not be needed when all engines actually
|
||||
respect offset and increment in get_auto_increment(). But they don't
|
||||
so we still do it. Wonder if for the not-first-in-index we should do
|
||||
it. Hope that this rounding didn't push us out of the interval; even
|
||||
if it did we cannot do anything about it (calling the engine again
|
||||
will not help as we inserted no row).
|
||||
*/
|
||||
nr= compute_next_insert_id(nr-1, variables);
|
||||
}
|
||||
|
||||
if (table->s->next_number_key_offset == 0)
|
||||
{
|
||||
/* We must defer the appending until "nr" has been possibly truncated */
|
||||
append= TRUE;
|
||||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
For such auto_increment there is no notion of interval, just a
|
||||
singleton. The interval is not even stored in
|
||||
thd->auto_inc_interval_for_cur_row, so we are sure to call the engine
|
||||
for next row.
|
||||
*/
|
||||
DBUG_PRINT("info",("auto_increment: special not-first-in-index"));
|
||||
}
|
||||
}
|
||||
|
||||
DBUG_PRINT("info",("auto_increment: %lu", (ulong) nr));
|
||||
|
||||
/* Mark that we should clear next_insert_id before next stmt */
|
||||
thd->clear_next_insert_id= 1;
|
||||
|
||||
if (!table->next_number_field->store((longlong) nr, TRUE))
|
||||
thd->insert_id((ulonglong) nr);
|
||||
else
|
||||
thd->insert_id(table->next_number_field->val_int());
|
||||
|
||||
/*
|
||||
We can't set next_insert_id if the auto-increment key is not the
|
||||
first key part, as there is no guarantee that the first parts will be in
|
||||
sequence
|
||||
*/
|
||||
if (!table->s->next_number_key_offset)
|
||||
if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
|
||||
{
|
||||
/*
|
||||
Set next insert id to point to next auto-increment value to be able to
|
||||
handle multi-row statements
|
||||
This works even if auto_increment_increment > 1
|
||||
field refused this value (overflow) and truncated it, use the result of
|
||||
the truncation (which is going to be inserted); however we try to
|
||||
decrease it to honour auto_increment_* variables.
|
||||
That will shift the left bound of the reserved interval, we don't
|
||||
bother shifting the right bound (anyway any other value from this
|
||||
interval will cause a duplicate key).
|
||||
*/
|
||||
thd->next_insert_id= next_insert_id(nr, variables);
|
||||
nr= prev_insert_id(table->next_number_field->val_int(), variables);
|
||||
if (unlikely(table->next_number_field->store((longlong) nr, TRUE)))
|
||||
nr= table->next_number_field->val_int();
|
||||
}
|
||||
if (append)
|
||||
{
|
||||
auto_inc_interval_for_cur_row.replace(nr, nb_reserved_values,
|
||||
variables->auto_increment_increment);
|
||||
/* Row-based replication does not need to store intervals in binlog */
|
||||
if (!thd->current_stmt_binlog_row_based)
|
||||
result= result ||
|
||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog.append(auto_inc_interval_for_cur_row.minimum(),
|
||||
auto_inc_interval_for_cur_row.values(),
|
||||
variables->auto_increment_increment);
|
||||
}
|
||||
else
|
||||
thd->next_insert_id= 0;
|
||||
|
||||
/* Mark that we generated a new value */
|
||||
auto_increment_column_changed=1;
|
||||
/*
|
||||
Record this autogenerated value. If the caller then
|
||||
succeeds to insert this value, it will call
|
||||
record_first_successful_insert_id_in_cur_stmt()
|
||||
which will set first_successful_insert_id_in_cur_stmt if it's not
|
||||
already set.
|
||||
*/
|
||||
insert_id_for_cur_row= nr;
|
||||
/*
|
||||
Set next insert id to point to next auto-increment value to be able to
|
||||
handle multi-row statements.
|
||||
*/
|
||||
set_next_insert_id(compute_next_insert_id(nr, variables));
|
||||
|
||||
DBUG_RETURN(result);
|
||||
}
|
||||
|
||||
/*
|
||||
restore_auto_increment
|
||||
|
||||
In case of error on write, we restore the last used next_insert_id value
|
||||
because the previous value was not used.
|
||||
*/
|
||||
|
||||
void handler::restore_auto_increment()
|
||||
{
|
||||
THD *thd= table->in_use;
|
||||
if (thd->next_insert_id)
|
||||
thd->next_insert_id= thd->prev_insert_id;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
MySQL signal that it changed the column bitmap
|
||||
|
@ -1840,6 +1919,23 @@ void handler::get_auto_increment(ulonglong offset, ulonglong increment,
|
|||
}
|
||||
|
||||
|
||||
void handler::ha_release_auto_increment()
|
||||
{
|
||||
release_auto_increment();
|
||||
insert_id_for_cur_row= 0;
|
||||
auto_inc_interval_for_cur_row.replace(0, 0, 0);
|
||||
if (next_insert_id > 0)
|
||||
{
|
||||
next_insert_id= 0;
|
||||
/*
|
||||
this statement used forced auto_increment values if there were some,
|
||||
wipe them away for other statements.
|
||||
*/
|
||||
table->in_use->auto_inc_intervals_forced.empty();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void handler::print_keydup_error(uint key_nr, const char *msg)
|
||||
{
|
||||
/* Write the duplicated key in the error message */
|
||||
|
@ -3369,10 +3465,13 @@ namespace
|
|||
int handler::ha_external_lock(THD *thd, int lock_type)
|
||||
{
|
||||
DBUG_ENTER("handler::ha_external_lock");
|
||||
int error;
|
||||
if (unlikely(error= external_lock(thd, lock_type)))
|
||||
DBUG_RETURN(error);
|
||||
DBUG_RETURN(0);
|
||||
/*
|
||||
Whether this is lock or unlock, this should be true, and is to verify that
|
||||
if get_auto_increment() was called (thus may have reserved intervals or
|
||||
taken a table lock), ha_release_auto_increment() was too.
|
||||
*/
|
||||
DBUG_ASSERT(next_insert_id == 0);
|
||||
DBUG_RETURN(external_lock(thd, lock_type));
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -906,16 +906,37 @@ public:
|
|||
uint ref_length;
|
||||
FT_INFO *ft_handler;
|
||||
enum {NONE=0, INDEX, RND} inited;
|
||||
bool auto_increment_column_changed;
|
||||
bool implicit_emptied; /* Can be !=0 only if HEAP */
|
||||
const COND *pushed_cond;
|
||||
/*
|
||||
next_insert_id is the next value which should be inserted into the
|
||||
auto_increment column: in a inserting-multi-row statement (like INSERT
|
||||
SELECT), for the first row where the autoinc value is not specified by the
|
||||
statement, get_auto_increment() called and asked to generate a value,
|
||||
next_insert_id is set to the next value, then for all other rows
|
||||
next_insert_id is used (and increased each time) without calling
|
||||
get_auto_increment().
|
||||
*/
|
||||
ulonglong next_insert_id;
|
||||
/*
|
||||
insert id for the current row (*autogenerated*; if not
|
||||
autogenerated, it's 0).
|
||||
At first successful insertion, this variable is stored into
|
||||
THD::first_successful_insert_id_in_cur_stmt.
|
||||
*/
|
||||
ulonglong insert_id_for_cur_row;
|
||||
/*
|
||||
Interval returned by get_auto_increment() and being consumed by the
|
||||
inserter.
|
||||
*/
|
||||
Discrete_interval auto_inc_interval_for_cur_row;
|
||||
|
||||
handler(const handlerton *ht_arg, TABLE_SHARE *share_arg)
|
||||
:table_share(share_arg), estimation_rows_to_insert(0), ht(ht_arg),
|
||||
ref(0), key_used_on_scan(MAX_KEY), active_index(MAX_KEY),
|
||||
ref_length(sizeof(my_off_t)),
|
||||
ft_handler(0), inited(NONE), implicit_emptied(0),
|
||||
pushed_cond(NULL)
|
||||
pushed_cond(NULL), next_insert_id(0), insert_id_for_cur_row(0)
|
||||
{}
|
||||
virtual ~handler(void)
|
||||
{
|
||||
|
@ -954,6 +975,7 @@ public:
|
|||
return TRUE;
|
||||
}
|
||||
int ha_open(TABLE *table, const char *name, int mode, int test_if_locked);
|
||||
void adjust_next_insert_id_after_explicit_value(ulonglong nr);
|
||||
bool update_auto_increment();
|
||||
void print_keydup_error(uint key_nr, const char *msg);
|
||||
virtual void print_error(int error, myf errflag);
|
||||
|
@ -1247,9 +1269,30 @@ public:
|
|||
ulonglong nb_desired_values,
|
||||
ulonglong *first_value,
|
||||
ulonglong *nb_reserved_values);
|
||||
private:
|
||||
virtual void release_auto_increment() { return; };
|
||||
virtual void restore_auto_increment();
|
||||
|
||||
public:
|
||||
void ha_release_auto_increment();
|
||||
void set_next_insert_id(ulonglong id)
|
||||
{
|
||||
DBUG_PRINT("info",("auto_increment: next value %lu", (ulong)id));
|
||||
next_insert_id= id;
|
||||
}
|
||||
void restore_auto_increment(ulonglong prev_insert_id)
|
||||
{
|
||||
/*
|
||||
Insertion of a row failed, re-use the lastly generated auto_increment
|
||||
id, for the next row. This is achieved by resetting next_insert_id to
|
||||
what it was before the failed insertion (that old value is provided by
|
||||
the caller). If that value was 0, it was the first row of the INSERT;
|
||||
then if insert_id_for_cur_row contains 0 it means no id was generated
|
||||
for this first row, so no id was generated since the INSERT started, so
|
||||
we should set next_insert_id to 0; if insert_id_for_cur_row is not 0, it
|
||||
is the generated id of the first and failed row, so we use it.
|
||||
*/
|
||||
next_insert_id= (prev_insert_id > 0) ? prev_insert_id :
|
||||
insert_id_for_cur_row;
|
||||
}
|
||||
/*
|
||||
Reset the auto-increment counter to the given value, i.e. the next row
|
||||
inserted will get the given value. This is called e.g. after TRUNCATE
|
||||
|
|
|
@ -426,7 +426,9 @@ Item *create_func_unhex(Item* a)
|
|||
Item *create_func_uuid(void)
|
||||
{
|
||||
THD *thd= current_thd;
|
||||
thd->lex->binlog_row_based_if_mixed= 1;
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
thd->lex->binlog_row_based_if_mixed= TRUE;
|
||||
#endif
|
||||
return new(thd->mem_root) Item_func_uuid();
|
||||
}
|
||||
|
||||
|
|
|
@ -3283,12 +3283,20 @@ longlong Item_func_last_insert_id::val_int()
|
|||
if (arg_count)
|
||||
{
|
||||
longlong value= args[0]->val_int();
|
||||
thd->insert_id(value);
|
||||
null_value= args[0]->null_value;
|
||||
return value; // Avoid side effect of insert_id()
|
||||
/*
|
||||
LAST_INSERT_ID(X) must affect the client's mysql_insert_id() as
|
||||
documented in the manual. We don't want to touch
|
||||
first_successful_insert_id_in_cur_stmt because it would make
|
||||
LAST_INSERT_ID(X) take precedence over an generated auto_increment
|
||||
value for this row.
|
||||
*/
|
||||
thd->arg_of_last_insert_id_function= TRUE;
|
||||
thd->first_successful_insert_id_in_prev_stmt= value;
|
||||
return value;
|
||||
}
|
||||
thd->lex->uncacheable(UNCACHEABLE_SIDEEFFECT);
|
||||
return thd->last_insert_id_used ? thd->current_insert_id : thd->insert_id();
|
||||
return thd->read_first_successful_insert_id_in_prev_stmt();
|
||||
}
|
||||
|
||||
/* This function is just used to test speed of different functions */
|
||||
|
|
51
sql/log.cc
51
sql/log.cc
|
@ -432,16 +432,23 @@ bool Log_to_csv_event_handler::
|
|||
table->field[6]->set_notnull();
|
||||
}
|
||||
|
||||
if (thd->last_insert_id_used)
|
||||
if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
|
||||
{
|
||||
table->field[7]->store((longlong) thd->current_insert_id, TRUE);
|
||||
table->field[7]->store((longlong)
|
||||
thd->first_successful_insert_id_in_prev_stmt_for_binlog, TRUE);
|
||||
table->field[7]->set_notnull();
|
||||
}
|
||||
|
||||
/* set value if we do an insert on autoincrement column */
|
||||
if (thd->insert_id_used)
|
||||
/*
|
||||
Set value if we do an insert on autoincrement column. Note that for
|
||||
some engines (those for which get_auto_increment() does not leave a
|
||||
table lock until the statement ends), this is just the first value and
|
||||
the next ones used may not be contiguous to it.
|
||||
*/
|
||||
if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
|
||||
{
|
||||
table->field[8]->store((longlong) thd->last_insert_id, TRUE);
|
||||
table->field[8]->store((longlong)
|
||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum(), TRUE);
|
||||
table->field[8]->set_notnull();
|
||||
}
|
||||
|
||||
|
@ -731,7 +738,6 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
|
|||
Security_context *sctx= thd->security_ctx;
|
||||
uint message_buff_len= 0, user_host_len= 0;
|
||||
longlong query_time= 0, lock_time= 0;
|
||||
longlong last_insert_id= 0, insert_id= 0;
|
||||
|
||||
/*
|
||||
Print the message to the buffer if we have slow log enabled
|
||||
|
@ -766,13 +772,6 @@ bool LOGGER::slow_log_print(THD *thd, const char *query, uint query_length,
|
|||
lock_time= (longlong) (thd->time_after_lock - query_start_arg);
|
||||
}
|
||||
|
||||
if (thd->last_insert_id_used)
|
||||
last_insert_id= (longlong) thd->current_insert_id;
|
||||
|
||||
/* set value if we do an insert on autoincrement column */
|
||||
if (thd->insert_id_used)
|
||||
insert_id= (longlong) thd->last_insert_id;
|
||||
|
||||
if (!query)
|
||||
{
|
||||
is_command= TRUE;
|
||||
|
@ -1931,18 +1930,22 @@ bool MYSQL_QUERY_LOG::write(THD *thd, time_t current_time,
|
|||
tmp_errno= errno;
|
||||
strmov(db,thd->db);
|
||||
}
|
||||
if (thd->last_insert_id_used)
|
||||
if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
|
||||
{
|
||||
end=strmov(end, ",last_insert_id=");
|
||||
end=longlong10_to_str((longlong) thd->current_insert_id, end, -10);
|
||||
end=longlong10_to_str((longlong)
|
||||
thd->first_successful_insert_id_in_prev_stmt_for_binlog,
|
||||
end, -10);
|
||||
}
|
||||
// Save value if we do an insert.
|
||||
if (thd->insert_id_used)
|
||||
if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
|
||||
{
|
||||
if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT))
|
||||
{
|
||||
end=strmov(end,",insert_id=");
|
||||
end=longlong10_to_str((longlong) thd->last_insert_id, end, -10);
|
||||
end=longlong10_to_str((longlong)
|
||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum(),
|
||||
end, -10);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -3363,21 +3366,24 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
|
|||
{
|
||||
if (!thd->current_stmt_binlog_row_based)
|
||||
{
|
||||
if (thd->last_insert_id_used)
|
||||
if (thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt)
|
||||
{
|
||||
Intvar_log_event e(thd,(uchar) LAST_INSERT_ID_EVENT,
|
||||
thd->current_insert_id);
|
||||
thd->first_successful_insert_id_in_prev_stmt_for_binlog);
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
if (thd->insert_id_used)
|
||||
if (thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements() > 0)
|
||||
{
|
||||
DBUG_PRINT("info",("number of auto_inc intervals: %lu",
|
||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog.nb_elements()));
|
||||
/*
|
||||
If the auto_increment was second in a table's index (possible with
|
||||
MyISAM or BDB) (table->next_number_key_offset != 0), such event is
|
||||
in fact not necessary. We could avoid logging it.
|
||||
*/
|
||||
Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,thd->last_insert_id);
|
||||
Intvar_log_event e(thd,(uchar) INSERT_ID_EVENT,
|
||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog.minimum());
|
||||
if (e.write(file))
|
||||
goto err;
|
||||
}
|
||||
|
@ -3404,6 +3410,9 @@ bool MYSQL_BIN_LOG::write(Log_event *event_info)
|
|||
}
|
||||
}
|
||||
}
|
||||
/* Forget those values, for next binlogger: */
|
||||
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
|
||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty();
|
||||
}
|
||||
|
||||
/*
|
||||
|
|
|
@ -1934,6 +1934,16 @@ end:
|
|||
thd->query_length= 0;
|
||||
VOID(pthread_mutex_unlock(&LOCK_thread_count));
|
||||
close_thread_tables(thd);
|
||||
/*
|
||||
As a disk space optimization, future masters will not log an event for
|
||||
LAST_INSERT_ID() if that function returned 0 (and thus they will be able
|
||||
to replace the THD::stmt_depends_on_first_successful_insert_id_in_prev_stmt
|
||||
variable by (THD->first_successful_insert_id_in_prev_stmt > 0) ; with the
|
||||
resetting below we are ready to support that.
|
||||
*/
|
||||
thd->first_successful_insert_id_in_prev_stmt_for_binlog= 0;
|
||||
thd->first_successful_insert_id_in_prev_stmt= 0;
|
||||
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 0;
|
||||
free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
|
||||
/*
|
||||
If there was an error we stop. Otherwise we increment positions. Note that
|
||||
|
@ -3425,11 +3435,11 @@ int Intvar_log_event::exec_event(struct st_relay_log_info* rli)
|
|||
{
|
||||
switch (type) {
|
||||
case LAST_INSERT_ID_EVENT:
|
||||
thd->last_insert_id_used = 1;
|
||||
thd->last_insert_id = val;
|
||||
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;
|
||||
thd->first_successful_insert_id_in_prev_stmt= val;
|
||||
break;
|
||||
case INSERT_ID_EVENT:
|
||||
thd->next_insert_id = val;
|
||||
thd->force_one_auto_inc_interval(val);
|
||||
break;
|
||||
}
|
||||
rli->inc_event_relay_log_pos();
|
||||
|
@ -5353,10 +5363,10 @@ int Rows_log_event::exec_event(st_relay_log_info *rli)
|
|||
|
||||
/*
|
||||
lock_tables() reads the contents of thd->lex, so they must be
|
||||
initialized, so we should call lex_start(); to be even safer, we
|
||||
call mysql_init_query() which does a more complete set of inits.
|
||||
initialized. Contrary to in Table_map_log_event::exec_event() we don't
|
||||
call mysql_init_query() as that may reset the binlog format.
|
||||
*/
|
||||
mysql_init_query(thd, NULL, 0);
|
||||
lex_start(thd, NULL, 0);
|
||||
|
||||
while ((error= lock_tables(thd, rli->tables_to_lock,
|
||||
rli->tables_to_lock_count, &need_reopen)))
|
||||
|
@ -5859,6 +5869,12 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
|
|||
}
|
||||
else
|
||||
{
|
||||
/*
|
||||
open_tables() reads the contents of thd->lex, so they must be
|
||||
initialized, so we should call lex_start(); to be even safer, we
|
||||
call mysql_init_query() which does a more complete set of inits.
|
||||
*/
|
||||
mysql_init_query(thd, NULL, 0);
|
||||
/*
|
||||
Check if the slave is set to use SBR. If so, it should switch
|
||||
to using RBR until the end of the "statement", i.e., next
|
||||
|
@ -5875,12 +5891,6 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli)
|
|||
Note that for any table that should not be replicated, a filter is needed.
|
||||
*/
|
||||
uint count;
|
||||
/*
|
||||
open_tables() reads the contents of thd->lex, so they must be
|
||||
initialized, so we should call lex_start(); to be even safer, we
|
||||
call mysql_init_query() which does a more complete set of inits.
|
||||
*/
|
||||
mysql_init_query(thd, NULL, 0);
|
||||
if ((error= open_tables(thd, &table_list, &count, 0)))
|
||||
{
|
||||
if (thd->query_error || thd->is_fatal_error)
|
||||
|
|
|
@ -1971,6 +1971,17 @@ inline int hexchar_to_int(char c)
|
|||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
is_user_table()
|
||||
return true if the table was created explicitly
|
||||
*/
|
||||
|
||||
inline bool is_user_table(TABLE * table)
|
||||
{
|
||||
const char *name= table->s->table_name.str;
|
||||
return strncmp(name, tmp_file_prefix, tmp_file_prefix_length);
|
||||
}
|
||||
|
||||
/*
|
||||
Some functions that are different in the embedded library and the normal
|
||||
server
|
||||
|
|
|
@ -1343,9 +1343,9 @@ bool sys_var_thd_binlog_format::is_readonly() const
|
|||
return 1;
|
||||
}
|
||||
/*
|
||||
if in a stored function, it's too late to change mode
|
||||
if in a stored function/trigger, it's too late to change mode
|
||||
*/
|
||||
if (thd->spcont && thd->prelocked_mode)
|
||||
if (thd->in_sub_stmt)
|
||||
{
|
||||
my_error(ER_STORED_FUNCTION_PREVENTS_SWITCH_BINLOG_FORMAT, MYF(0));
|
||||
return 1;
|
||||
|
@ -2794,7 +2794,8 @@ byte *sys_var_timestamp::value_ptr(THD *thd, enum_var_type type,
|
|||
|
||||
bool sys_var_last_insert_id::update(THD *thd, set_var *var)
|
||||
{
|
||||
thd->insert_id(var->save_result.ulonglong_value);
|
||||
thd->first_successful_insert_id_in_prev_stmt=
|
||||
var->save_result.ulonglong_value;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2802,14 +2803,19 @@ bool sys_var_last_insert_id::update(THD *thd, set_var *var)
|
|||
byte *sys_var_last_insert_id::value_ptr(THD *thd, enum_var_type type,
|
||||
LEX_STRING *base)
|
||||
{
|
||||
thd->sys_var_tmp.long_value= (long) thd->insert_id();
|
||||
return (byte*) &thd->last_insert_id;
|
||||
/*
|
||||
this tmp var makes it robust againt change of type of
|
||||
read_first_successful_insert_id_in_prev_stmt().
|
||||
*/
|
||||
thd->sys_var_tmp.ulonglong_value=
|
||||
thd->read_first_successful_insert_id_in_prev_stmt();
|
||||
return (byte*) &thd->sys_var_tmp.ulonglong_value;
|
||||
}
|
||||
|
||||
|
||||
bool sys_var_insert_id::update(THD *thd, set_var *var)
|
||||
{
|
||||
thd->next_insert_id= var->save_result.ulonglong_value;
|
||||
thd->force_one_auto_inc_interval(var->save_result.ulonglong_value);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2817,7 +2823,9 @@ bool sys_var_insert_id::update(THD *thd, set_var *var)
|
|||
byte *sys_var_insert_id::value_ptr(THD *thd, enum_var_type type,
|
||||
LEX_STRING *base)
|
||||
{
|
||||
return (byte*) &thd->next_insert_id;
|
||||
thd->sys_var_tmp.ulonglong_value=
|
||||
thd->auto_inc_intervals_forced.minimum();
|
||||
return (byte*) &thd->sys_var_tmp.ulonglong_value;
|
||||
}
|
||||
|
||||
|
||||
|
|
1087
sql/slave.cc
1087
sql/slave.cc
File diff suppressed because it is too large
Load diff
13
sql/sp.cc
13
sql/sp.cc
|
@ -1630,6 +1630,7 @@ sp_cache_routines_and_add_tables_aux(THD *thd, LEX *lex,
|
|||
sp->add_used_tables_to_table_list(thd, &lex->query_tables_last,
|
||||
rt->belong_to_view);
|
||||
}
|
||||
sp->propagate_attributes(lex);
|
||||
}
|
||||
first= FALSE;
|
||||
}
|
||||
|
@ -1727,14 +1728,16 @@ sp_cache_routines_and_add_tables_for_triggers(THD *thd, LEX *lex,
|
|||
{
|
||||
for (int j= 0; j < (int)TRG_ACTION_MAX; j++)
|
||||
{
|
||||
if (triggers->bodies[i][j])
|
||||
sp_head *trigger_body= triggers->bodies[i][j];
|
||||
if (trigger_body)
|
||||
{
|
||||
(void)triggers->bodies[i][j]->
|
||||
add_used_tables_to_table_list(thd, &lex->query_tables_last,
|
||||
table->belong_to_view);
|
||||
(void)trigger_body->
|
||||
add_used_tables_to_table_list(thd, &lex->query_tables_last,
|
||||
table->belong_to_view);
|
||||
sp_update_stmt_used_routines(thd, lex,
|
||||
&triggers->bodies[i][j]->m_sroutines,
|
||||
&trigger_body->m_sroutines,
|
||||
table->belong_to_view);
|
||||
trigger_body->propagate_attributes(lex);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1661,6 +1661,16 @@ sp_head::restore_lex(THD *thd)
|
|||
oldlex->next_state= sublex->next_state;
|
||||
oldlex->trg_table_fields.push_back(&sublex->trg_table_fields);
|
||||
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
/*
|
||||
If this substatement needs row-based, the entire routine does too (we
|
||||
cannot switch from statement-based to row-based only for this
|
||||
substatement).
|
||||
*/
|
||||
if (sublex->binlog_row_based_if_mixed)
|
||||
m_flags|= BINLOG_ROW_BASED_IF_MIXED;
|
||||
#endif
|
||||
|
||||
/*
|
||||
Add routines which are used by statement to respective set for
|
||||
this routine.
|
||||
|
|
|
@ -117,7 +117,8 @@ public:
|
|||
/* Is set if a procedure with COMMIT (implicit or explicit) | ROLLBACK */
|
||||
HAS_COMMIT_OR_ROLLBACK= 128,
|
||||
LOG_SLOW_STATEMENTS= 256, // Used by events
|
||||
LOG_GENERAL_LOG= 512 // Used by events
|
||||
LOG_GENERAL_LOG= 512, // Used by events
|
||||
BINLOG_ROW_BASED_IF_MIXED= 1024
|
||||
};
|
||||
|
||||
/* TYPE_ENUM_FUNCTION, TYPE_ENUM_PROCEDURE or TYPE_ENUM_TRIGGER */
|
||||
|
@ -342,6 +343,25 @@ public:
|
|||
int show_routine_code(THD *thd);
|
||||
#endif
|
||||
|
||||
/*
|
||||
This method is intended for attributes of a routine which need
|
||||
to propagate upwards to the LEX of the caller (when a property of a
|
||||
sp_head needs to "taint" the caller).
|
||||
*/
|
||||
void propagate_attributes(LEX *lex)
|
||||
{
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
/*
|
||||
If this routine needs row-based binary logging, the entire top statement
|
||||
too (we cannot switch from statement-based to row-based only for this
|
||||
routine, as in statement-based the top-statement may be binlogged and
|
||||
the substatements not).
|
||||
*/
|
||||
if (m_flags & BINLOG_ROW_BASED_IF_MIXED)
|
||||
lex->binlog_row_based_if_mixed= TRUE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
|
|
243
sql/sql_base.cc
243
sql/sql_base.cc
|
@ -49,6 +49,8 @@ static bool open_new_frm(THD *thd, TABLE_SHARE *share, const char *alias,
|
|||
static void close_old_data_files(THD *thd, TABLE *table, bool abort_locks,
|
||||
bool send_refresh);
|
||||
static bool reopen_table(TABLE *table);
|
||||
static bool
|
||||
has_two_write_locked_tables_with_auto_increment(TABLE_LIST *tables);
|
||||
|
||||
|
||||
extern "C" byte *table_cache_key(const byte *record,uint *length,
|
||||
|
@ -1179,135 +1181,134 @@ static inline uint tmpkeyval(THD *thd, TABLE *table)
|
|||
|
||||
void close_temporary_tables(THD *thd)
|
||||
{
|
||||
TABLE *next, *prev_table, *table;
|
||||
char *query= 0, *end;
|
||||
uint query_buf_size, max_names_len;
|
||||
bool found_user_tables;
|
||||
|
||||
TABLE *table;
|
||||
if (!thd->temporary_tables)
|
||||
return;
|
||||
|
||||
LINT_INIT(end);
|
||||
query_buf_size= 50; // Enough for DROP ... TABLE IF EXISTS
|
||||
|
||||
/*
|
||||
insertion sort of temp tables by pseudo_thread_id to build ordered list
|
||||
if (!mysql_bin_log.is_open() || thd->current_stmt_binlog_row_based)
|
||||
{
|
||||
TABLE *next;
|
||||
for (table= thd->temporary_tables; table; table= next)
|
||||
{
|
||||
next=table->next;
|
||||
close_temporary(table, 1, 1);
|
||||
}
|
||||
thd->temporary_tables= 0;
|
||||
return;
|
||||
}
|
||||
|
||||
TABLE *next,
|
||||
*prev_table /* TODO: 5.1 maintaines prev link in temporary_tables
|
||||
double-linked list so we could fix it. But it is not necessary
|
||||
at this time when the list is being destroyed */;
|
||||
bool was_quote_show= true; /* to assume thd->options has OPTION_QUOTE_SHOW_CREATE */
|
||||
// Better add "if exists", in case a RESET MASTER has been done
|
||||
const char stub[]= "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ";
|
||||
uint stub_len= sizeof(stub) - 1;
|
||||
char buf[256];
|
||||
memcpy(buf, stub, stub_len);
|
||||
String s_query= String(buf, sizeof(buf), system_charset_info);
|
||||
bool found_user_tables= false;
|
||||
LINT_INIT(next);
|
||||
|
||||
/*
|
||||
insertion sort of temp tables by pseudo_thread_id to build ordered list
|
||||
of sublists of equal pseudo_thread_id
|
||||
*/
|
||||
for (prev_table= thd->temporary_tables,
|
||||
table= prev_table->next,
|
||||
found_user_tables= (prev_table->s->table_name.str[0] != '#');
|
||||
|
||||
for (prev_table= thd->temporary_tables, table= prev_table->next;
|
||||
table;
|
||||
prev_table= table, table= table->next)
|
||||
{
|
||||
TABLE *prev_sorted /* same as for prev_table */,
|
||||
*sorted;
|
||||
/*
|
||||
table not created directly by the user is moved to the tail.
|
||||
Fixme/todo: nothing (I checked the manual) prevents user to create temp
|
||||
with `#'
|
||||
*/
|
||||
if (table->s->table_name.str[0] == '#')
|
||||
continue;
|
||||
else
|
||||
TABLE *prev_sorted /* same as for prev_table */, *sorted;
|
||||
if (is_user_table(table))
|
||||
{
|
||||
found_user_tables = 1;
|
||||
}
|
||||
for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table;
|
||||
prev_sorted= sorted, sorted= sorted->next)
|
||||
{
|
||||
if (sorted->s->table_name.str[0] == '#' || tmpkeyval(thd, sorted) > tmpkeyval(thd, table))
|
||||
if (!found_user_tables)
|
||||
found_user_tables= true;
|
||||
for (prev_sorted= NULL, sorted= thd->temporary_tables; sorted != table;
|
||||
prev_sorted= sorted, sorted= sorted->next)
|
||||
{
|
||||
/* move into the sorted part of the list from the unsorted */
|
||||
prev_table->next= table->next;
|
||||
table->next= sorted;
|
||||
if (prev_sorted)
|
||||
if (!is_user_table(sorted) ||
|
||||
tmpkeyval(thd, sorted) > tmpkeyval(thd, table))
|
||||
{
|
||||
prev_sorted->next= table;
|
||||
/* move into the sorted part of the list from the unsorted */
|
||||
prev_table->next= table->next;
|
||||
table->next= sorted;
|
||||
if (prev_sorted)
|
||||
{
|
||||
prev_sorted->next= table;
|
||||
}
|
||||
else
|
||||
{
|
||||
thd->temporary_tables= table;
|
||||
}
|
||||
table= prev_table;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
thd->temporary_tables= table;
|
||||
}
|
||||
table= prev_table;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
calc query_buf_size as max per sublists, one sublist per pseudo thread id.
|
||||
Also stop at first occurence of `#'-named table that starts
|
||||
all implicitly created temp tables
|
||||
*/
|
||||
for (max_names_len= 0, table=thd->temporary_tables;
|
||||
table && table->s->table_name.str[0] != '#';
|
||||
table=table->next)
|
||||
{
|
||||
uint tmp_names_len;
|
||||
for (tmp_names_len= table->s->table_cache_key.length + 1;
|
||||
table->next && table->s->table_name.str[0] != '#' &&
|
||||
tmpkeyval(thd, table) == tmpkeyval(thd, table->next);
|
||||
table=table->next)
|
||||
{
|
||||
/*
|
||||
We are going to add 4 ` around the db/table names, so 1 might not look
|
||||
enough; indeed it is enough, because table->s->table_cache_key.length is
|
||||
greater (by 8, because of server_id and thread_id) than db||table.
|
||||
*/
|
||||
tmp_names_len += table->next->s->table_cache_key.length + 1;
|
||||
}
|
||||
if (tmp_names_len > max_names_len) max_names_len= tmp_names_len;
|
||||
}
|
||||
|
||||
/* allocate */
|
||||
if (found_user_tables && mysql_bin_log.is_open() &&
|
||||
!thd->current_stmt_binlog_row_based &&
|
||||
(query = alloc_root(thd->mem_root, query_buf_size+= max_names_len)))
|
||||
// Better add "if exists", in case a RESET MASTER has been done
|
||||
end= strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ");
|
||||
|
||||
/* We always quote db,table names though it is slight overkill */
|
||||
if (found_user_tables &&
|
||||
!(was_quote_show= (thd->options & OPTION_QUOTE_SHOW_CREATE)))
|
||||
{
|
||||
thd->options |= OPTION_QUOTE_SHOW_CREATE;
|
||||
}
|
||||
|
||||
/* scan sorted tmps to generate sequence of DROP */
|
||||
for (table=thd->temporary_tables; table; table= next)
|
||||
for (table= thd->temporary_tables; table; table= next)
|
||||
{
|
||||
if (query // we might be out of memory, but this is not fatal
|
||||
&& table->s->table_name.str[0] != '#')
|
||||
if (is_user_table(table))
|
||||
{
|
||||
char *end_cur;
|
||||
/* Set pseudo_thread_id to be that of the processed table */
|
||||
thd->variables.pseudo_thread_id= tmpkeyval(thd, table);
|
||||
/* Loop forward through all tables within the sublist of
|
||||
common pseudo_thread_id to create single DROP query */
|
||||
for (end_cur= end;
|
||||
table && table->s->table_name.str[0] != '#' &&
|
||||
for (s_query.length(stub_len);
|
||||
table && is_user_table(table) &&
|
||||
tmpkeyval(thd, table) == thd->variables.pseudo_thread_id;
|
||||
table= next)
|
||||
{
|
||||
end_cur= strxmov(end_cur, "`", table->s->db.str, "`.`",
|
||||
table->s->table_name.str, "`,", NullS);
|
||||
/*
|
||||
We are going to add 4 ` around the db/table names and possible more
|
||||
due to special characters in the names
|
||||
*/
|
||||
append_identifier(thd, &s_query, table->s->db.str, strlen(table->s->db.str));
|
||||
s_query.q_append('.');
|
||||
append_identifier(thd, &s_query, table->s->table_name.str,
|
||||
strlen(table->s->table_name.str));
|
||||
s_query.q_append(',');
|
||||
next= table->next;
|
||||
close_temporary(table, 1, 1);
|
||||
}
|
||||
thd->clear_error();
|
||||
/* The -1 is to remove last ',' */
|
||||
Query_log_event qinfo(thd, query, (ulong)(end_cur - query) - 1, 0, FALSE);
|
||||
CHARSET_INFO *cs_save= thd->variables.character_set_client;
|
||||
thd->variables.character_set_client= system_charset_info;
|
||||
Query_log_event qinfo(thd, s_query.ptr(),
|
||||
s_query.length() - 1 /* to remove trailing ',' */,
|
||||
0, FALSE);
|
||||
thd->variables.character_set_client= cs_save;
|
||||
/*
|
||||
Imagine the thread had created a temp table, then was doing a SELECT,
|
||||
and the SELECT was killed. Then it's not clever to mark the statement
|
||||
above as "killed", because it's not really a statement updating data,
|
||||
and there are 99.99% chances it will succeed on slave. If a real update
|
||||
(one updating a persistent table) was killed on the master, then this
|
||||
real update will be logged with error_code=killed, rightfully causing
|
||||
the slave to stop.
|
||||
Imagine the thread had created a temp table, then was doing a SELECT, and
|
||||
the SELECT was killed. Then it's not clever to mark the statement above as
|
||||
"killed", because it's not really a statement updating data, and there
|
||||
are 99.99% chances it will succeed on slave.
|
||||
If a real update (one updating a persistent table) was killed on the
|
||||
master, then this real update will be logged with error_code=killed,
|
||||
rightfully causing the slave to stop.
|
||||
*/
|
||||
qinfo.error_code= 0;
|
||||
mysql_bin_log.write(&qinfo);
|
||||
}
|
||||
else
|
||||
else
|
||||
{
|
||||
next= table->next;
|
||||
close_temporary(table, 1, 1);
|
||||
}
|
||||
}
|
||||
if (!was_quote_show)
|
||||
thd->options &= ~OPTION_QUOTE_SHOW_CREATE; /* restore option */
|
||||
thd->temporary_tables=0;
|
||||
}
|
||||
|
||||
|
@ -3317,6 +3318,14 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
|
|||
|
||||
*need_reopen= FALSE;
|
||||
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
/*
|
||||
CREATE ... SELECT UUID() locks no tables, we have to test here.
|
||||
*/
|
||||
if (thd->lex->binlog_row_based_if_mixed)
|
||||
thd->set_current_stmt_binlog_row_based_if_mixed();
|
||||
#endif /*HAVE_ROW_BASED_REPLICATION*/
|
||||
|
||||
if (!tables)
|
||||
DBUG_RETURN(0);
|
||||
|
||||
|
@ -3347,6 +3356,19 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count, bool *need_reopen)
|
|||
{
|
||||
thd->in_lock_tables=1;
|
||||
thd->options|= OPTION_TABLE_LOCK;
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
/*
|
||||
If we have >= 2 different tables to update with auto_inc columns,
|
||||
statement-based binlogging won't work. We can solve this problem in
|
||||
mixed mode by switching to row-based binlogging:
|
||||
*/
|
||||
if (thd->variables.binlog_format == BINLOG_FORMAT_MIXED &&
|
||||
has_two_write_locked_tables_with_auto_increment(tables))
|
||||
{
|
||||
thd->lex->binlog_row_based_if_mixed= TRUE;
|
||||
thd->set_current_stmt_binlog_row_based_if_mixed();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (! (thd->lock= mysql_lock_tables(thd, start, (uint) (ptr - start),
|
||||
|
@ -6479,3 +6501,46 @@ void mysql_wait_completed_table(ALTER_PARTITION_PARAM_TYPE *lpt, TABLE *my_table
|
|||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Tells if two (or more) tables have auto_increment columns and we want to
|
||||
lock those tables with a write lock.
|
||||
|
||||
SYNOPSIS
|
||||
has_two_write_locked_tables_with_auto_increment
|
||||
tables Table list
|
||||
|
||||
NOTES:
|
||||
Call this function only when you have established the list of all tables
|
||||
which you'll want to update (including stored functions, triggers, views
|
||||
inside your statement).
|
||||
|
||||
RETURN
|
||||
0 No
|
||||
1 Yes
|
||||
*/
|
||||
|
||||
static bool
|
||||
has_two_write_locked_tables_with_auto_increment(TABLE_LIST *tables)
|
||||
{
|
||||
char *first_table_name= NULL, *first_db;
|
||||
for (TABLE_LIST *table= tables; table; table= table->next_global)
|
||||
{
|
||||
/* we must do preliminary checks as table->table may be NULL */
|
||||
if (!table->placeholder() && !table->schema_table &&
|
||||
table->table->found_next_number_field &&
|
||||
(table->lock_type >= TL_WRITE_ALLOW_WRITE))
|
||||
{
|
||||
if (first_table_name == NULL)
|
||||
{
|
||||
first_table_name= table->table_name;
|
||||
first_db= table->db;
|
||||
DBUG_ASSERT(first_db);
|
||||
}
|
||||
else if (strcmp(first_db, table->db) ||
|
||||
strcmp(first_table_name, table->table_name))
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -208,8 +208,12 @@ THD::THD()
|
|||
#endif /*HAVE_ROW_BASED_REPLICATION*/
|
||||
global_read_lock(0), is_fatal_error(0),
|
||||
rand_used(0), time_zone_used(0),
|
||||
last_insert_id_used(0), insert_id_used(0), clear_next_insert_id(0),
|
||||
arg_of_last_insert_id_function(FALSE),
|
||||
first_successful_insert_id_in_prev_stmt(0),
|
||||
first_successful_insert_id_in_prev_stmt_for_binlog(0),
|
||||
first_successful_insert_id_in_cur_stmt(0),
|
||||
in_lock_tables(0), bootstrap(0), derived_tables_processing(FALSE),
|
||||
stmt_depends_on_first_successful_insert_id_in_prev_stmt(FALSE),
|
||||
spcont(NULL)
|
||||
{
|
||||
stmt_arena= this;
|
||||
|
@ -224,7 +228,6 @@ THD::THD()
|
|||
killed= NOT_KILLED;
|
||||
db_length= col_access=0;
|
||||
query_error= tmp_table_used= 0;
|
||||
next_insert_id=last_insert_id=0;
|
||||
hash_clear(&handler_tables_hash);
|
||||
tmp_table=0;
|
||||
used_tables=0;
|
||||
|
@ -628,11 +631,14 @@ bool THD::store_globals()
|
|||
|
||||
void THD::cleanup_after_query()
|
||||
{
|
||||
if (clear_next_insert_id)
|
||||
if (first_successful_insert_id_in_cur_stmt > 0)
|
||||
{
|
||||
clear_next_insert_id= 0;
|
||||
next_insert_id= 0;
|
||||
/* set what LAST_INSERT_ID() will return */
|
||||
first_successful_insert_id_in_prev_stmt=
|
||||
first_successful_insert_id_in_cur_stmt;
|
||||
first_successful_insert_id_in_cur_stmt= 0;
|
||||
}
|
||||
arg_of_last_insert_id_function= 0;
|
||||
/* Free Items that were created during this execution */
|
||||
free_items();
|
||||
/* Reset where. */
|
||||
|
@ -2139,18 +2145,16 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
|||
backup->in_sub_stmt= in_sub_stmt;
|
||||
backup->no_send_ok= net.no_send_ok;
|
||||
backup->enable_slow_log= enable_slow_log;
|
||||
backup->last_insert_id= last_insert_id;
|
||||
backup->next_insert_id= next_insert_id;
|
||||
backup->current_insert_id= current_insert_id;
|
||||
backup->insert_id_used= insert_id_used;
|
||||
backup->last_insert_id_used= last_insert_id_used;
|
||||
backup->clear_next_insert_id= clear_next_insert_id;
|
||||
backup->limit_found_rows= limit_found_rows;
|
||||
backup->examined_row_count= examined_row_count;
|
||||
backup->sent_row_count= sent_row_count;
|
||||
backup->cuted_fields= cuted_fields;
|
||||
backup->client_capabilities= client_capabilities;
|
||||
backup->savepoints= transaction.savepoints;
|
||||
backup->first_successful_insert_id_in_prev_stmt=
|
||||
first_successful_insert_id_in_prev_stmt;
|
||||
backup->first_successful_insert_id_in_cur_stmt=
|
||||
first_successful_insert_id_in_cur_stmt;
|
||||
|
||||
if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) &&
|
||||
!current_stmt_binlog_row_based)
|
||||
|
@ -2160,12 +2164,11 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup,
|
|||
/* Disable result sets */
|
||||
client_capabilities &= ~CLIENT_MULTI_RESULTS;
|
||||
in_sub_stmt|= new_state;
|
||||
next_insert_id= 0;
|
||||
insert_id_used= 0;
|
||||
examined_row_count= 0;
|
||||
sent_row_count= 0;
|
||||
cuted_fields= 0;
|
||||
transaction.savepoints= 0;
|
||||
first_successful_insert_id_in_cur_stmt= 0;
|
||||
|
||||
/* Surpress OK packets in case if we will execute statements */
|
||||
net.no_send_ok= TRUE;
|
||||
|
@ -2193,12 +2196,10 @@ void THD::restore_sub_statement_state(Sub_statement_state *backup)
|
|||
in_sub_stmt= backup->in_sub_stmt;
|
||||
net.no_send_ok= backup->no_send_ok;
|
||||
enable_slow_log= backup->enable_slow_log;
|
||||
last_insert_id= backup->last_insert_id;
|
||||
next_insert_id= backup->next_insert_id;
|
||||
current_insert_id= backup->current_insert_id;
|
||||
insert_id_used= backup->insert_id_used;
|
||||
last_insert_id_used= backup->last_insert_id_used;
|
||||
clear_next_insert_id= backup->clear_next_insert_id;
|
||||
first_successful_insert_id_in_prev_stmt=
|
||||
backup->first_successful_insert_id_in_prev_stmt;
|
||||
first_successful_insert_id_in_cur_stmt=
|
||||
backup->first_successful_insert_id_in_cur_stmt;
|
||||
limit_found_rows= backup->limit_found_rows;
|
||||
sent_row_count= backup->sent_row_count;
|
||||
client_capabilities= backup->client_capabilities;
|
||||
|
@ -2712,6 +2713,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
|
|||
bool is_trans, bool suppress_use)
|
||||
{
|
||||
DBUG_ENTER("THD::binlog_query");
|
||||
DBUG_PRINT("enter", ("qtype=%d, query='%s'", qtype, query));
|
||||
DBUG_ASSERT(query && mysql_bin_log.is_open());
|
||||
|
||||
switch (qtype) {
|
||||
|
@ -2779,4 +2781,26 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype,
|
|||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
bool Discrete_intervals_list::append(ulonglong start, ulonglong val,
|
||||
ulonglong incr)
|
||||
{
|
||||
DBUG_ENTER("Discrete_intervals_list::append");
|
||||
/* first, see if this can be merged with previous */
|
||||
if ((head == NULL) || tail->merge_if_contiguous(start, val, incr))
|
||||
{
|
||||
/* it cannot, so need to add a new interval */
|
||||
Discrete_interval *new_interval= new Discrete_interval(start, val, incr);
|
||||
if (unlikely(new_interval == NULL)) // out of memory
|
||||
DBUG_RETURN(1);
|
||||
DBUG_PRINT("info",("adding new auto_increment interval"));
|
||||
if (head == NULL)
|
||||
head= current= new_interval;
|
||||
else
|
||||
tail->next= new_interval;
|
||||
tail= new_interval;
|
||||
elements++;
|
||||
}
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
#endif /* !defined(MYSQL_CLIENT) */
|
||||
|
|
205
sql/sql_class.h
205
sql/sql_class.h
|
@ -770,12 +770,14 @@ class Sub_statement_state
|
|||
{
|
||||
public:
|
||||
ulonglong options;
|
||||
ulonglong last_insert_id, next_insert_id, current_insert_id;
|
||||
ulonglong first_successful_insert_id_in_prev_stmt;
|
||||
ulonglong first_successful_insert_id_in_cur_stmt, insert_id_for_cur_row;
|
||||
Discrete_interval auto_inc_interval_for_cur_row;
|
||||
ulonglong limit_found_rows;
|
||||
ha_rows cuted_fields, sent_row_count, examined_row_count;
|
||||
ulong client_capabilities;
|
||||
uint in_sub_stmt;
|
||||
bool enable_slow_log, insert_id_used, clear_next_insert_id;
|
||||
bool enable_slow_log;
|
||||
bool last_insert_id_used;
|
||||
my_bool no_send_ok;
|
||||
SAVEPOINT *savepoints;
|
||||
|
@ -1071,24 +1073,138 @@ public:
|
|||
Note: in the parser, stmt_arena == thd, even for PS/SP.
|
||||
*/
|
||||
Query_arena *stmt_arena;
|
||||
/* Tells if LAST_INSERT_ID(#) was called for the current statement */
|
||||
bool arg_of_last_insert_id_function;
|
||||
/*
|
||||
next_insert_id is set on SET INSERT_ID= #. This is used as the next
|
||||
generated auto_increment value in handler.cc
|
||||
ALL OVER THIS FILE, "insert_id" means "*automatically generated* value for
|
||||
insertion into an auto_increment column".
|
||||
*/
|
||||
ulonglong next_insert_id;
|
||||
/* Remember last next_insert_id to reset it if something went wrong */
|
||||
ulonglong prev_insert_id;
|
||||
/*
|
||||
The insert_id used for the last statement or set by SET LAST_INSERT_ID=#
|
||||
or SELECT LAST_INSERT_ID(#). Used for binary log and returned by
|
||||
LAST_INSERT_ID()
|
||||
This is the first autogenerated insert id which was *successfully*
|
||||
inserted by the previous statement (exactly, if the previous statement
|
||||
didn't successfully insert an autogenerated insert id, then it's the one
|
||||
of the statement before, etc).
|
||||
It can also be set by SET LAST_INSERT_ID=# or SELECT LAST_INSERT_ID(#).
|
||||
It is returned by LAST_INSERT_ID().
|
||||
*/
|
||||
ulonglong last_insert_id;
|
||||
ulonglong first_successful_insert_id_in_prev_stmt;
|
||||
/*
|
||||
Set to the first value that LAST_INSERT_ID() returned for the last
|
||||
statement. When this is set, last_insert_id_used is set to true.
|
||||
Variant of the above, used for storing in statement-based binlog. The
|
||||
difference is that the one above can change as the execution of a stored
|
||||
function progresses, while the one below is set once and then does not
|
||||
change (which is the value which statement-based binlog needs).
|
||||
*/
|
||||
ulonglong current_insert_id;
|
||||
ulonglong first_successful_insert_id_in_prev_stmt_for_binlog;
|
||||
/*
|
||||
This is the first autogenerated insert id which was *successfully*
|
||||
inserted by the current statement. It is maintained only to set
|
||||
first_successful_insert_id_in_prev_stmt when statement ends.
|
||||
*/
|
||||
ulonglong first_successful_insert_id_in_cur_stmt;
|
||||
/*
|
||||
We follow this logic:
|
||||
- when stmt starts, first_successful_insert_id_in_prev_stmt contains the
|
||||
first insert id successfully inserted by the previous stmt.
|
||||
- as stmt makes progress, handler::insert_id_for_cur_row changes; every
|
||||
time get_auto_increment() is called, auto_inc_intervals_for_binlog is
|
||||
augmented with the reserved interval (if statement-based binlogging).
|
||||
- at first successful insertion of an autogenerated value,
|
||||
first_successful_insert_id_in_cur_stmt is set to
|
||||
handler::insert_id_for_cur_row.
|
||||
- when stmt goes to binlog, auto_inc_intervals_for_binlog is
|
||||
binlogged if non-empty.
|
||||
- when stmt ends, first_successful_insert_id_in_prev_stmt is set to
|
||||
first_successful_insert_id_in_cur_stmt.
|
||||
*/
|
||||
/*
|
||||
stmt_depends_on_first_successful_insert_id_in_prev_stmt is set when
|
||||
LAST_INSERT_ID() is used by a statement.
|
||||
If it is set, first_successful_insert_id_in_prev_stmt_for_binlog will be
|
||||
stored in the statement-based binlog.
|
||||
This variable is CUMULATIVE along the execution of a stored function or
|
||||
trigger: if one substatement sets it to 1 it will stay 1 until the
|
||||
function/trigger ends, thus making sure that
|
||||
first_successful_insert_id_in_prev_stmt_for_binlog does not change anymore
|
||||
and is propagated to the caller for binlogging.
|
||||
*/
|
||||
bool stmt_depends_on_first_successful_insert_id_in_prev_stmt;
|
||||
/*
|
||||
List of auto_increment intervals reserved by the thread so far, for
|
||||
storage in the statement-based binlog.
|
||||
Note that its minimum is not first_successful_insert_id_in_cur_stmt:
|
||||
assuming a table with an autoinc column, and this happens:
|
||||
INSERT INTO ... VALUES(3);
|
||||
SET INSERT_ID=3; INSERT IGNORE ... VALUES (NULL);
|
||||
then the latter INSERT will insert no rows
|
||||
(first_successful_insert_id_in_cur_stmt == 0), but storing "INSERT_ID=3"
|
||||
in the binlog is still needed; the list's minimum will contain 3.
|
||||
*/
|
||||
Discrete_intervals_list auto_inc_intervals_in_cur_stmt_for_binlog;
|
||||
/* Used by replication and SET INSERT_ID */
|
||||
Discrete_intervals_list auto_inc_intervals_forced;
|
||||
/*
|
||||
There is BUG#19630 where statement-based replication of stored
|
||||
functions/triggers with two auto_increment columns breaks.
|
||||
We however ensure that it works when there is 0 or 1 auto_increment
|
||||
column; our rules are
|
||||
a) on master, while executing a top statement involving substatements,
|
||||
first top- or sub- statement to generate auto_increment values wins the
|
||||
exclusive right to see its values be written to binlog (the write
|
||||
will be done by the statement or its caller), and the losers won't see
|
||||
their values be written to binlog.
|
||||
b) on slave, while replicating a top statement involving substatements,
|
||||
first top- or sub- statement to need to read auto_increment values from
|
||||
the master's binlog wins the exclusive right to read them (so the losers
|
||||
won't read their values from binlog but instead generate on their own).
|
||||
a) implies that we mustn't backup/restore
|
||||
auto_inc_intervals_in_cur_stmt_for_binlog.
|
||||
b) implies that we mustn't backup/restore auto_inc_intervals_forced.
|
||||
|
||||
If there are more than 1 auto_increment columns, then intervals for
|
||||
different columns may mix into the
|
||||
auto_inc_intervals_in_cur_stmt_for_binlog list, which is logically wrong,
|
||||
but there is no point in preventing this mixing by preventing intervals
|
||||
from the secondly inserted column to come into the list, as such
|
||||
prevention would be wrong too.
|
||||
What will happen in the case of
|
||||
INSERT INTO t1 (auto_inc) VALUES(NULL);
|
||||
where t1 has a trigger which inserts into an auto_inc column of t2, is
|
||||
that in binlog we'll store the interval of t1 and the interval of t2 (when
|
||||
we store intervals, soon), then in slave, t1 will use both intervals, t2
|
||||
will use none; if t1 inserts the same number of rows as on master,
|
||||
normally the 2nd interval will not be used by t1, which is fine. t2's
|
||||
values will be wrong if t2's internal auto_increment counter is different
|
||||
from what it was on master (which is likely). In 5.1, in mixed binlogging
|
||||
mode, row-based binlogging is used for such cases where two
|
||||
auto_increment columns are inserted.
|
||||
*/
|
||||
inline void record_first_successful_insert_id_in_cur_stmt(ulonglong id)
|
||||
{
|
||||
if (first_successful_insert_id_in_cur_stmt == 0)
|
||||
first_successful_insert_id_in_cur_stmt= id;
|
||||
}
|
||||
inline ulonglong read_first_successful_insert_id_in_prev_stmt(void)
|
||||
{
|
||||
if (!stmt_depends_on_first_successful_insert_id_in_prev_stmt)
|
||||
{
|
||||
/* It's the first time we read it */
|
||||
first_successful_insert_id_in_prev_stmt_for_binlog=
|
||||
first_successful_insert_id_in_prev_stmt;
|
||||
stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;
|
||||
}
|
||||
return first_successful_insert_id_in_prev_stmt;
|
||||
}
|
||||
/*
|
||||
Used by Intvar_log_event::exec_event() and by "SET INSERT_ID=#"
|
||||
(mysqlbinlog). We'll soon add a variant which can take many intervals in
|
||||
argument.
|
||||
*/
|
||||
inline void force_one_auto_inc_interval(ulonglong next_id)
|
||||
{
|
||||
auto_inc_intervals_forced.empty(); // in case of multiple SET INSERT_ID
|
||||
auto_inc_intervals_forced.append(next_id, ULONGLONG_MAX, 0);
|
||||
}
|
||||
|
||||
ulonglong limit_found_rows;
|
||||
ulonglong options; /* Bitmap of states */
|
||||
longlong row_count_func; /* For the ROW_COUNT() function */
|
||||
|
@ -1157,7 +1273,6 @@ public:
|
|||
bool last_cuted_field;
|
||||
bool no_errors, password, is_fatal_error;
|
||||
bool query_start_used, rand_used, time_zone_used;
|
||||
bool last_insert_id_used,insert_id_used, clear_next_insert_id;
|
||||
bool in_lock_tables;
|
||||
bool query_error, bootstrap, cleanup_done;
|
||||
bool tmp_table_used;
|
||||
|
@ -1185,9 +1300,10 @@ public:
|
|||
/* Used by the sys_var class to store temporary values */
|
||||
union
|
||||
{
|
||||
my_bool my_bool_value;
|
||||
long long_value;
|
||||
ulong ulong_value;
|
||||
my_bool my_bool_value;
|
||||
long long_value;
|
||||
ulong ulong_value;
|
||||
ulonglong ulonglong_value;
|
||||
} sys_var_tmp;
|
||||
|
||||
struct {
|
||||
|
@ -1288,20 +1404,6 @@ public:
|
|||
inline void end_time() { time(&start_time); }
|
||||
inline void set_time(time_t t) { time_after_lock=start_time=user_time=t; }
|
||||
inline void lock_time() { time(&time_after_lock); }
|
||||
inline void insert_id(ulonglong id_arg)
|
||||
{
|
||||
last_insert_id= id_arg;
|
||||
insert_id_used=1;
|
||||
}
|
||||
inline ulonglong insert_id(void)
|
||||
{
|
||||
if (!last_insert_id_used)
|
||||
{
|
||||
last_insert_id_used=1;
|
||||
current_insert_id=last_insert_id;
|
||||
}
|
||||
return last_insert_id;
|
||||
}
|
||||
inline ulonglong found_rows(void)
|
||||
{
|
||||
return limit_found_rows;
|
||||
|
@ -1418,7 +1520,17 @@ public:
|
|||
inline void set_current_stmt_binlog_row_based_if_mixed()
|
||||
{
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
if (variables.binlog_format == BINLOG_FORMAT_MIXED)
|
||||
/*
|
||||
If in a stored/function trigger, the caller should already have done the
|
||||
change. We test in_sub_stmt to prevent introducing bugs where people
|
||||
wouldn't ensure that, and would switch to row-based mode in the middle
|
||||
of executing a stored function/trigger (which is too late, see also
|
||||
reset_current_stmt_binlog_row_based()); this condition will make their
|
||||
tests fail and so force them to propagate the
|
||||
lex->binlog_row_based_if_mixed upwards to the caller.
|
||||
*/
|
||||
if ((variables.binlog_format == BINLOG_FORMAT_MIXED) &&
|
||||
(in_sub_stmt == 0))
|
||||
current_stmt_binlog_row_based= TRUE;
|
||||
#endif
|
||||
}
|
||||
|
@ -1437,8 +1549,26 @@ public:
|
|||
inline void reset_current_stmt_binlog_row_based()
|
||||
{
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
current_stmt_binlog_row_based=
|
||||
test(variables.binlog_format == BINLOG_FORMAT_ROW);
|
||||
/*
|
||||
If there are temporary tables, don't reset back to
|
||||
statement-based. Indeed it could be that:
|
||||
CREATE TEMPORARY TABLE t SELECT UUID(); # row-based
|
||||
# and row-based does not store updates to temp tables
|
||||
# in the binlog.
|
||||
INSERT INTO u SELECT * FROM t; # stmt-based
|
||||
and then the INSERT will fail as data inserted into t was not logged.
|
||||
So we continue with row-based until the temp table is dropped.
|
||||
If we are in a stored function or trigger, we mustn't reset in the
|
||||
middle of its execution (as the binary logging way of a stored function
|
||||
or trigger is decided when it starts executing, depending for example on
|
||||
the caller (for a stored function: if caller is SELECT or
|
||||
INSERT/UPDATE/DELETE...).
|
||||
*/
|
||||
if ((temporary_tables == NULL) && (in_sub_stmt == 0))
|
||||
{
|
||||
current_stmt_binlog_row_based=
|
||||
test(variables.binlog_format == BINLOG_FORMAT_ROW);
|
||||
}
|
||||
#else
|
||||
current_stmt_binlog_row_based= FALSE;
|
||||
#endif
|
||||
|
@ -1630,7 +1760,7 @@ class select_insert :public select_result_interceptor {
|
|||
TABLE_LIST *table_list;
|
||||
TABLE *table;
|
||||
List<Item> *fields;
|
||||
ulonglong last_insert_id;
|
||||
ulonglong autoinc_value_of_last_inserted_row; // autogenerated or not
|
||||
COPY_INFO info;
|
||||
bool insert_into_view;
|
||||
|
||||
|
@ -1678,7 +1808,8 @@ public:
|
|||
virtual bool can_rollback_data() { return 1; }
|
||||
|
||||
// Needed for access from local class MY_HOOKS in prepare(), since thd is proteted.
|
||||
THD *get_thd(void) { return thd; }
|
||||
const THD *get_thd(void) { return thd; }
|
||||
const HA_CREATE_INFO *get_create_info() { return create_info; };
|
||||
};
|
||||
|
||||
#include <myisam.h>
|
||||
|
|
|
@ -986,12 +986,12 @@ trunc_by_del:
|
|||
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_NOT_AUTOCOMMIT);
|
||||
ha_enable_transaction(thd, FALSE);
|
||||
mysql_init_select(thd->lex);
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
bool save_binlog_row_based= thd->current_stmt_binlog_row_based;
|
||||
thd->clear_current_stmt_binlog_row_based();
|
||||
#endif
|
||||
error= mysql_delete(thd, table_list, (COND*) 0, (SQL_LIST*) 0,
|
||||
HA_POS_ERROR, LL(0), TRUE);
|
||||
ha_enable_transaction(thd, TRUE);
|
||||
thd->options= save_options;
|
||||
thd->current_stmt_binlog_row_based= save_binlog_row_based;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
|
|
@ -64,8 +64,8 @@
|
|||
static int check_null_fields(THD *thd,TABLE *entry);
|
||||
#ifndef EMBEDDED_LIBRARY
|
||||
static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list);
|
||||
static int write_delayed(THD *thd,TABLE *table, enum_duplicates dup, bool ignore,
|
||||
char *query, uint query_length, bool log_on);
|
||||
static int write_delayed(THD *thd, TABLE *table, enum_duplicates dup,
|
||||
LEX_STRING query, bool ignore, bool log_on);
|
||||
static void end_delayed_insert(THD *thd);
|
||||
pthread_handler_t handle_delayed_insert(void *arg);
|
||||
static void unlink_blobs(register TABLE *table);
|
||||
|
@ -448,7 +448,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
table->next_number_field=table->found_next_number_field;
|
||||
|
||||
error=0;
|
||||
id=0;
|
||||
thd->proc_info="update";
|
||||
if (duplic != DUP_ERROR || ignore)
|
||||
table->file->extra(HA_EXTRA_IGNORE_DUP_KEY);
|
||||
|
@ -548,22 +547,13 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
#ifndef EMBEDDED_LIBRARY
|
||||
if (lock_type == TL_WRITE_DELAYED)
|
||||
{
|
||||
error=write_delayed(thd, table, duplic, ignore, query, thd->query_length, log_on);
|
||||
LEX_STRING const st_query = { query, thd->query_length };
|
||||
error=write_delayed(thd, table, duplic, st_query, ignore, log_on);
|
||||
query=0;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
error=write_record(thd, table ,&info);
|
||||
/*
|
||||
If auto_increment values are used, save the first one
|
||||
for LAST_INSERT_ID() and for the update log.
|
||||
We can't use insert_id() as we don't want to touch the
|
||||
last_insert_id_used flag.
|
||||
*/
|
||||
if (! id && thd->insert_id_used)
|
||||
{ // Get auto increment value
|
||||
id= thd->last_insert_id;
|
||||
}
|
||||
if (error)
|
||||
break;
|
||||
thd->row_count++;
|
||||
|
@ -571,6 +561,7 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
|
||||
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||
joins_freed= TRUE;
|
||||
table->file->ha_release_auto_increment();
|
||||
|
||||
/*
|
||||
Now all rows are inserted. Time to update logs and sends response to
|
||||
|
@ -581,7 +572,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
{
|
||||
if (!error)
|
||||
{
|
||||
id=0; // No auto_increment id
|
||||
info.copied=values_list.elements;
|
||||
end_delayed_insert(thd);
|
||||
}
|
||||
|
@ -595,11 +585,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
table->file->print_error(my_errno,MYF(0));
|
||||
error=1;
|
||||
}
|
||||
if (id && values_list.elements != 1)
|
||||
thd->insert_id(id); // For update log
|
||||
else if (table->next_number_field && info.copied)
|
||||
id=table->next_number_field->val_int(); // Return auto_increment value
|
||||
|
||||
transactional_table= table->file->has_transactions();
|
||||
|
||||
if ((changed= (info.copied || info.deleted || info.updated)))
|
||||
|
@ -648,18 +633,27 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
}
|
||||
}
|
||||
thd->proc_info="end";
|
||||
/*
|
||||
We'll report to the client this id:
|
||||
- if the table contains an autoincrement column and we successfully
|
||||
inserted an autogenerated value, the autogenerated value.
|
||||
- if the table contains no autoincrement column and LAST_INSERT_ID(X) was
|
||||
called, X.
|
||||
- if the table contains an autoincrement column, and some rows were
|
||||
inserted, the id of the last "inserted" row (if IGNORE, that value may not
|
||||
have been really inserted but ignored).
|
||||
*/
|
||||
id= (thd->first_successful_insert_id_in_cur_stmt > 0) ?
|
||||
thd->first_successful_insert_id_in_cur_stmt :
|
||||
(thd->arg_of_last_insert_id_function ?
|
||||
thd->first_successful_insert_id_in_prev_stmt :
|
||||
((table->next_number_field && info.copied) ?
|
||||
table->next_number_field->val_int() : 0));
|
||||
table->next_number_field=0;
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
|
||||
thd->next_insert_id=0; // Reset this if wrongly used
|
||||
if (duplic != DUP_ERROR || ignore)
|
||||
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
|
||||
/* Reset value of LAST_INSERT_ID if no rows where inserted */
|
||||
if (!info.copied && thd->insert_id_used)
|
||||
{
|
||||
thd->insert_id(0);
|
||||
id=0;
|
||||
}
|
||||
if (error)
|
||||
goto abort;
|
||||
if (values_list.elements == 1 && (!(thd->options & OPTION_WARNINGS) ||
|
||||
|
@ -681,8 +675,6 @@ bool mysql_insert(THD *thd,TABLE_LIST *table_list,
|
|||
thd->row_count_func= info.copied+info.deleted+info.updated;
|
||||
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
||||
}
|
||||
if (table != NULL)
|
||||
table->file->release_auto_increment();
|
||||
thd->abort_on_warning= 0;
|
||||
DBUG_RETURN(FALSE);
|
||||
|
||||
|
@ -692,7 +684,7 @@ abort:
|
|||
end_delayed_insert(thd);
|
||||
#endif
|
||||
if (table != NULL)
|
||||
table->file->release_auto_increment();
|
||||
table->file->ha_release_auto_increment();
|
||||
if (!joins_freed)
|
||||
free_underlaid_joins(thd, &thd->lex->select_lex);
|
||||
thd->abort_on_warning= 0;
|
||||
|
@ -1001,6 +993,8 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
int error, trg_error= 0;
|
||||
char *key=0;
|
||||
MY_BITMAP *save_read_set, *save_write_set;
|
||||
ulonglong prev_insert_id= table->file->next_insert_id;
|
||||
ulonglong insert_id_for_cur_row= 0;
|
||||
DBUG_ENTER("write_record");
|
||||
|
||||
info->records++;
|
||||
|
@ -1013,10 +1007,20 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
while ((error=table->file->ha_write_row(table->record[0])))
|
||||
{
|
||||
uint key_nr;
|
||||
/*
|
||||
If we do more than one iteration of this loop, from the second one the
|
||||
row will have an explicit value in the autoinc field, which was set at
|
||||
the first call of handler::update_auto_increment(). So we must save
|
||||
the autogenerated value to avoid thd->insert_id_for_cur_row to become
|
||||
0.
|
||||
*/
|
||||
if (table->file->insert_id_for_cur_row > 0)
|
||||
insert_id_for_cur_row= table->file->insert_id_for_cur_row;
|
||||
else
|
||||
table->file->insert_id_for_cur_row= insert_id_for_cur_row;
|
||||
bool is_duplicate_key_error;
|
||||
if (table->file->is_fatal_error(error, HA_CHECK_DUP))
|
||||
goto err;
|
||||
table->file->restore_auto_increment(); // it's too early here! BUG#20188
|
||||
is_duplicate_key_error= table->file->is_fatal_error(error, 0);
|
||||
if (!is_duplicate_key_error)
|
||||
{
|
||||
|
@ -1044,7 +1048,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
if (info->handle_duplicates == DUP_REPLACE &&
|
||||
table->next_number_field &&
|
||||
key_nr == table->s->next_number_index &&
|
||||
table->file->auto_increment_column_changed)
|
||||
(insert_id_for_cur_row > 0))
|
||||
goto err;
|
||||
if (table->file->ha_table_flags() & HA_DUPLICATE_POS)
|
||||
{
|
||||
|
@ -1103,22 +1107,29 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
if (res == VIEW_CHECK_ERROR)
|
||||
goto before_trg_err;
|
||||
|
||||
if (thd->clear_next_insert_id)
|
||||
{
|
||||
/* Reset auto-increment cacheing if we do an update */
|
||||
thd->clear_next_insert_id= 0;
|
||||
thd->next_insert_id= 0;
|
||||
}
|
||||
if ((error=table->file->ha_update_row(table->record[1],
|
||||
table->record[0])))
|
||||
{
|
||||
if (info->ignore &&
|
||||
!table->file->is_fatal_error(error, HA_CHECK_DUP_KEY))
|
||||
{
|
||||
table->file->restore_auto_increment(prev_insert_id);
|
||||
goto ok_or_after_trg_err;
|
||||
}
|
||||
goto err;
|
||||
}
|
||||
info->updated++;
|
||||
|
||||
/*
|
||||
If ON DUP KEY UPDATE updates a row instead of inserting one, and
|
||||
there is an auto_increment column, then SELECT LAST_INSERT_ID()
|
||||
returns the id of the updated row:
|
||||
*/
|
||||
if (table->next_number_field)
|
||||
{
|
||||
longlong field_val= table->next_number_field->val_int();
|
||||
thd->record_first_successful_insert_id_in_cur_stmt(field_val);
|
||||
table->file->adjust_next_insert_id_after_explicit_value(field_val);
|
||||
}
|
||||
trg_error= (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_UPDATE,
|
||||
TRG_ACTION_AFTER, TRUE));
|
||||
|
@ -1147,16 +1158,11 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
table->timestamp_field_type == TIMESTAMP_AUTO_SET_ON_BOTH) &&
|
||||
(!table->triggers || !table->triggers->has_delete_triggers()))
|
||||
{
|
||||
if (thd->clear_next_insert_id)
|
||||
{
|
||||
/* Reset auto-increment cacheing if we do an update */
|
||||
thd->clear_next_insert_id= 0;
|
||||
thd->next_insert_id= 0;
|
||||
}
|
||||
if ((error=table->file->ha_update_row(table->record[1],
|
||||
table->record[0])))
|
||||
goto err;
|
||||
info->deleted++;
|
||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
||||
/*
|
||||
Since we pretend that we have done insert we should call
|
||||
its after triggers.
|
||||
|
@ -1185,6 +1191,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
}
|
||||
}
|
||||
}
|
||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
||||
/*
|
||||
Restore column maps if they where replaced during an duplicate key
|
||||
problem.
|
||||
|
@ -1198,12 +1205,13 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
|
|||
if (!info->ignore ||
|
||||
table->file->is_fatal_error(error, HA_CHECK_DUP))
|
||||
goto err;
|
||||
table->file->restore_auto_increment();
|
||||
table->file->restore_auto_increment(prev_insert_id);
|
||||
goto ok_or_after_trg_err;
|
||||
}
|
||||
|
||||
after_trg_n_copied_inc:
|
||||
info->copied++;
|
||||
thd->record_first_successful_insert_id_in_cur_stmt(table->file->insert_id_for_cur_row);
|
||||
trg_error= (table->triggers &&
|
||||
table->triggers->process_triggers(thd, TRG_EVENT_INSERT,
|
||||
TRG_ACTION_AFTER, TRUE));
|
||||
|
@ -1223,6 +1231,7 @@ err:
|
|||
table->file->print_error(error,MYF(0));
|
||||
|
||||
before_trg_err:
|
||||
table->file->restore_auto_increment(prev_insert_id);
|
||||
if (key)
|
||||
my_safe_afree(key, table->s->max_unique_length, MAX_KEY_LENGTH);
|
||||
table->column_bitmaps_set(save_read_set, save_write_set);
|
||||
|
@ -1285,14 +1294,20 @@ public:
|
|||
char *record;
|
||||
enum_duplicates dup;
|
||||
time_t start_time;
|
||||
bool query_start_used,last_insert_id_used,insert_id_used, ignore, log_query;
|
||||
ulonglong last_insert_id;
|
||||
bool query_start_used, ignore, log_query;
|
||||
bool stmt_depends_on_first_successful_insert_id_in_prev_stmt;
|
||||
ulonglong first_successful_insert_id_in_prev_stmt;
|
||||
timestamp_auto_set_type timestamp_field_type;
|
||||
LEX_STRING query;
|
||||
|
||||
delayed_row(enum_duplicates dup_arg, bool ignore_arg, bool log_query_arg)
|
||||
:record(0), dup(dup_arg), ignore(ignore_arg), log_query(log_query_arg) {}
|
||||
delayed_row(LEX_STRING const query_arg, enum_duplicates dup_arg,
|
||||
bool ignore_arg, bool log_query_arg)
|
||||
: record(0), dup(dup_arg), ignore(ignore_arg), log_query(log_query_arg),
|
||||
query(query_arg)
|
||||
{}
|
||||
~delayed_row()
|
||||
{
|
||||
x_free(query.str);
|
||||
x_free(record);
|
||||
}
|
||||
};
|
||||
|
@ -1300,9 +1315,6 @@ public:
|
|||
|
||||
class delayed_insert :public ilink {
|
||||
uint locks_in_memory;
|
||||
char *query;
|
||||
ulong query_length;
|
||||
ulong query_allocated;
|
||||
public:
|
||||
THD thd;
|
||||
TABLE *table;
|
||||
|
@ -1316,7 +1328,7 @@ public:
|
|||
TABLE_LIST table_list; // Argument
|
||||
|
||||
delayed_insert()
|
||||
:locks_in_memory(0), query(0), query_length(0), query_allocated(0),
|
||||
:locks_in_memory(0),
|
||||
table(0),tables_in_use(0),stacked_inserts(0), status(0), dead(0),
|
||||
group_count(0)
|
||||
{
|
||||
|
@ -1327,6 +1339,11 @@ public:
|
|||
thd.command=COM_DELAYED_INSERT;
|
||||
thd.lex->current_select= 0; // for my_message_sql
|
||||
thd.lex->sql_command= SQLCOM_INSERT; // For innodb::store_lock()
|
||||
/*
|
||||
Statement-based replication of INSERT DELAYED has problems with RAND()
|
||||
and user vars, so in mixed mode we go to row-based.
|
||||
*/
|
||||
thd.set_current_stmt_binlog_row_based_if_mixed();
|
||||
|
||||
bzero((char*) &thd.net, sizeof(thd.net)); // Safety
|
||||
bzero((char*) &table_list, sizeof(table_list)); // Safety
|
||||
|
@ -1342,7 +1359,6 @@ public:
|
|||
}
|
||||
~delayed_insert()
|
||||
{
|
||||
my_free(query, MYF(MY_WME|MY_ALLOW_ZERO_PTR));
|
||||
/* The following is not really needed, but just for safety */
|
||||
delayed_row *row;
|
||||
while ((row=rows.get()))
|
||||
|
@ -1362,25 +1378,6 @@ public:
|
|||
VOID(pthread_cond_broadcast(&COND_thread_count)); /* Tell main we are ready */
|
||||
}
|
||||
|
||||
int set_query(char const *q, ulong qlen) {
|
||||
if (q && qlen > 0)
|
||||
{
|
||||
if (query_allocated < qlen + 1)
|
||||
{
|
||||
ulong const flags(MY_WME|MY_FREE_ON_ERROR|MY_ALLOW_ZERO_PTR);
|
||||
query= my_realloc(query, qlen + 1, MYF(flags));
|
||||
if (query == 0)
|
||||
return HA_ERR_OUT_OF_MEM;
|
||||
query_allocated= qlen;
|
||||
}
|
||||
query_length= qlen;
|
||||
memcpy(query, q, qlen + 1);
|
||||
}
|
||||
else
|
||||
query_length= 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* The following is for checking when we can delete ourselves */
|
||||
inline void lock()
|
||||
{
|
||||
|
@ -1658,13 +1655,14 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
|
|||
|
||||
/* Put a question in queue */
|
||||
|
||||
static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic,
|
||||
bool ignore, char *query, uint query_length,
|
||||
bool log_on)
|
||||
static int
|
||||
write_delayed(THD *thd,TABLE *table, enum_duplicates duplic,
|
||||
LEX_STRING query, bool ignore, bool log_on)
|
||||
{
|
||||
delayed_row *row=0;
|
||||
delayed_row *row;
|
||||
delayed_insert *di=thd->di;
|
||||
DBUG_ENTER("write_delayed");
|
||||
DBUG_PRINT("enter", ("query = '%s' length %u", query.str, query.length));
|
||||
|
||||
thd->proc_info="waiting for handler insert";
|
||||
pthread_mutex_lock(&di->mutex);
|
||||
|
@ -1672,18 +1670,44 @@ static int write_delayed(THD *thd,TABLE *table,enum_duplicates duplic,
|
|||
pthread_cond_wait(&di->cond_client,&di->mutex);
|
||||
thd->proc_info="storing row into queue";
|
||||
|
||||
if (thd->killed || !(row= new delayed_row(duplic, ignore, log_on)))
|
||||
if (thd->killed)
|
||||
goto err;
|
||||
|
||||
/*
|
||||
Take a copy of the query string, if there is any. The string will
|
||||
be free'ed when the row is destroyed. If there is no query string,
|
||||
we don't do anything special.
|
||||
*/
|
||||
|
||||
if (query.str)
|
||||
{
|
||||
char *str;
|
||||
if (!(str= my_strndup(query.str, query.length, MYF(MY_WME))))
|
||||
goto err;
|
||||
query.str= str;
|
||||
}
|
||||
row= new delayed_row(query, duplic, ignore, log_on);
|
||||
if (row == NULL)
|
||||
{
|
||||
my_free(query.str, MYF(MY_WME));
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (!(row->record= (char*) my_malloc(table->s->reclength, MYF(MY_WME))))
|
||||
goto err;
|
||||
memcpy(row->record, table->record[0], table->s->reclength);
|
||||
di->set_query(query, query_length);
|
||||
row->start_time= thd->start_time;
|
||||
row->query_start_used= thd->query_start_used;
|
||||
row->last_insert_id_used= thd->last_insert_id_used;
|
||||
row->insert_id_used= thd->insert_id_used;
|
||||
row->last_insert_id= thd->last_insert_id;
|
||||
/*
|
||||
those are for the binlog: LAST_INSERT_ID() has been evaluated at this
|
||||
time, so record does not need it, but statement-based binlogging of the
|
||||
INSERT will need when the row is actually inserted.
|
||||
As for SET INSERT_ID, DELAYED does not honour it (BUG#20830).
|
||||
*/
|
||||
row->stmt_depends_on_first_successful_insert_id_in_prev_stmt=
|
||||
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt;
|
||||
row->first_successful_insert_id_in_prev_stmt=
|
||||
thd->first_successful_insert_id_in_prev_stmt;
|
||||
row->timestamp_field_type= table->timestamp_field_type;
|
||||
|
||||
di->rows.push_back(row);
|
||||
|
@ -1937,6 +1961,7 @@ pthread_handler_t handle_delayed_insert(void *arg)
|
|||
MYSQL_LOCK *lock=thd->lock;
|
||||
thd->lock=0;
|
||||
pthread_mutex_unlock(&di->mutex);
|
||||
di->table->file->ha_release_auto_increment();
|
||||
mysql_unlock_tables(thd, lock);
|
||||
di->group_count=0;
|
||||
pthread_mutex_lock(&di->mutex);
|
||||
|
@ -2037,7 +2062,7 @@ bool delayed_insert::handle_inserts(void)
|
|||
if (thd.killed || table->s->version != refresh_version)
|
||||
{
|
||||
thd.killed= THD::KILL_CONNECTION;
|
||||
max_rows= ~(ulong)0; // Do as much as possible
|
||||
max_rows= ULONG_MAX; // Do as much as possible
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -2049,13 +2074,6 @@ bool delayed_insert::handle_inserts(void)
|
|||
table->file->extra(HA_EXTRA_WRITE_CACHE);
|
||||
pthread_mutex_lock(&mutex);
|
||||
|
||||
/* Reset auto-increment cacheing */
|
||||
if (thd.clear_next_insert_id)
|
||||
{
|
||||
thd.next_insert_id= 0;
|
||||
thd.clear_next_insert_id= 0;
|
||||
}
|
||||
|
||||
while ((row=rows.get()))
|
||||
{
|
||||
stacked_inserts--;
|
||||
|
@ -2064,9 +2082,12 @@ bool delayed_insert::handle_inserts(void)
|
|||
|
||||
thd.start_time=row->start_time;
|
||||
thd.query_start_used=row->query_start_used;
|
||||
thd.last_insert_id=row->last_insert_id;
|
||||
thd.last_insert_id_used=row->last_insert_id_used;
|
||||
thd.insert_id_used=row->insert_id_used;
|
||||
/* for the binlog, forget auto_increment ids generated by previous rows */
|
||||
// thd.auto_inc_intervals_in_cur_stmt_for_binlog.empty();
|
||||
thd.first_successful_insert_id_in_prev_stmt=
|
||||
row->first_successful_insert_id_in_prev_stmt;
|
||||
thd.stmt_depends_on_first_successful_insert_id_in_prev_stmt=
|
||||
row->stmt_depends_on_first_successful_insert_id_in_prev_stmt;
|
||||
table->timestamp_field_type= row->timestamp_field_type;
|
||||
|
||||
info.ignore= row->ignore;
|
||||
|
@ -2084,11 +2105,28 @@ bool delayed_insert::handle_inserts(void)
|
|||
thread_safe_increment(delayed_insert_errors,&LOCK_delayed_status);
|
||||
row->log_query = 0;
|
||||
}
|
||||
|
||||
if (using_ignore)
|
||||
{
|
||||
using_ignore=0;
|
||||
table->file->extra(HA_EXTRA_NO_IGNORE_DUP_KEY);
|
||||
}
|
||||
|
||||
if (row->log_query && row->query.str != NULL && mysql_bin_log.is_open())
|
||||
{
|
||||
/*
|
||||
If the query has several rows to insert, only the first row will come
|
||||
here. In row-based binlogging, this means that the first row will be
|
||||
written to binlog as one Table_map event and one Rows event (due to an
|
||||
event flush done in binlog_query()), then all other rows of this query
|
||||
will be binlogged together as one single Table_map event and one
|
||||
single Rows event.
|
||||
*/
|
||||
thd.binlog_query(THD::ROW_QUERY_TYPE,
|
||||
row->query.str, row->query.length,
|
||||
FALSE, FALSE);
|
||||
}
|
||||
|
||||
if (table->s->blob_fields)
|
||||
free_delayed_insert_blobs(table);
|
||||
thread_safe_sub(delayed_rows_in_use,1,&LOCK_delayed_status);
|
||||
|
@ -2135,13 +2173,25 @@ bool delayed_insert::handle_inserts(void)
|
|||
pthread_cond_broadcast(&cond_client); // If waiting clients
|
||||
}
|
||||
}
|
||||
|
||||
thd.proc_info=0;
|
||||
pthread_mutex_unlock(&mutex);
|
||||
|
||||
/* After releasing the mutex, to prevent deadlocks. */
|
||||
if (mysql_bin_log.is_open())
|
||||
thd.binlog_query(THD::ROW_QUERY_TYPE, query, query_length, FALSE, FALSE);
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
/*
|
||||
We need to flush the pending event when using row-based
|
||||
replication since the flushing normally done in binlog_query() is
|
||||
not done last in the statement: for delayed inserts, the insert
|
||||
statement is logged *before* all rows are inserted.
|
||||
|
||||
We can flush the pending event without checking the thd->lock
|
||||
since the delayed insert *thread* is not inside a stored function
|
||||
or trigger.
|
||||
|
||||
TODO: Move the logging to last in the sequence of rows.
|
||||
*/
|
||||
if (thd.current_stmt_binlog_row_based)
|
||||
thd.binlog_flush_pending_rows_event(TRUE);
|
||||
#endif /* HAVE_ROW_BASED_REPLICATION */
|
||||
|
||||
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
|
||||
{ // This shouldn't happen
|
||||
|
@ -2229,7 +2279,7 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par,
|
|||
enum_duplicates duplic,
|
||||
bool ignore_check_option_errors)
|
||||
:table_list(table_list_par), table(table_par), fields(fields_par),
|
||||
last_insert_id(0),
|
||||
autoinc_value_of_last_inserted_row(0),
|
||||
insert_into_view(table_list_par && table_list_par->view != 0)
|
||||
{
|
||||
bzero((char*) &info,sizeof(info));
|
||||
|
@ -2437,16 +2487,21 @@ bool select_insert::send_data(List<Item> &values)
|
|||
}
|
||||
if (table->next_number_field)
|
||||
{
|
||||
/*
|
||||
If no value has been autogenerated so far, we need to remember the
|
||||
value we just saw, we may need to send it to client in the end.
|
||||
*/
|
||||
if (thd->first_successful_insert_id_in_cur_stmt == 0) // optimization
|
||||
autoinc_value_of_last_inserted_row=
|
||||
table->next_number_field->val_int();
|
||||
/*
|
||||
Clear auto-increment field for the next record, if triggers are used
|
||||
we will clear it twice, but this should be cheap.
|
||||
*/
|
||||
table->next_number_field->reset();
|
||||
if (!last_insert_id && thd->insert_id_used)
|
||||
last_insert_id= thd->insert_id();
|
||||
}
|
||||
}
|
||||
table->file->release_auto_increment();
|
||||
table->file->ha_release_auto_increment();
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
||||
|
@ -2508,8 +2563,6 @@ void select_insert::send_error(uint errcode,const char *err)
|
|||
{
|
||||
if (!table->file->has_transactions())
|
||||
{
|
||||
if (last_insert_id)
|
||||
thd->insert_id(last_insert_id); // For binary log
|
||||
if (mysql_bin_log.is_open())
|
||||
{
|
||||
thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length,
|
||||
|
@ -2529,6 +2582,7 @@ void select_insert::send_error(uint errcode,const char *err)
|
|||
bool select_insert::send_eof()
|
||||
{
|
||||
int error,error2;
|
||||
ulonglong id;
|
||||
DBUG_ENTER("select_insert::send_eof");
|
||||
|
||||
error= (!thd->prelocked_mode) ? table->file->ha_end_bulk_insert():0;
|
||||
|
@ -2554,8 +2608,6 @@ bool select_insert::send_eof()
|
|||
thd->options|= OPTION_STATUS_NO_TRANS_UPDATE;
|
||||
}
|
||||
|
||||
if (last_insert_id)
|
||||
thd->insert_id(last_insert_id); // For binary log
|
||||
/*
|
||||
Write to binlog before commiting transaction. No statement will
|
||||
be written by the binlog_query() below in RBR mode. All the
|
||||
|
@ -2585,7 +2637,13 @@ bool select_insert::send_eof()
|
|||
sprintf(buff, ER(ER_INSERT_INFO), (ulong) info.records,
|
||||
(ulong) (info.deleted+info.updated), (ulong) thd->cuted_fields);
|
||||
thd->row_count_func= info.copied+info.deleted+info.updated;
|
||||
::send_ok(thd, (ulong) thd->row_count_func, last_insert_id, buff);
|
||||
|
||||
id= (thd->first_successful_insert_id_in_cur_stmt > 0) ?
|
||||
thd->first_successful_insert_id_in_cur_stmt :
|
||||
(thd->arg_of_last_insert_id_function ?
|
||||
thd->first_successful_insert_id_in_prev_stmt :
|
||||
(info.copied ? autoinc_value_of_last_inserted_row : 0));
|
||||
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
||||
DBUG_RETURN(0);
|
||||
}
|
||||
|
||||
|
@ -2751,21 +2809,6 @@ static TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
|
|||
}
|
||||
|
||||
|
||||
class MY_HOOKS : public TABLEOP_HOOKS
|
||||
{
|
||||
public:
|
||||
MY_HOOKS(select_create *x) : ptr(x) { }
|
||||
virtual void do_prelock(TABLE **tables, uint count)
|
||||
{
|
||||
if (ptr->get_thd()->current_stmt_binlog_row_based)
|
||||
ptr->binlog_show_create_table(tables, count);
|
||||
}
|
||||
|
||||
private:
|
||||
select_create *ptr;
|
||||
};
|
||||
|
||||
|
||||
int
|
||||
select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
||||
{
|
||||
|
@ -2778,8 +2821,9 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
|
|||
MY_HOOKS(select_create *x) : ptr(x) { }
|
||||
virtual void do_prelock(TABLE **tables, uint count)
|
||||
{
|
||||
if (ptr->get_thd()->current_stmt_binlog_row_based)
|
||||
ptr->binlog_show_create_table(tables, count);
|
||||
if (ptr->get_thd()->current_stmt_binlog_row_based &&
|
||||
!(ptr->get_create_info()->options & HA_LEX_CREATE_TMP_TABLE))
|
||||
ptr->binlog_show_create_table(tables, count);
|
||||
}
|
||||
|
||||
private:
|
||||
|
|
|
@ -183,7 +183,6 @@ void lex_start(THD *thd, const uchar *buf, uint length)
|
|||
lex->nest_level=0 ;
|
||||
lex->allow_sum_func= 0;
|
||||
lex->in_sum_func= NULL;
|
||||
lex->binlog_row_based_if_mixed= 0;
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
@ -1625,6 +1624,9 @@ void Query_tables_list::reset_query_tables_list(bool init)
|
|||
sroutines_list.empty();
|
||||
sroutines_list_own_last= sroutines_list.next;
|
||||
sroutines_list_own_elements= 0;
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
binlog_row_based_if_mixed= FALSE;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -793,6 +793,16 @@ public:
|
|||
byte **sroutines_list_own_last;
|
||||
uint sroutines_list_own_elements;
|
||||
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
/*
|
||||
Tells if the parsing stage detected that some items require row-based
|
||||
binlogging to give a reliable binlog/replication, or if we will use
|
||||
stored functions or triggers which themselves need require row-based
|
||||
binlogging.
|
||||
*/
|
||||
bool binlog_row_based_if_mixed;
|
||||
#endif
|
||||
|
||||
/*
|
||||
These constructor and destructor serve for creation/destruction
|
||||
of Query_tables_list instances which are used as backup storage.
|
||||
|
@ -975,11 +985,7 @@ typedef struct st_lex : public Query_tables_list
|
|||
uint8 create_view_check;
|
||||
bool drop_if_exists, drop_temporary, local_file, one_shot_set;
|
||||
bool in_comment, ignore_space, verbose, no_write_to_binlog;
|
||||
/*
|
||||
binlog_row_based_if_mixed tells if the parsing stage detected that some
|
||||
items require row-based binlogging to give a reliable binlog/replication.
|
||||
*/
|
||||
bool tx_chain, tx_release, binlog_row_based_if_mixed;
|
||||
bool tx_chain, tx_release;
|
||||
/*
|
||||
Special JOIN::prepare mode: changing of query is prohibited.
|
||||
When creating a view, we need to just check its syntax omitting
|
||||
|
|
|
@ -497,13 +497,12 @@ bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
|
|||
error=ha_autocommit_or_rollback(thd,error);
|
||||
|
||||
err:
|
||||
table->file->ha_release_auto_increment();
|
||||
if (thd->lock)
|
||||
{
|
||||
mysql_unlock_tables(thd, thd->lock);
|
||||
thd->lock=0;
|
||||
}
|
||||
if (table != NULL)
|
||||
table->file->release_auto_increment();
|
||||
thd->abort_on_warning= 0;
|
||||
DBUG_RETURN(error);
|
||||
}
|
||||
|
@ -638,14 +637,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||
DBUG_RETURN(1);
|
||||
thd->no_trans_update= no_trans_update;
|
||||
|
||||
/*
|
||||
If auto_increment values are used, save the first one
|
||||
for LAST_INSERT_ID() and for the binary/update log.
|
||||
We can't use insert_id() as we don't want to touch the
|
||||
last_insert_id_used flag.
|
||||
*/
|
||||
if (!id && thd->insert_id_used)
|
||||
id= thd->last_insert_id;
|
||||
/*
|
||||
We don't need to reset auto-increment field since we are restoring
|
||||
its default value at the beginning of each loop iteration.
|
||||
|
@ -662,8 +653,6 @@ read_fixed_length(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||
thd->row_count++;
|
||||
continue_loop:;
|
||||
}
|
||||
if (id && !read_info.error)
|
||||
thd->insert_id(id); // For binary/update log
|
||||
DBUG_RETURN(test(read_info.error));
|
||||
}
|
||||
|
||||
|
@ -806,14 +795,6 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||
|
||||
if (write_record(thd, table, &info))
|
||||
DBUG_RETURN(1);
|
||||
/*
|
||||
If auto_increment values are used, save the first one
|
||||
for LAST_INSERT_ID() and for the binary/update log.
|
||||
We can't use insert_id() as we don't want to touch the
|
||||
last_insert_id_used flag.
|
||||
*/
|
||||
if (!id && thd->insert_id_used)
|
||||
id= thd->last_insert_id;
|
||||
/*
|
||||
We don't need to reset auto-increment field since we are restoring
|
||||
its default value at the beginning of each loop iteration.
|
||||
|
@ -833,8 +814,6 @@ read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
|
|||
thd->row_count++;
|
||||
continue_loop:;
|
||||
}
|
||||
if (id && !read_info.error)
|
||||
thd->insert_id(id); // For binary/update log
|
||||
DBUG_RETURN(test(read_info.error));
|
||||
}
|
||||
|
||||
|
|
|
@ -2563,11 +2563,6 @@ mysql_execute_command(THD *thd)
|
|||
statistic_increment(thd->status_var.com_stat[lex->sql_command],
|
||||
&LOCK_status);
|
||||
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
if (lex->binlog_row_based_if_mixed)
|
||||
thd->set_current_stmt_binlog_row_based_if_mixed();
|
||||
#endif /*HAVE_ROW_BASED_REPLICATION*/
|
||||
|
||||
switch (lex->sql_command) {
|
||||
case SQLCOM_SHOW_EVENTS:
|
||||
if ((res= check_access(thd, EVENT_ACL, thd->lex->select_lex.db, 0, 0, 0,
|
||||
|
@ -3394,8 +3389,9 @@ end_with_restore_list:
|
|||
res= mysql_insert(thd, all_tables, lex->field_list, lex->many_values,
|
||||
lex->update_list, lex->value_list,
|
||||
lex->duplicates, lex->ignore);
|
||||
/* do not show last insert ID if VIEW does not have auto_inc */
|
||||
if (first_table->view && !first_table->contain_auto_increment)
|
||||
thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
|
||||
thd->first_successful_insert_id_in_cur_stmt= 0;
|
||||
break;
|
||||
}
|
||||
case SQLCOM_REPLACE_SELECT:
|
||||
|
@ -3455,9 +3451,9 @@ end_with_restore_list:
|
|||
/* revert changes for SP */
|
||||
select_lex->table_list.first= (byte*) first_table;
|
||||
}
|
||||
|
||||
/* do not show last insert ID if VIEW does not have auto_inc */
|
||||
if (first_table->view && !first_table->contain_auto_increment)
|
||||
thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
|
||||
thd->first_successful_insert_id_in_cur_stmt= 0;
|
||||
break;
|
||||
}
|
||||
case SQLCOM_TRUNCATE:
|
||||
|
@ -5201,9 +5197,6 @@ end:
|
|||
*/
|
||||
if (thd->one_shot_set && lex->sql_command != SQLCOM_SET_OPTION)
|
||||
reset_one_shot_variables(thd);
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
thd->reset_current_stmt_binlog_row_based();
|
||||
#endif /*HAVE_ROW_BASED_REPLICATION*/
|
||||
|
||||
/*
|
||||
The return value for ROW_COUNT() is "implementation dependent" if the
|
||||
|
@ -5835,6 +5828,7 @@ mysql_init_query(THD *thd, uchar *buf, uint length)
|
|||
DESCRIPTION
|
||||
This needs to be called before execution of every statement
|
||||
(prepared or conventional).
|
||||
It is not called by substatements of routines.
|
||||
|
||||
TODO
|
||||
Make it a method of THD and align its name with the rest of
|
||||
|
@ -5845,9 +5839,12 @@ mysql_init_query(THD *thd, uchar *buf, uint length)
|
|||
void mysql_reset_thd_for_next_command(THD *thd)
|
||||
{
|
||||
DBUG_ENTER("mysql_reset_thd_for_next_command");
|
||||
DBUG_ASSERT(!thd->spcont); /* not for substatements of routines */
|
||||
thd->free_list= 0;
|
||||
thd->select_number= 1;
|
||||
thd->last_insert_id_used= thd->query_start_used= thd->insert_id_used=0;
|
||||
thd->auto_inc_intervals_in_cur_stmt_for_binlog.empty();
|
||||
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt=
|
||||
thd->query_start_used= 0;
|
||||
thd->is_fatal_error= thd->time_zone_used= 0;
|
||||
thd->server_status&= ~ (SERVER_MORE_RESULTS_EXISTS |
|
||||
SERVER_QUERY_NO_INDEX_USED |
|
||||
|
@ -5874,6 +5871,12 @@ void mysql_reset_thd_for_next_command(THD *thd)
|
|||
thd->rand_used= 0;
|
||||
thd->sent_row_count= thd->examined_row_count= 0;
|
||||
}
|
||||
/*
|
||||
Because we come here only for start of top-statements, binlog format is
|
||||
constant inside a complex statement (using stored functions) etc.
|
||||
*/
|
||||
thd->reset_current_stmt_binlog_row_based();
|
||||
|
||||
DBUG_VOID_RETURN;
|
||||
}
|
||||
|
||||
|
|
|
@ -7895,7 +7895,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
|||
Field *field=((Item_field*) args[0])->field;
|
||||
if (field->flags & AUTO_INCREMENT_FLAG && !field->table->maybe_null &&
|
||||
(thd->options & OPTION_AUTO_IS_NULL) &&
|
||||
thd->insert_id())
|
||||
(thd->first_successful_insert_id_in_prev_stmt > 0))
|
||||
{
|
||||
#ifdef HAVE_QUERY_CACHE
|
||||
query_cache_abort(&thd->net);
|
||||
|
@ -7903,7 +7903,7 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
|||
COND *new_cond;
|
||||
if ((new_cond= new Item_func_eq(args[0],
|
||||
new Item_int("last_insert_id()",
|
||||
thd->insert_id(),
|
||||
thd->read_first_successful_insert_id_in_prev_stmt(),
|
||||
21))))
|
||||
{
|
||||
cond=new_cond;
|
||||
|
@ -7914,7 +7914,11 @@ remove_eq_conds(THD *thd, COND *cond, Item::cond_result *cond_value)
|
|||
*/
|
||||
cond->fix_fields(thd, &cond);
|
||||
}
|
||||
thd->insert_id(0); // Clear for next request
|
||||
/*
|
||||
IS NULL should be mapped to LAST_INSERT_ID only for first row, so
|
||||
clear for next row
|
||||
*/
|
||||
thd->first_successful_insert_id_in_prev_stmt= 0;
|
||||
}
|
||||
/* fix to replace 'NULL' dates with '0' (shreeve@uci.edu) */
|
||||
else if (((field->type() == FIELD_TYPE_DATE) ||
|
||||
|
|
|
@ -4967,7 +4967,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||
char path[FN_REFLEN];
|
||||
char reg_path[FN_REFLEN+1];
|
||||
ha_rows copied,deleted;
|
||||
ulonglong next_insert_id;
|
||||
uint db_create_options, used_fields;
|
||||
handlerton *old_db_type, *new_db_type;
|
||||
HA_CREATE_INFO *create_info;
|
||||
|
@ -5787,7 +5786,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||
thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
|
||||
thd->cuted_fields=0L;
|
||||
thd->proc_info="copy to tmp table";
|
||||
next_insert_id=thd->next_insert_id; // Remember for logging
|
||||
copied=deleted=0;
|
||||
if (new_table && !(new_table->file->ha_table_flags() & HA_NO_COPY_ON_ALTER))
|
||||
{
|
||||
|
@ -5798,7 +5796,6 @@ bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
|
|||
handle_duplicates, ignore,
|
||||
order_num, order, &copied, &deleted);
|
||||
}
|
||||
thd->last_insert_id=next_insert_id; // Needed for correct log
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE;
|
||||
|
||||
/* If we did not need to copy, we might still need to add/drop indexes. */
|
||||
|
@ -6228,6 +6225,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||
ha_rows examined_rows;
|
||||
bool auto_increment_field_copied= 0;
|
||||
ulong save_sql_mode;
|
||||
ulonglong prev_insert_id;
|
||||
DBUG_ENTER("copy_data_between_tables");
|
||||
|
||||
/*
|
||||
|
@ -6334,6 +6332,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||
{
|
||||
copy_ptr->do_copy(copy_ptr);
|
||||
}
|
||||
prev_insert_id= to->file->next_insert_id;
|
||||
if ((error=to->file->ha_write_row((byte*) to->record[0])))
|
||||
{
|
||||
if (!ignore || handle_duplicates != DUP_ERROR ||
|
||||
|
@ -6357,7 +6356,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||
to->file->print_error(error,MYF(0));
|
||||
break;
|
||||
}
|
||||
to->file->restore_auto_increment();
|
||||
to->file->restore_auto_increment(prev_insert_id);
|
||||
delete_count++;
|
||||
}
|
||||
else
|
||||
|
@ -6391,6 +6390,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
|
|||
free_io_cache(from);
|
||||
*copied= found_count;
|
||||
*deleted=delete_count;
|
||||
to->file->ha_release_auto_increment();
|
||||
if (to->file->ha_external_lock(thd,F_UNLCK))
|
||||
error=1;
|
||||
DBUG_RETURN(error > 0 ? -1 : 0);
|
||||
|
|
|
@ -135,7 +135,8 @@ int mysql_update(THD *thd,
|
|||
SQL_SELECT *select;
|
||||
READ_RECORD info;
|
||||
SELECT_LEX *select_lex= &thd->lex->select_lex;
|
||||
bool need_reopen;
|
||||
bool need_reopen;
|
||||
ulonglong id;
|
||||
DBUG_ENTER("mysql_update");
|
||||
|
||||
for ( ; ; )
|
||||
|
@ -676,6 +677,10 @@ int mysql_update(THD *thd,
|
|||
thd->lock=0;
|
||||
}
|
||||
|
||||
/* If LAST_INSERT_ID(X) was used, report X */
|
||||
id= thd->arg_of_last_insert_id_function ?
|
||||
thd->first_successful_insert_id_in_prev_stmt : 0;
|
||||
|
||||
if (error < 0)
|
||||
{
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
|
@ -683,8 +688,7 @@ int mysql_update(THD *thd,
|
|||
(ulong) thd->cuted_fields);
|
||||
thd->row_count_func=
|
||||
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
|
||||
send_ok(thd, (ulong) thd->row_count_func,
|
||||
thd->insert_id_used ? thd->insert_id() : 0L,buff);
|
||||
send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
||||
DBUG_PRINT("info",("%d records updated",updated));
|
||||
}
|
||||
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
|
||||
|
@ -1634,6 +1638,7 @@ err2:
|
|||
bool multi_update::send_eof()
|
||||
{
|
||||
char buff[STRING_BUFFER_USUAL_SIZE];
|
||||
ulonglong id;
|
||||
thd->proc_info="updating reference tables";
|
||||
|
||||
/* Does updates for the last n - 1 tables, returns 0 if ok */
|
||||
|
@ -1686,12 +1691,12 @@ bool multi_update::send_eof()
|
|||
return TRUE;
|
||||
}
|
||||
|
||||
|
||||
id= thd->arg_of_last_insert_id_function ?
|
||||
thd->first_successful_insert_id_in_prev_stmt : 0;
|
||||
sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
|
||||
(ulong) thd->cuted_fields);
|
||||
thd->row_count_func=
|
||||
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
|
||||
::send_ok(thd, (ulong) thd->row_count_func,
|
||||
thd->insert_id_used ? thd->insert_id() : 0L,buff);
|
||||
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
|
||||
return FALSE;
|
||||
}
|
||||
|
|
|
@ -996,6 +996,15 @@ bool mysql_make_view(THD *thd, File_parser *parser, TABLE_LIST *table)
|
|||
table->next_global= view_tables;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ROW_BASED_REPLICATION
|
||||
/*
|
||||
If the view's body needs row-based binlogging (e.g. the VIEW is created
|
||||
from SELECT UUID()), the top statement also needs it.
|
||||
*/
|
||||
if (lex->binlog_row_based_if_mixed)
|
||||
old_lex->binlog_row_based_if_mixed= TRUE;
|
||||
#endif
|
||||
|
||||
/*
|
||||
If we are opening this view as part of implicit LOCK TABLES, then
|
||||
this view serves as simple placeholder and we should not continue
|
||||
|
|
|
@ -6403,7 +6403,7 @@ simple_expr:
|
|||
if (udf->type == UDFTYPE_AGGREGATE)
|
||||
Select->in_sum_expr--;
|
||||
|
||||
Lex->binlog_row_based_if_mixed= 1;
|
||||
Lex->binlog_row_based_if_mixed= TRUE;
|
||||
|
||||
switch (udf->returns) {
|
||||
case STRING_RESULT:
|
||||
|
|
|
@ -250,3 +250,99 @@ typedef struct user_conn {
|
|||
#define STATUS_UPDATED 16 /* Record is updated by formula */
|
||||
#define STATUS_NULL_ROW 32 /* table->null_row is set */
|
||||
#define STATUS_DELETED 64
|
||||
|
||||
/*
|
||||
Such interval is "discrete": it is the set of
|
||||
{ auto_inc_interval_min + k * increment,
|
||||
0 <= k <= (auto_inc_interval_values-1) }
|
||||
Where "increment" is maintained separately by the user of this class (and is
|
||||
currently only thd->variables.auto_increment_increment).
|
||||
It mustn't derive from Sql_alloc, because SET INSERT_ID needs to
|
||||
allocate memory which must stay allocated for use by the next statement.
|
||||
*/
|
||||
class Discrete_interval {
|
||||
private:
|
||||
ulonglong interval_min;
|
||||
ulonglong interval_values;
|
||||
ulonglong interval_max; // excluded bound. Redundant.
|
||||
public:
|
||||
Discrete_interval *next; // used when linked into Discrete_intervals_list
|
||||
void replace(ulonglong start, ulonglong val, ulonglong incr)
|
||||
{
|
||||
interval_min= start;
|
||||
interval_values= val;
|
||||
interval_max= (val == ULONGLONG_MAX) ? val : start + val * incr;
|
||||
}
|
||||
Discrete_interval(ulonglong start, ulonglong val, ulonglong incr) :
|
||||
next(NULL) { replace(start, val, incr); };
|
||||
Discrete_interval() : next(NULL) { replace(0, 0, 0); };
|
||||
ulonglong minimum() const { return interval_min; };
|
||||
ulonglong values() const { return interval_values; };
|
||||
ulonglong maximum() const { return interval_max; };
|
||||
/*
|
||||
If appending [3,5] to [1,2], we merge both in [1,5] (they should have the
|
||||
same increment for that, user of the class has to ensure that). That is
|
||||
just a space optimization. Returns 0 if merge succeeded.
|
||||
*/
|
||||
bool merge_if_contiguous(ulonglong start, ulonglong val, ulonglong incr)
|
||||
{
|
||||
if (interval_max == start)
|
||||
{
|
||||
if (val == ULONGLONG_MAX)
|
||||
{
|
||||
interval_values= interval_max= val;
|
||||
}
|
||||
else
|
||||
{
|
||||
interval_values+= val;
|
||||
interval_max= start + val * incr;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
};
|
||||
};
|
||||
|
||||
/* List of Discrete_interval objects */
|
||||
class Discrete_intervals_list {
|
||||
private:
|
||||
Discrete_interval *head;
|
||||
Discrete_interval *tail;
|
||||
/*
|
||||
When many intervals are provided at the beginning of the execution of a
|
||||
statement (in a replication slave or SET INSERT_ID), "current" points to
|
||||
the interval being consumed by the thread now (so "current" goes from
|
||||
"head" to "tail" then to NULL).
|
||||
*/
|
||||
Discrete_interval *current;
|
||||
uint elements; // number of elements
|
||||
public:
|
||||
Discrete_intervals_list() : head(NULL), current(NULL), elements(0) {};
|
||||
void empty_no_free()
|
||||
{
|
||||
head= current= NULL;
|
||||
elements= 0;
|
||||
}
|
||||
void empty()
|
||||
{
|
||||
for (Discrete_interval *i= head; i;)
|
||||
{
|
||||
Discrete_interval *next= i->next;
|
||||
delete i;
|
||||
i= next;
|
||||
}
|
||||
empty_no_free();
|
||||
}
|
||||
const Discrete_interval* get_next()
|
||||
{
|
||||
Discrete_interval *tmp= current;
|
||||
if (current != NULL)
|
||||
current= current->next;
|
||||
return tmp;
|
||||
}
|
||||
~Discrete_intervals_list() { empty(); };
|
||||
bool append(ulonglong start, ulonglong val, ulonglong incr);
|
||||
ulonglong minimum() const { return (head ? head->minimum() : 0); };
|
||||
ulonglong maximum() const { return (head ? tail->maximum() : 0); };
|
||||
uint nb_elements() const { return elements; }
|
||||
};
|
||||
|
|
|
@ -14947,7 +14947,193 @@ static void test_bug14169()
|
|||
|
||||
rc= mysql_query(mysql, "drop table t1");
|
||||
myquery(rc);
|
||||
}/*
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
Test that mysql_insert_id() behaves as documented in our manual
|
||||
*/
|
||||
static void test_mysql_insert_id()
|
||||
{
|
||||
my_ulonglong res;
|
||||
int rc;
|
||||
|
||||
myheader("test_mysql_insert_id");
|
||||
|
||||
rc= mysql_query(mysql, "drop table if exists t1");
|
||||
myquery(rc);
|
||||
/* table without auto_increment column */
|
||||
rc= mysql_query(mysql, "create table t1 (f1 int, f2 varchar(255), key(f1))");
|
||||
myquery(rc);
|
||||
rc= mysql_query(mysql, "insert into t1 values (1,'a')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t1 values (null,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t1 select 5,'c'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t1 select null,'d'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t1 values (null,last_insert_id(300))");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 300);
|
||||
rc= mysql_query(mysql, "insert into t1 select null,last_insert_id(400)");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
/*
|
||||
Behaviour change: old code used to return 0; but 400 is consistent
|
||||
with INSERT VALUES, and the manual's section of mysql_insert_id() does not
|
||||
say INSERT SELECT should be different.
|
||||
*/
|
||||
DIE_UNLESS(res == 400);
|
||||
|
||||
/* table with auto_increment column */
|
||||
rc= mysql_query(mysql, "create table t2 (f1 int not null primary key auto_increment, f2 varchar(255))");
|
||||
myquery(rc);
|
||||
rc= mysql_query(mysql, "insert into t2 values (1,'a')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 1);
|
||||
/* this should not influence next INSERT if it doesn't have auto_inc */
|
||||
rc= mysql_query(mysql, "insert into t1 values (10,'e')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 2);
|
||||
rc= mysql_query(mysql, "insert into t2 select 5,'c'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
/*
|
||||
Manual says that for multirow insert this should have been 5, but does not
|
||||
say for INSERT SELECT. This is a behaviour change: old code used to return
|
||||
0. We try to be consistent with INSERT VALUES.
|
||||
*/
|
||||
DIE_UNLESS(res == 5);
|
||||
rc= mysql_query(mysql, "insert into t2 select null,'d'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 6);
|
||||
/* with more than one row */
|
||||
rc= mysql_query(mysql, "insert into t2 values (10,'a'),(11,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 11);
|
||||
rc= mysql_query(mysql, "insert into t2 select 12,'a' union select 13,'b'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
/*
|
||||
Manual says that for multirow insert this should have been 13, but does
|
||||
not say for INSERT SELECT. This is a behaviour change: old code used to
|
||||
return 0. We try to be consistent with INSERT VALUES.
|
||||
*/
|
||||
DIE_UNLESS(res == 13);
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'a'),(null,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 14);
|
||||
rc= mysql_query(mysql, "insert into t2 select null,'a' union select null,'b'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 16);
|
||||
rc= mysql_query(mysql, "insert into t2 select 12,'a' union select 13,'b'");
|
||||
myquery_r(rc);
|
||||
rc= mysql_query(mysql, "insert ignore into t2 select 12,'a' union select 13,'b'");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert into t2 values (12,'a'),(13,'b')");
|
||||
myquery_r(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "insert ignore into t2 values (12,'a'),(13,'b')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
/* mixing autogenerated and explicit values */
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'e'),(12,'a'),(13,'b')");
|
||||
myquery_r(rc);
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'e'),(12,'a'),(13,'b'),(25,'g')");
|
||||
myquery_r(rc);
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,last_insert_id(300))");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
/*
|
||||
according to the manual, this might be 20 or 300, but it looks like
|
||||
auto_increment column takes priority over last_insert_id().
|
||||
*/
|
||||
DIE_UNLESS(res == 20);
|
||||
/* If first autogenerated number fails and 2nd works: */
|
||||
rc= mysql_query(mysql, "drop table t2");
|
||||
myquery(rc);
|
||||
rc= mysql_query(mysql, "create table t2 (f1 int not null primary key "
|
||||
"auto_increment, f2 varchar(255), unique (f2))");
|
||||
myquery(rc);
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'e')");
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 1);
|
||||
rc= mysql_query(mysql, "insert ignore into t2 values (null,'e'),(null,'a'),(null,'e')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 2);
|
||||
/* If autogenerated fails and explicit works: */
|
||||
rc= mysql_query(mysql, "insert ignore into t2 values (null,'e'),(12,'c'),(null,'d')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
/*
|
||||
Behaviour change: old code returned 3 (first autogenerated, even if it
|
||||
fails); we now return first successful autogenerated.
|
||||
*/
|
||||
DIE_UNLESS(res == 13);
|
||||
/* UPDATE may update mysql_insert_id() if it uses LAST_INSERT_ID(#) */
|
||||
rc= mysql_query(mysql, "update t2 set f1=14 where f1=12");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "update t2 set f1=NULL where f1=14");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
rc= mysql_query(mysql, "update t2 set f2=last_insert_id(372) where f1=0");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 372);
|
||||
/* check that LAST_INSERT_ID() does not update mysql_insert_id(): */
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,'g')");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 15);
|
||||
rc= mysql_query(mysql, "update t2 set f2=(@li:=last_insert_id()) where f1=15");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 0);
|
||||
/*
|
||||
Behaviour change: now if ON DUPLICATE KEY UPDATE updates a row,
|
||||
mysql_insert_id() returns the id of the row, instead of not being
|
||||
affected.
|
||||
*/
|
||||
rc= mysql_query(mysql, "insert into t2 values (null,@li) on duplicate key "
|
||||
"update f2=concat('we updated ',f2)");
|
||||
myquery(rc);
|
||||
res= mysql_insert_id(mysql);
|
||||
DIE_UNLESS(res == 15);
|
||||
|
||||
rc= mysql_query(mysql, "drop table t1,t2");
|
||||
myquery(rc);
|
||||
}
|
||||
|
||||
/*
|
||||
Read and parse arguments and MySQL options from my.cnf
|
||||
*/
|
||||
|
||||
|
@ -15214,6 +15400,7 @@ static struct my_tests_st my_tests[]= {
|
|||
{ "test_bug15613", test_bug15613 },
|
||||
{ "test_bug14169", test_bug14169 },
|
||||
{ "test_bug17667", test_bug17667 },
|
||||
{ "test_mysql_insert_id", test_mysql_insert_id },
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
|
|
|
@ -166,9 +166,9 @@ int main()
|
|||
pthread_cond_init(&cond, 0);
|
||||
my_atomic_rwlock_init(&rwl);
|
||||
|
||||
test_atomic("my_atomic_add32", test_atomic_add_handler, 100,1000000);
|
||||
test_atomic("my_atomic_swap32", test_atomic_swap_handler, 100,1000000);
|
||||
test_atomic("my_atomic_cas32", test_atomic_cas_handler, 100,1000000);
|
||||
test_atomic("my_atomic_add32", test_atomic_add_handler, 100,10000);
|
||||
test_atomic("my_atomic_swap32", test_atomic_swap_handler, 100,10000);
|
||||
test_atomic("my_atomic_cas32", test_atomic_cas_handler, 100,10000);
|
||||
|
||||
pthread_mutex_destroy(&mutex);
|
||||
pthread_cond_destroy(&cond);
|
||||
|
|
Loading…
Add table
Reference in a new issue