diff options
144 files changed, 3674 insertions, 1712 deletions
diff --git a/mysql-test/extra/rpl_tests/rpl_ddl.test b/mysql-test/extra/rpl_tests/rpl_ddl.test index 4aab45db18b..15794e5e035 100644 --- a/mysql-test/extra/rpl_tests/rpl_ddl.test +++ b/mysql-test/extra/rpl_tests/rpl_ddl.test @@ -228,15 +228,11 @@ let $my_master_commit= true; let $my_slave_commit= true; --source include/rpl_stmt_seq.inc SELECT * FROM mysqltest1.t7; -connection slave; ---disable_query_log -SELECT '-------- switch to slave --------' as ""; ---enable_query_log +--echo -------- switch to slave -------- +sync_slave_with_master; SELECT * FROM mysqltest1.t7; +--echo -------- switch to master ------- connection master; ---disable_query_log -SELECT '-------- switch to master -------' as ""; ---enable_query_log ############################################################### # Cases with LOCK/UNLOCK diff --git a/mysql-test/extra/rpl_tests/rpl_truncate.test b/mysql-test/extra/rpl_tests/rpl_truncate.test new file mode 100644 index 00000000000..982623dfff7 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_truncate.test @@ -0,0 +1,36 @@ +# +# Copyright 2006 MySQL. All rights reserved. +# +# Test to check for the different version of truncating a table. +# The statements are "TRUNCATE tbl" and "DELETE FROM tbl". We check +# the behaviour of each possible value for BINLOG_FORMAT. +# +# Author(s): Mats Kindahl + +--source include/have_row_based.inc +--source include/master-slave.inc + +let $format = STATEMENT; +let $stmt = TRUNCATE TABLE; +--source extra/rpl_tests/rpl_truncate_helper.inc + +let $format = MIXED; +let $stmt = TRUNCATE TABLE; +--source extra/rpl_tests/rpl_truncate_helper.inc + +let $format = ROW; +let $stmt = TRUNCATE TABLE; +--source extra/rpl_tests/rpl_truncate_helper.inc + +let $format = STATEMENT; +let $stmt = DELETE FROM; +--source extra/rpl_tests/rpl_truncate_helper.inc + +let $format = MIXED; +let $stmt = DELETE FROM; +--source extra/rpl_tests/rpl_truncate_helper.inc + +let $format = ROW; +let $stmt = DELETE FROM; +--source extra/rpl_tests/rpl_truncate_helper.inc + diff --git a/mysql-test/extra/rpl_tests/rpl_truncate_helper.inc b/mysql-test/extra/rpl_tests/rpl_truncate_helper.inc new file mode 100644 index 00000000000..2306b746a86 --- /dev/null +++ b/mysql-test/extra/rpl_tests/rpl_truncate_helper.inc @@ -0,0 +1,41 @@ + +--disable_query_log +--disable_warnings +connection slave; +STOP SLAVE; +connection master; +DROP TABLE IF EXISTS t1; +RESET MASTER; +connection slave; +DROP TABLE IF EXISTS t1; +RESET SLAVE; +START SLAVE; +--enable_warnings +--enable_query_log + +--echo **** On Master **** +connection master; +eval SET SESSION BINLOG_FORMAT=$format; +eval SET GLOBAL BINLOG_FORMAT=$format; + +eval CREATE TABLE t1 (a INT, b LONG) ENGINE=$engine; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +--echo **** On Slave **** +sync_slave_with_master; +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +--echo **** On Master **** +connection master; +eval $stmt t1; +SELECT * FROM t1; +--echo **** On Slave **** +sync_slave_with_master; +# Should be empty +SELECT * FROM t1; +--echo **** On Master **** +connection master; +DROP TABLE t1; +--replace_result $SERVER_VERSION SERVER_VERSION +--replace_regex /table_id: [0-9]+/table_id: #/ +SHOW BINLOG EVENTS; diff --git a/mysql-test/include/master-slave-reset.inc b/mysql-test/include/master-slave-reset.inc new file mode 100644 index 00000000000..204c6c5f5f6 --- /dev/null +++ b/mysql-test/include/master-slave-reset.inc @@ -0,0 +1,22 @@ +connection slave; +#we expect STOP SLAVE to produce a warning as the slave is stopped +#(the server was started with skip-slave-start) +--disable_warnings +stop slave; +--wait_for_slave_to_stop +--enable_warnings +connection master; +--disable_warnings +--disable_query_log +use test; +--enable_query_log +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +--enable_warnings +reset master; +connection slave; +reset slave; +# Clean up old test tables +--disable_warnings +drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; +--enable_warnings +start slave; diff --git a/mysql-test/include/master-slave.inc b/mysql-test/include/master-slave.inc index ea09f4e842b..fe1dacb433e 100644 --- a/mysql-test/include/master-slave.inc +++ b/mysql-test/include/master-slave.inc @@ -2,28 +2,8 @@ connect (master,127.0.0.1,root,,test,$MASTER_MYPORT,); connect (master1,127.0.0.1,root,,test,$MASTER_MYPORT,); connect (slave,127.0.0.1,root,,test,$SLAVE_MYPORT,); connect (slave1,127.0.0.1,root,,test,$SLAVE_MYPORT,); -connection slave; -#we expect STOP SLAVE to produce a warning as the slave is stopped -#(the server was started with skip-slave-start) ---disable_warnings -stop slave; ---enable_warnings ---require r/slave-stopped.result -show status like 'Slave_running'; -connection master; ---disable_warnings -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; ---enable_warnings -reset master; -connection slave; -reset slave; -# Clean up old test tables ---disable_warnings -drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; ---enable_warnings -start slave; ---require r/slave-running.result -show status like 'Slave_running'; + +-- source include/master-slave-reset.inc # Set the default connection to 'master' connection master; diff --git a/mysql-test/r/binlog_row_blackhole.result b/mysql-test/r/binlog_row_blackhole.result index 42bf7a10888..140d7d4da46 100644 --- a/mysql-test/r/binlog_row_blackhole.result +++ b/mysql-test/r/binlog_row_blackhole.result @@ -118,12 +118,6 @@ master-bin.000001 # Query 1 # use `test`; COMMIT 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`; COMMIT -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`; COMMIT -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`; COMMIT master-bin.000001 # Query 1 # use `test`; create table t2 (a varchar(200)) engine=blackhole master-bin.000001 # Table_map 1 # table_id: # (test.t2) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F @@ -131,12 +125,6 @@ master-bin.000001 # Query 1 # use `test`; COMMIT master-bin.000001 # Query 1 # use `test`; alter table t1 add b int master-bin.000001 # Query 1 # use `test`; alter table t1 drop b master-bin.000001 # Query 1 # use `test`; create table t3 like t1 -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`; COMMIT -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`; COMMIT drop table t1,t2,t3; reset master; create table t1 (a int) engine=blackhole; diff --git a/mysql-test/r/binlog_row_mix_innodb_myisam.result b/mysql-test/r/binlog_row_mix_innodb_myisam.result index 84959684c42..32c21a01f27 100644 --- a/mysql-test/r/binlog_row_mix_innodb_myisam.result +++ b/mysql-test/r/binlog_row_mix_innodb_myisam.result @@ -261,26 +261,21 @@ 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 Query 1 # use `test`; delete from t1 -master-bin.000001 459 Xid 1 # COMMIT /* xid= */ -master-bin.000001 486 Table_map 1 # table_id: # (test.t2) -master-bin.000001 525 Query 1 # use `test`; delete from t2 -master-bin.000001 602 Xid 1 # COMMIT /* xid= */ -master-bin.000001 629 Query 1 # use `test`; alter table t2 engine=MyISAM -master-bin.000001 720 Table_map 1 # table_id: # (test.t1) -master-bin.000001 759 Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 793 Xid 1 # COMMIT /* xid= */ -master-bin.000001 820 Query 1 # use `test`; BEGIN -master-bin.000001 888 Table_map 1 # table_id: # (test.t1) -master-bin.000001 927 Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 956 Xid 1 # COMMIT /* xid= */ -master-bin.000001 983 Query 1 # use `test`; drop table t1,t2 -master-bin.000001 1062 Query 1 # use `test`; create table t0 (n int) -master-bin.000001 1148 Table_map 1 # table_id: # (test.t0) -master-bin.000001 1187 Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 1221 Table_map 1 # table_id: # (test.t0) -master-bin.000001 1260 Write_rows 1 # table_id: # flags: STMT_END_F -master-bin.000001 1294 Query 1 # use `test`; create table t2 (n int) engine=innodb +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 do release_lock("lock1"); drop table t0,t2; set autocommit=0; diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result index 6f8c319eb6f..c3710865b15 100644 --- a/mysql-test/r/create.result +++ b/mysql-test/r/create.result @@ -780,12 +780,6 @@ t1 CREATE TABLE `t1` ( `i` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 MAX_ROWS=4294967295 drop table t1; -create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb -character set utf8 collate utf8_general_ci; -Warnings: -Warning 1071 Specified key was too long; max key length is 765 bytes -insert into t1 values('aaa'); -drop table t1; CREATE TABLE t1 (a int, b int); insert into t1 values (1,1),(1,2); CREATE TABLE t2 (primary key (a)) select * from t1; diff --git a/mysql-test/r/federated.result b/mysql-test/r/federated.result index b3d6e10448b..5f5cd94c216 100644 --- a/mysql-test/r/federated.result +++ b/mysql-test/r/federated.result @@ -82,7 +82,7 @@ t2 CREATE TABLE `t2` ( ) ENGINE=FEDERATED DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1' INSERT INTO federated.t2 (id, name) VALUES (1, 'foo'); INSERT INTO federated.t2 (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.t2; +SELECT * FROM federated.t2 ORDER BY id, name; id name 1 foo 2 fee @@ -107,7 +107,7 @@ ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1%'; INSERT INTO federated.t1 (id, name) VALUES (1, 'foo'); INSERT INTO federated.t1 (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.t1; +SELECT * FROM federated.t1 ORDER BY id,name; id name 1 foo 2 fee @@ -121,7 +121,7 @@ ENGINE="FEDERATED" DEFAULT CHARSET=latin1 CONNECTION='mysql://root@127.0.0.1:SLAVE_PORT/federated/t1%'; INSERT INTO federated.`t1%` (id, name) VALUES (1, 'foo'); INSERT INTO federated.`t1%` (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.`t1%`; +SELECT * FROM federated.`t1%` ORDER BY id, name; id name 1 foo 2 fee diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result index eca6d148567..72ae29185bc 100644 --- a/mysql-test/r/innodb.result +++ b/mysql-test/r/innodb.result @@ -1378,9 +1378,9 @@ insert into `t2`values ( 1 ) ; create table `t3` (`id` int( 11 ) not null default '0',key `id` ( `id` ) ,constraint `t2_id_fk` foreign key ( `id` ) references `t2` (`id` )) engine = innodb; insert into `t3`values ( 1 ) ; delete t3,t2,t1 from t1,t2,t3 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)) update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)) update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id; ERROR 42S22: Unknown column 't1.id' in 'where clause' drop table t3,t2,t1; @@ -1392,7 +1392,7 @@ foreign key(pid) references t1(id) on delete cascade) engine=innodb; insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6), (8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14); delete from t1 where id=0; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `t1` (`id`) ON DELETE CASCADE) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t1`, CONSTRAINT `t1_ibfk_1` FOREIGN KEY (`pid`) REFERENCES `t1` (`id`) ON DELETE CASCADE) delete from t1 where id=15; delete from t1 where id=0; drop table t1; @@ -2633,18 +2633,18 @@ v INT, CONSTRAINT c1 FOREIGN KEY (v) REFERENCES t1(id) ) ENGINE=InnoDB; INSERT INTO t2 VALUES(2); -ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) INSERT INTO t1 VALUES(1); INSERT INTO t2 VALUES(1); DELETE FROM t1 WHERE id = 1; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) DROP TABLE t1; ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails SET FOREIGN_KEY_CHECKS=0; DROP TABLE t1; SET FOREIGN_KEY_CHECKS=1; INSERT INTO t2 VALUES(3); -ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c1` FOREIGN KEY (`v`) REFERENCES `t1` (`id`)) DROP TABLE t2; create table t1(a int not null) engine=innodb DEFAULT CHARSET=latin1; insert into t1 values (1),(2); @@ -2922,23 +2922,23 @@ create table t4(a int primary key,constraint foreign key(a)references t3(a)) row insert into t1 values(1); insert into t3 values(1); insert into t2 values(2); -ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) insert into t4 values(2); -ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) insert into t2 values(1); insert into t4 values(1); update t1 set a=2; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) update t2 set a=2; -ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) update t3 set a=2; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) update t4 set a=2; -ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) truncate t1; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t1` (`a`)) truncate t3; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t4`, CONSTRAINT `t4_ibfk_1` FOREIGN KEY (`a`) REFERENCES `t3` (`a`)) truncate t2; truncate t4; truncate t1; @@ -2993,7 +2993,7 @@ create table t1 (a int primary key,s1 varbinary(3) not null unique) engine=innod create table t2 (s1 binary(2) not null, constraint c foreign key(s1) references t1(s1) on update cascade) engine=innodb; insert into t1 values(1,0x4100),(2,0x41),(3,0x4120),(4,0x42); insert into t2 values(0x42); -ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +ERROR 23000: Cannot add or update a child row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) insert into t2 values(0x41); select hex(s1) from t2; hex(s1) @@ -3003,11 +3003,11 @@ select hex(s1) from t2; hex(s1) 4100 update t1 set s1=0x12 where a=1; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) update t1 set s1=0x12345678 where a=1; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) update t1 set s1=0x123457 where a=1; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) update t1 set s1=0x1220 where a=1; select hex(s1) from t2; hex(s1) @@ -3021,11 +3021,11 @@ select hex(s1) from t2; hex(s1) 4200 delete from t1 where a=1; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) delete from t1 where a=2; update t2 set s1=0x4120; delete from t1; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) delete from t1 where a!=3; select a,hex(s1) from t1; a hex(s1) @@ -3051,7 +3051,7 @@ hex(s1) 12 delete from t1 where a=1; delete from t1 where a=2; -ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test/t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) +ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails (`test`.`t2`, CONSTRAINT `c` FOREIGN KEY (`s1`) REFERENCES `t1` (`s1`) ON UPDATE CASCADE) select a,hex(s1) from t1; a hex(s1) 2 12 diff --git a/mysql-test/r/innodb_mysql.result b/mysql-test/r/innodb_mysql.result index 918f1c2c7c5..62e1c2f4019 100644 --- a/mysql-test/r/innodb_mysql.result +++ b/mysql-test/r/innodb_mysql.result @@ -1,4 +1,10 @@ drop table if exists t1,t2,t1m,t1i,t2m,t2i,t4; +create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb +character set utf8 collate utf8_general_ci; +Warnings: +Warning 1071 Specified key was too long; max key length is 765 bytes +insert into t1 values('aaa'); +drop table t1; create table t1 ( c_id int(11) not null default '0', org_id int(11) default null, diff --git a/mysql-test/r/ndb_binlog_ignore_db.result b/mysql-test/r/ndb_binlog_ignore_db.result index 2f411fcd03d..8dc2c1ff1f8 100644 --- a/mysql-test/r/ndb_binlog_ignore_db.result +++ b/mysql-test/r/ndb_binlog_ignore_db.result @@ -7,6 +7,4 @@ insert into t1 values (1, 1); show binlog events from <binlog_start>; Log_name Pos Event_type Server_id End_log_pos Info master-bin.000001 # Query # # use `test`; drop table if exists t1 -master-bin.000001 # Table_map # # table_id: # (mysql.proc) -master-bin.000001 # Write_rows # # table_id: # flags: STMT_END_F drop database mysqltest; diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result index f6b7409ea6a..f687ab7e2c6 100644 --- a/mysql-test/r/range.result +++ b/mysql-test/r/range.result @@ -406,7 +406,7 @@ insert into t2(uid, name) values (24, CHAR(64+24)), (25, CHAR(64+25)), (26, CHAR(64+26)); -insert into t1(uid, name) select uid, name from t2; +insert into t1(uid, name) select uid, name from t2 order by uid; delete from t2; insert into t2(id, uid, name) select id, uid, name from t1; select count(*) from t1; diff --git a/mysql-test/r/rpl_ddl.result b/mysql-test/r/rpl_ddl.result index cfa2b4dc76d..ace86532b12 100644 --- a/mysql-test/r/rpl_ddl.result +++ b/mysql-test/r/rpl_ddl.result @@ -646,11 +646,9 @@ flush logs; -------- switch to master ------- SELECT * FROM mysqltest1.t7; f1 - -------- switch to slave -------- SELECT * FROM mysqltest1.t7; f1 - -------- switch to master ------- ######## LOCK TABLES mysqltest1.t1 WRITE, mysqltest1.t8 READ ######## diff --git a/mysql-test/r/rpl_ndb_charset.result b/mysql-test/r/rpl_ndb_charset.result index 31a7e1368f3..0ce4446c8a5 100644 --- a/mysql-test/r/rpl_ndb_charset.result +++ b/mysql-test/r/rpl_ndb_charset.result @@ -112,16 +112,10 @@ drop database mysqltest3; 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 mysqltest2 -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 # drop database if exists mysqltest3 -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 mysqltest2 character set latin2 master-bin.000001 # Query 1 # create database mysqltest3 master-bin.000001 # Query 1 # drop database mysqltest3 -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 mysqltest3 master-bin.000001 # Query 1 # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100)) master-bin.000001 # Table_map 1 # table_id: # (mysqltest2.t1) @@ -147,11 +141,7 @@ master-bin.000001 # Query 1 # use `mysqltest2`; truncate table t1 master-bin.000001 # Table_map 1 # table_id: # (mysqltest2.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # drop database mysqltest2 -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 # drop database mysqltest3 -master-bin.000001 # Table_map 1 # table_id: # (mysql.proc) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F select "--- --global--" as ""; --- --global-- diff --git a/mysql-test/r/rpl_row_basic_11bugs.result b/mysql-test/r/rpl_row_basic_11bugs.result index 4ed7d54647b..8c8a77b5084 100644 --- a/mysql-test/r/rpl_row_basic_11bugs.result +++ b/mysql-test/r/rpl_row_basic_11bugs.result @@ -44,3 +44,19 @@ t1 USE test_ignore; ERROR 42000: Unknown database 'test_ignore' DROP DATABASE test_ignore; +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 TABLE t1 (a INT); +DELETE FROM t1; +INSERT INTO t1 VALUES (1),(2); +DELETE FROM t1 WHERE a = 0; +UPDATE t1 SET a=99 WHERE a = 0; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: 5.1.11-beta-debug-log, Binlog ver: 4 +master-bin.000001 102 Query 1 188 use `test`; CREATE TABLE t1 (a INT) +master-bin.000001 188 Table_map 1 227 table_id: # (test.t1) +master-bin.000001 227 Write_rows 1 266 table_id: # flags: STMT_END_F diff --git a/mysql-test/r/rpl_row_charset.result b/mysql-test/r/rpl_row_charset.result index d80b5fa60de..79cf75c8cc1 100644 --- a/mysql-test/r/rpl_row_charset.result +++ b/mysql-test/r/rpl_row_charset.result @@ -112,16 +112,10 @@ drop database mysqltest3; 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 mysqltest2 -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 # drop database if exists mysqltest3 -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 mysqltest2 character set latin2 master-bin.000001 # Query 1 # create database mysqltest3 master-bin.000001 # Query 1 # drop database mysqltest3 -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 mysqltest3 master-bin.000001 # Query 1 # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100)) master-bin.000001 # Table_map 1 # table_id: # (mysqltest2.t1) @@ -147,11 +141,7 @@ master-bin.000001 # Query 1 # use `mysqltest2`; truncate table t1 master-bin.000001 # Table_map 1 # table_id: # (mysqltest2.t1) master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F master-bin.000001 # Query 1 # drop database mysqltest2 -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 # drop database mysqltest3 -master-bin.000001 # Table_map 1 # table_id: # (mysql.proc) -master-bin.000001 # Write_rows 1 # table_id: # flags: STMT_END_F select "--- --global--" as ""; --- --global-- diff --git a/mysql-test/r/rpl_row_create_table.result b/mysql-test/r/rpl_row_create_table.result index b3a8f5e1a0f..f314aa39b81 100644 --- a/mysql-test/r/rpl_row_create_table.result +++ b/mysql-test/r/rpl_row_create_table.result @@ -127,7 +127,7 @@ NULL 5 10 NULL 6 12 CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3; ERROR 23000: Duplicate entry '2' for key 'b' -SHOW BINLOG EVENTS FROM 1326; +SHOW BINLOG EVENTS FROM 1256; Log_name Pos Event_type Server_id End_log_pos Info CREATE TABLE t7 (a INT, b INT UNIQUE); INSERT INTO t7 SELECT a,b FROM tt3; @@ -137,11 +137,11 @@ a b 1 2 2 4 3 6 -SHOW BINLOG EVENTS FROM 1326; +SHOW BINLOG EVENTS FROM 1256; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 1326 Query 1 1426 use `test`; CREATE TABLE t7 (a INT, b INT UNIQUE) -master-bin.000001 1426 Table_map 1 1466 table_id: # (test.t7) -master-bin.000001 1466 Write_rows 1 1522 table_id: # flags: STMT_END_F +master-bin.000001 1256 Query 1 1356 use `test`; CREATE TABLE t7 (a INT, b INT UNIQUE) +master-bin.000001 1356 Table_map 1 1396 table_id: # (test.t7) +master-bin.000001 1396 Write_rows 1 1452 table_id: # flags: STMT_END_F SELECT * FROM t7 ORDER BY a,b; a b 1 2 @@ -154,10 +154,10 @@ INSERT INTO t7 SELECT a,b FROM tt4; ROLLBACK; Warnings: Warning 1196 Some non-transactional changed tables couldn't be rolled back -SHOW BINLOG EVENTS FROM 1522; +SHOW BINLOG EVENTS FROM 1452; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 1522 Table_map 1 1562 table_id: # (test.t7) -master-bin.000001 1562 Write_rows 1 1618 table_id: # flags: STMT_END_F +master-bin.000001 1452 Table_map 1 1492 table_id: # (test.t7) +master-bin.000001 1492 Write_rows 1 1548 table_id: # flags: STMT_END_F SELECT * FROM t7 ORDER BY a,b; a b 1 2 @@ -191,10 +191,10 @@ Create Table CREATE TABLE `t9` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL ) ENGINE=MyISAM DEFAULT CHARSET=latin1 -SHOW BINLOG EVENTS FROM 1618; +SHOW BINLOG EVENTS FROM 1548; Log_name Pos Event_type Server_id End_log_pos Info -master-bin.000001 1618 Query 1 1704 use `test`; CREATE TABLE t8 LIKE t4 -master-bin.000001 1704 Query 1 1843 use `test`; CREATE TABLE `t9` ( +master-bin.000001 1548 Query 1 1634 use `test`; CREATE TABLE t8 LIKE t4 +master-bin.000001 1634 Query 1 1773 use `test`; CREATE TABLE `t9` ( `a` int(11) DEFAULT NULL, `b` int(11) DEFAULT NULL ) diff --git a/mysql-test/r/rpl_row_inexist_tbl.result b/mysql-test/r/rpl_row_inexist_tbl.result index 1d18819fdd6..5f5a4556d76 100644 --- a/mysql-test/r/rpl_row_inexist_tbl.result +++ b/mysql-test/r/rpl_row_inexist_tbl.result @@ -5,9 +5,18 @@ reset slave; drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9; start slave; create table t1 (a int not null primary key); +insert into t1 values (1); +create table t2 (a int); +insert into t2 values (1); +update t1, t2 set t1.a = 0 where t1.a = t2.a; +show tables; +Tables_in_test +t1 +select * from t1; +a +0 drop table t1; insert into t1 values (1); -insert into t1 values (2); show slave status; Slave_IO_State # Master_Host 127.0.0.1 @@ -24,13 +33,13 @@ Slave_SQL_Running No Replicate_Do_DB Replicate_Ignore_DB Replicate_Do_Table -Replicate_Ignore_Table +Replicate_Ignore_Table test.t2 Replicate_Wild_Do_Table Replicate_Wild_Ignore_Table Last_Errno 1146 Last_Error Error 'Table 'test.t1' doesn't exist' on opening table `test`.`t1` Skip_Counter 0 -Exec_Master_Log_Pos 209 +Exec_Master_Log_Pos 519 Relay_Log_Space # Until_Condition None Until_Log_File @@ -42,4 +51,4 @@ Master_SSL_Cert Master_SSL_Cipher Master_SSL_Key Seconds_Behind_Master # -drop table t1; +drop table t1, t2; diff --git a/mysql-test/r/rpl_sp_effects.result b/mysql-test/r/rpl_sp_effects.result index 26455b65beb..b42fe64e603 100644 --- a/mysql-test/r/rpl_sp_effects.result +++ b/mysql-test/r/rpl_sp_effects.result @@ -124,9 +124,9 @@ delete from t1; delete from t2; delete from t1; insert into t2 values(1),(2); -create view v1 as select f1(a) from t2; -select * from v1; -f1(a) +create view v1 as select f1(a) as f from t2; +select * from v1 order by f; +f 2 3 SELECT 'master:',a FROM t1 ORDER BY a; diff --git a/mysql-test/r/rpl_truncate_2myisam.result b/mysql-test/r/rpl_truncate_2myisam.result new file mode 100644 index 00000000000..41640a709b9 --- /dev/null +++ b/mysql-test/r/rpl_truncate_2myisam.result @@ -0,0 +1,202 @@ +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; +**** On Master **** +SET SESSION BINLOG_FORMAT=STATEMENT; +SET GLOBAL BINLOG_FORMAT=STATEMENT; +CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +TRUNCATE TABLE t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM +master-bin.000001 210 Query 1 307 use `test`; INSERT INTO t1 VALUES (1,1), (2,2) +master-bin.000001 307 Query 1 387 use `test`; TRUNCATE TABLE t1 +master-bin.000001 387 Query 1 463 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=MIXED; +SET GLOBAL BINLOG_FORMAT=MIXED; +CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +TRUNCATE TABLE t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM +master-bin.000001 210 Query 1 307 use `test`; INSERT INTO t1 VALUES (1,1), (2,2) +master-bin.000001 307 Query 1 387 use `test`; TRUNCATE TABLE t1 +master-bin.000001 387 Query 1 463 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=ROW; +SET GLOBAL BINLOG_FORMAT=ROW; +CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +TRUNCATE TABLE t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM +master-bin.000001 210 Table_map 1 250 table_id: # (test.t1) +master-bin.000001 250 Write_rows 1 297 table_id: # flags: STMT_END_F +master-bin.000001 297 Query 1 377 use `test`; TRUNCATE TABLE t1 +master-bin.000001 377 Query 1 453 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=STATEMENT; +SET GLOBAL BINLOG_FORMAT=STATEMENT; +CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +DELETE FROM t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM +master-bin.000001 210 Query 1 307 use `test`; INSERT INTO t1 VALUES (1,1), (2,2) +master-bin.000001 307 Query 1 384 use `test`; DELETE FROM t1 +master-bin.000001 384 Query 1 460 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=MIXED; +SET GLOBAL BINLOG_FORMAT=MIXED; +CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +DELETE FROM t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM +master-bin.000001 210 Query 1 307 use `test`; INSERT INTO t1 VALUES (1,1), (2,2) +master-bin.000001 307 Query 1 384 use `test`; DELETE FROM t1 +master-bin.000001 384 Query 1 460 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=ROW; +SET GLOBAL BINLOG_FORMAT=ROW; +CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +DELETE FROM t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +3 3 +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=MyISAM +master-bin.000001 210 Table_map 1 250 table_id: # (test.t1) +master-bin.000001 250 Write_rows 1 297 table_id: # flags: STMT_END_F +master-bin.000001 297 Table_map 1 337 table_id: # (test.t1) +master-bin.000001 337 Delete_rows 1 384 table_id: # flags: STMT_END_F +master-bin.000001 384 Query 1 460 use `test`; DROP TABLE t1 diff --git a/mysql-test/r/rpl_truncate_3innodb.result b/mysql-test/r/rpl_truncate_3innodb.result new file mode 100644 index 00000000000..062c9704ae0 --- /dev/null +++ b/mysql-test/r/rpl_truncate_3innodb.result @@ -0,0 +1,214 @@ +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; +**** On Master **** +SET SESSION BINLOG_FORMAT=STATEMENT; +SET GLOBAL BINLOG_FORMAT=STATEMENT; +CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +TRUNCATE TABLE t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB +master-bin.000001 210 Query 1 97 use `test`; INSERT INTO t1 VALUES (1,1), (2,2) +master-bin.000001 307 Xid 1 334 COMMIT /* xid= */ +master-bin.000001 334 Query 1 80 use `test`; TRUNCATE TABLE t1 +master-bin.000001 414 Xid 1 441 COMMIT /* xid= */ +master-bin.000001 441 Query 1 517 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=MIXED; +SET GLOBAL BINLOG_FORMAT=MIXED; +CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +TRUNCATE TABLE t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB +master-bin.000001 210 Query 1 97 use `test`; INSERT INTO t1 VALUES (1,1), (2,2) +master-bin.000001 307 Xid 1 334 COMMIT /* xid= */ +master-bin.000001 334 Query 1 80 use `test`; TRUNCATE TABLE t1 +master-bin.000001 414 Xid 1 441 COMMIT /* xid= */ +master-bin.000001 441 Query 1 517 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=ROW; +SET GLOBAL BINLOG_FORMAT=ROW; +CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +TRUNCATE TABLE t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB +master-bin.000001 210 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 250 Write_rows 1 87 table_id: # flags: STMT_END_F +master-bin.000001 297 Xid 1 324 COMMIT /* xid= */ +master-bin.000001 324 Query 1 80 use `test`; TRUNCATE TABLE t1 +master-bin.000001 404 Xid 1 431 COMMIT /* xid= */ +master-bin.000001 431 Query 1 507 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=STATEMENT; +SET GLOBAL BINLOG_FORMAT=STATEMENT; +CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +DELETE FROM t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB +master-bin.000001 210 Query 1 97 use `test`; INSERT INTO t1 VALUES (1,1), (2,2) +master-bin.000001 307 Xid 1 334 COMMIT /* xid= */ +master-bin.000001 334 Query 1 77 use `test`; DELETE FROM t1 +master-bin.000001 411 Xid 1 438 COMMIT /* xid= */ +master-bin.000001 438 Query 1 514 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=MIXED; +SET GLOBAL BINLOG_FORMAT=MIXED; +CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +DELETE FROM t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB +master-bin.000001 210 Query 1 97 use `test`; INSERT INTO t1 VALUES (1,1), (2,2) +master-bin.000001 307 Xid 1 334 COMMIT /* xid= */ +master-bin.000001 334 Query 1 77 use `test`; DELETE FROM t1 +master-bin.000001 411 Xid 1 438 COMMIT /* xid= */ +master-bin.000001 438 Query 1 514 use `test`; DROP TABLE t1 +**** On Master **** +SET SESSION BINLOG_FORMAT=ROW; +SET GLOBAL BINLOG_FORMAT=ROW; +CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1; +a b +1 1 +2 2 +3 3 +**** On Master **** +DELETE FROM t1; +SELECT * FROM t1; +a b +**** On Slave **** +SELECT * FROM t1; +a b +3 3 +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 210 use `test`; CREATE TABLE t1 (a INT, b LONG) ENGINE=InnoDB +master-bin.000001 210 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 250 Write_rows 1 87 table_id: # flags: STMT_END_F +master-bin.000001 297 Xid 1 324 COMMIT /* xid= */ +master-bin.000001 324 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 364 Delete_rows 1 87 table_id: # flags: STMT_END_F +master-bin.000001 411 Xid 1 438 COMMIT /* xid= */ +master-bin.000001 438 Query 1 514 use `test`; DROP TABLE t1 diff --git a/mysql-test/r/rpl_truncate_7ndb.result b/mysql-test/r/rpl_truncate_7ndb.result new file mode 100644 index 00000000000..b33f8f1ccaa --- /dev/null +++ b/mysql-test/r/rpl_truncate_7ndb.result @@ -0,0 +1,105 @@ +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; +**** On Master **** +CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1 ORDER BY a,b; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1 ORDER BY a,b; +a b +1 1 +2 2 +3 3 +**** On Master **** +TRUNCATE TABLE t1; +SELECT * FROM t1 ORDER BY a,b; +a b +**** On Slave **** +SELECT * FROM t1 ORDER BY a,b; +a b +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB +master-bin.000001 219 Query 1 283 BEGIN +master-bin.000001 283 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 323 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 376 Write_rows 1 135 table_id: # +master-bin.000001 418 Write_rows 1 182 table_id: # flags: STMT_END_F +master-bin.000001 465 Query 1 530 COMMIT +master-bin.000001 530 Query 1 80 use `test`; TRUNCATE TABLE t1 +master-bin.000001 610 Query 1 679 use `test`; COMMIT +master-bin.000001 679 Query 1 743 BEGIN +master-bin.000001 743 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 783 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 836 Write_rows 1 135 table_id: # +master-bin.000001 878 Delete_rows 1 174 table_id: # flags: STMT_END_F +master-bin.000001 917 Query 1 982 COMMIT +master-bin.000001 982 Query 1 1058 use `test`; DROP TABLE t1 +**** On Master **** +CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1 ORDER BY a,b; +a b +1 1 +2 2 +**** On Slave **** +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1 ORDER BY a,b; +a b +1 1 +2 2 +3 3 +**** On Master **** +DELETE FROM t1; +SELECT * FROM t1 ORDER BY a,b; +a b +**** On Slave **** +SELECT * FROM t1 ORDER BY a,b; +a b +3 3 +**** On Master **** +DROP TABLE t1; +SHOW BINLOG EVENTS; +Log_name Pos Event_type Server_id End_log_pos Info +master-bin.000001 4 Format_desc 1 102 Server ver: SERVER_VERSION, Binlog ver: 4 +master-bin.000001 102 Query 1 219 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB +master-bin.000001 219 Query 1 283 BEGIN +master-bin.000001 283 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 323 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 376 Write_rows 1 135 table_id: # +master-bin.000001 418 Write_rows 1 182 table_id: # flags: STMT_END_F +master-bin.000001 465 Query 1 530 COMMIT +master-bin.000001 530 Query 1 80 use `test`; TRUNCATE TABLE t1 +master-bin.000001 610 Query 1 679 use `test`; COMMIT +master-bin.000001 679 Query 1 743 BEGIN +master-bin.000001 743 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 783 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 836 Write_rows 1 135 table_id: # +master-bin.000001 878 Delete_rows 1 174 table_id: # flags: STMT_END_F +master-bin.000001 917 Query 1 982 COMMIT +master-bin.000001 982 Query 1 1058 use `test`; DROP TABLE t1 +master-bin.000001 1058 Query 1 1175 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB +master-bin.000001 1175 Query 1 1239 BEGIN +master-bin.000001 1239 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 1279 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 1332 Write_rows 1 135 table_id: # +master-bin.000001 1374 Write_rows 1 182 table_id: # flags: STMT_END_F +master-bin.000001 1421 Query 1 1486 COMMIT +master-bin.000001 1486 Query 1 1550 BEGIN +master-bin.000001 1550 Table_map 1 40 table_id: # (test.t1) +master-bin.000001 1590 Table_map 1 93 table_id: # (cluster.apply_status) +master-bin.000001 1643 Write_rows 1 135 table_id: # +master-bin.000001 1685 Delete_rows 1 174 table_id: # flags: STMT_END_F +master-bin.000001 1724 Query 1 1789 COMMIT +master-bin.000001 1789 Query 1 1865 use `test`; DROP TABLE t1 diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result index 5dcb8b2afd6..267993d9354 100644 --- a/mysql-test/r/show_check.result +++ b/mysql-test/r/show_check.result @@ -382,9 +382,9 @@ Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length I t1 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL t2 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL t3 MEMORY 10 Fixed 4 # # # # # NULL NULL NULL NULL latin1_swedish_ci NULL -delete from t1; -delete from t2; -delete from t3; +truncate table t1; +truncate table t2; +truncate table t3; show table status; Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment t1 MEMORY 10 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result index fde273c55ee..29206393b04 100644 --- a/mysql-test/r/sp-error.result +++ b/mysql-test/r/sp-error.result @@ -368,7 +368,7 @@ end| insert into t1 values (666, 51.3)| call bug2272()| ERROR 42S22: Unknown column 'v' in 'field list' -delete from t1| +truncate table t1| drop procedure bug2272| create procedure bug2329_1() begin @@ -520,7 +520,7 @@ declare exit handler for sqlexception select 'Error!'; open c; fetch c into v; end| -delete from t1| +truncate table t1| call bug7299()| ERROR 02000: No data - zero rows fetched, selected, or processed drop procedure bug7299| @@ -621,7 +621,7 @@ val x bug8408() 3 3.14 3 7 7 3 drop function bug8408| -delete from t1| +truncate table t1| drop procedure if exists bug10537| create procedure bug10537() load data local infile '/tmp/somefile' into table t1| diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result index 9bdd1d5645f..39ab34c86bb 100644 --- a/mysql-test/r/sp.result +++ b/mysql-test/r/sp.result @@ -78,7 +78,7 @@ replace t1 set data = data, id = "bar"; update t1 set id = "kaka", data = 3 where t1.data = data; end| call setcontext()| -select * from t1| +select * from t1 order by data| id data foo 1 kaka 3 @@ -191,7 +191,7 @@ drop procedure if exists inc| create procedure inc(inout io int) set io = io + 1| call iotest("io1", "io2", 1)| -select * from t1| +select * from t1 order by data desc| id data io2 2 io1 1 @@ -224,7 +224,7 @@ set y2 = 4711; insert into test.t1 values ("cbv2", y1); end| call cbv1()| -select * from t1| +select * from t1 order by data| id data cbv2 4 cbv1 4711 @@ -251,7 +251,7 @@ call sub1("sub1c", (select i,d from t2 limit 1))| ERROR 21000: Operand should contain 1 column(s) call sub1("sub1d", (select 1 from (select 1) a))| call sub2("sub2")| -select * from t1| +select * from t1 order by id| id data sub1a 7 sub1b 3 @@ -272,7 +272,7 @@ set x = x-1; insert into test.t1 values ("a0", x); end while| call a0(3)| -select * from t1| +select * from t1 order by data desc| id data a0 2 a0 1 @@ -286,7 +286,7 @@ set x = x-1; insert into test.t1 values ("a", x); end while| call a(3)| -select * from t1| +select * from t1 order by data desc| id data a 2 a 1 @@ -300,7 +300,7 @@ insert into test.t1 values (repeat("b",3), x); set x = x-1; until x = 0 end repeat| call b(3)| -select * from t1| +select * from t1 order by data desc| id data bbb 3 bbb 2 @@ -323,7 +323,7 @@ iterate hmm; insert into test.t1 values ("x", x); end while hmm| call c(3)| -select * from t1| +select * from t1 order by data desc| id data c 3 c 2 @@ -354,7 +354,7 @@ insert into test.t1 values ("e", x); set x = x-1; end loop foo| call e(3)| -select * from t1| +select * from t1 order by data desc| id data e 3 e 2 @@ -373,7 +373,7 @@ end if| call f(-2)| call f(0)| call f(4)| -select * from t1| +select * from t1 order by data| id data f 0 f 1 @@ -393,7 +393,7 @@ end case| call g(-42)| call g(0)| call g(1)| -select * from t1| +select * from t1 order by data| id data g 0 g 1 @@ -413,7 +413,7 @@ end case| call h(0)| call h(1)| call h(17)| -select * from t1| +select * from t1 order by data| id data h0 0 h1 1 @@ -441,7 +441,7 @@ insert into t2 values ("x", 9, 4.1), ("y", -1, 19.2), ("z", 3, 2.2)| drop procedure if exists sel1| create procedure sel1() begin -select * from t1; +select * from t1 order by data; end| call sel1()| id data @@ -451,8 +451,8 @@ drop procedure sel1| drop procedure if exists sel2| create procedure sel2() begin -select * from t1; -select * from t2; +select * from t1 order by data; +select * from t2 order by s; end| call sel2()| id data @@ -473,7 +473,7 @@ select id,data into x,y from test.t1 limit 1; insert into test.t1 values (concat(x, "2"), y+2); end| call into_test("into", 100)| -select * from t1| +select * from t1 order by data| id data into 100 into2 102 @@ -487,7 +487,7 @@ select id,data into x,@z from test.t1 limit 1; insert into test.t1 values (concat(x, "2"), y+2); end| call into_test2("into", 100)| -select id,data,@z from t1| +select id,data,@z from t1 order by data| id data @z into 100 100 into2 102 100 @@ -619,14 +619,14 @@ insert into t2 values (append("a", "b"), mul(2,mul(3,4)), fun(1.7, 4, 6))| select * from t2 where s = append("a", "b")| s i d ab 24 1324.36598821719 -select * from t2 where i = mul(4,3) or i = mul(mul(3,4),2)| +select * from t2 where i = mul(4,3) or i = mul(mul(3,4),2) order by i| s i d xxxyyy 12 2.71828182845905 ab 24 1324.36598821719 select * from t2 where d = e()| s i d xxxyyy 12 2.71828182845905 -select * from t2| +select * from t2 order by i| s i d xxxyyy 12 2.71828182845905 ab 24 1324.36598821719 @@ -745,8 +745,8 @@ drop procedure if exists cur2| create procedure cur2() begin declare done int default 0; -declare c1 cursor for select id,data from test.t1; -declare c2 cursor for select i from test.t2; +declare c1 cursor for select id,data from test.t1 order by id,data; +declare c2 cursor for select i from test.t2 order by i; declare continue handler for sqlstate '02000' set done = 1; open c1; open c2; @@ -769,10 +769,10 @@ close c1; close c2; end| call cur2()| -select * from t3| +select * from t3 order by i,s| s i -foo 40 bar 3 +foo 40 zap 663 delete from t1| delete from t2| @@ -935,16 +935,16 @@ return (select sum(data) from t1)| select f1()| f1() 3 -select id, f1() from t1| +select id, f1() from t1 order by id| id f1() a 3 b 3 create function f2() returns int -return (select data from t1 where data <= (select sum(data) from t1) limit 1)| +return (select data from t1 where data <= (select sum(data) from t1) order by data limit 1)| select f2()| f2() 1 -select id, f2() from t1| +select id, f2() from t1 order by id| id f2() a 1 b 1 @@ -959,14 +959,14 @@ end| select f3()| f3() 1 -select id, f3() from t1| +select id, f3() from t1 order by id| id f3() a 1 b 1 select f1(), f3()| f1() f3() 3 1 -select id, f1(), f3() from t1| +select id, f1(), f3() from t1 order by id| id f1() f3() a 3 1 b 3 1 @@ -975,7 +975,7 @@ return (select d from t1, t2 where t1.data = t2.i and t1.id= "b")| select f4()| f4() 2 -select s, f4() from t2| +select s, f4() from t2 order by s| s f4() a 2 b 2 @@ -1008,7 +1008,7 @@ return (select sum(data) from t1 where data <= f1())| select f6()| f6() 2 -select id, f6() from t1| +select id, f6() from t1 order by id| id f6() a 2 b 2 @@ -1016,7 +1016,7 @@ create view v1 (a) as select f1()| select * from v1| a 3 -select id, a from t1, v1| +select id, a from t1, v1 order by id| id a a 3 b 3 @@ -1027,7 +1027,7 @@ create view v2 (a) as select a*10 from v1| select * from v2| a 30 -select id, a from t1, v2| +select id, a from t1, v2 order by id| id a a 30 b 30 @@ -1072,7 +1072,7 @@ lock tables t1 read, t1 as t11 read| select f3()| f3() 1 -select id, f3() from t1 as t11| +select id, f3() from t1 as t11 order by id| id f3() a 1 b 1 @@ -1175,8 +1175,8 @@ drop function f12_2| drop view v0| drop view v1| drop view v2| -delete from t1 | -delete from t2 | +truncate table t1 | +truncate table t2 | drop table t4| drop table if exists t3| create table t3 (n int unsigned not null primary key, f bigint unsigned)| @@ -1355,7 +1355,7 @@ f 1 1 2 -delete from t3| +truncate table t3| insert into t3 values (0), (1)| call fib(10)| select * from t3 order by f asc| @@ -1814,7 +1814,7 @@ delete from t1| call bug822('foo', 42)| call bug822('foo', 42)| call bug822('bar', 666)| -select * from t1| +select * from t1 order by data| id data foo 42 bar 666 @@ -1837,7 +1837,7 @@ delete from t1 where id='foo'| insert into t1 values ('bar', 7)| call bug1495()| delete from t1 where id='bar'| -select * from t1| +select * from t1 order by data| id data less 2 more 17 @@ -1857,10 +1857,10 @@ end| insert into t1 values ("foo", 12), ("bar", 7)| call bug1547("foo")| call bug1547("bar")| -select * from t1| +select * from t1 order by id| id data -foo 12 bar 7 +foo 12 less 2 more 17 delete from t1| @@ -1908,12 +1908,12 @@ insert into t2 values ("avg", 0, y); end| insert into t1 (data) values (3), (1), (5), (9), (4)| call bug1874()| -select * from t2| +select * from t2 order by i| s i d -max 9 0 +avg 0 4.4 min 1 0 +max 9 0 sum 22 0 -avg 0 4.4 delete from t1| delete from t2| drop procedure bug1874| @@ -4466,7 +4466,7 @@ Error 1347 'test.v1' is not BASE TABLE Error 1347 'test.v1' is not BASE TABLE drop procedure bug13012| drop view v1; -select * from t1| +select * from t1 order by data| id data aa 0 aa 1 @@ -4819,7 +4819,7 @@ insert into t1 values ('c', 2), ('b', 3), ('a', 1)| create procedure bug16474_1() begin declare x int; -select id from t1 order by x; +select id from t1 order by x, id; end| drop procedure if exists bug14945| create table t3 (id int not null auto_increment primary key)| @@ -4833,30 +4833,30 @@ id drop table t3| drop procedure bug14945| create procedure bug16474_2(x int) -select id from t1 order by x| +select id from t1 order by x, id| call bug16474_1()| id -c -b a +b +c call bug16474_2(1)| id -c -b a +b +c call bug16474_2(2)| id -c -b a +b +c drop procedure bug16474_1| drop procedure bug16474_2| set @x = 2| -select * from t1 order by @x| +select * from t1 order by @x, data| id data +a 1 c 2 b 3 -a 1 delete from t1| drop function if exists bug15728| drop table if exists t3| diff --git a/mysql-test/r/timezone2.result b/mysql-test/r/timezone2.result index fe9e971af2f..af8d52a017d 100644 --- a/mysql-test/r/timezone2.result +++ b/mysql-test/r/timezone2.result @@ -70,7 +70,7 @@ i ts 1067129999 2003-10-26 00:59:59 1067137200 2003-10-26 03:00:00 1067129999 2003-10-26 00:59:59 -delete from t1; +truncate table t1; set time_zone='Europe/Moscow'; insert into t1 (i, ts) values (unix_timestamp('2004-01-01 00:00:00'),'2004-01-01 00:00:00'), @@ -85,7 +85,7 @@ i ts 1080428400 2004-03-28 03:00:00 1091304000 2003-08-01 00:00:00 1099175400 2004-10-31 02:30:00 -delete from t1; +truncate table t1; set time_zone='leap/Europe/Moscow'; insert into t1 (i, ts) values (unix_timestamp('2004-01-01 00:00:00'),'2004-01-01 00:00:00'), @@ -100,7 +100,7 @@ i ts 1080428422 2004-03-28 03:00:00 1091304022 2003-08-01 00:00:00 1099175422 2004-10-31 02:30:00 -delete from t1; +truncate table t1; insert into t1 (i, ts) values (unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'), (unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00'); @@ -129,7 +129,7 @@ ts 1970-01-01 00:00:01 2037-12-31 23:59:59 0000-00-00 00:00:00 -delete from t1; +truncate table t1; set time_zone='MET'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'), ('1970-01-01 01:00:00'),('1970-01-01 01:00:01'), @@ -146,7 +146,7 @@ ts 1970-01-01 01:00:01 2038-01-01 00:59:59 0000-00-00 00:00:00 -delete from t1; +truncate table t1; set time_zone='+01:30'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'), ('1970-01-01 01:30:00'),('1970-01-01 01:30:01'), diff --git a/mysql-test/r/trigger-grant.result b/mysql-test/r/trigger-grant.result index fec5d4812d9..eb211be0270 100644 --- a/mysql-test/r/trigger-grant.result +++ b/mysql-test/r/trigger-grant.result @@ -51,8 +51,8 @@ GRANT TRIGGER ON mysqltest_db1.t1 TO mysqltest_dfn@localhost; ---> connection: wl2818_definer_con INSERT INTO t1 VALUES(0); DROP TRIGGER trg1; -DELETE FROM t1; -DELETE FROM t2; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; ---> connection: default REVOKE SUPER ON *.* FROM mysqltest_dfn@localhost; diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result index 5eba97a9eda..6f1a45f27c5 100644 --- a/mysql-test/r/type_datetime.result +++ b/mysql-test/r/type_datetime.result @@ -151,7 +151,7 @@ insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 Warnings: Warning 1264 Out of range value for column 't' at row 1 Warning 1264 Out of range value for column 't' at row 2 -select * from t1; +select * from t1 order by t; t 0000-00-00 00:00:00 2003-01-01 00:00:00 diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result index ba401a22945..df3298bad1a 100644 --- a/mysql-test/r/type_ranges.result +++ b/mysql-test/r/type_ranges.result @@ -323,7 +323,7 @@ select * from t3; id_A id_B 1 1 2 NULL -delete from t3; +truncate table t3; insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id); select * from t3; id_A id_B diff --git a/mysql-test/r/type_timestamp.result b/mysql-test/r/type_timestamp.result index 95ec7526473..6bec1e2b46b 100644 --- a/mysql-test/r/type_timestamp.result +++ b/mysql-test/r/type_timestamp.result @@ -59,7 +59,7 @@ ix+0 19990501000000 19991101000000 19990501000000 -delete from t1; +truncate table t1; insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000"); select ix+0 from t1; ix+0 @@ -140,7 +140,7 @@ ix+0 0 0 0 -delete from t1; +truncate table t1; insert into t1 values ("00000000000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101"),("20031200000000"),("20030000000000"); Warnings: Warning 1265 Data truncated for column 'ix' at row 2 @@ -160,7 +160,7 @@ ix+0 0 0 0 -delete from t1; +truncate table t1; insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer"); Warnings: Warning 1265 Data truncated for column 'ix' at row 1 @@ -329,7 +329,7 @@ show columns from t1; Field Type Null Key Default Extra t1 timestamp YES CURRENT_TIMESTAMP t2 datetime YES NULL -delete from t1; +truncate table t1; insert into t1 values ('2004-04-01 00:00:00', '2004-04-01 00:00:00'); SET TIMESTAMP=1000000012; update t1 set t1= '2004-04-02 00:00:00'; diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result index 9fabb0ad2d8..7f3c0f79520 100644 --- a/mysql-test/r/view.result +++ b/mysql-test/r/view.result @@ -1106,21 +1106,21 @@ insert ignore into v1 SELECT a from t2; Warnings: Error 1369 CHECK OPTION failed 'test.v1' Error 1369 CHECK OPTION failed 'test.v1' -select * from t1; +select * from t1 order by a desc; a 1 0 update v1 set a=-1 where a=0; update v1 set a=2 where a=1; ERROR HY000: CHECK OPTION failed 'test.v1' -select * from t1; +select * from t1 order by a desc; a 1 -1 update v1 set a=0 where a=0; insert into t2 values (1); update v1,t2 set v1.a=v1.a-1 where v1.a=t2.a; -select * from t1; +select * from t1 order by a desc; a 0 -1 @@ -1310,12 +1310,12 @@ Warning 1264 Out of range value for column 'a' at row 3 Error 1369 CHECK OPTION failed 'test.v1' Warning 1264 Out of range value for column 'a' at row 4 Error 1369 CHECK OPTION failed 'test.v1' -select * from t1; +select * from t1 order by a,b; a b 1 row 1 2 row 2 3 row 3 -select * from v1; +select * from v1 order by a,b; a b 1 row 1 2 row 2 diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test index c89d31c69b9..4ff7c5e6cda 100644 --- a/mysql-test/t/archive.test +++ b/mysql-test/t/archive.test @@ -3,6 +3,7 @@ # Taken FROM the select test # -- source include/have_archive.inc +-- source include/have_binlog_format_statement.inc --disable_warnings drop table if exists t1,t2,t3; diff --git a/mysql-test/t/create.test b/mysql-test/t/create.test index e4a7d1cd9af..714e3844e66 100644 --- a/mysql-test/t/create.test +++ b/mysql-test/t/create.test @@ -670,14 +670,6 @@ alter table t1 max_rows=100000000000; show create table t1; drop table t1; -# -# Bug#17530: Incorrect key truncation on table creation caused server crash. -# -create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb - character set utf8 collate utf8_general_ci; -insert into t1 values('aaa'); -drop table t1; - # End of 5.0 tests # diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index 96f31133e65..a815d538e57 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -36,7 +36,6 @@ rpl_ndb_myisam2ndb : Bug #19710 Cluster replication to partition table fa 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_row_inexist_tbl : BUG#18948 2006-03-09 mats Disabled since patch makes this test wait forever rpl_sp : BUG#16456 2006-02-16 jmiller # the below testcase have been reworked to avoid the bug, test contains comment, keep bug open diff --git a/mysql-test/t/federated.test b/mysql-test/t/federated.test index f6799f3630a..5f5c8d44f35 100644 --- a/mysql-test/t/federated.test +++ b/mysql-test/t/federated.test @@ -83,7 +83,7 @@ eval SHOW CREATE TABLE federated.t2; INSERT INTO federated.t2 (id, name) VALUES (1, 'foo'); INSERT INTO federated.t2 (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.t2; +SELECT * FROM federated.t2 ORDER BY id, name; DROP TABLE federated.t2; connection slave; @@ -110,7 +110,7 @@ eval CREATE TABLE federated.t1 ( INSERT INTO federated.t1 (id, name) VALUES (1, 'foo'); INSERT INTO federated.t1 (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.t1; +SELECT * FROM federated.t1 ORDER BY id,name; DELETE FROM federated.t1; DROP TABLE IF EXISTS federated.t1; @@ -125,7 +125,7 @@ eval CREATE TABLE federated.`t1%` ( INSERT INTO federated.`t1%` (id, name) VALUES (1, 'foo'); INSERT INTO federated.`t1%` (id, name) VALUES (2, 'fee'); -SELECT * FROM federated.`t1%`; +SELECT * FROM federated.`t1%` ORDER BY id, name; DELETE FROM federated.`t1%`; DROP TABLE IF EXISTS federated.`t1%`; diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test index 92e060eed92..5b1b374e487 100644 --- a/mysql-test/t/innodb.test +++ b/mysql-test/t/innodb.test @@ -2510,3 +2510,16 @@ BEGIN; INSERT INTO t1 VALUES (1); OPTIMIZE TABLE t1; DROP TABLE t1; + +####################################################################### +# # +# Please, DO NOT TOUCH this file as well as the innodb.result file. # +# These files are to be modified ONLY BY INNOBASE guys. # +# # +# Use innodb_mysql.[test|result] files instead. # +# # +# If nevertheless you need to make some changes here, please, forward # +# your commit message To: dev@innodb.com Cc: dev-innodb@mysql.com # +# (otherwise your changes may be erased). # +# # +####################################################################### diff --git a/mysql-test/t/innodb_mysql.test b/mysql-test/t/innodb_mysql.test index 0a9eeb049b0..65e2cc658f5 100644 --- a/mysql-test/t/innodb_mysql.test +++ b/mysql-test/t/innodb_mysql.test @@ -4,6 +4,14 @@ drop table if exists t1,t2,t1m,t1i,t2m,t2i,t4; --enable_warnings +# +# Bug#17530: Incorrect key truncation on table creation caused server crash. +# +create table t1(f1 varchar(800) binary not null, key(f1)) engine = innodb + character set utf8 collate utf8_general_ci; +insert into t1 values('aaa'); +drop table t1; + # BUG#16798: Uninitialized row buffer reads in ref-or-null optimizer # (repeatable only w/innodb). create table t1 ( diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test index f6493bac244..d1ce1104322 100644 --- a/mysql-test/t/range.test +++ b/mysql-test/t/range.test @@ -370,7 +370,7 @@ insert into t2(uid, name) values (25, CHAR(64+25)), (26, CHAR(64+26)); -insert into t1(uid, name) select uid, name from t2; +insert into t1(uid, name) select uid, name from t2 order by uid; delete from t2; insert into t2(id, uid, name) select id, uid, name from t1; diff --git a/mysql-test/t/rpl_rbr_to_sbr.test b/mysql-test/t/rpl_rbr_to_sbr.test index f04caf05057..c10199f8ff5 100644 --- a/mysql-test/t/rpl_rbr_to_sbr.test +++ b/mysql-test/t/rpl_rbr_to_sbr.test @@ -1,3 +1,4 @@ +-- source include/have_row_based.inc -- source include/have_binlog_format_statement.inc -- source include/master-slave.inc diff --git a/mysql-test/t/rpl_row_basic_11bugs.test b/mysql-test/t/rpl_row_basic_11bugs.test index 3a686ea6b3d..bd582ce349a 100644 --- a/mysql-test/t/rpl_row_basic_11bugs.test +++ b/mysql-test/t/rpl_row_basic_11bugs.test @@ -36,3 +36,18 @@ USE test_ignore; connection master; DROP DATABASE test_ignore; sync_slave_with_master; + +# Bug#19995: Extreneous table maps generated for statements that does +# not generate rows +--disable_query_log +--source include/master-slave-reset.inc +--enable_query_log + +connection master; +CREATE TABLE t1 (a INT); +DELETE FROM t1; +INSERT INTO t1 VALUES (1),(2); +DELETE FROM t1 WHERE a = 0; +UPDATE t1 SET a=99 WHERE a = 0; +--replace_regex /table_id: [0-9]+/table_id: #/ +SHOW BINLOG EVENTS; diff --git a/mysql-test/t/rpl_row_basic_8partition.test b/mysql-test/t/rpl_row_basic_8partition.test index 8cad2226d4a..640a420c10e 100644 --- a/mysql-test/t/rpl_row_basic_8partition.test +++ b/mysql-test/t/rpl_row_basic_8partition.test @@ -7,6 +7,7 @@ # partition tables with same engine (MyISAM) in both ends. # ############################################################ +--source include/have_row_based.inc --source include/have_partition.inc --source include/master-slave.inc connection master; diff --git a/mysql-test/t/rpl_row_create_table.test b/mysql-test/t/rpl_row_create_table.test index 0cb0fd766a3..8a8ea01d688 100644 --- a/mysql-test/t/rpl_row_create_table.test +++ b/mysql-test/t/rpl_row_create_table.test @@ -67,7 +67,7 @@ connection master; CREATE TABLE t7 (UNIQUE(b)) SELECT a,b FROM tt3; # Shouldn't be written to the binary log --replace_regex /table_id: [0-9]+/table_id: #/ -SHOW BINLOG EVENTS FROM 1326; +SHOW BINLOG EVENTS FROM 1256; # Test that INSERT-SELECT works the same way as for SBR. CREATE TABLE t7 (a INT, b INT UNIQUE); @@ -76,7 +76,7 @@ INSERT INTO t7 SELECT a,b FROM tt3; SELECT * FROM t7 ORDER BY a,b; # Should be written to the binary log --replace_regex /table_id: [0-9]+/table_id: #/ -SHOW BINLOG EVENTS FROM 1326; +SHOW BINLOG EVENTS FROM 1256; sync_slave_with_master; SELECT * FROM t7 ORDER BY a,b; @@ -87,7 +87,7 @@ BEGIN; INSERT INTO t7 SELECT a,b FROM tt4; ROLLBACK; --replace_regex /table_id: [0-9]+/table_id: #/ -SHOW BINLOG EVENTS FROM 1522; +SHOW BINLOG EVENTS FROM 1452; SELECT * FROM t7 ORDER BY a,b; sync_slave_with_master; SELECT * FROM t7 ORDER BY a,b; @@ -101,7 +101,7 @@ CREATE TEMPORARY TABLE tt6 LIKE tt4; --query_vertical SHOW CREATE TABLE t8 --query_vertical SHOW CREATE TABLE t9 --replace_regex /table_id: [0-9]+/table_id: #/ -SHOW BINLOG EVENTS FROM 1618; +SHOW BINLOG EVENTS FROM 1548; sync_slave_with_master; --echo **** On Slave **** --query_vertical SHOW CREATE TABLE t8 diff --git a/mysql-test/t/rpl_row_inexist_tbl-slave.opt b/mysql-test/t/rpl_row_inexist_tbl-slave.opt new file mode 100644 index 00000000000..abd717f8222 --- /dev/null +++ b/mysql-test/t/rpl_row_inexist_tbl-slave.opt @@ -0,0 +1 @@ +--replicate-ignore-table=test.t2 diff --git a/mysql-test/t/rpl_row_inexist_tbl.test b/mysql-test/t/rpl_row_inexist_tbl.test index e77ea216571..741cc8b7ba3 100644 --- a/mysql-test/t/rpl_row_inexist_tbl.test +++ b/mysql-test/t/rpl_row_inexist_tbl.test @@ -6,15 +6,23 @@ source include/master-slave.inc; connection master; create table t1 (a int not null primary key); +insert into t1 values (1); +create table t2 (a int); +insert into t2 values (1); +update t1, t2 set t1.a = 0 where t1.a = t2.a; + sync_slave_with_master; +# t2 should not have been replicated +# t1 should have been properly updated +show tables; +select * from t1; drop table t1; connection master; insert into t1 values (1); -insert into t1 values (2); connection slave; -# slave should have stopped because can't find table +# slave should have stopped because can't find table t1 wait_for_slave_to_stop; # see if we have a good error message: --replace_result $MASTER_MYPORT MASTER_MYPORT @@ -24,4 +32,4 @@ show slave status; # cleanup connection master; -drop table t1; +drop table t1, t2; diff --git a/mysql-test/t/rpl_sp_effects.test b/mysql-test/t/rpl_sp_effects.test index 40c9a5d0b74..e1746682b76 100644 --- a/mysql-test/t/rpl_sp_effects.test +++ b/mysql-test/t/rpl_sp_effects.test @@ -106,8 +106,8 @@ delete from t2; # 4. VIEWs delete from t1; insert into t2 values(1),(2); -create view v1 as select f1(a) from t2; -select * from v1; +create view v1 as select f1(a) as f from t2; +select * from v1 order by f; SELECT 'master:',a FROM t1 ORDER BY a; sync_slave_with_master; diff --git a/mysql-test/t/rpl_truncate_2myisam.test b/mysql-test/t/rpl_truncate_2myisam.test new file mode 100644 index 00000000000..1a2cb1d0fb3 --- /dev/null +++ b/mysql-test/t/rpl_truncate_2myisam.test @@ -0,0 +1,4 @@ + +let $engine=MyISAM; +--source extra/rpl_tests/rpl_truncate.test + diff --git a/mysql-test/t/rpl_truncate_3innodb.test b/mysql-test/t/rpl_truncate_3innodb.test new file mode 100644 index 00000000000..7f3145feb1b --- /dev/null +++ b/mysql-test/t/rpl_truncate_3innodb.test @@ -0,0 +1,5 @@ + +--source include/have_innodb.inc + +let $engine=InnoDB; +--source extra/rpl_tests/rpl_truncate.test diff --git a/mysql-test/t/rpl_truncate_7ndb.test b/mysql-test/t/rpl_truncate_7ndb.test new file mode 100644 index 00000000000..7a6151c6028 --- /dev/null +++ b/mysql-test/t/rpl_truncate_7ndb.test @@ -0,0 +1,66 @@ + +--source include/have_ndb.inc +--source include/master-slave.inc + +--disable_query_log +--disable_warnings +connection slave; +STOP SLAVE; +connection master; +DROP TABLE IF EXISTS t1; +RESET MASTER; +connection slave; +DROP TABLE IF EXISTS t1; +RESET SLAVE; +START SLAVE; +--enable_warnings +--enable_query_log + +--echo **** On Master **** +connection master; +CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1 ORDER BY a,b; +--echo **** On Slave **** +sync_slave_with_master; +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1 ORDER BY a,b; +--echo **** On Master **** +connection master; +TRUNCATE TABLE t1; +SELECT * FROM t1 ORDER BY a,b; +--echo **** On Slave **** +sync_slave_with_master; +# Should be empty +SELECT * FROM t1 ORDER BY a,b; +--echo **** On Master **** +connection master; +DROP TABLE t1; +--replace_regex /table_id: [0-9]+/table_id: #/ +--replace_result $SERVER_VERSION SERVER_VERSION +SHOW BINLOG EVENTS; + +--echo **** On Master **** +connection master; +CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB; +INSERT INTO t1 VALUES (1,1), (2,2); +SELECT * FROM t1 ORDER BY a,b; +--echo **** On Slave **** +sync_slave_with_master; +INSERT INTO t1 VALUE (3,3); +SELECT * FROM t1 ORDER BY a,b; +--echo **** On Master **** +connection master; +DELETE FROM t1; +SELECT * FROM t1 ORDER BY a,b; +--echo **** On Slave **** +sync_slave_with_master; +# Should be empty +SELECT * FROM t1 ORDER BY a,b; +--echo **** On Master **** +connection master; +DROP TABLE t1; +--replace_regex /table_id: [0-9]+/table_id: #/ +--replace_result $SERVER_VERSION SERVER_VERSION +SHOW BINLOG EVENTS; + diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test index a7b24a5e06c..2f44f4e97c5 100644 --- a/mysql-test/t/show_check.test +++ b/mysql-test/t/show_check.test @@ -255,9 +255,9 @@ delete from t2 where b=3; delete from t3 where a=3; --replace_column 6 # 7 # 8 # 9 # 10 # show table status; -delete from t1; -delete from t2; -delete from t3; +truncate table t1; +truncate table t2; +truncate table t3; --replace_column 6 # 7 # 8 # 9 # show table status; insert into t1 values (5); diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test index c9ce26b6dda..24b0d4674c5 100644 --- a/mysql-test/t/sp-error.test +++ b/mysql-test/t/sp-error.test @@ -508,7 +508,7 @@ end| insert into t1 values (666, 51.3)| --error 1054 call bug2272()| -delete from t1| +truncate table t1| drop procedure bug2272| # @@ -742,7 +742,7 @@ begin fetch c into v; end| -delete from t1| +truncate table t1| --error ER_SP_FETCH_NO_DATA call bug7299()| drop procedure bug7299| @@ -871,7 +871,7 @@ insert into t1 value (2, 2.7), (3, 3.14), (7, 7.0)| select *,bug8408() from t1| drop function bug8408| -delete from t1| +truncate table t1| # diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test index 8f5fcdc9d52..e3d4e1c9834 100644 --- a/mysql-test/t/sp.test +++ b/mysql-test/t/sp.test @@ -143,7 +143,7 @@ begin end| call setcontext()| -select * from t1| +select * from t1 order by data| delete from t1| drop procedure setcontext| @@ -287,7 +287,7 @@ create procedure inc(inout io int) set io = io + 1| call iotest("io1", "io2", 1)| -select * from t1| +select * from t1 order by data desc| delete from t1| drop procedure iotest| drop procedure inc2| @@ -333,7 +333,7 @@ begin end| call cbv1()| -select * from t1| +select * from t1 order by data| delete from t1| drop procedure cbv1| drop procedure cbv2| @@ -371,7 +371,7 @@ call sub1("sub1b", (select max(i) from t2))| call sub1("sub1c", (select i,d from t2 limit 1))| call sub1("sub1d", (select 1 from (select 1) a))| call sub2("sub2")| -select * from t1| +select * from t1 order by id| select sub3((select max(i) from t2))| drop procedure sub1| drop procedure sub2| @@ -392,7 +392,7 @@ while x do end while| call a0(3)| -select * from t1| +select * from t1 order by data desc| delete from t1| drop procedure a0| @@ -408,7 +408,7 @@ while x > 0 do end while| call a(3)| -select * from t1| +select * from t1 order by data desc| delete from t1| drop procedure a| @@ -424,7 +424,7 @@ repeat until x = 0 end repeat| call b(3)| -select * from t1| +select * from t1 order by data desc| delete from t1| drop procedure b| @@ -456,7 +456,7 @@ hmm: while x > 0 do end while hmm| call c(3)| -select * from t1| +select * from t1 order by data desc| delete from t1| drop procedure c| @@ -493,7 +493,7 @@ foo: loop end loop foo| call e(3)| -select * from t1| +select * from t1 order by data desc| delete from t1| drop procedure e| @@ -514,7 +514,7 @@ end if| call f(-2)| call f(0)| call f(4)| -select * from t1| +select * from t1 order by data| delete from t1| drop procedure f| @@ -536,7 +536,7 @@ end case| call g(-42)| call g(0)| call g(1)| -select * from t1| +select * from t1 order by data| delete from t1| drop procedure g| @@ -558,7 +558,7 @@ end case| call h(0)| call h(1)| call h(17)| -select * from t1| +select * from t1 order by data| delete from t1| drop procedure h| @@ -592,7 +592,7 @@ drop procedure if exists sel1| --enable_warnings create procedure sel1() begin - select * from t1; + select * from t1 order by data; end| call sel1()| @@ -603,8 +603,8 @@ drop procedure if exists sel2| --enable_warnings create procedure sel2() begin - select * from t1; - select * from t2; + select * from t1 order by data; + select * from t2 order by s; end| call sel2()| @@ -624,7 +624,7 @@ begin end| call into_test("into", 100)| -select * from t1| +select * from t1 order by data| delete from t1| drop procedure into_test| @@ -641,7 +641,7 @@ begin end| call into_test2("into", 100)| -select id,data,@z from t1| +select id,data,@z from t1 order by data| delete from t1| drop procedure into_test2| @@ -819,9 +819,9 @@ insert into t2 values (append("a", "b"), mul(2,mul(3,4)), fun(1.7, 4, 6))| # Disable PS because double's give a bit different values --disable_ps_protocol select * from t2 where s = append("a", "b")| -select * from t2 where i = mul(4,3) or i = mul(mul(3,4),2)| +select * from t2 where i = mul(4,3) or i = mul(mul(3,4),2) order by i| select * from t2 where d = e()| -select * from t2| +select * from t2 order by i| --enable_ps_protocol delete from t2| @@ -976,8 +976,8 @@ drop procedure if exists cur2| create procedure cur2() begin declare done int default 0; - declare c1 cursor for select id,data from test.t1; - declare c2 cursor for select i from test.t2; + declare c1 cursor for select id,data from test.t1 order by id,data; + declare c2 cursor for select i from test.t2 order by i; declare continue handler for sqlstate '02000' set done = 1; open c1; @@ -1003,7 +1003,7 @@ begin end| call cur2()| -select * from t3| +select * from t3 order by i,s| delete from t1| delete from t2| drop table t3| @@ -1178,13 +1178,13 @@ create function f1() returns int return (select sum(data) from t1)| select f1()| # This should work too (and give 2 rows as result) -select id, f1() from t1| +select id, f1() from t1 order by id| # Function which uses two instances of table simultaneously create function f2() returns int - return (select data from t1 where data <= (select sum(data) from t1) limit 1)| + return (select data from t1 where data <= (select sum(data) from t1) order by data limit 1)| select f2()| -select id, f2() from t1| +select id, f2() from t1 order by id| # Function which uses the same table twice in different queries create function f3() returns int @@ -1196,17 +1196,17 @@ begin return n < m; end| select f3()| -select id, f3() from t1| +select id, f3() from t1 order by id| # Calling two functions using same table select f1(), f3()| -select id, f1(), f3() from t1| +select id, f1(), f3() from t1 order by id| # Function which uses two different tables create function f4() returns double return (select d from t1, t2 where t1.data = t2.i and t1.id= "b")| select f4()| -select s, f4() from t2| +select s, f4() from t2 order by s| # Recursive functions which due to this recursion require simultaneous # access to several instance of the same table won't work @@ -1239,7 +1239,7 @@ end| create function f7() returns int return (select sum(data) from t1 where data <= f1())| select f6()| -select id, f6() from t1| +select id, f6() from t1 order by id| # # Let us test how new locking work with views @@ -1247,12 +1247,12 @@ select id, f6() from t1| # The most trivial view create view v1 (a) as select f1()| select * from v1| -select id, a from t1, v1| +select id, a from t1, v1 order by id| select * from v1, v1 as v| # A bit more complex construction create view v2 (a) as select a*10 from v1| select * from v2| -select id, a from t1, v2| +select id, a from t1, v2 order by id| select * from v1, v2| # Nice example where the same view is used on @@ -1297,7 +1297,7 @@ select *, f0() from v0| lock tables t1 read, t1 as t11 read| # These should work well select f3()| -select id, f3() from t1 as t11| +select id, f3() from t1 as t11 order by id| # Degenerate cases work too :) select f0()| select * from v0| @@ -1407,8 +1407,8 @@ drop function f12_2| drop view v0| drop view v1| drop view v2| -delete from t1 | -delete from t2 | +truncate table t1 | +truncate table t2 | drop table t4| # End of non-bug tests @@ -1596,7 +1596,7 @@ call fib(3)| select * from t3 order by f asc| -delete from t3| +truncate table t3| # The original test, 20 levels, ran into memory limits on some machines # and builds. Try 10 instead... @@ -1693,7 +1693,6 @@ begin end if; return x; end| - select * from t1 where data = getcount("bar")| select * from t3| select getcount("zip")| @@ -2120,7 +2119,7 @@ delete from t1| call bug822('foo', 42)| call bug822('foo', 42)| call bug822('bar', 666)| -select * from t1| +select * from t1 order by data| delete from t1| drop procedure bug822| @@ -2148,7 +2147,7 @@ delete from t1 where id='foo'| insert into t1 values ('bar', 7)| call bug1495()| delete from t1 where id='bar'| -select * from t1| +select * from t1 order by data| delete from t1| drop procedure bug1495| @@ -2173,7 +2172,7 @@ end| insert into t1 values ("foo", 12), ("bar", 7)| call bug1547("foo")| call bug1547("bar")| -select * from t1| +select * from t1 order by id| delete from t1| drop procedure bug1547| @@ -2240,7 +2239,7 @@ end| insert into t1 (data) values (3), (1), (5), (9), (4)| call bug1874()| -select * from t2| +select * from t2 order by i| delete from t1| delete from t2| drop procedure bug1874| @@ -5260,7 +5259,7 @@ call bug13012()| call bug13012()| drop procedure bug13012| drop view v1; -select * from t1| +select * from t1 order by data| # # A test case for Bug#15392 "Server crashes during prepared statement @@ -5669,7 +5668,7 @@ create procedure bug16474_1() begin declare x int; - select id from t1 order by x; + select id from t1 order by x, id; end| # @@ -5689,7 +5688,7 @@ drop procedure bug14945| # This does NOT order by column index; variable is an expression. create procedure bug16474_2(x int) - select id from t1 order by x| + select id from t1 order by x, id| call bug16474_1()| call bug16474_2(1)| @@ -5699,7 +5698,7 @@ drop procedure bug16474_2| # For reference: user variables are expressions too and do not affect ordering. set @x = 2| -select * from t1 order by @x| +select * from t1 order by @x, data| delete from t1| diff --git a/mysql-test/t/timezone2.test b/mysql-test/t/timezone2.test index bfc909d6995..bad1df554d9 100644 --- a/mysql-test/t/timezone2.test +++ b/mysql-test/t/timezone2.test @@ -69,7 +69,7 @@ set time_zone='UTC'; select * from t1; -delete from t1; +truncate table t1; # Simple check for 'Europe/Moscow' time zone just for showing that it works set time_zone='Europe/Moscow'; @@ -79,7 +79,7 @@ insert into t1 (i, ts) values (unix_timestamp('2004-08-01 00:00:00'),'2003-08-01 00:00:00'), (unix_timestamp('2004-10-31 02:30:00'),'2004-10-31 02:30:00'); select * from t1; -delete from t1; +truncate table t1; # @@ -94,7 +94,7 @@ insert into t1 (i, ts) values (unix_timestamp('2004-08-01 00:00:00'),'2003-08-01 00:00:00'), (unix_timestamp('2004-10-31 02:30:00'),'2004-10-31 02:30:00'); select * from t1; -delete from t1; +truncate table t1; # Let us test leap jump insert into t1 (i, ts) values (unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'), @@ -115,14 +115,14 @@ insert into t1 values ('0000-00-00 00:00:00'),('1969-12-31 23:59:59'), ('1970-01-01 00:00:00'),('1970-01-01 00:00:01'), ('2037-12-31 23:59:59'),('2038-01-01 00:00:00'); select * from t1; -delete from t1; +truncate table t1; # MET time zone has range shifted by one hour set time_zone='MET'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 00:30:00'), ('1970-01-01 01:00:00'),('1970-01-01 01:00:01'), ('2038-01-01 00:59:59'),('2038-01-01 01:00:00'); select * from t1; -delete from t1; +truncate table t1; # same for +01:30 time zone set time_zone='+01:30'; insert into t1 values ('0000-00-00 00:00:00'),('1970-01-01 01:00:00'), diff --git a/mysql-test/t/trigger-grant.test b/mysql-test/t/trigger-grant.test index 8ca8ffe904b..6dd0c83dc92 100644 --- a/mysql-test/t/trigger-grant.test +++ b/mysql-test/t/trigger-grant.test @@ -151,8 +151,8 @@ INSERT INTO t1 VALUES(0); # Cleanup for further tests. DROP TRIGGER trg1; -DELETE FROM t1; -DELETE FROM t2; +TRUNCATE TABLE t1; +TRUNCATE TABLE t2; --disconnect wl2818_definer_con diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test index 4b6741b4242..f8953686c89 100644 --- a/mysql-test/t/type_datetime.test +++ b/mysql-test/t/type_datetime.test @@ -98,7 +98,7 @@ insert into t1 values select * from t1; delete from t1; insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer"); -select * from t1; +select * from t1 order by t; drop table t1; # diff --git a/mysql-test/t/type_ranges.test b/mysql-test/t/type_ranges.test index 03ee91f14d8..4a897c1e440 100644 --- a/mysql-test/t/type_ranges.test +++ b/mysql-test/t/type_ranges.test @@ -162,7 +162,7 @@ select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id); create table t3 (id_A integer unsigned not null, id_B integer unsigned null ); insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 using ( id ); select * from t3; -delete from t3; +truncate table t3; insert into t3 select t1.id as id_A, t2.id as id_B from t1 left join t2 on (t1.id = t2.id); select * from t3; drop table t3; diff --git a/mysql-test/t/type_timestamp.test b/mysql-test/t/type_timestamp.test index f96beedbebc..9b09421dd1f 100644 --- a/mysql-test/t/type_timestamp.test +++ b/mysql-test/t/type_timestamp.test @@ -41,7 +41,7 @@ drop table t1; create table t1 (ix timestamp); insert into t1 values (19991101000000),(19990102030405),(19990630232922),(19990601000000),(19990930232922),(19990531232922),(19990501000000),(19991101000000),(19990501000000); select ix+0 from t1; -delete from t1; +truncate table t1; insert into t1 values ("19991101000000"),("19990102030405"),("19990630232922"),("19990601000000"); select ix+0 from t1; drop table t1; @@ -82,10 +82,10 @@ drop table t1; create table t1 (ix timestamp); insert into t1 values (0),(20030101010160),(20030101016001),(20030101240101),(20030132010101),(20031301010101),(20031200000000),(20030000000000); select ix+0 from t1; -delete from t1; +truncate table t1; insert into t1 values ("00000000000000"),("20030101010160"),("20030101016001"),("20030101240101"),("20030132010101"),("20031301010101"),("20031200000000"),("20030000000000"); select ix+0 from t1; -delete from t1; +truncate table t1; insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer"); select ix+0 from t1; drop table t1; @@ -186,7 +186,7 @@ insert into t1 (t1) values (default); select * from t1; show create table t1; show columns from t1; -delete from t1; +truncate table t1; # # Let us test some cases when auto-set should be disabled or influence diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test index 0db97f6d4af..b432a4c39ca 100644 --- a/mysql-test/t/view.test +++ b/mysql-test/t/view.test @@ -1035,18 +1035,18 @@ create table t2 (a int); insert into t2 values (2),(3),(0); # INSERT SELECT with ignore test insert ignore into v1 SELECT a from t2; -select * from t1; +select * from t1 order by a desc; #simple UPDATE test update v1 set a=-1 where a=0; -- error 1369 update v1 set a=2 where a=1; -select * from t1; +select * from t1 order by a desc; # prepare data for next check update v1 set a=0 where a=0; insert into t2 values (1); # multiupdate test update v1,t2 set v1.a=v1.a-1 where v1.a=t2.a; -select * from t1; +select * from t1 order by a desc; # prepare data for next check update v1 set a=a+1; # multiupdate with ignore test @@ -1226,8 +1226,8 @@ select * from t1; select * from v1; delete from t1; load data infile '../std_data_ln/loaddata3.dat' ignore into table v1 fields terminated by '' enclosed by '' ignore 1 lines; -select * from t1; -select * from v1; +select * from t1 order by a,b; +select * from v1 order by a,b; drop view v1; drop table t1; # variable length fields diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc index 742f9ce7631..ec504cc1266 100644 --- a/sql/ha_innodb.cc +++ b/sql/ha_innodb.cc @@ -135,6 +135,7 @@ extern "C" { #include "../storage/innobase/include/fil0fil.h" #include "../storage/innobase/include/trx0xa.h" #include "../storage/innobase/include/thr0loc.h" +#include "../storage/innobase/include/ha_prototypes.h" } #define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */ @@ -668,6 +669,61 @@ innobase_get_cset_width( } /********************************************************************** +Converts an identifier to a table name. + +NOTE that the exact prototype of this function has to be in +/innobase/dict/dict0dict.c! */ +extern "C" +void +innobase_convert_from_table_id( +/*===========================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len) /* in: length of 'to', in bytes */ +{ + uint errors; + + strconvert(current_thd->charset(), from, + &my_charset_filename, to, len, &errors); +} + +/********************************************************************** +Converts an identifier to UTF-8. + +NOTE that the exact prototype of this function has to be in +/innobase/dict/dict0dict.c! */ +extern "C" +void +innobase_convert_from_id( +/*=====================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len) /* in: length of 'to', in bytes */ +{ + uint errors; + + strconvert(current_thd->charset(), from, + system_charset_info, to, len, &errors); +} + +/********************************************************************** +Removes the filename encoding of a table or database name. + +NOTE that the exact prototype of this function has to be in +/innobase/dict/dict0dict.c! */ +extern "C" +void +innobase_convert_from_filename( +/*===========================*/ + char* s) /* in: identifier; out: decoded identifier */ +{ + uint errors; + + strconvert(&my_charset_filename, s, + system_charset_info, s, strlen(s), &errors); +} + +/********************************************************************** Compares NUL-terminated UTF-8 strings case insensitively. NOTE that the exact prototype of this function has to be in @@ -697,6 +753,21 @@ innobase_casedn_str( my_casedn_str(system_charset_info, a); } +/************************************************************************** +Determines the connection character set. + +NOTE that the exact prototype of this function has to be in +/innobase/dict/dict0dict.c! */ +extern "C" +struct charset_info_st* +innobase_get_charset( +/*=================*/ + /* out: connection character set */ + void* mysql_thd) /* in: MySQL thread handle */ +{ + return(((THD*) mysql_thd)->charset()); +} + /************************************************************************* Creates a temporary file. */ extern "C" @@ -743,6 +814,25 @@ innobase_mysql_tmpfile(void) } /************************************************************************* +Wrapper around MySQL's copy_and_convert function, see it for +documentation. */ +extern "C" +ulint +innobase_convert_string( +/*====================*/ + void* to, + ulint to_length, + CHARSET_INFO* to_cs, + const void* from, + ulint from_length, + CHARSET_INFO* from_cs, + uint* errors) +{ + return(copy_and_convert((char*)to, to_length, to_cs, + (const char*)from, from_length, from_cs, errors)); +} + +/************************************************************************* Gets the InnoDB transaction handle for a MySQL handler object, creates an InnoDB transaction struct if the corresponding MySQL thread struct still lacks one. */ @@ -1076,23 +1166,69 @@ innobase_invalidate_query_cache( } /********************************************************************* -Get the quote character to be used in SQL identifiers. +Display an SQL identifier. This definition must match the one in innobase/ut/ut0ut.c! */ extern "C" -int -mysql_get_identifier_quote_char( -/*============================*/ - /* out: quote character to be - used in SQL identifiers; EOF if none */ +void +innobase_print_identifier( +/*======================*/ + FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction */ + ibool table_id,/* in: TRUE=decode table name */ const char* name, /* in: name to print */ ulint namelen)/* in: length of name */ { + const char* s = name; + char* qname = NULL; + int q; + + if (table_id) { + /* Decode the table name. The filename_to_tablename() + function expects a NUL-terminated string. The input and + output strings buffers must not be shared. The function + only produces more output when the name contains other + characters than [0-9A-Z_a-z]. */ + char* temp_name = my_malloc(namelen + 1, MYF(MY_WME)); + uint qnamelen = namelen + + (1 + sizeof srv_mysql50_table_name_prefix); + + if (temp_name) { + qname = my_malloc(qnamelen, MYF(MY_WME)); + if (qname) { + memcpy(temp_name, name, namelen); + temp_name[namelen] = 0; + s = qname; + namelen = filename_to_tablename(temp_name, + qname, qnamelen); + } + my_free(temp_name, MYF(0)); + } + } + if (!trx || !trx->mysql_thd) { - return(EOF); + + q = '"'; + } else { + q = get_quote_char_for_identifier((THD*) trx->mysql_thd, + s, (int) namelen); + } + + if (q == EOF) { + fwrite(s, 1, namelen, f); + } else { + const char* e = s + namelen; + putc(q, f); + while (s < e) { + int c = *s++; + if (c == q) { + putc(c, f); + } + putc(c, f); + } + putc(q, f); } - return(get_quote_char_for_identifier((THD*) trx->mysql_thd, - name, (int) namelen)); + + my_free(qname, MYF(MY_ALLOW_ZERO_PTR)); } /************************************************************************** @@ -1232,6 +1368,24 @@ innobase_init(void) ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR); +#ifdef UNIV_DEBUG + static const char test_filename[] = "-@"; + char test_tablename[sizeof test_filename + + sizeof srv_mysql50_table_name_prefix]; + if ((sizeof test_tablename) - 1 + != filename_to_tablename(test_filename, test_tablename, + sizeof test_tablename) + || strncmp(test_tablename, + srv_mysql50_table_name_prefix, + sizeof srv_mysql50_table_name_prefix) + || strcmp(test_tablename + + sizeof srv_mysql50_table_name_prefix, + test_filename)) { + sql_print_error("tablename encoding has been changed"); + goto error; + } +#endif /* UNIV_DEBUG */ + /* Check that values don't overflow on 32-bit systems. */ if (sizeof(ulint) == 4) { if (innobase_buffer_pool_size > UINT_MAX32) { @@ -2200,8 +2354,7 @@ ha_innobase::open( /* Get pointer to a table object in InnoDB dictionary cache */ - ib_table = dict_table_get_and_increment_handle_count( - norm_name, NULL); + ib_table = dict_table_get_and_increment_handle_count(norm_name); if (NULL == ib_table) { ut_print_timestamp(stderr); @@ -4116,6 +4269,9 @@ ha_innobase::index_prev( mysql_byte* buf) /* in/out: buffer for previous row in MySQL format */ { + statistic_increment(current_thd->status_var.ha_read_prev_count, + &LOCK_status); + return(general_fetch(buf, ROW_SEL_PREV, 0)); } @@ -4652,7 +4808,7 @@ ha_innobase::create( /* Get the transaction associated with the current thd, or create one if not yet created */ - parent_trx = check_trx_exists(current_thd); + parent_trx = check_trx_exists(thd); /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ @@ -4748,20 +4904,9 @@ ha_innobase::create( } } - if (current_thd->query != NULL) { - LEX_STRING q; - - if (thd->convert_string(&q, system_charset_info, - current_thd->query, - current_thd->query_length, - current_thd->charset())) { - error = HA_ERR_OUT_OF_MEM; - - goto cleanup; - } - + if (thd->query != NULL) { error = row_table_add_foreign_constraints(trx, - q.str, norm_name, + thd->query, norm_name, create_info->options & HA_LEX_CREATE_TMP_TABLE); error = convert_error_code_to_mysql(error, NULL); @@ -4781,7 +4926,7 @@ ha_innobase::create( log_buffer_flush_to_disk(); - innobase_table = dict_table_get(norm_name, NULL); + innobase_table = dict_table_get(norm_name); DBUG_ASSERT(innobase_table != 0); @@ -4917,7 +5062,7 @@ ha_innobase::delete_table( /* Get the transaction associated with the current thd, or create one if not yet created */ - parent_trx = check_trx_exists(current_thd); + parent_trx = check_trx_exists(thd); /* In case MySQL calls this in the middle of a SELECT query, release possible adaptive hash latch to avoid deadlocks of threads */ diff --git a/sql/handler.cc b/sql/handler.cc index 47bcf1caba1..ce96817695a 100644 --- a/sql/handler.cc +++ b/sql/handler.cc @@ -3234,35 +3234,128 @@ namespace { } } -template<class RowsEventT> int binlog_log_row(TABLE *table, - const byte *before_record, - const byte *after_record) +/* + Write table maps for all (manually or automatically) locked tables + to the binary log. + + SYNOPSIS + write_locked_table_maps() + thd Pointer to THD structure + + DESCRIPTION + This function will generate and write table maps for all tables + that are locked by the thread 'thd'. Either manually locked + (stored in THD::locked_tables) and automatically locked (stored + in THD::lock) are considered. + + RETURN VALUE + 0 All OK + 1 Failed to write all table maps + + SEE ALSO + THD::lock + THD::locked_tables + */ +namespace { - if (table->file->is_injective()) - return 0; - bool error= 0; + int write_locked_table_maps(THD *thd) + { + DBUG_ENTER("write_locked_table_maps"); + DBUG_PRINT("enter", ("thd=%p, thd->lock=%p, thd->locked_tables=%p", + thd, thd->lock, thd->locked_tables)); + + if (thd->get_binlog_table_maps() == 0) + { + /* + Exactly one table has to be locked, otherwise this code is not + guaranteed to work. + */ + DBUG_ASSERT((thd->lock != NULL) + (thd->locked_tables != NULL) == 1); + + MYSQL_LOCK *lock= thd->lock ? thd->lock : thd->locked_tables; + DBUG_ASSERT(lock->table_count > 0); + TABLE **const end_ptr= lock->table + lock->table_count; + for (TABLE **table_ptr= lock->table ; + table_ptr != end_ptr ; + ++table_ptr) + { + TABLE *const table= *table_ptr; + DBUG_PRINT("info", ("Checking table %s", table->s->table_name)); + if (table->current_lock == F_WRLCK && + check_table_binlog_row_based(thd, table)) + { + int const has_trans= table->file->has_transactions(); + int const error= thd->binlog_write_table_map(table, has_trans); + /* + If an error occurs, it is the responsibility of the caller to + roll back the transaction. + */ + if (unlikely(error)) + DBUG_RETURN(1); + } + } + } + DBUG_RETURN(0); + } - if (check_table_binlog_row_based(table->in_use, table)) + template<class RowsEventT> int + binlog_log_row(TABLE* table, + const byte *before_record, + const byte *after_record) { - error= - RowsEventT::binlog_row_logging_function(table->in_use, table, - table->file->has_transactions(), - &table->s->all_set, - table->s->fields, - before_record, after_record); + if (table->file->is_injective()) + return 0; + bool error= 0; + THD *const thd= table->in_use; + + if (check_table_binlog_row_based(thd, table)) + { + MY_BITMAP cols; + /* Potential buffer on the stack for the bitmap */ + uint32 bitbuf[BITMAP_STACKBUF_SIZE/sizeof(uint32)]; + uint n_fields= table->s->fields; + my_bool use_bitbuf= n_fields <= sizeof(bitbuf)*8; + + /* + If there are no table maps written to the binary log, this is + the first row handled in this statement. In that case, we need + to write table maps for all locked tables to the binary log. + */ + if (likely(!(error= bitmap_init(&cols, + use_bitbuf ? bitbuf : NULL, + (n_fields + 7) & ~7UL, + false)))) + { + bitmap_set_all(&cols); + if (likely(!(error= write_locked_table_maps(thd)))) + { + error= + RowsEventT::binlog_row_logging_function(thd, table, + table->file->has_transactions(), + &cols, table->s->fields, + before_record, after_record); + } + if (!use_bitbuf) + bitmap_free(&cols); + } + } + return error ? HA_ERR_RBR_LOGGING_FAILED : 0; } - return error ? HA_ERR_RBR_LOGGING_FAILED : 0; -} + /* + Instantiate the versions we need for the above template function, + because we have -fno-implicit-template as compiling option. + */ -/* - Instantiate the versions we need for the above template function, because we - have -fno-implicit-template as compiling option. -*/ + template int + binlog_log_row<Write_rows_log_event>(TABLE *, const byte *, const byte *); -template int binlog_log_row<Write_rows_log_event>(TABLE *, const byte *, const byte *); -template int binlog_log_row<Delete_rows_log_event>(TABLE *, const byte *, const byte *); -template int binlog_log_row<Update_rows_log_event>(TABLE *, const byte *, const byte *); + template int + binlog_log_row<Delete_rows_log_event>(TABLE *, const byte *, const byte *); + + template int + binlog_log_row<Update_rows_log_event>(TABLE *, const byte *, const byte *); +} #endif /* HAVE_ROW_BASED_REPLICATION */ @@ -3272,41 +3365,6 @@ int handler::ha_external_lock(THD *thd, int lock_type) int error; if (unlikely(error= external_lock(thd, lock_type))) DBUG_RETURN(error); -#ifdef HAVE_ROW_BASED_REPLICATION - if (table->file->is_injective()) - DBUG_RETURN(0); - - /* - There is a number of statements that are logged statement-based - but call external lock. For these, we do not need to generate a - table map. - - TODO: The need for this switch is an indication that the model for - locking combined with row-based replication needs to be looked - over. Ideally, no such special handling should be needed. - */ - switch (thd->lex->sql_command) { - case SQLCOM_TRUNCATE: - case SQLCOM_ALTER_TABLE: - case SQLCOM_OPTIMIZE: - case SQLCOM_REPAIR: - DBUG_RETURN(0); - default: - break; - } - - /* - If we are locking a table for writing, we generate a table map. - For all other kinds of locks, we don't do anything. - */ - if (lock_type == F_WRLCK && check_table_binlog_row_based(thd, table)) - { - int const has_trans= table->file->has_transactions(); - error= thd->binlog_write_table_map(table, has_trans); - if (unlikely(error)) - DBUG_RETURN(error); - } -#endif DBUG_RETURN(0); } diff --git a/sql/log.cc b/sql/log.cc index 5a17ef817d0..8e56244fce6 100644 --- a/sql/log.cc +++ b/sql/log.cc @@ -71,11 +71,17 @@ sql_print_message_func sql_print_message_handlers[3] = struct binlog_trx_data { bool empty() const { +#ifdef HAVE_ROW_BASED_REPLICATION return pending == NULL && my_b_tell(&trans_log) == 0; +#else + return my_b_tell(&trans_log) == 0; +#endif } binlog_trx_data() {} IO_CACHE trans_log; // The transaction cache +#ifdef HAVE_ROW_BASED_REPLICATION Rows_log_event *pending; // The pending binrows event +#endif }; handlerton binlog_hton; @@ -1074,6 +1080,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, Log_event *end_ev) #endif error= mysql_bin_log.write(thd, trans_log, end_ev); } +#ifdef HAVE_ROW_BASED_REPLICATION else { #ifdef HAVE_ROW_BASED_REPLICATION @@ -1093,6 +1100,7 @@ binlog_end_trans(THD *thd, binlog_trx_data *trx_data, Log_event *end_ev) transaction cache. */ mysql_bin_log.update_table_map_version(); +#endif statistic_increment(binlog_cache_use, &LOCK_status); if (trans_log->disk_writes != 0) @@ -2605,7 +2613,6 @@ bool MYSQL_LOG::is_query_in_union(THD *thd, query_id_t query_id_param) } -#ifdef HAVE_ROW_BASED_REPLICATION /* These functions are placed in this file since they need access to binlog_hton, which has internal linkage. @@ -2641,6 +2648,7 @@ int THD::binlog_setup_trx_data() engine has registered for the transaction. */ +#ifdef HAVE_ROW_BASED_REPLICATION int THD::binlog_write_table_map(TABLE *table, bool is_trans) { int error; @@ -2818,9 +2826,9 @@ bool MYSQL_LOG::write(Log_event *event_info) we are inside a stored function, we do not end the statement since this will close all tables on the slave. */ +#ifdef HAVE_ROW_BASED_REPLICATION bool const end_stmt= thd->prelocked_mode && thd->lex->requires_prelocking(); -#ifdef HAVE_ROW_BASED_REPLICATION thd->binlog_flush_pending_rows_event(end_stmt); #endif /*HAVE_ROW_BASED_REPLICATION*/ @@ -2871,7 +2879,6 @@ bool MYSQL_LOG::write(Log_event *event_info) (binlog_trx_data*) thd->ha_data[binlog_hton.slot]; IO_CACHE *trans_log= &trx_data->trans_log; bool trans_log_in_use= my_b_tell(trans_log) != 0; - if (event_info->get_cache_stmt() && !trans_log_in_use) trans_register_ha(thd, (thd->options & diff --git a/sql/log_event.cc b/sql/log_event.cc index 78ab54aeb79..bf876366879 100644 --- a/sql/log_event.cc +++ b/sql/log_event.cc @@ -5595,6 +5595,7 @@ int Rows_log_event::exec_event(st_relay_log_info *rli) bool Rows_log_event::write_data_header(IO_CACHE *file) { byte buf[ROWS_HEADER_LEN]; // No need to init the buffer + DBUG_ASSERT(m_table_id != ~0UL); DBUG_EXECUTE_IF("old_row_based_repl_4_byte_map_id_master", { int4store(buf + 0, m_table_id); @@ -5845,9 +5846,7 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli) /* Open the table if it is not already open and add the table to table map. - If the table should not be replicated, we don't bother to do anything. - The table map will return NULL and the row-level event will effectively - be a no-op. + Note that for any table that should not be replicated, a filter is needed. */ uint count; /* @@ -5863,34 +5862,14 @@ int Table_map_log_event::exec_event(st_relay_log_info *rli) /* Error reporting borrowed from Query_log_event with many excessive simplifications (we don't honour --slave-skip-errors) - - BUG: There can be extreneous table maps in the binary log, - so in case we fail to open the table, we just generate a - warning and do not add the table to the list of tables to - open and lock. */ uint actual_error= thd->net.last_errno; - switch (actual_error) - { - case ER_NO_SUCH_TABLE: - slave_print_msg(WARNING_LEVEL, rli, actual_error, - thd->net.last_error ? - thd->net.last_error : - "<no message>"); - clear_all_errors(thd, rli); - rli->inc_event_relay_log_pos(); // Continue with next event - error= 0; - break; - - default: - slave_print_msg(ERROR_LEVEL, rli, actual_error, - "Error '%s' on opening table `%s`.`%s`", - (actual_error ? thd->net.last_error : - "unexpected success or fatal error"), - table_list->db, table_list->table_name); - thd->query_error= 1; - break; - } + slave_print_msg(ERROR_LEVEL, rli, actual_error, + "Error '%s' on opening table `%s`.`%s`", + (actual_error ? thd->net.last_error : + "unexpected success or fatal error"), + table_list->db, table_list->table_name); + thd->query_error= 1; } DBUG_RETURN(error); } diff --git a/sql/set_var.cc b/sql/set_var.cc index a44395c74ca..acd17a07f78 100644 --- a/sql/set_var.cc +++ b/sql/set_var.cc @@ -1301,15 +1301,20 @@ bool sys_var_thd_binlog_format::is_readonly() const if global or not here. And this test will also prevent switching from RBR to RBR (a no-op which should not happen too often). + + If we don't have row-based replication compiled in, the variable + is always read-only. */ -#ifdef HAVE_ROW_BASED_REPLICATION +#ifndef HAVE_ROW_BASED_REPLICATION + my_error(ER_RBR_NOT_AVAILABLE, MYF(0)); + return 1; +#else if ((thd->variables.binlog_format == BINLOG_FORMAT_ROW) && thd->temporary_tables) { my_error(ER_TEMP_TABLE_PREVENTS_SWITCH_OUT_OF_RBR, MYF(0)); return 1; } -#endif /*HAVE_ROW_BASED_REPLICATION*/ /* if in a stored function, it's too late to change mode */ @@ -1327,10 +1332,12 @@ bool sys_var_thd_binlog_format::is_readonly() const my_error(ER_NDB_CANT_SWITCH_BINLOG_FORMAT, MYF(0)); return 1; } -#endif +#endif /* HAVE_NDB_BINLOG */ +#endif /* HAVE_ROW_BASED_REPLICATION */ return sys_var_thd_enum::is_readonly(); } + void fix_binlog_format_after_update(THD *thd, enum_var_type type) { #ifdef HAVE_ROW_BASED_REPLICATION @@ -1338,6 +1345,7 @@ void fix_binlog_format_after_update(THD *thd, enum_var_type type) #endif /*HAVE_ROW_BASED_REPLICATION*/ } + static void fix_max_binlog_size(THD *thd, enum_var_type type) { DBUG_ENTER("fix_max_binlog_size"); diff --git a/sql/set_var.h b/sql/set_var.h index 1049b154d47..5e264c68337 100644 --- a/sql/set_var.h +++ b/sql/set_var.h @@ -881,15 +881,20 @@ public: byte *value_ptr(THD *thd, enum_var_type type, LEX_STRING *base); }; +#ifdef HAVE_ROW_BASED_REPLICATION extern void fix_binlog_format_after_update(THD *thd, enum_var_type type); +#endif class sys_var_thd_binlog_format :public sys_var_thd_enum { public: sys_var_thd_binlog_format(const char *name_arg, ulong SV::*offset_arg) :sys_var_thd_enum(name_arg, offset_arg, - &binlog_format_typelib, - fix_binlog_format_after_update) + &binlog_format_typelib +#ifdef HAVE_ROW_BASED_REPLICATION + , fix_binlog_format_after_update +#endif + ) {}; bool is_readonly() const; }; diff --git a/sql/share/errmsg.txt b/sql/share/errmsg.txt index 421da4d40b5..01fcfd1adf9 100644 --- a/sql/share/errmsg.txt +++ b/sql/share/errmsg.txt @@ -5835,3 +5835,5 @@ ER_EVENT_SET_VAR_ERROR ER_PARTITION_MERGE_ERROR eng "%s handler cannot be used in partitioned tables" swe "%s kan inte användas i en partitionerad tabell" +ER_RBR_NOT_AVAILABLE + eng "The server was not built with row-based replication" diff --git a/sql/sql_class.cc b/sql/sql_class.cc index 0ede042da17..2e435415444 100644 --- a/sql/sql_class.cc +++ b/sql/sql_class.cc @@ -2132,7 +2132,9 @@ void THD::reset_sub_statement_state(Sub_statement_state *backup, if ((!lex->requires_prelocking() || is_update_query(lex->sql_command)) && !current_stmt_binlog_row_based) + { options&= ~OPTION_BIN_LOG; + } /* Disable result sets */ client_capabilities &= ~CLIENT_MULTI_RESULTS; in_sub_stmt|= new_state; @@ -2638,31 +2640,6 @@ int THD::binlog_flush_pending_rows_event(bool stmt_end) error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0); } - else if (stmt_end && binlog_table_maps > 0) - { /* there is no pending event at this point */ - /* - If pending is null and we are going to end the statement, we - have to write an extra, empty, binrow event so that the slave - knows to discard the tables it has received. Otherwise, the - table maps written this far will be included in the table maps - for the following statement. - - TODO: Remove the need for a dummy event altogether. It can be - fixed if we can write table maps to a memory buffer before - writing the first binrow event. We can then flush and clear the - memory buffer with table map events before writing the first - binrow event. In the event of a crash, nothing is lost since - the table maps are only needed if there are binrow events. - */ - - Rows_log_event *ev= - new Write_rows_log_event(this, 0, ~0UL, 0, FALSE); - ev->set_flags(Rows_log_event::STMT_END_F); - binlog_set_pending_rows_event(ev); - - error= mysql_bin_log.flush_and_set_pending_rows_event(this, 0); - binlog_table_maps= 0; - } DBUG_RETURN(error); } @@ -2720,6 +2697,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, to how you treat this. */ case THD::ROW_QUERY_TYPE: +#ifdef HAVE_ROW_BASED_REPLICATION if (current_stmt_binlog_row_based) { /* @@ -2740,6 +2718,7 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, #endif /*HAVE_ROW_BASED_REPLICATION*/ DBUG_RETURN(0); } +#endif /* Otherwise, we fall through */ case THD::STMT_QUERY_TYPE: /* @@ -2748,7 +2727,9 @@ int THD::binlog_query(THD::enum_binlog_query_type qtype, */ { Query_log_event qinfo(this, query, query_len, is_trans, suppress_use); +#ifdef HAVE_ROW_BASED_REPLICATION qinfo.flags|= LOG_EVENT_UPDATE_TABLE_MAP_VERSION_F; +#endif /* Binlog table maps will be irrelevant after a Query_log_event (they are just removed on the slave side) so after the query diff --git a/sql/sql_class.h b/sql/sql_class.h index 450a8d041c9..702c8fee671 100644 --- a/sql/sql_class.h +++ b/sql/sql_class.h @@ -907,8 +907,10 @@ public: /* container for handler's private per-connection data */ void *ha_data[MAX_HA]; -#ifdef HAVE_ROW_BASED_REPLICATION #ifndef MYSQL_CLIENT + int binlog_setup_trx_data(); + +#ifdef HAVE_ROW_BASED_REPLICATION /* Public interface to write RBR events to the binlog @@ -938,7 +940,6 @@ public: RowsEventT* hint); Rows_log_event* binlog_get_pending_rows_event() const; void binlog_set_pending_rows_event(Rows_log_event* ev); - int binlog_setup_trx_data(); my_size_t max_row_length_blob(TABLE* table, const byte *data) const; my_size_t max_row_length(TABLE* table, const byte *data) const @@ -959,12 +960,15 @@ public: private: uint binlog_table_maps; // Number of table maps currently in the binlog - public: - -#endif + uint get_binlog_table_maps() const { + return binlog_table_maps; + } #endif /* HAVE_ROW_BASED_REPLICATION */ +#endif /* MYSQL_CLIENT */ + #ifndef MYSQL_CLIENT +public: enum enum_binlog_query_type { /* The query can be logged row-based or statement-based @@ -1402,18 +1406,26 @@ public: inline void set_current_stmt_binlog_row_based_if_mixed() { if (variables.binlog_format == BINLOG_FORMAT_MIXED) - current_stmt_binlog_row_based= 1; + current_stmt_binlog_row_based= TRUE; } inline void set_current_stmt_binlog_row_based() { - current_stmt_binlog_row_based= 1; + current_stmt_binlog_row_based= TRUE; + } + inline void clear_current_stmt_binlog_row_based() + { + current_stmt_binlog_row_based= FALSE; } +#endif inline void reset_current_stmt_binlog_row_based() { - current_stmt_binlog_row_based= test(variables.binlog_format == - BINLOG_FORMAT_ROW); +#ifdef HAVE_ROW_BASED_REPLICATION + current_stmt_binlog_row_based= + test(variables.binlog_format == BINLOG_FORMAT_ROW); +#else + current_stmt_binlog_row_based= FALSE; +#endif } -#endif /*HAVE_ROW_BASED_REPLICATION*/ }; @@ -1578,6 +1590,9 @@ class select_insert :public select_result_interceptor { bool send_eof(); /* not implemented: select_insert is never re-used in prepared statements */ void cleanup(); + +protected: + MYSQL_LOCK *lock; }; @@ -1587,7 +1602,6 @@ class select_create: public select_insert { List<create_field> *extra_fields; List<Key> *keys; HA_CREATE_INFO *create_info; - MYSQL_LOCK *lock; Field **field; public: select_create (TABLE_LIST *table, @@ -1601,7 +1615,10 @@ public: lock(0) {} int prepare(List<Item> &list, SELECT_LEX_UNIT *u); + +#ifdef HAVE_ROW_BASED_REPLICATION void binlog_show_create_table(TABLE **tables, uint count); +#endif void store_values(List<Item> &values); void send_error(uint errcode,const char *err); bool send_eof(); diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc index dd4748bc15c..73a0a9a69c2 100644 --- a/sql/sql_delete.cc +++ b/sql/sql_delete.cc @@ -42,8 +42,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, ha_rows deleted= 0; uint usable_index= MAX_KEY; SELECT_LEX *select_lex= &thd->lex->select_lex; - bool ha_delete_all_rows= 0; - ulonglong const saved_options= thd->options; DBUG_ENTER("mysql_delete"); if (open_and_lock_tables(thd, table_list)) @@ -75,20 +73,19 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, Test if the user wants to delete all rows and deletion doesn't have any side-effects (because of triggers), so we can use optimized handler::delete_all_rows() method. + + If row-based replication is used, we also delete the table row by + row. */ if (!using_limit && const_cond && (!conds || conds->val_int()) && !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) && - !(table->triggers && table->triggers->has_delete_triggers())) + !(table->triggers && table->triggers->has_delete_triggers()) && + !thd->current_stmt_binlog_row_based) { /* Update the table->file->stats.records number */ table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK); ha_rows const maybe_deleted= table->file->stats.records; - /* - If all rows shall be deleted, we (almost) always log this - statement-based (see [binlog], below), so we set this flag and - test it below. - */ - ha_delete_all_rows= 1; + DBUG_PRINT("debug", ("Trying to use delete_all_rows()")); if (!(error=table->file->delete_all_rows())) { error= -1; // ok @@ -218,13 +215,6 @@ bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, thd->proc_info="updating"; will_batch= !table->file->start_bulk_delete(); - /* - We saved the thread options above before clearing the - OPTION_BIN_LOG, and will restore below, effectively disabling the - binary log (unless it was already disabled, of course). - */ - if (ha_delete_all_rows) - thd->options&= ~static_cast<ulonglong>(OPTION_BIN_LOG); table->mark_columns_needed_for_delete(); @@ -318,12 +308,6 @@ cleanup: delete select; transactional_table= table->file->has_transactions(); - /* - Restore the saved value of the OPTION_BIN_LOG bit in the thread - options before executing binlog_query() below. - */ - thd->options|= (saved_options & OPTION_BIN_LOG); - /* See similar binlogging code in sql_update.cc, for comments */ if ((error < 0) || (deleted && !transactional_table)) { @@ -338,11 +322,7 @@ cleanup: statement-based; otherwise, 'ha_delete_row()' was used to delete specific rows which we might log row-based. */ - THD::enum_binlog_query_type const - query_type(ha_delete_all_rows && !table->file->is_injective() ? - THD::STMT_QUERY_TYPE : - THD::ROW_QUERY_TYPE); - int log_result= thd->binlog_query(query_type, + int log_result= thd->binlog_query(THD::ROW_QUERY_TYPE, thd->query, thd->query_length, transactional_table, FALSE); @@ -1004,6 +984,9 @@ 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 + 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); diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc index 0dae2b8f37b..175d69de244 100644 --- a/sql/sql_insert.cc +++ b/sql/sql_insert.cc @@ -2183,6 +2183,7 @@ select_insert::select_insert(TABLE_LIST *table_list_par, TABLE *table_par, bool ignore_check_option_errors) :table_list(table_list_par), table(table_par), fields(fields_par), last_insert_id(0), + lock(0), insert_into_view(table_list_par && table_list_par->view != 0) { bzero((char*) &info,sizeof(info)); @@ -2370,7 +2371,36 @@ bool select_insert::send_data(List<Item> &values) DBUG_RETURN(1); } } - if (!(error= write_record(thd, table, &info))) + + /* + The thd->lock lock contain the locks for the select part of the + statement and the 'lock' variable contain the write lock for the + currently locked table that is being created or inserted + into. However, the row-based replication will investigate the + thd->lock to decide what table maps are to be written, so this one + has to contain the tables locked for writing. To be able to write + table map for the table being created, we temporarily set + THD::lock to select_insert::lock while writing the record to the + storage engine. We cannot set this elsewhere, since the execution + of a stored function inside the select expression might cause the + lock structures to be NULL. + */ + + { + MYSQL_LOCK *saved_lock= NULL; + if (lock) + { + saved_lock= thd->lock; + thd->lock= lock; + } + + error= write_record(thd, table, &info); + + if (lock) + thd->lock= saved_lock; + } + + if (!error) { if (table->triggers || info.handle_duplicates == DUP_UPDATE) { @@ -2715,15 +2745,34 @@ private: }; -int select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) +int +select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) { - MY_HOOKS hooks(this); DBUG_ENTER("select_create::prepare"); + TABLEOP_HOOKS *hook_ptr= NULL; +#ifdef HAVE_ROW_BASED_REPLICATION + 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; + }; + + MY_HOOKS hooks(this); + hook_ptr= &hooks; +#endif + unit= u; if (!(table= create_table_from_items(thd, create_info, create_table, extra_fields, keys, &values, &lock, - &hooks))) + &hook_ptr))) DBUG_RETURN(-1); // abort() deletes table if (table->s->fields < values.elements) @@ -2759,7 +2808,9 @@ int select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u) } -void select_create::binlog_show_create_table(TABLE **tables, uint count) +#ifdef HAVE_ROW_BASED_REPLICATION +void +select_create::binlog_show_create_table(TABLE **tables, uint count) { /* Note 1: In RBR mode, we generate a CREATE TABLE statement for the @@ -2778,9 +2829,7 @@ void select_create::binlog_show_create_table(TABLE **tables, uint count) schema that will do a close_thread_tables(), destroying the statement transaction cache. */ -#ifdef HAVE_ROW_BASED_REPLICATION DBUG_ASSERT(thd->current_stmt_binlog_row_based); -#endif DBUG_ASSERT(tables && *tables && count > 0); char buf[2048]; @@ -2800,7 +2849,7 @@ void select_create::binlog_show_create_table(TABLE **tables, uint count) /* is_trans */ TRUE, /* suppress_use */ FALSE); } - +#endif // HAVE_ROW_BASED_REPLICATION void select_create::store_values(List<Item> &values) { diff --git a/storage/innobase/CMakeLists.txt b/storage/innobase/CMakeLists.txt index def51873725..8b8c3af6582 100644 --- a/storage/innobase/CMakeLists.txt +++ b/storage/innobase/CMakeLists.txt @@ -32,4 +32,4 @@ ADD_LIBRARY(innobase btr/btr0btr.c btr/btr0cur.c btr/btr0pcur.c btr/btr0sea.c thr/thr0loc.c trx/trx0purge.c trx/trx0rec.c trx/trx0roll.c trx/trx0rseg.c trx/trx0sys.c trx/trx0trx.c trx/trx0undo.c usr/usr0sess.c - ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c) + ut/ut0byte.c ut/ut0dbg.c ut/ut0mem.c ut/ut0rnd.c ut/ut0ut.c ut/ut0vec.c ut/ut0list.c ut/ut0wqueue.c) diff --git a/storage/innobase/Makefile.am b/storage/innobase/Makefile.am index bf41d3dca88..7884715d839 100644 --- a/storage/innobase/Makefile.am +++ b/storage/innobase/Makefile.am @@ -76,7 +76,9 @@ EXTRA_DIST = include/btr0btr.h include/btr0btr.ic include/btr0cur.h include/btr include/univ.i include/usr0sess.h include/usr0sess.ic include/usr0types.h \ include/ut0byte.h include/ut0byte.ic include/ut0dbg.h include/ut0lst.h \ include/ut0mem.h include/ut0mem.ic include/ut0rnd.h include/ut0rnd.ic \ - include/ut0sort.h include/ut0ut.h include/ut0ut.ic include/ut0vec.h include/ut0vec.ic \ + include/ut0sort.h include/ut0ut.h include/ut0ut.ic include/ut0vec.h include/ut0vec.ic include/ha_prototypes.h \ + include/ut0list.h include/ut0list.ic \ + include/ut0wqueue.h \ CMakeLists.txt noinst_LIBRARIES = libinnobase.a diff --git a/storage/innobase/btr/btr0btr.c b/storage/innobase/btr/btr0btr.c index 5e338f97982..ae3e722b513 100644 --- a/storage/innobase/btr/btr0btr.c +++ b/storage/innobase/btr/btr0btr.c @@ -190,6 +190,10 @@ btr_get_prev_user_rec( || (mtr_memo_contains(mtr, buf_block_align(prev_page), MTR_MEMO_PAGE_X_FIX))); ut_a(page_is_comp(prev_page) == page_is_comp(page)); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(prev_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ return(page_rec_get_prev(page_get_supremum_rec(prev_page))); } @@ -237,6 +241,10 @@ btr_get_next_user_rec( MTR_MEMO_PAGE_S_FIX)) || (mtr_memo_contains(mtr, buf_block_align(next_page), MTR_MEMO_PAGE_X_FIX))); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_prev(next_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ ut_a(page_is_comp(next_page) == page_is_comp(page)); return(page_rec_get_next(page_get_infimum_rec(next_page))); @@ -597,9 +605,9 @@ btr_page_get_father_for_rec( buf_page_print(buf_frame_align(node_ptr)); fputs("InnoDB: Corruption of an index tree: table ", stderr); - ut_print_name(stderr, NULL, index->table_name); + ut_print_name(stderr, NULL, TRUE, index->table_name); fputs(", index ", stderr); - ut_print_name(stderr, NULL, index->name); + ut_print_name(stderr, NULL, FALSE, index->name); fprintf(stderr, ",\n" "InnoDB: father ptr page no %lu, child page no %lu\n", (ulong) @@ -1518,6 +1526,10 @@ btr_attach_half_pages( prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr); ut_a(page_is_comp(prev_page) == page_is_comp(page)); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(prev_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ btr_page_set_next(prev_page, lower_page_no, mtr); } @@ -1805,6 +1817,10 @@ btr_level_list_remove( prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr); ut_a(page_is_comp(prev_page) == page_is_comp(page)); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(prev_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ btr_page_set_next(prev_page, next_page_no, mtr); } @@ -1813,6 +1829,10 @@ btr_level_list_remove( next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr); ut_a(page_is_comp(next_page) == page_is_comp(page)); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_prev(next_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ btr_page_set_prev(next_page, prev_page_no, mtr); } @@ -2032,16 +2052,24 @@ btr_compress( /* Decide the page to which we try to merge and which will inherit the locks */ - if (left_page_no != FIL_NULL) { + is_left = left_page_no != FIL_NULL; + + if (is_left) { - is_left = TRUE; merge_page = btr_page_get(space, left_page_no, RW_X_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(merge_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ } else if (right_page_no != FIL_NULL) { - is_left = FALSE; merge_page = btr_page_get(space, right_page_no, RW_X_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_prev(merge_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ } else { /* The page is the only one on the level, lift the records to the father */ @@ -2203,7 +2231,6 @@ btr_discard_page( ulint left_page_no; ulint right_page_no; page_t* merge_page; - ibool is_left; page_t* page; rec_t* node_ptr; @@ -2223,13 +2250,19 @@ btr_discard_page( right_page_no = btr_page_get_next(page, mtr); if (left_page_no != FIL_NULL) { - is_left = TRUE; merge_page = btr_page_get(space, left_page_no, RW_X_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(merge_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ } else if (right_page_no != FIL_NULL) { - is_left = FALSE; merge_page = btr_page_get(space, right_page_no, RW_X_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_prev(merge_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ } else { btr_discard_only_page_on_level(tree, page, mtr); @@ -2256,11 +2289,11 @@ btr_discard_page( /* Remove the page from the level list */ btr_level_list_remove(tree, page, mtr); - if (is_left) { + if (left_page_no != FIL_NULL) { lock_update_discard(page_get_supremum_rec(merge_page), page); } else { lock_update_discard(page_rec_get_next( - page_get_infimum_rec(merge_page)), page); + page_get_infimum_rec(merge_page)), page); } /* Free the file page */ @@ -2745,7 +2778,29 @@ loop: rec_t* right_rec; right_page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr); - ut_a(page_is_comp(right_page) == page_is_comp(page)); + if (UNIV_UNLIKELY(btr_page_get_prev(right_page, &mtr) + != buf_frame_get_page_no(page))) { + btr_validate_report2(index, level, page, right_page); + fputs("InnoDB: broken FIL_PAGE_NEXT" + " or FIL_PAGE_PREV links\n", stderr); + buf_page_print(page); + buf_page_print(right_page); + + ret = FALSE; + } + + if (UNIV_UNLIKELY(page_is_comp(right_page) + != page_is_comp(page))) { + btr_validate_report2(index, level, page, right_page); + fputs("InnoDB: 'compact' flag mismatch\n", stderr); + buf_page_print(page); + buf_page_print(right_page); + + ret = FALSE; + + goto node_ptr_fails; + } + rec = page_rec_get_prev(page_get_supremum_rec(page)); right_rec = page_rec_get_next( page_get_infimum_rec(right_page)); @@ -2753,8 +2808,8 @@ loop: offsets, ULINT_UNDEFINED, &heap); offsets2 = rec_get_offsets(right_rec, index, offsets2, ULINT_UNDEFINED, &heap); - if (cmp_rec_rec(rec, right_rec, offsets, offsets2, index) - >= 0) { + if (UNIV_UNLIKELY(cmp_rec_rec(rec, right_rec, + offsets, offsets2, index) >= 0)) { btr_validate_report2(index, level, page, right_page); @@ -2869,10 +2924,7 @@ loop: ut_a(node_ptr == page_rec_get_prev( page_get_supremum_rec(father_page))); ut_a(btr_page_get_next(father_page, &mtr) == FIL_NULL); - } - - if (right_page_no != FIL_NULL) { - + } else { right_node_ptr = btr_page_get_father_node_ptr(tree, right_page, &mtr); if (page_rec_get_next(node_ptr) != @@ -2934,14 +2986,15 @@ loop: } node_ptr_fails: + /* Commit the mini-transaction to release the latch on 'page'. + Re-acquire the latch on right_page, which will become 'page' + on the next loop. The page has already been checked. */ mtr_commit(&mtr); if (right_page_no != FIL_NULL) { - ulint comp = page_is_comp(page); mtr_start(&mtr); page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr); - ut_a(page_is_comp(page) == comp); goto loop; } diff --git a/storage/innobase/btr/btr0cur.c b/storage/innobase/btr/btr0cur.c index deba3e23487..74def379058 100644 --- a/storage/innobase/btr/btr0cur.c +++ b/storage/innobase/btr/btr0cur.c @@ -157,6 +157,10 @@ btr_cur_latch_leaves( if (left_page_no != FIL_NULL) { get_page = btr_page_get(space, left_page_no, RW_X_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(get_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ ut_a(page_is_comp(get_page) == page_is_comp(page)); buf_block_align(get_page)->check_index_page_at_flush = TRUE; @@ -171,6 +175,10 @@ btr_cur_latch_leaves( if (right_page_no != FIL_NULL) { get_page = btr_page_get(space, right_page_no, RW_X_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_prev(get_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ buf_block_align(get_page)->check_index_page_at_flush = TRUE; } @@ -183,6 +191,10 @@ btr_cur_latch_leaves( if (left_page_no != FIL_NULL) { cursor->left_page = btr_page_get(space, left_page_no, RW_S_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(cursor->left_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ ut_a(page_is_comp(cursor->left_page) == page_is_comp(page)); buf_block_align( @@ -201,6 +213,10 @@ btr_cur_latch_leaves( if (left_page_no != FIL_NULL) { cursor->left_page = btr_page_get(space, left_page_no, RW_X_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(cursor->left_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ ut_a(page_is_comp(cursor->left_page) == page_is_comp(page)); buf_block_align( @@ -1731,6 +1747,10 @@ btr_cur_pess_upd_restore_supremum( ut_ad(prev_page_no != FIL_NULL); prev_page = buf_page_get_with_no_latch(space, prev_page_no, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(prev_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ /* We must already have an x-latch to prev_page! */ ut_ad(mtr_memo_contains(mtr, buf_block_align(prev_page), @@ -3771,11 +3791,6 @@ btr_copy_externally_stored_field( page_no = btr_blob_get_next_page_no(blob_header); - /* On other BLOB pages except the first the BLOB header - always is at the page data start: */ - - offset = FIL_PAGE_DATA; - mtr_commit(&mtr); if (page_no == FIL_NULL) { @@ -3786,6 +3801,11 @@ btr_copy_externally_stored_field( return(buf); } + /* On other BLOB pages except the first the BLOB header + always is at the page data start: */ + + offset = FIL_PAGE_DATA; + ut_a(copied_len < local_len + extern_len); } } diff --git a/storage/innobase/btr/btr0pcur.c b/storage/innobase/btr/btr0pcur.c index 85a6577bafb..c739930ce04 100644 --- a/storage/innobase/btr/btr0pcur.c +++ b/storage/innobase/btr/btr0pcur.c @@ -397,6 +397,9 @@ btr_pcur_move_to_next_page( ut_ad(next_page_no != FIL_NULL); next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_prev(next_page, mtr) == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ ut_a(page_is_comp(next_page) == page_is_comp(page)); buf_block_align(next_page)->check_index_page_at_flush = TRUE; diff --git a/storage/innobase/btr/btr0sea.c b/storage/innobase/btr/btr0sea.c index be7bb7c421f..2f2102379ab 100644 --- a/storage/innobase/btr/btr0sea.c +++ b/storage/innobase/btr/btr0sea.c @@ -136,13 +136,12 @@ btr_search_sys_create( btr_search_latch_temp = mem_alloc(sizeof(rw_lock_t)); - rw_lock_create(&btr_search_latch); + rw_lock_create(&btr_search_latch, SYNC_SEARCH_SYS); btr_search_sys = mem_alloc(sizeof(btr_search_sys_t)); btr_search_sys->hash_index = ha_create(TRUE, hash_size, 0, 0); - rw_lock_set_level(&btr_search_latch, SYNC_SEARCH_SYS); } /********************************************************************* diff --git a/storage/innobase/buf/buf0buf.c b/storage/innobase/buf/buf0buf.c index 197b38149fe..5f3e4a9ea50 100644 --- a/storage/innobase/buf/buf0buf.c +++ b/storage/innobase/buf/buf0buf.c @@ -524,12 +524,11 @@ buf_block_init( block->n_pointers = 0; - rw_lock_create(&(block->lock)); + rw_lock_create(&block->lock, SYNC_LEVEL_VARYING); ut_ad(rw_lock_validate(&(block->lock))); #ifdef UNIV_SYNC_DEBUG - rw_lock_create(&(block->debug_latch)); - rw_lock_set_level(&(block->debug_latch), SYNC_NO_ORDER_CHECK); + rw_lock_create(&block->debug_latch, SYNC_NO_ORDER_CHECK); #endif /* UNIV_SYNC_DEBUG */ } @@ -572,8 +571,7 @@ buf_pool_init( /* 1. Initialize general fields ---------------------------- */ - mutex_create(&(buf_pool->mutex)); - mutex_set_level(&(buf_pool->mutex), SYNC_BUF_POOL); + mutex_create(&buf_pool->mutex, SYNC_BUF_POOL); mutex_enter(&(buf_pool->mutex)); @@ -1856,7 +1854,6 @@ buf_page_io_complete( buf_block_t* block) /* in: pointer to the block in question */ { ulint io_type; - ulint read_page_no; ut_ad(block); @@ -1866,18 +1863,36 @@ buf_page_io_complete( if (io_type == BUF_IO_READ) { /* If this page is not uninitialized and not in the - doublewrite buffer, then the page number should be the - same as in block */ - - read_page_no = mach_read_from_4((block->frame) + doublewrite buffer, then the page number and space id + should be the same as in block. */ + ulint read_page_no = mach_read_from_4((block->frame) + FIL_PAGE_OFFSET); - if (read_page_no != 0 - && !trx_doublewrite_page_inside(read_page_no) - && read_page_no != block->offset) { + ulint read_space_id = mach_read_from_4((block->frame) + + FIL_PAGE_ARCH_LOG_NO_OR_SPACE_ID); + + if (!block->space && trx_doublewrite_page_inside( + block->offset)) { + ut_print_timestamp(stderr); fprintf(stderr, -"InnoDB: Error: page n:o stored in the page read in is %lu, should be %lu!\n", - (ulong) read_page_no, (ulong) block->offset); +" InnoDB: Error: reading page %lu\n" +"InnoDB: which is in the doublewrite buffer!\n", + (ulong) block->offset); + } else if (!read_space_id && !read_page_no) { + /* This is likely an uninitialized page. */ + } else if ((block->space && block->space != read_space_id) + || block->offset != read_page_no) { + /* We did not compare space_id to read_space_id + if block->space == 0, because the field on the + page may contain garbage in MySQL < 4.1.1, + which only supported block->space == 0. */ + + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: Error: space id and page n:o stored in the page\n" +"InnoDB: read in are %lu:%lu, should be %lu:%lu!\n", + (ulong) read_space_id, (ulong) read_page_no, + (ulong) block->space, (ulong) block->offset); } /* From version 3.23.38 up we store the page checksum to the 4 first bytes of the page end lsn field */ @@ -2233,7 +2248,8 @@ buf_get_latched_pages_number(void) } mutex_exit(&(buf_pool->mutex)); - return fixed_pages_number; + + return(fixed_pages_number); } /************************************************************************* diff --git a/storage/innobase/buf/buf0flu.c b/storage/innobase/buf/buf0flu.c index 7b02e353b76..9bfbeb1b456 100644 --- a/storage/innobase/buf/buf0flu.c +++ b/storage/innobase/buf/buf0flu.c @@ -26,7 +26,7 @@ Created 11/11/1995 Heikki Tuuri #include "trx0sys.h" #include "srv0srv.h" -/* When flushed, dirty blocks are searched in neigborhoods of this size, and +/* When flushed, dirty blocks are searched in neighborhoods of this size, and flushed along with the original page. */ #define BUF_FLUSH_AREA ut_min(BUF_READ_AHEAD_AREA,\ diff --git a/storage/innobase/data/data0type.c b/storage/innobase/data/data0type.c index 2f36e7250fc..54dbb7b1a15 100644 --- a/storage/innobase/data/data0type.c +++ b/storage/innobase/data/data0type.c @@ -293,3 +293,35 @@ dtype_print( fprintf(stderr, " len %lu prec %lu", (ulong) len, (ulong) type->prec); } + +/*************************************************************************** +Returns the maximum size of a data type. Note: types in system tables may be +incomplete and return incorrect information. */ +ulint +dtype_get_max_size( +/*===============*/ + /* out: maximum size (ULINT_MAX for + unbounded types) */ + const dtype_t* type) /* in: type */ +{ + switch (type->mtype) { + case DATA_SYS: + case DATA_CHAR: + case DATA_FIXBINARY: + case DATA_INT: + case DATA_FLOAT: + case DATA_DOUBLE: + case DATA_MYSQL: + case DATA_VARCHAR: + case DATA_BINARY: + case DATA_DECIMAL: + case DATA_VARMYSQL: + return(type->len); + case DATA_BLOB: + return(ULINT_MAX); + default: + ut_error; + } + + return(ULINT_MAX); +} diff --git a/storage/innobase/dict/dict0crea.c b/storage/innobase/dict/dict0crea.c index 4233cb05773..a41c90261d8 100644 --- a/storage/innobase/dict/dict0crea.c +++ b/storage/innobase/dict/dict0crea.c @@ -1250,9 +1250,9 @@ dict_foreign_eval_sql( ut_print_timestamp(ef); fputs(" Error in foreign key constraint creation for table ", ef); - ut_print_name(ef, trx, table->name); + ut_print_name(ef, trx, TRUE, table->name); fputs(".\nA foreign key constraint of name ", ef); - ut_print_name(ef, trx, foreign->id); + ut_print_name(ef, trx, FALSE, foreign->id); fputs("\nalready exists." " (Note that internally InnoDB adds 'databasename/'\n" "in front of the user-defined constraint name).\n", @@ -1280,7 +1280,7 @@ dict_foreign_eval_sql( ut_print_timestamp(ef); fputs(" Internal error in foreign key constraint creation" " for table ", ef); - ut_print_name(ef, trx, table->name); + ut_print_name(ef, trx, TRUE, table->name); fputs(".\n" "See the MySQL .err log in the datadir for more information.\n", ef); mutex_exit(&dict_foreign_err_mutex); diff --git a/storage/innobase/dict/dict0dict.c b/storage/innobase/dict/dict0dict.c index 74dffd4c906..8fe3dac4c56 100644 --- a/storage/innobase/dict/dict0dict.c +++ b/storage/innobase/dict/dict0dict.c @@ -26,6 +26,9 @@ Created 1/8/1996 Heikki Tuuri #include "pars0sym.h" #include "que0que.h" #include "rem0cmp.h" +#ifndef UNIV_HOTBACKUP +# include "m_ctype.h" /* my_isspace() */ +#endif /* !UNIV_HOTBACKUP */ dict_sys_t* dict_sys = NULL; /* the dictionary system */ @@ -55,6 +58,42 @@ static char dict_ibfk[] = "_ibfk_"; #ifndef UNIV_HOTBACKUP /********************************************************************** +Converts an identifier to a table name. + +NOTE: the prototype of this function is copied from ha_innodb.cc! If you change +this function, you MUST change also the prototype here! */ +extern +void +innobase_convert_from_table_id( +/*===========================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len); /* in: length of 'to', in bytes; + should be at least 5 * strlen(to) + 1 */ +/********************************************************************** +Converts an identifier to UTF-8. + +NOTE: the prototype of this function is copied from ha_innodb.cc! If you change +this function, you MUST change also the prototype here! */ +extern +void +innobase_convert_from_id( +/*=====================*/ + char* to, /* out: converted identifier */ + const char* from, /* in: identifier to convert */ + ulint len); /* in: length of 'to', in bytes; + should be at least 3 * strlen(to) + 1 */ +/********************************************************************** +Removes the filename encoding of a table or database name. + +NOTE: the prototype of this function is copied from ha_innodb.cc! If you change +this function, you MUST change also the prototype here! */ +extern +void +innobase_convert_from_filename( +/*===========================*/ + char* s); /* in: identifier; out: decoded identifier */ +/********************************************************************** Compares NUL-terminated UTF-8 strings case insensitively. NOTE: the prototype of this function is copied from ha_innodb.cc! If you change @@ -77,6 +116,17 @@ void innobase_casedn_str( /*================*/ char* a); /* in/out: string to put in lower case */ + +/************************************************************************** +Determines the connection character set. + +NOTE: the prototype of this function is copied from ha_innodb.cc! If you change +this function, you MUST change also the prototype here! */ +struct charset_info_st* +innobase_get_charset( +/*=================*/ + /* out: connection character set */ + void* mysql_thd); /* in: MySQL thread handle */ #endif /* !UNIV_HOTBACKUP */ /************************************************************************** @@ -607,7 +657,7 @@ dict_index_get_nth_field_pos( } /************************************************************************** -Returns a table object, based on table id, and memoryfixes it. */ +Returns a table object based on table id. */ dict_table_t* dict_table_get_on_id( @@ -629,12 +679,12 @@ dict_table_get_on_id( ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ - return(dict_table_get_on_id_low(table_id, trx)); + return(dict_table_get_on_id_low(table_id)); } mutex_enter(&(dict_sys->mutex)); - table = dict_table_get_on_id_low(table_id, trx); + table = dict_table_get_on_id_low(table_id); mutex_exit(&(dict_sys->mutex)); @@ -716,8 +766,7 @@ dict_init(void) { dict_sys = mem_alloc(sizeof(dict_sys_t)); - mutex_create(&(dict_sys->mutex)); - mutex_set_level(&(dict_sys->mutex), SYNC_DICT); + mutex_create(&dict_sys->mutex, SYNC_DICT); dict_sys->table_hash = hash_create(buf_pool_get_max_size() / (DICT_POOL_PER_TABLE_HASH * @@ -732,32 +781,28 @@ dict_init(void) UT_LIST_INIT(dict_sys->table_LRU); - rw_lock_create(&dict_operation_lock); - rw_lock_set_level(&dict_operation_lock, SYNC_DICT_OPERATION); + rw_lock_create(&dict_operation_lock, SYNC_DICT_OPERATION); dict_foreign_err_file = os_file_create_tmpfile(); ut_a(dict_foreign_err_file); - mutex_create(&dict_foreign_err_mutex); - mutex_set_level(&dict_foreign_err_mutex, SYNC_ANY_LATCH); + + mutex_create(&dict_foreign_err_mutex, SYNC_ANY_LATCH); } /************************************************************************** -Returns a table object and memoryfixes it. NOTE! This is a high-level -function to be used mainly from outside the 'dict' directory. Inside this -directory dict_table_get_low is usually the appropriate function. */ +Returns a table object. NOTE! This is a high-level function to be used +mainly from outside the 'dict' directory. Inside this directory +dict_table_get_low is usually the appropriate function. */ dict_table_t* dict_table_get( /*===========*/ /* out: table, NULL if does not exist */ - const char* table_name, /* in: table name */ - trx_t* trx) /* in: transaction handle or NULL */ + const char* table_name) /* in: table name */ { dict_table_t* table; - UT_NOT_USED(trx); - mutex_enter(&(dict_sys->mutex)); table = dict_table_get_low(table_name); @@ -781,13 +826,10 @@ dict_table_get_and_increment_handle_count( /*======================================*/ /* out: table, NULL if does not exist */ - const char* table_name, /* in: table name */ - trx_t* trx) /* in: transaction handle or NULL */ + const char* table_name) /* in: table name */ { dict_table_t* table; - UT_NOT_USED(trx); - mutex_enter(&(dict_sys->mutex)); table = dict_table_get_low(table_name); @@ -819,6 +861,7 @@ dict_table_add_to_cache( ulint fold; ulint id_fold; ulint i; + ulint row_len; ut_ad(table); #ifdef UNIV_SYNC_DEBUG @@ -866,6 +909,24 @@ dict_table_add_to_cache( #error "DATA_N_SYS_COLS != 4" #endif + row_len = 0; + for (i = 0; i < table->n_def; i++) { + ulint col_len = dtype_get_max_size( + dict_col_get_type(dict_table_get_nth_col(table, i))); + + /* If we have a single unbounded field, or several gigantic + fields, mark the maximum row size as ULINT_MAX. */ + if (ut_max(col_len, row_len) >= (ULINT_MAX / 2)) { + row_len = ULINT_MAX; + + break; + } + + row_len += col_len; + } + + table->max_row_size = row_len; + /* Look for a table with the same name: error if such exists */ { dict_table_t* table2; @@ -897,10 +958,7 @@ dict_table_add_to_cache( /* Add table to LRU list of tables */ UT_LIST_ADD_FIRST(table_LRU, dict_sys->table_LRU, table); - /* If the dictionary cache grows too big, trim the table LRU list */ - dict_sys->size += mem_heap_get_size(table->heap); - /* dict_table_LRU_trim(); */ } /************************************************************************** @@ -1266,38 +1324,6 @@ dict_table_remove_from_cache( } /************************************************************************** -Frees tables from the end of table_LRU if the dictionary cache occupies -too much space. Currently not used! */ - -void -dict_table_LRU_trim(void) -/*=====================*/ -{ - dict_table_t* table; - dict_table_t* prev_table; - - ut_error; - -#ifdef UNIV_SYNC_DEBUG - ut_ad(mutex_own(&(dict_sys->mutex))); -#endif /* UNIV_SYNC_DEBUG */ - - table = UT_LIST_GET_LAST(dict_sys->table_LRU); - - while (table && (dict_sys->size > - buf_pool_get_max_size() / DICT_POOL_PER_VARYING)) { - - prev_table = UT_LIST_GET_PREV(table_LRU, table); - - if (table->mem_fix == 0) { - dict_table_remove_from_cache(table); - } - - table = prev_table; - } -} - -/************************************************************************** Adds a column to the data dictionary hash table. */ static void @@ -1443,6 +1469,7 @@ dict_index_add_to_cache( ut_ad(mem_heap_validate(index->heap)); +#ifdef UNIV_DEBUG { dict_index_t* index2; index2 = UT_LIST_GET_FIRST(table->indexes); @@ -1452,10 +1479,11 @@ dict_index_add_to_cache( index2 = UT_LIST_GET_NEXT(indexes, index2); } - - ut_a(UT_LIST_GET_LEN(table->indexes) == 0 - || (index->type & DICT_CLUSTERED) == 0); } +#endif /* UNIV_DEBUG */ + + ut_a(!(index->type & DICT_CLUSTERED) + || UT_LIST_GET_LEN(table->indexes) == 0); success = dict_index_find_cols(table, index); @@ -1526,10 +1554,7 @@ dict_index_add_to_cache( /* Add the index to the list of indexes stored in the tree */ tree->tree_index = new_index; - /* If the dictionary cache grows too big, trim the table LRU list */ - dict_sys->size += mem_heap_get_size(new_index->heap); - /* dict_table_LRU_trim(); */ dict_mem_index_free(index); @@ -2091,6 +2116,7 @@ dict_foreign_find( return(NULL); } +#ifndef UNIV_HOTBACKUP /************************************************************************* Tries to find an index whose first fields are the columns in the array, in the same order. */ @@ -2108,7 +2134,6 @@ dict_foreign_find_index( only has an effect if types_idx != NULL. */ { -#ifndef UNIV_HOTBACKUP dict_index_t* index; const char* col_name; ulint i; @@ -2154,13 +2179,6 @@ dict_foreign_find_index( } return(NULL); -#else /* UNIV_HOTBACKUP */ - /* This function depends on MySQL code that is not included in - InnoDB Hot Backup builds. Besides, this function should never - be called in InnoDB Hot Backup. */ - ut_error; - return(NULL); -#endif /* UNIV_HOTBACKUP */ } /************************************************************************** @@ -2196,7 +2214,7 @@ dict_foreign_error_report( putc('\n', file); if (fk->foreign_index) { fputs("The index in the foreign key in table is ", file); - ut_print_name(file, NULL, fk->foreign_index->name); + ut_print_name(file, NULL, FALSE, fk->foreign_index->name); fputs( "\nSee http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" "for correct foreign key definition.\n", @@ -2359,12 +2377,13 @@ dict_scan_to( /************************************************************************* Accepts a specified string. Comparisons are case-insensitive. */ - +static const char* dict_accept( /*========*/ /* out: if string was accepted, the pointer is moved after that, else ptr is returned */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scan from this */ const char* string, /* in: accept only this string as the next non-whitespace string */ @@ -2375,7 +2394,7 @@ dict_accept( *success = FALSE; - while (isspace(*ptr)) { + while (my_isspace(cs, *ptr)) { ptr++; } @@ -2400,12 +2419,15 @@ const char* dict_scan_id( /*=========*/ /* out: scanned to */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scanned to */ mem_heap_t* heap, /* in: heap where to allocate the id (NULL=id will not be allocated, but it will point to string near ptr) */ const char** id, /* out,own: the id; NULL if no id was scannable */ + ibool table_id,/* in: TRUE=convert the allocated id + as a table name; FALSE=convert to UTF-8 */ ibool accept_also_dot) /* in: TRUE if also a dot can appear in a non-quoted id; in a quoted id it can appear @@ -2414,13 +2436,12 @@ dict_scan_id( char quote = '\0'; ulint len = 0; const char* s; - char* d; - ulint id_len; - byte* b; + char* str; + char* dst; *id = NULL; - while (isspace(*ptr)) { + while (my_isspace(cs, *ptr)) { ptr++; } @@ -2451,7 +2472,7 @@ dict_scan_id( len++; } } else { - while (!isspace(*ptr) && *ptr != '(' && *ptr != ')' + while (!my_isspace(cs, *ptr) && *ptr != '(' && *ptr != ')' && (accept_also_dot || *ptr != '.') && *ptr != ',' && *ptr != '\0') { @@ -2461,43 +2482,50 @@ dict_scan_id( len = ptr - s; } - if (quote && heap) { - *id = d = mem_heap_alloc(heap, len + 1); + if (UNIV_UNLIKELY(!heap)) { + /* no heap given: id will point to source string */ + *id = s; + return(ptr); + } + + if (quote) { + char* d; + str = d = mem_heap_alloc(heap, len + 1); while (len--) { if ((*d++ = *s++) == quote) { s++; } } *d++ = 0; - ut_a(*s == quote); - ut_a(s + 1 == ptr); - } else if (heap) { - *id = mem_heap_strdupl(heap, s, len); + len = d - str; + ut_ad(*s == quote); + ut_ad(s + 1 == ptr); } else { - /* no heap given: id will point to source string */ - *id = s; - } - - if (heap && !quote) { - /* EMS MySQL Manager sometimes adds characters 0xA0 (in - latin1, a 'non-breakable space') to the end of a table name. - But isspace(0xA0) is not true, which confuses our foreign key - parser. After the UTF-8 conversion in ha_innodb.cc, bytes 0xC2 - and 0xA0 are at the end of the string. - - TODO: we should lex the string using thd->charset_info, and - my_isspace(). Only after that, convert id names to UTF-8. */ - - b = (byte*)(*id); - id_len = strlen((char*) b); - - if (id_len >= 3 && b[id_len - 1] == 0xA0 - && b[id_len - 2] == 0xC2) { - - /* Strip the 2 last bytes */ + str = mem_heap_strdupl(heap, s, len); + } + + if (!table_id) { +convert_id: + /* Convert the identifier from connection character set + to UTF-8. */ + len = 3 * len + 1; + *id = dst = mem_heap_alloc(heap, len); + + innobase_convert_from_id(dst, str, len); + } else if (!strncmp(str, srv_mysql50_table_name_prefix, + sizeof srv_mysql50_table_name_prefix)) { + /* This is a pre-5.1 table name + containing chars other than [A-Za-z0-9]. + Discard the prefix and use raw UTF-8 encoding. */ + str += sizeof srv_mysql50_table_name_prefix; + len -= sizeof srv_mysql50_table_name_prefix; + goto convert_id; + } else { + /* Encode using filename-safe characters. */ + len = 5 * len + 1; + *id = dst = mem_heap_alloc(heap, len); - b[id_len - 2] = '\0'; - } + innobase_convert_from_table_id(dst, str, len); } return(ptr); @@ -2510,6 +2538,7 @@ const char* dict_scan_col( /*==========*/ /* out: scanned to */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scanned to */ ibool* success,/* out: TRUE if success */ dict_table_t* table, /* in: table in which the column is */ @@ -2518,13 +2547,12 @@ dict_scan_col( const char** name) /* out,own: the column name; NULL if no name was scannable */ { -#ifndef UNIV_HOTBACKUP dict_col_t* col; ulint i; *success = FALSE; - ptr = dict_scan_id(ptr, heap, name, TRUE); + ptr = dict_scan_id(cs, ptr, heap, name, FALSE, TRUE); if (*name == NULL) { @@ -2552,13 +2580,6 @@ dict_scan_col( } return(ptr); -#else /* UNIV_HOTBACKUP */ - /* This function depends on MySQL code that is not included in - InnoDB Hot Backup builds. Besides, this function should never - be called in InnoDB Hot Backup. */ - ut_error; - return(NULL); -#endif /* UNIV_HOTBACKUP */ } /************************************************************************* @@ -2568,6 +2589,7 @@ const char* dict_scan_table_name( /*=================*/ /* out: scanned to */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scanned to */ dict_table_t** table, /* out: table object or NULL */ const char* name, /* in: foreign key table name */ @@ -2576,7 +2598,6 @@ dict_scan_table_name( const char** ref_name)/* out,own: the table name; NULL if no name was scannable */ { -#ifndef UNIV_HOTBACKUP const char* database_name = NULL; ulint database_name_len = 0; const char* table_name = NULL; @@ -2587,7 +2608,7 @@ dict_scan_table_name( *success = FALSE; *table = NULL; - ptr = dict_scan_id(ptr, heap, &scan_name, FALSE); + ptr = dict_scan_id(cs, ptr, heap, &scan_name, TRUE, FALSE); if (scan_name == NULL) { @@ -2602,7 +2623,7 @@ dict_scan_table_name( database_name = scan_name; database_name_len = strlen(database_name); - ptr = dict_scan_id(ptr, heap, &table_name, FALSE); + ptr = dict_scan_id(cs, ptr, heap, &table_name, TRUE, FALSE); if (table_name == NULL) { @@ -2658,13 +2679,6 @@ dict_scan_table_name( *table = dict_table_get_low(ref); return(ptr); -#else /* UNIV_HOTBACKUP */ - /* This function depends on MySQL code that is not included in - InnoDB Hot Backup builds. Besides, this function should never - be called in InnoDB Hot Backup. */ - ut_error; - return(NULL); -#endif /* UNIV_HOTBACKUP */ } /************************************************************************* @@ -2674,6 +2688,7 @@ const char* dict_skip_word( /*===========*/ /* out: scanned to */ + struct charset_info_st* cs,/* in: the character set of ptr */ const char* ptr, /* in: scanned to */ ibool* success)/* out: TRUE if success, FALSE if just spaces left in string or a syntax error */ @@ -2682,7 +2697,7 @@ dict_skip_word( *success = FALSE; - ptr = dict_scan_id(ptr, NULL, &start, TRUE); + ptr = dict_scan_id(cs, ptr, NULL, &start, FALSE, TRUE); if (start) { *success = TRUE; @@ -2860,6 +2875,7 @@ dict_create_foreign_constraints_low( /* out: error code or DB_SUCCESS */ trx_t* trx, /* in: transaction */ mem_heap_t* heap, /* in: memory heap */ + struct charset_info_st* cs,/* in: the character set of sql_string */ const char* sql_string, /* in: CREATE TABLE or ALTER TABLE statement where foreign keys are declared like: @@ -2917,14 +2933,14 @@ dict_create_foreign_constraints_low( /* First check if we are actually doing an ALTER TABLE, and in that case look for the table being altered */ - ptr = dict_accept(ptr, "ALTER", &success); + ptr = dict_accept(cs, ptr, "ALTER", &success); if (!success) { goto loop; } - ptr = dict_accept(ptr, "TABLE", &success); + ptr = dict_accept(cs, ptr, "TABLE", &success); if (!success) { @@ -2933,7 +2949,7 @@ dict_create_foreign_constraints_low( /* We are doing an ALTER TABLE: scan the table name we are altering */ - ptr = dict_scan_table_name(ptr, &table_to_alter, name, + ptr = dict_scan_table_name(cs, ptr, &table_to_alter, name, &success, heap, &referenced_table_name); if (!success) { fprintf(stderr, @@ -2973,21 +2989,22 @@ loop: of the constraint to system tables. */ ptr = ptr1; - ptr = dict_accept(ptr, "CONSTRAINT", &success); + ptr = dict_accept(cs, ptr, "CONSTRAINT", &success); ut_a(success); - if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') { + if (!my_isspace(cs, *ptr) && *ptr != '"' && *ptr != '`') { goto loop; } - while (isspace(*ptr)) { + while (my_isspace(cs, *ptr)) { ptr++; } /* read constraint name unless got "CONSTRAINT FOREIGN" */ if (ptr != ptr2) { - ptr = dict_scan_id(ptr, heap, &constraint_name, FALSE); + ptr = dict_scan_id(cs, ptr, heap, + &constraint_name, FALSE, FALSE); } } else { ptr = ptr2; @@ -3002,7 +3019,8 @@ loop: if so, immediately reject the command if the table is a temporary one. For now, this kludge will work. */ if (reject_fks && (UT_LIST_GET_LEN(table->foreign_list) > 0)) { - return DB_CANNOT_ADD_CONSTRAINT; + + return(DB_CANNOT_ADD_CONSTRAINT); } /**********************************************************/ @@ -3016,28 +3034,28 @@ loop: start_of_latest_foreign = ptr; - ptr = dict_accept(ptr, "FOREIGN", &success); + ptr = dict_accept(cs, ptr, "FOREIGN", &success); if (!success) { goto loop; } - if (!isspace(*ptr)) { + if (!my_isspace(cs, *ptr)) { goto loop; } - ptr = dict_accept(ptr, "KEY", &success); + ptr = dict_accept(cs, ptr, "KEY", &success); if (!success) { goto loop; } - ptr = dict_accept(ptr, "(", &success); + ptr = dict_accept(cs, ptr, "(", &success); if (!success) { /* MySQL allows also an index id before the '('; we skip it */ - ptr = dict_skip_word(ptr, &success); + ptr = dict_skip_word(cs, ptr, &success); if (!success) { dict_foreign_report_syntax_err(name, @@ -3046,7 +3064,7 @@ loop: return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, "(", &success); + ptr = dict_accept(cs, ptr, "(", &success); if (!success) { /* We do not flag a syntax error here because in an @@ -3061,7 +3079,7 @@ loop: /* Scan the columns in the first list */ col_loop1: ut_a(i < (sizeof column_names) / sizeof *column_names); - ptr = dict_scan_col(ptr, &success, table, columns + i, + ptr = dict_scan_col(cs, ptr, &success, table, columns + i, heap, column_names + i); if (!success) { mutex_enter(&dict_foreign_err_mutex); @@ -3075,13 +3093,13 @@ col_loop1: i++; - ptr = dict_accept(ptr, ",", &success); + ptr = dict_accept(cs, ptr, ",", &success); if (success) { goto col_loop1; } - ptr = dict_accept(ptr, ")", &success); + ptr = dict_accept(cs, ptr, ")", &success); if (!success) { dict_foreign_report_syntax_err(name, start_of_latest_foreign, @@ -3098,7 +3116,7 @@ col_loop1: mutex_enter(&dict_foreign_err_mutex); dict_foreign_error_report_low(ef, name); fputs("There is no index in table ", ef); - ut_print_name(ef, NULL, name); + ut_print_name(ef, NULL, TRUE, name); fprintf(ef, " where the columns appear\n" "as the first columns. Constraint:\n%s\n" "See http://dev.mysql.com/doc/mysql/en/InnoDB_foreign_key_constraints.html\n" @@ -3108,9 +3126,9 @@ col_loop1: return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, "REFERENCES", &success); + ptr = dict_accept(cs, ptr, "REFERENCES", &success); - if (!success || !isspace(*ptr)) { + if (!success || !my_isspace(cs, *ptr)) { dict_foreign_report_syntax_err(name, start_of_latest_foreign, ptr); return(DB_CANNOT_ADD_CONSTRAINT); @@ -3150,7 +3168,7 @@ col_loop1: mem_heap_strdup(foreign->heap, columns[i]->name); } - ptr = dict_scan_table_name(ptr, &referenced_table, name, + ptr = dict_scan_table_name(cs, ptr, &referenced_table, name, &success, heap, &referenced_table_name); /* Note that referenced_table can be NULL if the user has suppressed @@ -3169,7 +3187,7 @@ col_loop1: return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, "(", &success); + ptr = dict_accept(cs, ptr, "(", &success); if (!success) { dict_foreign_free(foreign); @@ -3182,7 +3200,7 @@ col_loop1: i = 0; col_loop2: - ptr = dict_scan_col(ptr, &success, referenced_table, columns + i, + ptr = dict_scan_col(cs, ptr, &success, referenced_table, columns + i, heap, column_names + i); i++; @@ -3199,13 +3217,13 @@ col_loop2: return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, ",", &success); + ptr = dict_accept(cs, ptr, ",", &success); if (success) { goto col_loop2; } - ptr = dict_accept(ptr, ")", &success); + ptr = dict_accept(cs, ptr, ")", &success); if (!success || foreign->n_fields != i) { dict_foreign_free(foreign); @@ -3221,17 +3239,17 @@ col_loop2: scan_on_conditions: /* Loop here as long as we can find ON ... conditions */ - ptr = dict_accept(ptr, "ON", &success); + ptr = dict_accept(cs, ptr, "ON", &success); if (!success) { goto try_find_index; } - ptr = dict_accept(ptr, "DELETE", &success); + ptr = dict_accept(cs, ptr, "DELETE", &success); if (!success) { - ptr = dict_accept(ptr, "UPDATE", &success); + ptr = dict_accept(cs, ptr, "UPDATE", &success); if (!success) { dict_foreign_free(foreign); @@ -3248,13 +3266,13 @@ scan_on_conditions: n_on_deletes++; } - ptr = dict_accept(ptr, "RESTRICT", &success); + ptr = dict_accept(cs, ptr, "RESTRICT", &success); if (success) { goto scan_on_conditions; } - ptr = dict_accept(ptr, "CASCADE", &success); + ptr = dict_accept(cs, ptr, "CASCADE", &success); if (success) { if (is_on_delete) { @@ -3266,10 +3284,10 @@ scan_on_conditions: goto scan_on_conditions; } - ptr = dict_accept(ptr, "NO", &success); + ptr = dict_accept(cs, ptr, "NO", &success); if (success) { - ptr = dict_accept(ptr, "ACTION", &success); + ptr = dict_accept(cs, ptr, "ACTION", &success); if (!success) { dict_foreign_free(foreign); @@ -3288,7 +3306,7 @@ scan_on_conditions: goto scan_on_conditions; } - ptr = dict_accept(ptr, "SET", &success); + ptr = dict_accept(cs, ptr, "SET", &success); if (!success) { dict_foreign_free(foreign); @@ -3297,7 +3315,7 @@ scan_on_conditions: return(DB_CANNOT_ADD_CONSTRAINT); } - ptr = dict_accept(ptr, "NULL", &success); + ptr = dict_accept(cs, ptr, "NULL", &success); if (!success) { dict_foreign_free(foreign); @@ -3407,6 +3425,25 @@ try_find_index: goto loop; } +/************************************************************************** +Determines whether a string starts with the specified keyword. */ + +ibool +dict_str_starts_with_keyword( +/*=========================*/ + /* out: TRUE if str starts + with keyword */ + void* mysql_thd, /* in: MySQL thread handle */ + const char* str, /* in: string to scan for keyword */ + const char* keyword) /* in: keyword to look for */ +{ + struct charset_info_st* cs = innobase_get_charset(mysql_thd); + ibool success; + + dict_accept(cs, str, keyword, &success); + return(success); +} + /************************************************************************* Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function should be called after @@ -3434,15 +3471,18 @@ dict_create_foreign_constraints( code DB_CANNOT_ADD_CONSTRAINT if any foreign keys are found. */ { - char* str; - ulint err; - mem_heap_t* heap; + char* str; + ulint err; + mem_heap_t* heap; + + ut_a(trx && trx->mysql_thd); str = dict_strip_comments(sql_string); heap = mem_heap_create(10000); - err = dict_create_foreign_constraints_low(trx, heap, str, name, - reject_fks); + err = dict_create_foreign_constraints_low(trx, heap, + innobase_get_charset(trx->mysql_thd), + str, name, reject_fks); mem_heap_free(heap); mem_free(str); @@ -3469,12 +3509,17 @@ dict_foreign_parse_drop_constraints( const char*** constraints_to_drop) /* out: id's of the constraints to drop */ { - dict_foreign_t* foreign; - ibool success; - char* str; - const char* ptr; - const char* id; - FILE* ef = dict_foreign_err_file; + dict_foreign_t* foreign; + ibool success; + char* str; + const char* ptr; + const char* id; + FILE* ef = dict_foreign_err_file; + struct charset_info_st* cs; + + ut_a(trx && trx->mysql_thd); + + cs = innobase_get_charset(trx->mysql_thd); *n = 0; @@ -3495,28 +3540,28 @@ loop: return(DB_SUCCESS); } - ptr = dict_accept(ptr, "DROP", &success); + ptr = dict_accept(cs, ptr, "DROP", &success); - if (!isspace(*ptr)) { + if (!my_isspace(cs, *ptr)) { goto loop; } - ptr = dict_accept(ptr, "FOREIGN", &success); + ptr = dict_accept(cs, ptr, "FOREIGN", &success); if (!success) { goto loop; } - ptr = dict_accept(ptr, "KEY", &success); + ptr = dict_accept(cs, ptr, "KEY", &success); if (!success) { goto syntax_error; } - ptr = dict_scan_id(ptr, heap, &id, TRUE); + ptr = dict_scan_id(cs, ptr, heap, &id, FALSE, TRUE); if (id == NULL) { @@ -3549,12 +3594,12 @@ loop: ut_print_timestamp(ef); fputs( " Error in dropping of a foreign key constraint of table ", ef); - ut_print_name(ef, NULL, table->name); + ut_print_name(ef, NULL, TRUE, table->name); fputs(",\n" "in SQL command\n", ef); fputs(str, ef); fputs("\nCannot find a constraint with the given id ", ef); - ut_print_name(ef, NULL, id); + ut_print_name(ef, NULL, FALSE, id); fputs(".\n", ef); mutex_exit(&dict_foreign_err_mutex); @@ -3571,7 +3616,7 @@ syntax_error: ut_print_timestamp(ef); fputs( " Syntax error in dropping of a foreign key constraint of table ", ef); - ut_print_name(ef, NULL, table->name); + ut_print_name(ef, NULL, TRUE, table->name); fprintf(ef, ",\n" "close to:\n%s\n in SQL command\n%s\n", ptr, str); mutex_exit(&dict_foreign_err_mutex); @@ -3580,6 +3625,7 @@ syntax_error: return(DB_CANNOT_DROP_CONSTRAINT); } +#endif /* UNIV_HOTBACKUP */ /*==================== END OF FOREIGN KEY PROCESSING ====================*/ @@ -3653,9 +3699,7 @@ dict_tree_create( tree->magic_n = DICT_TREE_MAGIC_N; - rw_lock_create(&(tree->lock)); - - rw_lock_set_level(&(tree->lock), SYNC_INDEX_TREE); + rw_lock_create(&tree->lock, SYNC_INDEX_TREE); return(tree); } @@ -4232,11 +4276,11 @@ dict_print_info_on_foreign_key_in_create_format( } fputs(" CONSTRAINT ", file); - ut_print_name(file, trx, stripped_id); + ut_print_name(file, trx, FALSE, stripped_id); fputs(" FOREIGN KEY (", file); for (i = 0;;) { - ut_print_name(file, trx, foreign->foreign_col_names[i]); + ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]); if (++i < foreign->n_fields) { fputs(", ", file); } else { @@ -4249,7 +4293,7 @@ dict_print_info_on_foreign_key_in_create_format( if (dict_tables_have_same_db(foreign->foreign_table_name, foreign->referenced_table_name)) { /* Do not print the database name of the referenced table */ - ut_print_name(file, trx, dict_remove_db_name( + ut_print_name(file, trx, TRUE, dict_remove_db_name( foreign->referenced_table_name)); } else { /* Look for the '/' in the table name */ @@ -4259,9 +4303,10 @@ dict_print_info_on_foreign_key_in_create_format( i++; } - ut_print_namel(file, trx, foreign->referenced_table_name, i); + ut_print_namel(file, trx, TRUE, + foreign->referenced_table_name, i); putc('.', file); - ut_print_name(file, trx, + ut_print_name(file, trx, TRUE, foreign->referenced_table_name + i + 1); } @@ -4269,7 +4314,8 @@ dict_print_info_on_foreign_key_in_create_format( putc('(', file); for (i = 0;;) { - ut_print_name(file, trx, foreign->referenced_col_names[i]); + ut_print_name(file, trx, FALSE, + foreign->referenced_col_names[i]); if (++i < foreign->n_fields) { fputs(", ", file); } else { @@ -4343,12 +4389,12 @@ dict_print_info_on_foreign_keys( putc(' ', file); } - ut_print_name(file, trx, + ut_print_name(file, trx, FALSE, foreign->foreign_col_names[i]); } fputs(") REFER ", file); - ut_print_name(file, trx, + ut_print_name(file, trx, TRUE, foreign->referenced_table_name); putc('(', file); @@ -4356,7 +4402,7 @@ dict_print_info_on_foreign_keys( if (i) { putc(' ', file); } - ut_print_name(file, trx, + ut_print_name(file, trx, FALSE, foreign->referenced_col_names[i]); } @@ -4403,7 +4449,7 @@ dict_index_name_print( const dict_index_t* index) /* in: index to print */ { fputs("index ", file); - ut_print_name(file, trx, index->name); + ut_print_name(file, trx, FALSE, index->name); fputs(" of table ", file); - ut_print_name(file, trx, index->table_name); + ut_print_name(file, trx, TRUE, index->table_name); } diff --git a/storage/innobase/dict/dict0load.c b/storage/innobase/dict/dict0load.c index ccf4b47c284..58900d85f67 100644 --- a/storage/innobase/dict/dict0load.c +++ b/storage/innobase/dict/dict0load.c @@ -184,7 +184,7 @@ loop: if (table == NULL) { fputs("InnoDB: Failed to load table ", stderr); - ut_print_namel(stderr, NULL, (char*) field, len); + ut_print_namel(stderr, NULL, TRUE, (char*) field, len); putc('\n', stderr); } else { /* The table definition was corrupt if there diff --git a/storage/innobase/dict/dict0mem.c b/storage/innobase/dict/dict0mem.c index fe21890adc8..42bf39078d1 100644 --- a/storage/innobase/dict/dict0mem.c +++ b/storage/innobase/dict/dict0mem.c @@ -58,7 +58,6 @@ dict_mem_table_create( table->tablespace_discarded = FALSE; table->n_def = 0; table->n_cols = n_cols + DATA_N_SYS_COLS; - table->mem_fix = 0; table->n_mysql_handles_opened = 0; table->n_foreign_key_checks_running = 0; @@ -83,8 +82,9 @@ dict_mem_table_create( table->stat_modified_counter = 0; - mutex_create(&(table->autoinc_mutex)); - mutex_set_level(&(table->autoinc_mutex), SYNC_DICT_AUTOINC_MUTEX); + table->max_row_size = 0; + + mutex_create(&table->autoinc_mutex, SYNC_DICT_AUTOINC_MUTEX); table->autoinc_inited = FALSE; diff --git a/storage/innobase/fil/fil0fil.c b/storage/innobase/fil/fil0fil.c index 7418420628e..b2935a119a5 100644 --- a/storage/innobase/fil/fil0fil.c +++ b/storage/innobase/fil/fil0fil.c @@ -1050,8 +1050,7 @@ try_again: space->ibuf_data = NULL; - rw_lock_create(&(space->latch)); - rw_lock_set_level(&(space->latch), SYNC_FSP); + rw_lock_create(&space->latch, SYNC_FSP); HASH_INSERT(fil_space_t, hash, system->spaces, id, space); @@ -1295,9 +1294,7 @@ fil_system_create( system = mem_alloc(sizeof(fil_system_t)); - mutex_create(&(system->mutex)); - - mutex_set_level(&(system->mutex), SYNC_ANY_LATCH); + mutex_create(&system->mutex, SYNC_ANY_LATCH); system->spaces = hash_create(hash_size); system->name_hash = hash_create(hash_size); diff --git a/storage/innobase/ha/hash0hash.c b/storage/innobase/ha/hash0hash.c index 659aeb815d8..6084a19fa27 100644 --- a/storage/innobase/ha/hash0hash.c +++ b/storage/innobase/ha/hash0hash.c @@ -144,9 +144,7 @@ hash_create_mutexes( table->mutexes = mem_alloc(n_mutexes * sizeof(mutex_t)); for (i = 0; i < n_mutexes; i++) { - mutex_create(table->mutexes + i); - - mutex_set_level(table->mutexes + i, sync_level); + mutex_create(table->mutexes + i, sync_level); } table->n_mutexes = n_mutexes; diff --git a/storage/innobase/ibuf/ibuf0ibuf.c b/storage/innobase/ibuf/ibuf0ibuf.c index 3263a0efd5b..369fbd61c04 100644 --- a/storage/innobase/ibuf/ibuf0ibuf.c +++ b/storage/innobase/ibuf/ibuf0ibuf.c @@ -144,6 +144,7 @@ static ulint ibuf_rnd = 986058871; ulint ibuf_flush_count = 0; +#ifdef UNIV_IBUF_DEBUG /* Dimensions for the ibuf_count array */ #define IBUF_COUNT_N_SPACES 500 #define IBUF_COUNT_N_PAGES 2000 @@ -152,6 +153,7 @@ ulint ibuf_flush_count = 0; static ulint* ibuf_counts[IBUF_COUNT_N_SPACES]; static ibool ibuf_counts_inited = FALSE; +#endif /* The start address for an insert buffer bitmap page bitmap */ #define IBUF_BITMAP PAGE_DATA @@ -314,6 +316,7 @@ ibuf_tree_root_get( return(page); } +#ifdef UNIV_IBUF_DEBUG /********************************************************************** Gets the ibuf count for a given page. */ @@ -338,7 +341,6 @@ ibuf_count_get( /********************************************************************** Sets the ibuf count for a given page. */ -#ifdef UNIV_IBUF_DEBUG static void ibuf_count_set( @@ -389,23 +391,18 @@ ibuf_init_at_db_start(void) ibuf_count_set(i, j, 0); } } + + ibuf_counts_inited = TRUE; } #endif - mutex_create(&ibuf_pessimistic_insert_mutex); - - mutex_set_level(&ibuf_pessimistic_insert_mutex, - SYNC_IBUF_PESS_INSERT_MUTEX); - mutex_create(&ibuf_mutex); + mutex_create(&ibuf_pessimistic_insert_mutex, + SYNC_IBUF_PESS_INSERT_MUTEX); - mutex_set_level(&ibuf_mutex, SYNC_IBUF_MUTEX); + mutex_create(&ibuf_mutex, SYNC_IBUF_MUTEX); - mutex_create(&ibuf_bitmap_mutex); - - mutex_set_level(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX); + mutex_create(&ibuf_bitmap_mutex, SYNC_IBUF_BITMAP_MUTEX); fil_ibuf_init_at_db_start(); - - ibuf_counts_inited = TRUE; } /********************************************************************** @@ -2348,6 +2345,10 @@ ibuf_get_volume_buffered( } prev_page = buf_page_get(0, prev_page_no, RW_X_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_next(prev_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(prev_page, SYNC_TREE_NODE); @@ -2411,6 +2412,10 @@ count_later: } next_page = buf_page_get(0, next_page_no, RW_X_LATCH, mtr); +#ifdef UNIV_BTR_DEBUG + ut_a(btr_page_get_prev(next_page, mtr) + == buf_frame_get_page_no(page)); +#endif /* UNIV_BTR_DEBUG */ #ifdef UNIV_SYNC_DEBUG buf_page_dbg_add_level(next_page, SYNC_TREE_NODE); diff --git a/storage/innobase/include/data0type.h b/storage/innobase/include/data0type.h index d7c9dcb45a2..789b76b1498 100644 --- a/storage/innobase/include/data0type.h +++ b/storage/innobase/include/data0type.h @@ -330,6 +330,15 @@ dtype_get_min_size( /* out: minimum size */ const dtype_t* type); /* in: type */ /*************************************************************************** +Returns the maximum size of a data type. Note: types in system tables may be +incomplete and return incorrect information. */ +ulint +dtype_get_max_size( +/*===============*/ + /* out: maximum size (ULINT_MAX for + unbounded types) */ + const dtype_t* type); /* in: type */ +/*************************************************************************** Returns a stored SQL NULL size for a type. For fixed length types it is the fixed length of the type, otherwise 0. */ UNIV_INLINE diff --git a/storage/innobase/include/dict0dict.h b/storage/innobase/include/dict0dict.h index 39cde5bfb55..c27ff715986 100644 --- a/storage/innobase/include/dict0dict.h +++ b/storage/innobase/include/dict0dict.h @@ -44,18 +44,6 @@ dict_get_db_name_len( /* out: database name length */ const char* name); /* in: table name in the form dbname '/' tablename */ -/************************************************************************* -Accepts a specified string. Comparisons are case-insensitive. */ - -const char* -dict_accept( -/*========*/ - /* out: if string was accepted, the pointer - is moved after that, else ptr is returned */ - const char* ptr, /* in: scan from this */ - const char* string, /* in: accept only this string as the next - non-whitespace string */ - ibool* success);/* out: TRUE if accepted */ /************************************************************************ Decrements the count of open MySQL handles to a table. */ @@ -219,6 +207,17 @@ dict_table_referenced_by_foreign_key( /* out: TRUE if table is referenced by a foreign key */ dict_table_t* table); /* in: InnoDB table */ +/************************************************************************** +Determines whether a string starts with the specified keyword. */ + +ibool +dict_str_starts_with_keyword( +/*=========================*/ + /* out: TRUE if str starts + with keyword */ + void* mysql_thd, /* in: MySQL thread handle */ + const char* str, /* in: string to scan for keyword */ + const char* keyword); /* in: keyword to look for */ /************************************************************************* Scans a table create SQL string and adds to the data dictionary the foreign key constraints declared in the string. This function @@ -265,17 +264,16 @@ dict_foreign_parse_drop_constraints( const char*** constraints_to_drop); /* out: id's of the constraints to drop */ /************************************************************************** -Returns a table object and memoryfixes it. NOTE! This is a high-level -function to be used mainly from outside the 'dict' directory. Inside this -directory dict_table_get_low is usually the appropriate function. */ +Returns a table object. NOTE! This is a high-level function to be used +mainly from outside the 'dict' directory. Inside this directory +dict_table_get_low is usually the appropriate function. */ dict_table_t* dict_table_get( /*===========*/ /* out: table, NULL if does not exist */ - const char* table_name, /* in: table name */ - trx_t* trx); /* in: transaction handle */ + const char* table_name); /* in: table name */ /************************************************************************** Returns a table object and increments MySQL open handle count on the table. */ @@ -285,10 +283,9 @@ dict_table_get_and_increment_handle_count( /*======================================*/ /* out: table, NULL if does not exist */ - const char* table_name, /* in: table name */ - trx_t* trx); /* in: transaction handle or NULL */ + const char* table_name); /* in: table name */ /************************************************************************** -Returns a table object, based on table id, and memoryfixes it. */ +Returns a table object based on table id. */ dict_table_t* dict_table_get_on_id( @@ -297,21 +294,13 @@ dict_table_get_on_id( dulint table_id, /* in: table id */ trx_t* trx); /* in: transaction handle */ /************************************************************************** -Returns a table object, based on table id, and memoryfixes it. */ +Returns a table object based on table id. */ UNIV_INLINE dict_table_t* dict_table_get_on_id_low( /*=====================*/ /* out: table, NULL if does not exist */ - dulint table_id, /* in: table id */ - trx_t* trx); /* in: transaction handle */ -/************************************************************************** -Releases a table from being memoryfixed. Currently this has no relevance. */ -UNIV_INLINE -void -dict_table_release( -/*===============*/ - dict_table_t* table); /* in: table to be released */ + dulint table_id); /* in: table id */ /************************************************************************** Checks if a table is in the dictionary cache. */ UNIV_INLINE diff --git a/storage/innobase/include/dict0dict.ic b/storage/innobase/include/dict0dict.ic index 0b5a23e9380..c65fdde81e9 100644 --- a/storage/innobase/include/dict0dict.ic +++ b/storage/innobase/include/dict0dict.ic @@ -545,14 +545,13 @@ dict_table_get_low( } /************************************************************************** -Returns a table object, based on table id, and memoryfixes it. */ +Returns a table object based on table id. */ UNIV_INLINE dict_table_t* dict_table_get_on_id_low( /*=====================*/ /* out: table, NULL if does not exist */ - dulint table_id, /* in: table id */ - trx_t* trx) /* in: transaction handle */ + dulint table_id) /* in: table id */ { dict_table_t* table; ulint fold; @@ -560,7 +559,6 @@ dict_table_get_on_id_low( #ifdef UNIV_SYNC_DEBUG ut_ad(mutex_own(&(dict_sys->mutex))); #endif /* UNIV_SYNC_DEBUG */ - UT_NOT_USED(trx); /* Look for the table name in the hash table */ fold = ut_fold_dulint(table_id); @@ -571,33 +569,12 @@ dict_table_get_on_id_low( table = dict_load_table_on_id(table_id); } - if (table != NULL) { - table->mem_fix++; - - /* lock_push(trx, table, LOCK_DICT_MEM_FIX) */ - } - /* TODO: should get the type information from MySQL */ return(table); } /************************************************************************** -Releases a table from being memoryfixed. Currently this has no relevance. */ -UNIV_INLINE -void -dict_table_release( -/*===============*/ - dict_table_t* table) /* in: table to be released */ -{ - mutex_enter(&(dict_sys->mutex)); - - table->mem_fix--; - - mutex_exit(&(dict_sys->mutex)); -} - -/************************************************************************** Returns an index object. */ UNIV_INLINE dict_index_t* diff --git a/storage/innobase/include/dict0mem.h b/storage/innobase/include/dict0mem.h index 0135ba3874d..427991180f6 100644 --- a/storage/innobase/include/dict0mem.h +++ b/storage/innobase/include/dict0mem.h @@ -169,10 +169,6 @@ struct dict_tree_struct{ the same memory cache line */ rw_lock_t lock; /* read-write lock protecting the upper levels of the index tree */ - ulint mem_fix;/* count of how many times this tree - struct has been memoryfixed (by mini- - transactions wanting to access the index - tree) */ dict_index_t* tree_index; /* the index stored in the index tree */ ulint magic_n;/* magic number */ @@ -315,9 +311,6 @@ struct dict_table_struct{ which refer to this table */ UT_LIST_NODE_T(dict_table_t) table_LRU; /* node of the LRU list of tables */ - ulint mem_fix;/* count of how many times the table - and its indexes has been fixed in memory; - currently NOT used */ ulint n_mysql_handles_opened; /* count of how many handles MySQL has opened to this table; dropping of the table is @@ -348,6 +341,12 @@ struct dict_table_struct{ had an IX lock on */ UT_LIST_BASE_NODE_T(lock_t) locks; /* list of locks on the table */ + ulint max_row_size; + /* maximum size of a single row in the + table, not guaranteed to be especially + accurate. it's ULINT_MAX if there are + unbounded variable-width fields. initialized + in dict_table_add_to_cache. */ /*----------------------*/ ibool does_not_fit_in_memory; /* this field is used to specify in simulations diff --git a/storage/innobase/include/fil0fil.h b/storage/innobase/include/fil0fil.h index 53bb496c190..6b8fd4b03d5 100644 --- a/storage/innobase/include/fil0fil.h +++ b/storage/innobase/include/fil0fil.h @@ -57,9 +57,21 @@ extern fil_addr_t fil_addr_null; page */ #define FIL_PAGE_OFFSET 4 /* page offset inside space */ #define FIL_PAGE_PREV 8 /* if there is a 'natural' predecessor - of the page, its offset */ + of the page, its offset. + Otherwise FIL_NULL. + This field is not set on BLOB pages, + which are stored as a singly-linked + list. See also FIL_PAGE_NEXT. */ #define FIL_PAGE_NEXT 12 /* if there is a 'natural' successor - of the page, its offset */ + of the page, its offset. + Otherwise FIL_NULL. + B-tree index pages + (FIL_PAGE_TYPE contains FIL_PAGE_INDEX) + on the same PAGE_LEVEL are maintained + as a doubly linked list via + FIL_PAGE_PREV and FIL_PAGE_NEXT + in the collation order of the + smallest user record on each page. */ #define FIL_PAGE_LSN 16 /* lsn of the end of the newest modification log record to the page */ #define FIL_PAGE_TYPE 24 /* file page type: FIL_PAGE_INDEX,..., diff --git a/storage/innobase/include/fsp0fsp.h b/storage/innobase/include/fsp0fsp.h index 11b664b6826..d04269fc157 100644 --- a/storage/innobase/include/fsp0fsp.h +++ b/storage/innobase/include/fsp0fsp.h @@ -360,24 +360,28 @@ description takes less than 1 byte; a descriptor page is repeated every this many file pages */ #define XDES_DESCRIBED_PER_PAGE UNIV_PAGE_SIZE -/* The space low address page map, and also offsets for extent descriptor and -bitmap pages which are repeated always after XDES_DESCRIBED_PER_PAGE more -pages: */ +/* The space low address page map */ /*--------------------------------------*/ -#define FSP_XDES_OFFSET 0 -#define FSP_IBUF_BITMAP_OFFSET 1 + /* The following two pages are repeated + every XDES_DESCRIBED_PER_PAGE pages in + every tablespace. */ +#define FSP_XDES_OFFSET 0 /* extent descriptor */ +#define FSP_IBUF_BITMAP_OFFSET 1 /* insert buffer bitmap */ /* The ibuf bitmap pages are the ones whose page number is the number above plus a multiple of XDES_DESCRIBED_PER_PAGE */ -#define FSP_FIRST_INODE_PAGE_NO 2 -#define FSP_IBUF_HEADER_PAGE_NO 3 -#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 + +#define FSP_FIRST_INODE_PAGE_NO 2 /* in every tablespace */ + /* The following pages exist + in the system tablespace (space 0). */ +#define FSP_IBUF_HEADER_PAGE_NO 3 /* in tablespace 0 */ +#define FSP_IBUF_TREE_ROOT_PAGE_NO 4 /* in tablespace 0 */ /* The ibuf tree root page number in tablespace 0; its fseg inode is on the page number FSP_FIRST_INODE_PAGE_NO */ -#define FSP_TRX_SYS_PAGE_NO 5 -#define FSP_FIRST_RSEG_PAGE_NO 6 -#define FSP_DICT_HDR_PAGE_NO 7 +#define FSP_TRX_SYS_PAGE_NO 5 /* in tablespace 0 */ +#define FSP_FIRST_RSEG_PAGE_NO 6 /* in tablespace 0 */ +#define FSP_DICT_HDR_PAGE_NO 7 /* in tablespace 0 */ /*--------------------------------------*/ #ifndef UNIV_NONINL diff --git a/storage/innobase/include/ha_prototypes.h b/storage/innobase/include/ha_prototypes.h new file mode 100644 index 00000000000..2d27034fdfe --- /dev/null +++ b/storage/innobase/include/ha_prototypes.h @@ -0,0 +1,22 @@ +#ifndef HA_INNODB_PROTOTYPES_H +#define HA_INNODB_PROTOTYPES_H + +/* Prototypes for global functions in ha_innodb.cc that are called by +InnoDB's C-code. */ + +/************************************************************************* +Wrapper around MySQL's copy_and_convert function, see it for +documentation. */ + +ulint +innobase_convert_string( +/*====================*/ + void* to, + ulint to_length, + CHARSET_INFO* to_cs, + const void* from, + ulint from_length, + CHARSET_INFO* from_cs, + uint* errors); + +#endif diff --git a/storage/innobase/include/ibuf0ibuf.h b/storage/innobase/include/ibuf0ibuf.h index 34f29ae5dec..77fefe2020b 100644 --- a/storage/innobase/include/ibuf0ibuf.h +++ b/storage/innobase/include/ibuf0ibuf.h @@ -267,6 +267,7 @@ ibuf_parse_bitmap_init( byte* end_ptr,/* in: buffer end */ page_t* page, /* in: page or NULL */ mtr_t* mtr); /* in: mtr or NULL */ +#ifdef UNIV_IBUF_DEBUG /********************************************************************** Gets the ibuf count for a given page. */ @@ -277,6 +278,7 @@ ibuf_count_get( currently buffered for this page */ ulint space, /* in: space id */ ulint page_no);/* in: page number */ +#endif /********************************************************************** Looks if the insert buffer is empty. */ diff --git a/storage/innobase/include/mem0mem.h b/storage/innobase/include/mem0mem.h index f9342e962f2..f68d45d83df 100644 --- a/storage/innobase/include/mem0mem.h +++ b/storage/innobase/include/mem0mem.h @@ -297,8 +297,8 @@ char* mem_heap_strdup( /*============*/ /* out, own: a copy of the string */ - mem_heap_t* heap, /* in: memory heap where string is allocated */ - const char* str); /* in: string to be copied */ + mem_heap_t* heap, /* in: memory heap where string is allocated */ + const char* str); /* in: string to be copied */ /************************************************************************** Makes a NUL-terminated copy of a nonterminated string, allocated from a memory heap. */ @@ -322,6 +322,44 @@ mem_heap_strcat( const char* s1, /* in: string 1 */ const char* s2); /* in: string 2 */ +/************************************************************************** +Duplicate a block of data, allocated from a memory heap. */ + +void* +mem_heap_dup( +/*=========*/ + /* out, own: a copy of the data */ + mem_heap_t* heap, /* in: memory heap where copy is allocated */ + const void* data, /* in: data to be copied */ + ulint len); /* in: length of data, in bytes */ + +/************************************************************************** +Concatenate two memory blocks and return the result, using a memory heap. */ + +void* +mem_heap_cat( +/*=========*/ + /* out, own: the result */ + mem_heap_t* heap, /* in: memory heap where result is allocated */ + const void* b1, /* in: block 1 */ + ulint len1, /* in: length of b1, in bytes */ + const void* b2, /* in: block 2 */ + ulint len2); /* in: length of b2, in bytes */ + +/******************************************************************** +A simple (s)printf replacement that dynamically allocates the space for the +formatted string from the given heap. This supports a very limited set of +the printf syntax: types 's' and 'u' and length modifier 'l' (which is +required for the 'u' type). */ + +char* +mem_heap_printf( +/*============*/ + /* out: heap-allocated formatted string */ + mem_heap_t* heap, /* in: memory heap */ + const char* format, /* in: format string */ + ...) __attribute__ ((format (printf, 2, 3))); + #ifdef MEM_PERIODIC_CHECK /********************************************************************** Goes through the list of all allocated mem blocks, checks their magic diff --git a/storage/innobase/include/pars0pars.h b/storage/innobase/include/pars0pars.h index 68b8ae41cc0..b3140008a3c 100644 --- a/storage/innobase/include/pars0pars.h +++ b/storage/innobase/include/pars0pars.h @@ -532,6 +532,16 @@ pars_info_add_function( void* arg); /* in: user-supplied argument */ /******************************************************************** +Add bound id. */ + +void +pars_info_add_id( +/*=============*/ + pars_info_t* info, /* in: info struct */ + const char* name, /* in: name */ + const char* id); /* in: id */ + +/******************************************************************** Get user function with the given name.*/ pars_user_func_t* @@ -553,6 +563,17 @@ pars_info_get_bound_lit( pars_info_t* info, /* in: info struct */ const char* name); /* in: bound literal name to find */ +/******************************************************************** +Get bound id with the given name.*/ + +pars_bound_id_t* +pars_info_get_bound_id( +/*===================*/ + /* out: bound id, or NULL if not + found */ + pars_info_t* info, /* in: info struct */ + const char* name); /* in: bound id name to find */ + /* Extra information supplied for pars_sql(). */ struct pars_info_struct { @@ -562,6 +583,8 @@ struct pars_info_struct { (pars_user_func_t*) */ ib_vector_t* bound_lits; /* bound literals, or NULL (pars_bound_lit_t*) */ + ib_vector_t* bound_ids; /* bound ids, or NULL + (pars_bound_id_t*) */ ibool graph_owns_us; /* if TRUE (which is the default), que_graph_free() will free us */ @@ -583,6 +606,12 @@ struct pars_bound_lit_struct { ulint prtype; /* precise type, e.g. DATA_UNSIGNED */ }; +/* Bound id. */ +struct pars_bound_id_struct { + const char* name; /* name */ + const char* id; /* id */ +}; + /* Struct used to denote a reserved word in a parsing tree */ struct pars_res_word_struct{ int code; /* the token code for the reserved word from diff --git a/storage/innobase/include/pars0sym.h b/storage/innobase/include/pars0sym.h index 14f762d5b7a..fc7df92ff60 100644 --- a/storage/innobase/include/pars0sym.h +++ b/storage/innobase/include/pars0sym.h @@ -82,6 +82,16 @@ sym_tab_add_id( byte* name, /* in: identifier name */ ulint len); /* in: identifier length */ +/********************************************************************** +Add a bound identifier to a symbol table. */ + +sym_node_t* +sym_tab_add_bound_id( +/*===========*/ + /* out: symbol table node */ + sym_tab_t* sym_tab, /* in: symbol table */ + const char* name); /* in: name of bound id */ + #define SYM_CLUST_FIELD_NO 0 #define SYM_SEC_FIELD_NO 1 diff --git a/storage/innobase/include/pars0types.h b/storage/innobase/include/pars0types.h index 6fcfaf23024..bf7df89a883 100644 --- a/storage/innobase/include/pars0types.h +++ b/storage/innobase/include/pars0types.h @@ -12,6 +12,7 @@ Created 1/11/1998 Heikki Tuuri typedef struct pars_info_struct pars_info_t; typedef struct pars_user_func_struct pars_user_func_t; typedef struct pars_bound_lit_struct pars_bound_lit_t; +typedef struct pars_bound_id_struct pars_bound_id_t; typedef struct sym_node_struct sym_node_t; typedef struct sym_tab_struct sym_tab_t; typedef struct pars_res_word_struct pars_res_word_t; diff --git a/storage/innobase/include/rem0rec.h b/storage/innobase/include/rem0rec.h index b2f3b9d141b..af11198d001 100644 --- a/storage/innobase/include/rem0rec.h +++ b/storage/innobase/include/rem0rec.h @@ -19,8 +19,10 @@ Created 5/30/1994 Heikki Tuuri #define REC_MAX_HEAP_NO (2 * 8192 - 1) #define REC_MAX_N_OWNED (16 - 1) -/* Flag denoting the predefined minimum record: this bit is ORed in the 4 -info bits of a record */ +/* Info bit denoting the predefined minimum record: this bit is set +if and only if the record is the first user record on a non-leaf +B-tree page that is the leftmost page on its level +(PAGE_LEVEL is nonzero and FIL_PAGE_PREV is FIL_NULL). */ #define REC_INFO_MIN_REC_FLAG 0x10UL /* Number of extra bytes in an old-style record, diff --git a/storage/innobase/include/row0purge.h b/storage/innobase/include/row0purge.h index 52dd2fce551..2653f8a354d 100644 --- a/storage/innobase/include/row0purge.h +++ b/storage/innobase/include/row0purge.h @@ -56,9 +56,7 @@ struct purge_node_struct{ determined by ref was found in the clustered index, and we were able to position pcur on it */ - dict_table_t* table; /* table where purge is done; NOTE that the - table has to be released explicitly with - dict_table_release */ + dict_table_t* table; /* table where purge is done */ ulint cmpl_info;/* compiler analysis info of an update */ upd_t* update; /* update vector for a clustered index record */ dtuple_t* ref; /* NULL, or row reference to the next row to diff --git a/storage/innobase/include/row0undo.h b/storage/innobase/include/row0undo.h index 5e3f514ad8d..29cfbc9ac20 100644 --- a/storage/innobase/include/row0undo.h +++ b/storage/innobase/include/row0undo.h @@ -84,9 +84,7 @@ struct undo_node_struct{ record */ btr_pcur_t pcur; /* persistent cursor used in searching the clustered index record */ - dict_table_t* table; /* table where undo is done; NOTE that the - table has to be released explicitly with - dict_table_release */ + dict_table_t* table; /* table where undo is done */ ulint cmpl_info;/* compiler analysis of an update */ upd_t* update; /* update vector for a clustered index record */ dtuple_t* ref; /* row reference to the next row to handle */ diff --git a/storage/innobase/include/srv0srv.h b/storage/innobase/include/srv0srv.h index ff82cb2999a..dc1f2d96d9d 100644 --- a/storage/innobase/include/srv0srv.h +++ b/storage/innobase/include/srv0srv.h @@ -18,6 +18,9 @@ Created 10/10/1995 Heikki Tuuri extern const char* srv_main_thread_op_info; +/* Prefix used by MySQL to indicate pre-5.1 table name encoding */ +extern const char srv_mysql50_table_name_prefix[9]; + /* When this event is set the lock timeout and InnoDB monitor thread starts running */ extern os_event_t srv_lock_timeout_thread_event; diff --git a/storage/innobase/include/sync0rw.h b/storage/innobase/include/sync0rw.h index e6ca3258099..616d3eeb978 100644 --- a/storage/innobase/include/sync0rw.h +++ b/storage/innobase/include/sync0rw.h @@ -61,7 +61,7 @@ Creates, or rather, initializes an rw-lock object in a specified memory location (which must be appropriately aligned). The rw-lock is initialized to the non-locked state. Explicit freeing of the rw-lock with rw_lock_free is necessary only if the memory block containing it is freed. */ -#define rw_lock_create(L) rw_lock_create_func((L), __FILE__, __LINE__, #L) +#define rw_lock_create(L, level) rw_lock_create_func((L), (level), __FILE__, __LINE__, #L) /*=====================*/ /********************************************************************** @@ -74,9 +74,10 @@ void rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ + ulint level, /* in: level */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name); /* in: mutex name */ + ulint cline, /* in: file line where created */ + const char* cmutex_name); /* in: mutex name */ /********************************************************************** Calling this function is obligatory only if the memory buffer containing the rw-lock is freed. Removes an rw-lock object from the global list. The @@ -299,14 +300,6 @@ rw_lock_x_unlock_direct( /*====================*/ rw_lock_t* lock); /* in: rw-lock */ /********************************************************************** -Sets the rw-lock latching level field. */ - -void -rw_lock_set_level( -/*==============*/ - rw_lock_t* lock, /* in: rw-lock */ - ulint level); /* in: level */ -/********************************************************************** Returns the value of writer_count for the lock. Does not reserve the lock mutex, so the caller must be sure it is not changed during the call. */ UNIV_INLINE @@ -448,8 +441,8 @@ struct rw_lock_struct { /* In the debug version: pointer to the debug info list of the lock */ #endif /* UNIV_SYNC_DEBUG */ - ulint level; /* Level in the global latching - order; default SYNC_LEVEL_NONE */ + + ulint level; /* Level in the global latching order. */ const char* cfile_name;/* File name where lock created */ ulint cline; /* Line where created */ const char* last_s_file_name;/* File name where last s-locked */ diff --git a/storage/innobase/include/sync0sync.h b/storage/innobase/include/sync0sync.h index 0a233843b50..64b245246f8 100644 --- a/storage/innobase/include/sync0sync.h +++ b/storage/innobase/include/sync0sync.h @@ -39,7 +39,7 @@ location (which must be appropriately aligned). The mutex is initialized in the reset state. Explicit freeing of the mutex with mutex_free is necessary only if the memory block containing it is freed. */ -#define mutex_create(M) mutex_create_func((M), __FILE__, __LINE__, #M) +#define mutex_create(M, level) mutex_create_func((M), (level), __FILE__, __LINE__, #M) /*===================*/ /********************************************************************** Creates, or rather, initializes a mutex object in a specified memory @@ -51,6 +51,7 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ + ulint level, /* in: level */ const char* cfile_name, /* in: file name where created */ ulint cline, /* in: file line where created */ const char* cmutex_name); /* in: mutex name */ @@ -155,14 +156,6 @@ mutex_validate( /*===========*/ mutex_t* mutex); /********************************************************************** -Sets the mutex latching level field. */ - -void -mutex_set_level( -/*============*/ - mutex_t* mutex, /* in: mutex */ - ulint level); /* in: level */ -/********************************************************************** Adds a latch and its level in the thread level array. Allocates the memory for the array if called first time for this OS thread. Makes the checks against other latch levels stored in the array for this thread. */ @@ -171,8 +164,8 @@ void sync_thread_add_level( /*==================*/ void* latch, /* in: pointer to a mutex or an rw-lock */ - ulint level); /* in: level in the latching order; if SYNC_LEVEL_NONE, - nothing is done */ + ulint level); /* in: level in the latching order; if + SYNC_LEVEL_VARYING, nothing is done */ /********************************************************************** Removes a latch from the thread level array if it is found there. */ @@ -383,7 +376,12 @@ or row lock! */ #define SYNC_USER_TRX_LOCK 9999 #define SYNC_NO_ORDER_CHECK 3000 /* this can be used to suppress latching order checking */ -#define SYNC_LEVEL_NONE 2000 /* default: level not defined */ +#define SYNC_LEVEL_VARYING 2000 /* Level is varying. Only used with + buffer pool page locks, which do not + have a fixed level, but instead have + their level set after the page is + locked; see e.g. + ibuf_bitmap_get_map_page(). */ #define SYNC_DICT_OPERATION 1001 /* table create, drop, etc. reserve this in X-mode, implicit or backround operations purge, rollback, foreign @@ -426,6 +424,7 @@ or row lock! */ #define SYNC_TRX_SYS_HEADER 290 #define SYNC_LOG 170 #define SYNC_RECV 168 +#define SYNC_WORK_QUEUE 161 #define SYNC_SEARCH_SYS 160 /* NOTE that if we have a memory heap that can be extended to the buffer pool, its logical level is @@ -472,8 +471,7 @@ struct mutex_struct { os_thread_id_t thread_id; /* Debug version: The thread id of the thread which locked the mutex. */ #endif /* UNIV_SYNC_DEBUG */ - ulint level; /* Level in the global latching - order; default SYNC_LEVEL_NONE */ + ulint level; /* Level in the global latching order */ const char* cfile_name;/* File name where mutex created */ ulint cline; /* Line where created */ ulint magic_n; diff --git a/storage/innobase/include/univ.i b/storage/innobase/include/univ.i index c5e87e468c6..f2dafbc3a70 100644 --- a/storage/innobase/include/univ.i +++ b/storage/innobase/include/univ.i @@ -82,7 +82,7 @@ memory is read outside the allocated blocks. */ /* Make a non-inline debug version */ -/* +#if 0 #define UNIV_DEBUG #define UNIV_MEM_DEBUG #define UNIV_IBUF_DEBUG @@ -90,8 +90,10 @@ memory is read outside the allocated blocks. */ #define UNIV_SEARCH_DEBUG #define UNIV_SYNC_PERF_STAT #define UNIV_SEARCH_PERF_STAT -#define UNIV_SRV_PRINT_LATCH_WAITS; -*/ +#define UNIV_SRV_PRINT_LATCH_WAITS +#endif + +#define UNIV_BTR_DEBUG #define UNIV_LIGHT_MEM_DEBUG #define YYDEBUG 1 diff --git a/storage/innobase/include/ut0dbg.h b/storage/innobase/include/ut0dbg.h index 55e8c8ef88c..a317f35f4be 100644 --- a/storage/innobase/include/ut0dbg.h +++ b/storage/innobase/include/ut0dbg.h @@ -41,12 +41,21 @@ void ut_dbg_panic(void); /* Stop threads in ut_a(). */ # define UT_DBG_STOP while (0) /* We do not do this on NetWare */ #else /* __NETWARE__ */ -/* Flag for indicating that all threads should stop. This will be set -by ut_dbg_assertion_failed(). */ -extern ibool ut_dbg_stop_threads; +# if defined(__WIN__) || defined(__INTEL_COMPILER) +# undef UT_DBG_USE_ABORT +# elif defined(__GNUC__) && (__GNUC__ > 2) +# define UT_DBG_USE_ABORT +# endif +# ifndef UT_DBG_USE_ABORT /* A null pointer that will be dereferenced to trigger a memory trap */ extern ulint* ut_dbg_null_ptr; +# endif + +# if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) +/* Flag for indicating that all threads should stop. This will be set +by ut_dbg_assertion_failed(). */ +extern ibool ut_dbg_stop_threads; /***************************************************************** Stop a thread after assertion failure. */ @@ -56,15 +65,23 @@ ut_dbg_stop_thread( /*===============*/ const char* file, ulint line); +# endif +# ifdef UT_DBG_USE_ABORT +/* Abort the execution. */ +# define UT_DBG_PANIC abort() +/* Stop threads (null operation) */ +# define UT_DBG_STOP while (0) +# else /* UT_DBG_USE_ABORT */ /* Abort the execution. */ -# define UT_DBG_PANIC \ +# define UT_DBG_PANIC \ if (*(ut_dbg_null_ptr)) ut_dbg_null_ptr = NULL /* Stop threads in ut_a(). */ -# define UT_DBG_STOP do \ +# define UT_DBG_STOP do \ if (UNIV_UNLIKELY(ut_dbg_stop_threads)) { \ ut_dbg_stop_thread(__FILE__, (ulint) __LINE__); \ } while (0) +# endif /* UT_DBG_USE_ABORT */ #endif /* __NETWARE__ */ /* Abort execution if EXPR does not evaluate to nonzero. */ diff --git a/storage/innobase/include/ut0list.h b/storage/innobase/include/ut0list.h new file mode 100644 index 00000000000..c35cf202600 --- /dev/null +++ b/storage/innobase/include/ut0list.h @@ -0,0 +1,148 @@ +/*********************************************************************** +A double-linked list. This differs from the one in ut0lst.h in that in this +one, each list node contains a pointer to the data, whereas the one in +ut0lst.h uses a strategy where the list pointers are embedded in the data +items themselves. + +Use this one when you need to store arbitrary data in the list where you +can't embed the list pointers in the data, if a data item needs to be +stored in multiple lists, etc. + +Note about the memory management: ib_list_t is a fixed-size struct whose +allocation/deallocation is done through ib_list_create/ib_list_free, but the +memory for the list nodes is allocated through a user-given memory heap, +which can either be the same for all nodes or vary per node. Most users will +probably want to create a memory heap to store the item-specific data, and +pass in this same heap to the list node creation functions, thus +automatically freeing the list node when the item's heap is freed. + +************************************************************************/ + + +#ifndef IB_LIST_H +#define IB_LIST_H + +#include "mem0mem.h" + +typedef struct ib_list_struct ib_list_t; +typedef struct ib_list_node_struct ib_list_node_t; +typedef struct ib_list_helper_struct ib_list_helper_t; + +/******************************************************************** +Create a new list using mem_alloc. Lists created with this function must be +freed with ib_list_free. */ + +ib_list_t* +ib_list_create(void); +/*=================*/ + /* out: list */ + + +/******************************************************************** +Create a new list using the given heap. ib_list_free MUST NOT BE CALLED for +lists created with this function. */ + +ib_list_t* +ib_list_create_heap( +/*================*/ + /* out: list */ + mem_heap_t* heap); /* in: memory heap to use */ + +/******************************************************************** +Free a list. */ + +void +ib_list_free( +/*=========*/ + ib_list_t* list); /* in: list */ + +/******************************************************************** +Add the data to the start of the list. */ + +ib_list_node_t* +ib_list_add_first( +/*==============*/ + /* out: new list node*/ + ib_list_t* list, /* in: list */ + void* data, /* in: data */ + mem_heap_t* heap); /* in: memory heap to use */ + +/******************************************************************** +Add the data to the end of the list. */ + +ib_list_node_t* +ib_list_add_last( +/*=============*/ + /* out: new list node*/ + ib_list_t* list, /* in: list */ + void* data, /* in: data */ + mem_heap_t* heap); /* in: memory heap to use */ + +/******************************************************************** +Add the data after the indicated node. */ + +ib_list_node_t* +ib_list_add_after( +/*==============*/ + /* out: new list node*/ + ib_list_t* list, /* in: list */ + ib_list_node_t* prev_node, /* in: node preceding new node (can + be NULL) */ + void* data, /* in: data */ + mem_heap_t* heap); /* in: memory heap to use */ + +/******************************************************************** +Remove the node from the list. */ + +void +ib_list_remove( +/*===========*/ + ib_list_t* list, /* in: list */ + ib_list_node_t* node); /* in: node to remove */ + +/******************************************************************** +Get the first node in the list. */ +UNIV_INLINE +ib_list_node_t* +ib_list_get_first( +/*==============*/ + /* out: first node, or NULL */ + ib_list_t* list); /* in: list */ + +/******************************************************************** +Get the last node in the list. */ +UNIV_INLINE +ib_list_node_t* +ib_list_get_last( +/*=============*/ + /* out: last node, or NULL */ + ib_list_t* list); /* in: list */ + +/* List. */ +struct ib_list_struct { + ib_list_node_t* first; /* first node */ + ib_list_node_t* last; /* last node */ + ibool is_heap_list; /* TRUE if this list was + allocated through a heap */ +}; + +/* A list node. */ +struct ib_list_node_struct { + ib_list_node_t* prev; /* previous node */ + ib_list_node_t* next; /* next node */ + void* data; /* user data */ +}; + +/* Quite often, the only additional piece of data you need is the per-item +memory heap, so we have this generic struct available to use in those +cases. */ +struct ib_list_helper_struct { + mem_heap_t* heap; /* memory heap */ + void* data; /* user data */ +}; + +#ifndef UNIV_NONINL +#include "ut0list.ic" +#endif + +#endif diff --git a/storage/innobase/include/ut0list.ic b/storage/innobase/include/ut0list.ic new file mode 100644 index 00000000000..c2d3e4557f0 --- /dev/null +++ b/storage/innobase/include/ut0list.ic @@ -0,0 +1,23 @@ +/******************************************************************** +Get the first node in the list. */ +UNIV_INLINE +ib_list_node_t* +ib_list_get_first( +/*==============*/ + /* out: first node, or NULL */ + ib_list_t* list) /* in: list */ +{ + return(list->first); +} + +/******************************************************************** +Get the last node in the list. */ +UNIV_INLINE +ib_list_node_t* +ib_list_get_last( +/*=============*/ + /* out: last node, or NULL */ + ib_list_t* list) /* in: list */ +{ + return(list->last); +} diff --git a/storage/innobase/include/ut0ut.h b/storage/innobase/include/ut0ut.h index 8f1be212fbf..1bb90ae041b 100644 --- a/storage/innobase/include/ut0ut.h +++ b/storage/innobase/include/ut0ut.h @@ -224,6 +224,7 @@ ut_print_name( /*==========*/ FILE* f, /* in: output stream */ struct trx_struct*trx, /* in: transaction */ + ibool table_id,/* in: TRUE=decode table name */ const char* name); /* in: name to print */ /************************************************************************** @@ -234,6 +235,7 @@ ut_print_namel( /*===========*/ FILE* f, /* in: output stream */ struct trx_struct*trx, /* in: transaction (NULL=no quotes) */ + ibool table_id,/* in: TRUE=decode table name */ const char* name, /* in: name to print */ ulint namelen);/* in: length of name */ diff --git a/storage/innobase/include/ut0wqueue.h b/storage/innobase/include/ut0wqueue.h new file mode 100644 index 00000000000..57f2297beee --- /dev/null +++ b/storage/innobase/include/ut0wqueue.h @@ -0,0 +1,60 @@ +/*********************************************************************** +A Work queue. Threads can add work items to the queue and other threads can +wait for work items to be available and take them off the queue for +processing. + +************************************************************************/ + +#ifndef IB_WORK_QUEUE_H +#define IB_WORK_QUEUE_H + +#include "ut0list.h" +#include "mem0mem.h" +#include "os0sync.h" +#include "sync0types.h" + +typedef struct ib_wqueue_struct ib_wqueue_t; + +/******************************************************************** +Create a new work queue. */ + +ib_wqueue_t* +ib_wqueue_create(void); +/*===================*/ + /* out: work queue */ + +/******************************************************************** +Free a work queue. */ + +void +ib_wqueue_free( +/*===========*/ + ib_wqueue_t* wq); /* in: work queue */ + +/******************************************************************** +Add a work item to the queue. */ + +void +ib_wqueue_add( +/*==========*/ + ib_wqueue_t* wq, /* in: work queue */ + void* item, /* in: work item */ + mem_heap_t* heap); /* in: memory heap to use for allocating the + list node */ + +/******************************************************************** +Wait for a work item to appear in the queue. */ + +void* +ib_wqueue_wait( + /* out: work item */ + ib_wqueue_t* wq); /* in: work queue */ + +/* Work queue. */ +struct ib_wqueue_struct { + mutex_t mutex; /* mutex protecting everything */ + ib_list_t* items; /* work item list */ + os_event_t event; /* event we use to signal additions to list */ +}; + +#endif diff --git a/storage/innobase/lock/lock0lock.c b/storage/innobase/lock/lock0lock.c index 34e3296c9bc..a73a78620f1 100644 --- a/storage/innobase/lock/lock0lock.c +++ b/storage/innobase/lock/lock0lock.c @@ -1860,7 +1860,7 @@ lock_rec_enqueue_waiting( fputs( " InnoDB: Error: a record lock wait happens in a dictionary operation!\n" "InnoDB: Table name ", stderr); - ut_print_name(stderr, trx, index->table_name); + ut_print_name(stderr, trx, TRUE, index->table_name); fputs(".\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); @@ -1899,7 +1899,7 @@ lock_rec_enqueue_waiting( if (lock_print_waits) { fprintf(stderr, "Lock wait for trx %lu in index ", (ulong) ut_dulint_get_low(trx->id)); - ut_print_name(stderr, trx, index->name); + ut_print_name(stderr, trx, FALSE, index->name); } #endif /* UNIV_DEBUG */ @@ -3555,7 +3555,7 @@ lock_table_enqueue_waiting( fputs( " InnoDB: Error: a table lock wait happens in a dictionary operation!\n" "InnoDB: Table name ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs(".\n" "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr); @@ -4074,7 +4074,8 @@ lock_table_print( ut_a(lock_get_type(lock) == LOCK_TABLE); fputs("TABLE LOCK table ", file); - ut_print_name(file, lock->trx, lock->un_member.tab_lock.table->name); + ut_print_name(file, lock->trx, TRUE, + lock->un_member.tab_lock.table->name); fprintf(file, " trx id %lu %lu", (ulong) (lock->trx)->id.high, (ulong) (lock->trx)->id.low); diff --git a/storage/innobase/log/log0log.c b/storage/innobase/log/log0log.c index ea3b74c00f9..db6b8fabf6f 100644 --- a/storage/innobase/log/log0log.c +++ b/storage/innobase/log/log0log.c @@ -741,8 +741,7 @@ log_init(void) log_sys = mem_alloc(sizeof(log_t)); - mutex_create(&(log_sys->mutex)); - mutex_set_level(&(log_sys->mutex), SYNC_LOG); + mutex_create(&log_sys->mutex, SYNC_LOG); mutex_enter(&(log_sys->mutex)); @@ -798,8 +797,7 @@ log_init(void) log_sys->last_checkpoint_lsn = log_sys->lsn; log_sys->n_pending_checkpoint_writes = 0; - rw_lock_create(&(log_sys->checkpoint_lock)); - rw_lock_set_level(&(log_sys->checkpoint_lock), SYNC_NO_ORDER_CHECK); + rw_lock_create(&log_sys->checkpoint_lock, SYNC_NO_ORDER_CHECK); log_sys->checkpoint_buf = ut_align( mem_alloc(2 * OS_FILE_LOG_BLOCK_SIZE), @@ -815,8 +813,7 @@ log_init(void) log_sys->n_pending_archive_ios = 0; - rw_lock_create(&(log_sys->archive_lock)); - rw_lock_set_level(&(log_sys->archive_lock), SYNC_NO_ORDER_CHECK); + rw_lock_create(&log_sys->archive_lock, SYNC_NO_ORDER_CHECK); log_sys->archive_buf = NULL; diff --git a/storage/innobase/log/log0recv.c b/storage/innobase/log/log0recv.c index 4a91192782e..63a90f05212 100644 --- a/storage/innobase/log/log0recv.c +++ b/storage/innobase/log/log0recv.c @@ -112,8 +112,7 @@ recv_sys_create(void) recv_sys = mem_alloc(sizeof(recv_sys_t)); - mutex_create(&(recv_sys->mutex)); - mutex_set_level(&(recv_sys->mutex), SYNC_RECV); + mutex_create(&recv_sys->mutex, SYNC_RECV); recv_sys->heap = NULL; recv_sys->addr_hash = NULL; @@ -894,7 +893,6 @@ recv_parse_or_apply_log_rec_body( recv_sys->found_corrupt_log = TRUE; } - ut_ad(!page || ptr); if (index) { dict_table_t* table = index->table; diff --git a/storage/innobase/mem/mem0dbg.c b/storage/innobase/mem/mem0dbg.c index 86c33a22531..1220c2c8e82 100644 --- a/storage/innobase/mem/mem0dbg.c +++ b/storage/innobase/mem/mem0dbg.c @@ -122,8 +122,7 @@ mem_init( /* Initialize the hash table */ ut_a(FALSE == mem_hash_initialized); - mutex_create(&mem_hash_mutex); - mutex_set_level(&mem_hash_mutex, SYNC_MEM_HASH); + mutex_create(&mem_hash_mutex, SYNC_MEM_HASH); for (i = 0; i < MEM_HASH_SIZE; i++) { UT_LIST_INIT(*mem_hash_get_nth_cell(i)); diff --git a/storage/innobase/mem/mem0mem.c b/storage/innobase/mem/mem0mem.c index 5e7c48d3d3d..d26e4be3f88 100644 --- a/storage/innobase/mem/mem0mem.c +++ b/storage/innobase/mem/mem0mem.c @@ -17,6 +17,7 @@ Created 6/9/1994 Heikki Tuuri #include "btr0sea.h" #include "srv0srv.h" #include "mem0dbg.c" +#include <stdarg.h> /* THE MEMORY MANAGEMENT @@ -107,11 +108,45 @@ char* mem_heap_strdup( /*============*/ /* out, own: a copy of the string */ - mem_heap_t* heap, /* in: memory heap where string is allocated */ - const char* str) /* in: string to be copied */ + mem_heap_t* heap, /* in: memory heap where string is allocated */ + const char* str) /* in: string to be copied */ { - ulint len = strlen(str) + 1; - return(memcpy(mem_heap_alloc(heap, len), str, len)); + return(mem_heap_dup(heap, str, strlen(str) + 1)); +} + +/************************************************************************** +Duplicate a block of data, allocated from a memory heap. */ + +void* +mem_heap_dup( +/*=========*/ + /* out, own: a copy of the data */ + mem_heap_t* heap, /* in: memory heap where copy is allocated */ + const void* data, /* in: data to be copied */ + ulint len) /* in: length of data, in bytes */ +{ + return(memcpy(mem_heap_alloc(heap, len), data, len)); +} + +/************************************************************************** +Concatenate two memory blocks and return the result, using a memory heap. */ + +void* +mem_heap_cat( +/*=========*/ + /* out, own: the result */ + mem_heap_t* heap, /* in: memory heap where result is allocated */ + const void* b1, /* in: block 1 */ + ulint len1, /* in: length of b1, in bytes */ + const void* b2, /* in: block 2 */ + ulint len2) /* in: length of b2, in bytes */ +{ + void* res = mem_heap_alloc(heap, len1 + len2); + + memcpy(res, b1, len1); + memcpy((char *)res + len1, b2, len2); + + return(res); } /************************************************************************** @@ -139,6 +174,150 @@ mem_heap_strcat( return(s); } + +/******************************************************************** +Helper function for mem_heap_printf. */ +static +ulint +mem_heap_printf_low( +/*================*/ + /* out: length of formatted string, + including terminating NUL */ + char* buf, /* in/out: buffer to store formatted string + in, or NULL to just calculate length */ + const char* format, /* in: format string */ + va_list ap) /* in: arguments */ +{ + ulint len = 0; + + while (*format) { + + /* Does this format specifier have the 'l' length modifier. */ + ibool is_long = FALSE; + + /* Length of one parameter. */ + size_t plen; + + if (*format++ != '%') { + /* Non-format character. */ + + len++; + + if (buf) { + *buf++ = *(format - 1); + } + + continue; + } + + if (*format == 'l') { + is_long = TRUE; + format++; + } + + switch (*format++) { + case 's': + /* string */ + { + char* s = va_arg(ap, char*); + + /* "%ls" is a non-sensical format specifier. */ + ut_a(!is_long); + + plen = strlen(s); + len += plen; + + if (buf) { + memcpy(buf, s, plen); + buf += plen; + } + } + + break; + + case 'u': + /* unsigned int */ + { + char tmp[32]; + unsigned long val; + + /* We only support 'long' values for now. */ + ut_a(is_long); + + val = va_arg(ap, unsigned long); + + plen = sprintf(tmp, "%lu", val); + len += plen; + + if (buf) { + memcpy(buf, tmp, plen); + buf += plen; + } + } + + break; + + case '%': + + /* "%l%" is a non-sensical format specifier. */ + ut_a(!is_long); + + len++; + + if (buf) { + *buf++ = '%'; + } + + break; + + default: + ut_error; + } + } + + /* For the NUL character. */ + len++; + + if (buf) { + *buf = '\0'; + } + + return(len); +} + +/******************************************************************** +A simple (s)printf replacement that dynamically allocates the space for the +formatted string from the given heap. This supports a very limited set of +the printf syntax: types 's' and 'u' and length modifier 'l' (which is +required for the 'u' type). */ + +char* +mem_heap_printf( +/*============*/ + /* out: heap-allocated formatted string */ + mem_heap_t* heap, /* in: memory heap */ + const char* format, /* in: format string */ + ...) +{ + va_list ap; + char* str; + ulint len; + + /* Calculate length of string */ + len = 0; + va_start(ap, format); + len = mem_heap_printf_low(NULL, format, ap); + va_end(ap); + + /* Now create it for real. */ + str = mem_heap_alloc(heap, len); + va_start(ap, format); + mem_heap_printf_low(str, format, ap); + va_end(ap); + + return(str); +} + /******************************************************************* Creates a memory heap block where data can be allocated. */ diff --git a/storage/innobase/mem/mem0pool.c b/storage/innobase/mem/mem0pool.c index a61ab1ce170..5606921758c 100644 --- a/storage/innobase/mem/mem0pool.c +++ b/storage/innobase/mem/mem0pool.c @@ -204,8 +204,7 @@ mem_pool_create( pool->buf = ut_malloc_low(size, FALSE, TRUE); pool->size = size; - mutex_create(&(pool->mutex)); - mutex_set_level(&(pool->mutex), SYNC_MEM_POOL); + mutex_create(&pool->mutex, SYNC_MEM_POOL); /* Initialize the free lists */ diff --git a/storage/innobase/os/os0file.c b/storage/innobase/os/os0file.c index d10bdccbd2b..74905ce06dd 100644 --- a/storage/innobase/os/os0file.c +++ b/storage/innobase/os/os0file.c @@ -3680,6 +3680,37 @@ os_aio_posix_handle( #endif /************************************************************************** +Do a 'last millisecond' check that the page end is sensible; +reported page checksum errors from Linux seem to wipe over the page end. */ +static +void +os_file_check_page_trailers( +/*========================*/ + byte* combined_buf, /* in: combined write buffer */ + ulint total_len) /* in: size of combined_buf, in bytes + (a multiple of UNIV_PAGE_SIZE) */ +{ + ulint len; + + for (len = 0; len + UNIV_PAGE_SIZE <= total_len; + len += UNIV_PAGE_SIZE) { + byte* buf = combined_buf + len; + + if (memcmp(buf + (FIL_PAGE_LSN + 4), buf + (UNIV_PAGE_SIZE + - FIL_PAGE_END_LSN_OLD_CHKSUM + 4), 4)) { + ut_print_timestamp(stderr); + fprintf(stderr, +" InnoDB: ERROR: The page to be written seems corrupt!\n" +"InnoDB: Writing a block of %lu bytes, currently at offset %lu\n", + (ulong)total_len, (ulong)len); + buf_page_print(buf); + fprintf(stderr, +"InnoDB: ERROR: The page to be written seems corrupt!\n"); + } + } +} + +/************************************************************************** Does simulated aio. This function should be called by an i/o-handler thread. */ @@ -3716,7 +3747,6 @@ os_aio_simulated_handle( ibool ret; ulint n; ulint i; - ulint len2; segment = os_aio_get_array_and_local_segment(&array, global_segment); @@ -3924,32 +3954,15 @@ consecutive_loop: ut_error; } - /* Do a 'last millisecond' check that the page end - is sensible; reported page checksum errors from - Linux seem to wipe over the page end */ - - for (len2 = 0; len2 + UNIV_PAGE_SIZE <= total_len; - len2 += UNIV_PAGE_SIZE) { - if (mach_read_from_4(combined_buf + len2 - + FIL_PAGE_LSN + 4) - != mach_read_from_4(combined_buf + len2 - + UNIV_PAGE_SIZE - - FIL_PAGE_END_LSN_OLD_CHKSUM + 4)) { - ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: ERROR: The page to be written seems corrupt!\n"); - fprintf(stderr, -"InnoDB: Writing a block of %lu bytes, currently writing at offset %lu\n", - (ulong)total_len, (ulong)len2); - buf_page_print(combined_buf + len2); - fprintf(stderr, -"InnoDB: ERROR: The page to be written seems corrupt!\n"); - } - } + os_file_check_page_trailers(combined_buf, total_len); } ret = os_file_write(slot->name, slot->file, combined_buf, slot->offset, slot->offset_high, total_len); + + if (array == os_aio_write_array) { + os_file_check_page_trailers(combined_buf, total_len); + } } else { ret = os_file_read(slot->file, combined_buf, slot->offset, slot->offset_high, total_len); diff --git a/storage/innobase/os/os0thread.c b/storage/innobase/os/os0thread.c index 0b739c07557..138db6426ea 100644 --- a/storage/innobase/os/os0thread.c +++ b/storage/innobase/os/os0thread.c @@ -220,7 +220,7 @@ os_thread_join( /*===========*/ os_thread_id_t thread_id) /* in: id of the thread to join */ { - return pthread_join(thread_id, NULL); + return(pthread_join(thread_id, NULL)); } #endif /********************************************************************* diff --git a/storage/innobase/pars/lexyy.c b/storage/innobase/pars/lexyy.c index bbe78db1613..6d4e692e86b 100644 --- a/storage/innobase/pars/lexyy.c +++ b/storage/innobase/pars/lexyy.c @@ -356,8 +356,8 @@ static void yy_fatal_error (yyconst char msg[] ); *yy_cp = '\0'; \ (yy_c_buf_p) = yy_cp; -#define YY_NUM_RULES 116 -#define YY_END_OF_BUFFER 117 +#define YY_NUM_RULES 117 +#define YY_END_OF_BUFFER 118 /* This struct is not used in this scanner, but its presence is necessary. */ struct yy_trans_info @@ -365,51 +365,51 @@ struct yy_trans_info flex_int32_t yy_verify; flex_int32_t yy_nxt; }; -static yyconst flex_int16_t yy_accept[394] = +static yyconst flex_int16_t yy_accept[396] = { 0, - 0, 0, 111, 111, 0, 0, 0, 0, 117, 115, - 114, 114, 7, 106, 4, 95, 101, 104, 102, 99, - 103, 115, 105, 1, 115, 100, 98, 96, 97, 109, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 107, 108, - 111, 112, 5, 6, 8, 9, 114, 90, 110, 2, - 1, 3, 91, 92, 94, 93, 89, 89, 89, 89, - 89, 89, 44, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 27, - 16, 24, 89, 89, 89, 89, 54, 61, 89, 13, - - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 111, 112, 112, - 113, 5, 6, 8, 9, 2, 12, 45, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 26, 89, 89, 89, - 40, 89, 89, 89, 89, 20, 89, 89, 14, 89, - 89, 89, 17, 89, 89, 89, 89, 89, 80, 89, - 89, 89, 51, 11, 89, 35, 89, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 89, 89, 89, 89, - 19, 23, 89, 89, 89, 89, 89, 89, 89, 89, - - 89, 89, 89, 46, 89, 89, 29, 89, 87, 89, - 89, 38, 89, 89, 89, 89, 89, 48, 89, 31, - 89, 10, 64, 89, 89, 89, 42, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 28, 89, 89, 89, - 89, 89, 89, 89, 89, 89, 85, 89, 25, 89, - 66, 89, 89, 89, 89, 36, 89, 89, 89, 89, - 89, 89, 89, 30, 65, 22, 89, 57, 89, 75, - 89, 89, 89, 43, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 56, 89, 89, 89, 89, 89, - 89, 89, 39, 32, 79, 18, 89, 83, 74, 89, - - 55, 89, 63, 89, 52, 89, 89, 89, 47, 89, - 76, 89, 78, 89, 89, 33, 89, 89, 89, 34, - 72, 89, 89, 89, 89, 58, 89, 50, 49, 89, - 89, 89, 53, 62, 89, 89, 89, 21, 89, 89, - 73, 81, 89, 89, 77, 89, 68, 89, 89, 89, - 89, 89, 37, 89, 88, 67, 89, 84, 89, 89, - 89, 86, 89, 59, 89, 89, 15, 89, 70, 69, - 89, 41, 89, 82, 89, 89, 89, 89, 89, 89, - 89, 89, 89, 89, 71, 89, 89, 89, 89, 89, - 89, 60, 0 + 0, 0, 112, 112, 0, 0, 0, 0, 118, 116, + 115, 115, 8, 116, 107, 5, 96, 102, 105, 103, + 100, 104, 116, 106, 1, 116, 101, 99, 97, 98, + 110, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 108, + 109, 112, 113, 6, 7, 9, 10, 115, 4, 91, + 111, 2, 1, 3, 92, 93, 95, 94, 90, 90, + 90, 90, 90, 90, 45, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 28, 17, 25, 90, 90, 90, 90, 55, 62, + + 90, 14, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 112, + 113, 113, 114, 6, 7, 9, 10, 2, 13, 46, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 27, 90, + 90, 90, 41, 90, 90, 90, 90, 21, 90, 90, + 15, 90, 90, 90, 18, 90, 90, 90, 90, 90, + 81, 90, 90, 90, 52, 12, 90, 36, 90, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 90, 90, + 90, 90, 20, 24, 90, 90, 90, 90, 90, 90, + + 90, 90, 90, 90, 90, 47, 90, 90, 30, 90, + 88, 90, 90, 39, 90, 90, 90, 90, 90, 49, + 90, 32, 90, 11, 65, 90, 90, 90, 43, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 29, 90, + 90, 90, 90, 90, 90, 90, 90, 90, 86, 90, + 26, 90, 67, 90, 90, 90, 90, 37, 90, 90, + 90, 90, 90, 90, 90, 31, 66, 23, 90, 58, + 90, 76, 90, 90, 90, 44, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 57, 90, 90, 90, + 90, 90, 90, 90, 40, 33, 80, 19, 90, 84, + + 75, 90, 56, 90, 64, 90, 53, 90, 90, 90, + 48, 90, 77, 90, 79, 90, 90, 34, 90, 90, + 90, 35, 73, 90, 90, 90, 90, 59, 90, 51, + 50, 90, 90, 90, 54, 63, 90, 90, 90, 22, + 90, 90, 74, 82, 90, 90, 78, 90, 69, 90, + 90, 90, 90, 90, 38, 90, 89, 68, 90, 85, + 90, 90, 90, 87, 90, 60, 90, 90, 16, 90, + 71, 70, 90, 42, 90, 83, 90, 90, 90, 90, + 90, 90, 90, 90, 90, 90, 72, 90, 90, 90, + 90, 90, 90, 61, 0 } ; @@ -418,17 +418,17 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1, 1, 1, 1, 2, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 2, 1, 4, 1, 1, 5, 1, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, 15, 15, - 15, 15, 15, 15, 15, 15, 15, 16, 17, 18, - 19, 20, 21, 1, 22, 23, 24, 25, 26, 27, - 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, 46, 31, - 1, 1, 1, 1, 47, 1, 31, 31, 31, 31, - - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 31, 31, 31, 31, 31, 31, 31, 31, - 31, 31, 48, 1, 49, 1, 1, 1, 1, 1, + 1, 2, 1, 4, 1, 5, 6, 1, 7, 8, + 9, 10, 11, 12, 13, 14, 15, 16, 16, 16, + 16, 16, 16, 16, 16, 16, 16, 17, 18, 19, + 20, 21, 22, 1, 23, 24, 25, 26, 27, 28, + 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, + 39, 40, 41, 42, 43, 44, 45, 46, 47, 32, + 1, 1, 1, 1, 48, 1, 32, 32, 32, 32, + + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 32, 32, 32, 32, 32, 32, 32, 32, + 32, 32, 49, 1, 50, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, @@ -445,228 +445,228 @@ static yyconst flex_int32_t yy_ec[256] = 1, 1, 1, 1, 1 } ; -static yyconst flex_int32_t yy_meta[50] = +static yyconst flex_int32_t yy_meta[51] = { 0, - 1, 1, 1, 2, 1, 3, 1, 1, 4, 1, - 1, 1, 1, 1, 5, 1, 1, 1, 6, 1, - 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, + 1, 1, 1, 2, 1, 1, 3, 1, 1, 4, + 1, 1, 1, 1, 1, 5, 1, 1, 1, 6, + 1, 1, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, - 5, 5, 5, 5, 5, 5, 5, 1, 1 + 5, 5, 5, 5, 5, 5, 5, 5, 1, 1 } ; -static yyconst flex_int16_t yy_base[403] = +static yyconst flex_int16_t yy_base[406] = { 0, - 0, 0, 434, 433, 435, 434, 435, 434, 437, 444, - 48, 50, 444, 444, 444, 444, 444, 444, 444, 444, - 444, 423, 426, 41, 415, 444, 38, 444, 414, 444, - 20, 33, 32, 46, 40, 44, 0, 54, 52, 48, - 60, 393, 65, 66, 74, 27, 409, 69, 444, 444, - 0, 97, 0, 424, 0, 425, 111, 444, 444, 413, - 54, 408, 444, 444, 444, 444, 0, 401, 69, 397, - 389, 387, 0, 400, 79, 82, 395, 381, 94, 379, - 392, 377, 391, 385, 373, 377, 373, 375, 375, 0, - 82, 0, 374, 372, 366, 373, 0, 0, 379, 379, - - 362, 89, 98, 377, 93, 95, 368, 106, 360, 376, - 372, 350, 101, 371, 362, 112, 355, 0, 134, 135, - 444, 0, 387, 0, 388, 376, 0, 0, 364, 359, - 366, 364, 347, 345, 344, 349, 106, 347, 359, 93, - 347, 353, 354, 336, 336, 121, 0, 334, 350, 351, - 0, 338, 347, 344, 119, 126, 341, 331, 340, 333, - 330, 338, 0, 328, 338, 336, 327, 317, 311, 324, - 309, 329, 0, 0, 314, 0, 328, 319, 316, 130, - 312, 319, 326, 305, 307, 312, 312, 304, 307, 302, - 0, 0, 314, 298, 308, 315, 306, 294, 293, 307, - - 296, 309, 289, 0, 299, 281, 0, 300, 0, 297, - 284, 0, 283, 278, 283, 282, 292, 0, 278, 0, - 282, 0, 0, 278, 275, 289, 0, 274, 274, 272, - 288, 273, 285, 267, 285, 280, 0, 275, 275, 261, - 260, 273, 259, 273, 272, 271, 0, 255, 0, 249, - 0, 268, 252, 251, 251, 0, 264, 254, 249, 248, - 260, 250, 249, 0, 0, 0, 253, 0, 241, 0, - 255, 251, 237, 0, 251, 252, 235, 240, 233, 251, - 233, 230, 231, 228, 0, 233, 245, 232, 239, 229, - 237, 222, 0, 0, 0, 214, 221, 0, 0, 218, - - 0, 217, 0, 231, 0, 232, 219, 218, 0, 214, - 0, 217, 0, 209, 211, 0, 210, 224, 217, 0, - 0, 220, 223, 205, 220, 0, 216, 0, 0, 200, - 214, 213, 0, 0, 197, 196, 201, 0, 210, 195, - 0, 0, 201, 197, 0, 192, 0, 204, 204, 192, - 202, 191, 0, 178, 0, 0, 198, 0, 182, 176, - 182, 0, 173, 0, 178, 191, 0, 190, 0, 0, - 181, 0, 185, 0, 172, 172, 178, 164, 187, 175, - 174, 154, 125, 116, 0, 127, 133, 124, 121, 117, - 109, 0, 444, 165, 171, 177, 179, 145, 185, 191, - - 197, 203 + 0, 0, 435, 434, 436, 435, 437, 436, 439, 446, + 49, 51, 446, 0, 446, 446, 446, 446, 446, 446, + 446, 446, 424, 427, 41, 416, 446, 38, 446, 415, + 446, 20, 33, 32, 46, 40, 44, 0, 54, 52, + 48, 60, 394, 65, 66, 74, 27, 410, 69, 446, + 446, 0, 97, 0, 425, 0, 427, 112, 0, 446, + 446, 414, 54, 409, 446, 446, 446, 446, 0, 402, + 69, 398, 390, 388, 0, 401, 79, 82, 396, 382, + 94, 380, 393, 378, 392, 386, 374, 378, 374, 376, + 376, 0, 82, 0, 375, 373, 367, 374, 0, 0, + + 380, 380, 363, 89, 98, 378, 93, 95, 369, 106, + 361, 377, 373, 351, 101, 372, 363, 112, 356, 0, + 134, 135, 446, 0, 388, 0, 390, 377, 0, 0, + 365, 360, 367, 365, 348, 346, 345, 350, 106, 348, + 360, 93, 348, 354, 355, 337, 337, 121, 0, 335, + 351, 352, 0, 339, 348, 345, 119, 126, 342, 332, + 341, 334, 331, 339, 0, 329, 339, 337, 328, 318, + 312, 325, 310, 330, 0, 0, 315, 0, 329, 320, + 317, 130, 313, 320, 327, 306, 308, 313, 313, 305, + 308, 303, 0, 0, 315, 299, 309, 316, 307, 295, + + 294, 308, 297, 310, 290, 0, 300, 282, 0, 301, + 0, 298, 285, 0, 284, 279, 284, 283, 293, 0, + 279, 0, 283, 0, 0, 279, 276, 290, 0, 275, + 275, 273, 289, 274, 286, 268, 286, 281, 0, 276, + 276, 262, 261, 274, 260, 274, 273, 272, 0, 256, + 0, 250, 0, 269, 253, 252, 252, 0, 265, 255, + 250, 249, 261, 251, 250, 0, 0, 0, 254, 0, + 242, 0, 256, 252, 238, 0, 252, 253, 236, 241, + 234, 252, 234, 231, 232, 229, 0, 234, 246, 233, + 240, 230, 238, 223, 0, 0, 0, 215, 222, 0, + + 0, 219, 0, 218, 0, 232, 0, 233, 220, 219, + 0, 215, 0, 218, 0, 210, 212, 0, 211, 225, + 218, 0, 0, 221, 224, 206, 221, 0, 217, 0, + 0, 201, 215, 214, 0, 0, 198, 197, 202, 0, + 211, 196, 0, 0, 202, 198, 0, 193, 0, 205, + 205, 193, 203, 192, 0, 179, 0, 0, 199, 0, + 183, 177, 183, 0, 174, 0, 179, 192, 0, 191, + 0, 0, 182, 0, 186, 0, 173, 173, 179, 165, + 188, 180, 179, 165, 150, 117, 0, 129, 135, 125, + 122, 118, 110, 0, 446, 166, 172, 178, 151, 180, + + 146, 186, 192, 198, 204 } ; -static yyconst flex_int16_t yy_def[403] = +static yyconst flex_int16_t yy_def[406] = { 0, - 393, 1, 394, 394, 395, 395, 396, 396, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 397, 393, 393, 393, 393, 393, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 393, 393, - 399, 400, 401, 393, 402, 393, 393, 393, 393, 393, - 393, 397, 393, 393, 393, 393, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 399, 400, 400, - 393, 401, 393, 402, 393, 393, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 398, 398, 398, 398, 398, 398, 398, 398, - 398, 398, 0, 393, 393, 393, 393, 393, 393, 393, - - 393, 393 + 395, 1, 396, 396, 397, 397, 398, 398, 395, 395, + 395, 395, 395, 399, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 400, 395, 395, 395, 395, + 395, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 395, + 395, 402, 403, 404, 395, 405, 395, 395, 399, 395, + 395, 395, 395, 400, 395, 395, 395, 395, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 402, + 403, 403, 395, 404, 395, 405, 395, 395, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 401, 401, 401, 401, 401, 401, + 401, 401, 401, 401, 0, 395, 395, 395, 395, 395, + + 395, 395, 395, 395, 395 } ; -static yyconst flex_int16_t yy_nxt[494] = +static yyconst flex_int16_t yy_nxt[497] = { 0, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, - 30, 31, 32, 33, 34, 35, 36, 37, 37, 38, - 37, 37, 39, 37, 40, 41, 42, 37, 43, 44, - 45, 46, 47, 48, 37, 37, 37, 49, 50, 57, - 57, 57, 57, 60, 68, 61, 64, 65, 70, 69, - 74, 113, 71, 114, 75, 72, 60, 76, 61, 85, - 77, 79, 82, 78, 83, 80, 86, 93, 73, 87, - 90, 81, 88, 95, 84, 89, 97, 94, 91, 96, - 103, 106, 128, 92, 98, 110, 99, 116, 100, 104, - - 105, 101, 111, 107, 117, 120, 154, 108, 129, 112, - 121, 109, 57, 57, 134, 136, 137, 141, 164, 166, - 135, 155, 156, 138, 165, 170, 142, 172, 175, 196, - 181, 200, 201, 143, 167, 173, 171, 185, 168, 176, - 182, 186, 393, 120, 215, 197, 207, 393, 121, 67, - 208, 217, 238, 239, 392, 391, 390, 389, 388, 216, - 387, 218, 386, 385, 240, 51, 51, 51, 51, 51, - 51, 53, 53, 53, 53, 53, 53, 55, 55, 55, - 55, 55, 55, 62, 62, 118, 118, 118, 384, 118, - 118, 119, 119, 119, 119, 119, 119, 122, 122, 383, - - 122, 122, 122, 124, 382, 124, 124, 124, 124, 381, - 380, 379, 378, 377, 376, 375, 374, 373, 372, 371, - 370, 369, 368, 367, 366, 365, 364, 363, 362, 361, - 360, 359, 358, 357, 356, 355, 354, 353, 352, 351, - 350, 349, 348, 347, 346, 345, 344, 343, 342, 341, - 340, 339, 338, 337, 336, 335, 334, 333, 332, 331, - 330, 329, 328, 327, 326, 325, 324, 323, 322, 321, - 320, 319, 318, 317, 316, 315, 314, 313, 312, 311, - 310, 309, 308, 307, 306, 305, 304, 303, 302, 301, - 300, 299, 298, 297, 296, 295, 294, 293, 292, 291, - - 290, 289, 288, 287, 286, 285, 284, 283, 282, 281, - 280, 279, 278, 277, 276, 275, 274, 273, 272, 271, - 270, 269, 268, 267, 266, 265, 264, 263, 262, 261, - 260, 259, 258, 257, 256, 255, 254, 253, 252, 251, - 250, 249, 248, 247, 246, 245, 244, 243, 242, 241, - 237, 236, 235, 234, 233, 232, 231, 230, 229, 228, - 227, 226, 225, 224, 223, 222, 221, 220, 219, 214, - 213, 212, 211, 210, 209, 206, 205, 204, 203, 202, - 199, 198, 195, 194, 193, 192, 191, 190, 189, 188, - 126, 125, 123, 187, 184, 183, 180, 179, 178, 177, - - 174, 169, 163, 162, 161, 160, 159, 158, 157, 153, - 152, 151, 150, 149, 148, 147, 146, 145, 144, 140, - 139, 133, 132, 131, 130, 127, 393, 126, 125, 123, - 115, 102, 66, 63, 59, 58, 393, 56, 56, 54, - 54, 52, 52, 9, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393 + 30, 31, 32, 33, 34, 35, 36, 37, 38, 38, + 39, 38, 38, 40, 38, 41, 42, 43, 38, 44, + 45, 46, 47, 48, 49, 38, 38, 38, 50, 51, + 58, 58, 58, 58, 62, 70, 63, 66, 67, 72, + 71, 76, 115, 73, 116, 77, 74, 62, 78, 63, + 87, 79, 81, 84, 80, 85, 82, 88, 95, 75, + 89, 92, 83, 90, 97, 86, 91, 99, 96, 93, + 98, 105, 108, 130, 94, 100, 112, 101, 118, 102, + + 106, 107, 103, 113, 109, 119, 122, 156, 110, 131, + 114, 123, 111, 58, 58, 136, 138, 139, 143, 166, + 168, 137, 157, 158, 140, 167, 172, 144, 174, 177, + 198, 183, 202, 203, 145, 169, 175, 173, 187, 170, + 178, 184, 188, 395, 122, 217, 199, 209, 395, 123, + 69, 210, 219, 240, 241, 59, 394, 393, 392, 391, + 218, 390, 220, 389, 388, 242, 52, 52, 52, 52, + 52, 52, 54, 54, 54, 54, 54, 54, 56, 56, + 56, 56, 56, 56, 64, 64, 120, 120, 120, 387, + 120, 120, 121, 121, 121, 121, 121, 121, 124, 124, + + 386, 124, 124, 124, 126, 385, 126, 126, 126, 126, + 384, 383, 382, 381, 380, 379, 378, 377, 376, 375, + 374, 373, 372, 371, 370, 369, 368, 367, 366, 365, + 364, 363, 362, 361, 360, 359, 358, 357, 356, 355, + 354, 353, 352, 351, 350, 349, 348, 347, 346, 345, + 344, 343, 342, 341, 340, 339, 338, 337, 336, 335, + 334, 333, 332, 331, 330, 329, 328, 327, 326, 325, + 324, 323, 322, 321, 320, 319, 318, 317, 316, 315, + 314, 313, 312, 311, 310, 309, 308, 307, 306, 305, + 304, 303, 302, 301, 300, 299, 298, 297, 296, 295, + + 294, 293, 292, 291, 290, 289, 288, 287, 286, 285, + 284, 283, 282, 281, 280, 279, 278, 277, 276, 275, + 274, 273, 272, 271, 270, 269, 268, 267, 266, 265, + 264, 263, 262, 261, 260, 259, 258, 257, 256, 255, + 254, 253, 252, 251, 250, 249, 248, 247, 246, 245, + 244, 243, 239, 238, 237, 236, 235, 234, 233, 232, + 231, 230, 229, 228, 227, 226, 225, 224, 223, 222, + 221, 216, 215, 214, 213, 212, 211, 208, 207, 206, + 205, 204, 201, 200, 197, 196, 195, 194, 193, 192, + 191, 190, 128, 127, 125, 189, 186, 185, 182, 181, + + 180, 179, 176, 171, 165, 164, 163, 162, 161, 160, + 159, 155, 154, 153, 152, 151, 150, 149, 148, 147, + 146, 142, 141, 135, 134, 133, 132, 129, 395, 128, + 127, 125, 117, 104, 68, 65, 61, 60, 395, 57, + 57, 55, 55, 53, 53, 9, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395 } ; -static yyconst flex_int16_t yy_chk[494] = +static yyconst flex_int16_t yy_chk[497] = { 0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 11, - 11, 12, 12, 24, 31, 24, 27, 27, 32, 31, - 33, 46, 32, 46, 33, 32, 61, 33, 61, 36, - 33, 34, 35, 33, 35, 34, 36, 39, 32, 36, - 38, 34, 36, 40, 35, 36, 41, 39, 38, 40, - 43, 44, 69, 38, 41, 45, 41, 48, 41, 43, - - 43, 41, 45, 44, 48, 52, 91, 44, 69, 45, - 52, 44, 57, 57, 75, 76, 76, 79, 102, 103, - 75, 91, 91, 76, 102, 105, 79, 106, 108, 137, - 113, 140, 140, 79, 103, 106, 105, 116, 103, 108, - 113, 116, 119, 120, 155, 137, 146, 119, 120, 398, - 146, 156, 180, 180, 391, 390, 389, 388, 387, 155, - 386, 156, 384, 383, 180, 394, 394, 394, 394, 394, - 394, 395, 395, 395, 395, 395, 395, 396, 396, 396, - 396, 396, 396, 397, 397, 399, 399, 399, 382, 399, - 399, 400, 400, 400, 400, 400, 400, 401, 401, 381, - - 401, 401, 401, 402, 380, 402, 402, 402, 402, 379, - 378, 377, 376, 375, 373, 371, 368, 366, 365, 363, - 361, 360, 359, 357, 354, 352, 351, 350, 349, 348, - 346, 344, 343, 340, 339, 337, 336, 335, 332, 331, - 330, 327, 325, 324, 323, 322, 319, 318, 317, 315, - 314, 312, 310, 308, 307, 306, 304, 302, 300, 297, - 296, 292, 291, 290, 289, 288, 287, 286, 284, 283, - 282, 281, 280, 279, 278, 277, 276, 275, 273, 272, - 271, 269, 267, 263, 262, 261, 260, 259, 258, 257, - 255, 254, 253, 252, 250, 248, 246, 245, 244, 243, - - 242, 241, 240, 239, 238, 236, 235, 234, 233, 232, - 231, 230, 229, 228, 226, 225, 224, 221, 219, 217, - 216, 215, 214, 213, 211, 210, 208, 206, 205, 203, - 202, 201, 200, 199, 198, 197, 196, 195, 194, 193, - 190, 189, 188, 187, 186, 185, 184, 183, 182, 181, - 179, 178, 177, 175, 172, 171, 170, 169, 168, 167, - 166, 165, 164, 162, 161, 160, 159, 158, 157, 154, - 153, 152, 150, 149, 148, 145, 144, 143, 142, 141, - 139, 138, 136, 135, 134, 133, 132, 131, 130, 129, - 126, 125, 123, 117, 115, 114, 112, 111, 110, 109, - - 107, 104, 101, 100, 99, 96, 95, 94, 93, 89, - 88, 87, 86, 85, 84, 83, 82, 81, 80, 78, - 77, 74, 72, 71, 70, 68, 62, 60, 56, 54, - 47, 42, 29, 25, 23, 22, 9, 8, 7, 6, - 5, 4, 3, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393, 393, 393, 393, 393, 393, 393, 393, - 393, 393, 393 + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 11, 11, 12, 12, 25, 32, 25, 28, 28, 33, + 32, 34, 47, 33, 47, 34, 33, 63, 34, 63, + 37, 34, 35, 36, 34, 36, 35, 37, 40, 33, + 37, 39, 35, 37, 41, 36, 37, 42, 40, 39, + 41, 44, 45, 71, 39, 42, 46, 42, 49, 42, + + 44, 44, 42, 46, 45, 49, 53, 93, 45, 71, + 46, 53, 45, 58, 58, 77, 78, 78, 81, 104, + 105, 77, 93, 93, 78, 104, 107, 81, 108, 110, + 139, 115, 142, 142, 81, 105, 108, 107, 118, 105, + 110, 115, 118, 121, 122, 157, 139, 148, 121, 122, + 401, 148, 158, 182, 182, 399, 393, 392, 391, 390, + 157, 389, 158, 388, 386, 182, 396, 396, 396, 396, + 396, 396, 397, 397, 397, 397, 397, 397, 398, 398, + 398, 398, 398, 398, 400, 400, 402, 402, 402, 385, + 402, 402, 403, 403, 403, 403, 403, 403, 404, 404, + + 384, 404, 404, 404, 405, 383, 405, 405, 405, 405, + 382, 381, 380, 379, 378, 377, 375, 373, 370, 368, + 367, 365, 363, 362, 361, 359, 356, 354, 353, 352, + 351, 350, 348, 346, 345, 342, 341, 339, 338, 337, + 334, 333, 332, 329, 327, 326, 325, 324, 321, 320, + 319, 317, 316, 314, 312, 310, 309, 308, 306, 304, + 302, 299, 298, 294, 293, 292, 291, 290, 289, 288, + 286, 285, 284, 283, 282, 281, 280, 279, 278, 277, + 275, 274, 273, 271, 269, 265, 264, 263, 262, 261, + 260, 259, 257, 256, 255, 254, 252, 250, 248, 247, + + 246, 245, 244, 243, 242, 241, 240, 238, 237, 236, + 235, 234, 233, 232, 231, 230, 228, 227, 226, 223, + 221, 219, 218, 217, 216, 215, 213, 212, 210, 208, + 207, 205, 204, 203, 202, 201, 200, 199, 198, 197, + 196, 195, 192, 191, 190, 189, 188, 187, 186, 185, + 184, 183, 181, 180, 179, 177, 174, 173, 172, 171, + 170, 169, 168, 167, 166, 164, 163, 162, 161, 160, + 159, 156, 155, 154, 152, 151, 150, 147, 146, 145, + 144, 143, 141, 140, 138, 137, 136, 135, 134, 133, + 132, 131, 128, 127, 125, 119, 117, 116, 114, 113, + + 112, 111, 109, 106, 103, 102, 101, 98, 97, 96, + 95, 91, 90, 89, 88, 87, 86, 85, 84, 83, + 82, 80, 79, 76, 74, 73, 72, 70, 64, 62, + 57, 55, 48, 43, 30, 26, 24, 23, 9, 8, + 7, 6, 5, 4, 3, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395, 395, 395, 395, 395, + 395, 395, 395, 395, 395, 395 } ; @@ -908,7 +908,7 @@ YY_DECL register char *yy_cp, *yy_bp; register int yy_act; -#line 91 "pars0lex.l" +#line 92 "pars0lex.l" #line 914 "_flex_tmp.c" @@ -964,13 +964,13 @@ yy_match: while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 394 ) + if ( yy_current_state >= 396 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; ++yy_cp; } - while ( yy_current_state != 393 ); + while ( yy_current_state != 395 ); yy_cp = (yy_last_accepting_cpos); yy_current_state = (yy_last_accepting_state); @@ -992,7 +992,7 @@ do_action: /* This label is used only to access EOF actions. */ case 1: YY_RULE_SETUP -#line 93 "pars0lex.l" +#line 94 "pars0lex.l" { yylval = sym_tab_add_int_lit(pars_sym_tab_global, atoi(yytext)); @@ -1001,7 +1001,7 @@ YY_RULE_SETUP YY_BREAK case 2: YY_RULE_SETUP -#line 99 "pars0lex.l" +#line 100 "pars0lex.l" { ut_error; /* not implemented */ @@ -1010,7 +1010,7 @@ YY_RULE_SETUP YY_BREAK case 3: YY_RULE_SETUP -#line 105 "pars0lex.l" +#line 106 "pars0lex.l" { ulint type; @@ -1022,7 +1022,17 @@ YY_RULE_SETUP YY_BREAK case 4: YY_RULE_SETUP -#line 114 "pars0lex.l" +#line 115 "pars0lex.l" +{ + yylval = sym_tab_add_bound_id(pars_sym_tab_global, + yytext + 1); + + return(PARS_ID_TOKEN); +} + YY_BREAK +case 5: +YY_RULE_SETUP +#line 122 "pars0lex.l" { /* Quoted character string literals are handled in an explicit start state 'quoted'. This state is entered and the buffer for @@ -1033,19 +1043,19 @@ In the state 'quoted', only two actions are possible (defined below). */ stringbuf_len = 0; } YY_BREAK -case 5: -/* rule 5 can match eol */ +case 6: +/* rule 6 can match eol */ YY_RULE_SETUP -#line 123 "pars0lex.l" +#line 131 "pars0lex.l" { /* Got a sequence of characters other than "'": append to string buffer */ string_append(yytext, yyleng); } YY_BREAK -case 6: +case 7: YY_RULE_SETUP -#line 128 "pars0lex.l" +#line 136 "pars0lex.l" { /* Got a sequence of "'" characters: append half of them to string buffer, @@ -1070,9 +1080,9 @@ YY_RULE_SETUP } } YY_BREAK -case 7: +case 8: YY_RULE_SETUP -#line 152 "pars0lex.l" +#line 160 "pars0lex.l" { /* Quoted identifiers are handled in an explicit start state 'id'. This state is entered and the buffer for the scanned string is emptied @@ -1083,19 +1093,19 @@ In the state 'id', only two actions are possible (defined below). */ stringbuf_len = 0; } YY_BREAK -case 8: -/* rule 8 can match eol */ +case 9: +/* rule 9 can match eol */ YY_RULE_SETUP -#line 161 "pars0lex.l" +#line 169 "pars0lex.l" { /* Got a sequence of characters other than '"': append to string buffer */ string_append(yytext, yyleng); } YY_BREAK -case 9: +case 10: YY_RULE_SETUP -#line 166 "pars0lex.l" +#line 174 "pars0lex.l" { /* Got a sequence of '"' characters: append half of them to string buffer, @@ -1121,18 +1131,18 @@ YY_RULE_SETUP } } YY_BREAK -case 10: +case 11: YY_RULE_SETUP -#line 191 "pars0lex.l" +#line 199 "pars0lex.l" { yylval = sym_tab_add_null_lit(pars_sym_tab_global); return(PARS_NULL_LIT); } YY_BREAK -case 11: +case 12: YY_RULE_SETUP -#line 197 "pars0lex.l" +#line 205 "pars0lex.l" { /* Implicit cursor name */ yylval = sym_tab_add_str_lit(pars_sym_tab_global, @@ -1140,548 +1150,548 @@ YY_RULE_SETUP return(PARS_SQL_TOKEN); } YY_BREAK -case 12: +case 13: YY_RULE_SETUP -#line 204 "pars0lex.l" +#line 212 "pars0lex.l" { return(PARS_AND_TOKEN); } YY_BREAK -case 13: +case 14: YY_RULE_SETUP -#line 208 "pars0lex.l" +#line 216 "pars0lex.l" { return(PARS_OR_TOKEN); } YY_BREAK -case 14: +case 15: YY_RULE_SETUP -#line 212 "pars0lex.l" +#line 220 "pars0lex.l" { return(PARS_NOT_TOKEN); } YY_BREAK -case 15: +case 16: YY_RULE_SETUP -#line 216 "pars0lex.l" +#line 224 "pars0lex.l" { return(PARS_PROCEDURE_TOKEN); } YY_BREAK -case 16: +case 17: YY_RULE_SETUP -#line 220 "pars0lex.l" +#line 228 "pars0lex.l" { return(PARS_IN_TOKEN); } YY_BREAK -case 17: +case 18: YY_RULE_SETUP -#line 224 "pars0lex.l" +#line 232 "pars0lex.l" { return(PARS_OUT_TOKEN); } YY_BREAK -case 18: +case 19: YY_RULE_SETUP -#line 228 "pars0lex.l" +#line 236 "pars0lex.l" { return(PARS_BINARY_TOKEN); } YY_BREAK -case 19: +case 20: YY_RULE_SETUP -#line 232 "pars0lex.l" +#line 240 "pars0lex.l" { return(PARS_BLOB_TOKEN); } YY_BREAK -case 20: +case 21: YY_RULE_SETUP -#line 236 "pars0lex.l" +#line 244 "pars0lex.l" { return(PARS_INT_TOKEN); } YY_BREAK -case 21: +case 22: YY_RULE_SETUP -#line 240 "pars0lex.l" +#line 248 "pars0lex.l" { return(PARS_INT_TOKEN); } YY_BREAK -case 22: +case 23: YY_RULE_SETUP -#line 244 "pars0lex.l" +#line 252 "pars0lex.l" { return(PARS_FLOAT_TOKEN); } YY_BREAK -case 23: +case 24: YY_RULE_SETUP -#line 248 "pars0lex.l" +#line 256 "pars0lex.l" { return(PARS_CHAR_TOKEN); } YY_BREAK -case 24: +case 25: YY_RULE_SETUP -#line 252 "pars0lex.l" +#line 260 "pars0lex.l" { return(PARS_IS_TOKEN); } YY_BREAK -case 25: +case 26: YY_RULE_SETUP -#line 256 "pars0lex.l" +#line 264 "pars0lex.l" { return(PARS_BEGIN_TOKEN); } YY_BREAK -case 26: +case 27: YY_RULE_SETUP -#line 260 "pars0lex.l" +#line 268 "pars0lex.l" { return(PARS_END_TOKEN); } YY_BREAK -case 27: +case 28: YY_RULE_SETUP -#line 264 "pars0lex.l" +#line 272 "pars0lex.l" { return(PARS_IF_TOKEN); } YY_BREAK -case 28: +case 29: YY_RULE_SETUP -#line 268 "pars0lex.l" +#line 276 "pars0lex.l" { return(PARS_THEN_TOKEN); } YY_BREAK -case 29: +case 30: YY_RULE_SETUP -#line 272 "pars0lex.l" +#line 280 "pars0lex.l" { return(PARS_ELSE_TOKEN); } YY_BREAK -case 30: +case 31: YY_RULE_SETUP -#line 276 "pars0lex.l" +#line 284 "pars0lex.l" { return(PARS_ELSIF_TOKEN); } YY_BREAK -case 31: +case 32: YY_RULE_SETUP -#line 280 "pars0lex.l" +#line 288 "pars0lex.l" { return(PARS_LOOP_TOKEN); } YY_BREAK -case 32: +case 33: YY_RULE_SETUP -#line 284 "pars0lex.l" +#line 292 "pars0lex.l" { return(PARS_WHILE_TOKEN); } YY_BREAK -case 33: +case 34: YY_RULE_SETUP -#line 288 "pars0lex.l" +#line 296 "pars0lex.l" { return(PARS_RETURN_TOKEN); } YY_BREAK -case 34: +case 35: YY_RULE_SETUP -#line 292 "pars0lex.l" +#line 300 "pars0lex.l" { return(PARS_SELECT_TOKEN); } YY_BREAK -case 35: +case 36: YY_RULE_SETUP -#line 296 "pars0lex.l" +#line 304 "pars0lex.l" { return(PARS_SUM_TOKEN); } YY_BREAK -case 36: +case 37: YY_RULE_SETUP -#line 300 "pars0lex.l" +#line 308 "pars0lex.l" { return(PARS_COUNT_TOKEN); } YY_BREAK -case 37: +case 38: YY_RULE_SETUP -#line 304 "pars0lex.l" +#line 312 "pars0lex.l" { return(PARS_DISTINCT_TOKEN); } YY_BREAK -case 38: +case 39: YY_RULE_SETUP -#line 308 "pars0lex.l" +#line 316 "pars0lex.l" { return(PARS_FROM_TOKEN); } YY_BREAK -case 39: +case 40: YY_RULE_SETUP -#line 312 "pars0lex.l" +#line 320 "pars0lex.l" { return(PARS_WHERE_TOKEN); } YY_BREAK -case 40: +case 41: YY_RULE_SETUP -#line 316 "pars0lex.l" +#line 324 "pars0lex.l" { return(PARS_FOR_TOKEN); } YY_BREAK -case 41: +case 42: YY_RULE_SETUP -#line 320 "pars0lex.l" +#line 328 "pars0lex.l" { return(PARS_CONSISTENT_TOKEN); } YY_BREAK -case 42: +case 43: YY_RULE_SETUP -#line 324 "pars0lex.l" +#line 332 "pars0lex.l" { return(PARS_READ_TOKEN); } YY_BREAK -case 43: +case 44: YY_RULE_SETUP -#line 328 "pars0lex.l" +#line 336 "pars0lex.l" { return(PARS_ORDER_TOKEN); } YY_BREAK -case 44: +case 45: YY_RULE_SETUP -#line 332 "pars0lex.l" +#line 340 "pars0lex.l" { return(PARS_BY_TOKEN); } YY_BREAK -case 45: +case 46: YY_RULE_SETUP -#line 336 "pars0lex.l" +#line 344 "pars0lex.l" { return(PARS_ASC_TOKEN); } YY_BREAK -case 46: +case 47: YY_RULE_SETUP -#line 340 "pars0lex.l" +#line 348 "pars0lex.l" { return(PARS_DESC_TOKEN); } YY_BREAK -case 47: +case 48: YY_RULE_SETUP -#line 344 "pars0lex.l" +#line 352 "pars0lex.l" { return(PARS_INSERT_TOKEN); } YY_BREAK -case 48: +case 49: YY_RULE_SETUP -#line 348 "pars0lex.l" +#line 356 "pars0lex.l" { return(PARS_INTO_TOKEN); } YY_BREAK -case 49: +case 50: YY_RULE_SETUP -#line 352 "pars0lex.l" +#line 360 "pars0lex.l" { return(PARS_VALUES_TOKEN); } YY_BREAK -case 50: +case 51: YY_RULE_SETUP -#line 356 "pars0lex.l" +#line 364 "pars0lex.l" { return(PARS_UPDATE_TOKEN); } YY_BREAK -case 51: +case 52: YY_RULE_SETUP -#line 360 "pars0lex.l" +#line 368 "pars0lex.l" { return(PARS_SET_TOKEN); } YY_BREAK -case 52: +case 53: YY_RULE_SETUP -#line 364 "pars0lex.l" +#line 372 "pars0lex.l" { return(PARS_DELETE_TOKEN); } YY_BREAK -case 53: +case 54: YY_RULE_SETUP -#line 368 "pars0lex.l" +#line 376 "pars0lex.l" { return(PARS_CURRENT_TOKEN); } YY_BREAK -case 54: +case 55: YY_RULE_SETUP -#line 372 "pars0lex.l" +#line 380 "pars0lex.l" { return(PARS_OF_TOKEN); } YY_BREAK -case 55: +case 56: YY_RULE_SETUP -#line 376 "pars0lex.l" +#line 384 "pars0lex.l" { return(PARS_CREATE_TOKEN); } YY_BREAK -case 56: +case 57: YY_RULE_SETUP -#line 380 "pars0lex.l" +#line 388 "pars0lex.l" { return(PARS_TABLE_TOKEN); } YY_BREAK -case 57: +case 58: YY_RULE_SETUP -#line 384 "pars0lex.l" +#line 392 "pars0lex.l" { return(PARS_INDEX_TOKEN); } YY_BREAK -case 58: +case 59: YY_RULE_SETUP -#line 388 "pars0lex.l" +#line 396 "pars0lex.l" { return(PARS_UNIQUE_TOKEN); } YY_BREAK -case 59: +case 60: YY_RULE_SETUP -#line 392 "pars0lex.l" +#line 400 "pars0lex.l" { return(PARS_CLUSTERED_TOKEN); } YY_BREAK -case 60: +case 61: YY_RULE_SETUP -#line 396 "pars0lex.l" +#line 404 "pars0lex.l" { return(PARS_DOES_NOT_FIT_IN_MEM_TOKEN); } YY_BREAK -case 61: +case 62: YY_RULE_SETUP -#line 400 "pars0lex.l" +#line 408 "pars0lex.l" { return(PARS_ON_TOKEN); } YY_BREAK -case 62: +case 63: YY_RULE_SETUP -#line 404 "pars0lex.l" +#line 412 "pars0lex.l" { return(PARS_DECLARE_TOKEN); } YY_BREAK -case 63: +case 64: YY_RULE_SETUP -#line 408 "pars0lex.l" +#line 416 "pars0lex.l" { return(PARS_CURSOR_TOKEN); } YY_BREAK -case 64: +case 65: YY_RULE_SETUP -#line 412 "pars0lex.l" +#line 420 "pars0lex.l" { return(PARS_OPEN_TOKEN); } YY_BREAK -case 65: +case 66: YY_RULE_SETUP -#line 416 "pars0lex.l" +#line 424 "pars0lex.l" { return(PARS_FETCH_TOKEN); } YY_BREAK -case 66: +case 67: YY_RULE_SETUP -#line 420 "pars0lex.l" +#line 428 "pars0lex.l" { return(PARS_CLOSE_TOKEN); } YY_BREAK -case 67: +case 68: YY_RULE_SETUP -#line 424 "pars0lex.l" +#line 432 "pars0lex.l" { return(PARS_NOTFOUND_TOKEN); } YY_BREAK -case 68: +case 69: YY_RULE_SETUP -#line 428 "pars0lex.l" +#line 436 "pars0lex.l" { return(PARS_TO_CHAR_TOKEN); } YY_BREAK -case 69: +case 70: YY_RULE_SETUP -#line 432 "pars0lex.l" +#line 440 "pars0lex.l" { return(PARS_TO_NUMBER_TOKEN); } YY_BREAK -case 70: +case 71: YY_RULE_SETUP -#line 436 "pars0lex.l" +#line 444 "pars0lex.l" { return(PARS_TO_BINARY_TOKEN); } YY_BREAK -case 71: +case 72: YY_RULE_SETUP -#line 440 "pars0lex.l" +#line 448 "pars0lex.l" { return(PARS_BINARY_TO_NUMBER_TOKEN); } YY_BREAK -case 72: +case 73: YY_RULE_SETUP -#line 444 "pars0lex.l" +#line 452 "pars0lex.l" { return(PARS_SUBSTR_TOKEN); } YY_BREAK -case 73: +case 74: YY_RULE_SETUP -#line 448 "pars0lex.l" +#line 456 "pars0lex.l" { return(PARS_REPLSTR_TOKEN); } YY_BREAK -case 74: +case 75: YY_RULE_SETUP -#line 452 "pars0lex.l" +#line 460 "pars0lex.l" { return(PARS_CONCAT_TOKEN); } YY_BREAK -case 75: +case 76: YY_RULE_SETUP -#line 456 "pars0lex.l" +#line 464 "pars0lex.l" { return(PARS_INSTR_TOKEN); } YY_BREAK -case 76: +case 77: YY_RULE_SETUP -#line 460 "pars0lex.l" +#line 468 "pars0lex.l" { return(PARS_LENGTH_TOKEN); } YY_BREAK -case 77: +case 78: YY_RULE_SETUP -#line 464 "pars0lex.l" +#line 472 "pars0lex.l" { return(PARS_SYSDATE_TOKEN); } YY_BREAK -case 78: +case 79: YY_RULE_SETUP -#line 468 "pars0lex.l" +#line 476 "pars0lex.l" { return(PARS_PRINTF_TOKEN); } YY_BREAK -case 79: +case 80: YY_RULE_SETUP -#line 472 "pars0lex.l" +#line 480 "pars0lex.l" { return(PARS_ASSERT_TOKEN); } YY_BREAK -case 80: +case 81: YY_RULE_SETUP -#line 476 "pars0lex.l" +#line 484 "pars0lex.l" { return(PARS_RND_TOKEN); } YY_BREAK -case 81: +case 82: YY_RULE_SETUP -#line 480 "pars0lex.l" +#line 488 "pars0lex.l" { return(PARS_RND_STR_TOKEN); } YY_BREAK -case 82: +case 83: YY_RULE_SETUP -#line 484 "pars0lex.l" +#line 492 "pars0lex.l" { return(PARS_ROW_PRINTF_TOKEN); } YY_BREAK -case 83: +case 84: YY_RULE_SETUP -#line 488 "pars0lex.l" +#line 496 "pars0lex.l" { return(PARS_COMMIT_TOKEN); } YY_BREAK -case 84: +case 85: YY_RULE_SETUP -#line 492 "pars0lex.l" +#line 500 "pars0lex.l" { return(PARS_ROLLBACK_TOKEN); } YY_BREAK -case 85: +case 86: YY_RULE_SETUP -#line 496 "pars0lex.l" +#line 504 "pars0lex.l" { return(PARS_WORK_TOKEN); } YY_BREAK -case 86: +case 87: YY_RULE_SETUP -#line 500 "pars0lex.l" +#line 508 "pars0lex.l" { return(PARS_UNSIGNED_TOKEN); } YY_BREAK -case 87: +case 88: YY_RULE_SETUP -#line 504 "pars0lex.l" +#line 512 "pars0lex.l" { return(PARS_EXIT_TOKEN); } YY_BREAK -case 88: +case 89: YY_RULE_SETUP -#line 508 "pars0lex.l" +#line 516 "pars0lex.l" { return(PARS_FUNCTION_TOKEN); } YY_BREAK -case 89: +case 90: YY_RULE_SETUP -#line 512 "pars0lex.l" +#line 520 "pars0lex.l" { yylval = sym_tab_add_id(pars_sym_tab_global, (byte*)yytext, @@ -1689,52 +1699,44 @@ YY_RULE_SETUP return(PARS_ID_TOKEN); } YY_BREAK -case 90: -YY_RULE_SETUP -#line 519 "pars0lex.l" -{ - return(PARS_DDOT_TOKEN); -} - YY_BREAK case 91: YY_RULE_SETUP -#line 523 "pars0lex.l" +#line 527 "pars0lex.l" { - return(PARS_ASSIGN_TOKEN); + return(PARS_DDOT_TOKEN); } YY_BREAK case 92: YY_RULE_SETUP -#line 527 "pars0lex.l" +#line 531 "pars0lex.l" { - return(PARS_LE_TOKEN); + return(PARS_ASSIGN_TOKEN); } YY_BREAK case 93: YY_RULE_SETUP -#line 531 "pars0lex.l" +#line 535 "pars0lex.l" { - return(PARS_GE_TOKEN); + return(PARS_LE_TOKEN); } YY_BREAK case 94: YY_RULE_SETUP -#line 535 "pars0lex.l" +#line 539 "pars0lex.l" { - return(PARS_NE_TOKEN); + return(PARS_GE_TOKEN); } YY_BREAK case 95: YY_RULE_SETUP -#line 539 "pars0lex.l" +#line 543 "pars0lex.l" { - - return((int)(*yytext)); + return(PARS_NE_TOKEN); } YY_BREAK case 96: YY_RULE_SETUP -#line 544 "pars0lex.l" +#line 547 "pars0lex.l" { return((int)(*yytext)); @@ -1742,7 +1744,7 @@ YY_RULE_SETUP YY_BREAK case 97: YY_RULE_SETUP -#line 549 "pars0lex.l" +#line 552 "pars0lex.l" { return((int)(*yytext)); @@ -1750,7 +1752,7 @@ YY_RULE_SETUP YY_BREAK case 98: YY_RULE_SETUP -#line 554 "pars0lex.l" +#line 557 "pars0lex.l" { return((int)(*yytext)); @@ -1758,7 +1760,7 @@ YY_RULE_SETUP YY_BREAK case 99: YY_RULE_SETUP -#line 559 "pars0lex.l" +#line 562 "pars0lex.l" { return((int)(*yytext)); @@ -1766,7 +1768,7 @@ YY_RULE_SETUP YY_BREAK case 100: YY_RULE_SETUP -#line 564 "pars0lex.l" +#line 567 "pars0lex.l" { return((int)(*yytext)); @@ -1774,7 +1776,7 @@ YY_RULE_SETUP YY_BREAK case 101: YY_RULE_SETUP -#line 569 "pars0lex.l" +#line 572 "pars0lex.l" { return((int)(*yytext)); @@ -1782,7 +1784,7 @@ YY_RULE_SETUP YY_BREAK case 102: YY_RULE_SETUP -#line 574 "pars0lex.l" +#line 577 "pars0lex.l" { return((int)(*yytext)); @@ -1790,7 +1792,7 @@ YY_RULE_SETUP YY_BREAK case 103: YY_RULE_SETUP -#line 579 "pars0lex.l" +#line 582 "pars0lex.l" { return((int)(*yytext)); @@ -1798,7 +1800,7 @@ YY_RULE_SETUP YY_BREAK case 104: YY_RULE_SETUP -#line 584 "pars0lex.l" +#line 587 "pars0lex.l" { return((int)(*yytext)); @@ -1806,7 +1808,7 @@ YY_RULE_SETUP YY_BREAK case 105: YY_RULE_SETUP -#line 589 "pars0lex.l" +#line 592 "pars0lex.l" { return((int)(*yytext)); @@ -1814,7 +1816,7 @@ YY_RULE_SETUP YY_BREAK case 106: YY_RULE_SETUP -#line 594 "pars0lex.l" +#line 597 "pars0lex.l" { return((int)(*yytext)); @@ -1822,7 +1824,7 @@ YY_RULE_SETUP YY_BREAK case 107: YY_RULE_SETUP -#line 599 "pars0lex.l" +#line 602 "pars0lex.l" { return((int)(*yytext)); @@ -1830,7 +1832,7 @@ YY_RULE_SETUP YY_BREAK case 108: YY_RULE_SETUP -#line 604 "pars0lex.l" +#line 607 "pars0lex.l" { return((int)(*yytext)); @@ -1838,7 +1840,7 @@ YY_RULE_SETUP YY_BREAK case 109: YY_RULE_SETUP -#line 609 "pars0lex.l" +#line 612 "pars0lex.l" { return((int)(*yytext)); @@ -1846,35 +1848,43 @@ YY_RULE_SETUP YY_BREAK case 110: YY_RULE_SETUP -#line 614 "pars0lex.l" -BEGIN(comment); /* eat up comment */ +#line 617 "pars0lex.l" +{ + + return((int)(*yytext)); +} YY_BREAK case 111: -/* rule 111 can match eol */ YY_RULE_SETUP -#line 616 "pars0lex.l" - +#line 622 "pars0lex.l" +BEGIN(comment); /* eat up comment */ YY_BREAK case 112: /* rule 112 can match eol */ YY_RULE_SETUP -#line 617 "pars0lex.l" +#line 624 "pars0lex.l" YY_BREAK case 113: +/* rule 113 can match eol */ YY_RULE_SETUP -#line 618 "pars0lex.l" -BEGIN(INITIAL); +#line 625 "pars0lex.l" + YY_BREAK case 114: -/* rule 114 can match eol */ YY_RULE_SETUP -#line 620 "pars0lex.l" -/* eat up whitespace */ +#line 626 "pars0lex.l" +BEGIN(INITIAL); YY_BREAK case 115: +/* rule 115 can match eol */ YY_RULE_SETUP -#line 623 "pars0lex.l" +#line 628 "pars0lex.l" +/* eat up whitespace */ + YY_BREAK +case 116: +YY_RULE_SETUP +#line 631 "pars0lex.l" { fprintf(stderr,"Unrecognized character: %02x\n", *yytext); @@ -1884,12 +1894,12 @@ YY_RULE_SETUP return(0); } YY_BREAK -case 116: +case 117: YY_RULE_SETUP -#line 632 "pars0lex.l" +#line 640 "pars0lex.l" YY_FATAL_ERROR( "flex scanner jammed" ); YY_BREAK -#line 1892 "_flex_tmp.c" +#line 1902 "_flex_tmp.c" case YY_STATE_EOF(INITIAL): case YY_STATE_EOF(comment): case YY_STATE_EOF(quoted): @@ -2177,7 +2187,7 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 394 ) + if ( yy_current_state >= 396 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; @@ -2205,11 +2215,11 @@ static int yy_get_next_buffer (void) while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state ) { yy_current_state = (int) yy_def[yy_current_state]; - if ( yy_current_state >= 394 ) + if ( yy_current_state >= 396 ) yy_c = yy_meta[(unsigned int) yy_c]; } yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c]; - yy_is_jam = (yy_current_state == 393); + yy_is_jam = (yy_current_state == 395); return yy_is_jam ? 0 : yy_current_state; } @@ -2732,7 +2742,7 @@ void yyfree (void * ptr ) #undef YY_DECL_IS_OURS #undef YY_DECL #endif -#line 632 "pars0lex.l" +#line 640 "pars0lex.l" diff --git a/storage/innobase/pars/pars0lex.l b/storage/innobase/pars/pars0lex.l index ab1fe446924..8f6a8d39a36 100644 --- a/storage/innobase/pars/pars0lex.l +++ b/storage/innobase/pars/pars0lex.l @@ -84,6 +84,7 @@ string_append( DIGIT [0-9] ID [a-z_A-Z][a-z_A-Z0-9]* BOUND_LIT \:[a-z_A-Z0-9]+ +BOUND_ID \$[a-z_A-Z0-9]+ %x comment %x quoted @@ -111,6 +112,13 @@ BOUND_LIT \:[a-z_A-Z0-9]+ return(type); } +{BOUND_ID} { + yylval = sym_tab_add_bound_id(pars_sym_tab_global, + yytext + 1); + + return(PARS_ID_TOKEN); +} + "'" { /* Quoted character string literals are handled in an explicit start state 'quoted'. This state is entered and the buffer for diff --git a/storage/innobase/pars/pars0pars.c b/storage/innobase/pars/pars0pars.c index 7ef2f65c724..def26e62d29 100644 --- a/storage/innobase/pars/pars0pars.c +++ b/storage/innobase/pars/pars0pars.c @@ -1931,6 +1931,7 @@ pars_info_create(void) info->heap = heap; info->funcs = NULL; info->bound_lits = NULL; + info->bound_ids = NULL; info->graph_owns_us = TRUE; return(info); @@ -2071,6 +2072,32 @@ pars_info_add_function( } /******************************************************************** +Add bound id. */ + +void +pars_info_add_id( +/*=============*/ + pars_info_t* info, /* in: info struct */ + const char* name, /* in: name */ + const char* id) /* in: id */ +{ + pars_bound_id_t* bid; + + ut_ad(!pars_info_get_bound_id(info, name)); + + bid = mem_heap_alloc(info->heap, sizeof(*bid)); + + bid->name = name; + bid->id = id; + + if (!info->bound_ids) { + info->bound_ids = ib_vector_create(info->heap, 8); + } + + ib_vector_push(info->bound_ids, bid); +} + +/******************************************************************** Get user function with the given name.*/ pars_user_func_t* @@ -2131,3 +2158,34 @@ pars_info_get_bound_lit( return(NULL); } + +/******************************************************************** +Get bound id with the given name.*/ + +pars_bound_id_t* +pars_info_get_bound_id( +/*===================*/ + /* out: bound id, or NULL if not + found */ + pars_info_t* info, /* in: info struct */ + const char* name) /* in: bound id name to find */ +{ + ulint i; + ib_vector_t* vec; + + if (!info || !info->bound_ids) { + return(NULL); + } + + vec = info->bound_ids; + + for (i = 0; i < ib_vector_size(vec); i++) { + pars_bound_id_t* bid = ib_vector_get(vec, i); + + if (strcmp(bid->name, name) == 0) { + return(bid); + } + } + + return(NULL); +} diff --git a/storage/innobase/pars/pars0sym.c b/storage/innobase/pars/pars0sym.c index 79a1e555b06..8d691febb14 100644 --- a/storage/innobase/pars/pars0sym.c +++ b/storage/innobase/pars/pars0sym.c @@ -207,6 +207,13 @@ sym_tab_add_bound_lit( *lit_type = PARS_STR_LIT; break; + case DATA_CHAR: + ut_a(blit->length > 0); + + len = blit->length; + *lit_type = PARS_STR_LIT; + break; + case DATA_INT: ut_a(blit->length > 0); ut_a(blit->length <= 8); @@ -304,3 +311,42 @@ sym_tab_add_id( return(node); } + +/********************************************************************** +Add a bound identifier to a symbol table. */ + +sym_node_t* +sym_tab_add_bound_id( +/*===========*/ + /* out: symbol table node */ + sym_tab_t* sym_tab, /* in: symbol table */ + const char* name) /* in: name of bound id */ +{ + sym_node_t* node; + pars_bound_id_t* bid; + + bid = pars_info_get_bound_id(sym_tab->info, name); + ut_a(bid); + + node = mem_heap_alloc(sym_tab->heap, sizeof(sym_node_t)); + + node->common.type = QUE_NODE_SYMBOL; + + node->resolved = FALSE; + node->indirection = NULL; + + node->name = mem_heap_strdup(sym_tab->heap, bid->id); + node->name_len = strlen(node->name); + + UT_LIST_ADD_LAST(sym_list, sym_tab->sym_list, node); + + dfield_set_data(&(node->common.val), NULL, UNIV_SQL_NULL); + + node->common.val_buf_size = 0; + node->prefetch_buf = NULL; + node->cursor_def = NULL; + + node->sym_table = sym_tab; + + return(node); +} diff --git a/storage/innobase/row/row0ins.c b/storage/innobase/row/row0ins.c index e47d6a621a7..414f4091403 100644 --- a/storage/innobase/row/row0ins.c +++ b/storage/innobase/row/row0ins.c @@ -601,7 +601,7 @@ row_ins_set_detailed( rewind(srv_misc_tmpfile); if (os_file_set_eof(srv_misc_tmpfile)) { - ut_print_name(srv_misc_tmpfile, trx, + ut_print_name(srv_misc_tmpfile, trx, TRUE, foreign->foreign_table_name); dict_print_info_on_foreign_key_in_create_format( srv_misc_tmpfile, @@ -643,22 +643,22 @@ row_ins_foreign_report_err( trx_print(ef, trx, 600); fputs("Foreign key constraint fails for table ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, TRUE); putc('\n', ef); fputs(errstr, ef); fputs(" in parent table, in index ", ef); - ut_print_name(ef, trx, foreign->referenced_index->name); + ut_print_name(ef, trx, FALSE, foreign->referenced_index->name); if (entry) { fputs(" tuple:\n", ef); dtuple_print(ef, entry); } fputs("\nBut in child table ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(", in index ", ef); - ut_print_name(ef, trx, foreign->foreign_index->name); + ut_print_name(ef, trx, FALSE, foreign->foreign_index->name); if (rec) { fputs(", there is a record:\n", ef); rec_print(ef, rec, foreign->foreign_index); @@ -696,20 +696,20 @@ row_ins_foreign_report_add_err( fputs(" Transaction:\n", ef); trx_print(ef, trx, 600); fputs("Foreign key constraint fails for table ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); fputs(":\n", ef); dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, TRUE); fputs("\nTrying to add in child table, in index ", ef); - ut_print_name(ef, trx, foreign->foreign_index->name); + ut_print_name(ef, trx, FALSE, foreign->foreign_index->name); if (entry) { fputs(" tuple:\n", ef); dtuple_print(ef, entry); } fputs("\nBut in parent table ", ef); - ut_print_name(ef, trx, foreign->referenced_table_name); + ut_print_name(ef, trx, TRUE, foreign->referenced_table_name); fputs(", in index ", ef); - ut_print_name(ef, trx, foreign->referenced_index->name); + ut_print_name(ef, trx, FALSE, foreign->referenced_index->name); fputs(",\nthe closest match we can find is record:\n", ef); if (rec && page_rec_is_supremum(rec)) { /* If the cursor ended on a supremum record, it is better @@ -1277,16 +1277,19 @@ run_again: fputs(" Transaction:\n", ef); trx_print(ef, trx, 600); fputs("Foreign key constraint fails for table ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, + foreign->foreign_table_name); fputs(":\n", ef); dict_print_info_on_foreign_key_in_create_format(ef, trx, foreign, TRUE); fputs("\nTrying to add to index ", ef); - ut_print_name(ef, trx, foreign->foreign_index->name); + ut_print_name(ef, trx, FALSE, + foreign->foreign_index->name); fputs(" tuple:\n", ef); dtuple_print(ef, entry); fputs("\nBut the parent table ", ef); - ut_print_name(ef, trx, foreign->referenced_table_name); + ut_print_name(ef, trx, TRUE, + foreign->referenced_table_name); fputs("\nor its .ibd file does not currently exist!\n", ef); mutex_exit(&dict_foreign_err_mutex); @@ -1513,8 +1516,7 @@ row_ins_check_foreign_constraints( if (foreign->foreign_index == index) { if (foreign->referenced_table == NULL) { - dict_table_get(foreign->referenced_table_name, - trx); + dict_table_get(foreign->referenced_table_name); } if (0 == trx->dict_operation_lock_mode) { diff --git a/storage/innobase/row/row0mysql.c b/storage/innobase/row/row0mysql.c index 56574618f9a..58d86790c0a 100644 --- a/storage/innobase/row/row0mysql.c +++ b/storage/innobase/row/row0mysql.c @@ -680,7 +680,7 @@ row_prebuilt_free( "InnoDB: table handle. Magic n %lu, magic n2 %lu, table name", (ulong) prebuilt->magic_n, (ulong) prebuilt->magic_n2); - ut_print_name(stderr, NULL, prebuilt->table->name); + ut_print_name(stderr, NULL, TRUE, prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -773,7 +773,7 @@ row_update_prebuilt_trx( "InnoDB: Error: trying to use a corrupt\n" "InnoDB: table handle. Magic n %lu, table name", (ulong) prebuilt->magic_n); - ut_print_name(stderr, NULL, prebuilt->table->name); + ut_print_name(stderr, NULL, TRUE, prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -1094,7 +1094,8 @@ row_insert_for_mysql( "InnoDB: Error: trying to free a corrupt\n" "InnoDB: table handle. Magic n %lu, table name", (ulong) prebuilt->magic_n); - ut_print_name(stderr, prebuilt->trx, prebuilt->table->name); + ut_print_name(stderr, prebuilt->trx, TRUE, + prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -1329,7 +1330,8 @@ row_update_for_mysql( "InnoDB: Error: trying to free a corrupt\n" "InnoDB: table handle. Magic n %lu, table name", (ulong) prebuilt->magic_n); - ut_print_name(stderr, prebuilt->trx, prebuilt->table->name); + ut_print_name(stderr, prebuilt->trx, TRUE, + prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -1941,7 +1943,7 @@ row_create_table_for_mysql( fputs(" InnoDB: Warning: cannot create table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs(" because tablespace full\n", stderr); if (dict_table_get_low(table->name)) { @@ -1954,7 +1956,7 @@ row_create_table_for_mysql( ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs(" already exists in InnoDB internal\n" "InnoDB: data dictionary. Have you deleted the .frm file\n" "InnoDB: and not used DROP TABLE? Have you used DROP DATABASE\n" @@ -2031,7 +2033,7 @@ row_create_index_for_mysql( ut_print_timestamp(stderr); fputs(" InnoDB: Error: column ", stderr); - ut_print_name(stderr, trx, + ut_print_name(stderr, trx, FALSE, dict_index_get_nth_field(index, i)->name); fputs(" appears twice in ", stderr); dict_index_name_print(stderr, trx, index); @@ -2196,7 +2198,7 @@ row_drop_table_for_mysql_in_background( trx->check_foreigns = FALSE; /* fputs("InnoDB: Error: Dropping table ", stderr); - ut_print_name(stderr, name); + ut_print_name(stderr, trx, TRUE, name); fputs(" in background drop list\n", stderr); */ /* Try to drop the table in InnoDB */ @@ -2360,7 +2362,7 @@ row_add_table_to_background_drop_list( UT_LIST_ADD_LAST(row_mysql_drop_list, row_mysql_drop_list, drop); /* fputs("InnoDB: Adding table ", stderr); - ut_print_name(stderr, drop->table_name); + ut_print_name(stderr, trx, TRUE, drop->table_name); fputs(" to background drop list\n", stderr); */ mutex_exit(&kernel_mutex); @@ -2429,7 +2431,7 @@ do not allow the discard. We also reserve the data dictionary latch. */ if (table->space == 0) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: is in the system tablespace 0 which cannot be discarded\n", stderr); err = DB_ERROR; @@ -2441,7 +2443,7 @@ do not allow the discard. We also reserve the data dictionary latch. */ ut_print_timestamp(stderr); fputs(" InnoDB: You are trying to DISCARD table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs("\n" "InnoDB: though there is a foreign key check running on it.\n" "InnoDB: Cannot discard the table.\n", @@ -2475,10 +2477,10 @@ do not allow the discard. We also reserve the data dictionary latch. */ ut_print_timestamp(ef); fputs(" Cannot DISCARD table ", ef); - ut_print_name(ef, trx, name); + ut_print_name(ef, trx, TRUE, name); fputs("\n" "because it is referenced by ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); putc('\n', ef); mutex_exit(&dict_foreign_err_mutex); @@ -2540,10 +2542,10 @@ do not allow the discard. We also reserve the data dictionary latch. */ } funct_exit: - row_mysql_unlock_data_dictionary(trx); - trx_commit_for_mysql(trx); + row_mysql_unlock_data_dictionary(trx); + trx->op_info = ""; return((int) err); @@ -2590,7 +2592,7 @@ row_import_tablespace_for_mysql( if (!success) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: cannot reset lsn's in table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", stderr); @@ -2611,7 +2613,7 @@ row_import_tablespace_for_mysql( if (!table) { ut_print_timestamp(stderr); fputs(" InnoDB: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: does not exist in the InnoDB data dictionary\n" "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", @@ -2625,7 +2627,7 @@ row_import_tablespace_for_mysql( if (table->space == 0) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: is in the system tablespace 0 which cannot be imported\n", stderr); err = DB_ERROR; @@ -2638,7 +2640,7 @@ row_import_tablespace_for_mysql( fputs( " InnoDB: Error: you are trying to IMPORT a tablespace\n" "InnoDB: ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs(", though you have not called DISCARD on it yet\n" "InnoDB: during the lifetime of the mysqld process!\n", stderr); @@ -2663,7 +2665,7 @@ row_import_tablespace_for_mysql( fputs( " InnoDB: cannot find or open in the database directory the .ibd file of\n" "InnoDB: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: in ALTER TABLE ... IMPORT TABLESPACE\n", stderr); @@ -2673,10 +2675,10 @@ row_import_tablespace_for_mysql( } funct_exit: - row_mysql_unlock_data_dictionary(trx); - trx_commit_for_mysql(trx); + row_mysql_unlock_data_dictionary(trx); + trx->op_info = ""; return((int) err); @@ -2783,10 +2785,10 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */ ut_print_timestamp(ef); fputs(" Cannot truncate table ", ef); - ut_print_name(ef, trx, table->name); + ut_print_name(ef, trx, TRUE, table->name); fputs(" by DROP+CREATE\n" "InnoDB: because it is referenced by ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); putc('\n', ef); mutex_exit(&dict_foreign_err_mutex); @@ -2803,7 +2805,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */ if (table->n_foreign_key_checks_running > 0) { ut_print_timestamp(stderr); fputs(" InnoDB: Cannot truncate table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs(" by DROP+CREATE\n" "InnoDB: because there is a foreign key check running on it.\n", stderr); @@ -2918,7 +2920,7 @@ do not allow the TRUNCATE. We also reserve the data dictionary latch. */ trx->error_state = DB_SUCCESS; ut_print_timestamp(stderr); fputs(" InnoDB: Unable to assign a new identifier to table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs("\n" "InnoDB: after truncating it. Background processes may corrupt the table!\n", stderr); @@ -3045,7 +3047,7 @@ row_drop_table_for_mysql( ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs(" does not exist in the InnoDB internal\n" "InnoDB: data dictionary though MySQL is trying to drop it.\n" "InnoDB: Have you copied the .frm file of the table to the\n" @@ -3081,10 +3083,10 @@ row_drop_table_for_mysql( ut_print_timestamp(ef); fputs(" Cannot drop table ", ef); - ut_print_name(ef, trx, name); + ut_print_name(ef, trx, TRUE, name); fputs("\n" "because it is referenced by ", ef); - ut_print_name(ef, trx, foreign->foreign_table_name); + ut_print_name(ef, trx, TRUE, foreign->foreign_table_name); putc('\n', ef); mutex_exit(&dict_foreign_err_mutex); @@ -3103,7 +3105,7 @@ row_drop_table_for_mysql( if (added) { ut_print_timestamp(stderr); fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs("\n" "InnoDB: though there are still open handles to it.\n" "InnoDB: Adding the table to the background drop queue.\n", @@ -3136,7 +3138,7 @@ fputs(" InnoDB: Warning: MySQL is trying to drop table ", stderr); if (added) { ut_print_timestamp(stderr); fputs(" InnoDB: You are trying to drop table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs("\n" "InnoDB: though there is a foreign key check running on it.\n" "InnoDB: Adding the table to the background drop queue.\n", @@ -3259,7 +3261,7 @@ fputs(" InnoDB: You are trying to drop table ", stderr); ut_print_timestamp(stderr); fputs(" InnoDB: Error: not able to remove table ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs(" from the dictionary cache!\n", stderr); err = DB_ERROR; } @@ -3277,7 +3279,7 @@ fputs(" InnoDB: You are trying to drop table ", stderr); fprintf(stderr, "InnoDB: We removed now the InnoDB internal data dictionary entry\n" "InnoDB: of table "); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fprintf(stderr, ".\n"); goto funct_exit; @@ -3289,14 +3291,14 @@ fputs(" InnoDB: You are trying to drop table ", stderr); fprintf(stderr, "InnoDB: We removed now the InnoDB internal data dictionary entry\n" "InnoDB: of table "); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fprintf(stderr, ".\n"); ut_print_timestamp(stderr); fprintf(stderr, " InnoDB: Error: not able to delete tablespace %lu of table ", (ulong) space_id); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("!\n", stderr); err = DB_ERROR; } @@ -3304,6 +3306,8 @@ fputs(" InnoDB: You are trying to drop table ", stderr); } funct_exit: + trx_commit_for_mysql(trx); + if (locked_dictionary) { row_mysql_unlock_data_dictionary(trx); } @@ -3312,8 +3316,6 @@ funct_exit: mem_free(dir_path_of_temp_table); } - trx_commit_for_mysql(trx); - trx->op_info = ""; #ifndef UNIV_HOTBACKUP @@ -3364,10 +3366,10 @@ loop: ut_print_timestamp(stderr); fputs( " InnoDB: Warning: MySQL is trying to drop database ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fputs("\n" "InnoDB: though there are still open handles to table ", stderr); - ut_print_name(stderr, trx, table_name); + ut_print_name(stderr, trx, TRUE, table_name); fputs(".\n", stderr); os_thread_sleep(1000000); @@ -3383,19 +3385,19 @@ loop: if (err != DB_SUCCESS) { fputs("InnoDB: DROP DATABASE ", stderr); - ut_print_name(stderr, trx, name); + ut_print_name(stderr, trx, TRUE, name); fprintf(stderr, " failed with error %lu for table ", (ulint) err); - ut_print_name(stderr, trx, table_name); + ut_print_name(stderr, trx, TRUE, table_name); putc('\n', stderr); break; } } - row_mysql_unlock_data_dictionary(trx); - trx_commit_for_mysql(trx); + row_mysql_unlock_data_dictionary(trx); + trx->op_info = ""; return(err); @@ -3543,7 +3545,7 @@ row_rename_table_for_mysql( ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, old_name); + ut_print_name(stderr, trx, TRUE, old_name); fputs(" does not exist in the InnoDB internal\n" "InnoDB: data dictionary though MySQL is trying to rename the table.\n" "InnoDB: Have you copied the .frm file of the table to the\n" @@ -3559,7 +3561,7 @@ row_rename_table_for_mysql( ut_print_timestamp(stderr); fputs(" InnoDB: Error: table ", stderr); - ut_print_name(stderr, trx, old_name); + ut_print_name(stderr, trx, TRUE, old_name); fputs( " does not have an .ibd file in the database directory.\n" "InnoDB: You can look for further help from\n" @@ -3704,17 +3706,17 @@ end: "InnoDB: 1) Table rename would cause two FOREIGN KEY constraints\n" "InnoDB: to have the same internal name in case-insensitive comparison.\n" "InnoDB: 2) table ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); fputs(" exists in the InnoDB internal data\n" "InnoDB: dictionary though MySQL is trying rename table ", stderr); - ut_print_name(stderr, trx, old_name); + ut_print_name(stderr, trx, TRUE, old_name); fputs(" to it.\n" "InnoDB: Have you deleted the .frm file and not used DROP TABLE?\n" "InnoDB: You can look for further help from\n" "InnoDB: http://dev.mysql.com/doc/mysql/en/" "InnoDB_troubleshooting_datadict.html\n" "InnoDB: If table ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); fputs( " is a temporary table #sql..., then it can be that\n" "InnoDB: there are still queries running on the table, and it will be\n" @@ -3742,9 +3744,9 @@ end: ut_print_timestamp(stderr); fputs(" InnoDB: Error in table rename, cannot rename ", stderr); - ut_print_name(stderr, trx, old_name); + ut_print_name(stderr, trx, TRUE, old_name); fputs(" to ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); putc('\n', stderr); err = DB_ERROR; @@ -3763,7 +3765,7 @@ end: if (old_is_tmp) { fputs(" InnoDB: Error: in ALTER TABLE ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); fputs("\n" "InnoDB: has or is referenced in foreign key constraints\n" "InnoDB: which are not compatible with the new table definition.\n", @@ -3772,7 +3774,7 @@ end: fputs( " InnoDB: Error: in RENAME TABLE table ", stderr); - ut_print_name(stderr, trx, new_name); + ut_print_name(stderr, trx, TRUE, new_name); fputs("\n" "InnoDB: is referenced in foreign key constraints\n" "InnoDB: which are not compatible with the new table definition.\n", @@ -3788,6 +3790,8 @@ end: } funct_exit: + trx_commit_for_mysql(trx); + if (!recovering_temp_table) { row_mysql_unlock_data_dictionary(trx); } @@ -3796,8 +3800,6 @@ funct_exit: mem_heap_free(heap); } - trx_commit_for_mysql(trx); - trx->op_info = ""; return((int) err); @@ -3986,7 +3988,7 @@ row_check_table_for_mysql( while (index != NULL) { /* fputs("Validating index ", stderr); - ut_print_name(stderr, index->name); + ut_print_name(stderr, trx, FALSE, index->name); putc('\n', stderr); */ if (!btr_validate_tree(index->tree, prebuilt->trx)) { diff --git a/storage/innobase/row/row0purge.c b/storage/innobase/row/row0purge.c index b7581fa3644..1ef24f8e957 100644 --- a/storage/innobase/row/row0purge.c +++ b/storage/innobase/row/row0purge.c @@ -520,7 +520,7 @@ row_purge_parse_undo_rec( mutex_enter(&(dict_sys->mutex)); - node->table = dict_table_get_on_id_low(table_id, trx); + node->table = dict_table_get_on_id_low(table_id); mutex_exit(&(dict_sys->mutex)); diff --git a/storage/innobase/row/row0row.c b/storage/innobase/row/row0row.c index 24464ab5b99..50ad462f4aa 100644 --- a/storage/innobase/row/row0row.c +++ b/storage/innobase/row/row0row.c @@ -480,12 +480,12 @@ row_build_row_ref_in_tuple( ut_a(ref && index && rec); - if (!index->table) { + if (UNIV_UNLIKELY(!index->table)) { fputs("InnoDB: table ", stderr); notfound: - ut_print_name(stderr, trx, index->table_name); + ut_print_name(stderr, trx, TRUE, index->table_name); fputs(" for index ", stderr); - ut_print_name(stderr, trx, index->name); + ut_print_name(stderr, trx, FALSE, index->name); fputs(" not found\n", stderr); ut_error; } diff --git a/storage/innobase/row/row0sel.c b/storage/innobase/row/row0sel.c index c0f906f4ed7..a3360bff952 100644 --- a/storage/innobase/row/row0sel.c +++ b/storage/innobase/row/row0sel.c @@ -302,19 +302,45 @@ row_sel_fetch_columns( } while (column) { + mem_heap_t* heap = NULL; + ibool needs_copy; + field_no = column->field_nos[index_type]; if (field_no != ULINT_UNDEFINED) { - data = rec_get_nth_field(rec, offsets, field_no, &len); + if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, + field_no))) { + + /* Copy an externally stored field to the + temporary heap */ + + heap = mem_heap_create(1); + + data = btr_rec_copy_externally_stored_field( + rec, offsets, field_no, &len, heap); + + ut_a(len != UNIV_SQL_NULL); - if (column->copy_val) { + needs_copy = TRUE; + } else { + data = rec_get_nth_field(rec, offsets, + field_no, &len); + + needs_copy = column->copy_val; + } + + if (needs_copy) { eval_node_copy_and_alloc_val(column, data, len); } else { val = que_node_get_val(column); dfield_set_data(val, data, len); } + + if (UNIV_LIKELY_NULL(heap)) { + mem_heap_free(heap); + } } column = UT_LIST_GET_NEXT(col_var_list, column); @@ -2036,8 +2062,13 @@ row_fetch_print( dtype_print(type); fprintf(stderr, "\n"); - ut_print_buf(stderr, dfield_get_data(dfield), - dfield_get_len(dfield)); + if (dfield_get_len(dfield) != UNIV_SQL_NULL) { + ut_print_buf(stderr, dfield_get_data(dfield), + dfield_get_len(dfield)); + } else { + fprintf(stderr, " <NULL>;"); + } + fprintf(stderr, "\n"); exp = que_node_get_next(exp); @@ -2542,6 +2573,7 @@ row_sel_store_mysql_rec( { mysql_row_templ_t* templ; mem_heap_t* extern_field_heap = NULL; + mem_heap_t* heap; byte* data; ulint len; ulint i; @@ -2558,9 +2590,6 @@ row_sel_store_mysql_rec( templ = prebuilt->mysql_template + i; - data = rec_get_nth_field(rec, offsets, - templ->rec_field_no, &len); - if (UNIV_UNLIKELY(rec_offs_nth_extern(offsets, templ->rec_field_no))) { @@ -2569,7 +2598,19 @@ row_sel_store_mysql_rec( ut_a(!prebuilt->trx->has_search_latch); - extern_field_heap = mem_heap_create(UNIV_PAGE_SIZE); + if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) { + if (prebuilt->blob_heap == NULL) { + prebuilt->blob_heap = + mem_heap_create(UNIV_PAGE_SIZE); + } + + heap = prebuilt->blob_heap; + } else { + extern_field_heap = + mem_heap_create(UNIV_PAGE_SIZE); + + heap = extern_field_heap; + } /* NOTE: if we are retrieving a big BLOB, we may already run out of memory in the next call, which @@ -2577,54 +2618,17 @@ row_sel_store_mysql_rec( data = btr_rec_copy_externally_stored_field(rec, offsets, templ->rec_field_no, &len, - extern_field_heap); + heap); ut_a(len != UNIV_SQL_NULL); + } else { + /* Field is stored in the row. */ + + data = rec_get_nth_field(rec, offsets, + templ->rec_field_no, &len); } if (len != UNIV_SQL_NULL) { - if (UNIV_UNLIKELY(templ->type == DATA_BLOB)) { - - ut_a(prebuilt->templ_contains_blob); - - /* A heuristic test that we can allocate the - memory for a big BLOB. We have a safety margin - of 1000000 bytes. Since the test takes some - CPU time, we do not use it for small BLOBs. */ - - if (UNIV_UNLIKELY(len > 2000000) - && UNIV_UNLIKELY(!ut_test_malloc( - len + 1000000))) { - - ut_print_timestamp(stderr); - fprintf(stderr, -" InnoDB: Warning: could not allocate %lu + 1000000 bytes to retrieve\n" -"InnoDB: a big column. Table name ", (ulong) len); - ut_print_name(stderr, - prebuilt->trx, - prebuilt->table->name); - putc('\n', stderr); - - if (extern_field_heap) { - mem_heap_free( - extern_field_heap); - } - return(FALSE); - } - - /* Copy the BLOB data to the BLOB heap of - prebuilt */ - - if (prebuilt->blob_heap == NULL) { - prebuilt->blob_heap = - mem_heap_create(len); - } - - data = memcpy(mem_heap_alloc( - prebuilt->blob_heap, len), - data, len); - } - row_sel_field_store_in_mysql_format( mysql_rec + templ->mysql_col_offset, templ, data, len); @@ -3244,7 +3248,7 @@ row_search_for_mysql( "InnoDB: Error: trying to free a corrupt\n" "InnoDB: table handle. Magic n %lu, table name ", (ulong) prebuilt->magic_n); - ut_print_name(stderr, trx, prebuilt->table->name); + ut_print_name(stderr, trx, TRUE, prebuilt->table->name); putc('\n', stderr); mem_analyze_corruption(prebuilt); @@ -3530,15 +3534,13 @@ shortcut_fails_too_big_rec: if (trx->isolation_level <= TRX_ISO_READ_COMMITTED && prebuilt->select_lock_type != LOCK_NONE - && trx->mysql_query_str) { + && trx->mysql_query_str && trx->mysql_thd) { /* Scan the MySQL query string; check if SELECT is the first word there */ - ibool success; - dict_accept(*trx->mysql_query_str, "SELECT", &success); - - if (success) { + if (dict_str_starts_with_keyword(trx->mysql_thd, + *trx->mysql_query_str, "SELECT")) { /* It is a plain locking SELECT and the isolation level is low: do not lock gaps */ @@ -4402,7 +4404,7 @@ row_search_check_if_query_cache_permitted( dict_table_t* table; ibool ret = FALSE; - table = dict_table_get(norm_name, trx); + table = dict_table_get(norm_name); if (table == NULL) { diff --git a/storage/innobase/row/row0upd.c b/storage/innobase/row/row0upd.c index 4023283a60c..7be2fb17a07 100644 --- a/storage/innobase/row/row0upd.c +++ b/storage/innobase/row/row0upd.c @@ -202,8 +202,7 @@ row_upd_check_references_constraints( foreign->n_fields))) { if (foreign->foreign_table == NULL) { - dict_table_get(foreign->foreign_table_name, - trx); + dict_table_get(foreign->foreign_table_name); } if (foreign->foreign_table) { diff --git a/storage/innobase/srv/srv0srv.c b/storage/innobase/srv/srv0srv.c index 83cdcaa271b..c7bff806674 100644 --- a/storage/innobase/srv/srv0srv.c +++ b/storage/innobase/srv/srv0srv.c @@ -68,6 +68,9 @@ ibool srv_error_monitor_active = FALSE; const char* srv_main_thread_op_info = ""; +/* Prefix used by MySQL to indicate pre-5.1 table name encoding */ +const char srv_mysql50_table_name_prefix[9] = "#mysql50#"; + /* Server parameters which are read from the initfile */ /* The following three are dir paths which are catenated before file @@ -849,11 +852,9 @@ srv_init(void) srv_sys = mem_alloc(sizeof(srv_sys_t)); kernel_mutex_temp = mem_alloc(sizeof(mutex_t)); - mutex_create(&kernel_mutex); - mutex_set_level(&kernel_mutex, SYNC_KERNEL); + mutex_create(&kernel_mutex, SYNC_KERNEL); - mutex_create(&srv_innodb_monitor_mutex); - mutex_set_level(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&srv_innodb_monitor_mutex, SYNC_NO_ORDER_CHECK); srv_sys->threads = mem_alloc(OS_THREAD_MAX_N * sizeof(srv_slot_t)); @@ -2559,18 +2560,9 @@ suspend_thread: os_thread_exit(NULL); } - /* When there is user activity, InnoDB will set the event and the main - thread goes back to loop: */ + /* When there is user activity, InnoDB will set the event and the + main thread goes back to loop. */ goto loop; - - /* We count the number of threads in os_thread_exit(). A created - thread should always use that to exit and not use return() to exit. - The thread actually never comes here because it is exited in an - os_event_wait(). */ - - os_thread_exit(NULL); - - OS_THREAD_DUMMY_RETURN; } #endif /* !UNIV_HOTBACKUP */ diff --git a/storage/innobase/srv/srv0start.c b/storage/innobase/srv/srv0start.c index da2deac123d..205b54004ce 100644 --- a/storage/innobase/srv/srv0start.c +++ b/storage/innobase/srv/srv0start.c @@ -108,12 +108,45 @@ static char* srv_monitor_file_name; static int inno_bcmp(register const char *s1, register const char *s2, register uint len) { - while (len-- != 0 && *s1++ == *s2++) ; - return len+1; + while ((len-- != 0) && (*s1++ == *s2++)) + ; + + return(len + 1); } #define memcmp(A,B,C) inno_bcmp((A),(B),(C)) #endif +static +char* +srv_parse_megabytes( +/*================*/ + /* out: next character in string */ + char* str, /* in: string containing a quantity in bytes */ + ulint* megs) /* out: the number in megabytes */ +{ + char* endp; + ulint size; + + size = strtoul(str, &endp, 10); + + str = endp; + + switch (*str) { + case 'G': case 'g': + size *= 1024; + /* fall through */ + case 'M': case 'm': + str++; + break; + default: + size /= 1024 * 1024; + break; + } + + *megs = size; + return(str); +} + /************************************************************************* Reads the data files and their sizes from a character string given in the .cnf file. */ @@ -138,7 +171,6 @@ srv_parse_data_file_paths_and_sizes( last file if specified, 0 if not */ { char* input_str; - char* endp; char* path; ulint size; ulint i = 0; @@ -168,18 +200,7 @@ srv_parse_data_file_paths_and_sizes( str++; - size = strtoul(str, &endp, 10); - - str = endp; - - if (*str != 'M' && *str != 'G') { - size = size / (1024 * 1024); - } else if (*str == 'G') { - size = size * 1024; - str++; - } else { - str++; - } + str = srv_parse_megabytes(str, &size); if (0 == memcmp(str, ":autoextend", (sizeof ":autoextend") - 1)) { @@ -189,18 +210,7 @@ srv_parse_data_file_paths_and_sizes( str += (sizeof ":max:") - 1; - size = strtoul(str, &endp, 10); - - str = endp; - - if (*str != 'M' && *str != 'G') { - size = size / (1024 * 1024); - } else if (*str == 'G') { - size = size * 1024; - str++; - } else { - str++; - } + str = srv_parse_megabytes(str, &size); } if (*str != '\0') { @@ -273,18 +283,7 @@ srv_parse_data_file_paths_and_sizes( str++; } - size = strtoul(str, &endp, 10); - - str = endp; - - if ((*str != 'M') && (*str != 'G')) { - size = size / (1024 * 1024); - } else if (*str == 'G') { - size = size * 1024; - str++; - } else { - str++; - } + str = srv_parse_megabytes(str, &size); (*data_file_names)[i] = path; (*data_file_sizes)[i] = size; @@ -299,20 +298,8 @@ srv_parse_data_file_paths_and_sizes( str += (sizeof ":max:") - 1; - size = strtoul(str, &endp, 10); - - str = endp; - - if (*str != 'M' && *str != 'G') { - size = size / (1024 * 1024); - } else if (*str == 'G') { - size = size * 1024; - str++; - } else { - str++; - } - - *max_auto_extend_size = size; + str = srv_parse_megabytes(str, + max_auto_extend_size); } if (*str != '\0') { @@ -934,8 +921,7 @@ skip_size_check: ios = 0; - mutex_create(&ios_mutex); - mutex_set_level(&ios_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&ios_mutex, SYNC_NO_ORDER_CHECK); return(DB_SUCCESS); } @@ -1167,8 +1153,8 @@ NetWare. */ return((int) err); } - mutex_create(&srv_monitor_file_mutex); - mutex_set_level(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&srv_monitor_file_mutex, SYNC_NO_ORDER_CHECK); + if (srv_innodb_status) { srv_monitor_file_name = mem_alloc( strlen(fil_path_to_mysql_datadir) + @@ -1189,15 +1175,15 @@ NetWare. */ } } - mutex_create(&srv_dict_tmpfile_mutex); - mutex_set_level(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION); + mutex_create(&srv_dict_tmpfile_mutex, SYNC_DICT_OPERATION); + srv_dict_tmpfile = os_file_create_tmpfile(); if (!srv_dict_tmpfile) { return(DB_ERROR); } - mutex_create(&srv_misc_tmpfile_mutex); - mutex_set_level(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH); + mutex_create(&srv_misc_tmpfile_mutex, SYNC_ANY_LATCH); + srv_misc_tmpfile = os_file_create_tmpfile(); if (!srv_misc_tmpfile) { return(DB_ERROR); diff --git a/storage/innobase/sync/sync0arr.c b/storage/innobase/sync/sync0arr.c index fb7ec4cc78b..81986cdfd33 100644 --- a/storage/innobase/sync/sync0arr.c +++ b/storage/innobase/sync/sync0arr.c @@ -213,8 +213,7 @@ sync_array_create( if (protection == SYNC_ARRAY_OS_MUTEX) { arr->os_mutex = os_mutex_create(NULL); } else if (protection == SYNC_ARRAY_MUTEX) { - mutex_create(&(arr->mutex)); - mutex_set_level(&(arr->mutex), SYNC_NO_ORDER_CHECK); + mutex_create(&arr->mutex, SYNC_NO_ORDER_CHECK); } else { ut_error; } diff --git a/storage/innobase/sync/sync0rw.c b/storage/innobase/sync/sync0rw.c index 673e1080d89..ffc2633b467 100644 --- a/storage/innobase/sync/sync0rw.c +++ b/storage/innobase/sync/sync0rw.c @@ -89,19 +89,19 @@ void rw_lock_create_func( /*================*/ rw_lock_t* lock, /* in: pointer to memory */ + ulint level, /* in: level */ const char* cfile_name, /* in: file name where created */ - ulint cline, /* in: file line where created */ - const char* cmutex_name) /* in: mutex name */ + ulint cline, /* in: file line where created */ + const char* cmutex_name) /* in: mutex name */ { - /* If this is the very first time a synchronization - object is created, then the following call initializes - the sync system. */ + /* If this is the very first time a synchronization object is + created, then the following call initializes the sync system. */ - mutex_create(rw_lock_get_mutex(lock)); - mutex_set_level(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK); + mutex_create(rw_lock_get_mutex(lock), SYNC_NO_ORDER_CHECK); lock->mutex.cfile_name = cfile_name; lock->mutex.cline = cline; + #ifndef UNIV_HOTBACKUP lock->mutex.cmutex_name = cmutex_name; lock->mutex.mutex_type = 1; @@ -116,9 +116,10 @@ rw_lock_create_func( #ifdef UNIV_SYNC_DEBUG UT_LIST_INIT(lock->debug_list); - - lock->level = SYNC_LEVEL_NONE; #endif /* UNIV_SYNC_DEBUG */ + + lock->level = level; + lock->magic_n = RW_LOCK_MAGIC_N; lock->cfile_name = cfile_name; @@ -669,18 +670,6 @@ rw_lock_remove_debug_info( } #endif /* UNIV_SYNC_DEBUG */ -/********************************************************************** -Sets the rw-lock latching level field. */ - -void -rw_lock_set_level( -/*==============*/ - rw_lock_t* lock, /* in: rw-lock */ - ulint level) /* in: level */ -{ - lock->level = level; -} - #ifdef UNIV_SYNC_DEBUG /********************************************************************** Checks if the thread has locked the rw-lock in the specified mode, with diff --git a/storage/innobase/sync/sync0sync.c b/storage/innobase/sync/sync0sync.c index 6354830df70..04f03e89ec5 100644 --- a/storage/innobase/sync/sync0sync.c +++ b/storage/innobase/sync/sync0sync.c @@ -202,6 +202,7 @@ void mutex_create_func( /*==============*/ mutex_t* mutex, /* in: pointer to memory */ + ulint level, /* in: level */ const char* cfile_name, /* in: file name where created */ ulint cline, /* in: file line where created */ const char* cmutex_name) /* in: mutex name */ @@ -218,7 +219,7 @@ mutex_create_func( mutex->line = 0; mutex->file_name = "not yet reserved"; #endif /* UNIV_SYNC_DEBUG */ - mutex->level = SYNC_LEVEL_NONE; + mutex->level = level; mutex->cfile_name = cfile_name; mutex->cline = cline; #ifndef UNIV_HOTBACKUP @@ -598,19 +599,6 @@ mutex_get_debug_info( } #endif /* UNIV_SYNC_DEBUG */ -/********************************************************************** -Sets the mutex latching level field. */ - -void -mutex_set_level( -/*============*/ - mutex_t* mutex, /* in: mutex */ - ulint level) /* in: level */ -{ - mutex->level = level; -} - - #ifdef UNIV_SYNC_DEBUG /********************************************************************** Checks that the current thread owns the mutex. Works only in the debug @@ -979,8 +967,8 @@ void sync_thread_add_level( /*==================*/ void* latch, /* in: pointer to a mutex or an rw-lock */ - ulint level) /* in: level in the latching order; if SYNC_LEVEL_NONE, - nothing is done */ + ulint level) /* in: level in the latching order; if + SYNC_LEVEL_VARYING, nothing is done */ { sync_level_t* array; sync_level_t* slot; @@ -1002,7 +990,7 @@ sync_thread_add_level( return; } - if (level == SYNC_LEVEL_NONE) { + if (level == SYNC_LEVEL_VARYING) { return; } @@ -1050,6 +1038,9 @@ sync_thread_add_level( case SYNC_RECV: ut_a(sync_thread_levels_g(array, SYNC_RECV)); break; + case SYNC_WORK_QUEUE: + ut_a(sync_thread_levels_g(array, SYNC_WORK_QUEUE)); + break; case SYNC_LOG: ut_a(sync_thread_levels_g(array, SYNC_LOG)); break; @@ -1290,21 +1281,17 @@ sync_init(void) /* Init the mutex list and create the mutex to protect it. */ UT_LIST_INIT(mutex_list); - mutex_create(&mutex_list_mutex); - mutex_set_level(&mutex_list_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&mutex_list_mutex, SYNC_NO_ORDER_CHECK); - mutex_create(&sync_thread_mutex); - mutex_set_level(&sync_thread_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&sync_thread_mutex, SYNC_NO_ORDER_CHECK); /* Init the rw-lock list and create the mutex to protect it. */ UT_LIST_INIT(rw_lock_list); - mutex_create(&rw_lock_list_mutex); - mutex_set_level(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&rw_lock_list_mutex, SYNC_NO_ORDER_CHECK); #ifdef UNIV_SYNC_DEBUG - mutex_create(&rw_lock_debug_mutex); - mutex_set_level(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK); + mutex_create(&rw_lock_debug_mutex, SYNC_NO_ORDER_CHECK); rw_lock_debug_event = os_event_create(NULL); rw_lock_debug_waiters = FALSE; diff --git a/storage/innobase/thr/thr0loc.c b/storage/innobase/thr/thr0loc.c index 2a7a6c1c21f..c63520e8a07 100644 --- a/storage/innobase/thr/thr0loc.c +++ b/storage/innobase/thr/thr0loc.c @@ -226,6 +226,5 @@ thr_local_init(void) thr_local_hash = hash_create(OS_THREAD_MAX_N + 100); - mutex_create(&thr_local_mutex); - mutex_set_level(&thr_local_mutex, SYNC_THR_LOCAL); + mutex_create(&thr_local_mutex, SYNC_THR_LOCAL); } diff --git a/storage/innobase/trx/trx0purge.c b/storage/innobase/trx/trx0purge.c index be949079f80..79f38b1ee52 100644 --- a/storage/innobase/trx/trx0purge.c +++ b/storage/innobase/trx/trx0purge.c @@ -211,11 +211,9 @@ trx_purge_sys_create(void) purge_sys->purge_undo_no = ut_dulint_zero; purge_sys->next_stored = FALSE; - rw_lock_create(&(purge_sys->latch)); - rw_lock_set_level(&(purge_sys->latch), SYNC_PURGE_LATCH); + rw_lock_create(&purge_sys->latch, SYNC_PURGE_LATCH); - mutex_create(&(purge_sys->mutex)); - mutex_set_level(&(purge_sys->mutex), SYNC_PURGE_SYS); + mutex_create(&purge_sys->mutex, SYNC_PURGE_SYS); purge_sys->heap = mem_heap_create(256); diff --git a/storage/innobase/trx/trx0rec.c b/storage/innobase/trx/trx0rec.c index d8a5cce22e9..55723df48c5 100644 --- a/storage/innobase/trx/trx0rec.c +++ b/storage/innobase/trx/trx0rec.c @@ -843,7 +843,7 @@ trx_undo_update_rec_get_update( "InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n" "InnoDB: Run also CHECK TABLE ", (ulong) dict_index_get_n_fields(index)); - ut_print_name(stderr, trx, index->table_name); + ut_print_name(stderr, trx, TRUE, index->table_name); fprintf(stderr, "\n" "InnoDB: n_fields = %lu, i = %lu, ptr %p\n", (ulong) n_fields, (ulong) i, ptr); diff --git a/storage/innobase/trx/trx0roll.c b/storage/innobase/trx/trx0roll.c index af74cfe9032..2e7a5aa7b68 100644 --- a/storage/innobase/trx/trx0roll.c +++ b/storage/innobase/trx/trx0roll.c @@ -241,7 +241,7 @@ trx_rollback_to_savepoint_for_mysql( if (trx->conc_state == TRX_NOT_STARTED) { ut_print_timestamp(stderr); fputs(" InnoDB: Error: transaction has a savepoint ", stderr); - ut_print_name(stderr, trx, savep->name); + ut_print_name(stderr, trx, FALSE, savep->name); fputs(" though it is not started\n", stderr); return(DB_ERROR); } @@ -540,11 +540,11 @@ loop: (ulong) ut_dulint_get_high(trx->table_id), (ulong) ut_dulint_get_low(trx->table_id)); - table = dict_table_get_on_id_low(trx->table_id, trx); + table = dict_table_get_on_id_low(trx->table_id); if (table) { fputs("InnoDB: Table found: dropping table ", stderr); - ut_print_name(stderr, trx, table->name); + ut_print_name(stderr, trx, TRUE, table->name); fputs(" in recovery\n", stderr); err = row_drop_table_for_mysql(table->name, trx, TRUE); diff --git a/storage/innobase/trx/trx0rseg.c b/storage/innobase/trx/trx0rseg.c index f396666e7c9..5136174d110 100644 --- a/storage/innobase/trx/trx0rseg.c +++ b/storage/innobase/trx/trx0rseg.c @@ -147,8 +147,7 @@ trx_rseg_mem_create( rseg->space = space; rseg->page_no = page_no; - mutex_create(&(rseg->mutex)); - mutex_set_level(&(rseg->mutex), SYNC_RSEG); + mutex_create(&rseg->mutex, SYNC_RSEG); UT_LIST_ADD_LAST(rseg_list, trx_sys->rseg_list, rseg); diff --git a/storage/innobase/trx/trx0sys.c b/storage/innobase/trx/trx0sys.c index bd1bceef7da..8f24a54208a 100644 --- a/storage/innobase/trx/trx0sys.c +++ b/storage/innobase/trx/trx0sys.c @@ -101,8 +101,7 @@ trx_doublewrite_init( os_do_not_call_flush_at_each_write = TRUE; #endif /* UNIV_DO_FLUSH */ - mutex_create(&(trx_doublewrite->mutex)); - mutex_set_level(&(trx_doublewrite->mutex), SYNC_DOUBLEWRITE); + mutex_create(&trx_doublewrite->mutex, SYNC_DOUBLEWRITE); trx_doublewrite->first_free = 0; diff --git a/storage/innobase/trx/trx0trx.c b/storage/innobase/trx/trx0trx.c index a3115e332cd..5f191f4599b 100644 --- a/storage/innobase/trx/trx0trx.c +++ b/storage/innobase/trx/trx0trx.c @@ -144,8 +144,7 @@ trx_create( trx->repl_wait_binlog_name = NULL; trx->repl_wait_binlog_pos = 0; - mutex_create(&(trx->undo_mutex)); - mutex_set_level(&(trx->undo_mutex), SYNC_TRX_UNDO); + mutex_create(&trx->undo_mutex, SYNC_TRX_UNDO); trx->rseg = NULL; diff --git a/storage/innobase/ut/Makefile.am b/storage/innobase/ut/Makefile.am index c833a6d5a4c..fa4eeb2e9c9 100644 --- a/storage/innobase/ut/Makefile.am +++ b/storage/innobase/ut/Makefile.am @@ -19,6 +19,6 @@ include ../include/Makefile.i noinst_LIBRARIES = libut.a -libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c ut0vec.c +libut_a_SOURCES = ut0byte.c ut0dbg.c ut0mem.c ut0rnd.c ut0ut.c ut0vec.c ut0list.c ut0wqueue.c EXTRA_PROGRAMS = diff --git a/storage/innobase/ut/ut0dbg.c b/storage/innobase/ut/ut0dbg.c index 2157a71116a..a9391cd3adc 100644 --- a/storage/innobase/ut/ut0dbg.c +++ b/storage/innobase/ut/ut0dbg.c @@ -14,19 +14,21 @@ Created 1/30/1994 Heikki Tuuri ulint ut_dbg_zero = 0; #endif +#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) /* If this is set to TRUE all threads will stop into the next assertion and assert */ ibool ut_dbg_stop_threads = FALSE; +#endif #ifdef __NETWARE__ ibool panic_shutdown = FALSE; /* This is set to TRUE when on NetWare there happens an InnoDB assertion failure or other fatal error condition that requires an immediate shutdown. */ -#else /* __NETWARE__ */ +#elif !defined(UT_DBG_USE_ABORT) /* Null pointer used to generate memory trap */ ulint* ut_dbg_null_ptr = NULL; -#endif /* __NETWARE__ */ +#endif /***************************************************************** Report a failed assertion. */ @@ -56,7 +58,9 @@ ut_dbg_assertion_failed( "InnoDB: corruption in the InnoDB tablespace. Please refer to\n" "InnoDB: http://dev.mysql.com/doc/mysql/en/Forcing_recovery.html\n" "InnoDB: about forcing recovery.\n", stderr); +#if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) ut_dbg_stop_threads = TRUE; +#endif } #ifdef __NETWARE__ @@ -74,6 +78,7 @@ ut_dbg_panic(void) exit(1); } #else /* __NETWARE__ */ +# if defined(UNIV_SYNC_DEBUG) || !defined(UT_DBG_USE_ABORT) /***************************************************************** Stop a thread after assertion failure. */ @@ -87,4 +92,5 @@ ut_dbg_stop_thread( os_thread_pf(os_thread_get_curr_id()), file, line); os_thread_sleep(1000000000); } +# endif #endif /* __NETWARE__ */ diff --git a/storage/innobase/ut/ut0list.c b/storage/innobase/ut/ut0list.c new file mode 100644 index 00000000000..a0db7ff7b55 --- /dev/null +++ b/storage/innobase/ut/ut0list.c @@ -0,0 +1,169 @@ +#include "ut0list.h" +#ifdef UNIV_NONINL +#include "ut0list.ic" +#endif + +/******************************************************************** +Create a new list. */ + +ib_list_t* +ib_list_create(void) +/*=================*/ + /* out: list */ +{ + ib_list_t* list = mem_alloc(sizeof(ib_list_t)); + + list->first = NULL; + list->last = NULL; + list->is_heap_list = FALSE; + + return(list); +} + +/******************************************************************** +Create a new list using the given heap. ib_list_free MUST NOT BE CALLED for +lists created with this function. */ + +ib_list_t* +ib_list_create_heap( +/*================*/ + /* out: list */ + mem_heap_t* heap) /* in: memory heap to use */ +{ + ib_list_t* list = mem_heap_alloc(heap, sizeof(ib_list_t)); + + list->first = NULL; + list->last = NULL; + list->is_heap_list = TRUE; + + return(list); +} + +/******************************************************************** +Free a list. */ + +void +ib_list_free( +/*=========*/ + ib_list_t* list) /* in: list */ +{ + ut_a(!list->is_heap_list); + + /* We don't check that the list is empty because it's entirely valid + to e.g. have all the nodes allocated from a single heap that is then + freed after the list itself is freed. */ + + mem_free(list); +} + +/******************************************************************** +Add the data to the start of the list. */ + +ib_list_node_t* +ib_list_add_first( +/*==============*/ + /* out: new list node*/ + ib_list_t* list, /* in: list */ + void* data, /* in: data */ + mem_heap_t* heap) /* in: memory heap to use */ +{ + return(ib_list_add_after(list, ib_list_get_first(list), data, heap)); +} + +/******************************************************************** +Add the data to the end of the list. */ + +ib_list_node_t* +ib_list_add_last( +/*=============*/ + /* out: new list node*/ + ib_list_t* list, /* in: list */ + void* data, /* in: data */ + mem_heap_t* heap) /* in: memory heap to use */ +{ + return(ib_list_add_after(list, ib_list_get_last(list), data, heap)); +} + +/******************************************************************** +Add the data after the indicated node. */ + +ib_list_node_t* +ib_list_add_after( +/*==============*/ + /* out: new list node*/ + ib_list_t* list, /* in: list */ + ib_list_node_t* prev_node, /* in: node preceding new node (can + be NULL) */ + void* data, /* in: data */ + mem_heap_t* heap) /* in: memory heap to use */ +{ + ib_list_node_t* node = mem_heap_alloc(heap, sizeof(ib_list_node_t)); + + node->data = data; + + if (!list->first) { + /* Empty list. */ + + ut_a(!prev_node); + + node->prev = NULL; + node->next = NULL; + + list->first = node; + list->last = node; + } else if (!prev_node) { + /* Start of list. */ + + node->prev = NULL; + node->next = list->first; + + list->first->prev = node; + + list->first = node; + } else { + /* Middle or end of list. */ + + node->prev = prev_node; + node->next = prev_node->next; + + prev_node->next = node; + + if (node->next) { + node->next->prev = node; + } else { + list->last = node; + } + } + + return(node); +} + +/******************************************************************** +Remove the node from the list. */ + +void +ib_list_remove( +/*===========*/ + ib_list_t* list, /* in: list */ + ib_list_node_t* node) /* in: node to remove */ +{ + if (node->prev) { + node->prev->next = node->next; + } else { + /* First item in list. */ + + ut_ad(list->first == node); + + list->first = node->next; + } + + if (node->next) { + node->next->prev = node->prev; + } else { + /* Last item in list. */ + + ut_ad(list->last == node); + + list->last = node->prev; + } +} diff --git a/storage/innobase/ut/ut0ut.c b/storage/innobase/ut/ut0ut.c index 48435fe6155..6d81c113e42 100644 --- a/storage/innobase/ut/ut0ut.c +++ b/storage/innobase/ut/ut0ut.c @@ -20,18 +20,20 @@ Created 5/11/1994 Heikki Tuuri ibool ut_always_false = FALSE; +#ifndef UNIV_HOTBACKUP /********************************************************************* -Get the quote character to be used in SQL identifiers. +Display an SQL identifier. This definition must match the one in sql/ha_innodb.cc! */ extern -int -mysql_get_identifier_quote_char( -/*============================*/ - /* out: quote character to be - used in SQL identifiers; EOF if none */ +void +innobase_print_identifier( +/*======================*/ + FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction */ + ibool table_id,/* in: TRUE=decode table name */ const char* name, /* in: name to print */ ulint namelen);/* in: length of name */ +#endif /* !UNIV_HOTBACKUP */ /************************************************************ Gets the high 32 bits in a ulint. That is makes a shift >> 32, @@ -398,9 +400,10 @@ ut_print_name( /*==========*/ FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction */ + ibool table_id,/* in: TRUE=decode table name */ const char* name) /* in: name to print */ { - ut_print_namel(f, trx, name, strlen(name)); + ut_print_namel(f, trx, table_id, name, strlen(name)); } /************************************************************************** @@ -411,29 +414,27 @@ ut_print_namel( /*===========*/ FILE* f, /* in: output stream */ trx_t* trx, /* in: transaction (NULL=no quotes) */ + ibool table_id,/* in: TRUE=decode table name */ const char* name, /* in: name to print */ ulint namelen)/* in: length of name */ { - const char* s = name; - const char* e = s + namelen; #ifdef UNIV_HOTBACKUP - int q = '"'; + fwrite(name, 1, namelen, f); #else - int q = mysql_get_identifier_quote_char(trx, name, namelen); -#endif - if (q == EOF) { - fwrite(name, 1, namelen, f); - return; + char* slash = strchr(name, '/'); + + if (UNIV_LIKELY_NULL(slash)) { + /* Print the database name and table name separately. */ + ut_ad(table_id); + + innobase_print_identifier(f, trx, TRUE, name, slash - name); + putc('.', f); + innobase_print_identifier(f, trx, TRUE, slash + 1, + namelen - (slash - name) - 1); + } else { + innobase_print_identifier(f, trx, table_id, name, namelen); } - putc(q, f); - while (s < e) { - int c = *s++; - if (c == q) { - putc(c, f); - } - putc(c, f); - } - putc(q, f); +#endif } /************************************************************************** diff --git a/storage/innobase/ut/ut0wqueue.c b/storage/innobase/ut/ut0wqueue.c new file mode 100644 index 00000000000..2a6d8c19ef0 --- /dev/null +++ b/storage/innobase/ut/ut0wqueue.c @@ -0,0 +1,92 @@ +#include "ut0wqueue.h" + +/******************************************************************** +Create a new work queue. */ + +ib_wqueue_t* +ib_wqueue_create(void) +/*===================*/ + /* out: work queue */ +{ + ib_wqueue_t* wq = mem_alloc(sizeof(ib_wqueue_t)); + + mutex_create(&wq->mutex, SYNC_WORK_QUEUE); + + wq->items = ib_list_create(); + wq->event = os_event_create(NULL); + + return(wq); +} + +/******************************************************************** +Free a work queue. */ + +void +ib_wqueue_free( +/*===========*/ + ib_wqueue_t* wq) /* in: work queue */ +{ + ut_a(!ib_list_get_first(wq->items)); + + mutex_free(&wq->mutex); + ib_list_free(wq->items); + os_event_free(wq->event); + + mem_free(wq); +} + +/******************************************************************** +Add a work item to the queue. */ + +void +ib_wqueue_add( +/*==========*/ + ib_wqueue_t* wq, /* in: work queue */ + void* item, /* in: work item */ + mem_heap_t* heap) /* in: memory heap to use for allocating the + list node */ +{ + mutex_enter(&wq->mutex); + + ib_list_add_last(wq->items, item, heap); + os_event_set(wq->event); + + mutex_exit(&wq->mutex); +} + +/******************************************************************** +Wait for a work item to appear in the queue. */ + +void* +ib_wqueue_wait( + /* out: work item */ + ib_wqueue_t* wq) /* in: work queue */ +{ + ib_list_node_t* node; + + for (;;) { + os_event_wait(wq->event); + + mutex_enter(&wq->mutex); + + node = ib_list_get_first(wq->items); + + if (node) { + ib_list_remove(wq->items, node); + + if (!ib_list_get_first(wq->items)) { + /* We must reset the event when the list + gets emptied. */ + os_event_reset(wq->event); + } + + break; + } + + mutex_exit(&wq->mutex); + } + + mutex_exit(&wq->mutex); + + return(node->data); +} |