diff options
-rw-r--r-- | .bzrignore | 9 | ||||
-rwxr-xr-x | BUILD/SETUP.sh | 5 | ||||
-rw-r--r-- | include/maria.h | 17 | ||||
-rwxr-xr-x | mysql-test/mysql-test-run.pl | 19 | ||||
-rw-r--r-- | mysql-test/r/maria.result | 79 | ||||
-rw-r--r-- | mysql-test/t/disabled.def | 1 | ||||
-rw-r--r-- | mysql-test/t/maria.test | 93 | ||||
-rw-r--r-- | sql/filesort.cc | 2 | ||||
-rw-r--r-- | sql/slave.cc | 2 | ||||
-rw-r--r-- | storage/maria/ha_maria.cc | 85 | ||||
-rw-r--r-- | storage/maria/ha_maria.h | 4 | ||||
-rw-r--r-- | storage/maria/ma_bitmap.c | 19 | ||||
-rw-r--r-- | storage/maria/ma_blockrec.c | 269 | ||||
-rw-r--r-- | storage/maria/ma_blockrec.h | 3 | ||||
-rw-r--r-- | storage/maria/ma_check.c | 15 | ||||
-rw-r--r-- | storage/maria/ma_checksum.c | 5 | ||||
-rw-r--r-- | storage/maria/ma_create.c | 77 | ||||
-rw-r--r-- | storage/maria/ma_delete.c | 3 | ||||
-rw-r--r-- | storage/maria/ma_delete_all.c | 1 | ||||
-rw-r--r-- | storage/maria/ma_extra.c | 19 | ||||
-rw-r--r-- | storage/maria/ma_info.c | 6 | ||||
-rw-r--r-- | storage/maria/ma_search.c | 9 | ||||
-rw-r--r-- | storage/maria/ma_test2.c | 3 | ||||
-rw-r--r-- | storage/maria/ma_write.c | 2 | ||||
-rw-r--r-- | storage/maria/maria_def.h | 1 | ||||
-rw-r--r-- | storage/myisam/mi_create.c | 21 | ||||
-rw-r--r-- | storage/myisam/mi_test2.c | 3 |
27 files changed, 510 insertions, 262 deletions
diff --git a/.bzrignore b/.bzrignore index 297338d08dc..cd469d20721 100644 --- a/.bzrignore +++ b/.bzrignore @@ -2401,6 +2401,15 @@ storage/maria/maria_ftdump storage/maria/maria_log storage/maria/maria_pack storage/maria/unittest/maria_control +storage/maria/unittest/mf_pagecache_consist_1k-t-big +storage/maria/unittest/mf_pagecache_consist_1kHC-t-big +storage/maria/unittest/mf_pagecache_consist_1kRD-t-big +storage/maria/unittest/mf_pagecache_consist_1kWR-t-big +storage/maria/unittest/mf_pagecache_consist_64k-t-big +storage/maria/unittest/mf_pagecache_consist_64kHC-t-big +storage/maria/unittest/mf_pagecache_consist_64kRD-t-big +storage/maria/unittest/mf_pagecache_consist_64kWR-t-big +storage/maria/unittest/mf_pagecache_single_64k-t-big storage/myisam/.deps/ft_boolean_search.Po storage/myisam/.deps/ft_nlq_search.Po storage/myisam/.deps/ft_parser.Po diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh index 5dca590849e..11dd67d5de0 100755 --- a/BUILD/SETUP.sh +++ b/BUILD/SETUP.sh @@ -121,9 +121,8 @@ valgrind_flags="-USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify " valgrind_flags="$valgrind_flags -DMYSQL_SERVER_SUFFIX=-valgrind-max" # # Used in -debug builds -debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS" +debug_cflags="-DUNIV_MUST_NOT_INLINE -DEXTRA_DEBUG -DFORCE_INIT_OF_VARS " debug_cflags="$debug_cflags -DSAFEMALLOC -DPEDANTIC_SAFEMALLOC -DSAFE_MUTEX" -debug_cflags="$debug_cflags -DMY_LF_EXTRA_DEBUG" error_inject="--with-error-inject " # # Base C++ flags for all builds @@ -155,6 +154,8 @@ then base_configs="$base_configs --with-libedit" fi +static_link="--with-mysqld-ldflags=-all-static " +static_link="$static_link --with-client-ldflags=-all-static" # we need local-infile in all binaries for rpl000001 # if you need to disable local-infile in the client, write a build script # and unset local_infile_configs diff --git a/include/maria.h b/include/maria.h index 94152ce9bfa..a8c5cbf794b 100644 --- a/include/maria.h +++ b/include/maria.h @@ -122,22 +122,23 @@ typedef struct st_maria_isaminfo /* Struct from h_info */ my_off_t data_file_length; /* Length of data file */ my_off_t max_data_file_length, index_file_length; my_off_t max_index_file_length, delete_length; - ulong reclength; /* Recordlength */ - ulong mean_reclength; /* Mean recordlength (if packed) */ ulonglong auto_increment; ulonglong key_map; /* Which keys are used */ + time_t create_time; /* When table was created */ + time_t check_time; + time_t update_time; + ulong record_offset; + ulong *rec_per_key; /* for sql optimizing */ + ulong reclength; /* Recordlength */ + ulong mean_reclength; /* Mean recordlength (if packed) */ char *data_file_name, *index_file_name; + enum data_file_type data_file_type; uint keys; /* Number of keys in use */ uint options; /* HA_OPTION_... used */ + uint reflength; int errkey, /* With key was dupplicated on err */ sortkey; /* clustered by this key */ File filenr; /* (uniq) filenr for datafile */ - time_t create_time; /* When table was created */ - time_t check_time; - time_t update_time; - uint reflength; - ulong record_offset; - ulong *rec_per_key; /* for sql optimizing */ } MARIA_INFO; diff --git a/mysql-test/mysql-test-run.pl b/mysql-test/mysql-test-run.pl index c105a69e861..b5137e06fb8 100755 --- a/mysql-test/mysql-test-run.pl +++ b/mysql-test/mysql-test-run.pl @@ -2237,6 +2237,25 @@ sub setup_vardir() { { unlink($name); } + if ( $opt_valgrind and $opt_debug ) + { + # When both --valgrind and --debug is selected, send + # all output to the trace file, making it possible to + # see the exact location where valgrind complains + foreach my $mysqld (@{$master}, @{$slave}) + { + my $sidx= $mysqld->{idx} ? "$mysqld->{idx}" : ""; + my $trace_name= "$opt_vardir/log/" . $mysqld->{type} . "$sidx.trace"; + open(LOG, ">$mysqld->{path_myerr}") or die "Can't create $mysqld->{path_myerr}\n"; + print LOG " +NOTE: When running with --valgrind --debug the output from the .err file is +stored together with the trace file to make it easier to find the exact +position for valgrind errors. +See trace file $trace_name.\n"; + close(LOG); + $mysqld->{path_myerr}= $trace_name; + } + } } diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result index 7812f04336a..4a708cde307 100644 --- a/mysql-test/r/maria.result +++ b/mysql-test/r/maria.result @@ -348,11 +348,11 @@ t1 1 c_2 2 a A 5 NULL NULL BTREE explain select * from t1,t2 where t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL a NULL NULL NULL 2 -1 SIMPLE t1 ALL a NULL NULL NULL 5 Using where +1 SIMPLE t1 ref a a 4 test.t2.a 3 explain select * from t1,t2 force index(a) where t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL a NULL NULL NULL 2 -1 SIMPLE t1 ALL a NULL NULL NULL 5 Using where +1 SIMPLE t1 ref a a 4 test.t2.a 3 explain select * from t1 force index(a),t2 force index(a) where t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL a NULL NULL NULL 2 @@ -364,10 +364,10 @@ id select_type table type possible_keys key key_len ref rows Extra explain select * from t1,t2 force index(c) where t1.a=t2.a; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t2 ALL NULL NULL NULL NULL 2 -1 SIMPLE t1 ALL a NULL NULL NULL 5 Using where +1 SIMPLE t1 ref a a 4 test.t2.a 3 explain select * from t1 where a=0 or a=2; id select_type table type possible_keys key key_len ref rows Extra -1 SIMPLE t1 ALL a NULL NULL NULL 5 Using where +1 SIMPLE t1 range a a 4 NULL 4 Using where explain select * from t1 force index (a) where a=0 or a=2; id select_type table type possible_keys key key_len ref rows Extra 1 SIMPLE t1 range a a 4 NULL 4 Using where @@ -430,9 +430,6 @@ select * from t1 where a='807780' and b='477' and c='165'; a b c 807780 477 165 drop table t1; -DROP TABLE IF EXISTS t1; -Warnings: -Note 1051 Unknown table 't1' CREATE TABLE t1 (a varchar(150) NOT NULL, KEY (a)); INSERT t1 VALUES ("can \tcan"); INSERT t1 VALUES ("can can"); @@ -517,8 +514,8 @@ select c1 from t1 order by c1 limit 1; c1 a drop table t1; -create table t1 (a int not null, primary key(a)); -create table t2 (a int not null, b int not null, primary key(a,b)); +create table t1 (a int not null, primary key(a)) ROW_FORMAT=FIXED; +create table t2 (a int not null, b int not null, primary key(a,b)) ROW_FORMAT=FIXED; insert into t1 values (1),(2),(3),(4),(5),(6); insert into t2 values (1,1),(2,1); lock tables t1 read local, t2 read local; @@ -532,8 +529,8 @@ a a b 1 1 1 2 2 1 drop table t1,t2; -CREATE TABLE t1 (c1 varchar(250) NOT NULL); -CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)); +CREATE TABLE t1 (c1 varchar(250) NOT NULL) ROW_FORMAT=DYNAMIC; +CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)) ROW_FORMAT=DYNAMIC; INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003'); INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004'); LOCK TABLES t1 READ LOCAL, t2 READ LOCAL; @@ -590,7 +587,7 @@ t1 1 a 1 a A NULL NULL NULL YES BTREE disabled alter table t1 enable keys; show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 1 a 1 a A 1000 NULL NULL YES BTREE +t1 1 a 1 a A NULL NULL NULL YES BTREE disabled alter table t1 engine=heap; alter table t1 disable keys; Warnings: @@ -715,7 +712,7 @@ t1 1 a 4 d A 4 NULL NULL YES BTREE delete from t1; analyze table t1; Table Op Msg_type Msg_text -test.t1 analyze status OK +test.t1 analyze status Table is already up to date show index from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment t1 1 a 1 a A 0 NULL NULL YES BTREE @@ -800,7 +797,7 @@ CREATE TABLE t1 ( PRIMARY KEY (`_id`), UNIQUE KEY `sequence_name_index` (`name`(50)), KEY (`length_`) -) ENGINE=maria DEFAULT CHARSET=latin1; +) DEFAULT CHARSET=latin1; INSERT INTO t1 VALUES (1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample1',''), (2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample2',''), @@ -825,19 +822,19 @@ _id DELETE FROM t1 WHERE _id < 8; SHOW TABLE STATUS LIKE 't1'; 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 MARIA 10 Dynamic 2 # # # # 140 # # # # # # +t1 MARIA 10 Paged 2 # # # # 0 # # # # # # CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text test.t1 check status OK OPTIMIZE TABLE t1; Table Op Msg_type Msg_text -test.t1 optimize status OK +test.t1 optimize status Table is already up to date CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text test.t1 check status OK SHOW TABLE STATUS LIKE 't1'; 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 MARIA 10 Dynamic 2 # # # # 0 # # # # # # +t1 MARIA 10 Paged 2 # # # # 0 # # # # # # SELECT _id FROM t1; _id 8 @@ -859,7 +856,7 @@ CREATE TABLE t1 ( PRIMARY KEY (`_id`), UNIQUE KEY `sequence_name_index` (`name`(50)), KEY (`length_`) -) ENGINE=maria DEFAULT CHARSET=latin1; +) DEFAULT CHARSET=latin1; INSERT INTO t1 VALUES (1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample1',''), (2,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample2',''), @@ -884,7 +881,7 @@ _id DELETE FROM t1 WHERE _id < 8; SHOW TABLE STATUS LIKE 't1'; 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 MARIA 10 Dynamic 2 # # # # 140 # # # # # # +t1 MARIA 10 Paged 2 # # # # 0 # # # # # # CHECK TABLE t1 EXTENDED; Table Op Msg_type Msg_text test.t1 check status OK @@ -896,7 +893,7 @@ Table Op Msg_type Msg_text test.t1 check status OK SHOW TABLE STATUS LIKE 't1'; 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 MARIA 10 Dynamic 2 # # # # 140 # # # # # # +t1 MARIA 10 Paged 2 # # # # 0 # # # # # # SELECT _id FROM t1; _id 8 @@ -1503,7 +1500,7 @@ create table t1 (v varchar(65535)); ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs set @save_concurrent_insert=@@concurrent_insert; set global concurrent_insert=1; -create table t1 (a int); +create table t1 (a int) ROW_FORMAT=FIXED; insert into t1 values (1),(2),(3),(4),(5); lock table t1 read local; insert into t1 values(6),(7); @@ -1530,7 +1527,7 @@ check table t1; Table Op Msg_type Msg_text test.t1 check status OK drop table t1; -create table t1 (a int, b varchar(30) default "hello"); +create table t1 (a int, b varchar(30) default "hello") ROW_FORMAT=DYNAMIC; insert into t1 (a) values (1),(2),(3),(4),(5); lock table t1 read local; insert into t1 (a) values(6),(7); @@ -1570,7 +1567,7 @@ alter table t1 disable keys; alter table t1 enable keys; show keys from t1; Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment -t1 1 a 1 a A 8 NULL NULL YES BTREE +t1 1 a 1 a A 8 NULL NULL YES BTREE disabled drop table t1; show create table t1; show create table t1; @@ -1592,13 +1589,12 @@ create table t3 (c1 int) pack_keys=default; create table t4 (c1 int) pack_keys=2; ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2' at line 1 drop table t1, t2, t3; -End of 5.0 tests create table t1 (a int not null, key `a` (a) key_block_size=1024); show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, - KEY `a` (`a`) KEY_BLOCK_SIZE=1024 + KEY `a` (`a`) KEY_BLOCK_SIZE=8192 ) ENGINE=MARIA DEFAULT CHARSET=latin1 drop table t1; create table t1 (a int not null, key `a` (a) key_block_size=2048); @@ -1606,7 +1602,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, - KEY `a` (`a`) KEY_BLOCK_SIZE=2048 + KEY `a` (`a`) KEY_BLOCK_SIZE=8192 ) ENGINE=MARIA DEFAULT CHARSET=latin1 drop table t1; create table t1 (a varchar(2048), key `a` (a)); @@ -1626,7 +1622,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` varchar(2048) DEFAULT NULL, - KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=4096 + KEY `a` (`a`(1000)) KEY_BLOCK_SIZE=8192 ) ENGINE=MARIA DEFAULT CHARSET=latin1 drop table t1; create table t1 (a int not null, b varchar(2048), key (a), key(b)) key_block_size=1024; @@ -1637,8 +1633,8 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` varchar(2048) DEFAULT NULL, - KEY `a` (`a`), - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096 + KEY `a` (`a`) KEY_BLOCK_SIZE=8192, + KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192 ) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=1024 alter table t1 key_block_size=2048; show create table t1; @@ -1646,8 +1642,8 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` varchar(2048) DEFAULT NULL, - KEY `a` (`a`) KEY_BLOCK_SIZE=1024, - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096 + KEY `a` (`a`) KEY_BLOCK_SIZE=8192, + KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192 ) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048 alter table t1 add c int, add key (c); show create table t1; @@ -1656,9 +1652,9 @@ t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` varchar(2048) DEFAULT NULL, `c` int(11) DEFAULT NULL, - KEY `a` (`a`) KEY_BLOCK_SIZE=1024, - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096, - KEY `c` (`c`) + KEY `a` (`a`) KEY_BLOCK_SIZE=8192, + KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192, + KEY `c` (`c`) KEY_BLOCK_SIZE=8192 ) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=2048 alter table t1 key_block_size=0; alter table t1 add d int, add key (d); @@ -1669,9 +1665,9 @@ t1 CREATE TABLE `t1` ( `b` varchar(2048) DEFAULT NULL, `c` int(11) DEFAULT NULL, `d` int(11) DEFAULT NULL, - KEY `a` (`a`) KEY_BLOCK_SIZE=1024, - KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=4096, - KEY `c` (`c`) KEY_BLOCK_SIZE=2048, + KEY `a` (`a`) KEY_BLOCK_SIZE=8192, + KEY `b` (`b`(1000)) KEY_BLOCK_SIZE=8192, + KEY `c` (`c`) KEY_BLOCK_SIZE=8192, KEY `d` (`d`) ) ENGINE=MARIA DEFAULT CHARSET=latin1 drop table t1; @@ -1695,7 +1691,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` varchar(2048) DEFAULT NULL, - KEY `a` (`a`) KEY_BLOCK_SIZE=1024, + KEY `a` (`a`), KEY `b` (`b`(1000)) ) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=8192 drop table t1; @@ -1705,7 +1701,7 @@ Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, `b` int(11) DEFAULT NULL, - KEY `a` (`a`) KEY_BLOCK_SIZE=1024, + KEY `a` (`a`) KEY_BLOCK_SIZE=8192, KEY `b` (`b`) KEY_BLOCK_SIZE=8192 ) ENGINE=MARIA DEFAULT CHARSET=latin1 KEY_BLOCK_SIZE=16384 drop table t1; @@ -1714,7 +1710,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, - KEY `a` (`a`) KEY_BLOCK_SIZE=1024 + KEY `a` (`a`) KEY_BLOCK_SIZE=8192 ) ENGINE=MARIA DEFAULT CHARSET=latin1 drop table t1; create table t1 (a varchar(2048), key `a` (a) key_block_size=1000000000000000000); @@ -1732,7 +1728,7 @@ show create table t1; Table Create Table t1 CREATE TABLE `t1` ( `a` int(11) NOT NULL, - KEY `a` (`a`) KEY_BLOCK_SIZE=2048 + KEY `a` (`a`) KEY_BLOCK_SIZE=8192 ) ENGINE=MARIA DEFAULT CHARSET=latin1 drop table t1; create table t1 (a int not null, key key_block_size=1024 (a)); @@ -1784,5 +1780,4 @@ CHECK TABLE t1; Table Op Msg_type Msg_text test.t1 check status OK DROP TABLE t1; -End of 5.1 tests set global storage_engine=MyISAM; diff --git a/mysql-test/t/disabled.def b/mysql-test/t/disabled.def index ed0e665c9ce..e0812f54b4f 100644 --- a/mysql-test/t/disabled.def +++ b/mysql-test/t/disabled.def @@ -39,5 +39,4 @@ mysql_upgrade : Bug#25074 mysql_upgrade gives inconsisten results plugin : Bug#25659 memory leak via "plugins" test rpl_ndb_dd_advance : Bug#25913 rpl_ndb_dd_advance fails randomly ndb_alter_table : Bug##25774 ndb_alter_table.test fails in DBUG_ASSERT() on Linux x64 -maria : Until maria is fully functional ps_maria : Until maria is fully functional diff --git a/mysql-test/t/maria.test b/mysql-test/t/maria.test index 87a38ff60b0..898268c9bb0 100644 --- a/mysql-test/t/maria.test +++ b/mysql-test/t/maria.test @@ -1,6 +1,8 @@ # -# Test bugs in the MARIA code +# Testing of potential probelms in Maria +# This code was initially taken from myisam.test # + -- source include/have_maria.inc let $default=`select @@global.storage_engine`; @@ -48,7 +50,7 @@ while ($1) } SET SQL_WARNINGS=1; --enable_warnings -enable_query_log; +--enable_query_log check table t1; repair table t1; delete from t1 where (a & 1); @@ -404,7 +406,7 @@ check table t1; drop table t1; # -# two bugs in maria-space-stripping feature +# Test space-stripping features # create table t1 ( a text not null, key a (a(20))); insert into t1 values ('aaa '),('aaa'),('aa'); @@ -417,7 +419,7 @@ select concat(a,'.') from t1; drop table t1; # -# Third bug in the same code (BUG#2295) +# More space testing # create table t1(a text not null, b text not null, c text not null, index (a(10),b(10),c(10))); @@ -428,9 +430,9 @@ select * from t1 where a='807780' and b='477' and c='165'; drop table t1; # -# space-stripping in _mi_prefix_search: BUG#5284 +# Space-stripping in prefix_search # -DROP TABLE IF EXISTS t1; + CREATE TABLE t1 (a varchar(150) NOT NULL, KEY (a)); INSERT t1 VALUES ("can \tcan"); INSERT t1 VALUES ("can can"); @@ -442,6 +444,7 @@ DROP TABLE t1; # # Verify blob handling # + create table t1 (a blob); insert into t1 values('a '),('a'); select concat(a,'.') from t1 where a='a'; @@ -458,9 +461,9 @@ create table t1 (a int not null auto_increment primary key, b text not null, uni insert into t1 (b) values ('a'),('b'),('c'); select concat(b,'.') from t1; update t1 set b='b ' where a=2; ---error 1062 +--error 1582 update t1 set b='b ' where a > 1; ---error 1062 +--error 1582 insert into t1 (b) values ('b'); select * from t1; delete from t1 where b='b'; @@ -468,7 +471,7 @@ select a,concat(b,'.') from t1; drop table t1; # -# Test keys with 0 segments. (Bug #3203) +# Test keys with 0 segments # create table t1 (a int not null); create table t2 (a int not null, primary key (a)); @@ -482,7 +485,7 @@ explain select distinct t1.a from t1,t2 order by t2.a; drop table t1,t2; # -# Bug#14616 - Freshly imported table returns error 124 when using LIMIT +# Test freshly imported table and LIMIT # create table t1 ( c1 varchar(32), @@ -494,16 +497,18 @@ select c1 from t1 order by c1 limit 1; drop table t1; # -# Bug #14400 Join could miss concurrently inserted row +# Test join that could miss concurrently inserted row +# Note that for the moment Maria only supports multiple writers if we have +# static or dynamic row format # # Partial key. -create table t1 (a int not null, primary key(a)); -create table t2 (a int not null, b int not null, primary key(a,b)); +create table t1 (a int not null, primary key(a)) ROW_FORMAT=FIXED; +create table t2 (a int not null, b int not null, primary key(a,b)) ROW_FORMAT=FIXED; insert into t1 values (1),(2),(3),(4),(5),(6); insert into t2 values (1,1),(2,1); lock tables t1 read local, t2 read local; select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; -connect (root,localhost,root,,test,$MASTER_MYPORT,master.sock); +connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK); insert into t2 values(2,0); disconnect root; connection default; @@ -511,8 +516,8 @@ select straight_join * from t1,t2 force index (primary) where t1.a=t2.a; drop table t1,t2; # # Full key. -CREATE TABLE t1 (c1 varchar(250) NOT NULL); -CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)); +CREATE TABLE t1 (c1 varchar(250) NOT NULL) ROW_FORMAT=DYNAMIC; +CREATE TABLE t2 (c1 varchar(250) NOT NULL, PRIMARY KEY (c1)) ROW_FORMAT=DYNAMIC; INSERT INTO t1 VALUES ('test000001'), ('test000002'), ('test000003'); INSERT INTO t2 VALUES ('test000002'), ('test000003'), ('test000004'); LOCK TABLES t1 READ LOCAL, t2 READ LOCAL; @@ -527,8 +532,6 @@ SELECT t1.c1 AS t1c1, t2.c1 AS t2c1 FROM t1, t2 WHERE t1.c1 = t2.c1 HAVING t1c1 != t2c1; DROP TABLE t1,t2; -# End of 4.0 tests - # # Test RTREE index # @@ -566,13 +569,16 @@ insert t1 select * from t2; show keys from t1; alter table t1 enable keys; show keys from t1; +#TODO after we have repair: delete the following --disable-warnings +--disable_warnings alter table t1 engine=heap; +--enable_warnings alter table t1 disable keys; show keys from t1; drop table t1,t2; # -# index search for NULL in blob. Bug #4816 +# Index search for NULL in blob # create table t1 ( a tinytext, b char(1), index idx (a(1),b) ); insert into t1 values (null,''), (null,''); @@ -581,7 +587,7 @@ select count(*) from t1 where a is null; drop table t1; # -# bug9188 - Corruption Can't open file: 'table.MYI' (errno: 145) +# Test corruption Can't open file: 'table.MYI' (errno: 145) # create table t1 (c1 int, c2 varchar(4) not null default '', key(c2(3))) default charset=utf8; @@ -592,9 +598,9 @@ drop table t1; # -# Bug#12296 - CHECKSUM TABLE reports 0 for the table -# This happened if the first record was marked as deleted. +# Test CHECKSUM TABLE # + create table t1 (c1 int); insert into t1 values (1),(2),(3),(4); checksum table t1; @@ -607,7 +613,7 @@ checksum table t2; drop table t1, t2; # -# BUG#12232: New maria_stats_method variable. +# maria_stats_method variable. # show variables like 'maria_stats_method'; @@ -677,7 +683,9 @@ show index from t1; set maria_stats_method=DEFAULT; drop table t1; -# BUG#13814 - key value packed incorrectly for TINYBLOBs +# +# Test key value packing for TINYBLOBs +# create table t1( cip INT NOT NULL, @@ -695,8 +703,9 @@ select * from t1 where bob is null and cip=1; drop table t1; # -# Bug#14980 - COUNT(*) incorrect on MARIA table with certain INDEX +# Test COUNT(*) table with different INDEX # + create table t1 ( id1 int not null auto_increment, id2 int not null default '0', @@ -713,9 +722,9 @@ select count(id1) from t1 where id2 = 10; drop table t1; # -# BUG##20357 - Got error 124 from storage engine using MIN and MAX functions -# in queries +# Test MIN and MAX functions in queries # + CREATE TABLE t1(a TINYINT, KEY(a)); INSERT INTO t1 VALUES(1); SELECT MAX(a) FROM t1 IGNORE INDEX(a); @@ -725,7 +734,7 @@ SELECT MAX(a) FROM t1 IGNORE INDEX(a); DROP TABLE t1; # -# BUG#18036 - update of table joined to self reports table as crashed +# Test update of table joined to self # CREATE TABLE t1(a CHAR(9), b VARCHAR(7)); INSERT INTO t1(a) VALUES('xxxxxxxxx'),('xxxxxxxxx'); @@ -734,7 +743,7 @@ SELECT * FROM t1; DROP TABLE t1; # -# Bug#8283 - OPTIMIZE TABLE causes data loss +# OPTIMIZE TABLE with multiple threads # SET @@maria_repair_threads=2; SHOW VARIABLES LIKE 'maria_repair%'; @@ -756,7 +765,7 @@ CREATE TABLE t1 ( PRIMARY KEY (`_id`), UNIQUE KEY `sequence_name_index` (`name`(50)), KEY (`length_`) -) ENGINE=maria DEFAULT CHARSET=latin1; +) DEFAULT CHARSET=latin1; # INSERT INTO t1 VALUES (1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample1',''), @@ -798,7 +807,7 @@ CREATE TABLE t1 ( PRIMARY KEY (`_id`), UNIQUE KEY `sequence_name_index` (`name`(50)), KEY (`length_`) -) ENGINE=maria DEFAULT CHARSET=latin1; +) DEFAULT CHARSET=latin1; # INSERT INTO t1 VALUES (1,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,NULL,'sample1',''), @@ -825,6 +834,7 @@ DROP TABLE t1; # SET @@maria_repair_threads=1; SHOW VARIABLES LIKE 'maria_repair%'; + # # Test varchar # @@ -854,7 +864,7 @@ create table t1 (v varchar(65535)); # set @save_concurrent_insert=@@concurrent_insert; set global concurrent_insert=1; -create table t1 (a int); +create table t1 (a int) ROW_FORMAT=FIXED; insert into t1 values (1),(2),(3),(4),(5); lock table t1 read local; connect (con1,localhost,root,,); @@ -879,7 +889,7 @@ drop table t1; disconnect con1; # Same test with dynamic record length -create table t1 (a int, b varchar(30) default "hello"); +create table t1 (a int, b varchar(30) default "hello") ROW_FORMAT=DYNAMIC; insert into t1 (a) values (1),(2),(3),(4),(5); lock table t1 read local; connect (con1,localhost,root,,); @@ -904,9 +914,10 @@ drop table t1; disconnect con1; set global concurrent_insert=@save_concurrent_insert; +# +# ANALYZE TABLE and ALTER TABLE .. ENABLE INDEX +# -# BUG#9622 - ANALYZE TABLE and ALTER TABLE .. ENABLE INDEX produce -# different statistics on the same table with NULL values. create table t1 (a int, key(a)); insert into t1 values (1),(2),(3),(4),(NULL),(NULL),(NULL),(NULL); @@ -920,7 +931,7 @@ show keys from t1; drop table t1; # -# Bug#8706 - temporary table with data directory option fails +# Test temporary table with data directory option # connect (session1,localhost,root,,); connect (session2,localhost,root,,); @@ -957,7 +968,7 @@ drop table t1; --echo End of 4.1 tests # -# Bug#10056 - PACK_KEYS option take values greater than 1 while creating table +# Test if PACK_KEYS option takes values greater than 1 while creating table # create table t1 (c1 int) pack_keys=0; create table t2 (c1 int) pack_keys=1; @@ -966,8 +977,6 @@ create table t3 (c1 int) pack_keys=default; create table t4 (c1 int) pack_keys=2; drop table t1, t2, t3; ---echo End of 5.0 tests - # # Test of key_block_size # @@ -1033,7 +1042,7 @@ create table t1 (a int not null, key `a` key_block_size=1024 (a)); # -# Bug#22119 - Changing MI_KEY_BLOCK_LENGTH makes a wrong myisamchk +# Test of changing MI_KEY_BLOCK_LENGTH # CREATE TABLE t1 ( c1 INT, @@ -1075,8 +1084,6 @@ DELETE FROM t1 WHERE c1 >= 10; CHECK TABLE t1; DROP TABLE t1; ---echo End of 5.1 tests +# End of 5.2 tests eval set global storage_engine=$default; - -# End of 5.2 tests diff --git a/sql/filesort.cc b/sql/filesort.cc index 4b0170a0db0..c8cf084604c 100644 --- a/sql/filesort.cc +++ b/sql/filesort.cc @@ -451,7 +451,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select, ref_pos= ref_buff; quick_select=select && select->quick; record=0; - flag= ((!indexfile && file->ha_table_flags() & HA_REC_NOT_IN_SEQ) + flag= ((!indexfile && (file->ha_table_flags() & HA_REC_NOT_IN_SEQ)) || quick_select); if (indexfile || flag) ref_pos= &file->ref[0]; diff --git a/sql/slave.cc b/sql/slave.cc index 12418915ad7..0514dd6cd05 100644 --- a/sql/slave.cc +++ b/sql/slave.cc @@ -26,6 +26,8 @@ #include <my_dir.h> #include <sql_common.h> +static Log_event* next_event(RELAY_LOG_INFO* rli); + #ifdef HAVE_REPLICATION #include "rpl_tblmap.h" diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc index 5ffd991d58a..1522bf80a28 100644 --- a/storage/maria/ha_maria.cc +++ b/storage/maria/ha_maria.cc @@ -126,7 +126,7 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type, RETURN VALUE 0 OK - !0 error code + # error code */ int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out, @@ -142,6 +142,7 @@ int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out, TABLE_SHARE *share= table_arg->s; uint options= share->db_options_in_use; DBUG_ENTER("table2maria"); + if (!(my_multi_malloc(MYF(MY_WME), recinfo_out, (share->fields * 2 + 2) * sizeof(MARIA_COLUMNDEF), keydef_out, share->keys * sizeof(MARIA_KEYDEF), @@ -268,7 +269,8 @@ int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out, recinfo_pos->type= FIELD_BLOB; else if (found->type() == MYSQL_TYPE_VARCHAR) recinfo_pos->type= FIELD_VARCHAR; - else if (!(options & HA_OPTION_PACK_RECORD)) + else if (!(options & HA_OPTION_PACK_RECORD) || + (found->zero_pack() && (found->flags & PRI_KEY_FLAG))) recinfo_pos->type= FIELD_NORMAL; else if (found->zero_pack()) recinfo_pos->type= FIELD_SKIP_ZERO; @@ -503,6 +505,14 @@ const char *ha_maria::index_type(uint key_number) } +double ha_maria::scan_time() +{ + if (file->s->data_file_type == BLOCK_RECORD) + return ulonglong2double(stats.data_file_length - file->s->block_size) / max(file->s->block_size / 2, IO_SIZE) + 2; + return handler::scan_time(); +} + + #ifdef HAVE_REPLICATION int ha_maria::net_read_dump(NET * net) { @@ -653,7 +663,7 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked) info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST); if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED)) VOID(maria_extra(file, HA_EXTRA_WAIT_LOCK, 0)); - if (!table->s->db_record_offset) + if (file->s->data_file_type != STATIC_RECORD) int_table_flags |= HA_REC_NOT_IN_SEQ; if (file->s->options & (HA_OPTION_CHECKSUM | HA_OPTION_COMPRESS_RECORD)) int_table_flags |= HA_HAS_CHECKSUM; @@ -1028,6 +1038,16 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) param.out_flag= 0; strmov(fixed_name, file->filename); +#ifndef TO_BE_FIXED + /* QQ: Until we have repair for block format, lie that it succeded */ + if (file->s->data_file_type == BLOCK_RECORD) + { + if (optimize) + DBUG_RETURN(analyze(thd, (HA_CHECK_OPT*) 0)); + DBUG_RETURN(HA_ADMIN_OK); + } +#endif + // Don't lock tables if we have used LOCK TABLE if (!thd->locked_tables && maria_lock_database(file, table->s->tmp_table ? F_EXTRA_LCK : F_WRLCK)) @@ -1039,7 +1059,8 @@ int ha_maria::repair(THD *thd, HA_CHECK ¶m, bool do_optimize) if (!do_optimize || ((file->state->del || share->state.split != file->state->records) && (!(param.testflag & T_QUICK) || - !(share->state.changed & STATE_NOT_OPTIMIZED_KEYS)))) + (share->state.changed & (STATE_NOT_OPTIMIZED_KEYS | + STATE_NOT_OPTIMIZED_ROWS))))) { ulonglong key_map= ((local_testflag & T_CREATE_MISSING_KEYS) ? maria_get_mask_all_keys_active(share->base.keys) : @@ -1449,6 +1470,8 @@ void ha_maria::start_bulk_insert(ha_rows rows) can_enable_indexes= maria_is_all_keys_active(file->s->state.key_map, file->s->base.keys); + /* TODO: Remove when we have repair() working */ + can_enable_indexes= 0; if (!(specialflag & SPECIAL_SAFE_MODE)) { @@ -1487,10 +1510,12 @@ void ha_maria::start_bulk_insert(ha_rows rows) int ha_maria::end_bulk_insert() { + int err; + DBUG_ENTER("ha_maria::end_bulk_insert"); maria_end_bulk_insert(file); - int err= maria_extra(file, HA_EXTRA_NO_CACHE, 0); - return err ? err : can_enable_indexes ? - enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE) : 0; + err= maria_extra(file, HA_EXTRA_NO_CACHE, 0); + DBUG_RETURN(err ? err : can_enable_indexes ? + enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE) : 0); } @@ -1660,6 +1685,14 @@ int ha_maria::rnd_init(bool scan) } +int ha_maria::rnd_end() +{ + /* Safe to call even if we don't have started a scan */ + maria_scan_end(file); + return 0; +} + + int ha_maria::rnd_next(byte *buf) { statistic_increment(table->in_use->status_var.ha_read_rnd_next_count, @@ -1825,6 +1858,28 @@ void ha_maria::update_create_info(HA_CREATE_INFO *create_info) } +enum row_type ha_maria::get_row_type() const +{ + switch (file->s->data_file_type) { + case STATIC_RECORD: return ROW_TYPE_FIXED; + case DYNAMIC_RECORD: return ROW_TYPE_DYNAMIC; + case BLOCK_RECORD: return ROW_TYPE_PAGES; + case COMPRESSED_RECORD: return ROW_TYPE_COMPRESSED; + default: return ROW_TYPE_NOT_USED; + } +} + + +static enum data_file_type maria_row_type(HA_CREATE_INFO *info) +{ + switch (info->row_type) { + case ROW_TYPE_FIXED: return STATIC_RECORD; + case ROW_TYPE_DYNAMIC: return DYNAMIC_RECORD; + default: return BLOCK_RECORD; + } +} + + int ha_maria::create(const char *name, register TABLE *table_arg, HA_CREATE_INFO *ha_create_info) { @@ -1838,6 +1893,7 @@ int ha_maria::create(const char *name, register TABLE *table_arg, uint options= share->db_options_in_use; enum data_file_type row_type; DBUG_ENTER("ha_maria::create"); + for (i= 0; i < share->keys; i++) { if (table_arg->key_info[i].flags & HA_USES_PARSER) @@ -1846,6 +1902,7 @@ int ha_maria::create(const char *name, register TABLE *table_arg, break; } } + row_type= maria_row_type(ha_create_info); if ((error= table2maria(table_arg, &keydef, &recinfo, &records))) DBUG_RETURN(error); /* purecov: inspected */ bzero((char*) &create_info, sizeof(create_info)); @@ -1869,19 +1926,6 @@ int ha_maria::create(const char *name, register TABLE *table_arg, if (options & HA_OPTION_DELAY_KEY_WRITE) create_flags|= HA_CREATE_DELAY_KEY_WRITE; - switch (ha_create_info->row_type) { - case ROW_TYPE_FIXED: - row_type= STATIC_RECORD; - break; - case ROW_TYPE_DYNAMIC: - row_type= DYNAMIC_RECORD; - break; - default: - case ROW_TYPE_PAGES: - row_type= BLOCK_RECORD; - break; - } - /* TODO: Check that the following fn_format is really needed */ error= maria_create(fn_format(buff, name, "", "", @@ -2012,6 +2056,7 @@ bool ha_maria::check_if_incompatible_data(HA_CREATE_INFO *info, if (info->auto_increment_value != stats.auto_increment_value || info->data_file_name != data_file_name || info->index_file_name != index_file_name || + maria_row_type(info) != data_file_type || table_changes == IS_EQUAL_NO || table_changes & IS_EQUAL_PACK_LENGTH) // Not implemented yet return COMPATIBLE_DATA_NO; diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h index e856189829e..3f281711253 100644 --- a/storage/maria/ha_maria.h +++ b/storage/maria/ha_maria.h @@ -37,6 +37,7 @@ class ha_maria :public handler MARIA_HA *file; ulonglong int_table_flags; char *data_file_name, *index_file_name; + enum data_file_type data_file_type; bool can_enable_indexes; int repair(THD * thd, HA_CHECK ¶m, bool optimize); @@ -62,7 +63,9 @@ public: { return HA_MAX_KEY_LENGTH; } uint max_supported_key_part_length() const { return HA_MAX_KEY_LENGTH; } + enum row_type get_row_type() const; uint checksum() const; + virtual double scan_time(); virtual bool check_if_locking_is_allowed(uint sql_command, ulong type, TABLE * table, @@ -98,6 +101,7 @@ public: } int ft_read(byte * buf); int rnd_init(bool scan); + int rnd_end(void); int rnd_next(byte * buf); int rnd_pos(byte * buf, byte * pos); int restart_rnd_next(byte * buf, byte * pos); diff --git a/storage/maria/ma_bitmap.c b/storage/maria/ma_bitmap.c index f5cbaefb6bc..b32a2a11bfc 100644 --- a/storage/maria/ma_bitmap.c +++ b/storage/maria/ma_bitmap.c @@ -936,7 +936,7 @@ static my_bool find_mid(MARIA_HA *info, ulong pages, uint position) MARIA_BITMAP_BLOCK *block; block= dynamic_element(&info->bitmap_blocks, position, MARIA_BITMAP_BLOCK *); - while (allocate_full_pages(bitmap, pages, block, 1)) + while (!allocate_full_pages(bitmap, pages, block, 1)) { if (move_to_next_bitmap(info, bitmap)) return 1; @@ -1100,6 +1100,9 @@ static my_bool write_rest_of_head(MARIA_HA *info, uint position, MARIA_SHARE *share= info->s; uint full_page_size= FULL_PAGE_SIZE(share->block_size); MARIA_BITMAP_BLOCK *block; + DBUG_ENTER("write_rest_of_head"); + DBUG_PRINT("enter", ("position: %u rest_length: %lu", position, + rest_length)); if (position == 0) { @@ -1113,8 +1116,8 @@ static my_bool write_rest_of_head(MARIA_HA *info, uint position, pages++; rest_length= 0; } - if (find_mid(info, rest_length / full_page_size, 1)) - return 1; + if (find_mid(info, pages, 1)) + DBUG_RETURN(1); /* Insert empty block after full pages, to allow write_block_record() to split segment into used + free page @@ -1126,7 +1129,7 @@ static my_bool write_rest_of_head(MARIA_HA *info, uint position, if (rest_length) { if (find_tail(info, rest_length, ELEMENTS_RESERVED_FOR_MAIN_PART - 1)) - return 1; + DBUG_RETURN(1); } else { @@ -1137,7 +1140,7 @@ static my_bool write_rest_of_head(MARIA_HA *info, uint position, block->page_count= 0; block->used= 0; } - return 0; + DBUG_RETURN(0); } @@ -1509,6 +1512,9 @@ my_bool _ma_reset_full_page_bits(MARIA_HA *info, MARIA_FILE_BITMAP *bitmap, For the first block (head block) the logic is same as for a tail block + Note that we may have 'filler blocks' that are used to split a block + in half; These can be recognized by that they have page_count == 0. + RETURN 0 ok 1 error (Couldn't write or read bitmap page) @@ -1547,6 +1553,9 @@ my_bool _ma_bitmap_release_unused(MARIA_HA *info, MARIA_BITMAP_BLOCKS *blocks) /* Handle all full pages and tail pages (for head page and blob) */ for (block++; block < end; block++) { + if (!block->page_count) + continue; /* Skip 'filler blocks' */ + if (block->used & BLOCKUSED_TAIL) { if (block->used & BLOCKUSED_USED) diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c index 94209b8e41c..1db372cdffc 100644 --- a/storage/maria/ma_blockrec.c +++ b/storage/maria/ma_blockrec.c @@ -265,6 +265,8 @@ static my_bool delete_head_or_tail(MARIA_HA *info, ulonglong page, uint record_number, my_bool head); static void _ma_print_directory(byte *buff, uint block_size); +static void compact_page(byte *buff, uint block_size, uint rownr, + my_bool extend_block); /**************************************************************************** Initialization @@ -364,7 +366,8 @@ my_bool _ma_init_block_row(MARIA_HA *info) &row->blob_lengths, sizeof(ulong) * info->s->base.blobs, &row->null_field_lengths, (sizeof(uint) * (info->s->base.fields - - info->s->base.blobs)), + info->s->base.blobs + + EXTRA_LENGTH_FIELDS)), &row->tail_positions, (sizeof(MARIA_RECORD_POS) * (info->s->base.blobs + 2)), &new_row->empty_bits_buffer, info->s->base.pack_bytes, @@ -374,7 +377,8 @@ my_bool _ma_init_block_row(MARIA_HA *info) sizeof(ulong) * info->s->base.blobs, &new_row->null_field_lengths, (sizeof(uint) * (info->s->base.fields - - info->s->base.blobs)), + info->s->base.blobs + + EXTRA_LENGTH_FIELDS)), NullS, 0)) DBUG_RETURN(1); if (my_init_dynamic_array(&info->bitmap_blocks, @@ -382,9 +386,18 @@ my_bool _ma_init_block_row(MARIA_HA *info) ELEMENTS_RESERVED_FOR_MAIN_PART, 16)) my_free((char*) &info->bitmap_blocks, MYF(0)); row->base_length= new_row->base_length= info->s->base_length; + + /* + We need to reserve 'EXTRA_LENGTH_FIELDS' number of parts in + null_field_lengths to allow splitting of rows in 'find_where_to_split_row' + */ + + row->null_field_lengths+= EXTRA_LENGTH_FIELDS; + new_row->null_field_lengths+= EXTRA_LENGTH_FIELDS; DBUG_RETURN(0); } + void _ma_end_block_row(MARIA_HA *info) { DBUG_ENTER("_ma_end_block_row"); @@ -443,8 +456,9 @@ static my_bool check_if_zero(byte *pos, uint length) are stored on disk in inverse directory order, which makes life easier for 'compact_page()' and to know if there is free space after any block. - If there is no free entry (entry with postion == 0), then we create - a new one. + If there is no free entry (entry with position == 0), then we create + a new one. If there is not space for the directory entry (because + the last block overlapps with the directory), we compact the page. We will update the offset and the length of the found dir entry to match the position and empty space found. @@ -452,7 +466,7 @@ static my_bool check_if_zero(byte *pos, uint length) buff[EMPTY_SPACE_OFFSET] is NOT updated but left up to the caller RETURN - 0 Error (directory full) + 0 Error (directory full or last block goes over directory) # Pointer to directory entry on page */ @@ -462,6 +476,8 @@ static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr, uint max_entry= (uint) ((uchar*) buff)[DIR_ENTRY_OFFSET]; uint entry, length, first_pos; byte *dir, *end; + DBUG_ENTER("find_free_position"); + DBUG_PRINT("info", ("max_entry: %u", max_entry)); dir= (buff + block_size - DIR_ENTRY_SIZE * max_entry - PAGE_SUFFIX_SIZE); end= buff + block_size - PAGE_SUFFIX_SIZE - DIR_ENTRY_SIZE; @@ -470,7 +486,7 @@ static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr, *empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); /* Search after first empty position */ - for (entry= 0 ; dir <= end ; end-= DIR_ENTRY_SIZE, entry--) + for (entry= 0 ; dir <= end ; end-= DIR_ENTRY_SIZE, entry++) { if (end[0] == 0 && end[1] == 0) /* Found not used entry */ { @@ -479,15 +495,25 @@ static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr, int2store(end + 2, length); *res_rownr= entry; *res_length= length; - return end; + DBUG_RETURN(end); } first_pos= uint2korr(end) + uint2korr(end + 2); } /* No empty places in dir; create a new one */ + dir= end; + /* Check if there is place for the directory entry */ if (max_entry == MAX_ROWS_PER_PAGE) - return 0; + DBUG_RETURN(0); + /* Check if there is place for the directory entry */ + if ((dir - buff) < first_pos) + { + /* Create place for directory */ + compact_page(buff, block_size, max_entry-1, 0); + first_pos= (uint2korr(end + DIR_ENTRY_SIZE) + + uint2korr(end + DIR_ENTRY_SIZE+ 2)); + *empty_space= uint2korr(buff + EMPTY_SPACE_OFFSET); + } buff[DIR_ENTRY_OFFSET]= (byte) (uchar) max_entry+1; - dir-= DIR_ENTRY_SIZE; length= (uint) (dir - buff - first_pos); DBUG_ASSERT(length <= *empty_space - DIR_ENTRY_SIZE); int2store(dir, first_pos); @@ -497,7 +523,7 @@ static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr, /* Reduce directory entry size from free space size */ (*empty_space)-= DIR_ENTRY_SIZE; - return dir; + DBUG_RETURN(dir); } @@ -507,6 +533,17 @@ static byte *find_free_position(byte *buff, uint block_size, uint *res_rownr, /* Calculate length of all the different field parts + + SYNOPSIS + calc_record_size() + info Maria handler + record Row to store + row Store statistics about row here + + NOTES + The statistics is used to find out how much space a row will need + and also where we can split a row when we need to split it into several + extents. */ static void calc_record_size(MARIA_HA *info, const byte *record, @@ -515,7 +552,8 @@ static void calc_record_size(MARIA_HA *info, const byte *record, MARIA_SHARE *share= info->s; byte *field_length_data; MARIA_COLUMNDEF *rec, *end_field; - uint blob_count= 0, *null_field_lengths= row->null_field_lengths; + uint *null_field_lengths= row->null_field_lengths; + ulong *blob_lengths= row->blob_lengths; row->normal_length= row->char_length= row->varchar_length= row->blob_length= row->extents_count= 0; @@ -532,6 +570,8 @@ static void calc_record_size(MARIA_HA *info, const byte *record, { if (rec->type != FIELD_BLOB) *null_field_lengths= 0; + else + *blob_lengths++= 0; continue; } switch ((enum en_fieldtype) rec->type) { @@ -585,32 +625,31 @@ static void calc_record_size(MARIA_HA *info, const byte *record, } case FIELD_VARCHAR: { - uint length; + uint length, field_length_data_length; const byte *field_pos= record + rec->offset; /* 256 is correct as this includes the length byte */ + + field_length_data[0]= field_pos[0]; if (rec->length <= 256) { - if (!(length= (uint) (uchar) *field_pos)) - { - row->empty_bits[rec->empty_pos]|= rec->empty_bit; - *null_field_lengths= 0; - break; - } - *field_length_data++= *field_pos; + length= (uint) (uchar) *field_pos; + field_length_data_length= 1; } else { - if (!(length= uint2korr(field_pos))) - { - row->empty_bits[rec->empty_pos]|= rec->empty_bit; - break; - } - field_length_data[0]= field_pos[0]; + length= uint2korr(field_pos); field_length_data[1]= field_pos[1]; - field_length_data+= 2; + field_length_data_length= 2; + } + *null_field_lengths= length; + if (!length) + { + row->empty_bits[rec->empty_pos]|= rec->empty_bit; + break; } row->varchar_length+= length; *null_field_lengths= length; + field_length_data+= field_length_data_length; break; } case FIELD_BLOB: @@ -618,16 +657,16 @@ static void calc_record_size(MARIA_HA *info, const byte *record, const byte *field_pos= record + rec->offset; uint size_length= rec->length - maria_portable_sizeof_char_ptr; ulong blob_length= _ma_calc_blob_length(size_length, field_pos); + + *blob_lengths++= blob_length; if (!blob_length) - { row->empty_bits[rec->empty_pos]|= rec->empty_bit; - row->blob_lengths[blob_count++]= 0; - break; + else + { + row->blob_length+= blob_length; + memcpy(field_length_data, field_pos, size_length); + field_length_data+= size_length; } - row->blob_length+= blob_length; - row->blob_lengths[blob_count++]= blob_length; - memcpy(field_length_data, field_pos, size_length); - field_length_data+= size_length; break; } default: @@ -662,10 +701,13 @@ static void calc_record_size(MARIA_HA *info, const byte *record, buff Page to compact block_size Size of page recnr Put empty data after this row + extend_block If 1, extend the block at 'rownr' to cover the + whole block. */ -void compact_page(byte *buff, uint block_size, uint rownr) +static void compact_page(byte *buff, uint block_size, uint rownr, + my_bool extend_block) { uint max_entry= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET]; uint page_pos, next_free_pos, start_of_found_block, diff, end_of_found_block; @@ -764,10 +806,12 @@ void compact_page(byte *buff, uint block_size, uint rownr) } else { - /* Extend last block cover whole page */ - uint length= (uint) (dir - buff) - start_of_found_block; - int2store(dir+2, length); - + if (extend_block) + { + /* Extend last block cover whole page */ + uint length= (uint) (dir - buff) - start_of_found_block; + int2store(dir+2, length); + } buff[PAGE_TYPE_OFFSET]&= ~(byte) PAGE_CAN_BE_COMPACTED; } DBUG_EXECUTE("directory", _ma_print_directory(buff, block_size);); @@ -836,9 +880,9 @@ static my_bool get_head_or_tail_page(MARIA_HA *info, res->empty_space= res->length= (block_size - PAGE_OVERHEAD_SIZE); res->data= (buff + PAGE_HEADER_SIZE); res->dir= res->data + res->length; + res->offset= 0; /* Store poistion to the first row */ int2store(res->dir, PAGE_HEADER_SIZE); - res->offset= 0; DBUG_ASSERT(length <= res->length); } else @@ -851,20 +895,22 @@ static my_bool get_head_or_tail_page(MARIA_HA *info, buff, block_size, block_size, 0))) DBUG_RETURN(1); DBUG_ASSERT((res->buff[PAGE_TYPE_OFFSET] & PAGE_TYPE_MASK) == page_type); - if (!(dir= find_free_position(buff, block_size, &res->offset, + if (!(dir= find_free_position(res->buff, block_size, &res->offset, &res->length, &res->empty_space))) + goto crashed; + + if (res->length < length) { - if (res->length < length) + if (res->empty_space + res->length < length) { - if (res->empty_space + res->length < length) - { - compact_page(res->buff, block_size, res->offset); - /* All empty space are now after current position */ - res->length= res->empty_space= uint2korr(dir+2); - } - if (res->length < length) - goto crashed; /* Wrong bitmap information */ + compact_page(res->buff, block_size, res->offset, 1); + /* All empty space are now after current position */ + dir= (res->buff + block_size - DIR_ENTRY_SIZE * res->offset - + PAGE_SUFFIX_SIZE); + res->length= res->empty_space= uint2korr(dir+2); } + if (res->length < length) + goto crashed; /* Wrong bitmap information */ } res->dir= dir; res->data= res->buff + uint2korr(dir); @@ -1040,8 +1086,9 @@ static void store_extent_info(byte *to, block < end_block; block++) { /* The following is only false for marker blocks */ - if (likely(block->used)) + if (likely(block->used & BLOCKUSED_USED)) { + DBUG_ASSERT(block->page_count != 0); int5store(to, block->page); int2store(to + 5, block->page_count); to+= ROW_EXTENT_SIZE; @@ -1052,7 +1099,7 @@ static void store_extent_info(byte *to, } } } - copy_length= (count -1) * ROW_EXTENT_SIZE; + copy_length= (count - 1) * ROW_EXTENT_SIZE; /* In some unlikely cases we have allocated to many blocks. Clear this data. @@ -1062,6 +1109,18 @@ static void store_extent_info(byte *to, /* Write a record to a (set of) pages + + SYNOPSIS + write_block_record() + info Maria handler + record Record we should write + row Statistics about record (calculated by calc_record_size()) + map_blocks On which pages the record should be stored + row_pos Position on head page where to put head part of record + + RETURN + 0 ok + 1 error */ static my_bool write_block_record(MARIA_HA *info, const byte *record, @@ -1089,8 +1148,8 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, head_block= bitmap_blocks->block; block_size= share->block_size; - info->cur_row.lastpos= ma_recordpos(head_block->page, row_pos->offset); page_buff= row_pos->buff; + /* Position on head page where we should store the head part */ data= row_pos->data; end_of_data= data + row_pos->length; @@ -1343,7 +1402,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, if (tmp_data_used) /* non blob data overflows */ { - MARIA_BITMAP_BLOCK *cur_block, *end_block; + MARIA_BITMAP_BLOCK *cur_block, *end_block, *last_head_block; MARIA_BITMAP_BLOCK *head_tail_block= 0; ulong length; ulong data_length= (tmp_data - info->rec_buff); @@ -1361,8 +1420,9 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, - Bitmap code allocated a tail page we don't need. - The last full page allocated needs to be changed to a tail page - (Because we put more data than we thought on the head page) - + (Because we where able to put more data on the head page than + the bitmap allocation assumed) + The reserved pages in bitmap_blocks for the main page has one of the following allocations: - Full pages, with following blocks: @@ -1375,8 +1435,13 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, cur_block= head_block + 1; end_block= head_block + head_block->sub_blocks; + /* + Loop until we have find a block bigger than we need or + we find the the empty page block. + */ while (data_length >= (length= (cur_block->page_count * - FULL_PAGE_SIZE(block_size)))) + FULL_PAGE_SIZE(block_size))) && + cur_block->page_count) { #ifdef SANITY_CHECK if ((cur_block == end_block) || (cur_block->used & BLOCKUSED_BIT)) @@ -1385,10 +1450,16 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, data_length-= length; (cur_block++)->used= BLOCKUSED_USED; } + last_head_block= cur_block; if (data_length) { + if (cur_block->page_count == 0) + { + /* Skip empty filler block */ + cur_block++; + } #ifdef SANITY_CHECK - if ((cur_block == end_block)) + if ((cur_block >= end_block)) goto crashed; #endif if (cur_block->used & BLOCKUSED_TAIL) @@ -1412,6 +1483,11 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, cur_block is a full block, followed by an empty and optional tail block. Change cur_block to a tail block or split it into full blocks and tail blocks. + + TODO: + If there is enough space on the following tail block, use + this instead of creating a new tail block. + */ DBUG_ASSERT(cur_block[1].page_count == 0); if (cur_block->page_count == 1) @@ -1425,11 +1501,11 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, DBUG_ASSERT(data_length < length - FULL_PAGE_SIZE(block_size)); DBUG_PRINT("info", ("Splitting blocks into full and tail")); cur_block[1].page= (cur_block->page + cur_block->page_count - 1); - cur_block[1].page_count= 1; - cur_block[1].used= 1; + cur_block[1].page_count= 1; /* Avoid DBUG_ASSERT */ + cur_block[1].used= BLOCKUSED_USED | BLOCKUSED_TAIL; cur_block->page_count--; - cur_block->used= BLOCKUSED_USED | BLOCKUSED_TAIL; - head_tail_block= cur_block + 1; + cur_block->used= BLOCKUSED_USED; + last_head_block= head_tail_block= cur_block+1; } if (end_block[-1].used & BLOCKUSED_TAIL) bitmap_blocks->tail_page_skipped= 1; @@ -1445,7 +1521,7 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, } /* - Write all extents into page or tmp_buff + Write all extents into page or tmp_data Note that we still don't have a correct position for the tail of the non-blob fields. @@ -1460,17 +1536,32 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, byte *extent_data; length= (uint) (data_length % FULL_PAGE_SIZE(block_size)); - if (write_tail(info, head_tail_block, data + data_length - length, + if (write_tail(info, head_tail_block, + info->rec_buff + data_length - length, length)) goto disk_err; tmp_data-= length; /* Remove the tail */ /* Store the tail position for the non-blob fields */ if (head_tail_block == head_block + 1) + { + /* + We had a head block + tail block, which means that the + tail block is the first extent + */ extent_data= row_extents_first_part; + } else + { + /* + We have a head block + some full blocks + tail block + last_head_block is pointing after the last used extent + for the head block. + */ extent_data= row_extents_second_part + - ((head_tail_block - head_block) - 2) * ROW_EXTENT_SIZE; + ((last_head_block - head_block) - 2) * ROW_EXTENT_SIZE; + } + DBUG_ASSERT(uint2korr(extent_data+5) & TAIL_BIT); int5store(extent_data, head_tail_block->page); int2store(extent_data + 5, head_tail_block->page_count); } @@ -1491,9 +1582,12 @@ static my_bool write_block_record(MARIA_HA *info, const byte *record, if (tmp_data_used) { - /* Write data stored in info->rec_buff to pages */ + /* + Write data stored in info->rec_buff to pages + This is the char/varchar data that didn't fit into the head page. + */ DBUG_ASSERT(bitmap_blocks->count != 0); - if (write_full_pages(info, bitmap_blocks->block + 1, info->rec_buff, + if (write_full_pages(info, head_block + 1, info->rec_buff, (ulong) (tmp_data - info->rec_buff))) goto disk_err; } @@ -1566,6 +1660,7 @@ MARIA_RECORD_POS _ma_write_init_block_record(MARIA_HA *info, if (write_block_record(info, record, &info->cur_row, blocks, &row_pos)) DBUG_RETURN(HA_OFFSET_ERROR); /* Error reading bitmap */ DBUG_PRINT("exit", ("Rowid: %lu", (ulong) info->cur_row.lastpos)); + info->s->state.split++; DBUG_RETURN(info->cur_row.lastpos); } @@ -1694,7 +1789,7 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos, empty= empty_pos_after_row(dir) - (offset + length); if (new_row->total_length > length + empty) { - compact_page(buff, info->s->block_size, rownr); + compact_page(buff, info->s->block_size, rownr, 1); org_empty_size= 0; length= uint2korr(dir + 2); } @@ -1729,7 +1824,7 @@ my_bool _ma_update_block_record(MARIA_HA *info, MARIA_RECORD_POS record_pos, (new_row->total_length <= head_length && org_empty_size + head_length >= new_row->total_length))) { - compact_page(buff, info->s->block_size, rownr); + compact_page(buff, info->s->block_size, rownr, 1); org_empty_size= 0; head_length= uint2korr(dir + 2); } @@ -1791,9 +1886,8 @@ static my_bool delete_head_or_tail(MARIA_HA *info, number_of_records= (uint) ((uchar *) buff)[DIR_ENTRY_OFFSET]; #ifdef SANITY_CHECKS if (record_number >= number_of_records || - record_number > MAX_ROWS_PER_PAGE || record_number > ((block_size - LSN_SIZE - PAGE_TYPE_SIZE - 1 - - PAGE_SUFFIX_SIZE) / (DIR_ENTRY_SIZE + MIN_TAIL_SIZE))) + PAGE_SUFFIX_SIZE) / DIR_ENTRY_SIZE)) { DBUG_PRINT("error", ("record_number: %u number_of_records: %u", record_number, number_of_records)); @@ -1888,6 +1982,7 @@ my_bool _ma_delete_block_record(MARIA_HA *info) 1) || delete_tails(info, info->cur_row.tail_positions)) DBUG_RETURN(1); + info->s->state.split--; DBUG_RETURN(_ma_bitmap_free_full_pages(info, info->cur_row.extents, info->cur_row.extents_count)); } @@ -1923,9 +2018,8 @@ static byte *get_record_position(byte *buff, uint block_size, #ifdef SANITY_CHECKS if (record_number >= number_of_records || - record_number > MAX_ROWS_PER_PAGE || record_number > ((block_size - PAGE_HEADER_SIZE - PAGE_SUFFIX_SIZE) / - (DIR_ENTRY_SIZE + MIN_TAIL_SIZE))) + DIR_ENTRY_SIZE)) { DBUG_PRINT("error", ("Wrong row number: record_number: %u number_of_records: %u", @@ -2012,6 +2106,7 @@ static byte *read_next_extent(MARIA_HA *info, MARIA_EXTENT_CURSOR *extent, extent->extent+= ROW_EXTENT_SIZE; extent->page= uint5korr(extent->extent); page_count= uint2korr(extent->extent+ROW_EXTENT_PAGE_SIZE); + DBUG_ASSERT(page_count != 0); extent->tail= page_count & TAIL_BIT; extent->page_count= (page_count & ~TAIL_BIT); extent->first_extent= 0; @@ -2278,9 +2373,8 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record, enum en_fieldtype type= (enum en_fieldtype) rec->type; byte *field_pos= record + rec->offset; /* First check if field is present in record */ - if (record[rec->null_pos] & rec->null_bit) - continue; - else if (info->cur_row.empty_bits[rec->empty_pos] & rec->empty_bit) + if ((record[rec->null_pos] & rec->null_bit) || + (info->cur_row.empty_bits[rec->empty_pos] & rec->empty_bit)) { if (type == FIELD_SKIP_ENDSPACE) bfill(record + rec->offset, rec->length, ' '); @@ -2404,19 +2498,24 @@ int _ma_read_block_record2(MARIA_HA *info, byte *record, if (extent.page_count) goto err; if (extent.extent_count > 1) - if (check_if_zero(extent.extent, + if (check_if_zero(extent.extent + ROW_EXTENT_SIZE, (extent.extent_count-1) * ROW_EXTENT_SIZE)) goto err; } else { DBUG_PRINT("info", ("Row read")); - if (data != end_of_data && (uint) (end_of_data - start_of_data) >= + /* + data should normally point to end_of_date. The only exception is if + the row is very short in which case we allocated 'min_row_length' data + for allowing the row to expand. + */ + if (data != end_of_data && (uint) (end_of_data - start_of_data) > info->s->base.min_row_length) goto err; } - info->update|= HA_STATE_AKTIV; /* We have a aktive record */ + info->update|= HA_STATE_AKTIV; /* We have an active record */ DBUG_RETURN(0); err: @@ -2446,6 +2545,7 @@ int _ma_read_block_record(MARIA_HA *info, byte *record, DBUG_ENTER("_ma_read_block_record"); DBUG_PRINT("enter", ("rowid: %lu", (long) record_pos)); + info->cur_row.lastpos= record_pos; page= ma_recordpos_to_page(record_pos) * block_size; offset= ma_recordpos_to_offset(record_pos); @@ -2514,13 +2614,18 @@ my_bool _ma_cmp_block_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, IMPLEMENTATION We allocate one buffer for the current bitmap and one buffer for the current page + + RETURN + 0 ok + 1 error (couldn't allocate memory or disk error) */ my_bool _ma_scan_init_block_record(MARIA_HA *info) { byte *ptr; + DBUG_ENTER("_ma_scan_init_block_record"); if (!(ptr= (byte *) my_malloc(info->s->block_size * 2, MYF(MY_WME)))) - return (1); + DBUG_RETURN(1); info->scan.bitmap_buff= ptr; info->scan.page_buff= ptr + info->s->block_size; info->scan.bitmap_end= info->scan.bitmap_buff + info->s->bitmap.total_size; @@ -2533,7 +2638,7 @@ my_bool _ma_scan_init_block_record(MARIA_HA *info) We have to flush bitmap as we will read the bitmap from the page cache while scanning rows */ - return _ma_flush_bitmap(info->s); + DBUG_RETURN(_ma_flush_bitmap(info->s)); } @@ -2541,8 +2646,10 @@ my_bool _ma_scan_init_block_record(MARIA_HA *info) void _ma_scan_end_block_record(MARIA_HA *info) { - my_free(info->scan.bitmap_buff, MYF(0)); + DBUG_ENTER("_ma_scan_end_block_record"); + my_free(info->scan.bitmap_buff, MYF(MY_ALLOW_ZERO_PTR)); info->scan.bitmap_buff= 0; + DBUG_VOID_RETURN; } diff --git a/storage/maria/ma_blockrec.h b/storage/maria/ma_blockrec.h index bdb86eb717d..e54ce45114f 100644 --- a/storage/maria/ma_blockrec.h +++ b/storage/maria/ma_blockrec.h @@ -70,7 +70,7 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_ /* Fixed part of Max possible header size; See table in ma_blockrec.c */ #define MAX_FIXED_HEADER_SIZE (FLAG_SIZE + 3 + ROW_EXTENT_SIZE + 3) #define TRANS_MAX_FIXED_HEADER_SIZE (MAX_FIXED_HEADER_SIZE + \ - FLAG_SIZE + TRANSID_SIZE + VERPTR_SIZE + \ + TRANSID_SIZE + VERPTR_SIZE + \ TRANSID_SIZE) /* We use 1 byte in record header to store number of directory entries */ @@ -90,6 +90,7 @@ enum en_page_type { UNALLOCATED_PAGE, HEAD_PAGE, TAIL_PAGE, BLOB_PAGE, MAX_PAGE_ static inline MARIA_RECORD_POS ma_recordpos(ulonglong page, uint offset) { + DBUG_ASSERT(offset <= 255); return (MARIA_RECORD_POS) ((page << 8) | offset); } diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c index f262917b706..a87de2bf9ed 100644 --- a/storage/maria/ma_check.c +++ b/storage/maria/ma_check.c @@ -135,7 +135,9 @@ int maria_chk_status(HA_CHECK *param, register MARIA_HA *info) return 0; } - /* Check delete links */ +/* + Check delete links in row data +*/ int maria_chk_del(HA_CHECK *param, register MARIA_HA *info, uint test_flag) { @@ -146,6 +148,10 @@ int maria_chk_del(HA_CHECK *param, register MARIA_HA *info, uint test_flag) DBUG_ENTER("maria_chk_del"); LINT_INIT(old_link); + + if (info->s->data_file_type == BLOCK_RECORD) + DBUG_RETURN(0); /* No delete links here */ + param->record_checksum=0; delete_link_length=((info->s->options & HA_OPTION_PACK_RECORD) ? 20 : info->s->rec_reflength+1); @@ -2144,6 +2150,7 @@ err: restore_data_file_type(share); share->state.changed|= (STATE_NOT_OPTIMIZED_KEYS | STATE_NOT_SORTED_PAGES | STATE_NOT_ANALYZED); + share->state.changed&= ~STATE_NOT_OPTIMIZED_ROWS; DBUG_RETURN(got_error); } @@ -2919,7 +2926,8 @@ err: } else if (key_map == share->state.key_map) share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS; - share->state.changed|=STATE_NOT_SORTED_PAGES; + share->state.changed|= STATE_NOT_SORTED_PAGES; + share->state.changed&= ~STATE_NOT_OPTIMIZED_ROWS; my_free(sort_param.rec_buff, MYF(MY_ALLOW_ZERO_PTR)); my_free(sort_param.record,MYF(MY_ALLOW_ZERO_PTR)); @@ -3439,7 +3447,8 @@ err: } else if (key_map == share->state.key_map) share->state.changed&= ~STATE_NOT_OPTIMIZED_KEYS; - share->state.changed|=STATE_NOT_SORTED_PAGES; + share->state.changed|= STATE_NOT_SORTED_PAGES; + share->state.changed&= ~STATE_NOT_OPTIMIZED_ROWS; pthread_cond_destroy (&sort_info.cond); pthread_mutex_destroy(&sort_info.mutex); diff --git a/storage/maria/ma_checksum.c b/storage/maria/ma_checksum.c index 140f500e64d..671e2a7358b 100644 --- a/storage/maria/ma_checksum.c +++ b/storage/maria/ma_checksum.c @@ -19,14 +19,13 @@ ha_checksum _ma_checksum(MARIA_HA *info, const byte *record) { - uint i; ha_checksum crc=0; - MARIA_COLUMNDEF *rec=info->s->rec; + MARIA_COLUMNDEF *rec= info->s->rec, *rec_end= rec+ info->s->base.fields; if (info->s->base.null_bytes) crc= my_checksum(crc, record, info->s->base.null_bytes); - for (i=info->s->base.fields ; i-- ; ) + for ( ; rec != rec_end ; rec++) { const byte *pos= record + rec->offset; ulong length; diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c index 2e491448a71..69c18f54910 100644 --- a/storage/maria/ma_create.c +++ b/storage/maria/ma_create.c @@ -43,7 +43,7 @@ int maria_create(const char *name, enum data_file_type record_type, { register uint i,j; File dfile,file; - int errpos,save_errno, create_mode= O_RDWR | O_TRUNC; + int errpos,save_errno, create_mode= O_RDWR | O_TRUNC, res; myf create_flag; uint length,max_key_length,packed,pack_bytes,pointer,real_length_diff, key_length,info_length,key_segs,options,min_key_length_skip, @@ -155,35 +155,41 @@ int maria_create(const char *name, enum data_file_type record_type, type == FIELD_SKIP_ENDSPACE) { max_field_lengths+= rec->length > 255 ? 2 : 1; - min_pack_length++; + if (record_type != BLOCK_RECORD) + min_pack_length++; packed++; } else if (type == FIELD_VARCHAR) { varchar_length+= rec->length-1; /* Used for min_pack_length */ pack_reclength++; - min_pack_length++; + if (record_type != BLOCK_RECORD) + min_pack_length++; max_field_lengths++; packed++; + rec->fill_length= 1; /* We must test for 257 as length includes pack-length */ if (test(rec->length >= 257)) { long_varchar_count++; max_field_lengths++; + rec->fill_length= 2; } } - else if (type != FIELD_SKIP_ZERO) + else if (type == FIELD_SKIP_ZERO) + packed++; + else { - min_pack_length+=rec->length; + if (record_type != BLOCK_RECORD || !rec->null_bit) + min_pack_length+= rec->length; rec->empty_pos= 0; rec->empty_bit= 0; } - else - packed++; } else /* FIELD_NORMAL */ { - min_pack_length+=rec->length; + if (record_type != BLOCK_RECORD || !rec->null_bit) + min_pack_length+= rec->length; if (!rec->null_bit) { share.base.fixed_not_null_fields++; @@ -203,6 +209,8 @@ int maria_create(const char *name, enum data_file_type record_type, if (rec->type == (int) FIELD_SKIP_ZERO && rec->length == 1) { rec->type=(int) FIELD_NORMAL; + rec->empty_pos= 0; + rec->empty_bit= 0; packed--; min_pack_length++; break; @@ -364,7 +372,7 @@ int maria_create(const char *name, enum data_file_type record_type, keyseg->type != HA_KEYTYPE_VARBINARY2) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } } keydef->keysegs+=sp_segs; @@ -373,7 +381,7 @@ int maria_create(const char *name, enum data_file_type record_type, min_key_length_skip+=SPLEN*2*SPDIMS; #else my_errno= HA_ERR_UNSUPPORTED; - goto err; + goto err_no_lock; #endif /*HAVE_SPATIAL*/ } else if (keydef->flag & HA_FULLTEXT) @@ -389,7 +397,7 @@ int maria_create(const char *name, enum data_file_type record_type, keyseg->type != HA_KEYTYPE_VARTEXT2) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } if (!(keyseg->flag & HA_BLOB_PART) && (keyseg->type == HA_KEYTYPE_VARTEXT1 || @@ -514,7 +522,7 @@ int maria_create(const char *name, enum data_file_type record_type, if (keydef->keysegs > HA_MAX_KEY_SEG) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } /* key_segs may be 0 in the case when we only want to be able to @@ -525,10 +533,10 @@ int maria_create(const char *name, enum data_file_type record_type, key_segs) share.state.rec_per_key_part[key_segs-1]=1L; length+=key_length; - if (length >= min(HA_MAX_KEY_BUFF, MARIA_MAX_KEY_LENGTH)) + if (length >= HA_MAX_KEY_BUFF) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } keydef->block_length= maria_block_size; keydef->keylength= (uint16) key_length; @@ -572,7 +580,7 @@ int maria_create(const char *name, enum data_file_type record_type, "indexes and/or unique constraints.", MYF(0), name + dirname_length(name)); my_errno= HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } bmove(share.state.header.file_version,(byte*) maria_file_magic,4); @@ -645,11 +653,16 @@ int maria_create(const char *name, enum data_file_type record_type, share.base.max_data_file_length= (my_off_t) ci->data_file_length; } - share.base.min_block_length= - (share.base.pack_reclength+3 < MARIA_EXTEND_BLOCK_LENGTH && - ! share.base.blobs) ? - max(share.base.pack_reclength,MARIA_MIN_BLOCK_LENGTH) : - MARIA_EXTEND_BLOCK_LENGTH; + if (record_type == BLOCK_RECORD) + share.base.min_block_length= share.base.min_row_length; + else + { + share.base.min_block_length= + (share.base.pack_reclength+3 < MARIA_EXTEND_BLOCK_LENGTH && + ! share.base.blobs) ? + max(share.base.pack_reclength,MARIA_MIN_BLOCK_LENGTH) : + MARIA_EXTEND_BLOCK_LENGTH; + } if (! (flags & HA_DONT_TOUCH_DATA)) share.state.create_time= (long) time((time_t*) 0); @@ -868,17 +881,24 @@ int maria_create(const char *name, enum data_file_type record_type, if (record_type == BLOCK_RECORD) { /* Store columns in a more efficent order */ - MARIA_COLUMNDEF **tmp, **pos; - if (!(tmp= (MARIA_COLUMNDEF**) my_malloc(share.base.fields * + MARIA_COLUMNDEF **col_order, **pos; + if (!(col_order= (MARIA_COLUMNDEF**) my_malloc(share.base.fields * sizeof(MARIA_COLUMNDEF*), MYF(MY_WME)))) goto err; - for (rec= recinfo, pos= tmp ; rec != rec_end ; rec++, pos++) + for (rec= recinfo, pos= col_order ; rec != rec_end ; rec++, pos++) *pos= rec; - qsort(tmp, share.base.fields, sizeof(*tmp), (qsort_cmp) compare_columns); + qsort(col_order, share.base.fields, sizeof(*col_order), + (qsort_cmp) compare_columns); for (i=0 ; i < share.base.fields ; i++) - if (_ma_recinfo_write(file, tmp[i])) + { + if (_ma_recinfo_write(file, col_order[i])) + { + my_free((gptr) col_order, MYF(0)); goto err; + } + } + my_free((gptr) col_order, MYF(0)); } else { @@ -917,8 +937,9 @@ int maria_create(const char *name, enum data_file_type record_type, } errpos=0; pthread_mutex_unlock(&THR_LOCK_maria); + res= 0; if (my_close(file,MYF(0))) - goto err; + res= my_errno; /* RECOVERY TODO Write a log record describing the CREATE operation (just the file @@ -933,10 +954,12 @@ int maria_create(const char *name, enum data_file_type record_type, will clean up the frm, so we needn't write anything to the log. */ my_free((char*) rec_per_key_part,MYF(0)); - DBUG_RETURN(0); + DBUG_RETURN(res); err: pthread_mutex_unlock(&THR_LOCK_maria); + +err_no_lock: save_errno=my_errno; switch (errpos) { case 3: diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c index b576eec5e5e..e06bb454edb 100644 --- a/storage/maria/ma_delete.c +++ b/storage/maria/ma_delete.c @@ -104,7 +104,8 @@ int maria_delete(MARIA_HA *info,const byte *record) info->update= HA_STATE_CHANGED+HA_STATE_DELETED+HA_STATE_ROW_CHANGED; info->state->records--; - + share->state.changed|= STATE_NOT_OPTIMIZED_ROWS; + mi_sizestore(lastpos, info->cur_row.lastpos); VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE)); allow_break(); /* Allow SIGHUP & SIGINT */ diff --git a/storage/maria/ma_delete_all.c b/storage/maria/ma_delete_all.c index 5a5ec98fe06..80022b1ae26 100644 --- a/storage/maria/ma_delete_all.c +++ b/storage/maria/ma_delete_all.c @@ -36,6 +36,7 @@ int maria_delete_all_rows(MARIA_HA *info) goto err; info->state->records=info->state->del=state->split=0; + state->changed= 0; /* File is optimized */ state->dellink = HA_OFFSET_ERROR; state->sortkey= (ushort) ~0; info->state->key_file_length=share->base.keystart; diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c index d654d5b2656..e461735f053 100644 --- a/storage/maria/ma_extra.c +++ b/storage/maria/ma_extra.c @@ -44,6 +44,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, int error=0; ulong cache_size; MARIA_SHARE *share=info->s; + my_bool block_records= share->data_file_type == BLOCK_RECORD; + DBUG_ENTER("maria_extra"); DBUG_PRINT("enter",("function: %d",(int) function)); @@ -64,6 +66,9 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, HA_STATE_PREV_FOUND); break; case HA_EXTRA_CACHE: + if (block_records) + break; /* Not supported */ + if (info->lock_type == F_UNLCK && (share->options & HA_OPTION_PACK_RECORD)) { @@ -127,9 +132,11 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, case HA_EXTRA_WRITE_CACHE: if (info->lock_type == F_UNLCK) { - error=1; /* Not possibly if not locked */ + error=1; /* Not possibly if not locked */ break; } + if (block_records) + break; /* Not supported */ cache_size= (extra_arg ? *(ulong*) extra_arg : my_default_record_cache_size); @@ -353,6 +360,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, break; case HA_EXTRA_MMAP: #ifdef HAVE_MMAP + if (block_records) + break; /* Not supported */ pthread_mutex_lock(&share->intern_lock); /* Memory map the data file if it is not already mapped and if there @@ -394,9 +403,11 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function, /* - Start/Stop Inserting Duplicates Into a Table, WL#1648. - */ -static void maria_extra_keyflag(MARIA_HA *info, enum ha_extra_function function) + Start/Stop Inserting Duplicates Into a Table, WL#1648. +*/ + +static void maria_extra_keyflag(MARIA_HA *info, + enum ha_extra_function function) { uint idx; diff --git a/storage/maria/ma_info.c b/storage/maria/ma_info.c index 45a67db605c..366243ccba7 100644 --- a/storage/maria/ma_info.c +++ b/storage/maria/ma_info.c @@ -76,14 +76,14 @@ int maria_status(MARIA_HA *info, register MARIA_INFO *x, uint flag) x->create_time=share->state.create_time; x->reflength= maria_get_pointer_length(share->base.max_data_file_length, maria_data_pointer_size); - x->record_offset= ((share->options & - (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? - 0L : share->base.pack_reclength); + x->record_offset= (info->s->data_file_type == STATIC_RECORD ? + share->base.pack_reclength: 0); x->sortkey= -1; /* No clustering */ x->rec_per_key = share->state.rec_per_key_part; x->key_map = share->state.key_map; x->data_file_name = share->data_file_name; x->index_file_name = share->index_file_name; + x->data_file_type = share->data_file_type; } if ((flag & HA_STATUS_TIME) && !my_fstat(info->dfile,&state,MYF(0))) x->update_time=state.st_mtime; diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c index 5db09cc9618..d171dca8729 100644 --- a/storage/maria/ma_search.c +++ b/storage/maria/ma_search.c @@ -188,7 +188,7 @@ int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo, byte *page, totlength=keyinfo->keylength+(nod_flag=_ma_test_if_nod(page)); start=0; mid=1; save_end=end=(int) ((maria_getint(page)-2-nod_flag)/totlength-1); - DBUG_PRINT("test",("maria_getint: %d end: %d",maria_getint(page),end)); + DBUG_PRINT("test",("page_length: %d end: %d",maria_getint(page),end)); page+=2+nod_flag; while (start != end) @@ -970,12 +970,12 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, { /* Get length of dynamic length key part */ if (from == from_end) { from=page; from_end=page_end; } - if ((length= (*key++ = *from++)) == 255) + if ((length= (uint) (uchar) (*key++ = *from++)) == 255) { if (from == from_end) { from=page; from_end=page_end; } - length= (uint) ((*key++ = *from++)) << 8; + length= ((uint) (uchar) ((*key++ = *from++))) << 8; if (from == from_end) { from=page; from_end=page_end; } - length+= (uint) ((*key++ = *from++)); + length+= (uint) (uchar) ((*key++ = *from++)); } } else @@ -987,6 +987,7 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag, length-=tmp; from=page; from_end=page_end; } + DBUG_ASSERT((int) length >= 0); DBUG_PRINT("info",("key: 0x%lx from: 0x%lx length: %u", (long) key, (long) from, length)); memmove((byte*) key, (byte*) from, (size_t) length); diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c index 4ec5afd35e7..92fa5b63650 100644 --- a/storage/maria/ma_test2.c +++ b/storage/maria/ma_test2.c @@ -814,8 +814,7 @@ int main(int argc, char *argv[]) { ulong blob_length,pos; uchar *ptr; - longget(blob_length,read_record+blob_pos+4); - ptr=(uchar*) blob_length; + memcpy_fixed(&ptr, read_record+blob_pos+4, sizeof(ptr)); longget(blob_length,read_record+blob_pos); for (pos=0 ; pos < blob_length ; pos++) { diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c index ec84eabd421..b05cafb0469 100644 --- a/storage/maria/ma_write.c +++ b/storage/maria/ma_write.c @@ -1066,6 +1066,7 @@ void maria_flush_bulk_insert(MARIA_HA *info, uint inx) void maria_end_bulk_insert(MARIA_HA *info) { + DBUG_ENTER("maria_end_bulk_insert"); if (info->bulk_insert) { uint i; @@ -1079,4 +1080,5 @@ void maria_end_bulk_insert(MARIA_HA *info) my_free((void *)info->bulk_insert, MYF(0)); info->bulk_insert=0; } + DBUG_VOID_RETURN; } diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h index 8f54001ad45..8d4cf75f09d 100644 --- a/storage/maria/maria_def.h +++ b/storage/maria/maria_def.h @@ -441,6 +441,7 @@ struct st_maria_info #define STATE_NOT_ANALYZED 8 #define STATE_NOT_OPTIMIZED_KEYS 16 #define STATE_NOT_SORTED_PAGES 32 +#define STATE_NOT_OPTIMIZED_ROWS 64 /* options to maria_read_cache */ diff --git a/storage/myisam/mi_create.c b/storage/myisam/mi_create.c index e9f5095bdc4..2c2e6b9e101 100644 --- a/storage/myisam/mi_create.c +++ b/storage/myisam/mi_create.c @@ -45,7 +45,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, key_length,info_length,key_segs,options,min_key_length_skip, base_pos,long_varchar_count,varchar_length, max_key_block_length,unique_key_parts,fulltext_keys,offset; - uint aligned_key_start, block_length; + uint aligned_key_start, block_length, res; ulong reclength, real_reclength,min_pack_length; char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr; ulong pack_reclength; @@ -270,7 +270,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, keyseg->type != HA_KEYTYPE_VARBINARY2) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } } keydef->keysegs+=sp_segs; @@ -279,7 +279,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, min_key_length_skip+=SPLEN*2*SPDIMS; #else my_errno= HA_ERR_UNSUPPORTED; - goto err; + goto err_no_lock; #endif /*HAVE_SPATIAL*/ } else if (keydef->flag & HA_FULLTEXT) @@ -295,7 +295,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, keyseg->type != HA_KEYTYPE_VARTEXT2) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } if (!(keyseg->flag & HA_BLOB_PART) && (keyseg->type == HA_KEYTYPE_VARTEXT1 || @@ -420,7 +420,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, if (keydef->keysegs > HA_MAX_KEY_SEG) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } /* key_segs may be 0 in the case when we only want to be able to @@ -445,7 +445,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, length >= HA_MAX_KEY_BUFF) { my_errno=HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } set_if_bigger(max_key_block_length,keydef->block_length); keydef->keylength= (uint16) key_length; @@ -492,7 +492,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, "indexes and/or unique constraints.", MYF(0), name + dirname_length(name)); my_errno= HA_WRONG_CREATE_OPTION; - goto err; + goto err_no_lock; } bmove(share.state.header.file_version,(byte*) myisam_file_magic,4); @@ -814,13 +814,16 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs, } errpos=0; pthread_mutex_unlock(&THR_LOCK_myisam); + res= 0; if (my_close(file,MYF(0))) - goto err; + res= my_errno; my_free((char*) rec_per_key_part,MYF(0)); - DBUG_RETURN(0); + DBUG_RETURN(res); err: pthread_mutex_unlock(&THR_LOCK_myisam); +err_no_lock: + save_errno=my_errno; switch (errpos) { case 3: diff --git a/storage/myisam/mi_test2.c b/storage/myisam/mi_test2.c index 894e48d863c..ef58f8776b5 100644 --- a/storage/myisam/mi_test2.c +++ b/storage/myisam/mi_test2.c @@ -777,8 +777,7 @@ int main(int argc, char *argv[]) { ulong blob_length,pos; uchar *ptr; - longget(blob_length,read_record+blob_pos+4); - ptr=(uchar*) blob_length; + memcpy_fixed(&ptr, read_record+blob_pos+4, sizeof(ptr)); longget(blob_length,read_record+blob_pos); for (pos=0 ; pos < blob_length ; pos++) { |