Commit c22a8981 authored by unknown's avatar unknown

Merge dl145k.mysql.com:/data0/mkindahl/bkroot/mysql-5.1-new-rpl

into  dl145k.mysql.com:/data0/mkindahl/bk/MERGE/mysql-5.1-merge


include/my_sys.h:
  Auto merged
mysql-test/mysql-test-run.pl:
  Auto merged
mysql-test/r/rpl_row_create_table.result:
  Auto merged
mysql-test/t/disabled.def:
  Auto merged
mysql-test/t/rpl_row_create_table.test:
  Auto merged
mysys/my_malloc.c:
  Auto merged
server-tools/instance-manager/parse.h:
  Auto merged
sql/ha_ndbcluster.cc:
  Auto merged
sql/handler.h:
  Auto merged
sql/log.cc:
  Auto merged
sql/log_event.cc:
  Auto merged
sql/mysql_priv.h:
  Auto merged
sql/set_var.h:
  Auto merged
sql/sp.cc:
  Auto merged
sql/sp_head.cc:
  Auto merged
sql/sp_head.h:
  Auto merged
sql/sql_base.cc:
  Auto merged
sql/sql_class.cc:
  Auto merged
sql/sql_insert.cc:
  Auto merged
sql/sql_lex.h:
  Auto merged
sql/sql_parse.cc:
  Auto merged
sql/sql_select.cc:
  Auto merged
sql/sql_table.cc:
  Auto merged
sql/sql_update.cc:
  Auto merged
sql/sql_view.cc:
  Auto merged
sql/sql_yacc.yy:
  Auto merged
mysys/safemalloc.c:
  Merge of mysql-5.1-new-rpl into mysql-5.1
sql/ha_federated.cc:
  d
  Merge of mysql-5.1-new-rpl into mysql-5.1
sql/set_var.cc:
  Merge of mysql-5.1-new-rpl with mysql-5.1
sql/slave.cc:
  Merge of mysql-5.1-new-rpl into mysql-5.1
sql/sql_class.h:
  Merge of mysql-5.1-new-rpl into mysql-5.1
parents a6edf110 e8f1a99a
......@@ -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;
connection master;
# 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,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;
......@@ -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;
......@@ -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;
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
......
......@@ -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;
#
# 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
......
This diff is collapsed.
......@@ -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)
......
......@@ -630,7 +630,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));
// Add a null for later termination of table name
share->scheme[table->s->connect_string.length]= 0;
......@@ -1708,14 +1709,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,
......
This diff is collapsed.
......@@ -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 */
......
......@@ -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;
}
......
This diff is collapsed.
......@@ -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:
......
This diff is collapsed.
......@@ -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) */
This diff is collapsed.
......@@ -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);
}
This diff is collapsed.
......@@ -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:
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment