Commit 5bef77a3 authored by unknown's avatar unknown

Merge bk-internal.mysql.com:/home/bk/mysql-maria

into  mysql.com:/home/my/mysql-maria


BitKeeper/etc/ignore:
  auto-union
BUILD/SETUP.sh:
  Auto merged
mysql-test/lib/init_db.sql:
  Auto merged
mysql-test/lib/mtr_cases.pl:
  Auto merged
mysql-test/lib/mtr_diff.pl:
  Auto merged
mysql-test/lib/mtr_gcov.pl:
  Auto merged
mysql-test/lib/mtr_gprof.pl:
  Auto merged
mysql-test/lib/mtr_im.pl:
  Auto merged
mysql-test/lib/mtr_io.pl:
  Auto merged
mysql-test/lib/mtr_match.pl:
  Auto merged
mysql-test/lib/mtr_misc.pl:
  Auto merged
mysql-test/lib/mtr_process.pl:
  Auto merged
mysql-test/lib/mtr_report.pl:
  Auto merged
mysql-test/lib/mtr_stress.pl:
  Auto merged
mysql-test/lib/mtr_timer.pl:
  Auto merged
mysql-test/lib/mtr_unique.pl:
  Auto merged
mysql-test/mysql-test-run.pl:
  Auto merged
mysql-test/t/disabled.def:
  Auto merged
mysql-test/t/myisam.test:
  Auto merged
mysql-test/t/query_cache_notembedded.test:
  Auto merged
sql/filesort.cc:
  Auto merged
sql/handler.cc:
  Auto merged
sql/slave.cc:
  Auto merged
sql/slave.h:
  Auto merged
sql/sql_table.cc:
  Auto merged
storage/maria/ha_maria.h:
  Auto merged
storage/maria/ma_bitmap.c:
  Auto merged
storage/maria/ma_blockrec.c:
  Auto merged
storage/maria/ma_blockrec.h:
  Auto merged
storage/maria/ma_check.c:
  Auto merged
storage/maria/ma_checksum.c:
  Auto merged
storage/maria/ma_create.c:
  Auto merged
storage/maria/ma_delete.c:
  Auto merged
storage/maria/ma_delete_all.c:
  Auto merged
storage/maria/ma_extra.c:
  Auto merged
storage/maria/ma_info.c:
  Auto merged
storage/maria/ma_search.c:
  Auto merged
storage/maria/ma_test2.c:
  Auto merged
storage/maria/ma_write.c:
  Auto merged
storage/maria/maria_def.h:
  Auto merged
storage/myisam/mi_create.c:
  Auto merged
storage/myisam/mi_test2.c:
  Auto merged
sql/share/errmsg.txt:
  Use remote version
mysql-test/include/varchar.inc:
  Manual merge (take changes from remote tree)
storage/maria/ha_maria.cc:
  Manual merge
parents 1a77ebd1 0abffa05
......@@ -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
......
......@@ -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
......
......@@ -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;
......
......@@ -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;
}
}
}
......
......@@ -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;
......@@ -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
#
# 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
......@@ -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];
......
......@@ -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"
......
......@@ -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 &param, 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 &param, 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;
......
......@@ -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 &param, 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);
......
......@@ -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)
......
......@@ -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)))
length= uint2korr(field_pos);
field_length_data[1]= field_pos[1];
field_length_data_length= 2;
}
*null_field_lengths= length;
if (!length)
{
row->empty_bits[rec->empty_pos]|= rec->empty_bit;
break;
}
field_length_data[0]= field_pos[0];
field_length_data[1]= field_pos[1];
field_length_data+= 2;
}
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;
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;
......@@ -763,11 +805,13 @@ void compact_page(byte *buff, uint block_size, uint rownr)
int2store(dir+2, rownr_length);
}
else
{
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,21 +895,23 @@ 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->empty_space + res->length < length)
{
compact_page(res->buff, block_size, res->offset);
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,7 +1420,8 @@ 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:
......@@ -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;
}
......
......@@ -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);
}
......
......@@ -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);
......
......@@ -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;
......
......@@ -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,6 +155,7 @@ int maria_create(const char *name, enum data_file_type record_type,
type == FIELD_SKIP_ENDSPACE)
{
max_field_lengths+= rec->length > 255 ? 2 : 1;
if (record_type != BLOCK_RECORD)
min_pack_length++;
packed++;
}
......@@ -162,28 +163,33 @@ int maria_create(const char *name, enum data_file_type record_type,
{
varchar_length+= rec->length-1; /* Used for min_pack_length */
pack_reclength++;
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;
}
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,18 +881,25 @@ 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
{
for (i=0 ; i < share.base.fields ; i++)
......@@ -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:
......
......@@ -104,6 +104,7 @@ 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));
......
......@@ -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;
......
......@@ -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))
{
......@@ -130,6 +135,8 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
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
......@@ -395,8 +404,10 @@ 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)
*/
static void maria_extra_keyflag(MARIA_HA *info,
enum ha_extra_function function)
{
uint idx;
......
......@@ -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;
......
......@@ -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);
......
......@@ -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++)
{
......
......@@ -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;
}
......@@ -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 */
......
......@@ -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:
......
......@@ -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++)
{
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment