summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore1
-rw-r--r--extra/Makefile.am4
-rw-r--r--include/maria.h39
-rw-r--r--include/my_base.h12
-rw-r--r--include/my_handler.h4
-rw-r--r--mysql-test/include/maria_empty_logs.inc9
-rw-r--r--mysql-test/r/maria-gis-rtree-dynamic.result9
-rw-r--r--mysql-test/r/maria-mvcc.result19
-rw-r--r--mysql-test/r/maria-purge.result1
-rw-r--r--mysql-test/r/maria-recovery-big.result1
-rw-r--r--mysql-test/r/maria-recovery-bitmap.result1
-rw-r--r--mysql-test/r/maria-recovery-rtree-ft.result1
-rw-r--r--mysql-test/r/maria-recovery.result4
-rw-r--r--mysql-test/r/maria.result19
-rw-r--r--mysql-test/r/variables-big.result10
-rw-r--r--mysql-test/suite/rpl/r/rpl_truncate_7ndb_2.result91
-rw-r--r--mysql-test/suite/rpl_ndb/r/rpl_truncate_7ndb_2.result91
-rw-r--r--mysql-test/suite/rpl_ndb/t/rpl_truncate_7ndb_2-master.opt (renamed from mysql-test/suite/rpl/t/rpl_truncate_7ndb_2-master.opt)0
-rw-r--r--mysql-test/suite/rpl_ndb/t/rpl_truncate_7ndb_2.test (renamed from mysql-test/suite/rpl/t/rpl_truncate_7ndb_2.test)2
-rw-r--r--mysql-test/t/maria-gis-rtree-dynamic.test3
-rw-r--r--mysql-test/t/maria-mvcc.test17
-rw-r--r--mysql-test/t/maria-purge.test11
-rw-r--r--mysql-test/t/maria.test24
-rw-r--r--mysql-test/t/variables-big.test6
-rw-r--r--mysys/my_handler.c99
-rw-r--r--mysys/my_lock.c2
-rw-r--r--scripts/Makefile.am3
-rw-r--r--sql/rpl_rli.cc2
-rw-r--r--storage/heap/hp_write.c2
-rw-r--r--storage/maria/Makefile.am2
-rw-r--r--storage/maria/ha_maria.cc65
-rw-r--r--storage/maria/ma_blockrec.c11
-rw-r--r--storage/maria/ma_check.c342
-rw-r--r--storage/maria/ma_close.c2
-rw-r--r--storage/maria/ma_create.c47
-rw-r--r--storage/maria/ma_dbug.c12
-rw-r--r--storage/maria/ma_delete.c428
-rw-r--r--storage/maria/ma_delete_all.c6
-rw-r--r--storage/maria/ma_extra.c18
-rw-r--r--storage/maria/ma_ft_boolean_search.c48
-rw-r--r--storage/maria/ma_ft_nlq_search.c46
-rw-r--r--storage/maria/ma_ft_update.c65
-rw-r--r--storage/maria/ma_ftdefs.h7
-rw-r--r--storage/maria/ma_fulltext.h2
-rw-r--r--storage/maria/ma_init.c2
-rw-r--r--storage/maria/ma_key.c222
-rw-r--r--storage/maria/ma_key_recover.c108
-rw-r--r--storage/maria/ma_key_recover.h6
-rw-r--r--storage/maria/ma_locking.c1
-rw-r--r--storage/maria/ma_loghandler.c19
-rw-r--r--storage/maria/ma_loghandler.h4
-rw-r--r--storage/maria/ma_open.c101
-rw-r--r--storage/maria/ma_page.c176
-rw-r--r--storage/maria/ma_range.c101
-rw-r--r--storage/maria/ma_recovery.c17
-rw-r--r--storage/maria/ma_rename.c3
-rw-r--r--storage/maria/ma_rkey.c167
-rw-r--r--storage/maria/ma_rnext.c55
-rw-r--r--storage/maria/ma_rnext_same.c23
-rw-r--r--storage/maria/ma_rprev.c37
-rw-r--r--storage/maria/ma_rsame.c34
-rw-r--r--storage/maria/ma_rsamepos.c23
-rw-r--r--storage/maria/ma_rt_index.c429
-rw-r--r--storage/maria/ma_rt_index.h28
-rw-r--r--storage/maria/ma_rt_key.c56
-rw-r--r--storage/maria/ma_rt_key.h11
-rw-r--r--storage/maria/ma_rt_mbr.c50
-rw-r--r--storage/maria/ma_rt_mbr.h2
-rw-r--r--storage/maria/ma_rt_split.c41
-rw-r--r--storage/maria/ma_rt_test.c6
-rw-r--r--storage/maria/ma_search.c848
-rw-r--r--storage/maria/ma_sort.c36
-rw-r--r--storage/maria/ma_sp_defs.h5
-rw-r--r--storage/maria/ma_sp_key.c51
-rw-r--r--storage/maria/ma_state.c50
-rw-r--r--storage/maria/ma_state.h3
-rw-r--r--storage/maria/ma_static.c21
-rw-r--r--storage/maria/ma_statrec.c4
-rw-r--r--storage/maria/ma_test1.c2
-rw-r--r--storage/maria/ma_test2.c2
-rw-r--r--storage/maria/ma_unique.c32
-rw-r--r--storage/maria/ma_update.c56
-rw-r--r--storage/maria/ma_write.c449
-rw-r--r--storage/maria/maria_chk.c30
-rw-r--r--storage/maria/maria_def.h217
-rw-r--r--storage/maria/maria_ftdump.c8
-rw-r--r--storage/maria/trnman.c32
-rw-r--r--storage/maria/trnman_public.h1
-rwxr-xr-xstorage/maria/unittest/ma_test_all-t27
-rw-r--r--storage/myisam/mi_check.c8
-rw-r--r--storage/myisam/mi_delete.c5
-rw-r--r--storage/myisam/mi_range.c4
-rw-r--r--storage/myisam/mi_write.c2
-rw-r--r--storage/myisam/rt_index.c5
94 files changed, 3378 insertions, 1830 deletions
diff --git a/.bzrignore b/.bzrignore
index 79c08ee98de..c8ce3fc8db5 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -1448,6 +1448,7 @@ storage/maria/maria_log
storage/maria/maria_log.*
storage/maria/maria_pack
storage/maria/maria_read_log
+storage/maria/tmp
storage/maria/tmp/*
storage/maria/unittest/ma_pagecache_consist_1k-t-big
storage/maria/unittest/ma_pagecache_consist_1kHC-t-big
diff --git a/extra/Makefile.am b/extra/Makefile.am
index bc7289c7f7d..cdce7a170e2 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -22,7 +22,8 @@ BUILT_SOURCES= $(top_builddir)/include/mysqld_error.h \
$(top_builddir)/include/sql_state.h \
$(top_builddir)/include/mysqld_ername.h
pkginclude_HEADERS= $(BUILT_SOURCES)
-DISTCLEANFILES = $(BUILT_SOURCES)
+EXTRA_PROGRAMS = comp_err
+DISTCLEANFILES = $(BUILT_SOURCES) $(EXTRA_PROGRAMS)
SUBDIRS = @yassl_dir@
DIST_SUBDIRS = yassl
@@ -45,7 +46,6 @@ $(top_builddir)/include/sql_state.h: $(top_builddir)/include/mysqld_error.h
bin_PROGRAMS = replace perror resolveip my_print_defaults \
resolve_stack_dump mysql_waitpid innochecksum
noinst_PROGRAMS = charset2html
-EXTRA_PROGRAMS = comp_err
EXTRA_DIST = CMakeLists.txt
perror.o: perror.c
diff --git a/include/maria.h b/include/maria.h
index 57726fb92bf..92f363e673e 100644
--- a/include/maria.h
+++ b/include/maria.h
@@ -160,10 +160,24 @@ struct st_maria_share;
struct st_maria_handler; /* For referense */
typedef struct st_maria_handler MARIA_HA;
struct st_maria_s_param;
+struct st_maria_keydef;
+
+typedef struct st_maria_key /* Internal info about a key */
+{
+ uchar *data; /* Data for key */
+ struct st_maria_keydef *keyinfo; /* Definition for key */
+ uint data_length; /* Length of key data */
+ uint ref_length; /* record ref + transid */
+ uint32 flag; /* 0 or SEARCH_PART_KEY */
+} MARIA_KEY;
+
typedef struct st_maria_keydef /* Key definition with open & info */
{
struct st_maria_share *share; /* Pointer to base (set in open) */
+#ifdef THREAD
+ rw_lock_t root_lock; /* locking of tree */
+#endif
uint16 keysegs; /* Number of key-segment */
uint16 flag; /* NOSAME, PACK_USED */
@@ -180,20 +194,23 @@ typedef struct st_maria_keydef /* Key definition with open & info */
HA_KEYSEG *seg, *end;
struct st_mysql_ftparser *parser; /* Fulltext [pre]parser */
- int (*bin_search)(MARIA_HA *info,
- struct st_maria_keydef *keyinfo, uchar *page,
- const uchar *key, uint key_len, uint comp_flag,
- uchar **ret_pos,
- uchar *buff, my_bool *was_last_key);
- uint(*get_key)(struct st_maria_keydef *keyinfo, uint nod_flag,
- uchar **page, uchar *key);
- int (*pack_key)(struct st_maria_keydef *keyinfo, uint nod_flag,
+ int (*bin_search)(const MARIA_KEY *key, uchar *page,
+ uint32 comp_flag, uchar **ret_pos, uchar *buff,
+ my_bool *was_last_key);
+ uint (*get_key)(MARIA_KEY *key, uint page_flag, uint nod_flag,
+ uchar **page);
+ uchar *(*skip_key)(MARIA_KEY *key, uint page_flag, uint nod_flag,
+ uchar *page);
+ int (*pack_key)(const MARIA_KEY *key, uint nod_flag,
uchar *next_key, uchar *org_key, uchar *prev_key,
- const uchar *key, struct st_maria_s_param *s_temp);
+ struct st_maria_s_param *s_temp);
void (*store_key)(struct st_maria_keydef *keyinfo, uchar *key_pos,
struct st_maria_s_param *s_temp);
- int (*ck_insert)(MARIA_HA *inf, uint k_nr, uchar *k, uint klen);
- int (*ck_delete)(MARIA_HA *inf, uint k_nr, uchar *k, uint klen);
+ my_bool (*ck_insert)(MARIA_HA *inf, MARIA_KEY *key);
+ int (*ck_delete)(MARIA_HA *inf, MARIA_KEY *klen);
+ MARIA_KEY *(*make_key)(MARIA_HA *info, MARIA_KEY *int_key, uint keynr,
+ uchar *key, const uchar *record,
+ MARIA_RECORD_POS filepos, ulonglong trid);
} MARIA_KEYDEF;
diff --git a/include/my_base.h b/include/my_base.h
index da5670644e7..3d7e8e1e60b 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -252,11 +252,13 @@ enum ha_base_keytype {
#define HA_SPATIAL 1024 /* For spatial search */
#define HA_NULL_ARE_EQUAL 2048 /* NULL in key are cmp as equal */
#define HA_GENERATED_KEY 8192 /* Automaticly generated key */
+#define HA_RTREE_INDEX 16384 /* For RTREE search */
/* The combination of the above can be used for key type comparison. */
#define HA_KEYFLAG_MASK (HA_NOSAME | HA_PACK_KEY | HA_AUTO_KEY | \
HA_BINARY_PACK_KEY | HA_FULLTEXT | HA_UNIQUE_CHECK | \
- HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY)
+ HA_SPATIAL | HA_NULL_ARE_EQUAL | HA_GENERATED_KEY | \
+ HA_RTREE_INDEX)
#define HA_KEY_HAS_PART_KEY_SEG 65536 /* Key contains partial segments */
@@ -479,6 +481,14 @@ typedef ulong key_part_map;
#define MBR_DATA 16384
#define SEARCH_NULL_ARE_EQUAL 32768 /* NULL in keys are equal */
#define SEARCH_NULL_ARE_NOT_EQUAL 65536 /* NULL in keys are not equal */
+/* Use this when inserting a key in position order */
+#define SEARCH_INSERT SEARCH_NULL_ARE_NOT_EQUAL*2
+/* Only part of the key is specified while reading */
+#define SEARCH_PART_KEY SEARCH_INSERT*2
+/* Used when user key (key 2) contains transaction id's */
+#define SEARCH_USER_KEY_HAS_TRANSID SEARCH_PART_KEY*2
+/* Used when page key (key 1) contains transaction id's */
+#define SEARCH_PAGE_KEY_HAS_TRANSID SEARCH_USER_KEY_HAS_TRANSID*2
/* bits in opt_flag */
#define QUICK_USED 1
diff --git a/include/my_handler.h b/include/my_handler.h
index c98ed0fd17f..09c7dd96c12 100644
--- a/include/my_handler.h
+++ b/include/my_handler.h
@@ -110,8 +110,8 @@ typedef struct st_HA_KEYSEG /* Key-portion */
extern int ha_compare_text(CHARSET_INFO *, const uchar *, uint,
const uchar *, uint , my_bool, my_bool);
extern int ha_key_cmp(register HA_KEYSEG *keyseg, register const uchar *a,
- register const uchar *b, uint key_length, uint nextflag,
- uint *diff_pos);
+ register const uchar *b, uint key_length,
+ uint32 nextflag, uint *diff_pos);
extern HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, const uchar *a);
extern void my_handler_error_register(void);
diff --git a/mysql-test/include/maria_empty_logs.inc b/mysql-test/include/maria_empty_logs.inc
index 2a4defe7b82..d75fcb45606 100644
--- a/mysql-test/include/maria_empty_logs.inc
+++ b/mysql-test/include/maria_empty_logs.inc
@@ -6,6 +6,8 @@
connection admin;
+let $current_database= `select database()`;
+
-- echo * shut down mysqld, removed logs, restarted it
append_file $MYSQLTEST_VARDIR/tmp/master0.expect;
wait-maria_empty_logs.inc
@@ -69,6 +71,7 @@ EOF
--source include/wait_until_connected_again.inc
connection default;
-# the effect of "use" is lost after a restart so we are back into db "test",
-# because connection 'default' was created with db "test".
-use mysqltest;
+# Restore current database as the effect of "use" was lost after restart
+--disable_query_log
+eval use $current_database;
+--enable_query_log
diff --git a/mysql-test/r/maria-gis-rtree-dynamic.result b/mysql-test/r/maria-gis-rtree-dynamic.result
index 09d93b1e49b..189872e8e13 100644
--- a/mysql-test/r/maria-gis-rtree-dynamic.result
+++ b/mysql-test/r/maria-gis-rtree-dynamic.result
@@ -993,6 +993,9 @@ SET @@RAND_SEED1=178507359, @@RAND_SEED2=332493072;
DELETE FROM t1 ORDER BY RAND() LIMIT 10;
SET @@RAND_SEED1=1034033013, @@RAND_SEED2=558966507;
DELETE FROM t1 ORDER BY RAND() LIMIT 10;
+CHECK TABLE t1 extended;
+Table Op Msg_type Msg_text
+test.t1 check status OK
UPDATE t1 set spatial_point=GeomFromText('POINT(230 9)') where c1 like 'y%';
UPDATE t1 set spatial_point=GeomFromText('POINT(95 35)') where c1 like 'j%';
UPDATE t1 set spatial_point=GeomFromText('POINT(93 99)') where c1 like 'a%';
@@ -1163,6 +1166,9 @@ UPDATE t1 set spatial_point=GeomFromText('POINT(120 137)') where c1 like 'w%';
UPDATE t1 set spatial_point=GeomFromText('POINT(207 147)') where c1 like 'c%';
UPDATE t1 set spatial_point=GeomFromText('POINT(31 125)') where c1 like 'e%';
UPDATE t1 set spatial_point=GeomFromText('POINT(27 36)') where c1 like 'r%';
+check table t1 extended;
+Table Op Msg_type Msg_text
+test.t1 check status OK
INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
('b', 'c', 'e', GeomFromText('POINT(41 137)')),
('p', 'y', 'k', GeomFromText('POINT(50 22)')),
@@ -1264,6 +1270,9 @@ INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
('m', 'i', 'd', GeomFromText('POINT(117 226)')),
('z', 'y', 'y', GeomFromText('POINT(62 81)')),
('g', 'v', 'm', GeomFromText('POINT(66 158)'));
+check table t1 extended;
+Table Op Msg_type Msg_text
+test.t1 check status OK
SET @@RAND_SEED1=481064922, @@RAND_SEED2=438133497;
DELETE FROM t1 ORDER BY RAND() LIMIT 10;
SET @@RAND_SEED1=280535103, @@RAND_SEED2=444518646;
diff --git a/mysql-test/r/maria-mvcc.result b/mysql-test/r/maria-mvcc.result
index b80f07cd9d2..0fec28697c2 100644
--- a/mysql-test/r/maria-mvcc.result
+++ b/mysql-test/r/maria-mvcc.result
@@ -138,3 +138,22 @@ select count(*) from t1;
count(*)
7
drop table t1;
+CREATE TABLE t1 (fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, g GEOMETRY NOT NULL, SPATIAL KEY(g) ) transactional=1 row_format=page engine=maria;
+lock tables t1 write concurrent, t1 as t2 write concurrent;
+insert into t1 (fid,g) values (NULL,GeomFromText('LineString(0 0,1 1)'));
+select fid from t1 as t2;
+fid
+1
+select count(*) from t1 as t2;
+count(*)
+1
+insert into t1 (fid,g) values (NULL,GeomFromText('LineString(0 0,1 1)'));
+select fid from t1 as t2;
+fid
+1
+2
+select count(*) from t1 as t2;
+count(*)
+2
+unlock tables;
+drop table t1;
diff --git a/mysql-test/r/maria-purge.result b/mysql-test/r/maria-purge.result
index 8155bc6ef2a..14cf51948a8 100644
--- a/mysql-test/r/maria-purge.result
+++ b/mysql-test/r/maria-purge.result
@@ -1,3 +1,4 @@
+* shut down mysqld, removed logs, restarted it
set global storage_engine=maria;
set session storage_engine=maria;
set global maria_log_file_size=4294967295;
diff --git a/mysql-test/r/maria-recovery-big.result b/mysql-test/r/maria-recovery-big.result
index 6fe2860382f..ecbcba9ff82 100644
--- a/mysql-test/r/maria-recovery-big.result
+++ b/mysql-test/r/maria-recovery-big.result
@@ -4,7 +4,6 @@ create database mysqltest;
use mysqltest;
* TEST of recovery with blobs
* shut down mysqld, removed logs, restarted it
-use mysqltest;
set @@max_allowed_packet=32000000;
create table t1 (a int, b longtext) engine=maria table_checksum=1;
* copied t1 for feeding_recovery
diff --git a/mysql-test/r/maria-recovery-bitmap.result b/mysql-test/r/maria-recovery-bitmap.result
index 9c8ee173041..01255c2394f 100644
--- a/mysql-test/r/maria-recovery-bitmap.result
+++ b/mysql-test/r/maria-recovery-bitmap.result
@@ -2,7 +2,6 @@ drop database if exists mysqltest;
create database mysqltest;
use mysqltest;
* shut down mysqld, removed logs, restarted it
-use mysqltest;
create table t1 (a varchar(10000)) engine=maria;
* TEST of over-allocated bitmap not flushed by checkpoint
insert into t1 values ("bbbbbbb");
diff --git a/mysql-test/r/maria-recovery-rtree-ft.result b/mysql-test/r/maria-recovery-rtree-ft.result
index dc12d9d6b3e..474d63d5c93 100644
--- a/mysql-test/r/maria-recovery-rtree-ft.result
+++ b/mysql-test/r/maria-recovery-rtree-ft.result
@@ -3,7 +3,6 @@ drop database if exists mysqltest;
create database mysqltest;
use mysqltest;
* shut down mysqld, removed logs, restarted it
-use mysqltest;
CREATE TABLE t1 (
line LINESTRING NOT NULL,
kind ENUM('po', 'pp', 'rr', 'dr', 'rd', 'ts', 'cl') NOT NULL DEFAULT 'po',
diff --git a/mysql-test/r/maria-recovery.result b/mysql-test/r/maria-recovery.result
index c137b2090b7..a46e96b1a9b 100644
--- a/mysql-test/r/maria-recovery.result
+++ b/mysql-test/r/maria-recovery.result
@@ -3,7 +3,6 @@ drop database if exists mysqltest;
create database mysqltest;
use mysqltest;
* shut down mysqld, removed logs, restarted it
-use mysqltest;
create table t1 (a varchar(1000)) engine=maria;
* TEST of REDO: see if recovery can reconstruct if we give it an old table
* copied t1 for feeding_recovery
@@ -121,7 +120,6 @@ a
drop table t1;
* TEST of two REDOs for same page in one REDO group
* shut down mysqld, removed logs, restarted it
-use mysqltest;
CREATE TABLE t1 (
i int,
b blob default NULL,
@@ -154,7 +152,6 @@ LENGTH(b)
drop table t1;
* TEST of INSERT vs state.auto_increment
* shut down mysqld, removed logs, restarted it
-use mysqltest;
CREATE TABLE t1 (
i int auto_increment primary key,
c varchar(6),
@@ -242,7 +239,6 @@ insert into t1 values(null, "f");
drop table t1;
* TEST of removing logs manually
* shut down mysqld, removed logs, restarted it
-use mysqltest;
* TEST of UNDO_ROW_DELETE preserving rowid
create table t1(a int) engine=maria;
insert into t1 values(1),(2);
diff --git a/mysql-test/r/maria.result b/mysql-test/r/maria.result
index 73d0df84d4f..46f6c35ec66 100644
--- a/mysql-test/r/maria.result
+++ b/mysql-test/r/maria.result
@@ -2346,6 +2346,25 @@ t1 CREATE TABLE `t1` (
`c` char(1) DEFAULT NULL
) ENGINE=MARIA DEFAULT CHARSET=latin1 PAGE_CHECKSUM=1 TRANSACTIONAL=1
drop table t1;
+create table t1 (a int, key(a)) transactional=0;
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t1 select NULL from t1;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
+create temporary table t1 (a int, key(a)) transactional=1;
+create temporary table t2 (a int, key(a)) transactional=1;
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select * from t1;
+insert into t1 select NULL from t2;
+select count(*) from t1;
+count(*)
+10
+select count(*) from t1 where a >= 4;
+count(*)
+1
+drop table t1;
create table t1 (i int auto_increment not null primary key) transactional=0;
check table t1 extended;
Table Op Msg_type Msg_text
diff --git a/mysql-test/r/variables-big.result b/mysql-test/r/variables-big.result
index ae1e20109b9..35882c7e284 100644
--- a/mysql-test/r/variables-big.result
+++ b/mysql-test/r/variables-big.result
@@ -1,20 +1,20 @@
set session transaction_prealloc_size=1024*1024*1024*1;
show processlist;
Id User Host db Command Time State Info
-1 root localhost test Query 0 NULL show processlist
+# root localhost test Query 0 NULL show processlist
set session transaction_prealloc_size=1024*1024*1024*2;
show processlist;
Id User Host db Command Time State Info
-1 root localhost test Query 0 NULL show processlist
+# root localhost test Query 0 NULL show processlist
set session transaction_prealloc_size=1024*1024*1024*3;
show processlist;
Id User Host db Command Time State Info
-1 root localhost test Query 0 NULL show processlist
+# root localhost test Query 0 NULL show processlist
set session transaction_prealloc_size=1024*1024*1024*4;
show processlist;
Id User Host db Command Time State Info
-1 root localhost test Query 0 NULL show processlist
+# root localhost test Query 0 NULL show processlist
set session transaction_prealloc_size=1024*1024*1024*5;
show processlist;
Id User Host db Command Time State Info
-1 root localhost test Query 0 NULL show processlist
+# root localhost test Query 0 NULL show processlist
diff --git a/mysql-test/suite/rpl/r/rpl_truncate_7ndb_2.result b/mysql-test/suite/rpl/r/rpl_truncate_7ndb_2.result
deleted file mode 100644
index d43704c2ba7..00000000000
--- a/mysql-test/suite/rpl/r/rpl_truncate_7ndb_2.result
+++ /dev/null
@@ -1,91 +0,0 @@
-stop slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-reset master;
-reset slave;
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
-start slave;
-**** On Master ****
-CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB;
-INSERT INTO t1 VALUES (1,1), (2,2);
-SELECT * FROM t1 ORDER BY a,b;
-a b
-1 1
-2 2
-**** On Slave ****
-INSERT INTO t1 VALUE (3,3);
-SELECT * FROM t1 ORDER BY a,b;
-a b
-1 1
-2 2
-3 3
-**** On Master ****
-TRUNCATE TABLE t1;
-SELECT * FROM t1 ORDER BY a,b;
-a b
-**** On Slave ****
-SELECT * FROM t1 ORDER BY a,b;
-a b
-**** On Master ****
-DROP TABLE t1;
-SHOW BINLOG EVENTS;
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4
-master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
-master-bin.000001 223 Query 1 287 BEGIN
-master-bin.000001 287 Table_map 1 40 table_id: # (test.t1)
-master-bin.000001 327 Table_map 1 98 table_id: # (mysql.ndb_apply_status)
-master-bin.000001 385 Write_rows 1 157 table_id: #
-master-bin.000001 444 Write_rows 1 204 table_id: # flags: STMT_END_F
-master-bin.000001 491 Query 1 556 COMMIT
-master-bin.000001 556 Query 1 636 use `test`; TRUNCATE TABLE t1
-master-bin.000001 636 Query 1 712 use `test`; DROP TABLE t1
-**** On Master ****
-CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB;
-INSERT INTO t1 VALUES (1,1), (2,2);
-SELECT * FROM t1 ORDER BY a,b;
-a b
-1 1
-2 2
-**** On Slave ****
-INSERT INTO t1 VALUE (3,3);
-SELECT * FROM t1 ORDER BY a,b;
-a b
-1 1
-2 2
-3 3
-**** On Master ****
-DELETE FROM t1;
-SELECT * FROM t1 ORDER BY a,b;
-a b
-**** On Slave ****
-SELECT * FROM t1 ORDER BY a,b;
-a b
-3 3
-**** On Master ****
-DROP TABLE t1;
-SHOW BINLOG EVENTS;
-Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4
-master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
-master-bin.000001 223 Query 1 287 BEGIN
-master-bin.000001 287 Table_map 1 40 table_id: # (test.t1)
-master-bin.000001 327 Table_map 1 98 table_id: # (mysql.ndb_apply_status)
-master-bin.000001 385 Write_rows 1 157 table_id: #
-master-bin.000001 444 Write_rows 1 204 table_id: # flags: STMT_END_F
-master-bin.000001 491 Query 1 556 COMMIT
-master-bin.000001 556 Query 1 636 use `test`; TRUNCATE TABLE t1
-master-bin.000001 636 Query 1 712 use `test`; DROP TABLE t1
-master-bin.000001 712 Query 1 829 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
-master-bin.000001 829 Query 1 893 BEGIN
-master-bin.000001 893 Table_map 1 40 table_id: # (test.t1)
-master-bin.000001 933 Table_map 1 98 table_id: # (mysql.ndb_apply_status)
-master-bin.000001 991 Write_rows 1 157 table_id: #
-master-bin.000001 1050 Write_rows 1 204 table_id: # flags: STMT_END_F
-master-bin.000001 1097 Query 1 1162 COMMIT
-master-bin.000001 1162 Query 1 1226 BEGIN
-master-bin.000001 1226 Table_map 1 40 table_id: # (test.t1)
-master-bin.000001 1266 Table_map 1 98 table_id: # (mysql.ndb_apply_status)
-master-bin.000001 1324 Write_rows 1 157 table_id: #
-master-bin.000001 1383 Delete_rows 1 196 table_id: # flags: STMT_END_F
-master-bin.000001 1422 Query 1 1487 COMMIT
-master-bin.000001 1487 Query 1 1563 use `test`; DROP TABLE t1
diff --git a/mysql-test/suite/rpl_ndb/r/rpl_truncate_7ndb_2.result b/mysql-test/suite/rpl_ndb/r/rpl_truncate_7ndb_2.result
new file mode 100644
index 00000000000..d6c57aed41b
--- /dev/null
+++ b/mysql-test/suite/rpl_ndb/r/rpl_truncate_7ndb_2.result
@@ -0,0 +1,91 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+**** On Master ****
+CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB;
+INSERT INTO t1 VALUES (1,1), (2,2);
+SELECT * FROM t1 ORDER BY a,b;
+a b
+1 1
+2 2
+**** On Slave ****
+INSERT INTO t1 VALUE (3,3);
+SELECT * FROM t1 ORDER BY a,b;
+a b
+1 1
+2 2
+3 3
+**** On Master ****
+TRUNCATE TABLE t1;
+SELECT * FROM t1 ORDER BY a,b;
+a b
+**** On Slave ****
+SELECT * FROM t1 ORDER BY a,b;
+a b
+**** On Master ****
+DROP TABLE t1;
+SHOW BINLOG EVENTS;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4
+master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
+master-bin.000001 223 Query 1 287 BEGIN
+master-bin.000001 287 Table_map 1 330 table_id: # (test.t1)
+master-bin.000001 330 Table_map 1 392 table_id: # (mysql.ndb_apply_status)
+master-bin.000001 392 Write_rows 1 451 table_id: #
+master-bin.000001 451 Write_rows 1 498 table_id: # flags: STMT_END_F
+master-bin.000001 498 Query 1 563 COMMIT
+master-bin.000001 563 Query 1 643 use `test`; TRUNCATE TABLE t1
+master-bin.000001 643 Query 1 719 use `test`; DROP TABLE t1
+**** On Master ****
+CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB;
+INSERT INTO t1 VALUES (1,1), (2,2);
+SELECT * FROM t1 ORDER BY a,b;
+a b
+1 1
+2 2
+**** On Slave ****
+INSERT INTO t1 VALUE (3,3);
+SELECT * FROM t1 ORDER BY a,b;
+a b
+1 1
+2 2
+3 3
+**** On Master ****
+DELETE FROM t1;
+SELECT * FROM t1 ORDER BY a,b;
+a b
+**** On Slave ****
+SELECT * FROM t1 ORDER BY a,b;
+a b
+3 3
+**** On Master ****
+DROP TABLE t1;
+SHOW BINLOG EVENTS;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 4 Format_desc 1 106 Server ver: SERVER_VERSION, Binlog ver: 4
+master-bin.000001 106 Query 1 223 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
+master-bin.000001 223 Query 1 287 BEGIN
+master-bin.000001 287 Table_map 1 330 table_id: # (test.t1)
+master-bin.000001 330 Table_map 1 392 table_id: # (mysql.ndb_apply_status)
+master-bin.000001 392 Write_rows 1 451 table_id: #
+master-bin.000001 451 Write_rows 1 498 table_id: # flags: STMT_END_F
+master-bin.000001 498 Query 1 563 COMMIT
+master-bin.000001 563 Query 1 643 use `test`; TRUNCATE TABLE t1
+master-bin.000001 643 Query 1 719 use `test`; DROP TABLE t1
+master-bin.000001 719 Query 1 836 use `test`; CREATE TABLE t1 (a INT PRIMARY KEY, b LONG) ENGINE=NDB
+master-bin.000001 836 Query 1 900 BEGIN
+master-bin.000001 900 Table_map 1 943 table_id: # (test.t1)
+master-bin.000001 943 Table_map 1 1005 table_id: # (mysql.ndb_apply_status)
+master-bin.000001 1005 Write_rows 1 1064 table_id: #
+master-bin.000001 1064 Write_rows 1 1111 table_id: # flags: STMT_END_F
+master-bin.000001 1111 Query 1 1176 COMMIT
+master-bin.000001 1176 Query 1 1240 BEGIN
+master-bin.000001 1240 Table_map 1 1283 table_id: # (test.t1)
+master-bin.000001 1283 Table_map 1 1345 table_id: # (mysql.ndb_apply_status)
+master-bin.000001 1345 Write_rows 1 1404 table_id: #
+master-bin.000001 1404 Delete_rows 1 1443 table_id: # flags: STMT_END_F
+master-bin.000001 1443 Query 1 1508 COMMIT
+master-bin.000001 1508 Query 1 1584 use `test`; DROP TABLE t1
diff --git a/mysql-test/suite/rpl/t/rpl_truncate_7ndb_2-master.opt b/mysql-test/suite/rpl_ndb/t/rpl_truncate_7ndb_2-master.opt
index 01cf3e0520f..01cf3e0520f 100644
--- a/mysql-test/suite/rpl/t/rpl_truncate_7ndb_2-master.opt
+++ b/mysql-test/suite/rpl_ndb/t/rpl_truncate_7ndb_2-master.opt
diff --git a/mysql-test/suite/rpl/t/rpl_truncate_7ndb_2.test b/mysql-test/suite/rpl_ndb/t/rpl_truncate_7ndb_2.test
index 4ee6c98d463..f316fa6d17c 100644
--- a/mysql-test/suite/rpl/t/rpl_truncate_7ndb_2.test
+++ b/mysql-test/suite/rpl_ndb/t/rpl_truncate_7ndb_2.test
@@ -3,4 +3,4 @@
# so slow...
--source include/big_test.inc
---source t/rpl_truncate_7ndb.test
+--source suite/rpl_ndb/t/rpl_truncate_7ndb.test
diff --git a/mysql-test/t/maria-gis-rtree-dynamic.test b/mysql-test/t/maria-gis-rtree-dynamic.test
index 10c03015731..228998c01c3 100644
--- a/mysql-test/t/maria-gis-rtree-dynamic.test
+++ b/mysql-test/t/maria-gis-rtree-dynamic.test
@@ -369,6 +369,7 @@ SET @@RAND_SEED1=178507359, @@RAND_SEED2=332493072;
DELETE FROM t1 ORDER BY RAND() LIMIT 10;
SET @@RAND_SEED1=1034033013, @@RAND_SEED2=558966507;
DELETE FROM t1 ORDER BY RAND() LIMIT 10;
+CHECK TABLE t1 extended;
UPDATE t1 set spatial_point=GeomFromText('POINT(230 9)') where c1 like 'y%';
UPDATE t1 set spatial_point=GeomFromText('POINT(95 35)') where c1 like 'j%';
UPDATE t1 set spatial_point=GeomFromText('POINT(93 99)') where c1 like 'a%';
@@ -539,6 +540,7 @@ UPDATE t1 set spatial_point=GeomFromText('POINT(120 137)') where c1 like 'w%';
UPDATE t1 set spatial_point=GeomFromText('POINT(207 147)') where c1 like 'c%';
UPDATE t1 set spatial_point=GeomFromText('POINT(31 125)') where c1 like 'e%';
UPDATE t1 set spatial_point=GeomFromText('POINT(27 36)') where c1 like 'r%';
+check table t1 extended;
INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
('b', 'c', 'e', GeomFromText('POINT(41 137)')),
('p', 'y', 'k', GeomFromText('POINT(50 22)')),
@@ -640,6 +642,7 @@ INSERT INTO t1 (c2, c1, c3, spatial_point) VALUES
('m', 'i', 'd', GeomFromText('POINT(117 226)')),
('z', 'y', 'y', GeomFromText('POINT(62 81)')),
('g', 'v', 'm', GeomFromText('POINT(66 158)'));
+check table t1 extended;
SET @@RAND_SEED1=481064922, @@RAND_SEED2=438133497;
DELETE FROM t1 ORDER BY RAND() LIMIT 10;
SET @@RAND_SEED1=280535103, @@RAND_SEED2=444518646;
diff --git a/mysql-test/t/maria-mvcc.test b/mysql-test/t/maria-mvcc.test
index f2946d9462f..f1ef9c34474 100644
--- a/mysql-test/t/maria-mvcc.test
+++ b/mysql-test/t/maria-mvcc.test
@@ -85,3 +85,20 @@ select count(*) from t1;
connection default;
drop table t1;
+
+#
+# Test count(*) for not versioned tables
+#
+
+CREATE TABLE t1 (fid INT NOT NULL AUTO_INCREMENT PRIMARY KEY, g GEOMETRY NOT NULL, SPATIAL KEY(g) ) transactional=1 row_format=page engine=maria;
+
+lock tables t1 write concurrent, t1 as t2 write concurrent;
+insert into t1 (fid,g) values (NULL,GeomFromText('LineString(0 0,1 1)'));
+select fid from t1 as t2;
+select count(*) from t1 as t2;
+insert into t1 (fid,g) values (NULL,GeomFromText('LineString(0 0,1 1)'));
+select fid from t1 as t2;
+select count(*) from t1 as t2;
+unlock tables;
+drop table t1;
+
diff --git a/mysql-test/t/maria-purge.test b/mysql-test/t/maria-purge.test
index 025118d3296..48f69e25bd9 100644
--- a/mysql-test/t/maria-purge.test
+++ b/mysql-test/t/maria-purge.test
@@ -1,5 +1,14 @@
-- source include/have_maria.inc
-- source include/big_test.inc
+
+#
+# Empty logs to get log file numbers repeatable
+#
+--enable_reconnect
+connect (admin, localhost, root,,);
+--enable_reconnect
+--source include/maria_empty_logs.inc
+
let $default=`select @@global.storage_engine`;
set global storage_engine=maria;
set session storage_engine=maria;
@@ -54,8 +63,6 @@ SHOW ENGINE maria logs;
insert into t2 select * from t1;
insert into t1 select * from t2;
-
-
eval set global maria_checkpoint_interval=$def_checkinterval;
--replace_regex /Size +[0-9]+ ; .+master-data/master-data/
SHOW ENGINE maria logs;
diff --git a/mysql-test/t/maria.test b/mysql-test/t/maria.test
index e180773869d..e176d7010cc 100644
--- a/mysql-test/t/maria.test
+++ b/mysql-test/t/maria.test
@@ -1519,6 +1519,30 @@ show create table t1;
drop table t1;
#
+# Some tests that have failed with transactional=0
+#
+
+# Testing buik insert
+create table t1 (a int, key(a)) transactional=0;
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t1 select NULL from t1;
+check table t1;
+drop table t1;
+
+#
+# Some tests with temporary tables
+#
+
+create temporary table t1 (a int, key(a)) transactional=1;
+create temporary table t2 (a int, key(a)) transactional=1;
+insert into t1 values (0),(1),(2),(3),(4);
+insert into t2 select * from t1;
+insert into t1 select NULL from t2;
+select count(*) from t1;
+select count(*) from t1 where a >= 4;
+drop table t1;
+
+#
# Test problems with small rows and row_type=page
# Bug 35048 "maria table corruption reported when transactional=0"
#
diff --git a/mysql-test/t/variables-big.test b/mysql-test/t/variables-big.test
index 43326f3d016..2dacabfece7 100644
--- a/mysql-test/t/variables-big.test
+++ b/mysql-test/t/variables-big.test
@@ -9,12 +9,18 @@
#
set session transaction_prealloc_size=1024*1024*1024*1;
+--replace_column 1 #
show processlist;
set session transaction_prealloc_size=1024*1024*1024*2;
+--replace_column 1 #
show processlist;
+--replace_column 1 #
set session transaction_prealloc_size=1024*1024*1024*3;
+--replace_column 1 #
show processlist;
set session transaction_prealloc_size=1024*1024*1024*4;
+--replace_column 1 #
show processlist;
set session transaction_prealloc_size=1024*1024*1024*5;
+--replace_column 1 #
show processlist;
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index 7a3b8269190..7c13149cb27 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -84,13 +84,15 @@ static int compare_bin(const uchar *a, uint a_length,
ha_key_cmp()
keyseg Array of key segments of key to compare
a First key to compare, in format from _mi_pack_key()
- This is normally key specified by user
- b Second key to compare. This is always from a row
- key_length Length of key to compare. This can be shorter than
- a to just compare sub keys
+ This is always from the row
+ b Second key to compare. This is from the row or the user
+ key_length Length of key to compare, based on key b. This can be shorter
+ than b to just compare sub keys
next_flag How keys should be compared
If bit SEARCH_FIND is not set the keys includes the row
position and this should also be compared
+ If SEARCH_PAGE_KEY_HAS_TRANSID is set then 'a' has transid
+ If SEARCH_USER_KEY_HAS_TRANSID is set then 'b' has transid
diff_pos OUT Number of first keypart where values differ, counting
from one.
diff_pos[1] OUT (b + diff_pos[1]) points to first value in tuple b
@@ -120,7 +122,7 @@ static int compare_bin(const uchar *a, uint a_length,
#define FCMP(A,B) ((int) (A) - (int) (B))
int ha_key_cmp(register HA_KEYSEG *keyseg, register const uchar *a,
- register const uchar *b, uint key_length, uint nextflag,
+ register const uchar *b, uint key_length, uint32 nextflag,
uint *diff_pos)
{
int flag;
@@ -152,8 +154,13 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register const uchar *a,
b++;
if (!*a++) /* If key was NULL */
{
- if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
- nextflag=SEARCH_SAME; /* Allow duplicate keys */
+ if ((nextflag & (SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT |
+ SEARCH_NULL_ARE_EQUAL)) ==
+ (SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT))
+ {
+ /* Allow duplicate keys */
+ nextflag= (nextflag & ~(SEARCH_FIND | SEARCH_UPDATE)) | SEARCH_SAME;
+ }
else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
{
/*
@@ -456,18 +463,90 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register const uchar *a,
end:
if (!(nextflag & SEARCH_FIND))
{
+ /*
+ Compare rowid and possible transid
+ This happens in the following case:
+ - INSERT, UPDATE, DELETE when we have not unique keys or
+ are using versioning
+ - SEARCH_NEXT, SEARCH_PREVIOUS when we need to restart search
+
+ The logic for comparing transid are as follows:
+ Keys with have a transid have lowest bit in the rowidt. This means that
+ if we are comparing a key with a transid with another key that doesn't
+ have a tranid, we must reset the lowest bit for both keys.
+
+ When we have transid, the keys are compared in transid order.
+ A key without a transid is regared to be smaller than a key with
+ a transid.
+ */
+
uint i;
+ uchar key_mask, tmp_a, tmp_b;
+
if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
- flag=0;
- for (i=keyseg->length ; i-- > 0 ; )
+ key_mask= (uchar) 255;
+
+ if (!(nextflag & (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID)))
+ {
+ /*
+ Neither key has a trid. Only compare row id's and don't
+ try to store rows in trid order
+ */
+ key_length= keyseg->length;
+ nextflag&= ~SEARCH_INSERT;
+ }
+ else
+ {
+ /*
+ Set key_mask so that we reset the last bit in the rowid before
+ we compare it. This is needed as the lowest bit in the rowid is
+ used to mark if the key has a transid or not.
+ */
+ key_mask= (uchar) 254;
+ if (!test_all_bits(nextflag, (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID)))
+ {
+ /*
+ No transaction id for user key or for key on page
+ Ignore transid as at least one of the keys are visible for all
+ */
+ key_length= keyseg->length;
+ }
+ else
+ {
+ /*
+ Both keys have trids. No need of special handling of incomplete
+ trids below.
+ */
+ nextflag&= ~SEARCH_INSERT;
+ }
+ }
+ DBUG_ASSERT(key_length > 0);
+
+ for (i= key_length-1 ; (int) i-- > 0 ; )
{
if (*a++ != *b++)
{
flag= FCMP(a[-1],b[-1]);
- break;
+ goto found;
}
}
+ tmp_a= *a & key_mask;
+ tmp_b= *b & key_mask;
+ flag= FCMP(tmp_a, tmp_b);
+
+ if (flag == 0 && (nextflag & SEARCH_INSERT))
+ {
+ /*
+ Ensure that on insert we get rows stored in trid order.
+ If one of the parts doesn't have a trid, this should be regarded
+ as smaller than the other
+ */
+ return (nextflag & SEARCH_USER_KEY_HAS_TRANSID) ? -1 : 1;
+ }
+found:
if (nextflag & SEARCH_SAME)
return (flag); /* read same */
if (nextflag & SEARCH_BIGGER)
diff --git a/mysys/my_lock.c b/mysys/my_lock.c
index 200ee7188c9..8450fcfc30a 100644
--- a/mysys/my_lock.c
+++ b/mysys/my_lock.c
@@ -87,7 +87,7 @@ int my_lock(File fd, int locktype, my_off_t start, my_off_t length,
nxLockFlags = NX_RANGE_LOCK_EXCL;
}
- if (MyFlags & MY_DONT_WAIT)
+ if (MyFlags & MY_NO_WAIT)
{
/* Don't block on the lock. */
nxLockFlags |= NX_RANGE_LOCK_TRYLOCK;
diff --git a/scripts/Makefile.am b/scripts/Makefile.am
index ac43bb7b0a4..4c6b77d49e0 100644
--- a/scripts/Makefile.am
+++ b/scripts/Makefile.am
@@ -90,7 +90,8 @@ CLEANFILES = @server_scripts@ \
mysql_find_rows \
mysqlhotcopy \
mysqldumpslow \
- mysqld_multi
+ mysqld_multi \
+ $(EXTRA_PROGRAMS)
pkgplugindir = $(pkglibdir)/plugin
diff --git a/sql/rpl_rli.cc b/sql/rpl_rli.cc
index b6dfd1a1dc8..8a977ad66af 100644
--- a/sql/rpl_rli.cc
+++ b/sql/rpl_rli.cc
@@ -33,10 +33,10 @@ Relay_log_info::Relay_log_info()
:Slave_reporting_capability("SQL"),
no_storage(FALSE), replicate_same_server_id(::replicate_same_server_id),
info_fd(-1), cur_log_fd(-1), save_temporary_tables(0),
+ cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0),
#if HAVE_purify
is_fake(FALSE),
#endif
- cur_log_old_open_count(0), group_relay_log_pos(0), event_relay_log_pos(0),
group_master_log_pos(0), log_space_total(0), ignore_log_space_limit(0),
last_master_timestamp(0), slave_skip_counter(0),
abort_pos_wait(0), slave_run_id(0), sql_thd(0),
diff --git a/storage/heap/hp_write.c b/storage/heap/hp_write.c
index 2abef2d9b43..c6f7e644ed6 100644
--- a/storage/heap/hp_write.c
+++ b/storage/heap/hp_write.c
@@ -109,7 +109,7 @@ int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *record,
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
if (keyinfo->flag & HA_NOSAME)
{
- custom_arg.search_flag= SEARCH_FIND | SEARCH_UPDATE;
+ custom_arg.search_flag= SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT;
keyinfo->rb_tree.flag= TREE_NO_DUPS;
}
else
diff --git a/storage/maria/Makefile.am b/storage/maria/Makefile.am
index 2f16d49ef5b..0f1e482c3a1 100644
--- a/storage/maria/Makefile.am
+++ b/storage/maria/Makefile.am
@@ -136,7 +136,7 @@ libmaria_a_SOURCES = ma_init.c ma_open.c ma_extra.c ma_info.c ma_rkey.c \
ma_checkpoint.c ma_recovery.c ma_commit.c \
ma_pagecrc.c ma_recovery_util.c \
ha_maria.cc
-CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA?
+CLEANFILES = test?.MA? FT?.MA? isam.log ma_test_all ma_rt_test.MA? sp_test.MA? maria_log_control maria_log.0000*
SUFFIXES = .sh
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index 5e9554b19d8..b82e2be4adf 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -2271,10 +2271,17 @@ int ha_maria::external_lock(THD *thd, int lock_type)
else
{
/*
- Copy the current state. This may have been wrong if the same file
- was used several times in the last statement. This should only
- happen for temporary tables.
+ We come here in the following cases:
+ - The table is a temporary table
+ - It's a table which is crash safe but not yet versioned, for
+ example a table with fulltext or rtree keys
+
+ Set the current state to point to save_state so that the
+ block_format code don't count the same record twice.
+ Copy also the current state. This may have been wrong if the
+ same file was used several times in the last statement
*/
+ file->state= file->state_start;
*file->state= file->s->state.state;
}
@@ -2305,7 +2312,13 @@ int ha_maria::external_lock(THD *thd, int lock_type)
if (_ma_reenable_logging_for_table(file, TRUE))
DBUG_RETURN(1);
/** @todo zero file->trn also in commit and rollback */
- file->trn= 0;
+ file->trn= 0; // Safety
+ /*
+ Ensure that file->state points to the current number of rows. This
+ is needed if someone calls maria_info() without first doing an
+ external lock of the table
+ */
+ file->state= &file->s->state.state;
if (trn && trnman_has_locked_tables(trn))
{
if (!trnman_decrement_locked_tables(trn))
@@ -2341,6 +2354,8 @@ int ha_maria::start_stmt(THD *thd, thr_lock_type lock_type)
DBUG_ASSERT(trn); // this may be called only after external_lock()
DBUG_ASSERT(trnman_has_locked_tables(trn));
DBUG_ASSERT(lock_type != TL_UNLOCK);
+ DBUG_ASSERT(file->trn == trn);
+
/*
If there was an implicit commit under this LOCK TABLES by a previous
statement (like a DDL), at least if that previous statement was about a
@@ -2378,6 +2393,7 @@ int ha_maria::implicit_commit(THD *thd)
#endif
TRN *trn;
int error= 0;
+ TABLE *table;
DBUG_ENTER("ha_maria::implicit_commit");
if ((trn= THD_TRN) != NULL)
{
@@ -2398,6 +2414,30 @@ int ha_maria::implicit_commit(THD *thd)
THD_TRN= trn;
if (unlikely(trn == NULL))
error= HA_ERR_OUT_OF_MEM;
+
+ /*
+ Move all locked tables to the new transaction
+ We must do it here as otherwise file->thd and file->state may be
+ stale pointers. We can't do this in start_stmt() as we don't know
+ when we should call _ma_setup_live_state() and in some cases, like
+ in check table, we use the table without calling start_stmt().
+ */
+ for (table=thd->open_tables; table ; table=table->next)
+ {
+ if (table->db_stat && table->file->ht == maria_hton)
+ {
+ MARIA_HA *handler= ((ha_maria*) table->file)->file;
+ if (handler->s->base.born_transactional)
+ {
+ handler->trn= trn;
+ if (handler->s->lock.get_status)
+ {
+ if (_ma_setup_live_state(handler))
+ error= HA_ERR_OUT_OF_MEM;
+ }
+ }
+ }
+ }
}
DBUG_RETURN(error);
}
@@ -2407,8 +2447,25 @@ THR_LOCK_DATA **ha_maria::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
+ /* Test if we can fix test below */
+ DBUG_ASSERT(lock_type != TL_UNLOCK &&
+ (lock_type == TL_IGNORE || file->lock.type == TL_UNLOCK));
if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
+ {
+ /*
+ We have to disable concurrent inserts for INSERT ... SELECT or
+ INSERT/UPDATE/DELETE with sub queries if we are using statement based
+ logging. We take the safe route here and disable this for all commands
+ that only does reading that are not SELECT.
+ */
+ if (lock_type <= TL_READ_HIGH_PRIORITY &&
+ !thd->current_stmt_binlog_row_based &&
+ (thd->lex->sql_command != SQLCOM_SELECT &&
+ thd->lex->sql_command != SQLCOM_LOCK_TABLES) &&
+ mysql_bin_log.is_open())
+ lock_type= TL_READ_NO_INSERT;
file->lock.type= lock_type;
+ }
*to++= &file->lock;
return to;
}
diff --git a/storage/maria/ma_blockrec.c b/storage/maria/ma_blockrec.c
index eaa37b8d016..3ae49c37b48 100644
--- a/storage/maria/ma_blockrec.c
+++ b/storage/maria/ma_blockrec.c
@@ -860,12 +860,12 @@ static my_bool extend_area_on_page(MARIA_HA *info,
}
-/*
- @brief Copy not changed fields from 'from' to 'to'
+/**
+ @brief Copy not changed fields from 'from' to 'to'
- @notes
- Assumption is that most fields are not changed!
- (Which is why we don't test if all bits are set for some bytes in bitmap)
+ @notes
+ Assumption is that most fields are not changed!
+ (Which is why we don't test if all bits are set for some bytes in bitmap)
*/
void copy_not_changed_fields(MARIA_HA *info, MY_BITMAP *changed_fields,
@@ -1362,7 +1362,6 @@ static void calc_record_size(MARIA_HA *info, const uchar *record,
min_read_from If <> 0, remove all trid's that are less than this
*/
-
void _ma_compact_block_page(uchar *buff, uint block_size, uint rownr,
my_bool extend_block, TrID min_read_from,
uint min_row_length)
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index 0844c932ab2..d91a1522055 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -75,8 +75,7 @@ static int sort_key_cmp(MARIA_SORT_PARAM *sort_param, const void *a,
static int sort_maria_ft_key_write(MARIA_SORT_PARAM *sort_param,
const uchar *a);
static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a);
-static my_off_t get_record_for_key(MARIA_HA *info,MARIA_KEYDEF *keyinfo,
- const uchar *key);
+static my_off_t get_record_for_key(MARIA_KEYDEF *keyinfo, const uchar *key);
static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
reg1 SORT_KEY_BLOCKS *key_block,
const uchar *key, my_off_t prev_block);
@@ -252,7 +251,7 @@ int maria_chk_del(HA_CHECK *param, register MARIA_HA *info,
else
{
param->record_checksum+=(ha_checksum) next_link;
- next_link= _ma_rec_pos(info, (uchar *) buff + 1);
+ next_link= _ma_rec_pos(share, (uchar *) buff + 1);
empty+=share->base.pack_reclength;
}
}
@@ -540,7 +539,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
if (chk_index(param,info,keyinfo,share->state.key_root[key],info->buff,
&keys, param->key_crc+key,1))
DBUG_RETURN(-1);
- if(!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL)))
+ if (!(keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL | HA_RTREE_INDEX)))
{
if (keys != share->state.state.records)
{
@@ -597,9 +596,10 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
/* Check that there isn't a row with auto_increment = 0 in the table */
maria_extra(info,HA_EXTRA_KEYREAD,0);
- bzero(info->lastkey,keyinfo->seg->length);
- if (!maria_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
- (key_part_map)1, HA_READ_KEY_EXACT))
+ bzero(info->lastkey_buff, keyinfo->seg->length);
+ if (!maria_rkey(info, info->rec_buff, key,
+ info->lastkey_buff,
+ (key_part_map) 1, HA_READ_KEY_EXACT))
{
/* Don't count this as a real warning, as maria_chk can't correct it */
uint save=param->warning_printed;
@@ -807,17 +807,18 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
ha_checksum *key_checksum, uint level)
{
int flag;
- uint used_length,comp_flag,nod_flag,key_length=0;
- uchar key[HA_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*old_keypos,*endpos;
+ uint used_length,comp_flag,page_flag,nod_flag;
+ uchar *temp_buff, *keypos, *old_keypos, *endpos;
my_off_t next_page,record;
MARIA_SHARE *share= info->s;
char llbuff[22];
uint diff_pos[2];
+ MARIA_KEY tmp_key;
DBUG_ENTER("chk_index");
DBUG_DUMP("buff", buff, _ma_get_page_used(share, buff));
/* TODO: implement appropriate check for RTree keys */
- if (keyinfo->flag & HA_SPATIAL)
+ if (keyinfo->flag & (HA_SPATIAL | HA_RTREE_INDEX))
DBUG_RETURN(0);
if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->block_length)))
@@ -827,11 +828,16 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
if (keyinfo->flag & HA_NOSAME)
- comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* Not real duplicates */
+ {
+ /* Not real duplicates */
+ comp_flag=SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT;
+ }
else
comp_flag=SEARCH_SAME; /* Keys in positionorder */
- _ma_get_used_and_nod(share, buff, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(share, buff);
+ _ma_get_used_and_nod_with_flag(share, page_flag, buff, used_length,
+ nod_flag);
keypos= buff + share->keypage_header + nod_flag;
endpos= buff + used_length;
@@ -845,19 +851,28 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
_ma_check_print_error(param, "Page at %s is not marked for index %u",
llstr(page, llbuff),
(uint) (keyinfo - share->keyinfo));
+ if ((page_flag & KEYPAGE_FLAG_HAS_TRANSID) &&
+ !share->base.born_transactional)
+ {
+ _ma_check_print_error(param,
+ "Page at %s is marked with HAS_TRANSID even if "
+ "table is not transactional",
+ llstr(page, llbuff));
+ }
- if (used_length > keyinfo->block_length)
+ if (used_length > (uint) keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE)
{
- _ma_check_print_error(param,"Wrong pageinfo at page: %s",
- llstr(page,llbuff));
+ _ma_check_print_error(param,"Page at %s has impossible (too big) pagelength",
+ llstr(page,llbuff));
goto err;
}
+
+ info->last_key.keyinfo= tmp_key.keyinfo= keyinfo;
+ tmp_key.data= info->lastkey_buff2;
for ( ;; )
{
if (*_ma_killed_ptr(param))
goto err;
- memcpy(info->lastkey, key, key_length);
- info->lastkey_length= key_length;
if (nod_flag)
{
next_page= _ma_kpos(nod_flag,keypos);
@@ -867,23 +882,39 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
old_keypos=keypos;
if (keypos >= endpos ||
- (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
+ !(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &keypos))
break;
if (keypos > endpos)
{
- _ma_check_print_error(param,"Wrong key block length at page: %s",
+ _ma_check_print_error(param,
+ "Page length and length of keys don't match at "
+ "page: %s",
llstr(page,llbuff));
goto err;
}
+ if (share->data_file_type == BLOCK_RECORD &&
+ !(page_flag & KEYPAGE_FLAG_HAS_TRANSID) &&
+ key_has_transid(tmp_key.data + tmp_key.data_length +
+ share->rec_reflength-1))
+ {
+ _ma_check_print_error(param,
+ "Found key marked for transid on page that is not "
+ "marked for transid at: %s",
+ llstr(page,llbuff));
+ goto err;
+ }
+
if ((*keys)++ &&
- (flag=ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey, (uchar*) key,
- key_length, comp_flag, diff_pos)) >=0)
+ (flag=ha_key_cmp(keyinfo->seg, info->last_key.data, tmp_key.data,
+ tmp_key.data_length + tmp_key.ref_length,
+ (comp_flag | SEARCH_INSERT | (tmp_key.flag >> 1) |
+ info->last_key.flag), diff_pos)) >=0)
{
- DBUG_DUMP("old", info->lastkey, info->lastkey_length);
- DBUG_DUMP("new", key, key_length);
+ DBUG_DUMP_KEY("old", &info->last_key);
+ DBUG_DUMP_KEY("new", &tmp_key);
DBUG_DUMP("new_in_page", old_keypos, (uint) (keypos-old_keypos));
- if (comp_flag & SEARCH_FIND && flag == 0)
+ if ((comp_flag & SEARCH_FIND) && flag == 0)
_ma_check_print_error(param,"Found duplicated key at page %s",
llstr(page,llbuff));
else
@@ -891,19 +922,22 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
llstr(page,llbuff));
goto err;
}
+
if (param->testflag & T_STATISTICS)
{
if (*keys != 1L) /* not first_key */
{
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
- ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey, (uchar*) key,
- USE_WHOLE_KEY, SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
+ ha_key_cmp(keyinfo->seg, (uchar*) info->last_key.data,
+ tmp_key.data, tmp_key.data_length,
+ SEARCH_FIND | SEARCH_NULL_ARE_NOT_EQUAL,
diff_pos);
else if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
{
diff_pos[0]= maria_collect_stats_nonulls_next(keyinfo->seg,
param->notnull_count,
- info->lastkey, key);
+ info->last_key.data,
+ tmp_key.data);
}
param->unique_count[diff_pos[0]-1]++;
}
@@ -911,18 +945,19 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
{
if (param->stats_method == MI_STATS_METHOD_IGNORE_NULLS)
maria_collect_stats_nonulls_first(keyinfo->seg, param->notnull_count,
- key);
+ tmp_key.data);
}
}
- (*key_checksum)+= maria_byte_checksum((uchar*) key,
- key_length- share->rec_reflength);
- record= _ma_dpos(info,0,key+key_length);
+ _ma_copy_key(&info->last_key, &tmp_key);
+ (*key_checksum)+= maria_byte_checksum(tmp_key.data, tmp_key.data_length);
+ record= _ma_row_pos_from_key(&tmp_key);
+
if (keyinfo->flag & HA_FULLTEXT) /* special handling for ft2 */
{
uint off;
int subkeys;
- get_key_full_length_rdonly(off, key);
- subkeys=ft_sintXkorr(key+off);
+ get_key_full_length_rdonly(off, tmp_key.data);
+ subkeys= ft_sintXkorr(tmp_key.data + off);
if (subkeys < 0)
{
ha_rows tmp_keys=0;
@@ -943,7 +978,11 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
/* fall through */
}
- if (record >= share->state.state.data_file_length)
+ if ((share->data_file_type != BLOCK_RECORD &&
+ record >= share->state.state.data_file_length) ||
+ (share->data_file_type == BLOCK_RECORD &&
+ ma_recordpos_to_page(record) * share->base.min_block_length >=
+ share->state.state.data_file_length))
{
#ifndef DBUG_OFF
char llbuff2[22], llbuff3[22];
@@ -952,7 +991,7 @@ static int chk_index(HA_CHECK *param, MARIA_HA *info, MARIA_KEYDEF *keyinfo,
DBUG_PRINT("test",("page: %s record: %s filelength: %s",
llstr(page,llbuff),llstr(record,llbuff2),
llstr(share->state.state.data_file_length,llbuff3)));
- DBUG_DUMP("key",(uchar*) key,key_length);
+ DBUG_DUMP_KEY("key", &tmp_key);
DBUG_DUMP("new_in_page", old_keypos, (uint) (keypos-old_keypos));
goto err;
}
@@ -1054,7 +1093,7 @@ static int check_keys_in_record(HA_CHECK *param, MARIA_HA *info, int extend,
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo;
char llbuff[22+4];
- uint key;
+ uint keynr;
param->tmp_record_checksum+= (ha_checksum) start_recpos;
param->records++;
@@ -1063,17 +1102,18 @@ static int check_keys_in_record(HA_CHECK *param, MARIA_HA *info, int extend,
printf("%s\r", llstr(param->records, llbuff));
VOID(fflush(stdout));
}
-
+
/* Check if keys match the record */
- for (key=0, keyinfo= share->keyinfo; key < share->base.keys;
- key++,keyinfo++)
+ for (keynr=0, keyinfo= share->keyinfo; keynr < share->base.keys;
+ keynr++, keyinfo++)
{
- if (maria_is_key_active(share->state.key_map, key))
+ if (maria_is_key_active(share->state.key_map, keynr))
{
- if(!(keyinfo->flag & HA_FULLTEXT))
+ MARIA_KEY key;
+ if (!(keyinfo->flag & HA_FULLTEXT))
{
- uint key_length= _ma_make_key(info,key,info->lastkey,record,
- start_recpos);
+ (*keyinfo->make_key)(info, &key, keynr, info->lastkey_buff, record,
+ start_recpos, 0);
if (extend)
{
/* We don't need to lock the key tree here as we don't allow
@@ -1081,26 +1121,24 @@ static int check_keys_in_record(HA_CHECK *param, MARIA_HA *info, int extend,
*/
int search_result=
#ifdef HAVE_RTREE_KEYS
- (keyinfo->flag & HA_SPATIAL) ?
- maria_rtree_find_first(info, key, info->lastkey, key_length,
- MBR_EQUAL | MBR_DATA) :
+ (keyinfo->flag & (HA_SPATIAL | HA_RTREE_INDEX)) ?
+ maria_rtree_find_first(info, &key, MBR_EQUAL | MBR_DATA) :
#endif
- _ma_search(info,keyinfo,info->lastkey,key_length,
- SEARCH_SAME, share->state.key_root[key]);
+ _ma_search(info, &key, SEARCH_SAME, share->state.key_root[keynr]);
if (search_result)
{
record_pos_to_txt(info, start_recpos, llbuff);
_ma_check_print_error(param,
"Record at: %14s "
"Can't find key for index: %2d",
- llbuff, key+1);
+ llbuff, keynr+1);
if (param->err_count++ > MAXERR || !(param->testflag & T_VERBOSE))
return -1;
}
}
else
- param->tmp_key_crc[key]+=
- maria_byte_checksum((uchar*) info->lastkey, key_length);
+ param->tmp_key_crc[keynr]+=
+ maria_byte_checksum(key.data, key.data_length);
}
}
}
@@ -2016,7 +2054,8 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
for (key=0 ; key < share->base.keys; key++)
{
if (param->tmp_key_crc[key] != param->key_crc[key] &&
- !(share->keyinfo[key].flag & (HA_FULLTEXT | HA_SPATIAL)))
+ !(share->keyinfo[key].flag &
+ (HA_FULLTEXT | HA_SPATIAL | HA_RTREE_INDEX)))
{
_ma_check_print_error(param,"Checksum for key: %2d doesn't match checksum for records",
key+1);
@@ -2172,7 +2211,8 @@ static my_bool protect_against_repair_crash(MARIA_HA *info,
return TRUE;
}
if (translog_status == TRANSLOG_OK &&
- _ma_update_state_lsns(share, translog_get_horizon(), FALSE, FALSE))
+ _ma_update_state_lsns(share, translog_get_horizon(),
+ share->state.create_trid, FALSE, FALSE))
return TRUE;
if (_ma_sync_table_files(info))
return TRUE;
@@ -2525,10 +2565,12 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
llstr(info->dup_key_pos,llbuff2));
if (param->testflag & T_VERBOSE)
{
- VOID(_ma_make_key(info,(uint) info->errkey,info->lastkey,
- sort_param.record,0L));
- _ma_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey,
- USE_WHOLE_KEY);
+ MARIA_KEY tmp_key;
+ MARIA_KEYDEF *keyinfo= share->keyinfo + info->errkey;
+ (*keyinfo->make_key)(info, &tmp_key, (uint) info->errkey,
+ info->lastkey_buff,
+ sort_param.record, 0L, 0);
+ _ma_print_key(stdout, &tmp_key);
}
sort_info.dupp++;
if ((param->testflag & (T_FORCE_UNIQUENESS|T_QUICK)) == T_QUICK)
@@ -2710,35 +2752,31 @@ err:
static int writekeys(MARIA_SORT_PARAM *sort_param)
{
uint i;
- uchar *key;
MARIA_HA *info= sort_param->sort_info->info;
MARIA_SHARE *share= info->s;
- uchar *buff= sort_param->record;
+ uchar *record= sort_param->record;
+ uchar *key_buff;
my_off_t filepos= sort_param->current_filepos;
+ MARIA_KEY key;
DBUG_ENTER("writekeys");
- key= info->lastkey+share->base.max_key_length;
+ key_buff= info->lastkey_buff+share->base.max_key_length;
+
for (i=0 ; i < share->base.keys ; i++)
{
if (maria_is_key_active(share->state.key_map, i))
{
if (share->keyinfo[i].flag & HA_FULLTEXT )
{
- if (_ma_ft_add(info,i, key,buff,filepos))
- goto err;
- }
-#ifdef HAVE_SPATIAL
- else if (share->keyinfo[i].flag & HA_SPATIAL)
- {
- uint key_length= _ma_make_key(info,i,key,buff,filepos);
- if (maria_rtree_insert(info, i, key, key_length))
+ if (_ma_ft_add(info, i, key_buff, record, filepos))
goto err;
}
-#endif /*HAVE_SPATIAL*/
else
{
- uint key_length= _ma_make_key(info,i,key,buff,filepos);
- if (_ma_ck_write(info,i,key,key_length))
+ if (!(*share->keyinfo[i].make_key)(info, &key, i, key_buff, record,
+ filepos, 0))
+ goto err;
+ if ((*share->keyinfo[i].ck_insert)(info, &key))
goto err;
}
}
@@ -2755,13 +2793,14 @@ static int writekeys(MARIA_SORT_PARAM *sort_param)
{
if (share->keyinfo[i].flag & HA_FULLTEXT)
{
- if (_ma_ft_del(info,i,key,buff,filepos))
+ if (_ma_ft_del(info,i,key_buff,record,filepos))
break;
}
else
{
- uint key_length= _ma_make_key(info,i,key,buff,filepos);
- if (_ma_ck_delete(info,i,key,key_length))
+ (*share->keyinfo[i].make_key)(info, &key, i, key_buff, record,
+ filepos, 0);
+ if (_ma_ck_delete(info, &key))
break;
}
}
@@ -2781,29 +2820,29 @@ int maria_movepoint(register MARIA_HA *info, uchar *record,
MARIA_RECORD_POS oldpos, MARIA_RECORD_POS newpos,
uint prot_key)
{
- register uint i;
- uchar *key;
- uint key_length;
+ uint i;
+ uchar *key_buff;
MARIA_SHARE *share= info->s;
DBUG_ENTER("maria_movepoint");
- key= info->lastkey+share->base.max_key_length;
+ key_buff= info->lastkey_buff + share->base.max_key_length;
for (i=0 ; i < share->base.keys; i++)
{
if (i != prot_key && maria_is_key_active(share->state.key_map, i))
{
- key_length= _ma_make_key(info,i,key,record,oldpos);
- if (share->keyinfo[i].flag & HA_NOSAME)
+ MARIA_KEY key;
+ (*share->keyinfo[i].make_key)(info, &key, i, key_buff, record, oldpos,
+ 0);
+ if (key.keyinfo->flag & HA_NOSAME)
{ /* Change pointer direct */
uint nod_flag;
MARIA_KEYDEF *keyinfo;
keyinfo=share->keyinfo+i;
- if (_ma_search(info,keyinfo,key,USE_WHOLE_KEY,
- (uint) (SEARCH_SAME | SEARCH_SAVE_BUFF),
+ if (_ma_search(info, &key, (uint32) (SEARCH_SAME | SEARCH_SAVE_BUFF),
share->state.key_root[i]))
DBUG_RETURN(-1);
nod_flag= _ma_test_if_nod(share, info->buff);
- _ma_dpointer(info,info->int_keypos-nod_flag-
+ _ma_dpointer(share, info->int_keypos - nod_flag -
share->rec_reflength,newpos);
if (_ma_write_keypage(info, keyinfo, info->last_keypage,
PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS,
@@ -2812,10 +2851,11 @@ int maria_movepoint(register MARIA_HA *info, uchar *record,
}
else
{ /* Change old key to new */
- if (_ma_ck_delete(info,i,key,key_length))
+ if (_ma_ck_delete(info, &key))
DBUG_RETURN(-1);
- key_length= _ma_make_key(info,i,key,record,newpos);
- if (_ma_ck_write(info,i,key,key_length))
+ (*share->keyinfo[i].make_key)(info, &key, i, key_buff, record, newpos,
+ 0);
+ if (_ma_ck_write(info, &key))
DBUG_RETURN(-1);
}
}
@@ -2997,23 +3037,25 @@ static void put_crc(uchar *buff, my_off_t pos, MARIA_SHARE *share)
}
- /* Sort records recursive using one index */
+/* Sort index blocks recursive using one index */
static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
MARIA_KEYDEF *keyinfo,
my_off_t pagepos, File new_file)
{
- uint length,nod_flag,used_length, key_length;
+ uint length,nod_flag,used_length;
uchar *buff,*keypos,*endpos;
- uchar key[HA_MAX_POSSIBLE_KEY_BUFF];
my_off_t new_page_pos,next_page;
MARIA_SHARE *share= info->s;
+ MARIA_KEY key;
DBUG_ENTER("sort_one_index");
/* cannot walk over R-tree indices */
DBUG_ASSERT(keyinfo->key_alg != HA_KEY_ALG_RTREE);
new_page_pos=param->new_file_pos;
param->new_file_pos+=keyinfo->block_length;
+ key.keyinfo= keyinfo;
+ key.data= info->lastkey_buff;
if (!(buff= (uchar*) my_alloca((uint) keyinfo->block_length)))
{
@@ -3028,9 +3070,11 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
}
if ((nod_flag=_ma_test_if_nod(share, buff)) || keyinfo->flag & HA_FULLTEXT)
{
+ uint page_flag= _ma_get_keypage_flag(share, buff);
used_length= _ma_get_page_used(share, buff);
keypos=buff + share->keypage_header + nod_flag;
endpos=buff + used_length;
+
for ( ;; )
{
if (nod_flag)
@@ -3049,19 +3093,19 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
}
}
if (keypos >= endpos ||
- (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key)) == 0)
+ !(*keyinfo->get_key)(&key, page_flag, nod_flag, &keypos))
break;
DBUG_ASSERT(keypos <= endpos);
if (keyinfo->flag & HA_FULLTEXT)
{
uint off;
int subkeys;
- get_key_full_length_rdonly(off, key);
- subkeys=ft_sintXkorr(key+off);
+ get_key_full_length_rdonly(off, key.data);
+ subkeys= ft_sintXkorr(key.data + off);
if (subkeys < 0)
{
- next_page= _ma_dpos(info,0,key+key_length);
- _ma_dpointer(info,keypos-nod_flag-share->rec_reflength,
+ next_page= _ma_row_pos_from_key(&key);
+ _ma_dpointer(share, keypos - nod_flag - share->rec_reflength,
param->new_file_pos); /* Save new pos */
if (sort_one_index(param,info,&share->ft2_keyinfo,
next_page,new_file))
@@ -3108,8 +3152,8 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info,
my_off_t pos;
my_off_t key_file_length= share->state.state.key_file_length;
uint block_size= share->block_size;
- my_bool zero_lsn= share->base.born_transactional &&
- !(param->testflag & T_ZEROFILL_KEEP_LSN);
+ my_bool zero_lsn= (share->base.born_transactional &&
+ !(param->testflag & T_ZEROFILL_KEEP_LSN));
DBUG_ENTER("maria_zerofill_index");
if (!(param->testflag & T_SILENT))
@@ -3138,6 +3182,25 @@ static my_bool maria_zerofill_index(HA_CHECK *param, MARIA_HA *info,
}
if (zero_lsn)
bzero(buff, LSN_SIZE);
+
+ if (share->base.born_transactional)
+ {
+ uint keynr= _ma_get_keynr(share, buff);
+ if (keynr != MARIA_DELETE_KEY_NR)
+ {
+ DBUG_ASSERT(keynr < share->base.keys);
+ if (_ma_compact_keypage(info, share->keyinfo + keynr, pos,
+ buff, ~(TrID) 0))
+ {
+ _ma_check_print_error(param,
+ "Page %9s: Got error %d when reading index "
+ "file",
+ llstr(pos, llbuff), my_errno);
+ DBUG_RETURN(1);
+ }
+ }
+ }
+
length= _ma_get_page_used(share, buff);
DBUG_ASSERT(length <= block_size);
if (length < block_size)
@@ -3246,7 +3309,7 @@ static my_bool maria_zerofill_data(HA_CHECK *param, MARIA_HA *info,
page_type == HEAD_PAGE ?
share->base.min_block_length : 0);
- /* Zerofille the not used part */
+ /* Zerofill the not used part */
offset= uint2korr(dir) + uint2korr(dir+2);
dir_start= (uint) (dir - buff);
DBUG_ASSERT(dir_start >= offset);
@@ -3308,6 +3371,9 @@ int maria_zerofill(HA_CHECK *param, MARIA_HA *info, const char *name)
info->s->state.changed&= ~(STATE_NOT_MOVABLE | STATE_MOVED);
/* Ensure state are flushed to disk */
info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
+
+ /* Reset create_trid to make file comparable */
+ info->s->state.create_trid= 0;
}
if (reenable_logging)
_ma_reenable_logging_for_table(info, FALSE);
@@ -4362,6 +4428,7 @@ static int sort_key_read(MARIA_SORT_PARAM *sort_param, uchar *key)
MARIA_SORT_INFO *sort_info= sort_param->sort_info;
MARIA_HA *info= sort_info->info;
DBUG_ENTER("sort_key_read");
+ MARIA_KEY int_key;
if ((error=sort_get_next_record(sort_param)))
DBUG_RETURN(error);
@@ -4375,10 +4442,12 @@ static int sort_key_read(MARIA_SORT_PARAM *sort_param, uchar *key)
if (_ma_sort_write_record(sort_param))
DBUG_RETURN(1);
- sort_param->real_key_length=
- (info->s->rec_reflength+
- _ma_make_key(info, sort_param->key, key,
- sort_param->record, sort_param->current_filepos));
+ (*info->s->keyinfo[sort_param->key].make_key)(info, &int_key,
+ sort_param->key, key,
+ sort_param->record,
+ sort_param->current_filepos,
+ 0);
+ sort_param->real_key_length= int_key.data_length + int_key.ref_length;
#ifdef HAVE_purify
bzero(key+sort_param->real_key_length,
(sort_param->key_length-sort_param->real_key_length));
@@ -4393,6 +4462,7 @@ static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, uchar *key)
MARIA_SORT_INFO *sort_info=sort_param->sort_info;
MARIA_HA *info=sort_info->info;
FT_WORD *wptr=0;
+ MARIA_KEY int_key;
DBUG_ENTER("sort_maria_ft_key_read");
if (!sort_param->wordlist)
@@ -4419,10 +4489,10 @@ static int sort_maria_ft_key_read(MARIA_SORT_PARAM *sort_param, uchar *key)
wptr=(FT_WORD*)(sort_param->wordptr);
}
- sort_param->real_key_length=(info->s->rec_reflength+
- _ma_ft_make_key(info, sort_param->key,
- key, wptr++,
- sort_param->current_filepos));
+ _ma_ft_make_key(info, &int_key, sort_param->key, key, wptr++,
+ sort_param->current_filepos);
+ sort_param->real_key_length= int_key.data_length + int_key.ref_length;
+
#ifdef HAVE_purify
if (sort_param->key_length > sort_param->real_key_length)
bzero(key+sort_param->real_key_length,
@@ -5139,9 +5209,10 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a)
if (sort_info->key_block->inited)
{
- cmp=ha_key_cmp(sort_param->seg, (uchar*) sort_info->key_block->lastkey,
- a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
- diff_pos);
+ cmp= ha_key_cmp(sort_param->seg, (uchar*) sort_info->key_block->lastkey,
+ a, USE_WHOLE_KEY,
+ SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT,
+ diff_pos);
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
ha_key_cmp(sort_param->seg, (uchar*) sort_info->key_block->lastkey,
a, USE_WHOLE_KEY,
@@ -5165,21 +5236,19 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a)
if ((sort_param->keyinfo->flag & HA_NOSAME) && cmp == 0)
{
sort_info->dupp++;
- sort_info->info->cur_row.lastpos= get_record_for_key(sort_info->info,
- sort_param->keyinfo,
+ sort_info->info->cur_row.lastpos= get_record_for_key(sort_param->keyinfo,
a);
_ma_check_print_warning(param,
"Duplicate key %2u for record at %10s against record at %10s",
sort_param->key + 1,
llstr(sort_info->info->cur_row.lastpos, llbuff),
- llstr(get_record_for_key(sort_info->info,
- sort_param->keyinfo,
+ llstr(get_record_for_key(sort_param->keyinfo,
sort_info->key_block->
lastkey),
llbuff2));
param->testflag|=T_RETRY_WITHOUT_QUICK;
if (sort_info->param->testflag & T_VERBOSE)
- _ma_print_key(stdout,sort_param->seg, a, USE_WHOLE_KEY);
+ _ma_print_keydata(stdout,sort_param->seg, a, USE_WHOLE_KEY);
return (sort_delete_record(sort_param));
}
#ifndef DBUG_OFF
@@ -5228,7 +5297,7 @@ int _ma_sort_ft_buf_flush(MARIA_SORT_PARAM *sort_param)
error=_ma_flush_pending_blocks(sort_param);
/* updating lastkey with second-level tree info */
ft_intXstore(maria_ft_buf->lastkey+val_off, -maria_ft_buf->count);
- _ma_dpointer(sort_info->info, maria_ft_buf->lastkey+val_off+HA_FT_WLEN,
+ _ma_dpointer(sort_info->info->s, maria_ft_buf->lastkey+val_off+HA_FT_WLEN,
share->state.key_root[sort_param->key]);
/* restoring first level tree data in sort_info/sort_param */
sort_info->key_block=sort_info->key_block_end- sort_info->param->sort_key_blocks;
@@ -5331,12 +5400,16 @@ word_init_ft_buf:
} /* sort_maria_ft_key_write */
- /* get pointer to record from a key */
+/* get pointer to record from a key */
-static my_off_t get_record_for_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- const uchar *key)
+static my_off_t get_record_for_key(MARIA_KEYDEF *keyinfo,
+ const uchar *key_data)
{
- return _ma_dpos(info,0, key + _ma_keylength(keyinfo, key));
+ MARIA_KEY key;
+ key.keyinfo= keyinfo;
+ key.data= (uchar*) key_data;
+ key.data_length= _ma_keylength(keyinfo, key_data);
+ return _ma_row_pos_from_key(&key);
} /* get_record_for_key */
@@ -5355,6 +5428,7 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
MARIA_SORT_INFO *sort_info= sort_param->sort_info;
HA_CHECK *param=sort_info->param;
MARIA_PINNED_PAGE tmp_page_link, *page_link= &tmp_page_link;
+ MARIA_KEY tmp_key;
MARIA_HA *info= sort_info->info;
MARIA_SHARE *share= info->s;
DBUG_ENTER("sort_insert_key");
@@ -5389,16 +5463,22 @@ static int sort_insert_key(MARIA_SORT_PARAM *sort_param,
_ma_kpointer(info,key_block->end_pos,prev_block);
}
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
- (uchar*) 0,lastkey,lastkey,key,
- &s_temp);
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= (uchar*) key;
+ tmp_key.data_length= _ma_keylength(keyinfo, key) - share->base.rec_reflength;
+ tmp_key.ref_length= share->base.rec_reflength;
+
+ t_length= (*keyinfo->pack_key)(&tmp_key, nod_flag,
+ (uchar*) 0, lastkey, lastkey, &s_temp);
(*keyinfo->store_key)(keyinfo, key_block->end_pos+nod_flag,&s_temp);
a_length+=t_length;
_ma_store_page_used(share, anc_buff, a_length);
key_block->end_pos+=t_length;
if (a_length <= (uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE))
{
- VOID(_ma_move_key(keyinfo, key_block->lastkey, key));
+ MARIA_KEY tmp_key2;
+ tmp_key2.data= key_block->lastkey;
+ _ma_copy_key(&tmp_key2, &tmp_key);
key_block->last_length=a_length-t_length;
DBUG_RETURN(0);
}
@@ -5474,7 +5554,7 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param)
if (flush_io_cache(&row_info->rec_cache))
DBUG_RETURN(1);
- key= key_info->lastkey + key_info->s->base.max_key_length;
+ key= key_info->lastkey_buff + key_info->s->base.max_key_length;
if ((error=(*row_info->s->read_record)(row_info, sort_param->record,
key_info->cur_row.lastpos)) &&
error != HA_ERR_RECORD_DELETED)
@@ -5487,9 +5567,11 @@ static int sort_delete_record(MARIA_SORT_PARAM *sort_param)
for (i=0 ; i < sort_info->current_key ; i++)
{
- uint key_length= _ma_make_key(key_info, i, key, sort_param->record,
- key_info->cur_row.lastpos);
- if (_ma_ck_delete(key_info, i, key, key_length))
+ MARIA_KEY tmp_key;
+ (*key_info->s->keyinfo[i].make_key)(key_info, &tmp_key, i, key,
+ sort_param->record,
+ key_info->cur_row.lastpos, 0);
+ if (_ma_ck_delete(key_info, &tmp_key))
{
_ma_check_print_error(param,
"Can't delete key %d from record to be removed",
@@ -5771,7 +5853,9 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
(*org_info)->s->state.state.records= info.state->records;
if (share.state.create_time)
(*org_info)->s->state.create_time=share.state.create_time;
+#ifdef EXTERNAL_LOCKING
(*org_info)->s->state.unique= (*org_info)->this_unique= share.state.unique;
+#endif
(*org_info)->s->state.state.checksum= info.state->checksum;
(*org_info)->s->state.state.del= info.state->del;
(*org_info)->s->state.dellink= share.state.dellink;
@@ -6075,7 +6159,8 @@ void maria_disable_non_unique_index(MARIA_HA *info, ha_rows rows)
(!rows || rows >= MARIA_MIN_ROWS_TO_DISABLE_INDEXES));
for (i=0 ; i < share->base.keys ; i++,key++)
{
- if (!(key->flag & (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY)) &&
+ if (!(key->flag &
+ (HA_NOSAME | HA_SPATIAL | HA_AUTO_KEY | HA_RTREE_INDEX)) &&
! maria_too_big_key_for_sort(key,rows) && share->base.auto_key != i+1)
{
maria_clear_key_active(share->state.key_map, i);
@@ -6457,7 +6542,8 @@ my_bool write_log_record_for_repair(const HA_CHECK *param, MARIA_HA *info)
point state (without crash mark) is already written.
*/
if ((!(param->testflag & T_NO_CREATE_RENAME_LSN) &&
- _ma_update_state_lsns(share, lsn, FALSE, FALSE)) ||
+ _ma_update_state_lsns(share, lsn, share->state.create_trid, FALSE,
+ FALSE)) ||
_ma_sync_table_files(info))
return TRUE;
share->now_transactional= save_now_transactional;
diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c
index 8fe2334f5e7..e01ac702772 100644
--- a/storage/maria/ma_close.c
+++ b/storage/maria/ma_close.c
@@ -115,7 +115,7 @@ int maria_close(register MARIA_HA *info)
keys = share->state.header.keys;
VOID(rwlock_destroy(&share->mmap_lock));
for(i=0; i<keys; i++) {
- VOID(rwlock_destroy(&share->key_root_lock[i]));
+ VOID(rwlock_destroy(&share->keyinfo[i].root_lock));
}
}
#endif
diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c
index 1b86f26f4c0..413c6b7b57d 100644
--- a/storage/maria/ma_create.c
+++ b/storage/maria/ma_create.c
@@ -75,7 +75,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
DBUG_PRINT("enter", ("keys: %u columns: %u uniques: %u flags: %u",
keys, columns, uniques, flags));
- DBUG_ASSERT(maria_block_size && maria_block_size % MARIA_MIN_KEY_BLOCK_LENGTH == 0);
+ DBUG_ASSERT(maria_inited);
LINT_INIT(dfile);
LINT_INIT(file);
@@ -95,6 +95,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
if (flags & HA_DONT_TOUCH_DATA)
{
+ /* We come here from recreate table */
org_datafile_type= ci->org_data_file_type;
if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
options= (ci->old_options &
@@ -111,6 +112,12 @@ int maria_create(const char *name, enum data_file_type datafile_type,
HA_OPTION_PAGE_CHECKSUM));
}
}
+ else
+ {
+ /* Transactional tables must be of type BLOCK_RECORD */
+ if (ci->transactional)
+ datafile_type= BLOCK_RECORD;
+ }
if (ci->reloc_rows > ci->max_rows)
ci->reloc_rows=ci->max_rows; /* Check if wrong parameter */
@@ -128,7 +135,6 @@ int maria_create(const char *name, enum data_file_type datafile_type,
/* Start by checking fields and field-types used */
-
varchar_length=long_varchar_count=packed= not_block_record_extra_length=
pack_reclength= max_field_lengths= 0;
reclength= min_pack_length= ci->null_bytes;
@@ -296,7 +302,7 @@ int maria_create(const char *name, enum data_file_type datafile_type,
pack_bytes= (packed + 7) / 8;
if (pack_reclength != INT_MAX32)
pack_reclength+= reclength+pack_bytes +
- test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_PACK_RECORD));
+ test(test_all_bits(options, HA_OPTION_CHECKSUM | HA_OPTION_PACK_RECORD));
min_pack_length+= pack_bytes;
/* Calculate min possible row length for rows-in-block */
extra_header_size= MAX_FIXED_HEADER_SIZE;
@@ -393,6 +399,9 @@ int maria_create(const char *name, enum data_file_type datafile_type,
length= real_length_diff= 0;
min_key_length= key_length= pointer;
+ if (keydef->key_alg == HA_KEY_ALG_RTREE)
+ keydef->flag|= HA_RTREE_INDEX; /* For easier tests */
+
if (keydef->flag & HA_SPATIAL)
{
#ifdef HAVE_SPATIAL
@@ -1055,7 +1064,8 @@ int maria_create(const char *name, enum data_file_type datafile_type,
DROP+CREATE happened (applying REDOs to the wrong table).
*/
share.kfile.file= file;
- if (_ma_update_state_lsns_sub(&share, lsn, FALSE, TRUE))
+ if (_ma_update_state_lsns_sub(&share, lsn, trnman_get_min_safe_trid(),
+ FALSE, TRUE))
goto err;
my_free(log_data, MYF(0));
}
@@ -1277,6 +1287,8 @@ int _ma_initialize_data_file(MARIA_SHARE *share, File dfile)
It acquires intern_lock to protect the LSNs and state write.
@param share table's share
+ @param lsn LSN to write to log files
+ @param create_trid Trid to be used as state.create_trid
@param do_sync if the write should be forced to disk
@param update_create_rename_lsn if this LSN should be updated or not
@@ -1285,12 +1297,12 @@ int _ma_initialize_data_file(MARIA_SHARE *share, File dfile)
@retval 1 error (disk problem)
*/
-int _ma_update_state_lsns(MARIA_SHARE *share, LSN lsn, my_bool do_sync,
- my_bool update_create_rename_lsn)
+int _ma_update_state_lsns(MARIA_SHARE *share, LSN lsn, TrID create_trid,
+ my_bool do_sync, my_bool update_create_rename_lsn)
{
int res;
pthread_mutex_lock(&share->intern_lock);
- res= _ma_update_state_lsns_sub(share, lsn, do_sync,
+ res= _ma_update_state_lsns_sub(share, lsn, create_trid, do_sync,
update_create_rename_lsn);
pthread_mutex_unlock(&share->intern_lock);
return res;
@@ -1305,6 +1317,8 @@ int _ma_update_state_lsns(MARIA_SHARE *share, LSN lsn, my_bool do_sync,
needed (when creating a table or opening it for the first time).
@param share table's share
+ @param lsn LSN to write to log files
+ @param create_trid Trid to be used as state.create_trid
@param do_sync if the write should be forced to disk
@param update_create_rename_lsn if this LSN should be updated or not
@@ -1320,15 +1334,19 @@ int _ma_update_state_lsns(MARIA_SHARE *share, LSN lsn, my_bool do_sync,
*/
#pragma optimize("",off)
#endif
-int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, my_bool do_sync,
+int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, TrID create_trid,
+ my_bool do_sync,
my_bool update_create_rename_lsn)
{
uchar buf[LSN_STORE_SIZE * 3], *ptr;
+ uchar trid_buff[8];
File file= share->kfile.file;
DBUG_ASSERT(file >= 0);
for (ptr= buf; ptr < (buf + sizeof(buf)); ptr+= LSN_STORE_SIZE)
lsn_store(ptr, lsn);
share->state.skip_redo_lsn= share->state.is_of_horizon= lsn;
+ share->state.create_trid= create_trid;
+ mi_int8store(trid_buff, create_trid);
if (update_create_rename_lsn)
{
share->state.create_rename_lsn= lsn;
@@ -1348,13 +1366,14 @@ int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn, my_bool do_sync,
}
else
lsn_store(buf, share->state.create_rename_lsn);
- return my_pwrite(file, buf, sizeof(buf),
- sizeof(share->state.header) +
- MARIA_FILE_CREATE_RENAME_LSN_OFFSET, MYF(MY_NABP)) ||
- (do_sync && my_sync(file, MYF(0)));
+ return (my_pwrite(file, buf, sizeof(buf),
+ sizeof(share->state.header) +
+ MARIA_FILE_CREATE_RENAME_LSN_OFFSET, MYF(MY_NABP)) ||
+ my_pwrite(file, trid_buff, sizeof(trid_buff),
+ sizeof(share->state.header) +
+ MARIA_FILE_CREATE_TRID_OFFSET, MYF(MY_NABP)) ||
+ (do_sync && my_sync(file, MYF(0))));
}
#if (_MSC_VER == 1310)
#pragma optimize("",on)
#endif /*VS2003 compiler bug workaround*/
-
-
diff --git a/storage/maria/ma_dbug.c b/storage/maria/ma_dbug.c
index 3fea275cfe5..149cc74fbe9 100644
--- a/storage/maria/ma_dbug.c
+++ b/storage/maria/ma_dbug.c
@@ -17,10 +17,16 @@
#include "maria_def.h"
- /* Print a key in user understandable format */
+void _ma_print_key(FILE *stream, MARIA_KEY *key)
+{
+ _ma_print_keydata(stream, key->keyinfo->seg, key->data, key->data_length);
+}
+
+
+/* Print a key in a user understandable format */
-void _ma_print_key(FILE *stream, register HA_KEYSEG *keyseg,
- const uchar *key, uint length)
+void _ma_print_keydata(FILE *stream, register HA_KEYSEG *keyseg,
+ const uchar *key, uint length)
{
int flag;
short int s_1;
diff --git a/storage/maria/ma_delete.c b/storage/maria/ma_delete.c
index 91106142204..c68a80a1fc9 100644
--- a/storage/maria/ma_delete.c
+++ b/storage/maria/ma_delete.c
@@ -18,11 +18,10 @@
#include "trnman.h"
#include "ma_key_recover.h"
-static int d_search(MARIA_HA *info,MARIA_KEYDEF *keyinfo,uint comp_flag,
- uchar *key, uint key_length,
+static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
my_off_t page, uchar *anc_buff,
MARIA_PINNED_PAGE *anc_page_link);
-static int del(MARIA_HA *info,MARIA_KEYDEF *keyinfo, uchar *key,
+static int del(MARIA_HA *info, MARIA_KEY *key,
my_off_t anc_page, uchar *anc_buff, my_off_t leaf_page,
uchar *leaf_buff, MARIA_PINNED_PAGE *leaf_page_link,
uchar *keypos, my_off_t next_block, uchar *ret_key);
@@ -30,8 +29,8 @@ static int underflow(MARIA_HA *info,MARIA_KEYDEF *keyinfo,
my_off_t anc_page, uchar *anc_buff,
my_off_t leaf_page, uchar *leaf_buff,
MARIA_PINNED_PAGE *leaf_page_link, uchar *keypos);
-static uint remove_key(MARIA_KEYDEF *keyinfo,uint nod_flag,uchar *keypos,
- uchar *lastkey,uchar *page_end,
+static uint remove_key(MARIA_KEYDEF *keyinfo, uint page_flag, uint nod_flag,
+ uchar *keypos, uchar *lastkey, uchar *page_end,
my_off_t *next_block, MARIA_KEY_PARAM *s_temp);
/* @breif Remove a row from a MARIA table */
@@ -43,6 +42,7 @@ int maria_delete(MARIA_HA *info,const uchar *record)
int save_errno;
char lastpos[8];
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo;
DBUG_ENTER("maria_delete");
/* Test if record is in datafile */
@@ -72,23 +72,26 @@ int maria_delete(MARIA_HA *info,const uchar *record)
info->last_auto_increment= ~(ulonglong) 0;
/* Remove all keys from the index file */
- old_key= info->lastkey2;
- for (i=0 ; i < share->base.keys ; i++ )
+ old_key= info->lastkey_buff2;
+
+ for (i=0, keyinfo= share->keyinfo ; i < share->base.keys ; i++, keyinfo++)
{
if (maria_is_key_active(share->state.key_map, i))
{
- share->keyinfo[i].version++;
- if (share->keyinfo[i].flag & HA_FULLTEXT)
+ keyinfo->version++;
+ if (keyinfo->flag & HA_FULLTEXT)
{
if (_ma_ft_del(info, i, old_key, record, info->cur_row.lastpos))
goto err;
}
else
{
- if (share->keyinfo[i].ck_delete(info,i,old_key,
- _ma_make_key(info, i, old_key,
- record,
- info->cur_row.lastpos)))
+ MARIA_KEY key;
+ if (keyinfo->ck_delete(info,
+ (*keyinfo->make_key)(info, &key, i, old_key,
+ record,
+ info->cur_row.lastpos,
+ info->cur_row.trid)))
goto err;
}
/* The above changed info->lastkey2. Inform maria_rnext_same(). */
@@ -149,33 +152,41 @@ err:
} /* maria_delete */
-/* Remove a key from the btree index */
+/*
+ Remove a key from the btree index
+
+ TODO:
+ Change ma_ck_real_delete() to use another buffer for changed keys instead
+ of key->data. This would allows us to remove the copying of the key here.
+*/
-int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key,
- uint key_length)
+int _ma_ck_delete(register MARIA_HA *info, MARIA_KEY *key)
{
MARIA_SHARE *share= info->s;
int res;
LSN lsn= LSN_IMPOSSIBLE;
- my_off_t new_root= share->state.key_root[keynr];
- uchar key_buff[HA_MAX_KEY_BUFF];
+ my_off_t new_root= share->state.key_root[key->keyinfo->key_nr];
+ uchar key_buff[MARIA_MAX_KEY_BUFF], *save_key_data;
+ MARIA_KEY org_key;
DBUG_ENTER("_ma_ck_delete");
+ save_key_data= key->data;
if (share->now_transactional)
{
/* Save original value as the key may change */
- memcpy(key_buff, key, key_length + share->rec_reflength);
+ memcpy(key_buff, key->data, key->data_length + key->ref_length);
+ org_key= *key;
+ key->data= key_buff;
}
- res= _ma_ck_real_delete(info, share->keyinfo+keynr, key, key_length,
- &new_root);
+ res= _ma_ck_real_delete(info, key, &new_root);
+ key->data= save_key_data;
if (!res && share->now_transactional)
- res= _ma_write_undo_key_delete(info, keynr, key_buff, key_length,
- new_root, &lsn);
+ res= _ma_write_undo_key_delete(info, &org_key, new_root, &lsn);
else
{
- share->state.key_root[keynr]= new_root;
+ share->state.key_root[key->keyinfo->key_nr]= new_root;
_ma_fast_unlock_key_del(info);
}
_ma_unpin_all_pages_and_finalize_row(info, lsn);
@@ -183,14 +194,15 @@ int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key,
} /* _ma_ck_delete */
-int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length, my_off_t *root)
+int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
+ my_off_t *root)
{
int error;
uint nod_flag;
my_off_t old_root;
uchar *root_buff;
MARIA_PINNED_PAGE *page_link;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_ck_real_delete");
if ((old_root=*root) == HA_OFFSET_ERROR)
@@ -199,7 +211,7 @@ int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
DBUG_RETURN(my_errno=HA_ERR_CRASHED);
}
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
- HA_MAX_KEY_BUFF*2)))
+ MARIA_MAX_KEY_BUFF*2)))
{
DBUG_PRINT("error",("Couldn't allocate memory"));
DBUG_RETURN(my_errno=ENOMEM);
@@ -212,15 +224,15 @@ int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
error= -1;
goto err;
}
- if ((error=d_search(info,keyinfo,
- (keyinfo->flag & HA_FULLTEXT ?
- SEARCH_FIND | SEARCH_UPDATE : SEARCH_SAME),
- key, key_length, old_root, root_buff, page_link)) >0)
+ if ((error= d_search(info, key, (keyinfo->flag & HA_FULLTEXT ?
+ SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT:
+ SEARCH_SAME),
+ old_root, root_buff, page_link)) > 0)
{
if (error == 2)
{
DBUG_PRINT("test",("Enlarging of root when deleting"));
- error= _ma_enlarge_root(info,keyinfo,key,root);
+ error= _ma_enlarge_root(info, key, root);
}
else /* error == 1 */
{
@@ -264,31 +276,31 @@ err:
@retval -1 On errors
*/
-static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uint comp_flag, uchar *key, uint key_length,
+static int d_search(MARIA_HA *info, MARIA_KEY *key, uint32 comp_flag,
my_off_t anc_page, uchar *anc_buff,
MARIA_PINNED_PAGE *anc_page_link)
{
int flag,ret_value,save_flag;
- uint length,nod_flag,search_key_length;
+ uint nod_flag, page_flag;
my_bool last_key;
uchar *leaf_buff,*keypos;
my_off_t leaf_page,next_block;
- uchar lastkey[HA_MAX_KEY_BUFF];
+ uchar lastkey[MARIA_MAX_KEY_BUFF];
MARIA_PINNED_PAGE *leaf_page_link;
MARIA_KEY_PARAM s_temp;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("d_search");
DBUG_DUMP("page",anc_buff,_ma_get_page_used(share, anc_buff));
- search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
- flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key, search_key_length,
- comp_flag, &keypos, lastkey, &last_key);
+ flag=(*keyinfo->bin_search)(key, anc_buff, comp_flag, &keypos, lastkey,
+ &last_key);
if (flag == MARIA_FOUND_WRONG_KEY)
{
DBUG_PRINT("error",("Found wrong key"));
DBUG_RETURN(-1);
}
+ page_flag= _ma_get_keypage_flag(share, anc_buff);
nod_flag= _ma_test_if_nod(share, anc_buff);
if (!flag && (keyinfo->flag & HA_FULLTEXT))
@@ -311,8 +323,8 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
else
{
/* we need exact match only if not in ft1->ft2 conversion mode */
- flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,USE_WHOLE_KEY,
- comp_flag, &keypos, lastkey, &last_key);
+ flag=(*keyinfo->bin_search)(key, anc_buff, comp_flag, &keypos,
+ lastkey, &last_key);
}
/* fall through to normal delete */
}
@@ -322,15 +334,19 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
uint tmp_key_length;
my_off_t root;
uchar *kpos=keypos;
+ MARIA_KEY tmp_key;
- if (!(tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,
- lastkey)))
+ tmp_key.data= lastkey;
+ tmp_key.keyinfo= keyinfo;
+
+ if (!(tmp_key_length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag,
+ &kpos)))
{
maria_print_error(share, HA_ERR_CRASHED);
my_errno= HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
- root= _ma_dpos(info,nod_flag,kpos);
+ root= _ma_row_pos_from_key(&tmp_key);
if (subkeys == -1)
{
/* the last entry in sub-tree */
@@ -340,14 +356,19 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
else
{
+ MARIA_KEY word_key;
keyinfo=&share->ft2_keyinfo;
/* we'll modify key entry 'in vivo' */
kpos-=keyinfo->keylength+nod_flag;
- get_key_full_length_rdonly(off, key);
- key+=off;
- ret_value= _ma_ck_real_delete(info, &share->ft2_keyinfo,
- key, HA_FT_WLEN, &root);
- _ma_dpointer(info, kpos+HA_FT_WLEN, root);
+ get_key_full_length_rdonly(off, key->data);
+
+ word_key.data= key->data + off;
+ word_key.keyinfo= &share->ft2_keyinfo;
+ word_key.data_length= HA_FT_WLEN;
+ word_key.ref_length= 0;
+ word_key.flag= 0;
+ ret_value= _ma_ck_real_delete(info, &word_key, &root);
+ _ma_dpointer(share, kpos+HA_FT_WLEN, root);
subkeys++;
ft_intXstore(kpos, subkeys);
if (!ret_value)
@@ -369,7 +390,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
/* Read left child page */
leaf_page= _ma_kpos(nod_flag,keypos);
if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
- HA_MAX_KEY_BUFF*2)))
+ MARIA_MAX_KEY_BUFF*2)))
{
DBUG_PRINT("error", ("Couldn't allocate memory"));
my_errno=ENOMEM;
@@ -391,14 +412,16 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
goto err;
}
save_flag=0;
- ret_value=d_search(info, keyinfo, comp_flag, key, key_length,
- leaf_page, leaf_buff, leaf_page_link);
+ ret_value= d_search(info, key, comp_flag, leaf_page, leaf_buff,
+ leaf_page_link);
}
else
{ /* Found key */
uint tmp;
uint anc_buff_length= _ma_get_page_used(share, anc_buff);
- if (!(tmp= remove_key(keyinfo,nod_flag,keypos,lastkey,
+ uint anc_page_flag= _ma_get_keypage_flag(share, anc_buff);
+
+ if (!(tmp= remove_key(keyinfo, anc_page_flag, nod_flag, keypos, lastkey,
anc_buff + anc_buff_length,
&next_block, &s_temp)))
goto err;
@@ -433,7 +456,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_RETURN(0);
}
save_flag=1; /* Mark that anc_buff is changed */
- ret_value= del(info, keyinfo, key, anc_page, anc_buff,
+ ret_value= del(info, key, anc_page, anc_buff,
leaf_page, leaf_buff, leaf_page_link,
keypos, next_block, lastkey);
}
@@ -444,12 +467,17 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
ret_value= underflow(info, keyinfo, anc_page, anc_buff,
leaf_page, leaf_buff, leaf_page_link, keypos);
else
- { /* This happens only with packed keys */
+ {
+ /* This can only happen with variable length keys */
+ MARIA_KEY last_key;
DBUG_PRINT("test",("Enlarging of key when deleting"));
- if (!_ma_get_last_key(info,keyinfo,anc_buff,lastkey,keypos,&length))
+
+ last_key.data= lastkey;
+ last_key.keyinfo= keyinfo;
+ if (!_ma_get_last_key(&last_key, anc_buff, keypos))
goto err;
- ret_value= _ma_insert(info, keyinfo, key, anc_buff, keypos, anc_page,
- lastkey, (my_off_t) 0, (uchar*) 0,
+ ret_value= _ma_insert(info, key, anc_buff, keypos, anc_page,
+ last_key.data, (my_off_t) 0, (uchar*) 0,
(MARIA_PINNED_PAGE*) 0, (uchar*) 0, (my_bool) 0);
}
}
@@ -458,7 +486,7 @@ static int d_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
{
/* parent buffer got too big ; We have to split the page */
save_flag=1;
- ret_value= _ma_split_page(info, keyinfo, key, anc_page, anc_buff,
+ ret_value= _ma_split_page(info, key, anc_page, anc_buff,
(uint) (keyinfo->block_length -
KEYPAGE_CHECKSUM_SIZE),
(uchar*) 0, 0, 0, lastkey, 0) | 2;
@@ -497,7 +525,7 @@ err:
@param leaf_buff_link Pinned page link for leaf_buff
@param keypos Pos to where deleted key was on anc_buff
@param next_block Page adress for nod after deleted key
- @param ret_key Key before keypos in anc_buff
+ @param ret_key_buff Key before keypos in anc_buff
@notes
leaf_buff must be written to disk if retval > 0
@@ -512,36 +540,43 @@ err:
@retval 2 key contains key to upper level (from split space)
*/
-static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, my_off_t anc_page, uchar *anc_buff,
+static int del(MARIA_HA *info, MARIA_KEY *key,
+ my_off_t anc_page, uchar *anc_buff,
my_off_t leaf_page, uchar *leaf_buff,
MARIA_PINNED_PAGE *leaf_page_link,
- uchar *keypos, my_off_t next_block, uchar *ret_key)
+ uchar *keypos, my_off_t next_block, uchar *ret_key_buff)
{
int ret_value,length;
- uint a_length, nod_flag, leaf_length, new_leaf_length, tmp;
+ uint a_length, page_flag, nod_flag, leaf_length, new_leaf_length;
my_off_t next_page;
- uchar keybuff[HA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key;
- MARIA_SHARE *share= info->s;
+ uchar keybuff[MARIA_MAX_KEY_BUFF],*endpos,*next_buff,*key_start, *prev_key;
MARIA_KEY_PARAM s_temp;
MARIA_PINNED_PAGE *next_page_link;
+ MARIA_KEY tmp_key;
+ MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_KEY ret_key;
DBUG_ENTER("del");
DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx", (long) leaf_page,
(ulong) keypos));
- _ma_get_used_and_nod(share, leaf_buff, leaf_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(share, leaf_buff);
+ _ma_get_used_and_nod_with_flag(share, page_flag, leaf_buff, leaf_length,
+ nod_flag);
DBUG_DUMP("leaf_buff", leaf_buff, leaf_length);
endpos= leaf_buff + leaf_length;
- if (!(key_start= _ma_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
- &tmp)))
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= keybuff;
+
+ if (!(key_start= _ma_get_last_key(&tmp_key, leaf_buff, endpos)))
DBUG_RETURN(-1);
if (nod_flag)
{
next_page= _ma_kpos(nod_flag,endpos);
if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
- HA_MAX_KEY_BUFF*2)))
+ MARIA_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1);
if (!_ma_fetch_keypage(info, keyinfo, next_page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, next_buff, 0, &next_page_link))
@@ -549,9 +584,9 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
else
{
DBUG_DUMP("next_page", next_buff, _ma_get_page_used(share, next_buff));
- if ((ret_value= del(info, keyinfo, key, anc_page, anc_buff, next_page,
+ if ((ret_value= del(info, key, anc_page, anc_buff, next_page,
next_buff, next_page_link, keypos, next_block,
- ret_key)) >0)
+ ret_key_buff)) >0)
{
/* Get new length after key was deleted */
endpos=leaf_buff+_ma_get_page_used(share, leaf_buff);
@@ -563,23 +598,23 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
_ma_get_page_used(share, leaf_buff) >
(uint) (keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE))
{
- ret_value= (_ma_split_page(info, keyinfo, key,
+ ret_value= (_ma_split_page(info, key,
leaf_page, leaf_buff,
(uint) (keyinfo->block_length -
KEYPAGE_CHECKSUM_SIZE),
(uchar*) 0, 0, 0,
- ret_key, 0) | 2);
+ ret_key_buff, 0) | 2);
}
}
else
{
DBUG_PRINT("test",("Inserting of key when deleting"));
- if (!_ma_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos,
- &tmp))
+ if (!_ma_get_last_key(&tmp_key, leaf_buff, endpos))
goto err;
- ret_value= _ma_insert(info, keyinfo, key, leaf_buff, endpos,
- leaf_page, keybuff, (my_off_t) 0, (uchar*) 0,
- (MARIA_PINNED_PAGE *) 0, (uchar*) 0, 0);
+ ret_value= _ma_insert(info, key, leaf_buff, endpos,
+ leaf_page, tmp_key.data, (my_off_t) 0,
+ (uchar*) 0, (MARIA_PINNED_PAGE *) 0,
+ (uchar*) 0, 0);
}
}
leaf_page_link->changed= 1;
@@ -629,18 +664,23 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
/* Place last key in ancestor page on deleted key position */
-
a_length= _ma_get_page_used(share, anc_buff);
endpos=anc_buff+a_length;
- if (keypos != anc_buff+share->keypage_header + share->base.key_reflength &&
- !_ma_get_last_key(info,keyinfo,anc_buff,ret_key,keypos,&tmp))
- goto err;
- prev_key= (keypos == anc_buff + share->keypage_header +
- share->base.key_reflength ? 0 : ret_key);
- length=(*keyinfo->pack_key)(keyinfo,share->base.key_reflength,
- keypos == endpos ? (uchar*) 0 : keypos,
- prev_key, prev_key,
- keybuff,&s_temp);
+
+ ret_key.keyinfo= keyinfo;
+ ret_key.data= ret_key_buff;
+
+ prev_key= 0;
+ if (keypos != anc_buff+share->keypage_header + share->base.key_reflength)
+ {
+ if (!_ma_get_last_key(&ret_key, anc_buff, keypos))
+ goto err;
+ prev_key= ret_key.data;
+ }
+ length= (*keyinfo->pack_key)(&tmp_key, share->base.key_reflength,
+ keypos == endpos ? (uchar*) 0 : keypos,
+ prev_key, prev_key,
+ &s_temp);
if (length > 0)
bmove_upp(endpos+length,endpos,(uint) (endpos-keypos));
else
@@ -648,8 +688,9 @@ static int del(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
(*keyinfo->store_key)(keyinfo,keypos,&s_temp);
key_start= keypos;
- /* Save pointer to next leaf */
- if (!(*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key))
+ /* Save pointer to next leaf on parent page */
+ if (!(*keyinfo->get_key)(&ret_key, page_flag, share->base.key_reflength,
+ &keypos))
goto err;
_ma_kpointer(info,keypos - share->base.key_reflength,next_block);
_ma_store_page_used(share, anc_buff, a_length + length);
@@ -688,30 +729,33 @@ err:
@retval -1 error
*/
-static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
+static int underflow(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t anc_page, uchar *anc_buff,
my_off_t leaf_page, uchar *leaf_buff,
MARIA_PINNED_PAGE *leaf_page_link,
uchar *keypos)
{
int t_length;
- uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag;
- uint next_buff_length, new_buff_length, key_reflength, key_length;
+ uint anc_length,buff_length,leaf_length,p_length,s_length,nod_flag;
+ uint next_buff_length, new_buff_length, key_reflength;
uint unchanged_leaf_length, new_leaf_length, new_anc_length;
+ uint anc_page_flag, page_flag;
my_off_t next_page;
- uchar anc_key[HA_MAX_KEY_BUFF],leaf_key[HA_MAX_KEY_BUFF];
+ uchar anc_key_buff[MARIA_MAX_KEY_BUFF], leaf_key_buff[MARIA_MAX_KEY_BUFF];
uchar *buff,*endpos,*next_keypos,*anc_pos,*half_pos,*prev_key;
uchar *after_key, *anc_end_pos;
MARIA_KEY_PARAM key_deleted, key_inserted;
MARIA_SHARE *share= info->s;
MARIA_PINNED_PAGE *next_page_link;
my_bool first_key;
+ MARIA_KEY tmp_key, anc_key, leaf_key;
DBUG_ENTER("underflow");
DBUG_PRINT("enter",("leaf_page: %ld keypos: 0x%lx",(long) leaf_page,
(ulong) keypos));
DBUG_DUMP("anc_buff", anc_buff, _ma_get_page_used(share, anc_buff));
DBUG_DUMP("leaf_buff", leaf_buff, _ma_get_page_used(share, leaf_buff));
+ anc_page_flag= _ma_get_keypage_flag(share, anc_buff);
buff=info->buff;
info->keyread_buff_used=1;
next_keypos=keypos;
@@ -724,25 +768,34 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->page_changed=1;
first_key= keypos == anc_buff + share->keypage_header + key_reflength;
+ tmp_key.data= buff;
+ anc_key.data= anc_key_buff;
+ leaf_key.data= leaf_key_buff;
+ tmp_key.keyinfo= leaf_key.keyinfo= anc_key.keyinfo= keyinfo;
+
if ((keypos < anc_buff + anc_length && (info->state->records & 1)) ||
first_key)
{
+ size_t tmp_length;
/* Use page right of anc-page */
DBUG_PRINT("test",("use right page"));
+ /*
+ Calculate position after the current key. Note that keydata itself is
+ not used
+ */
if (keyinfo->flag & HA_BINARY_PACK_KEY)
{
- if (!(next_keypos= _ma_get_key(info, keyinfo,
- anc_buff, buff, keypos, &length)))
+ if (!(next_keypos= _ma_get_key(&tmp_key, anc_buff, keypos)))
goto err;
}
else
{
/* Got to end of found key */
buff[0]=buff[1]=0; /* Avoid length error check if packed key */
- if (!(*keyinfo->get_key)(keyinfo,key_reflength,&next_keypos,
- buff))
- goto err;
+ if (!(*keyinfo->get_key)(&tmp_key, anc_page_flag, key_reflength,
+ &next_keypos))
+ goto err;
}
next_page= _ma_kpos(key_reflength,next_keypos);
if (!_ma_fetch_keypage(info,keyinfo, next_page, PAGECACHE_LOCK_WRITE,
@@ -754,29 +807,36 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
/* find keys to make a big key-page */
bmove(next_keypos-key_reflength, buff + share->keypage_header,
key_reflength);
- if (!_ma_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos,&length) ||
- !_ma_get_last_key(info,keyinfo,leaf_buff,leaf_key,
- leaf_buff+leaf_length,&length))
+
+ if (!_ma_get_last_key(&anc_key, anc_buff, next_keypos) ||
+ !_ma_get_last_key(&leaf_key, leaf_buff, leaf_buff+leaf_length))
goto err;
/* merge pages and put parting key from anc_buff between */
- prev_key=(leaf_length == p_length ? (uchar*) 0 : leaf_key);
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,buff+p_length,
- prev_key, prev_key,
- anc_key, &key_inserted);
- length= next_buff_length - p_length;
- endpos=buff+length+leaf_length+t_length;
+ prev_key= (leaf_length == p_length ? (uchar*) 0 : leaf_key.data);
+ t_length= (*keyinfo->pack_key)(&anc_key, nod_flag, buff+p_length,
+ prev_key, prev_key, &key_inserted);
+ tmp_length= next_buff_length - p_length;
+ endpos= buff+tmp_length+leaf_length+t_length;
/* buff will always be larger than before !*/
- bmove_upp(endpos, buff + next_buff_length, length);
+ bmove_upp(endpos, buff + next_buff_length, tmp_length);
memcpy(buff, leaf_buff,(size_t) leaf_length);
(*keyinfo->store_key)(keyinfo, buff+leaf_length, &key_inserted);
buff_length= (uint) (endpos-buff);
_ma_store_page_used(share, buff, buff_length);
+ /* Set page flag from combination of both key pages and parting key */
+ page_flag= (_ma_get_keypage_flag(share, buff) |
+ _ma_get_keypage_flag(share, leaf_buff));
+ if (anc_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID))
+ page_flag|= KEYPAGE_FLAG_HAS_TRANSID;
+ _ma_store_keypage_flag(share, buff, page_flag);
+
/* remove key from anc_buff */
- if (!(s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
- anc_buff+anc_length,(my_off_t *) 0,
- &key_deleted)))
+ if (!(s_length=remove_key(keyinfo, anc_page_flag, key_reflength, keypos,
+ anc_key_buff, anc_buff+anc_length,
+ (my_off_t *) 0, &key_deleted)))
goto err;
new_anc_length= anc_length - s_length;
@@ -821,29 +881,32 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
MARIA_KEY_PARAM anc_key_inserted;
anc_end_pos= anc_buff + new_anc_length;
+
DBUG_PRINT("test",("anc_buff: 0x%lx anc_end_pos: 0x%lx",
(long) anc_buff, (long) anc_end_pos));
- if (!first_key &&
- !_ma_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length))
+
+ if (!first_key && !_ma_get_last_key(&anc_key, anc_buff, keypos))
goto err;
- if (!(half_pos= _ma_find_half_pos(info, nod_flag, keyinfo, buff,
- leaf_key, &key_length, &after_key)))
+ if (!(half_pos= _ma_find_half_pos(info, &leaf_key, nod_flag, buff,
+ &after_key)))
goto err;
new_leaf_length= (uint) (half_pos-buff);
memcpy(leaf_buff, buff, (size_t) new_leaf_length);
_ma_store_page_used(share, leaf_buff, new_leaf_length);
+ _ma_store_keypage_flag(share, leaf_buff, page_flag);
/* Correct new keypointer to leaf_page */
half_pos=after_key;
- _ma_kpointer(info,leaf_key+key_length,next_page);
+ _ma_kpointer(info,
+ leaf_key.data+leaf_key.data_length + leaf_key.ref_length,
+ next_page);
/* Save key in anc_buff */
- prev_key= (first_key ? (uchar*) 0 : anc_key);
- t_length=(*keyinfo->pack_key)(keyinfo,key_reflength,
- (keypos == anc_end_pos ? (uchar*) 0 :
- keypos),
- prev_key, prev_key,
- leaf_key, &anc_key_inserted);
+ prev_key= (first_key ? (uchar*) 0 : anc_key.data);
+ t_length= (*keyinfo->pack_key)(&leaf_key, key_reflength,
+ (keypos == anc_end_pos ? (uchar*) 0 :
+ keypos),
+ prev_key, prev_key, &anc_key_inserted);
if (t_length >= 0)
bmove_upp(anc_end_pos+t_length, anc_end_pos,
(uint) (anc_end_pos - keypos));
@@ -852,22 +915,26 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
(*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted);
new_anc_length+= t_length;
_ma_store_page_used(share, anc_buff, new_anc_length);
+ if (leaf_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID))
+ _ma_mark_page_with_transid(share, anc_buff);
/* Store key first in new page */
if (nod_flag)
bmove(buff+share->keypage_header, half_pos-nod_flag,
(size_t) nod_flag);
- if (!(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key))
+ if (!(*keyinfo->get_key)(&leaf_key, page_flag, nod_flag, &half_pos))
goto err;
- t_length=(int) (*keyinfo->pack_key)(keyinfo, nod_flag, (uchar*) 0,
+ t_length=(int) (*keyinfo->pack_key)(&leaf_key, nod_flag, (uchar*) 0,
(uchar*) 0, (uchar*) 0,
- leaf_key, &key_inserted);
+ &key_inserted);
/* t_length will always be > 0 for a new page !*/
- length= (uint) ((buff + buff_length) - half_pos);
- bmove(buff+p_length+t_length, half_pos, (size_t) length);
+ tmp_length= (size_t) ((buff + buff_length) - half_pos);
+ bmove(buff+p_length+t_length, half_pos, tmp_length);
(*keyinfo->store_key)(keyinfo,buff+p_length, &key_inserted);
- new_buff_length= length + t_length + p_length;
+ new_buff_length= tmp_length + t_length + p_length;
_ma_store_page_used(share, buff, new_buff_length);
+ /* keypage flag is already up to date */
if (share->now_transactional)
{
@@ -940,7 +1007,7 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_PRINT("test",("use left page"));
- keypos= _ma_get_last_key(info,keyinfo,anc_buff,anc_key,keypos,&length);
+ keypos= _ma_get_last_key(&anc_key, anc_buff, keypos);
if (!keypos)
goto err;
next_page= _ma_kpos(key_reflength,keypos);
@@ -955,19 +1022,19 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
bmove(next_keypos - key_reflength, leaf_buff + share->keypage_header,
key_reflength);
next_keypos=keypos;
- if (!(*keyinfo->get_key)(keyinfo,key_reflength,&next_keypos,
- anc_key))
+ if (!(*keyinfo->get_key)(&anc_key, anc_page_flag, key_reflength,
+ &next_keypos))
goto err;
- if (!_ma_get_last_key(info,keyinfo,buff,leaf_key,endpos,&length))
+ if (!_ma_get_last_key(&leaf_key, buff, endpos))
goto err;
/* merge pages and put parting key from anc_buff between */
- prev_key=(leaf_length == p_length ? (uchar*) 0 : leaf_key);
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
+ prev_key= (leaf_length == p_length ? (uchar*) 0 : leaf_key.data);
+ t_length=(*keyinfo->pack_key)(&anc_key, nod_flag,
(leaf_length == p_length ?
(uchar*) 0 : leaf_buff+p_length),
prev_key, prev_key,
- anc_key, &key_inserted);
+ &key_inserted);
if (t_length >= 0)
bmove(endpos+t_length, leaf_buff+p_length,
(size_t) (leaf_length-p_length));
@@ -984,9 +1051,17 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
new_buff_length= buff_length + leaf_length - p_length + t_length;
_ma_store_page_used(share, buff, new_buff_length);
+ page_flag= (_ma_get_keypage_flag(share, buff) |
+ _ma_get_keypage_flag(share, leaf_buff));
+ if (anc_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID))
+ page_flag|= KEYPAGE_FLAG_HAS_TRANSID;
+ _ma_store_keypage_flag(share, buff, page_flag);
+
/* remove key from anc_buff */
- if (!(s_length= remove_key(keyinfo,key_reflength,keypos,anc_key,
- anc_buff+anc_length,(my_off_t *) 0,
+ if (!(s_length= remove_key(keyinfo, anc_page_flag, key_reflength, keypos,
+ anc_key_buff,
+ anc_buff+anc_length, (my_off_t *) 0,
&key_deleted)))
goto err;
@@ -1029,28 +1104,33 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- Shorten buff at 'endpos'
*/
MARIA_KEY_PARAM anc_key_inserted;
+ size_t tmp_length;
if (first_key)
anc_pos= 0; /* First key */
- else if (!_ma_get_last_key(info,keyinfo,anc_buff,anc_pos=anc_key,keypos,
- &length))
- goto err;
- if (!(endpos= _ma_find_half_pos(info, nod_flag, keyinfo, buff, leaf_key,
- &key_length, &half_pos)))
+ else
+ {
+ if (!_ma_get_last_key(&anc_key, anc_buff, keypos))
+ goto err;
+ anc_pos= anc_key.data;
+ }
+ if (!(endpos= _ma_find_half_pos(info, &leaf_key, nod_flag, buff,
+ &half_pos)))
goto err;
/* Correct new keypointer to leaf_page */
- _ma_kpointer(info,leaf_key+key_length,leaf_page);
+ _ma_kpointer(info,leaf_key.data + leaf_key.data_length +
+ leaf_key.ref_length, leaf_page);
/* Save key in anc_buff */
DBUG_DUMP("anc_buff", anc_buff, new_anc_length);
- DBUG_DUMP("key_to_anc",leaf_key,key_length);
+ DBUG_DUMP_KEY("key_to_anc", &leaf_key);
anc_end_pos= anc_buff + new_anc_length;
- t_length=(*keyinfo->pack_key)(keyinfo,key_reflength,
+ t_length=(*keyinfo->pack_key)(&leaf_key, key_reflength,
keypos == anc_end_pos ? (uchar*) 0
: keypos,
anc_pos, anc_pos,
- leaf_key, &anc_key_inserted);
+ &anc_key_inserted);
if (t_length >= 0)
bmove_upp(anc_end_pos+t_length, anc_end_pos,
(uint) (anc_end_pos-keypos));
@@ -1059,24 +1139,27 @@ static int underflow(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
(*keyinfo->store_key)(keyinfo,keypos, &anc_key_inserted);
new_anc_length+= t_length;
_ma_store_page_used(share, anc_buff, new_anc_length);
+ if (leaf_key.flag & (SEARCH_USER_KEY_HAS_TRANSID |
+ SEARCH_PAGE_KEY_HAS_TRANSID))
+ _ma_mark_page_with_transid(share, anc_buff);
/* Store first key on new page */
if (nod_flag)
bmove(leaf_buff + share->keypage_header, half_pos-nod_flag,
(size_t) nod_flag);
- if (!(length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key)))
+ if (!(*keyinfo->get_key)(&leaf_key, page_flag, nod_flag, &half_pos))
goto err;
- DBUG_DUMP("key_to_leaf",leaf_key,length);
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag, (uchar*) 0,
- (uchar*) 0, (uchar*) 0, leaf_key,
- &key_inserted);
+ DBUG_DUMP_KEY("key_to_leaf", &leaf_key);
+ t_length=(*keyinfo->pack_key)(&leaf_key, nod_flag, (uchar*) 0,
+ (uchar*) 0, (uchar*) 0, &key_inserted);
/* t_length will always be > 0 for a new page !*/
- length= (uint) ((buff + new_buff_length) - half_pos);
- DBUG_PRINT("info",("t_length: %d length: %d",t_length,(int) length));
- bmove(leaf_buff+p_length+t_length, half_pos, (size_t) length);
+ tmp_length= (size_t) ((buff + new_buff_length) - half_pos);
+ DBUG_PRINT("info",("t_length: %d length: %d",t_length, (int) tmp_length));
+ bmove(leaf_buff+p_length+t_length, half_pos, tmp_length);
(*keyinfo->store_key)(keyinfo,leaf_buff+p_length, &key_inserted);
- new_leaf_length= length + t_length + p_length;
+ new_leaf_length= tmp_length + t_length + p_length;
_ma_store_page_used(share, leaf_buff, new_leaf_length);
+ _ma_store_keypage_flag(share, leaf_buff, page_flag);
new_buff_length= (uint) (endpos - buff);
_ma_store_page_used(share, buff, new_buff_length);
@@ -1145,8 +1228,9 @@ err:
@fn remove_key()
keyinfo Key handle
+ nod_flag Length of node ptr
keypos Where on page key starts
- lastkey Unpacked version of key to be removed
+ lastkey Buffer for storing keys to be removed
page_end Pointer to end of page
next_block If <> 0 and node-page, this is set to address of
next page
@@ -1164,7 +1248,7 @@ err:
@retval # How many chars was removed
*/
-static uint remove_key(MARIA_KEYDEF *keyinfo, uint nod_flag,
+static uint remove_key(MARIA_KEYDEF *keyinfo, uint page_flag, uint nod_flag,
uchar *keypos, uchar *lastkey,
uchar *page_end, my_off_t *next_block,
MARIA_KEY_PARAM *s_temp)
@@ -1179,16 +1263,23 @@ static uint remove_key(MARIA_KEYDEF *keyinfo, uint nod_flag,
s_temp->changed_length= 0;
if (!(keyinfo->flag &
(HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
- HA_BINARY_PACK_KEY)))
+ HA_BINARY_PACK_KEY)) &&
+ !(page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
+ /* Static length key */
s_length=(int) (keyinfo->keylength+nod_flag);
if (next_block && nod_flag)
*next_block= _ma_kpos(nod_flag,keypos+s_length);
}
else
- { /* Let keypos point at next key */
+ {
+ /* Let keypos point at next key */
+ MARIA_KEY key;
+
/* Calculate length of key */
- if (!(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey))
+ key.keyinfo= keyinfo;
+ key.data= lastkey;
+ if (!(*keyinfo->get_key)(&key, page_flag, nod_flag, &keypos))
DBUG_RETURN(0); /* Error */
if (next_block && nod_flag)
@@ -1386,8 +1477,7 @@ my_bool _ma_log_delete(MARIA_HA *info, my_off_t page, const uchar *buff,
Logging of undos
****************************************************************************/
-int _ma_write_undo_key_delete(MARIA_HA *info, uint keynr,
- const uchar *key, uint key_length,
+int _ma_write_undo_key_delete(MARIA_HA *info, const MARIA_KEY *key,
my_off_t new_root, LSN *res_lsn)
{
MARIA_SHARE *share= info->s;
@@ -1396,6 +1486,7 @@ int _ma_write_undo_key_delete(MARIA_HA *info, uint keynr,
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
struct st_msg_to_write_hook_for_undo_key msg;
enum translog_record_type log_type= LOGREC_UNDO_KEY_DELETE;
+ uint keynr= key->keyinfo->key_nr;
lsn_store(log_data, info->trn->undo_lsn);
key_nr_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE, keynr);
@@ -1415,12 +1506,11 @@ int _ma_write_undo_key_delete(MARIA_HA *info, uint keynr,
log_type= LOGREC_UNDO_KEY_DELETE_WITH_ROOT;
}
- /* Log also position to row */
- key_length+= share->rec_reflength;
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= (uint) (log_pos - log_data);
- log_array[TRANSLOG_INTERNAL_PARTS + 1].str= key;
- log_array[TRANSLOG_INTERNAL_PARTS + 1].length= key_length;
+ log_array[TRANSLOG_INTERNAL_PARTS + 1].str= key->data;
+ log_array[TRANSLOG_INTERNAL_PARTS + 1].length= (key->data_length +
+ key->ref_length);
msg.root= &share->state.key_root[keynr];
msg.value= new_root;
@@ -1434,7 +1524,7 @@ int _ma_write_undo_key_delete(MARIA_HA *info, uint keynr,
info->trn, info,
(translog_size_t)
log_array[TRANSLOG_INTERNAL_PARTS + 0].length +
- key_length,
+ log_array[TRANSLOG_INTERNAL_PARTS + 1].length,
TRANSLOG_INTERNAL_PARTS + 2, log_array,
log_data + LSN_STORE_SIZE, &msg) ? -1 : 0;
}
diff --git a/storage/maria/ma_delete_all.c b/storage/maria/ma_delete_all.c
index c2857af7f62..b1e7596e4b9 100644
--- a/storage/maria/ma_delete_all.c
+++ b/storage/maria/ma_delete_all.c
@@ -81,6 +81,8 @@ int maria_delete_all_rows(MARIA_HA *info)
/* Other branch called function below when writing log record, in hook */
_ma_reset_status(info);
}
+ /* Remove old history as the table is now empty for everyone */
+ _ma_reset_state(info);
/*
If we are using delayed keys or if the user has done changes to the tables
@@ -115,7 +117,7 @@ int maria_delete_all_rows(MARIA_HA *info)
files.
*/
my_bool error= _ma_state_info_write(share, 1|4) ||
- _ma_update_state_lsns(share, lsn, FALSE, FALSE) ||
+ _ma_update_state_lsns(share, lsn, trnman_get_min_trid(), FALSE, FALSE) ||
_ma_sync_table_files(info);
info->trn->rec_lsn= LSN_IMPOSSIBLE;
if (error)
@@ -159,6 +161,7 @@ void _ma_reset_status(MARIA_HA *info)
MARIA_SHARE *share= info->s;
MARIA_STATE_INFO *state= &share->state;
uint i;
+ DBUG_ENTER("_ma_reset_status");
state->split= 0;
state->state.records= state->state.del= 0;
@@ -177,4 +180,5 @@ void _ma_reset_status(MARIA_HA *info)
/* Clear all keys */
for (i=0 ; i < share->base.keys ; i++)
state->key_root[i]= HA_OFFSET_ERROR;
+ DBUG_VOID_RETURN;
}
diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c
index c9373b770bc..d317119ebb9 100644
--- a/storage/maria/ma_extra.c
+++ b/storage/maria/ma_extra.c
@@ -189,12 +189,14 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
case HA_EXTRA_KEYREAD: /* Read only keys to record */
case HA_EXTRA_REMEMBER_POS:
info->opt_flag|= REMEMBER_OLD_POS;
- bmove((uchar*) info->lastkey+share->base.max_key_length*2,
- (uchar*) info->lastkey,info->lastkey_length);
+ bmove((uchar*) info->last_key.data + share->base.max_key_length*2,
+ (uchar*) info->last_key.data,
+ info->last_key.data_length + info->last_key.ref_length);
info->save_update= info->update;
info->save_lastinx= info->lastinx;
info->save_lastpos= info->cur_row.lastpos;
- info->save_lastkey_length= info->lastkey_length;
+ info->save_lastkey_data_length= info->last_key.data_length;
+ info->save_lastkey_ref_length= info->last_key.ref_length;
if (function == HA_EXTRA_REMEMBER_POS)
break;
/* fall through */
@@ -206,13 +208,15 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
case HA_EXTRA_RESTORE_POS:
if (info->opt_flag & REMEMBER_OLD_POS)
{
- bmove((uchar*) info->lastkey,
- (uchar*) info->lastkey+share->base.max_key_length*2,
- info->save_lastkey_length);
+ bmove((uchar*) info->last_key.data,
+ (uchar*) info->last_key.data + share->base.max_key_length*2,
+ info->save_lastkey_data_length + info->save_lastkey_ref_length);
info->update= info->save_update | HA_STATE_WRITTEN;
info->lastinx= info->save_lastinx;
info->cur_row.lastpos= info->save_lastpos;
- info->lastkey_length= info->save_lastkey_length;
+ info->last_key.data_length= info->save_lastkey_data_length;
+ info->last_key.ref_length= info->save_lastkey_ref_length;
+ info->last_key.flag= 0;
}
info->read_record= share->read_record;
info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c
index 7db45dffb77..3bcbd9edfbf 100644
--- a/storage/maria/ma_ft_boolean_search.c
+++ b/storage/maria/ma_ft_boolean_search.c
@@ -196,7 +196,7 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param,
case FT_TOKEN_WORD:
ftbw= (FTB_WORD *)alloc_root(&ftb_param->ftb->mem_root,
sizeof(FTB_WORD) +
- (info->trunc ? HA_MAX_KEY_BUFF :
+ (info->trunc ? MARIA_MAX_KEY_BUFF :
word_len * ftb_param->ftb->charset->mbmaxlen +
HA_FT_WLEN +
ftb_param->ftb->info->s->rec_reflength));
@@ -335,7 +335,9 @@ static int _ftb_no_dupes_cmp(void* not_used __attribute__((unused)),
return CMP_NUM((*((my_off_t*)a)), (*((my_off_t*)b)));
}
+
/* returns 1 if the search was finished (must-word wasn't found) */
+
static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
{
int r;
@@ -344,6 +346,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
MARIA_HA *info=ftb->info;
uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength;
uchar *lastkey_buf= ftbw->word+ftbw->off;
+ MARIA_KEY key;
LINT_INIT(off);
if (ftbw->flags & FTB_FLAG_TRUNC)
@@ -353,9 +356,13 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
{
ftbw->key_root=info->s->state.key_root[ftb->keynr];
ftbw->keyinfo=info->s->keyinfo+ftb->keynr;
+ key.keyinfo= ftbw->keyinfo;
+ key.data= ftbw->word;
+ key.data_length= ftbw->len;
+ key.ref_length= 0;
+ key.flag= 0;
- r= _ma_search(info, ftbw->keyinfo, ftbw->word, ftbw->len,
- SEARCH_FIND | SEARCH_BIGGER, ftbw->key_root);
+ r= _ma_search(info, &key, SEARCH_FIND | SEARCH_BIGGER, ftbw->key_root);
}
else
{
@@ -369,11 +376,17 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
if (ftbw->docid[0] < max_docid)
{
sflag|= SEARCH_SAME;
- _ma_dpointer(info, (uchar*) (ftbw->word + ftbw->len + HA_FT_WLEN),
+ _ma_dpointer(info->s, (uchar*) (ftbw->word + ftbw->len + HA_FT_WLEN),
max_docid);
}
- r= _ma_search(info, ftbw->keyinfo, lastkey_buf,
- USE_WHOLE_KEY, sflag, ftbw->key_root);
+
+ key.keyinfo= ftbw->keyinfo;
+ key.data= lastkey_buf;
+ key.data_length= USE_WHOLE_KEY;
+ key.ref_length= 0;
+ key.flag= 0;
+
+ r= _ma_search(info, &key, sflag, ftbw->key_root);
}
can_go_down=(!ftbw->off && (init_search || (ftbw->flags & FTB_FLAG_TRUNC)));
@@ -383,21 +396,20 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
if (can_go_down)
{
/* going down ? */
- off=info->lastkey_length-extra;
- subkeys=ft_sintXkorr(info->lastkey+off);
+ off= info->last_key.data_length + info->last_key.ref_length - extra;
+ subkeys=ft_sintXkorr(info->last_key.data + off);
}
if (subkeys<0 || info->cur_row.lastpos < info->state->data_file_length)
break;
- r= _ma_search_next(info, ftbw->keyinfo, info->lastkey,
- info->lastkey_length,
- SEARCH_BIGGER, ftbw->key_root);
+ r= _ma_search_next(info, &info->last_key, SEARCH_BIGGER, ftbw->key_root);
}
if (!r && !ftbw->off)
{
r= ha_compare_text(ftb->charset,
- info->lastkey+1,
- info->lastkey_length-extra-1,
+ info->last_key.data+1,
+ info->last_key.data_length + info->last_key.ref_length-
+ extra-1,
(uchar*) ftbw->word+1,
ftbw->len-1,
(my_bool) (ftbw->flags & FTB_FLAG_TRUNC), 0);
@@ -422,7 +434,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
}
/* going up to the first-level tree to continue search there */
- _ma_dpointer(info, (lastkey_buf+HA_FT_WLEN), ftbw->key_root);
+ _ma_dpointer(info->s, (lastkey_buf+HA_FT_WLEN), ftbw->key_root);
ftbw->key_root=info->s->state.key_root[ftb->keynr];
ftbw->keyinfo=info->s->keyinfo+ftb->keynr;
ftbw->off=0;
@@ -430,9 +442,10 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
}
/* matching key found */
- memcpy(lastkey_buf, info->lastkey, info->lastkey_length);
+ memcpy(lastkey_buf, info->last_key.data,
+ info->last_key.data_length + info->last_key.ref_length);
if (lastkey_buf == ftbw->word)
- ftbw->len=info->lastkey_length-extra;
+ ftbw->len= info->last_key.data_length + info->last_key.ref_length - extra;
/* going down ? */
if (subkeys<0)
@@ -446,7 +459,8 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
ftbw->keyinfo=& info->s->ft2_keyinfo;
r= _ma_search_first(info, ftbw->keyinfo, ftbw->key_root);
DBUG_ASSERT(r==0); /* found something */
- memcpy(lastkey_buf+off, info->lastkey, info->lastkey_length);
+ memcpy(lastkey_buf+off, info->last_key.data,
+ info->last_key.data_length + info->last_key.ref_length);
}
ftbw->docid[0]= info->cur_row.lastpos;
if (ftbw->flags & FTB_FLAG_YES && !(ftbw->flags & FTB_FLAG_TRUNC))
diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c
index 418656fc404..53ff9d5c47d 100644
--- a/storage/maria/ma_ft_nlq_search.c
+++ b/storage/maria/ma_ft_nlq_search.c
@@ -64,7 +64,7 @@ static int FT_SUPERDOC_cmp(void* cmp_arg __attribute__((unused)),
static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
{
int subkeys, r;
- uint keylen, doc_cnt;
+ uint doc_cnt;
FT_SUPERDOC sdoc, *sptr;
TREE_ELEMENT *selem;
double gweight=1;
@@ -73,27 +73,28 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
MARIA_KEYDEF *keyinfo=info->s->keyinfo+aio->keynr;
my_off_t key_root=info->s->state.key_root[aio->keynr];
uint extra=HA_FT_WLEN+info->s->base.rec_reflength;
+ MARIA_KEY key;
#if HA_FT_WTYPE == HA_KEYTYPE_FLOAT
float tmp_weight;
#else
#error
#endif
-
DBUG_ENTER("walk_and_match");
word->weight=LWS_FOR_QUERY;
- keylen= _ma_ft_make_key(info, aio->keynr, keybuff, word, 0);
- keylen-=HA_FT_WLEN;
+ _ma_ft_make_key(info, &key, aio->keynr, keybuff, word, 0);
+ key.data_length-= HA_FT_WLEN;
doc_cnt=0;
/* Skip rows inserted by current inserted */
- for (r= _ma_search(info, keyinfo, keybuff, keylen, SEARCH_FIND, key_root) ;
+ for (r= _ma_search(info, &key, SEARCH_FIND, key_root) ;
!r &&
- (subkeys=ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 &&
+ (subkeys=ft_sintXkorr(info->last_key.data +
+ info->last_key.data_length +
+ info->last_key.ref_length - extra)) > 0 &&
info->cur_row.lastpos >= info->state->data_file_length ;
- r= _ma_search_next(info, keyinfo, info->lastkey,
- info->lastkey_length, SEARCH_BIGGER, key_root))
+ r= _ma_search_next(info, &info->last_key, SEARCH_BIGGER, key_root))
;
info->update|= HA_STATE_AKTIV; /* for _ma_test_if_changed() */
@@ -102,10 +103,12 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
while (!r && gweight)
{
- if (keylen &&
+ if (key.data_length &&
ha_compare_text(aio->charset,
- (uchar*) info->lastkey+1, info->lastkey_length-extra-1,
- (uchar*) keybuff+1, keylen-1, 0, 0))
+ info->last_key.data+1,
+ info->last_key.data_length +
+ info->last_key.ref_length - extra - 1,
+ key.data+1, key.data_length-1, 0, 0))
break;
if (subkeys<0)
@@ -116,10 +119,10 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
TODO here: unsafe optimization, should this word
be skipped (based on subkeys) ?
*/
- keybuff+=keylen;
- keyinfo=& info->s->ft2_keyinfo;
+ keybuff+= key.data_length;
+ keyinfo= &info->s->ft2_keyinfo;
key_root= info->cur_row.lastpos;
- keylen=0;
+ key.data_length= 0;
r= _ma_search_first(info, keyinfo, key_root);
goto do_skip;
}
@@ -155,16 +158,15 @@ static int walk_and_match(FT_WORD *word, uint32 count, ALL_IN_ONE *aio)
gweight=0;
if (_ma_test_if_changed(info) == 0)
- r= _ma_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
- SEARCH_BIGGER, key_root);
+ r= _ma_search_next(info, &info->last_key, SEARCH_BIGGER, key_root);
else
- r= _ma_search(info, keyinfo, info->lastkey, info->lastkey_length,
- SEARCH_BIGGER, key_root);
+ r= _ma_search(info, &info->last_key, SEARCH_BIGGER, key_root);
do_skip:
- while ((subkeys=ft_sintXkorr(info->lastkey+info->lastkey_length-extra)) > 0 &&
+ while ((subkeys=ft_sintXkorr(info->last_key.data +
+ info->last_key.data_length +
+ info->last_key.ref_length - extra)) > 0 &&
!r && info->cur_row.lastpos >= info->state->data_file_length)
- r= _ma_search_next(info, keyinfo, info->lastkey, info->lastkey_length,
- SEARCH_BIGGER, key_root);
+ r= _ma_search_next(info, &info->last_key, SEARCH_BIGGER, key_root);
}
word->weight=gweight;
@@ -224,7 +226,7 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, uchar *query,
aio.info=info;
aio.keynr=keynr;
aio.charset=info->s->keyinfo[keynr].seg->charset;
- aio.keybuff= (uchar*) info->lastkey+info->s->base.max_key_length;
+ aio.keybuff= info->lastkey_buff2;
parser= info->s->keyinfo[keynr].parser;
if (! (ftparser_param= maria_ftparser_call_initializer(info, keynr, 0)))
goto err;
diff --git a/storage/maria/ma_ft_update.c b/storage/maria/ma_ft_update.c
index f132879fe11..567eb4dec13 100644
--- a/storage/maria/ma_ft_update.c
+++ b/storage/maria/ma_ft_update.c
@@ -135,13 +135,13 @@ FT_WORD * _ma_ft_parserecord(MARIA_HA *info, uint keynr, const uchar *record,
static int _ma_ft_store(MARIA_HA *info, uint keynr, uchar *keybuf,
FT_WORD *wlist, my_off_t filepos)
{
- uint key_length;
DBUG_ENTER("_ma_ft_store");
for (; wlist->pos; wlist++)
{
- key_length= _ma_ft_make_key(info,keynr,keybuf,wlist,filepos);
- if (_ma_ck_write(info, keynr, keybuf, key_length))
+ MARIA_KEY key;
+ _ma_ft_make_key(info, &key, keynr, keybuf, wlist, filepos);
+ if (_ma_ck_write(info, &key))
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -150,13 +150,14 @@ static int _ma_ft_store(MARIA_HA *info, uint keynr, uchar *keybuf,
static int _ma_ft_erase(MARIA_HA *info, uint keynr, uchar *keybuf,
FT_WORD *wlist, my_off_t filepos)
{
- uint key_length, err=0;
+ uint err=0;
DBUG_ENTER("_ma_ft_erase");
for (; wlist->pos; wlist++)
{
- key_length= _ma_ft_make_key(info,keynr,keybuf,wlist,filepos);
- if (_ma_ck_delete(info, keynr, keybuf, key_length))
+ MARIA_KEY key;
+ _ma_ft_make_key(info, &key, keynr, keybuf, wlist, filepos);
+ if (_ma_ck_delete(info, &key))
err=1;
}
DBUG_RETURN(err);
@@ -199,7 +200,6 @@ int _ma_ft_update(MARIA_HA *info, uint keynr, uchar *keybuf,
int error= -1;
FT_WORD *oldlist,*newlist, *old_word, *new_word;
CHARSET_INFO *cs=info->s->keyinfo[keynr].seg->charset;
- uint key_length;
int cmp, cmp2;
DBUG_ENTER("_ma_ft_update");
@@ -218,14 +218,16 @@ int _ma_ft_update(MARIA_HA *info, uint keynr, uchar *keybuf,
if (cmp < 0 || cmp2)
{
- key_length= _ma_ft_make_key(info,keynr,keybuf,old_word,pos);
- if ((error= _ma_ck_delete(info,keynr, keybuf,key_length)))
+ MARIA_KEY key;
+ _ma_ft_make_key(info, &key, keynr, keybuf, old_word, pos);
+ if ((error= _ma_ck_delete(info, &key)))
goto err;
}
if (cmp > 0 || cmp2)
{
- key_length= _ma_ft_make_key(info, keynr, keybuf, new_word,pos);
- if ((error= _ma_ck_write(info, keynr, keybuf,key_length)))
+ MARIA_KEY key;
+ _ma_ft_make_key(info, &key, keynr, keybuf, new_word,pos);
+ if ((error= _ma_ck_write(info, &key)))
goto err;
}
if (cmp<=0) old_word++;
@@ -278,8 +280,9 @@ int _ma_ft_del(MARIA_HA *info, uint keynr, uchar *keybuf, const uchar *record,
}
-uint _ma_ft_make_key(MARIA_HA *info, uint keynr, uchar *keybuf, FT_WORD *wptr,
- my_off_t filepos)
+MARIA_KEY *_ma_ft_make_key(MARIA_HA *info, MARIA_KEY *key, uint keynr,
+ uchar *keybuf,
+ FT_WORD *wptr, my_off_t filepos)
{
uchar buf[HA_FT_MAXBYTELEN+16];
DBUG_ENTER("_ma_ft_make_key");
@@ -295,7 +298,8 @@ uint _ma_ft_make_key(MARIA_HA *info, uint keynr, uchar *keybuf, FT_WORD *wptr,
int2store(buf+HA_FT_WLEN,wptr->len);
memcpy(buf+HA_FT_WLEN+2,wptr->pos,wptr->len);
- DBUG_RETURN(_ma_make_key(info, keynr, keybuf, buf, filepos));
+ /* Can't be spatial so it's ok to call _ma_make_key directly here */
+ DBUG_RETURN(_ma_make_key(info, key, keynr, keybuf, buf, filepos, 0));
}
@@ -303,7 +307,7 @@ uint _ma_ft_make_key(MARIA_HA *info, uint keynr, uchar *keybuf, FT_WORD *wptr,
convert key value to ft2
*/
-uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, uchar *key)
+uint _ma_ft_convert_to_ft2(MARIA_HA *info, MARIA_KEY *key)
{
MARIA_SHARE *share= info->s;
my_off_t root;
@@ -312,6 +316,7 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, uchar *key)
uchar *key_ptr= (uchar*) dynamic_array_ptr(da, 0), *end;
uint length, key_length;
MARIA_PINNED_PAGE tmp_page_link, *page_link= &tmp_page_link;
+ MARIA_KEY tmp_key;
DBUG_ENTER("_ma_ft_convert_to_ft2");
/* we'll generate one pageful at once, and insert the rest one-by-one */
@@ -320,8 +325,8 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, uchar *key)
set_if_smaller(length, da->elements);
length=length * keyinfo->keylength;
- get_key_full_length_rdonly(key_length, key);
- while (_ma_ck_delete(info, keynr, key, key_length) == 0)
+ get_key_full_length_rdonly(key_length, key->data);
+ while (_ma_ck_delete(info, key) == 0)
{
/*
nothing to do here.
@@ -331,7 +336,7 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, uchar *key)
/* creating pageful of keys */
bzero(info->buff, share->keypage_header);
- _ma_store_keynr(share, info->buff, keynr);
+ _ma_store_keynr(share, info->buff, keyinfo->key_nr);
_ma_store_page_used(share, info->buff, length + share->keypage_header);
memcpy(info->buff + share->keypage_header, key_ptr, length);
info->keyread_buff_used= info->page_changed=1; /* info->buff is used */
@@ -346,17 +351,23 @@ uint _ma_ft_convert_to_ft2(MARIA_HA *info, uint keynr, uchar *key)
/* inserting the rest of key values */
end= (uchar*) dynamic_array_ptr(da, da->elements);
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data_length= keyinfo->keylength;
+ tmp_key.ref_length= 0;
+ tmp_key.flag= 0;
for (key_ptr+=length; key_ptr < end; key_ptr+=keyinfo->keylength)
- if(_ma_ck_real_write_btree(info, keyinfo, key_ptr, 0, &root, SEARCH_SAME))
+ {
+ tmp_key.data= key_ptr;
+ if (_ma_ck_real_write_btree(info, key, &root, SEARCH_SAME))
DBUG_RETURN(-1);
+ }
/* now, writing the word key entry */
- ft_intXstore(key+key_length, - (int) da->elements);
- _ma_dpointer(info, key+key_length+HA_FT_WLEN, root);
-
- DBUG_RETURN(_ma_ck_real_write_btree(info,
- share->keyinfo+keynr,
- key, 0,
- &share->state.key_root[keynr],
- SEARCH_SAME));
+ ft_intXstore(key->data + key_length, - (int) da->elements);
+ _ma_dpointer(share, key->data + key_length + HA_FT_WLEN, root);
+
+ DBUG_RETURN(_ma_ck_real_write_btree(info, key,
+ &share->state.key_root[key->keyinfo->
+ key_nr],
+ SEARCH_SAME));
}
diff --git a/storage/maria/ma_ftdefs.h b/storage/maria/ma_ftdefs.h
index 5a7357e451c..bd5309ea265 100644
--- a/storage/maria/ma_ftdefs.h
+++ b/storage/maria/ma_ftdefs.h
@@ -103,12 +103,13 @@ typedef struct st_maria_ft_word {
int is_stopword(char *word, uint len);
-uint _ma_ft_make_key(MARIA_HA *, uint , uchar *, FT_WORD *, my_off_t);
+MARIA_KEY *_ma_ft_make_key(MARIA_HA *, MARIA_KEY *, uint , uchar *, FT_WORD *,
+ my_off_t);
uchar maria_ft_get_word(CHARSET_INFO *, uchar **, uchar *, FT_WORD *,
- MYSQL_FTPARSER_BOOLEAN_INFO *);
+ MYSQL_FTPARSER_BOOLEAN_INFO *);
uchar maria_ft_simple_get_word(CHARSET_INFO *, uchar **, const uchar *,
- FT_WORD *, my_bool);
+ FT_WORD *, my_bool);
typedef struct _st_maria_ft_seg_iterator {
uint num, len;
diff --git a/storage/maria/ma_fulltext.h b/storage/maria/ma_fulltext.h
index dc6cf9d1204..bc94bb9c0e5 100644
--- a/storage/maria/ma_fulltext.h
+++ b/storage/maria/ma_fulltext.h
@@ -24,4 +24,4 @@ int _ma_ft_cmp(MARIA_HA *, uint, const uchar *, const uchar *);
int _ma_ft_add(MARIA_HA *, uint, uchar *, const uchar *, my_off_t);
int _ma_ft_del(MARIA_HA *, uint, uchar *, const uchar *, my_off_t);
-uint _ma_ft_convert_to_ft2(MARIA_HA *, uint, uchar *);
+uint _ma_ft_convert_to_ft2(MARIA_HA *, MARIA_KEY *);
diff --git a/storage/maria/ma_init.c b/storage/maria/ma_init.c
index c13f01001b3..f657289ac76 100644
--- a/storage/maria/ma_init.c
+++ b/storage/maria/ma_init.c
@@ -56,6 +56,8 @@ void history_state_free(MARIA_STATE_HISTORY_CLOSED *closed_history)
int maria_init(void)
{
+ DBUG_ASSERT(maria_block_size &&
+ maria_block_size % MARIA_MIN_KEY_BLOCK_LENGTH == 0);
if (!maria_inited)
{
maria_inited= TRUE;
diff --git a/storage/maria/ma_key.c b/storage/maria/ma_key.c
index ac384821caf..9dfc0128b70 100644
--- a/storage/maria/ma_key.c
+++ b/storage/maria/ma_key.c
@@ -18,12 +18,16 @@
#include "maria_def.h"
#include "m_ctype.h"
#include "ma_sp_defs.h"
+#include "ma_blockrec.h" /* For ROW_FLAG_TRANSID */
+#include <trnman.h>
#ifdef HAVE_IEEEFP_H
#include <ieeefp.h>
#endif
#define CHECK_KEYS /* Enable safety checks */
+static int _ma_put_key_in_record(MARIA_HA *info,uint keynr,uchar *record);
+
#define FIX_LENGTH(cs, pos, length, char_length) \
do { \
if (length > char_length) \
@@ -31,46 +35,146 @@
set_if_smaller(char_length,length); \
} while(0)
-static int _ma_put_key_in_record(MARIA_HA *info,uint keynr,uchar *record);
+
+/**
+ Store trid in a packed format as part of a key
+
+ @fn transid_store_packed
+ @param info Maria handler
+ @param to End of key to which we should store a packed transid
+ @param trid Trid to be stored
+
+ @notes
+
+ Keys that have a transid has the lowest bit set for the last byte of the key
+ This function sets this bit for the key.
+
+ Trid is max 6 bytes long
+
+ First Trid it's converted to a smaller number by using
+ trid= trid - create_trid.
+ Then trid is then shifted up one bit so that we can use the
+ lowest bit as a marker if it's followed by another trid.
+
+ Trid is then stored as follows:
+
+ if trid < 256-12
+ one byte
+ else
+ one byte prefix (256-length_of_trid_in_bytes) followed by data
+ in high-byte-first order
+
+ Prefix bytes 244 to 249 are reserved for negative transid, that can be used
+ when we pack transid relative to each other on a key block.
+
+ We have to store transid in high-byte-first order to be able to do a
+ fast byte-per-byte comparision of them without packing them up.
+*/
+
+uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid)
+{
+ uchar *start;
+ uint length;
+ uchar buff[8];
+ DBUG_ASSERT(trid < (LL(1) << (MAX_PACK_TRANSID_SIZE*8)));
+ DBUG_ASSERT(trid >= info->s->state.create_trid);
+
+ trid= (trid - info->s->state.create_trid) << 1;
+
+ /* Mark that key contains transid */
+ to[-1]|= 1;
+
+ if (trid < MIN_TRANSID_PACK_PREFIX)
+ {
+ to[0]= (uchar) trid;
+ return 1;
+ }
+ start= to;
+
+ /* store things in low-byte-first-order in buff */
+ to= buff;
+ do
+ {
+ *to++= (uchar) trid;
+ trid= trid>>8;
+ } while (trid);
+
+ length= (uint) (to - buff);
+ start[0]= (uchar) (256 - length); /* Store length prefix */
+ start++;
+ /* Copy things in high-byte-first order to output buffer */
+ do
+ {
+ *start++= *--to;
+ } while (to != buff);
+ return length+1;
+}
+
+
+/**
+ Read packed transid
+
+ @fn transid_get_packed
+ @param info Maria handler
+ @param from Transid is stored here
+
+ See transid_store_packed() for how transid is packed
+
+*/
+
+ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from)
+{
+ ulonglong value;
+ uint length;
+
+ if (from[0] < MIN_TRANSID_PACK_PREFIX)
+ value= (ulonglong) from[0];
+ else
+ {
+ value= 0;
+ for (length= (uint) (256 - from[0]), value= (ulonglong) from[1], from+=2;
+ --length ;
+ from++)
+ value= (value << 8) + ((ulonglong) *from);
+ }
+ return (value >> 1) + share->state.create_trid;
+}
+
/*
- Make a intern key from a record
+ Make a normal (not spatial or fulltext) intern key from a record
SYNOPSIS
_ma_make_key()
info MyiSAM handler
+ int_key Store created key here
keynr key number
- key Store created key here
+ key Buffer used to store key data
record Record
filepos Position to record in the data file
+ NOTES
+ This is used to generate keys from the record on insert, update and delete
+
RETURN
- Length of key
+ key
*/
-uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key,
- const uchar *record, MARIA_RECORD_POS filepos)
+MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr,
+ uchar *key, const uchar *record,
+ MARIA_RECORD_POS filepos, ulonglong trid)
{
const uchar *pos;
- uchar *start;
reg1 HA_KEYSEG *keyseg;
- my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
+ my_bool is_ft;
DBUG_ENTER("_ma_make_key");
- if (info->s->keyinfo[keynr].flag & HA_SPATIAL)
- {
- /*
- TODO: nulls processing
- */
-#ifdef HAVE_SPATIAL
- DBUG_RETURN(_ma_sp_make_key(info,keynr, key,record,filepos));
-#else
- DBUG_ASSERT(0); /* maria_open should check that this never happens*/
-#endif
- }
+ int_key->data= key;
+ int_key->flag= 0; /* Always return full key */
+ int_key->keyinfo= info->s->keyinfo + keynr;
- start=key;
- for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
+ is_ft= int_key->keyinfo->flag & HA_FULLTEXT;
+ for (keyseg= int_key->keyinfo->seg ; keyseg->type ;keyseg++)
{
enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
uint length=keyseg->length;
@@ -188,13 +292,22 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key,
cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
key+= length;
}
- _ma_dpointer(info,key,filepos);
+ _ma_dpointer(info->s, key, filepos);
+ int_key->data_length= (key - int_key->data);
+ int_key->ref_length= info->s->rec_reflength;
+ int_key->flag= 0;
+ if (_ma_have_versioning(info) && trid)
+ {
+ int_key->ref_length+= transid_store_packed(info,
+ key + int_key->ref_length,
+ (TrID) trid);
+ int_key->flag|= SEARCH_USER_KEY_HAS_TRANSID;
+ }
+
DBUG_PRINT("exit",("keynr: %d",keynr));
- DBUG_DUMP("key",start,(uint) (key-start)+keyseg->length);
- DBUG_EXECUTE("key",
- _ma_print_key(DBUG_FILE,info->s->keyinfo[keynr].seg,start,
- (uint) (key-start)););
- DBUG_RETURN((uint) (key-start)); /* Return keylength */
+ DBUG_DUMP_KEY("key", int_key);
+ DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, int_key););
+ DBUG_RETURN(int_key);
} /* _ma_make_key */
@@ -204,35 +317,40 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key,
SYNOPSIS
_ma_pack_key()
info MARIA handler
- uint keynr key number
- key Store packed key here
- old Not packed key
+ int_key Store key here
+ keynr key number
+ key Buffer for key data
+ old Original not packed key
keypart_map bitmap of used keyparts
last_used_keyseg out parameter. May be NULL
RETURN
- length of packed key
+ int_key
last_use_keyseg Store pointer to the keyseg after the last used one
*/
-uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key,
- const uchar *old, key_part_map keypart_map,
- HA_KEYSEG **last_used_keyseg)
+MARIA_KEY *_ma_pack_key(register MARIA_HA *info, MARIA_KEY *int_key,
+ uint keynr, uchar *key,
+ const uchar *old, key_part_map keypart_map,
+ HA_KEYSEG **last_used_keyseg)
{
- uchar *start_key=key;
HA_KEYSEG *keyseg;
- my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
+ my_bool is_ft;
DBUG_ENTER("_ma_pack_key");
+ int_key->data= key;
+ int_key->keyinfo= info->s->keyinfo + keynr;
+
/* "one part" rtree key is 2*SPDIMS part key in Maria */
- if (info->s->keyinfo[keynr].key_alg == HA_KEY_ALG_RTREE)
+ if (int_key->keyinfo->key_alg == HA_KEY_ALG_RTREE)
keypart_map= (((key_part_map)1) << (2*SPDIMS)) - 1;
/* only key prefixes are supported */
DBUG_ASSERT(((keypart_map+1) & keypart_map) == 0);
- for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type && keypart_map;
+ is_ft= int_key->keyinfo->flag & HA_FULLTEXT;
+ for (keyseg=int_key->keyinfo->seg ; keyseg->type && keypart_map;
old+= keyseg->length, keyseg++)
{
enum ha_base_keytype type= (enum ha_base_keytype) keyseg->type;
@@ -303,11 +421,29 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key,
if (last_used_keyseg)
*last_used_keyseg= keyseg;
- DBUG_PRINT("exit", ("length: %u", (uint) (key-start_key)));
- DBUG_RETURN((uint) (key-start_key));
+ /* set flag to SEARCH_PART_KEY if we are not using all key parts */
+ int_key->flag= keyseg->type ? SEARCH_PART_KEY : 0;
+ int_key->ref_length= 0;
+ int_key->data_length= (key - int_key->data);
+
+ DBUG_PRINT("exit", ("length: %u", int_key->data_length));
+ DBUG_RETURN(int_key);
} /* _ma_pack_key */
+/**
+ Copy a key
+*/
+
+void _ma_copy_key(MARIA_KEY *to, const MARIA_KEY *from)
+{
+ memcpy(to->data, from->data, from->data_length + from->ref_length);
+ to->keyinfo= from->keyinfo;
+ to->data_length= from->data_length;
+ to->ref_length= from->ref_length;
+ to->flag= from->flag;
+}
+
/*
Store found key in record
@@ -337,9 +473,9 @@ static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr,
uchar *blob_ptr;
DBUG_ENTER("_ma_put_key_in_record");
- blob_ptr= info->lastkey2; /* Place to put blob parts */
- key=info->lastkey; /* KEy that was read */
- key_end=key+info->lastkey_length;
+ blob_ptr= info->lastkey_buff2; /* Place to put blob parts */
+ key= info->last_key.data; /* Key that was read */
+ key_end= key + info->last_key.data_length;
for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
{
if (keyseg->null_bit)
diff --git a/storage/maria/ma_key_recover.c b/storage/maria/ma_key_recover.c
index 5bb61fbeb97..f404c02dc5a 100644
--- a/storage/maria/ma_key_recover.c
+++ b/storage/maria/ma_key_recover.c
@@ -295,7 +295,6 @@ my_bool write_hook_for_undo_key_delete(enum translog_record_type type,
}
-
/*****************************************************************************
Functions for logging of key page changes
*****************************************************************************/
@@ -311,7 +310,7 @@ my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page,
{
uint translog_parts;
LSN lsn;
- uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 7 + 7], *log_pos;
+ uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 7 + 7 + 2], *log_pos;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 3];
DBUG_ENTER("_ma_log_prefix");
DBUG_PRINT("enter", ("page: %lu changed_length: %u move_length: %d",
@@ -322,6 +321,10 @@ my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page,
page_store(log_pos, page);
log_pos+= PAGE_STORE_SIZE;
+ /* Store keypage_flag */
+ *log_pos++= KEY_OP_SET_PAGEFLAG;
+ *log_pos++= buff[KEYPAGE_TRANSFLAG_OFFSET];
+
if (move_length < 0)
{
/* Delete prefix */
@@ -397,7 +400,7 @@ my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page,
{
LSN lsn;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 3];
- uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 10 + 7], *log_pos;
+ uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 10 + 7 + 2], *log_pos;
int diff;
uint translog_parts, extra_length;
DBUG_ENTER("_ma_log_suffix");
@@ -410,6 +413,10 @@ my_bool _ma_log_suffix(MARIA_HA *info, my_off_t page,
page_store(log_pos, page);
log_pos+= PAGE_STORE_SIZE;
+ /* Store keypage_flag */
+ *log_pos++= KEY_OP_SET_PAGEFLAG;
+ *log_pos++= buff[KEYPAGE_TRANSFLAG_OFFSET];
+
if ((diff= (int) (new_length - org_length)) < 0)
{
log_pos[0]= KEY_OP_DEL_SUFFIX;
@@ -477,7 +484,7 @@ my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff,
my_bool handle_overflow __attribute__ ((unused)))
{
LSN lsn;
- uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3 + 3 + 3 + 3 + 7];
+ uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 3 + 3 + 3 + 3 + 7 + 2];
uchar *log_pos;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 3];
uint offset= (uint) (key_pos - buff);
@@ -499,6 +506,10 @@ my_bool _ma_log_add(MARIA_HA *info, my_off_t page, uchar *buff,
page_store(log_pos, page);
log_pos+= PAGE_STORE_SIZE;
+ /* Store keypage_flag */
+ *log_pos++= KEY_OP_SET_PAGEFLAG;
+ *log_pos++= buff[KEYPAGE_TRANSFLAG_OFFSET];
+
if (buff_length + move_length > page_length)
{
/*
@@ -806,6 +817,8 @@ err:
KEY_OP_DEL_SUFFIX 2 length Reduce page length with this
Sets position to start of page
KEY_OP_CHECK 6 page_length[2},CRC Used only when debugging
+ KEY_OP_COMPACT_PAGE 6 transid
+ KEY_OP_SET_PAGEFLAG 1 flag for page
@return Operation status
@retval 0 OK
@@ -851,7 +864,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
_ma_get_used_and_nod(share, buff, page_length, nod_flag);
keypage_header= share->keypage_header;
org_page_length= page_length;
- DBUG_PRINT("info", ("page_length: %u", page_length));
+ DBUG_PRINT("redo", ("page_length: %u", page_length));
/* Apply modifications to page */
do
@@ -860,12 +873,14 @@ uint _ma_apply_redo_index(MARIA_HA *info,
case KEY_OP_OFFSET: /* 1 */
page_offset= uint2korr(header);
header+= 2;
+ DBUG_PRINT("redo", ("key_op_offset: %u", page_offset));
DBUG_ASSERT(page_offset >= keypage_header && page_offset <= page_length);
break;
case KEY_OP_SHIFT: /* 2 */
{
int length= sint2korr(header);
header+= 2;
+ DBUG_PRINT("redo", ("key_op_shift: %d", length));
DBUG_ASSERT(page_offset != 0 && page_offset <= page_length &&
page_length + length < share->block_size);
@@ -881,6 +896,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
case KEY_OP_CHANGE: /* 3 */
{
uint length= uint2korr(header);
+ DBUG_PRINT("redo", ("key_op_change: %u", length));
DBUG_ASSERT(page_offset != 0 && page_offset + length <= page_length);
memcpy(buff + page_offset, header + 2 , length);
@@ -891,6 +907,9 @@ uint _ma_apply_redo_index(MARIA_HA *info,
{
uint insert_length= uint2korr(header);
uint changed_length= uint2korr(header+2);
+ DBUG_PRINT("redo", ("key_op_add_prefix: %u %u",
+ insert_length, changed_length));
+
DBUG_ASSERT(insert_length <= changed_length &&
page_length + changed_length <= share->block_size);
@@ -905,6 +924,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
{
uint length= uint2korr(header);
header+= 2;
+ DBUG_PRINT("redo", ("key_op_del_prefix: %u", length));
DBUG_ASSERT(length <= page_length - keypage_header);
bmove(buff + keypage_header, buff + keypage_header +
@@ -917,6 +937,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
case KEY_OP_ADD_SUFFIX: /* 6 */
{
uint insert_length= uint2korr(header);
+ DBUG_PRINT("redo", ("key_op_add_prefix: %u", insert_length));
DBUG_ASSERT(page_length + insert_length <= share->block_size);
memcpy(buff + page_length, header+2, insert_length);
@@ -928,6 +949,7 @@ uint _ma_apply_redo_index(MARIA_HA *info,
{
uint del_length= uint2korr(header);
header+= 2;
+ DBUG_PRINT("redo", ("key_op_del_suffix: %u", del_length));
DBUG_ASSERT(page_length - del_length >= keypage_header);
page_length-= del_length;
break;
@@ -944,11 +966,12 @@ uint _ma_apply_redo_index(MARIA_HA *info,
if (crc != (uint32) my_checksum(0, buff + LSN_STORE_SIZE,
page_length - LSN_STORE_SIZE))
{
- DBUG_PRINT("info",("page_length %u",page_length));
+ DBUG_PRINT("error", ("page_length %u",page_length));
DBUG_DUMP("KEY_OP_CHECK bad page", buff, share->block_size);
DBUG_ASSERT("crc" == "failure in REDO_INDEX");
}
#endif
+ DBUG_PRINT("redo", ("key_op_check"));
header+= 6;
break;
}
@@ -965,6 +988,8 @@ uint _ma_apply_redo_index(MARIA_HA *info,
*/
uint full_length, log_memcpy_length;
const uchar *log_memcpy_end;
+
+ DBUG_PRINT("redo", ("key_op_multi_copy"));
full_length= uint2korr(header);
header+= 2;
log_memcpy_length= uint2korr(header);
@@ -984,6 +1009,24 @@ uint _ma_apply_redo_index(MARIA_HA *info,
}
break;
}
+ case KEY_OP_SET_PAGEFLAG:
+ DBUG_PRINT("redo", ("key_op_set_pageflag"));
+ buff[KEYPAGE_TRANSFLAG_OFFSET]= *header++;
+ break;
+ case KEY_OP_COMPACT_PAGE:
+ {
+ TrID transid= transid_korr(header);
+ uint keynr= _ma_get_keynr(share, buff);
+
+ DBUG_PRINT("redo", ("key_op_compact_page"));
+ header+= TRANSID_SIZE;
+ if (_ma_compact_keypage(info, share->keyinfo + keynr, (my_off_t) 0,
+ buff, transid))
+ {
+ result= 1;
+ goto err;
+ }
+ }
case KEY_OP_NONE:
default:
DBUG_ASSERT(0);
@@ -1034,8 +1077,9 @@ my_bool _ma_apply_undo_key_insert(MARIA_HA *info, LSN undo_lsn,
LSN lsn;
my_bool res;
uint keynr;
- uchar key[HA_MAX_KEY_BUFF];
+ uchar key_buff[MARIA_MAX_KEY_BUFF];
MARIA_SHARE *share= info->s;
+ MARIA_KEY key;
my_off_t new_root;
struct st_msg_to_write_hook_for_undo_key msg;
DBUG_ENTER("_ma_apply_undo_key_insert");
@@ -1047,15 +1091,29 @@ my_bool _ma_apply_undo_key_insert(MARIA_HA *info, LSN undo_lsn,
length-= KEY_NR_STORE_SIZE;
/* We have to copy key as _ma_ck_real_delete() may change it */
- memcpy(key, header + KEY_NR_STORE_SIZE, length);
- DBUG_DUMP("key", key, length);
+ memcpy(key_buff, header + KEY_NR_STORE_SIZE, length);
+ DBUG_DUMP("key_buff", key_buff, length);
new_root= share->state.key_root[keynr];
- res= (share->keyinfo[keynr].key_alg == HA_KEY_ALG_RTREE) ?
- maria_rtree_real_delete(info, keynr, key, length - share->rec_reflength,
- &new_root) :
- _ma_ck_real_delete(info, share->keyinfo+keynr, key,
- length - share->rec_reflength, &new_root);
+ /*
+ Change the key to an internal structure.
+ It's safe to have SEARCH_USER_KEY_HAS_TRANSID even if there isn't
+ a transaction id, as ha_key_cmp() will stop comparison when key length
+ is reached.
+ For index with transid flag, the ref_length of the key is not correct.
+ This should however be safe as long as this key is only used for
+ comparsion against other keys (not for packing or for read-next etc as
+ in this case we use data_length + ref_length, which is correct.
+ */
+ key.keyinfo= share->keyinfo + keynr;
+ key.data= key_buff;
+ key.data_length= length - share->rec_reflength;
+ key.ref_length= share->rec_reflength;
+ key.flag= SEARCH_USER_KEY_HAS_TRANSID;
+
+ res= ((share->keyinfo[keynr].key_alg == HA_KEY_ALG_RTREE) ?
+ maria_rtree_real_delete(info, &key, &new_root) :
+ _ma_ck_real_delete(info, &key, &new_root));
if (res)
_ma_mark_file_crashed(share);
msg.root= &share->state.key_root[keynr];
@@ -1086,10 +1144,11 @@ my_bool _ma_apply_undo_key_delete(MARIA_HA *info, LSN undo_lsn,
LSN lsn;
my_bool res;
uint keynr, skip_bytes;
- uchar key[HA_MAX_KEY_BUFF];
+ uchar key_buff[MARIA_MAX_KEY_BUFF];
MARIA_SHARE *share= info->s;
my_off_t new_root;
struct st_msg_to_write_hook_for_undo_key msg;
+ MARIA_KEY key;
DBUG_ENTER("_ma_apply_undo_key_delete");
share->state.changed|= (STATE_CHANGED | STATE_NOT_OPTIMIZED_KEYS |
@@ -1101,16 +1160,21 @@ my_bool _ma_apply_undo_key_delete(MARIA_HA *info, LSN undo_lsn,
length-= skip_bytes;
/* We have to copy key as _ma_ck_real_write_btree() may change it */
- memcpy(key, header, length);
- DBUG_DUMP("key", key, length);
+ memcpy(key_buff, header, length);
+ DBUG_DUMP("key", key_buff, length);
+
+ key.keyinfo= share->keyinfo + keynr;
+ key.data= key_buff;
+ key.data_length= length - share->rec_reflength;
+ key.ref_length= share->rec_reflength;
+ key.flag= SEARCH_USER_KEY_HAS_TRANSID;
new_root= share->state.key_root[keynr];
res= (share->keyinfo[keynr].key_alg == HA_KEY_ALG_RTREE) ?
- maria_rtree_insert_level(info, keynr, key, length - share->rec_reflength,
- -1, &new_root) :
- _ma_ck_real_write_btree(info, share->keyinfo+keynr, key,
- length - share->rec_reflength, &new_root,
- share->keyinfo[keynr].write_comp_flag);
+ maria_rtree_insert_level(info, &key, -1, &new_root) :
+ _ma_ck_real_write_btree(info, &key, &new_root,
+ share->keyinfo[keynr].write_comp_flag |
+ key.flag);
if (res)
_ma_mark_file_crashed(share);
diff --git a/storage/maria/ma_key_recover.h b/storage/maria/ma_key_recover.h
index 6f261ab8360..e8973082777 100644
--- a/storage/maria/ma_key_recover.h
+++ b/storage/maria/ma_key_recover.h
@@ -46,12 +46,10 @@ my_bool _ma_write_clr(MARIA_HA *info, LSN undo_lsn,
enum translog_record_type undo_type,
my_bool store_checksum, ha_checksum checksum,
LSN *res_lsn, void *extra_msg);
-int _ma_write_undo_key_insert(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
- const uchar *key, uint key_length,
+int _ma_write_undo_key_insert(MARIA_HA *info, const MARIA_KEY *key,
my_off_t *root, my_off_t new_root,
LSN *res_lsn);
-int _ma_write_undo_key_delete(MARIA_HA *info, uint keynr,
- const uchar *key, uint key_length,
+int _ma_write_undo_key_delete(MARIA_HA *info, const MARIA_KEY *key,
my_off_t new_root, LSN *res_lsn);
my_bool write_hook_for_clr_end(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info, LSN *lsn,
diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c
index 89a8cad26f1..e44f9491815 100644
--- a/storage/maria/ma_locking.c
+++ b/storage/maria/ma_locking.c
@@ -427,6 +427,7 @@ int _ma_mark_file_changed(MARIA_HA *info)
if (_ma_set_uuid(info, 0) ||
(share->state.create_rename_lsn == LSN_REPAIRED_BY_MARIA_CHK &&
_ma_update_state_lsns_sub(share, translog_get_horizon(),
+ trnman_get_min_trid(),
TRUE, TRUE)))
DBUG_RETURN(1);
share->state.changed|= STATE_NOT_MOVABLE;
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index 4daef976b6e..9f0afac25f7 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -1649,7 +1649,7 @@ static void translog_new_page_header(TRANSLOG_ADDRESS *horizon,
}
cursor->ptr= ptr;
DBUG_PRINT("info", ("NewP buffer #%u: 0x%lx chaser: %d Size: %lu (%lu) "
- "Horizon: (%lu,0x%lu)",
+ "Horizon: (%lu,0x%lx)",
(uint) cursor->buffer->buffer_no, (ulong) cursor->buffer,
cursor->chaser, (ulong) cursor->buffer->size,
(ulong) (cursor->ptr - cursor->buffer->buffer),
@@ -3162,8 +3162,8 @@ static my_bool translog_truncate_log(TRANSLOG_ADDRESS addr)
uchar page_buff[TRANSLOG_PAGE_SIZE];
DBUG_ENTER("translog_truncate_log");
/* TODO: write warning to the client */
- DBUG_PRINT("warning", ("removing all records from (%lx,0x%lx) "
- "till (%lx,0x%lx)",
+ DBUG_PRINT("warning", ("removing all records from (%lu,0x%lx) "
+ "till (%lu,0x%lx)",
LSN_IN_PARTS(addr),
LSN_IN_PARTS(log_descriptor.horizon)));
DBUG_ASSERT(cmp_translog_addr(addr, log_descriptor.horizon) < 0);
@@ -4945,7 +4945,7 @@ static uchar *translog_put_LSN_diff(LSN base_lsn, LSN lsn, uchar *dst)
{
uint64 diff;
DBUG_ENTER("translog_put_LSN_diff");
- DBUG_PRINT("enter", ("Base: (0x%lu,0x%lx) val: (0x%lu,0x%lx) dst: 0x%lx",
+ DBUG_PRINT("enter", ("Base: (%lu,0x%lx) val: (%lu,0x%lx) dst: 0x%lx",
LSN_IN_PARTS(base_lsn), LSN_IN_PARTS(lsn),
(ulong) dst));
DBUG_ASSERT(base_lsn > lsn);
@@ -5030,7 +5030,7 @@ static uchar *translog_get_LSN_from_diff(LSN base_lsn, uchar *src, uchar *dst)
uint32 file_no, rec_offset;
uint8 code;
DBUG_ENTER("translog_get_LSN_from_diff");
- DBUG_PRINT("enter", ("Base: (0x%lx,0x%lx) src: 0x%lx dst 0x%lx",
+ DBUG_PRINT("enter", ("Base: (%lu,0x%lx) src: 0x%lx dst 0x%lx",
LSN_IN_PARTS(base_lsn), (ulong) src, (ulong) dst));
first_byte= *((uint8*) src);
code= first_byte >> 6; /* Length is in 2 most significant bits */
@@ -6297,7 +6297,7 @@ my_bool translog_scanner_init(LSN lsn,
{
TRANSLOG_VALIDATOR_DATA data;
DBUG_ENTER("translog_scanner_init");
- DBUG_PRINT("enter", ("Scanner: 0x%lx LSN: (0x%lu,0x%lx)",
+ DBUG_PRINT("enter", ("Scanner: 0x%lx LSN: (%lu,0x%lx)",
(ulong) scanner, LSN_IN_PARTS(lsn)));
DBUG_ASSERT(translog_status == TRANSLOG_OK ||
translog_status == TRANSLOG_READONLY);
@@ -6312,8 +6312,7 @@ my_bool translog_scanner_init(LSN lsn,
scanner->direct_link= NULL;
scanner->horizon= translog_get_horizon();
- DBUG_PRINT("info", ("horizon: (0x%lu,0x%lx)",
- LSN_IN_PARTS(scanner->horizon)));
+ DBUG_PRINT("info", ("horizon: (%lu,0x%lx)", LSN_IN_PARTS(scanner->horizon)));
/* lsn < horizon */
DBUG_ASSERT(lsn <= scanner->horizon);
@@ -6783,7 +6782,7 @@ int translog_read_record_header(LSN lsn, TRANSLOG_HEADER_BUFFER *buff)
TRANSLOG_ADDRESS addr;
TRANSLOG_VALIDATOR_DATA data;
DBUG_ENTER("translog_read_record_header");
- DBUG_PRINT("enter", ("LSN: (0x%lu,0x%lx)", LSN_IN_PARTS(lsn)));
+ DBUG_PRINT("enter", ("LSN: (%lu,0x%lx)", LSN_IN_PARTS(lsn)));
DBUG_ASSERT(LSN_OFFSET(lsn) % TRANSLOG_PAGE_SIZE != 0);
DBUG_ASSERT(translog_status == TRANSLOG_OK ||
translog_status == TRANSLOG_READONLY);
@@ -7221,7 +7220,7 @@ static void translog_force_current_buffer_to_finish()
LSN_FILE_NO(log_descriptor.bc.buffer->offset));
translog_check_cursor(&log_descriptor.bc);
DBUG_ASSERT(left < TRANSLOG_PAGE_SIZE);
- if (left != 0)
+ if (left)
{
/*
TODO: if 'left' is so small that can't hold any other record
diff --git a/storage/maria/ma_loghandler.h b/storage/maria/ma_loghandler.h
index 3cb18a0eb49..5571d9136fa 100644
--- a/storage/maria/ma_loghandler.h
+++ b/storage/maria/ma_loghandler.h
@@ -161,7 +161,9 @@ enum en_key_op
KEY_OP_ADD_SUFFIX, /* Insert data at end of page */
KEY_OP_DEL_SUFFIX, /* Delete data at end of page */
KEY_OP_CHECK, /* For debugging; CRC of used part of page */
- KEY_OP_MULTI_COPY /* List of memcpy()s with fixed-len sources in page */
+ KEY_OP_MULTI_COPY, /* List of memcpy()s with fixed-len sources in page */
+ KEY_OP_SET_PAGEFLAG, /* Set pageflag from next byte */
+ KEY_OP_COMPACT_PAGE /* Compact key page */
};
/* Size of log file; One log file is restricted to 4G */
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c
index 5807002f70b..d95a305446d 100644
--- a/storage/maria/ma_open.c
+++ b/storage/maria/ma_open.c
@@ -79,7 +79,7 @@ MARIA_HA *_ma_test_if_reopen(const char *filename)
data_file Filedescriptor of data file to use < 0 if one should open
open it.
- RETURN
+ RETURN
# Maria handler
0 Error
*/
@@ -91,7 +91,6 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
int save_errno;
uint errpos;
MARIA_HA info,*m_info;
- MARIA_STATUS_INFO *state_dummy;
my_bitmap_map *changed_fields_bitmap;
DBUG_ENTER("maria_clone_internal");
@@ -115,33 +114,32 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
&info.blobs,sizeof(MARIA_BLOB)*share->base.blobs,
&info.buff,(share->base.max_key_block_length*2+
share->base.max_key_length),
- &info.lastkey,share->base.max_key_length*2+1,
+ &info.lastkey_buff,share->base.max_key_length*2+1,
&info.first_mbr_key, share->base.max_key_length,
&info.maria_rtree_recursion_state,
share->have_rtree ? 1024 : 0,
&changed_fields_bitmap,
bitmap_buffer_size(share->base.fields),
- &state_dummy, sizeof(*state_dummy),
NullS))
goto err;
errpos= 6;
memcpy(info.blobs,share->blobs,sizeof(MARIA_BLOB)*share->base.blobs);
- info.lastkey2=info.lastkey+share->base.max_key_length;
+ info.lastkey_buff2= info.lastkey_buff + share->base.max_key_length;
+ info.last_key.data= info.lastkey_buff;
info.s=share;
info.cur_row.lastpos= HA_OFFSET_ERROR;
info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
info.opt_flag=READ_CHECK_USED;
info.this_unique= (ulong) info.dfile.file; /* Uniq number in process */
+#ifdef EXTERNAL_LOCKING
if (share->data_file_type == COMPRESSED_RECORD)
info.this_unique= share->state.unique;
info.this_loop=0; /* Update counter */
info.last_unique= share->state.unique;
info.last_loop= share->state.update_count;
- info.quick_mode=0;
- info.bulk_insert=0;
- info.ft1_to_ft2=0;
+#endif
info.errkey= -1;
info.page_changed=1;
info.keyread_buff= info.buff + share->base.max_key_block_length;
@@ -185,7 +183,7 @@ static MARIA_HA *maria_clone_internal(MARIA_SHARE *share, int mode,
}
else
{
- info.state= state_dummy;
+ info.state= &share->state.common;
*info.state= share->state.state; /* Initial values */
}
info.state_start= info.state; /* Initial values */
@@ -268,6 +266,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
ulong nulls_per_key_part[HA_MAX_POSSIBLE_KEY*HA_MAX_KEY_SEG];
my_off_t key_root[HA_MAX_POSSIBLE_KEY];
ulonglong max_key_file_length, max_data_file_length;
+ my_bool versioning= 1;
File data_file= -1;
DBUG_ENTER("maria_open");
@@ -409,8 +408,9 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
*/
if ((share->state.changed & STATE_NOT_MOVABLE) &&
share->base.born_transactional &&
- !(open_flags & HA_OPEN_IGNORE_MOVED_STATE) &&
- memcmp(share->base.uuid, maria_uuid, MY_UUID_SIZE))
+ ((!(open_flags & HA_OPEN_IGNORE_MOVED_STATE) &&
+ memcmp(share->base.uuid, maria_uuid, MY_UUID_SIZE)) ||
+ share->state.create_trid > trnman_get_max_trid()))
{
if (open_flags & HA_OPEN_FOR_REPAIR)
share->state.changed|= STATE_MOVED;
@@ -436,6 +436,12 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
my_errno=HA_ERR_UNSUPPORTED;
goto err;
}
+
+ /* Ensure we have space in the key buffer for transaction id's */
+ if (share->base.born_transactional)
+ share->base.max_key_length= ALIGN_SIZE(share->base.max_key_length +
+ MAX_PACK_TRANSID_SIZE);
+
/*
If page cache is not initialized, then assume we will create the
page_cache after the table is opened!
@@ -494,9 +500,6 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
&share->data_file_name,strlen(data_name)+1,
&share->open_file_name,strlen(name)+1,
&share->state.key_root,keys*sizeof(my_off_t),
-#ifdef THREAD
- &share->key_root_lock,sizeof(rw_lock_t)*keys,
-#endif
&share->mmap_lock,sizeof(rw_lock_t),
NullS))
goto err;
@@ -552,6 +555,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
uint sp_segs=SPDIMS*2;
share->keyinfo[i].seg=pos-sp_segs;
share->keyinfo[i].keysegs--;
+ versioning= 0;
#else
my_errno=HA_ERR_UNSUPPORTED;
goto err;
@@ -559,12 +563,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
}
else if (share->keyinfo[i].flag & HA_FULLTEXT)
{
- if (!fulltext_keys)
- { /* 4.0 compatibility code, to be removed in 5.0 */
- share->keyinfo[i].seg=pos-FT_SEGS;
- share->keyinfo[i].keysegs-=FT_SEGS;
- }
- else
+ versioning= 0;
+ DBUG_ASSERT(fulltext_keys);
{
uint k;
share->keyinfo[i].seg=pos;
@@ -582,7 +582,8 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
}
if (!share->ft2_keyinfo.seg)
{
- memcpy(& share->ft2_keyinfo, & share->keyinfo[i], sizeof(MARIA_KEYDEF));
+ memcpy(&share->ft2_keyinfo, &share->keyinfo[i],
+ sizeof(MARIA_KEYDEF));
share->ft2_keyinfo.keysegs=1;
share->ft2_keyinfo.flag=0;
share->ft2_keyinfo.keylength=
@@ -655,9 +656,6 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
if (share->base.born_transactional)
{
share->page_type= PAGECACHE_LSN_PAGE;
-#ifdef ENABLE_WHEN_WE_HAVE_TRANS_ROW_ID /* QQ */
- share->base_length+= TRANS_ROW_EXTRA_HEADER_SIZE;
-#endif
if (share->state.create_rename_lsn == LSN_REPAIRED_BY_MARIA_CHK)
{
/*
@@ -668,7 +666,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
if (((open_flags & HA_OPEN_FROM_SQL_LAYER) &&
(share->state.changed & STATE_NOT_MOVABLE)) || maria_in_recovery)
_ma_update_state_lsns_sub(share, translog_get_horizon(),
- TRUE, TRUE);
+ trnman_get_min_safe_trid(), TRUE, TRUE);
}
else if ((!LSN_VALID(share->state.create_rename_lsn) ||
!LSN_VALID(share->state.is_of_horizon) ||
@@ -756,7 +754,9 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
_ma_set_index_pagecache_callbacks(&share->kfile, share);
share->this_process=(ulong) getpid();
+#ifdef EXTERNAL_LOCKING
share->last_process= share->state.process;
+#endif
share->base.key_parts=key_parts;
share->base.all_key_parts=key_parts+unique_key_parts;
if (!(share->last_version=share->state.version))
@@ -800,8 +800,10 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
VOID(pthread_mutex_init(&share->intern_lock, MY_MUTEX_INIT_FAST));
VOID(pthread_cond_init(&share->intern_cond, 0));
for (i=0; i<keys; i++)
- VOID(my_rwlock_init(&share->key_root_lock[i], NULL));
+ VOID(my_rwlock_init(&share->keyinfo[i].root_lock, NULL));
VOID(my_rwlock_init(&share->mmap_lock, NULL));
+
+ share->row_is_visible= _ma_row_visible_always;
if (!thr_lock_inited)
{
/* Probably a single threaded program; Don't use concurrent inserts */
@@ -817,24 +819,38 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->data_file_type == BLOCK_RECORD ||
share->have_rtree) ? 0 : 1;
if (share->non_transactional_concurrent_insert ||
- (!share->temporary && share->now_transactional && !share->base.keys))
+ (!share->temporary && share->now_transactional && versioning))
{
share->lock_key_trees= 1;
if (share->data_file_type == BLOCK_RECORD)
{
+ DBUG_ASSERT(share->now_transactional);
+ share->have_versioning= 1;
+ share->row_is_visible= _ma_row_visible_transactional_table;
share->lock.get_status= _ma_block_get_status;
share->lock.update_status= _ma_block_update_status;
share->lock.check_status= _ma_block_check_status;
- share->lock.allow_multiple_concurrent_insert= 1;
+ /*
+ We can for the moment only allow multiple concurrent inserts
+ only if there is no auto-increment key. To lift this restriction
+ we have to:
+ - Extend statement base replication to support auto-increment
+ intervalls.
+ - Fix that we allocate auto-increment in intervals and that
+ it's properly reset if the interval was not used
+ */
+ share->lock.allow_multiple_concurrent_insert=
+ share->base.auto_key == 0;
share->lock_restore_status= 0;
}
else
{
- share->lock.get_status= _ma_get_status;
- share->lock.copy_status= _ma_copy_status;
- share->lock.update_status= _ma_update_status;
- share->lock.restore_status=_ma_restore_status;
- share->lock.check_status= _ma_check_status;
+ share->row_is_visible= _ma_row_visible_non_transactional_table;
+ share->lock.get_status= _ma_get_status;
+ share->lock.copy_status= _ma_copy_status;
+ share->lock.update_status= _ma_update_status;
+ share->lock.restore_status= _ma_restore_status;
+ share->lock.check_status= _ma_check_status;
share->lock_restore_status= _ma_restore_status;
}
}
@@ -1053,16 +1069,23 @@ static void setup_key_functions(register MARIA_KEYDEF *keyinfo)
keyinfo->ck_insert = _ma_ck_write;
keyinfo->ck_delete = _ma_ck_delete;
}
+ if (keyinfo->flag & HA_SPATIAL)
+ keyinfo->make_key= _ma_sp_make_key;
+ else
+ keyinfo->make_key= _ma_make_key;
+
if (keyinfo->flag & HA_BINARY_PACK_KEY)
{ /* Simple prefix compression */
keyinfo->bin_search= _ma_seq_search;
keyinfo->get_key= _ma_get_binary_pack_key;
+ keyinfo->skip_key= _ma_skip_binary_pack_key;
keyinfo->pack_key= _ma_calc_bin_pack_key_length;
keyinfo->store_key= _ma_store_bin_pack_key;
}
else if (keyinfo->flag & HA_VAR_LENGTH_KEY)
{
- keyinfo->get_key= _ma_get_pack_key;
+ keyinfo->get_key= _ma_get_pack_key;
+ keyinfo->skip_key= _ma_skip_pack_key;
if (keyinfo->seg[0].flag & HA_PACK_KEY)
{ /* Prefix compression */
/*
@@ -1093,6 +1116,7 @@ static void setup_key_functions(register MARIA_KEYDEF *keyinfo)
{
keyinfo->bin_search= _ma_bin_search;
keyinfo->get_key= _ma_get_static_key;
+ keyinfo->skip_key= _ma_skip_static_key;
keyinfo->pack_key= _ma_calc_static_key_length;
keyinfo->store_key= _ma_store_static_key;
}
@@ -1108,6 +1132,7 @@ static void setup_key_functions(register MARIA_KEYDEF *keyinfo)
}
else
keyinfo->write_comp_flag= SEARCH_SAME; /* Keys in rec-pos order */
+ keyinfo->write_comp_flag|= SEARCH_INSERT;
return;
}
@@ -1213,8 +1238,7 @@ uint _ma_state_info_write_sub(File file, MARIA_STATE_INFO *state, uint pWrite)
mi_sizestore(ptr,state->state.key_empty); ptr+= 8;
mi_int8store(ptr,state->auto_increment); ptr+= 8;
mi_int8store(ptr,(ulonglong) state->state.checksum); ptr+= 8;
- mi_int4store(ptr,state->process); ptr+= 4;
- mi_int4store(ptr,state->unique); ptr+= 4;
+ mi_int8store(ptr,state->create_trid); ptr+= 8;
mi_int4store(ptr,state->status); ptr+= 4;
mi_int4store(ptr,state->update_count); ptr+= 4;
*ptr++= state->sortkey;
@@ -1279,10 +1303,7 @@ static uchar *_ma_state_info_read(uchar *ptr, MARIA_STATE_INFO *state)
state->state.key_empty= mi_sizekorr(ptr); ptr+= 8;
state->auto_increment=mi_uint8korr(ptr); ptr+= 8;
state->state.checksum=(ha_checksum) mi_uint8korr(ptr);ptr+= 8;
- /* Not used (legacy from MyISAM) */
- state->process= mi_uint4korr(ptr); ptr+= 4;
- /* Not used (legacy from MyISAM) */
- state->unique = mi_uint4korr(ptr); ptr+= 4;
+ state->create_trid= mi_uint8korr(ptr); ptr+= 8;
state->status = mi_uint4korr(ptr); ptr+= 4;
state->update_count=mi_uint4korr(ptr); ptr+= 4;
state->sortkey= (uint) *ptr++;
diff --git a/storage/maria/ma_page.c b/storage/maria/ma_page.c
index 24a97409aa3..2cbaf3ec690 100644
--- a/storage/maria/ma_page.c
+++ b/storage/maria/ma_page.c
@@ -13,7 +13,32 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Read and write key blocks */
+/*
+ Read and write key blocks
+
+ The basic structure of a key block is as follows:
+
+ LSN 7 (LSN_STORE_SIZE); Log number for last change;
+ Only for transactional pages
+ PACK_TRANSID 6 (TRANSID_SIZE); Relative transid to pack page transid's
+ Only for transactional pages
+ KEYNR 1 (KEYPAGE_KEYID_SIZE) Which index this page belongs to
+ FLAG 1 (KEYPAGE_FLAG_SIZE) Flags for page
+ PAGE_SIZE 2 (KEYPAGE_USED_SIZE) How much of the page is used.
+ high-byte-first
+
+ The flag is a combination of the following values:
+
+ KEYPAGE_FLAG_ISNOD Page is a node
+ KEYPAGE_FLAG_HAS_TRANSID There may be a transid on the page.
+
+ After this we store key data, either packed or not packed, directly
+ after each other. If the page is a node flag, there is a pointer to
+ the next key page at page start and after each key.
+
+ At end of page the last KEYPAGE_CHECKSUM_SIZE bytes are reserved for a
+ page checksum.
+*/
#include "maria_def.h"
#include "trnman.h"
@@ -163,7 +188,7 @@ int _ma_write_keypage(register MARIA_HA *info,
}
-/*
+/**
@brief Put page in free list
@fn _ma_dispose()
@@ -366,3 +391,150 @@ my_off_t _ma_new(register MARIA_HA *info, int level,
DBUG_PRINT("exit",("Pos: %ld",(long) pos));
DBUG_RETURN(pos);
} /* _ma_new */
+
+
+/**
+ Log compactation of a index page
+*/
+
+static my_bool _ma_log_compact_keypage(MARIA_HA *info, my_off_t page,
+ TrID min_read_from)
+{
+ LSN lsn;
+ uchar log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE + 1 + TRANSID_SIZE];
+ LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 1];
+ MARIA_SHARE *share= info->s;
+ DBUG_ENTER("_ma_log_compact_keypage");
+ DBUG_PRINT("enter", ("page: %lu", (ulong) page));
+
+ /* Store address of new root page */
+ page/= share->block_size;
+ page_store(log_data + FILEID_STORE_SIZE, page);
+
+ log_data[FILEID_STORE_SIZE + PAGE_STORE_SIZE]= KEY_OP_COMPACT_PAGE;
+ transid_store(log_data + FILEID_STORE_SIZE + PAGE_STORE_SIZE +1,
+ min_read_from);
+
+ log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
+ log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
+
+ if (translog_write_record(&lsn, LOGREC_REDO_INDEX,
+ info->trn, info,
+ (translog_size_t) sizeof(log_data),
+ TRANSLOG_INTERNAL_PARTS + 1, log_array,
+ log_data, NULL))
+ DBUG_RETURN(1);
+ DBUG_RETURN(0);
+}
+
+
+/**
+ Remove all transaction id's less than given one from a key page
+
+ @fn _ma_compact_keypage()
+ @param keyinfo Key handler
+ @param page_pos Page position on disk
+ @param page Buffer for page
+ @param min_read_from Remove all trids from page less than this
+
+ @retval 0 Ok
+ ®retval 1 Error; my_errno contains the error
+*/
+
+my_bool _ma_compact_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
+ my_off_t page_pos, uchar *page, TrID min_read_from)
+{
+ MARIA_SHARE *share= keyinfo->share;
+ MARIA_KEY key;
+ uchar *start_of_page, *endpos, *start_of_empty_space;
+ uint page_flag, nod_flag, saved_space;
+ my_bool page_has_transid;
+ DBUG_ENTER("_ma_compact_keypage");
+
+ page_flag= _ma_get_keypage_flag(share, page);
+ if (!(page_flag & KEYPAGE_FLAG_HAS_TRANSID))
+ DBUG_RETURN(0); /* No transaction id on page */
+
+ nod_flag= _ma_test_if_nod(share, page);
+ endpos= page + _ma_get_page_used(share, page);
+ key.data= info->lastkey_buff;
+ key.keyinfo= keyinfo;
+
+ start_of_page= page;
+ page_has_transid= 0;
+ page+= share->keypage_header + nod_flag;
+ key.data[0]= 0; /* safety */
+ start_of_empty_space= 0;
+ saved_space= 0;
+ do
+ {
+ if (!(page= (*keyinfo->skip_key)(&key, 0, 0, page)))
+ {
+ DBUG_PRINT("error",("Couldn't find last key: page: 0x%lx",
+ (long) page));
+ maria_print_error(share, HA_ERR_CRASHED);
+ my_errno=HA_ERR_CRASHED;
+ DBUG_RETURN(1);
+ }
+ if (key_has_transid(page-1))
+ {
+ uint transid_length;
+ transid_length= transid_packed_length(page);
+
+ if (min_read_from == ~(TrID) 0 ||
+ min_read_from < transid_get_packed(share, page))
+ {
+ page[-1]&= 254; /* Remove transid marker */
+ transid_length= transid_packed_length(page);
+ if (start_of_empty_space)
+ {
+ /* Move block before the transid up in page */
+ uint copy_length= (uint) (page - start_of_empty_space) - saved_space;
+ memmove(start_of_empty_space, start_of_empty_space + saved_space,
+ copy_length);
+ start_of_empty_space+= copy_length;
+ }
+ else
+ start_of_empty_space= page;
+ saved_space+= transid_length;
+ }
+ else
+ page_has_transid= 1; /* At least one id left */
+ page+= transid_length;
+ }
+ page+= nod_flag;
+ } while (page < endpos);
+
+ DBUG_ASSERT(page == endpos);
+
+ if (start_of_empty_space)
+ {
+ /*
+ Move last block down
+ This is always true if any transid was removed
+ */
+ uint copy_length= (uint) (endpos - start_of_empty_space) - saved_space;
+ uint page_length;
+
+ if (copy_length)
+ memmove(start_of_empty_space, start_of_empty_space + saved_space,
+ copy_length);
+ page_length= (uint) (start_of_empty_space + copy_length - start_of_page);
+ _ma_store_page_used(share, start_of_page, page_length);
+ }
+
+ if (!page_has_transid)
+ {
+ page_flag&= ~KEYPAGE_FLAG_HAS_TRANSID;
+ _ma_store_keypage_flag(share, start_of_page, page_flag);
+ /* Clear packed transid (in case of zerofill) */
+ bzero(start_of_page + LSN_STORE_SIZE, TRANSID_SIZE);
+ }
+
+ if (share->now_transactional)
+ {
+ if (_ma_log_compact_keypage(info, page_pos, min_read_from))
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
+}
diff --git a/storage/maria/ma_range.c b/storage/maria/ma_range.c
index 24e3d65714c..38f1d8aa44d 100644
--- a/storage/maria/ma_range.c
+++ b/storage/maria/ma_range.c
@@ -23,8 +23,7 @@
static ha_rows _ma_record_pos(MARIA_HA *,const uchar *, key_part_map,
enum ha_rkey_function);
-static double _ma_search_pos(MARIA_HA *, MARIA_KEYDEF *, uchar *,
- uint, uint, my_off_t);
+static double _ma_search_pos(MARIA_HA *, MARIA_KEY *, uint32, my_off_t);
static uint _ma_keynr(MARIA_HA *, MARIA_KEYDEF *, uchar *, uchar *, uint *);
@@ -49,6 +48,8 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
{
ha_rows start_pos,end_pos,res;
MARIA_SHARE *share= info->s;
+ MARIA_KEY key;
+ MARIA_KEYDEF *keyinfo;
DBUG_ENTER("maria_records_in_range");
if ((inx = _ma_check_index(info,inx)) < 0)
@@ -57,15 +58,15 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
if (fast_ma_readinfo(info))
DBUG_RETURN(HA_POS_ERROR);
info->update&= (HA_STATE_CHANGED+HA_STATE_ROW_CHANGED);
+ keyinfo= share->keyinfo + inx;
if (share->lock_key_trees)
- rw_rdlock(&share->key_root_lock[inx]);
+ rw_rdlock(&keyinfo->root_lock);
- switch(share->keyinfo[inx].key_alg){
+ switch (keyinfo->key_alg) {
#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
{
uchar *key_buff;
- uint start_key_len;
/*
The problem is that the optimizer doesn't support
@@ -82,12 +83,11 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
res= HA_POS_ERROR;
break;
}
- key_buff= info->lastkey+share->base.max_key_length;
- start_key_len= _ma_pack_key(info,inx, key_buff,
- min_key->key, min_key->keypart_map,
- (HA_KEYSEG**) 0);
- res= maria_rtree_estimate(info, inx, key_buff, start_key_len,
- maria_read_vec[min_key->flag]);
+ key_buff= info->last_key.data + share->base.max_key_length;
+ _ma_pack_key(info, &key, inx, key_buff,
+ min_key->key, min_key->keypart_map,
+ (HA_KEYSEG**) 0);
+ res= maria_rtree_estimate(info, &key, maria_read_vec[min_key->flag]);
res= res ? res : 1; /* Don't return 0 */
break;
}
@@ -109,7 +109,7 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
}
if (share->lock_key_trees)
- rw_unlock(&share->key_root_lock[inx]);
+ rw_unlock(&keyinfo->root_lock);
fast_ma_writeinfo(info);
/**
@@ -126,26 +126,24 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
/* Find relative position (in records) for key in index-tree */
-static ha_rows _ma_record_pos(MARIA_HA *info, const uchar *key,
+static ha_rows _ma_record_pos(MARIA_HA *info, const uchar *key_data,
key_part_map keypart_map,
enum ha_rkey_function search_flag)
{
- uint inx=(uint) info->lastinx, nextflag, key_len;
- MARIA_KEYDEF *keyinfo=info->s->keyinfo+inx;
+ uint inx= (uint) info->lastinx;
+ uint32 nextflag;
uchar *key_buff;
double pos;
+ MARIA_KEY key;
DBUG_ENTER("_ma_record_pos");
DBUG_PRINT("enter",("search_flag: %d",search_flag));
DBUG_ASSERT(keypart_map);
- key_buff=info->lastkey+info->s->base.max_key_length;
- key_len= _ma_pack_key(info, inx, key_buff, key, keypart_map,
+ key_buff= info->lastkey_buff+info->s->base.max_key_length;
+ _ma_pack_key(info, &key, inx, key_buff, key_data, keypart_map,
(HA_KEYSEG**) 0);
- DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, keyinfo->seg,
- key_buff, key_len););
+ DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, &key););
nextflag=maria_read_vec[search_flag];
- if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
- key_len=USE_WHOLE_KEY;
/*
my_handler.c:ha_compare_text() has a flag 'skip_end_space'.
@@ -181,9 +179,9 @@ static ha_rows _ma_record_pos(MARIA_HA *info, const uchar *key,
above mentioned condition only. So it can safely be used together
with other flags.
*/
- pos= _ma_search_pos(info,keyinfo, key_buff, key_len,
- nextflag | SEARCH_SAVE_BUFF | SEARCH_UPDATE,
- info->s->state.key_root[inx]);
+ pos= _ma_search_pos(info, &key,
+ nextflag | SEARCH_SAVE_BUFF | SEARCH_UPDATE,
+ info->s->state.key_root[inx]);
if (pos >= 0.0)
{
DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->state->records)));
@@ -193,19 +191,25 @@ static ha_rows _ma_record_pos(MARIA_HA *info, const uchar *key,
}
- /* This is a modified version of _ma_search */
- /* Returns offset for key in indextable (decimal 0.0 <= x <= 1.0) */
+/**
+ Find offset for key on index page
+
+ @notes
+ Modified version of _ma_search()
+
+ @return
+ @retval 0.0 <= x <= 1.0
+*/
-static double _ma_search_pos(register MARIA_HA *info,
- register MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_len, uint nextflag,
- register my_off_t pos)
+static double _ma_search_pos(MARIA_HA *info, MARIA_KEY *key,
+ uint32 nextflag, my_off_t pos)
{
int flag;
uint nod_flag,keynr,max_keynr;
my_bool after_key;
uchar *keypos, *buff;
double offset;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_search_pos");
LINT_INIT(max_keynr);
@@ -216,8 +220,8 @@ static double _ma_search_pos(register MARIA_HA *info,
PAGECACHE_LOCK_LEFT_UNLOCKED, DFLT_INIT_HITS,
info->buff, 1, 0)))
goto err;
- flag=(*keyinfo->bin_search)(info, keyinfo, buff, key, key_len, nextflag,
- &keypos,info->lastkey, &after_key);
+ flag= (*keyinfo->bin_search)(key, buff, nextflag, &keypos,
+ info->lastkey_buff, &after_key);
nod_flag=_ma_test_if_nod(info->s, buff);
keynr= _ma_keynr(info,keyinfo,buff,keypos,&max_keynr);
@@ -232,8 +236,8 @@ static double _ma_search_pos(register MARIA_HA *info,
*/
if (flag > 0 && ! nod_flag)
offset= 1.0;
- else if ((offset= _ma_search_pos(info,keyinfo,key,key_len,nextflag,
- _ma_kpos(nod_flag,keypos))) < 0)
+ else if ((offset= _ma_search_pos(info, key, nextflag,
+ _ma_kpos(nod_flag,keypos))) < 0)
DBUG_RETURN(offset);
}
else
@@ -245,14 +249,15 @@ static double _ma_search_pos(register MARIA_HA *info,
offset=1.0; /* Matches keynr+1 */
if ((nextflag & SEARCH_FIND) && nod_flag &&
((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME ||
- key_len != USE_WHOLE_KEY))
+ (nextflag & (SEARCH_PREFIX | SEARCH_NO_FIND | SEARCH_LAST |
+ SEARCH_PART_KEY))))
{
/*
There may be identical keys in the tree. Try to match on of those.
Matches keynr + [0-1]
*/
- if ((offset= _ma_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
- _ma_kpos(nod_flag,keypos))) < 0)
+ if ((offset= _ma_search_pos(info, key, SEARCH_FIND,
+ _ma_kpos(nod_flag,keypos))) < 0)
DBUG_RETURN(offset); /* Read error */
}
}
@@ -270,14 +275,18 @@ err:
static uint _ma_keynr(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
uchar *page, uchar *keypos, uint *ret_max_key)
{
- uint nod_flag, used_length, keynr, max_key;
- uchar t_buff[HA_MAX_KEY_BUFF],*end;
+ uint page_flag, nod_flag, used_length, keynr, max_key;
+ uchar t_buff[MARIA_MAX_KEY_BUFF],*end;
+ MARIA_KEY key;
- _ma_get_used_and_nod(info->s, page, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(info->s, page);
+ _ma_get_used_and_nod_with_flag(info->s, page_flag, page, used_length,
+ nod_flag);
end= page+ used_length;
page+= info->s->keypage_header + nod_flag;
- if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
+ if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
+ ! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
*ret_max_key= (uint) (end-page)/(keyinfo->keylength+nod_flag);
return (uint) (keypos-page)/(keyinfo->keylength+nod_flag);
@@ -285,13 +294,19 @@ static uint _ma_keynr(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
max_key=keynr=0;
t_buff[0]=0; /* Safety */
+ key.data= t_buff;
+ key.keyinfo= keyinfo;
+
while (page < end)
{
- if (!(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff))
+ if (!(page= (*keyinfo->skip_key)(&key, page_flag, nod_flag, page)))
+ {
+ DBUG_ASSERT(0);
return 0; /* Error */
+ }
max_key++;
if (page == keypos)
- keynr=max_key;
+ keynr= max_key;
}
*ret_max_key=max_key;
return(keynr);
diff --git a/storage/maria/ma_recovery.c b/storage/maria/ma_recovery.c
index ec679609320..0929f8de898 100644
--- a/storage/maria/ma_recovery.c
+++ b/storage/maria/ma_recovery.c
@@ -951,7 +951,8 @@ prototype_redo_exec_hook(REDO_RENAME_TABLE)
eprint(tracef, "Failed to open renamed table");
goto end;
}
- if (_ma_update_state_lsns(info->s, rec->lsn, TRUE, TRUE))
+ if (_ma_update_state_lsns(info->s, rec->lsn, info->s->state.create_trid,
+ TRUE, TRUE))
goto end;
if (maria_close(info))
goto end;
@@ -1027,8 +1028,8 @@ prototype_redo_exec_hook(REDO_REPAIR_TABLE)
else if (maria_repair(&param, info, name, quick_repair))
goto end;
- if (_ma_update_state_lsns(info->s, rec->lsn, TRUE,
- !(param.testflag & T_NO_CREATE_RENAME_LSN)))
+ if (_ma_update_state_lsns(info->s, rec->lsn, trnman_get_min_safe_trid(),
+ TRUE, !(param.testflag & T_NO_CREATE_RENAME_LSN)))
goto end;
error= 0;
@@ -1202,11 +1203,13 @@ static int new_table(uint16 sid, const char *name, LSN lsn_of_file_id)
if (close_one_table(share->open_file_name, lsn_of_file_id))
goto end;
}
- DBUG_ASSERT(share->now_transactional == share->base.born_transactional);
if (!share->base.born_transactional)
{
- tprint(tracef, ", is not transactional\n");
- ALERT_USER();
+ /*
+ This can happen if one converts a transactional table to a
+ not transactional table
+ */
+ tprint(tracef, ", is not transactional. Ignoring open request");
error= -1;
goto end;
}
@@ -1789,7 +1792,7 @@ prototype_redo_exec_hook(UNDO_KEY_INSERT)
if (keyseg->flag & HA_SWAP_KEY)
{
/* We put key from log record to "data record" packing format... */
- uchar reversed[HA_MAX_KEY_BUFF];
+ uchar reversed[MARIA_MAX_KEY_BUFF];
uchar *key_ptr= to;
uchar *key_end= key_ptr + keyseg->length;
to= reversed + keyseg->length;
diff --git a/storage/maria/ma_rename.c b/storage/maria/ma_rename.c
index 24a5e15d9cf..e9501d21350 100644
--- a/storage/maria/ma_rename.c
+++ b/storage/maria/ma_rename.c
@@ -95,7 +95,8 @@ int maria_rename(const char *old_name, const char *new_name)
store LSN into file, needed for Recovery to not be confused if a
RENAME happened (applying REDOs to the wrong table).
*/
- if (_ma_update_state_lsns(share, lsn, TRUE, TRUE))
+ if (_ma_update_state_lsns(share, lsn, share->state.create_trid, TRUE,
+ TRUE))
{
maria_close(info);
DBUG_RETURN(1);
diff --git a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c
index 27584e3db0b..9e529aca666 100644
--- a/storage/maria/ma_rkey.c
+++ b/storage/maria/ma_rkey.c
@@ -18,17 +18,22 @@
#include "maria_def.h"
#include "ma_rt_index.h"
- /* Read a record using key */
- /* Ordinary search_flag is 0 ; Give error if no record with key */
+/**
+ Read a record using key
-int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
+ @note
+ Ordinary search_flag is 0 ; Give error if no record with key
+*/
+
+int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key_data,
key_part_map keypart_map, enum ha_rkey_function search_flag)
{
uchar *key_buff;
MARIA_SHARE *share= info->s;
MARIA_KEYDEF *keyinfo;
HA_KEYSEG *last_used_keyseg;
- uint pack_key_length, use_key_length, nextflag;
+ uint32 nextflag;
+ MARIA_KEY key;
DBUG_ENTER("maria_rkey");
DBUG_PRINT("enter", ("base: 0x%lx buf: 0x%lx inx: %d search_flag: %d",
(long) info, (long) buf, inx, search_flag));
@@ -40,6 +45,8 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
info->last_key_func= search_flag;
keyinfo= share->keyinfo + inx;
+ key_buff= info->lastkey_buff+info->s->base.max_key_length;
+
if (info->once_flags & USE_PACKED_KEYS)
{
info->once_flags&= ~USE_PACKED_KEYS; /* Reset flag */
@@ -47,40 +54,39 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
key is already packed!; This happens when we are using a MERGE TABLE
In this key 'key_part_map' is the length of the key !
*/
- key_buff= info->lastkey+info->s->base.max_key_length;
- pack_key_length= keypart_map;
- bmove(key_buff, key, pack_key_length);
- last_used_keyseg= info->s->keyinfo[inx].seg + info->last_used_keyseg;
+ bmove(key_buff, key_data, keypart_map);
+ key.data= key_buff;
+ key.keyinfo= keyinfo;
+ key.data_length= keypart_map;
+ key.ref_length= 0;
+ key.flag= 0;
+
+ last_used_keyseg= keyinfo->seg + info->last_used_keyseg;
}
else
{
DBUG_ASSERT(keypart_map);
/* Save the packed key for later use in the second buffer of lastkey. */
- key_buff=info->lastkey+info->s->base.max_key_length;
- pack_key_length= _ma_pack_key(info,(uint) inx, key_buff, key,
- keypart_map, &last_used_keyseg);
+ _ma_pack_key(info, &key, inx, key_buff, key_data,
+ keypart_map, &last_used_keyseg);
/* Save packed_key_length for use by the MERGE engine. */
- info->pack_key_length= pack_key_length;
+ info->pack_key_length= key.data_length;
info->last_used_keyseg= (uint16) (last_used_keyseg -
- info->s->keyinfo[inx].seg);
- DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, keyinfo->seg,
- key_buff, pack_key_length););
+ keyinfo->seg);
+ DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, &key););
}
if (fast_ma_readinfo(info))
goto err;
if (share->lock_key_trees)
- rw_rdlock(&share->key_root_lock[inx]);
+ rw_rdlock(&keyinfo->root_lock);
- nextflag=maria_read_vec[search_flag];
- use_key_length=pack_key_length;
- if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
- use_key_length=USE_WHOLE_KEY;
+ nextflag= maria_read_vec[search_flag] | key.flag;
- switch (info->s->keyinfo[inx].key_alg) {
+ switch (keyinfo->key_alg) {
#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
- if (maria_rtree_find_first(info,inx,key_buff,use_key_length,nextflag) < 0)
+ if (maria_rtree_find_first(info, &key, nextflag) < 0)
{
maria_print_error(info->s, HA_ERR_CRASHED);
my_errno= HA_ERR_CRASHED;
@@ -90,74 +96,66 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
#endif
case HA_KEY_ALG_BTREE:
default:
- if (!_ma_search(info, keyinfo, key_buff, use_key_length,
- maria_read_vec[search_flag],
- info->s->state.key_root[inx]) &&
- share->non_transactional_concurrent_insert)
- {
+ if (!_ma_search(info, &key, nextflag, info->s->state.key_root[inx]))
+ {
+ MARIA_KEY lastkey;
+ lastkey.keyinfo= keyinfo;
+ lastkey.data= info->lastkey_buff;
/*
Found a key, but it might not be usable. We cannot use rows that
are inserted by other threads after we got our table lock
("concurrent inserts"). The record may not even be present yet.
Keys are inserted into the index(es) before the record is
- inserted into the data file. When we got our table lock, we
- saved the current data_file_length. Concurrent inserts always go
- to the end of the file. So we can test if the found key
- references a new record.
+ inserted into the data file.
*/
- if (info->cur_row.lastpos >= info->state->data_file_length)
+ if ((*share->row_is_visible)(info))
+ break;
+
+ /* The key references a concurrently inserted record. */
+ if (search_flag == HA_READ_KEY_EXACT &&
+ last_used_keyseg == keyinfo->seg + keyinfo->keysegs)
+ {
+ /* Simply ignore the key if it matches exactly. (Bug #29838) */
+ my_errno= HA_ERR_KEY_NOT_FOUND;
+ info->cur_row.lastpos= HA_OFFSET_ERROR;
+ break;
+ }
+
+ do
{
- /* The key references a concurrently inserted record. */
- if (search_flag == HA_READ_KEY_EXACT &&
- last_used_keyseg == keyinfo->seg + keyinfo->keysegs)
+ uint not_used[2];
+ /*
+ Skip rows that are inserted by other threads since we got
+ a lock. Note that this can only happen if we are not
+ searching after a full length exact key, because the keys
+ are sorted according to position.
+ */
+ lastkey.data_length= info->last_key.data_length;
+ lastkey.ref_length= info->last_key.ref_length;
+ lastkey.flag= info->last_key.flag;
+ if (_ma_search_next(info, &lastkey, maria_readnext_vec[search_flag],
+ info->s->state.key_root[inx]))
+ break; /* purecov: inspected */
+ /*
+ Check that the found key does still match the search.
+ _ma_search_next() delivers the next key regardless of its
+ value.
+ */
+ if (!(nextflag & (SEARCH_BIGGER | SEARCH_SMALLER)) &&
+ ha_key_cmp(keyinfo->seg, info->last_key.data, key.data,
+ key.data_length, SEARCH_FIND, not_used))
{
- /* Simply ignore the key if it matches exactly. (Bug #29838) */
+ /* purecov: begin inspected */
my_errno= HA_ERR_KEY_NOT_FOUND;
info->cur_row.lastpos= HA_OFFSET_ERROR;
+ break;
+ /* purecov: end */
}
- else
- {
- /*
- If searching for a partial key (or using >, >=, < or <=) and
- the data is outside of the data file, we need to continue
- searching for the first key inside the data file.
- */
- do
- {
- uint not_used[2];
- /*
- Skip rows that are inserted by other threads since we got
- a lock. Note that this can only happen if we are not
- searching after a full length exact key, because the keys
- are sorted according to position.
- */
- if (_ma_search_next(info, keyinfo, info->lastkey,
- info->lastkey_length,
- maria_readnext_vec[search_flag],
- info->s->state.key_root[inx]))
- break; /* purecov: inspected */
- /*
- Check that the found key does still match the search.
- _ma_search_next() delivers the next key regardless of its
- value.
- */
- if (search_flag == HA_READ_KEY_EXACT &&
- ha_key_cmp(keyinfo->seg, key_buff, info->lastkey,
- use_key_length, SEARCH_FIND, not_used))
- {
- /* purecov: begin inspected */
- my_errno= HA_ERR_KEY_NOT_FOUND;
- info->cur_row.lastpos= HA_OFFSET_ERROR;
- break;
- /* purecov: end */
- }
- } while (info->cur_row.lastpos >= info->state->data_file_length);
- }
- }
+ } while (!(*share->row_is_visible)(info));
}
}
if (share->lock_key_trees)
- rw_unlock(&share->key_root_lock[inx]);
+ rw_unlock(&keyinfo->root_lock);
if (info->cur_row.lastpos == HA_OFFSET_ERROR)
{
@@ -166,11 +164,11 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
}
/* Calculate length of the found key; Used by maria_rnext_same */
- if ((keyinfo->flag & HA_VAR_LENGTH_KEY) && last_used_keyseg)
- info->last_rkey_length= _ma_keylength_part(keyinfo, info->lastkey,
+ if ((keyinfo->flag & HA_VAR_LENGTH_KEY))
+ info->last_rkey_length= _ma_keylength_part(keyinfo, info->lastkey_buff,
last_used_keyseg);
else
- info->last_rkey_length= pack_key_length;
+ info->last_rkey_length= key.data_length;
/* Check if we don't want to have record back, only error message */
if (!buf)
@@ -188,10 +186,13 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
err:
/* Store last used key as a base for read next */
- memcpy(info->lastkey,key_buff,pack_key_length);
- info->last_rkey_length= pack_key_length;
- bzero((char*) info->lastkey+pack_key_length,info->s->base.rec_reflength);
- info->lastkey_length=pack_key_length+info->s->base.rec_reflength;
+ memcpy(info->last_key.data, key_buff, key.data_length);
+ info->last_key.data_length= key.data_length;
+ info->last_key.ref_length= info->s->base.rec_reflength;
+ info->last_key.flag= 0;
+ /* Create key with rowid 0 */
+ bzero((char*) info->last_key.data + info->last_key.data_length,
+ info->s->base.rec_reflength);
if (search_flag == HA_READ_AFTER_KEY)
info->update|=HA_STATE_NEXT_FOUND; /* Previous gives last row */
diff --git a/storage/maria/ma_rnext.c b/storage/maria/ma_rnext.c
index 0aab055e999..be960eccfe0 100644
--- a/storage/maria/ma_rnext.c
+++ b/storage/maria/ma_rnext.c
@@ -28,6 +28,8 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
{
int error,changed;
uint flag;
+ MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo;
DBUG_ENTER("maria_rnext");
if ((inx = _ma_check_index(info,inx)) < 0)
@@ -39,27 +41,30 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
if (fast_ma_readinfo(info))
DBUG_RETURN(my_errno);
- if (info->s->lock_key_trees)
- rw_rdlock(&info->s->key_root_lock[inx]);
+ keyinfo= share->keyinfo + inx;
+ if (share->lock_key_trees)
+ rw_rdlock(&keyinfo->root_lock);
changed= _ma_test_if_changed(info);
if (!flag)
{
- switch(info->s->keyinfo[inx].key_alg){
+ switch (keyinfo->key_alg){
#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
- error=maria_rtree_get_first(info,inx,info->lastkey_length);
+ error=maria_rtree_get_first(info, inx,
+ info->last_key.data_length +
+ info->last_key.ref_length);
+
break;
#endif
case HA_KEY_ALG_BTREE:
default:
- error= _ma_search_first(info,info->s->keyinfo+inx,
- info->s->state.key_root[inx]);
+ error= _ma_search_first(info, keyinfo, share->state.key_root[inx]);
break;
}
}
else
{
- switch (info->s->keyinfo[inx].key_alg) {
+ switch (keyinfo->key_alg) {
#ifdef HAVE_RTREE_KEYS
case HA_KEY_ALG_RTREE:
/*
@@ -67,38 +72,36 @@ int maria_rnext(MARIA_HA *info, uchar *buf, int inx)
may be changed since last call, so we do need
to skip rows inserted by other threads like in btree
*/
- error= maria_rtree_get_next(info,inx,info->lastkey_length);
+ error= maria_rtree_get_next(info, inx, info->last_key.data_length +
+ info->last_key.ref_length);
break;
#endif
case HA_KEY_ALG_BTREE:
default:
if (!changed)
- error= _ma_search_next(info,info->s->keyinfo+inx,info->lastkey,
- info->lastkey_length,flag,
- info->s->state.key_root[inx]);
+ error= _ma_search_next(info, &info->last_key,
+ flag | info->last_key.flag,
+ share->state.key_root[inx]);
else
- error= _ma_search(info,info->s->keyinfo+inx,info->lastkey,
- USE_WHOLE_KEY,flag, info->s->state.key_root[inx]);
+ error= _ma_search(info, &info->last_key, flag | info->last_key.flag,
+ share->state.key_root[inx]);
}
}
- if (info->s->non_transactional_concurrent_insert)
+ if (!error)
{
- if (!error)
+ while (!(*share->row_is_visible)(info))
{
- while (info->cur_row.lastpos >= info->state->data_file_length)
- {
- /* Skip rows inserted by other threads since we got a lock */
- if ((error= _ma_search_next(info,info->s->keyinfo+inx,
- info->lastkey,
- info->lastkey_length,
- SEARCH_BIGGER,
- info->s->state.key_root[inx])))
- break;
- }
+ /* Skip rows inserted by other threads since we got a lock */
+ if ((error= _ma_search_next(info, &info->last_key,
+ SEARCH_BIGGER,
+ share->state.key_root[inx])))
+ break;
}
- rw_unlock(&info->s->key_root_lock[inx]);
}
+ if (share->lock_key_trees)
+ rw_unlock(&keyinfo->root_lock);
+
/* Don't clear if database-changed */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
info->update|= HA_STATE_NEXT_FOUND;
diff --git a/storage/maria/ma_rnext_same.c b/storage/maria/ma_rnext_same.c
index ffb84e04776..d6d115c7f70 100644
--- a/storage/maria/ma_rnext_same.c
+++ b/storage/maria/ma_rnext_same.c
@@ -35,12 +35,12 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
if ((int) (inx= info->lastinx) < 0 ||
info->cur_row.lastpos == HA_OFFSET_ERROR)
DBUG_RETURN(my_errno=HA_ERR_WRONG_INDEX);
- keyinfo= info->s->keyinfo+inx;
if (fast_ma_readinfo(info))
DBUG_RETURN(my_errno);
+ keyinfo= info->s->keyinfo+inx;
if (info->s->lock_key_trees)
- rw_rdlock(&info->s->key_root_lock[inx]);
+ rw_rdlock(&keyinfo->root_lock);
switch (keyinfo->key_alg) {
#ifdef HAVE_RTREE_KEYS
@@ -60,17 +60,19 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
if (!(info->update & HA_STATE_RNEXT_SAME))
{
/* First rnext_same; Store old key */
- memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
+ memcpy(info->lastkey_buff2, info->last_key.data,
+ info->last_rkey_length);
}
for (;;)
{
- if ((error= _ma_search_next(info,keyinfo,info->lastkey,
- info->lastkey_length,SEARCH_BIGGER,
+ if ((error= _ma_search_next(info, &info->last_key,
+ SEARCH_BIGGER,
info->s->state.key_root[inx])))
break;
- if (ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey,
- (uchar*) info->lastkey2,
- info->last_rkey_length, SEARCH_FIND, not_used))
+ if (ha_key_cmp(keyinfo->seg, (uchar*) info->last_key.data,
+ (uchar*) info->lastkey_buff2,
+ info->last_rkey_length, SEARCH_FIND,
+ not_used))
{
error=1;
my_errno=HA_ERR_END_OF_FILE;
@@ -78,13 +80,12 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
break;
}
/* Skip rows that are inserted by other threads since we got a lock */
- if (!info->s->non_transactional_concurrent_insert ||
- info->cur_row.lastpos < info->state->data_file_length)
+ if ((info->s->row_is_visible)(info))
break;
}
}
if (info->s->lock_key_trees)
- rw_unlock(&info->s->key_root_lock[inx]);
+ rw_unlock(&keyinfo->root_lock);
/* Don't clear if database-changed */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
info->update|= HA_STATE_NEXT_FOUND | HA_STATE_RNEXT_SAME;
diff --git a/storage/maria/ma_rprev.c b/storage/maria/ma_rprev.c
index 39383f662f8..b9f46d7c405 100644
--- a/storage/maria/ma_rprev.c
+++ b/storage/maria/ma_rprev.c
@@ -27,6 +27,7 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
int error,changed;
register uint flag;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo;
DBUG_ENTER("maria_rprev");
if ((inx = _ma_check_index(info,inx)) < 0)
@@ -38,37 +39,33 @@ int maria_rprev(MARIA_HA *info, uchar *buf, int inx)
if (fast_ma_readinfo(info))
DBUG_RETURN(my_errno);
+ keyinfo= share->keyinfo + inx;
changed= _ma_test_if_changed(info);
if (share->lock_key_trees)
- rw_rdlock(&share->key_root_lock[inx]);
+ rw_rdlock(&keyinfo->root_lock);
if (!flag)
- error= _ma_search_last(info, share->keyinfo+inx,
- share->state.key_root[inx]);
+ error= _ma_search_last(info, keyinfo, share->state.key_root[inx]);
else if (!changed)
- error= _ma_search_next(info,share->keyinfo+inx,info->lastkey,
- info->lastkey_length,flag,
- share->state.key_root[inx]);
+ error= _ma_search_next(info, &info->last_key,
+ flag | info->last_key.flag,
+ share->state.key_root[inx]);
else
- error= _ma_search(info,share->keyinfo+inx,info->lastkey,
- USE_WHOLE_KEY, flag, share->state.key_root[inx]);
+ error= _ma_search(info, &info->last_key, flag | info->last_key.flag,
+ share->state.key_root[inx]);
- if (share->non_transactional_concurrent_insert)
+ if (!error)
{
- if (!error)
+ while (!(*share->row_is_visible)(info))
{
- while (info->cur_row.lastpos >= info->state->data_file_length)
- {
- /* Skip rows that are inserted by other threads since we got a lock */
- if ((error= _ma_search_next(info,share->keyinfo+inx,info->lastkey,
- info->lastkey_length,
- SEARCH_SMALLER,
- share->state.key_root[inx])))
- break;
- }
+ /* Skip rows that are inserted by other threads since we got a lock */
+ if ((error= _ma_search_next(info, &info->last_key,
+ SEARCH_SMALLER,
+ share->state.key_root[inx])))
+ break;
}
}
if (share->lock_key_trees)
- rw_unlock(&share->key_root_lock[inx]);
+ rw_unlock(&keyinfo->root_lock);
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
info->update|= HA_STATE_PREV_FOUND;
if (error)
diff --git a/storage/maria/ma_rsame.c b/storage/maria/ma_rsame.c
index 015a3816392..4bdbfd526ba 100644
--- a/storage/maria/ma_rsame.c
+++ b/storage/maria/ma_rsame.c
@@ -15,16 +15,20 @@
#include "maria_def.h"
-/*
+/**
Find current row with read on position or read on key
- NOTES
- If inx >= 0 find record using key
+ @notes
+ If inx >= 0 find record using key
- RETURN
- 0 Ok
- HA_ERR_KEY_NOT_FOUND Row is deleted
- HA_ERR_END_OF_FILE End of file
+ @warning
+ This function is not row version safe.
+ This is not crtical as this function is not used by MySQL
+
+ @return
+ @retval 0 Ok
+ @retval HA_ERR_KEY_NOT_FOUND Row is deleted
+ @retval HA_ERR_END_OF_FILE End of file
*/
@@ -51,16 +55,18 @@ int maria_rsame(MARIA_HA *info, uchar *record, int inx)
if (inx >= 0)
{
- info->lastinx=inx;
- info->lastkey_length= _ma_make_key(info,(uint) inx,info->lastkey,record,
- info->cur_row.lastpos);
+ MARIA_KEYDEF *keyinfo= info->s->keyinfo + inx;
+ info->lastinx= inx;
+ (*keyinfo->make_key)(info, &info->last_key, (uint) inx,
+ info->lastkey_buff, record,
+ info->cur_row.lastpos,
+ info->cur_row.trid);
if (info->s->lock_key_trees)
- rw_rdlock(&info->s->key_root_lock[inx]);
- VOID(_ma_search(info,info->s->keyinfo+inx,info->lastkey, USE_WHOLE_KEY,
- SEARCH_SAME,
+ rw_rdlock(&keyinfo->root_lock);
+ VOID(_ma_search(info, &info->last_key, SEARCH_SAME,
info->s->state.key_root[inx]));
if (info->s->lock_key_trees)
- rw_unlock(&info->s->key_root_lock[inx]);
+ rw_unlock(&keyinfo->root_lock);
}
if (!(*info->read_record)(info, record, info->cur_row.lastpos))
diff --git a/storage/maria/ma_rsamepos.c b/storage/maria/ma_rsamepos.c
index 186bc80c06d..d2099e7b116 100644
--- a/storage/maria/ma_rsamepos.c
+++ b/storage/maria/ma_rsamepos.c
@@ -19,13 +19,16 @@
#include "maria_def.h"
- /*
- ** If inx >= 0 update index pointer
- ** Returns one of the following values:
- ** 0 = Ok.
- ** HA_ERR_KEY_NOT_FOUND = Row is deleted
- ** HA_ERR_END_OF_FILE = End of file
- */
+/*
+ Read row based on postion
+
+ @param inx If inx >= 0 postion the given index on found row
+
+ @return
+ @retval 0 Ok
+ @retval HA_ERR_KEY_NOT_FOUND Row is deleted
+ @retval HA_ERR_END_OF_FILE End of file
+*/
int maria_rsame_with_pos(MARIA_HA *info, uchar *record, int inx,
MARIA_RECORD_POS filepos)
@@ -50,8 +53,10 @@ int maria_rsame_with_pos(MARIA_HA *info, uchar *record, int inx,
info->lastinx= inx;
if (inx >= 0)
{
- info->lastkey_length= _ma_make_key(info,(uint) inx,info->lastkey,record,
- info->cur_row.lastpos);
+ (*info->s->keyinfo[inx].make_key)(info, &info->last_key, (uint) inx,
+ info->lastkey_buff,
+ record, info->cur_row.lastpos,
+ info->cur_row.trid);
info->update|=HA_STATE_KEY_CHANGED; /* Don't use indexposition */
}
DBUG_RETURN(0);
diff --git a/storage/maria/ma_rt_index.c b/storage/maria/ma_rt_index.c
index a0ab8c722ad..ccdddf5906d 100644
--- a/storage/maria/ma_rt_index.c
+++ b/storage/maria/ma_rt_index.c
@@ -55,17 +55,17 @@ typedef struct st_page_list
*/
static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uint search_flag,
+ uint32 search_flag,
uint nod_cmp_flag, my_off_t page, int level)
{
MARIA_SHARE *share= info->s;
uint nod_flag;
int res;
uchar *page_buf, *k, *last;
- int k_len;
+ int key_data_length;
uint *saved_key= (uint*) (info->maria_rtree_recursion_state) + level;
- if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length)))
+ if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
{
my_errno= HA_ERR_OUT_OF_MEM;
return -1;
@@ -75,7 +75,7 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
goto err1;
nod_flag= _ma_test_if_nod(share, page_buf);
- k_len= keyinfo->keylength - share->base.rec_reflength;
+ key_data_length= keyinfo->keylength - share->base.rec_reflength;
if (info->maria_rtree_recursion_depth >= level)
{
@@ -87,7 +87,7 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
last= rt_PAGE_END(share, page_buf);
- for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, k_len, nod_flag))
+ for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_data_length, nod_flag))
{
if (nod_flag)
{
@@ -119,10 +119,24 @@ static int maria_rtree_find_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
if (!maria_rtree_key_cmp(keyinfo->seg, info->first_mbr_key,
k, info->last_rkey_length, search_flag))
{
- uchar *after_key= (uchar*) rt_PAGE_NEXT_KEY(share, k, k_len, nod_flag);
- info->cur_row.lastpos= _ma_dpos(info, 0, after_key);
- info->lastkey_length= k_len + share->base.rec_reflength;
- memcpy(info->lastkey, k, info->lastkey_length);
+ uchar *after_key= rt_PAGE_NEXT_KEY(share, k, key_data_length, 0);
+ MARIA_KEY tmp_key;
+
+ /*
+ We don't need to set all MARIA_KEY elements here as
+ _ma_row_pos_from_key() only uses a few of them.
+ */
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= k;
+ tmp_key.data_length= key_data_length;
+
+ info->cur_row.lastpos= _ma_row_pos_from_key(&tmp_key);
+ info->last_key.keyinfo= keyinfo;
+ info->last_key.data_length= key_data_length;
+ info->last_key.ref_length= share->base.rec_reflength;
+ info->last_key.flag= 0;
+ memcpy(info->last_key.data, k,
+ info->last_key.data_length + info->last_key.ref_length);
info->maria_rtree_recursion_depth= level;
*saved_key= last - page_buf;
@@ -165,9 +179,7 @@ err1:
SYNOPSIS
maria_rtree_find_first()
info Handler to MARIA file
- uint keynr Key number to use
key Key to search for
- key_length Length of 'key'
search_flag Bitmap of flags how to do the search
RETURN
@@ -176,14 +188,13 @@ err1:
1 Not found
*/
-int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key,
- uint key_length, uint search_flag)
+int maria_rtree_find_first(MARIA_HA *info, MARIA_KEY *key, uint32 search_flag)
{
my_off_t root;
uint nod_cmp_flag;
- MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
- if ((root= info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ if ((root= info->s->state.key_root[keyinfo->key_nr]) == HA_OFFSET_ERROR)
{
my_errno= HA_ERR_END_OF_FILE;
return -1;
@@ -194,8 +205,8 @@ int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key,
The data pointer is required if the search_flag contains MBR_DATA.
(minimum bounding rectangle)
*/
- memcpy(info->first_mbr_key, key, keyinfo->keylength);
- info->last_rkey_length= key_length;
+ memcpy(info->first_mbr_key, key->data, key->data_length + key->ref_length);
+ info->last_rkey_length= key->data_length;
info->maria_rtree_recursion_depth= -1;
info->keyread_buff_used= 1;
@@ -222,16 +233,15 @@ int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key,
1 Not found
*/
-int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag)
+int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint32 search_flag)
{
my_off_t root;
- uint nod_cmp_flag;
+ uint32 nod_cmp_flag;
MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr;
+ DBUG_ASSERT(info->last_key.keyinfo == keyinfo);
if (info->update & HA_STATE_DELETED)
- return maria_rtree_find_first(info, keynr, info->lastkey,
- info->lastkey_length,
- search_flag);
+ return maria_rtree_find_first(info, &info->last_key, search_flag);
if (!info->keyread_buff_used)
{
@@ -244,9 +254,18 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag)
info->last_rkey_length, search_flag))
{
uchar *after_key= key + keyinfo->keylength;
-
- info->cur_row.lastpos= _ma_dpos(info, 0, after_key);
- memcpy(info->lastkey, key, info->lastkey_length);
+ MARIA_KEY tmp_key;
+
+ /*
+ We don't need to set all MARIA_KEY elements here as
+ _ma_row_pos_from_key only uses a few of them.
+ */
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= key;
+ tmp_key.data_length= keyinfo->keylength - info->s->base.rec_reflength;
+
+ info->cur_row.lastpos= _ma_row_pos_from_key(&tmp_key);
+ memcpy(info->last_key.data, key, info->last_key.data_length);
if (after_key < info->int_maxpos)
info->int_keypos= after_key;
@@ -263,9 +282,10 @@ int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag)
return -1;
}
- nod_cmp_flag= ((search_flag & (MBR_EQUAL | MBR_WITHIN)) ?
- MBR_WITHIN : MBR_INTERSECT);
- return maria_rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root, 0);
+ nod_cmp_flag= (((search_flag & (MBR_EQUAL | MBR_WITHIN)) ?
+ MBR_WITHIN : MBR_INTERSECT));
+ return maria_rtree_find_req(info, keyinfo, search_flag, nod_cmp_flag, root,
+ 0);
}
@@ -286,27 +306,27 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
{
MARIA_SHARE *share= info->s;
uchar *page_buf, *last, *k;
- uint nod_flag, k_len;
+ uint nod_flag, key_data_length;
int res;
uint *saved_key= (uint*) (info->maria_rtree_recursion_state) + level;
- if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length)))
+ if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
return -1;
if (!_ma_fetch_keypage(info, keyinfo, page, PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, page_buf, 0, 0))
goto err1;
nod_flag= _ma_test_if_nod(share, page_buf);
- k_len= keyinfo->keylength - share->base.rec_reflength;
+ key_data_length= keyinfo->keylength - share->base.rec_reflength;
- if(info->maria_rtree_recursion_depth >= level)
+ if (info->maria_rtree_recursion_depth >= level)
{
k= page_buf + *saved_key;
if (!nod_flag)
{
/* Only leaf pages contain data references. */
/* Need to check next key with data reference. */
- k= rt_PAGE_NEXT_KEY(share, k, k_len, nod_flag);
+ k= rt_PAGE_NEXT_KEY(share, k, key_data_length, nod_flag);
}
}
else
@@ -315,7 +335,7 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
last= rt_PAGE_END(share, page_buf);
- for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, k_len, nod_flag))
+ for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_data_length, nod_flag))
{
if (nod_flag)
{
@@ -337,10 +357,23 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
else
{
/* this is a leaf */
- uchar *after_key= rt_PAGE_NEXT_KEY(share, k, k_len, nod_flag);
- info->cur_row.lastpos= _ma_dpos(info, 0, after_key);
- info->lastkey_length= k_len + share->base.rec_reflength;
- memcpy(info->lastkey, k, info->lastkey_length);
+ uchar *after_key= rt_PAGE_NEXT_KEY(share, k, key_data_length, 0);
+ MARIA_KEY tmp_key;
+
+ /*
+ We don't need to set all MARIA_KEY elements here as
+ _ma_row_pos_from_key() only uses a few of them.
+ */
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= k;
+ tmp_key.data_length= key_data_length;
+
+ info->cur_row.lastpos= _ma_row_pos_from_key(&tmp_key);
+ info->last_key.data_length= key_data_length;
+ info->last_key.ref_length= share->base.rec_reflength;
+
+ memcpy(info->last_key.data, k,
+ info->last_key.data_length + info->last_key.ref_length);
info->maria_rtree_recursion_depth= level;
*saved_key= k - page_buf;
@@ -348,7 +381,7 @@ static int maria_rtree_get_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
if (after_key < last)
{
uchar *keyread_buff= info->keyread_buff;
- info->int_keypos= (uchar*) saved_key;
+ info->last_rtree_keypos= saved_key;
memcpy(keyread_buff, page_buf, keyinfo->block_length);
info->int_maxpos= rt_PAGE_END(share, keyread_buff);
info->keyread_buff_used= 0;
@@ -421,18 +454,23 @@ int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length)
if (!info->keyread_buff_used)
{
- uint k_len= keyinfo->keylength - info->s->base.rec_reflength;
- /* rt_PAGE_NEXT_KEY(info->int_keypos) */
- uchar *key= keyread_buff + *(int*)info->int_keypos + k_len +
- info->s->base.rec_reflength;
+ uint key_data_length= keyinfo->keylength - info->s->base.rec_reflength;
+ /* rt_PAGE_NEXT_KEY(*info->last_rtree_keypos) */
+ uchar *key= keyread_buff + *info->last_rtree_keypos + keyinfo->keylength;
/* rt_PAGE_NEXT_KEY(key) */
- uchar *after_key= key + k_len + info->s->base.rec_reflength;
+ uchar *after_key= key + keyinfo->keylength;
+ MARIA_KEY tmp_key;
+
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= key;
+ tmp_key.data_length= key_data_length;
+ tmp_key.ref_length= info->s->base.rec_reflength;
+ tmp_key.flag= 0;
- info->cur_row.lastpos= _ma_dpos(info, 0, after_key);
- info->lastkey_length= k_len + info->s->base.rec_reflength;
- memcpy(info->lastkey, key, k_len + info->s->base.rec_reflength);
+ info->cur_row.lastpos= _ma_row_pos_from_key(&tmp_key);
+ _ma_copy_key(&info->last_key, &tmp_key);
- *(int*)info->int_keypos= key - keyread_buff;
+ *info->last_rtree_keypos= (uint) (key - keyread_buff);
if (after_key >= info->int_maxpos)
{
info->keyread_buff_used= 1;
@@ -460,9 +498,8 @@ int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length)
*/
#ifdef PICK_BY_PERIMETER
static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
- const MARIA_KEYDEF *keyinfo,
- const uchar *key,
- uint key_length, const uchar *page_buf,
+ const MARIA_KEY *key,
+ const uchar *page_buf,
uint nod_flag)
{
double increase;
@@ -477,10 +514,10 @@ static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
LINT_INIT(best_key);
LINT_INIT(best_incr);
- for (; k < last; k= rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
+ for (; k < last; k= rt_PAGE_NEXT_KEY(k, key->data_length, nod_flag))
{
- if ((increase= maria_rtree_perimeter_increase(keyinfo->seg, k, key, key_length,
- &perimeter)) == -1)
+ if ((increase= maria_rtree_perimeter_increase(keyinfo->seg, k, key,
+ &perimeter)) == -1)
return NULL;
if ((increase < best_incr)||
(increase == best_incr && perimeter < best_perimeter))
@@ -497,9 +534,8 @@ static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
#ifdef PICK_BY_AREA
static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
- const MARIA_KEYDEF *keyinfo,
- const uchar *key,
- uint key_length, const uchar *page_buf,
+ const MARIA_KEY *key,
+ const uchar *page_buf,
uint nod_flag)
{
MARIA_SHARE *share= info->s;
@@ -513,11 +549,14 @@ static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
LINT_INIT(best_area);
- for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_length, nod_flag))
+ for (; k < last;
+ k= rt_PAGE_NEXT_KEY(share, k, key->data_length, nod_flag))
{
/* The following is safe as -1.0 is an exact number */
- if ((increase= maria_rtree_area_increase(keyinfo->seg, k, key, key_length,
- &area)) == -1.0)
+ if ((increase= maria_rtree_area_increase(key->keyinfo->seg, k, key->data,
+ key->data_length +
+ key->ref_length,
+ &area)) == -1.0)
return NULL;
/* The following should be safe, even if we compare doubles */
if (!best_key || increase < best_incr ||
@@ -542,22 +581,21 @@ static const uchar *maria_rtree_pick_key(const MARIA_HA *info,
1 Child was split
*/
-static int maria_rtree_insert_req(MARIA_HA *info,
- const MARIA_KEYDEF *keyinfo,
- const uchar *key,
- uint key_length, my_off_t page,
- my_off_t *new_page,
+static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEY *key,
+ my_off_t page, my_off_t *new_page,
int ins_level, int level)
{
uint nod_flag, page_link_idx;
+ uint key_length= key->data_length;
int res;
uchar *page_buf, *k;
MARIA_PINNED_PAGE *page_link;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("maria_rtree_insert_req");
- if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length +
- HA_MAX_KEY_BUFF)))
+ if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length +
+ MARIA_MAX_KEY_BUFF)))
{
my_errno= HA_ERR_OUT_OF_MEM;
DBUG_RETURN(-1); /* purecov: inspected */
@@ -573,17 +611,16 @@ static int maria_rtree_insert_req(MARIA_HA *info,
if ((ins_level == -1 && nod_flag) || /* key: go down to leaf */
(ins_level > -1 && ins_level > level)) /* branch: go down to ins_level */
{
- if ((k= (uchar *)maria_rtree_pick_key(info, keyinfo, key, key_length,
- page_buf, nod_flag)) == NULL)
+ if (!(k= (uchar *)maria_rtree_pick_key(info, key, page_buf, nod_flag)))
goto err1;
/* k is now a pointer inside the page_buf buffer */
- switch ((res= maria_rtree_insert_req(info, keyinfo, key, key_length,
- _ma_kpos(nod_flag, k), new_page,
- ins_level, level + 1)))
+ switch ((res= maria_rtree_insert_req(info, key,
+ _ma_kpos(nod_flag, k), new_page,
+ ins_level, level + 1)))
{
case 0: /* child was not split, most common case */
{
- maria_rtree_combine_rect(keyinfo->seg, k, key, k, key_length);
+ maria_rtree_combine_rect(keyinfo->seg, k, key->data, k, key_length);
if (share->now_transactional &&
_ma_log_change(info, page, page_buf, k, key_length))
goto err1;
@@ -596,21 +633,30 @@ static int maria_rtree_insert_req(MARIA_HA *info,
}
case 1: /* child was split */
{
- uchar *new_key= page_buf + keyinfo->block_length + nod_flag;
+ /* Set new_key to point to a free buffer area */
+ uchar *new_key_buff= page_buf + keyinfo->block_length + nod_flag;
+ MARIA_KEY new_key;
+ MARIA_KEY k_key;
+
+ DBUG_ASSERT(nod_flag);
+ k_key.keyinfo= new_key.keyinfo= keyinfo;
+ new_key.data= new_key_buff;
+ k_key.data= k;
+ k_key.data_length= new_key.data_length= key->data_length;
+ k_key.ref_length= new_key.ref_length= key->ref_length;
+ k_key.flag= new_key.flag= 0; /* Safety */
+
/* set proper MBR for key */
- if (maria_rtree_set_key_mbr(info, keyinfo, k, key_length,
- _ma_kpos(nod_flag, k)))
+ if (maria_rtree_set_key_mbr(info, &k_key, _ma_kpos(nod_flag, k)))
goto err1;
if (share->now_transactional &&
_ma_log_change(info, page, page_buf, k, key_length))
goto err1;
/* add new key for new page */
- _ma_kpointer(info, new_key - nod_flag, *new_page);
- if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length,
- *new_page))
+ _ma_kpointer(info, new_key_buff - nod_flag, *new_page);
+ if (maria_rtree_set_key_mbr(info, &new_key, *new_page))
goto err1;
- res= maria_rtree_add_key(info, keyinfo, new_key, key_length,
- page_buf, page, new_page);
+ res= maria_rtree_add_key(info, &new_key, page_buf, page, new_page);
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_write_keypage(info, keyinfo, page,
PAGECACHE_LOCK_LEFT_WRITELOCKED,
@@ -627,8 +673,7 @@ static int maria_rtree_insert_req(MARIA_HA *info,
}
else
{
- res= maria_rtree_add_key(info, keyinfo, key, key_length, page_buf,
- page, new_page);
+ res= maria_rtree_add_key(info, key, page_buf, page, new_page);
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_write_keypage(info, keyinfo, page, PAGECACHE_LOCK_LEFT_WRITELOCKED,
DFLT_INIT_HITS, page_buf))
@@ -640,8 +685,8 @@ ok:
DBUG_RETURN(res);
err1:
- my_afree(page_buf);
- DBUG_RETURN(-1); /* purecov: inspected */
+ res= -1; /* purecov: inspected */
+ goto ok; /* purecov: inspected */
}
@@ -649,9 +694,7 @@ err1:
Insert key into the tree
@param info table
- @param keynr key's number
- @param key key to insert
- @param key_length key's length
+ @param key KEY to insert
@param ins_level at which level key insertion should start
@param root put new key_root there
@@ -661,19 +704,19 @@ err1:
@retval 1 Root was split
*/
-int maria_rtree_insert_level(MARIA_HA *info, uint keynr, const uchar *key,
- uint key_length, int ins_level, my_off_t *root)
+int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key, int ins_level,
+ my_off_t *root)
{
my_off_t old_root;
MARIA_SHARE *share= info->s;
- MARIA_KEYDEF *keyinfo= share->keyinfo + keynr;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
int res;
my_off_t new_page;
MARIA_PINNED_PAGE *page_link;
enum pagecache_page_lock write_lock;
DBUG_ENTER("maria_rtree_insert_level");
- if ((old_root= share->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ if ((old_root= share->state.key_root[keyinfo->key_nr]) == HA_OFFSET_ERROR)
{
MARIA_PINNED_PAGE tmp_page_link;
page_link= &tmp_page_link;
@@ -683,7 +726,7 @@ int maria_rtree_insert_level(MARIA_HA *info, uint keynr, const uchar *key,
write_lock= page_link->write_lock;
info->keyread_buff_used= 1;
bzero(info->buff, share->block_size);
- _ma_store_keynr(share, info->buff, keynr);
+ _ma_store_keynr(share, info->buff, keyinfo->key_nr);
_ma_store_page_used(share, info->buff, share->keypage_header);
if (share->now_transactional &&
@@ -691,8 +734,7 @@ int maria_rtree_insert_level(MARIA_HA *info, uint keynr, const uchar *key,
keyinfo->key_nr, 1))
DBUG_RETURN(1);
- res= maria_rtree_add_key(info, keyinfo, key, key_length, info->buff,
- old_root, NULL);
+ res= maria_rtree_add_key(info, key, info->buff, old_root, NULL);
if (_ma_write_keypage(info, keyinfo, old_root, write_lock,
DFLT_INIT_HITS, info->buff))
DBUG_RETURN(1);
@@ -700,8 +742,8 @@ int maria_rtree_insert_level(MARIA_HA *info, uint keynr, const uchar *key,
DBUG_RETURN(res);
}
- switch ((res= maria_rtree_insert_req(info, keyinfo, key, key_length,
- old_root, &new_page, ins_level, 0)))
+ switch ((res= maria_rtree_insert_req(info, key, old_root, &new_page,
+ ins_level, 0)))
{
case 0: /* root was not split */
{
@@ -709,15 +751,16 @@ int maria_rtree_insert_level(MARIA_HA *info, uint keynr, const uchar *key,
}
case 1: /* root was split, grow a new root; very rare */
{
- uchar *new_root_buf, *new_key;
+ uchar *new_root_buf, *new_key_buff;
my_off_t new_root;
uint nod_flag= share->base.key_reflength;
MARIA_PINNED_PAGE tmp_page_link;
+ MARIA_KEY new_key;
page_link= &tmp_page_link;
DBUG_PRINT("rtree", ("root was split, grow a new root"));
- if (!(new_root_buf= (uchar*) my_alloca((uint)keyinfo->block_length +
- HA_MAX_KEY_BUFF)))
+ if (!(new_root_buf= (uchar*) my_alloca((uint) keyinfo->block_length +
+ MARIA_MAX_KEY_BUFF)))
{
my_errno= HA_ERR_OUT_OF_MEM;
DBUG_RETURN(-1); /* purecov: inspected */
@@ -726,7 +769,7 @@ int maria_rtree_insert_level(MARIA_HA *info, uint keynr, const uchar *key,
bzero(new_root_buf, share->block_size);
if (nod_flag)
_ma_store_keypage_flag(share, new_root_buf, KEYPAGE_FLAG_ISNOD);
- _ma_store_keynr(share, new_root_buf, keynr);
+ _ma_store_keynr(share, new_root_buf, keyinfo->key_nr);
_ma_store_page_used(share, new_root_buf, share->keypage_header);
if ((new_root= _ma_new(info, DFLT_INIT_HITS, &page_link)) ==
HA_OFFSET_ERROR)
@@ -738,22 +781,24 @@ int maria_rtree_insert_level(MARIA_HA *info, uint keynr, const uchar *key,
keyinfo->key_nr, 1))
goto err1;
- new_key= new_root_buf + keyinfo->block_length + nod_flag;
+ /* Point to some free space */
+ new_key_buff= new_root_buf + keyinfo->block_length + nod_flag;
+ new_key.keyinfo= keyinfo;
+ new_key.data= new_key_buff;
+ new_key.data_length= key->data_length;
+ new_key.ref_length= key->ref_length;
+ new_key.flag= 0;
- _ma_kpointer(info, new_key - nod_flag, old_root);
- if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length,
- old_root))
+ _ma_kpointer(info, new_key_buff - nod_flag, old_root);
+ if (maria_rtree_set_key_mbr(info, &new_key, old_root))
goto err1;
- if (maria_rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf,
- new_root, NULL)
+ if (maria_rtree_add_key(info, &new_key, new_root_buf, new_root, NULL)
== -1)
goto err1;
- _ma_kpointer(info, new_key - nod_flag, new_page);
- if (maria_rtree_set_key_mbr(info, keyinfo, new_key, key_length,
- new_page))
+ _ma_kpointer(info, new_key_buff - nod_flag, new_page);
+ if (maria_rtree_set_key_mbr(info, &new_key, new_page))
goto err1;
- if (maria_rtree_add_key(info, keyinfo, new_key, key_length, new_root_buf,
- new_root, NULL)
+ if (maria_rtree_add_key(info, &new_key, new_root_buf, new_root, NULL)
== -1)
goto err1;
if (_ma_write_keypage(info, keyinfo, new_root, write_lock,
@@ -785,30 +830,28 @@ err1:
Insert key into the tree - interface function
RETURN
- -1 Error
+ 1 Error
0 OK
*/
-int maria_rtree_insert(MARIA_HA *info, uint keynr,
- uchar *key, uint key_length)
+my_bool maria_rtree_insert(MARIA_HA *info, MARIA_KEY *key)
{
int res;
MARIA_SHARE *share= info->s;
- my_off_t *root= &share->state.key_root[keynr];
- my_off_t new_root= *root;
+ my_off_t *root, new_root;
LSN lsn= LSN_IMPOSSIBLE;
DBUG_ENTER("maria_rtree_insert");
- if (key_length == 0)
- {
- res= -1;
- goto err;
- }
- if ((res= -(maria_rtree_insert_level(info, keynr, key, key_length, -1,
- &new_root) == -1)) != 0)
+
+ if (!key)
+ DBUG_RETURN(1); /* _ma_sp_make_key failed */
+
+ root= &share->state.key_root[key->keyinfo->key_nr];
+ new_root= *root;
+
+ if ((res= (maria_rtree_insert_level(info, key, -1, &new_root) == -1)))
goto err;
if (share->now_transactional)
- res= _ma_write_undo_key_insert(info, share->keyinfo + keynr,
- key, key_length, root, new_root, &lsn);
+ res= _ma_write_undo_key_insert(info, key, root, new_root, &lsn);
else
{
*root= new_root;
@@ -816,7 +859,7 @@ int maria_rtree_insert(MARIA_HA *info, uint keynr,
}
_ma_unpin_all_pages_and_finalize_row(info, lsn);
err:
- DBUG_RETURN(res);
+ DBUG_RETURN(res != 0);
}
@@ -828,8 +871,8 @@ err:
0 OK
*/
-static int maria_rtree_fill_reinsert_list(stPageList *ReinsertList, my_off_t page,
- int level)
+static int maria_rtree_fill_reinsert_list(stPageList *ReinsertList,
+ my_off_t page, int level)
{
DBUG_ENTER("maria_rtree_fill_reinsert_list");
DBUG_PRINT("rtree", ("page: %lu level: %d", (ulong) page, level));
@@ -861,10 +904,8 @@ err1:
2 Empty leaf
*/
-static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- const uchar *key,
- uint key_length, my_off_t page,
- uint *page_size,
+static int maria_rtree_delete_req(MARIA_HA *info, const MARIA_KEY *key,
+ my_off_t page, uint *page_size,
stPageList *ReinsertList, int level)
{
ulong i;
@@ -873,9 +914,10 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uchar *page_buf, *last, *k;
MARIA_PINNED_PAGE *page_link;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("maria_rtree_delete_req");
- if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length)))
+ if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
{
my_errno= HA_ERR_OUT_OF_MEM;
DBUG_RETURN(-1); /* purecov: inspected */
@@ -893,29 +935,39 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
for (i= 0;
k < last;
- k= rt_PAGE_NEXT_KEY(share, k, key_length, nod_flag), i++)
+ k= rt_PAGE_NEXT_KEY(share, k, key->data_length, nod_flag), i++)
{
if (nod_flag)
{
/* not leaf */
- if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length, MBR_WITHIN))
+ if (!maria_rtree_key_cmp(keyinfo->seg, key->data, k, key->data_length,
+ MBR_WITHIN))
{
- switch ((res= maria_rtree_delete_req(info, keyinfo, key, key_length,
- _ma_kpos(nod_flag, k), page_size, ReinsertList, level + 1)))
+ switch ((res= maria_rtree_delete_req(info, key,
+ _ma_kpos(nod_flag, k),
+ page_size, ReinsertList,
+ level + 1)))
{
case 0: /* deleted */
{
/* test page filling */
- if (*page_size + key_length >=
+ if (*page_size + key->data_length >=
rt_PAGE_MIN_SIZE(keyinfo->block_length))
{
/* OK */
/* Calculate a new key value (MBR) for the shrinked block. */
- if (maria_rtree_set_key_mbr(info, keyinfo, k, key_length,
- _ma_kpos(nod_flag, k)))
+ MARIA_KEY tmp_key;
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= k;
+ tmp_key.data_length= key->data_length;
+ tmp_key.ref_length= key->ref_length;
+ tmp_key.flag= 0; /* Safety */
+
+ if (maria_rtree_set_key_mbr(info, &tmp_key,
+ _ma_kpos(nod_flag, k)))
goto err1;
if (share->now_transactional &&
- _ma_log_change(info, page, page_buf, k, key_length))
+ _ma_log_change(info, page, page_buf, k, key->data_length))
goto err1;
page_link_from_idx(info, page_link_idx)->changed= 1;
if (_ma_write_keypage(info, keyinfo, page,
@@ -933,7 +985,7 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
DBUG_PRINT("rtree", ("too small. move block to reinsert list"));
if (maria_rtree_fill_reinsert_list(ReinsertList,
_ma_kpos(nod_flag, k),
- level + 1))
+ level + 1))
goto err1;
/*
Delete the key that references the block. This makes the
@@ -943,7 +995,7 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
subtree. So we need to re-insert its keys on the same
level later to reintegrate the subtrees.
*/
- if (maria_rtree_delete_key(info, page_buf, k, key_length,
+ if (maria_rtree_delete_key(info, page_buf, k, key->data_length,
nod_flag, page))
goto err1;
page_link_from_idx(info, page_link_idx)->changed= 1;
@@ -962,7 +1014,7 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
case 2: /* vacuous case: last key in the leaf */
{
- if (maria_rtree_delete_key(info, page_buf, k, key_length,
+ if (maria_rtree_delete_key(info, page_buf, k, key->data_length,
nod_flag, page))
goto err1;
page_link_from_idx(info, page_link_idx)->changed= 1;
@@ -985,13 +1037,13 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
else
{
/* leaf */
- if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length,
+ if (!maria_rtree_key_cmp(keyinfo->seg, key->data, k, key->data_length,
MBR_EQUAL | MBR_DATA))
{
page_link_from_idx(info, page_link_idx)->changed= 1;
- if (maria_rtree_delete_key(info, page_buf, k, key_length, nod_flag,
- page))
+ if (maria_rtree_delete_key(info, page_buf, k, key->data_length,
+ nod_flag, page))
goto err1;
*page_size= _ma_get_page_used(share, page_buf);
if (*page_size == info->s->keypage_header)
@@ -1033,24 +1085,21 @@ err1:
0 Deleted
*/
-int maria_rtree_delete(MARIA_HA *info, uint keynr,
- uchar *key, uint key_length)
+int maria_rtree_delete(MARIA_HA *info, MARIA_KEY *key)
{
MARIA_SHARE *share= info->s;
- my_off_t new_root= share->state.key_root[keynr];
+ my_off_t new_root= share->state.key_root[key->keyinfo->key_nr];
int res;
LSN lsn= LSN_IMPOSSIBLE;
DBUG_ENTER("maria_rtree_delete");
- if ((res= maria_rtree_real_delete(info, keynr, key, key_length,
- &new_root)))
+ if ((res= maria_rtree_real_delete(info, key, &new_root)))
goto err;
if (share->now_transactional)
- res= _ma_write_undo_key_delete(info, keynr, key, key_length,
- new_root, &lsn);
+ res= _ma_write_undo_key_delete(info, key, new_root, &lsn);
else
- share->state.key_root[keynr]= new_root;
+ share->state.key_root[key->keyinfo->key_nr]= new_root;
err:
_ma_fast_unlock_key_del(info);
@@ -1059,20 +1108,21 @@ err:
}
-int maria_rtree_real_delete(MARIA_HA *info, uint keynr,
- const uchar *key, uint key_length,
+int maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key,
my_off_t *root)
{
- MARIA_SHARE *share= info->s;
+ int res;
uint page_size, page_link_idx;
stPageList ReinsertList;
my_off_t old_root;
- MARIA_KEYDEF *keyinfo= info->s->keyinfo + keynr;
MARIA_PINNED_PAGE *page_link, *root_page_link;
- int res;
+ MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ uint key_data_length= key->data_length;
DBUG_ENTER("maria_rtree_real_delete");
- if ((old_root= share->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ if ((old_root= share->state.key_root[keyinfo->key_nr]) ==
+ HA_OFFSET_ERROR)
{
my_errno= HA_ERR_END_OF_FILE;
DBUG_RETURN(-1); /* purecov: inspected */
@@ -1084,8 +1134,8 @@ int maria_rtree_real_delete(MARIA_HA *info, uint keynr,
ReinsertList.n_pages= 0;
ReinsertList.m_pages= 0;
- switch (maria_rtree_delete_req(info, keyinfo, key, key_length, old_root,
- &page_size, &ReinsertList, 0)) {
+ switch (maria_rtree_delete_req(info, key, old_root, &page_size,
+ &ReinsertList, 0)) {
case 2: /* empty */
{
*root= HA_OFFSET_ERROR;
@@ -1096,11 +1146,17 @@ int maria_rtree_real_delete(MARIA_HA *info, uint keynr,
{
uint nod_flag;
ulong i;
+ MARIA_KEY tmp_key;
+ tmp_key.keyinfo= key->keyinfo;
+ tmp_key.data_length= key->data_length;
+ tmp_key.ref_length= key->ref_length;
+ tmp_key.flag= 0; /* Safety */
+
for (i= 0; i < ReinsertList.n_pages; ++i)
{
uchar *page_buf, *k, *last;
- if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length)))
+ if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
{
my_errno= HA_ERR_OUT_OF_MEM;
goto err1;
@@ -1118,10 +1174,12 @@ int maria_rtree_real_delete(MARIA_HA *info, uint keynr,
k= rt_PAGE_FIRST_KEY(share, page_buf, nod_flag);
last= rt_PAGE_END(share, page_buf);
- for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_length, nod_flag))
+ for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_data_length,
+ nod_flag))
{
+ tmp_key.data= k;
if ((res=
- maria_rtree_insert_level(info, keynr, k, key_length,
+ maria_rtree_insert_level(info, &tmp_key,
ReinsertList.pages[i].level,
root)) == -1)
{
@@ -1159,7 +1217,7 @@ int maria_rtree_real_delete(MARIA_HA *info, uint keynr,
goto err1;
nod_flag= _ma_test_if_nod(share, info->buff);
page_size= _ma_get_page_used(share, info->buff);
- if (nod_flag && (page_size == share->keypage_header + key_length +
+ if (nod_flag && (page_size == share->keypage_header + key_data_length +
nod_flag))
{
*root= _ma_kpos(nod_flag,
@@ -1199,40 +1257,40 @@ err:
estimated value
*/
-ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key,
- uint key_length, uint flag)
+ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag)
{
- MARIA_SHARE *share= info->s;
- MARIA_KEYDEF *keyinfo= share->keyinfo + keynr;
my_off_t root;
uint i= 0;
- uint nod_flag, k_len;
+ uint nod_flag, key_data_length;
uchar *page_buf, *k, *last;
double area= 0;
ha_rows res= 0;
+ MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
if (flag & MBR_DISJOINT)
return info->state->records;
- if ((root= share->state.key_root[keynr]) == HA_OFFSET_ERROR)
+ if ((root= share->state.key_root[key->keyinfo->key_nr]) == HA_OFFSET_ERROR)
return HA_POS_ERROR;
- if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length)))
+ if (!(page_buf= (uchar*) my_alloca((uint) keyinfo->block_length)))
return HA_POS_ERROR;
if (!_ma_fetch_keypage(info, keyinfo, root, PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, page_buf, 0, 0))
goto err1;
nod_flag= _ma_test_if_nod(share, page_buf);
- k_len= keyinfo->keylength - share->base.rec_reflength;
+ key_data_length= key->data_length;
k= rt_PAGE_FIRST_KEY(share, page_buf, nod_flag);
last= rt_PAGE_END(share, page_buf);
- for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, k_len, nod_flag), i++)
+ for (; k < last; k= rt_PAGE_NEXT_KEY(share, k, key_data_length,
+ nod_flag), i++)
{
if (nod_flag)
{
- double k_area= maria_rtree_rect_volume(keyinfo->seg, k, key_length);
+ double k_area= maria_rtree_rect_volume(keyinfo->seg, k, key_data_length);
/* The following should be safe, even if we compare doubles */
if (k_area == 0)
@@ -1243,7 +1301,7 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key,
}
else if (flag & (MBR_WITHIN | MBR_EQUAL))
{
- if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length,
+ if (!maria_rtree_key_cmp(keyinfo->seg, key->data, k, key_data_length,
MBR_WITHIN))
area += 1;
}
@@ -1254,15 +1312,15 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key,
{
if (flag & (MBR_CONTAIN | MBR_INTERSECT))
{
- area+= maria_rtree_overlapping_area(keyinfo->seg, key, k,
- key_length) / k_area;
+ area+= maria_rtree_overlapping_area(keyinfo->seg, key->data, k,
+ key_data_length) / k_area;
}
else if (flag & (MBR_WITHIN | MBR_EQUAL))
{
- if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length,
+ if (!maria_rtree_key_cmp(keyinfo->seg, key->data, k, key_data_length,
MBR_WITHIN))
- area+= (maria_rtree_rect_volume(keyinfo->seg, key, key_length) /
- k_area);
+ area+= (maria_rtree_rect_volume(keyinfo->seg, key->data,
+ key_data_length) / k_area);
}
else
goto err1;
@@ -1270,7 +1328,8 @@ ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key,
}
else
{
- if (!maria_rtree_key_cmp(keyinfo->seg, key, k, key_length, flag))
+ if (!maria_rtree_key_cmp(keyinfo->seg, key->data, k, key_data_length,
+ flag))
++res;
}
}
diff --git a/storage/maria/ma_rt_index.h b/storage/maria/ma_rt_index.h
index 16009135373..8705128e226 100644
--- a/storage/maria/ma_rt_index.h
+++ b/storage/maria/ma_rt_index.h
@@ -26,31 +26,21 @@
#define rt_PAGE_MIN_SIZE(block_length) ((uint)(block_length - KEYPAGE_CHECKSUM_SIZE) / 3)
-int maria_rtree_insert(MARIA_HA *info, uint keynr, uchar *key,
- uint key_length);
-int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key,
- uint key_length);
-int maria_rtree_insert_level(MARIA_HA *info, uint keynr,
- const uchar *key,
- uint key_length, int ins_level,
- my_off_t *root);
-int maria_rtree_real_delete(MARIA_HA *info, uint keynr,
- const uchar *key, uint key_length,
- my_off_t *root);
-
-int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key,
- uint key_length, uint search_flag);
-int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint search_flag);
+my_bool maria_rtree_insert(MARIA_HA *info, MARIA_KEY *key);
+int maria_rtree_delete(MARIA_HA *info, MARIA_KEY *key);
+int maria_rtree_insert_level(MARIA_HA *info, MARIA_KEY *key,
+ int ins_level, my_off_t *root);
+int maria_rtree_real_delete(MARIA_HA *info, MARIA_KEY *key, my_off_t *root);
+int maria_rtree_find_first(MARIA_HA *info, MARIA_KEY *key, uint search_flag);
+int maria_rtree_find_next(MARIA_HA *info, uint keynr, uint32 search_flag);
int maria_rtree_get_first(MARIA_HA *info, uint keynr, uint key_length);
int maria_rtree_get_next(MARIA_HA *info, uint keynr, uint key_length);
-ha_rows maria_rtree_estimate(MARIA_HA *info, uint keynr, uchar *key,
- uint key_length, uint flag);
+ha_rows maria_rtree_estimate(MARIA_HA *info, MARIA_KEY *key, uint32 flag);
-int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
+int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
my_off_t page_offs, uchar *page,
- const uchar *key, uint key_length,
my_off_t *new_page_offs);
/**
When you obtain a MARIA_PINNED_PAGE* link (by calling
diff --git a/storage/maria/ma_rt_key.c b/storage/maria/ma_rt_key.c
index 901e769f554..bf70d2ba798 100644
--- a/storage/maria/ma_rt_key.c
+++ b/storage/maria/ma_rt_key.c
@@ -31,53 +31,47 @@
1 Split
*/
-int maria_rtree_add_key(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
- const uchar *key,
- uint key_length, uchar *page_buf, my_off_t page,
- my_off_t *new_page)
+int maria_rtree_add_key(MARIA_HA *info, const MARIA_KEY *key,
+ uchar *page_buf, my_off_t page, my_off_t *new_page)
{
MARIA_SHARE *share= info->s;
- uint page_size= _ma_get_page_used(share, page_buf), added_len;
+ uint page_size= _ma_get_page_used(share, page_buf);
uint nod_flag= _ma_test_if_nod(share, page_buf);
uchar *key_pos= rt_PAGE_END(share, page_buf);
+ uint tot_key_length= key->data_length + key->ref_length + nod_flag;
DBUG_ENTER("maria_rtree_add_key");
- if (page_size + key_length + share->base.rec_reflength <=
- (uint16)(keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE))
+ if (page_size + tot_key_length <=
+ (uint)(key->keyinfo->block_length - KEYPAGE_CHECKSUM_SIZE))
{
/* split won't be necessary */
if (nod_flag)
{
- /* save key */
- DBUG_ASSERT(_ma_kpos(nod_flag, key) < info->state->key_file_length);
- memcpy(key_pos, key - nod_flag, key_length + nod_flag);
- added_len= key_length + nod_flag;
+ DBUG_ASSERT(_ma_kpos(nod_flag, key->data) <
+ info->state->key_file_length);
+ /* We don't store reference to row on nod pages for rtree index */
+ tot_key_length-= key->ref_length;
}
- else
- {
- /* save key */
- DBUG_ASSERT(_ma_dpos(info, nod_flag, key + key_length +
- share->base.rec_reflength) <
- share->state.state.data_file_length +
- share->base.pack_reclength);
- memcpy(key_pos, key, key_length + share->base.rec_reflength);
- added_len= key_length + share->base.rec_reflength;
- }
- page_size+= added_len;
+ /* save key */
+ memcpy(key_pos, key->data - nod_flag, tot_key_length);
+ page_size+= tot_key_length;
_ma_store_page_used(share, page_buf, page_size);
if (share->now_transactional &&
_ma_log_add(info, page, page_buf, key_pos - page_buf,
- key_pos, added_len, added_len, 0))
+ key_pos, tot_key_length, tot_key_length, 0))
DBUG_RETURN(-1);
DBUG_RETURN(0);
}
- DBUG_RETURN(maria_rtree_split_page(info, keyinfo, page, page_buf, key,
- key_length, new_page) ? -1 : 1);
+ DBUG_RETURN(maria_rtree_split_page(info, key, page, page_buf, new_page)
+ ? -1 : 1);
}
/*
Delete key from the page
+
+ Notes
+ key_length is only the data part of the key
*/
int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key,
@@ -110,18 +104,18 @@ int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key,
Calculate and store key MBR into *key.
*/
-int maria_rtree_set_key_mbr(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
- uchar *key,
- uint key_length, my_off_t child_page)
+int maria_rtree_set_key_mbr(MARIA_HA *info, MARIA_KEY *key,
+ my_off_t child_page)
{
DBUG_ENTER("maria_rtree_set_key_mbr");
- if (!_ma_fetch_keypage(info, keyinfo, child_page,
+ if (!_ma_fetch_keypage(info, key->keyinfo, child_page,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, info->buff, 0, 0))
DBUG_RETURN(-1);
- DBUG_RETURN(maria_rtree_page_mbr(info, keyinfo->seg,
- info->buff, key, key_length));
+ DBUG_RETURN(maria_rtree_page_mbr(info, key->keyinfo->seg,
+ info->buff, key->data,
+ key->data_length));
}
#endif /*HAVE_RTREE_KEYS*/
diff --git a/storage/maria/ma_rt_key.h b/storage/maria/ma_rt_key.h
index 66d1e0e699b..5e24ac51b93 100644
--- a/storage/maria/ma_rt_key.h
+++ b/storage/maria/ma_rt_key.h
@@ -21,15 +21,12 @@
#ifdef HAVE_RTREE_KEYS
-int maria_rtree_add_key(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
- const uchar *key,
- uint key_length, uchar *page_buf, my_off_t page,
- my_off_t *new_page);
+int maria_rtree_add_key(MARIA_HA *info, const MARIA_KEY *key, uchar *page_buf,
+ my_off_t page, my_off_t *new_page);
int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key,
uint key_length, uint nod_flag, my_off_t page);
-int maria_rtree_set_key_mbr(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
- uchar *key,
- uint key_length, my_off_t child_page);
+int maria_rtree_set_key_mbr(MARIA_HA *info, MARIA_KEY *key,
+ my_off_t child_page);
#endif /*HAVE_RTREE_KEYS*/
#endif /* _rt_key_h */
diff --git a/storage/maria/ma_rt_mbr.c b/storage/maria/ma_rt_mbr.c
index e269ed9f7af..9a5e60e36e7 100644
--- a/storage/maria/ma_rt_mbr.c
+++ b/storage/maria/ma_rt_mbr.c
@@ -94,7 +94,7 @@
*/
int maria_rtree_key_cmp(HA_KEYSEG *keyseg, const uchar *b, const uchar *a,
- uint key_length, uint nextflag)
+ uint key_length, uint32 nextflag)
{
for (; (int) key_length > 0; keyseg += 2 )
{
@@ -695,7 +695,7 @@ double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
}
-#define RT_PAGE_MBR_KORR(share, type, korr_func, store_func, len) \
+#define RT_PAGE_MBR_KORR(share, type, korr_func, store_func, len, to) \
{ \
type amin, amax, bmin, bmax; \
amin= korr_func(k + inc); \
@@ -710,14 +710,14 @@ double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
if (amax < bmax) \
amax= bmax; \
} \
- store_func(c, amin); \
- c += len; \
- store_func(c, amax); \
- c += len; \
+ store_func(to, amin); \
+ to+= len; \
+ store_func(to, amax); \
+ to += len; \
inc += 2 * len; \
}
-#define RT_PAGE_MBR_GET(share, type, get_func, store_func, len) \
+#define RT_PAGE_MBR_GET(share, type, get_func, store_func, len, to) \
{ \
type amin, amax, bmin, bmax; \
get_func(amin, k + inc); \
@@ -732,20 +732,20 @@ double maria_rtree_perimeter_increase(HA_KEYSEG *keyseg, uchar* a, uchar* b,
if (amax < bmax) \
amax= bmax; \
} \
- store_func(c, amin); \
- c += len; \
- store_func(c, amax); \
- c += len; \
+ store_func(to, amin); \
+ to+= len; \
+ store_func(to, amax); \
+ to+= len; \
inc += 2 * len; \
}
/*
Calculates key page total MBR= MBR(key1) + MBR(key2) + ...
- Stores into *c.
+ Stores into *to.
*/
int maria_rtree_page_mbr(const MARIA_HA *info, const HA_KEYSEG *keyseg,
const uchar *page_buf,
- uchar *c, uint key_length)
+ uchar *to, uint key_length)
{
MARIA_SHARE *share= info->s;
uint inc= 0;
@@ -768,42 +768,42 @@ int maria_rtree_page_mbr(const MARIA_HA *info, const HA_KEYSEG *keyseg,
switch ((enum ha_base_keytype) keyseg->type) {
case HA_KEYTYPE_INT8:
- RT_PAGE_MBR_KORR(share, int8, mi_sint1korr, mi_int1store, 1);
+ RT_PAGE_MBR_KORR(share, int8, mi_sint1korr, mi_int1store, 1, to);
break;
case HA_KEYTYPE_BINARY:
- RT_PAGE_MBR_KORR(share, uint8, mi_uint1korr, mi_int1store, 1);
+ RT_PAGE_MBR_KORR(share, uint8, mi_uint1korr, mi_int1store, 1, to);
break;
case HA_KEYTYPE_SHORT_INT:
- RT_PAGE_MBR_KORR(share, int16, mi_sint2korr, mi_int2store, 2);
+ RT_PAGE_MBR_KORR(share, int16, mi_sint2korr, mi_int2store, 2, to);
break;
case HA_KEYTYPE_USHORT_INT:
- RT_PAGE_MBR_KORR(share, uint16, mi_uint2korr, mi_int2store, 2);
+ RT_PAGE_MBR_KORR(share, uint16, mi_uint2korr, mi_int2store, 2, to);
break;
case HA_KEYTYPE_INT24:
- RT_PAGE_MBR_KORR(share, int32, mi_sint3korr, mi_int3store, 3);
+ RT_PAGE_MBR_KORR(share, int32, mi_sint3korr, mi_int3store, 3, to);
break;
case HA_KEYTYPE_UINT24:
- RT_PAGE_MBR_KORR(share, uint32, mi_uint3korr, mi_int3store, 3);
+ RT_PAGE_MBR_KORR(share, uint32, mi_uint3korr, mi_int3store, 3, to);
break;
case HA_KEYTYPE_LONG_INT:
- RT_PAGE_MBR_KORR(share, int32, mi_sint4korr, mi_int4store, 4);
+ RT_PAGE_MBR_KORR(share, int32, mi_sint4korr, mi_int4store, 4, to);
break;
case HA_KEYTYPE_ULONG_INT:
- RT_PAGE_MBR_KORR(share, uint32, mi_uint4korr, mi_int4store, 4);
+ RT_PAGE_MBR_KORR(share, uint32, mi_uint4korr, mi_int4store, 4, to);
break;
#ifdef HAVE_LONG_LONG
case HA_KEYTYPE_LONGLONG:
- RT_PAGE_MBR_KORR(share, longlong, mi_sint8korr, mi_int8store, 8);
+ RT_PAGE_MBR_KORR(share, longlong, mi_sint8korr, mi_int8store, 8, to);
break;
case HA_KEYTYPE_ULONGLONG:
- RT_PAGE_MBR_KORR(share, ulonglong, mi_uint8korr, mi_int8store, 8);
+ RT_PAGE_MBR_KORR(share, ulonglong, mi_uint8korr, mi_int8store, 8, to);
break;
#endif
case HA_KEYTYPE_FLOAT:
- RT_PAGE_MBR_GET(share, float, mi_float4get, mi_float4store, 4);
+ RT_PAGE_MBR_GET(share, float, mi_float4get, mi_float4store, 4, to);
break;
case HA_KEYTYPE_DOUBLE:
- RT_PAGE_MBR_GET(share, double, mi_float8get, mi_float8store, 8);
+ RT_PAGE_MBR_GET(share, double, mi_float8get, mi_float8store, 8, to);
break;
case HA_KEYTYPE_END:
return 0;
diff --git a/storage/maria/ma_rt_mbr.h b/storage/maria/ma_rt_mbr.h
index 7f436151dd3..11988868317 100644
--- a/storage/maria/ma_rt_mbr.h
+++ b/storage/maria/ma_rt_mbr.h
@@ -20,7 +20,7 @@
#ifdef HAVE_RTREE_KEYS
int maria_rtree_key_cmp(HA_KEYSEG *keyseg, const uchar *a, const uchar *b,
- uint key_length, uint nextflag);
+ uint key_length, uint32 nextflag);
int maria_rtree_combine_rect(const HA_KEYSEG *keyseg,
const uchar *, const uchar *, uchar*,
uint key_length);
diff --git a/storage/maria/ma_rt_split.c b/storage/maria/ma_rt_split.c
index 26399181e32..f2a64c55251 100644
--- a/storage/maria/ma_rt_split.c
+++ b/storage/maria/ma_rt_split.c
@@ -178,11 +178,11 @@ static void mark_all_entries(SplitStruct *node, int n_entries, int n_group)
}
static int split_maria_rtree_node(SplitStruct *node, int n_entries,
- int all_size, /* Total key's size */
- int key_size,
- int min_size, /* Minimal group size */
- int size1, int size2 /* initial group sizes */,
- double **d_buffer, int n_dim)
+ int all_size, /* Total key's size */
+ int key_size,
+ int min_size, /* Minimal group size */
+ int size1, int size2 /* initial group sizes */,
+ double **d_buffer, int n_dim)
{
SplitStruct *cur;
SplitStruct *a;
@@ -380,9 +380,9 @@ static my_bool _ma_log_rt_split(MARIA_HA *info,
If new_page_offs==NULL, won't create new page (for redo phase).
*/
-int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
- my_off_t page_offs, uchar *page, const uchar *key,
- uint key_length, my_off_t *new_page_offs)
+int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEY *key,
+ my_off_t page_offs, uchar *page,
+ my_off_t *new_page_offs)
{
MARIA_SHARE *share= info->s;
const my_bool transactional= share->now_transactional;
@@ -400,11 +400,12 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
int err_code= 0;
uint nod_flag= _ma_test_if_nod(share, page);
uint org_length= _ma_get_page_used(share, page), new_length;
- uint full_length= key_length + (nod_flag ? nod_flag :
- share->base.rec_reflength);
- int max_keys= ((org_length - share->keypage_header) /
- (full_length));
+ uint full_length= key->data_length + (nod_flag ? nod_flag :
+ key->ref_length);
+ uint key_data_length= key->data_length;
+ int max_keys= ((org_length - share->keypage_header) / (full_length));
MARIA_PINNED_PAGE tmp_page_link, *page_link= &tmp_page_link;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("maria_rtree_split_page");
DBUG_PRINT("rtree", ("splitting block"));
@@ -424,17 +425,17 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
for (cur= task;
cur < stop;
- cur++, source_cur= rt_PAGE_NEXT_KEY(share, source_cur, key_length,
+ cur++, source_cur= rt_PAGE_NEXT_KEY(share, source_cur, key_data_length,
nod_flag))
{
cur->coords= reserve_coords(&next_coord, n_dim);
cur->key= source_cur;
- maria_rtree_d_mbr(keyinfo->seg, source_cur, key_length, cur->coords);
+ maria_rtree_d_mbr(keyinfo->seg, source_cur, key_data_length, cur->coords);
}
cur->coords= reserve_coords(&next_coord, n_dim);
- maria_rtree_d_mbr(keyinfo->seg, key, key_length, cur->coords);
- cur->key= key;
+ maria_rtree_d_mbr(keyinfo->seg, key->data, key_data_length, cur->coords);
+ cur->key= key->data;
old_coord= next_coord;
@@ -474,14 +475,14 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
if (cur->n_node == 1)
{
to= cur1;
- cur1= rt_PAGE_NEXT_KEY(share, cur1, key_length, nod_flag);
+ cur1= rt_PAGE_NEXT_KEY(share, cur1, key_data_length, nod_flag);
n1++;
log_this_change= transactional;
}
else
{
to= cur2;
- cur2= rt_PAGE_NEXT_KEY(share, cur2, key_length, nod_flag);
+ cur2= rt_PAGE_NEXT_KEY(share, cur2, key_data_length, nod_flag);
n2++;
log_this_change= FALSE;
}
@@ -493,7 +494,7 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
if (log_this_change)
{
uint to_with_nod_flag_offs= to_with_nod_flag - page;
- if (likely(cur_key != key))
+ if (likely(cur_key != key->data))
{
/* this memcpy() is internal to the page (source in the page) */
uint cur_key_with_nod_flag_offs= cur_key_with_nod_flag - page;
@@ -536,7 +537,7 @@ int maria_rtree_split_page(MARIA_HA *info, const MARIA_KEYDEF *keyinfo,
{
if (transactional &&
( /* log change to split page */
- _ma_log_rt_split(info, page_offs, page, key - nod_flag,
+ _ma_log_rt_split(info, page_offs, page, key->data - nod_flag,
full_length, log_internal_copy,
log_internal_copy_ptr - log_internal_copy,
log_key_copy, org_length - new_length) ||
diff --git a/storage/maria/ma_rt_test.c b/storage/maria/ma_rt_test.c
index b329254149e..e17ff773b29 100644
--- a/storage/maria/ma_rt_test.c
+++ b/storage/maria/ma_rt_test.c
@@ -130,7 +130,7 @@ static int run_test(const char *filename)
int key_type=HA_KEYTYPE_DOUBLE;
int key_length=8;
int null_fields=0;
- int nrecords=sizeof(rt_data)/(sizeof(double)*4);/* 3000;*/
+ int nrecords=sizeof(rt_data)/(sizeof(double)*4);/* 40 */
int rec_length=0;
int uniques=0;
int i, max_i;
@@ -141,6 +141,8 @@ static int run_test(const char *filename)
int upd= 10;
ha_rows hrows;
+ bzero((char*) recinfo,sizeof(recinfo));
+
/* Define a column for NULLs and DEL markers*/
recinfo[0].type=FIELD_NORMAL;
@@ -315,7 +317,7 @@ static int run_test(const char *filename)
goto err;
}
print_record(read_record,maria_position(file),"");
- create_record(record,i+nrecords*upd);
+ create_record1(record,i+nrecords*upd);
printf("\t-> ");
print_record(record,maria_position(file),"\n");
error=maria_update(file,read_record,record);
diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c
index e39fb832fbd..96c4a1d0add 100644
--- a/storage/maria/ma_search.c
+++ b/storage/maria/ma_search.c
@@ -18,12 +18,10 @@
#include "ma_fulltext.h"
#include "m_ctype.h"
-static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page,
- uchar *key, uchar *keypos,
- uint *return_key_length);
+static my_bool _ma_get_prev_key(MARIA_KEY *key, uchar *page, uchar *keypos);
- /* Check index */
+
+/* Check that new index is ok */
int _ma_check_index(MARIA_HA *info, int inx)
{
@@ -57,18 +55,19 @@ int _ma_check_index(MARIA_HA *info, int inx)
@retval 1 If one should continue search on higher level
*/
-int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_len, uint nextflag, register my_off_t pos)
+int _ma_search(register MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
+ register my_off_t pos)
{
- my_bool last_key;
+ my_bool last_key_not_used;
int error,flag;
- uint nod_flag, used_length;
+ uint page_flag, nod_flag, used_length;
uchar *keypos,*maxpos;
- uchar lastkey[HA_MAX_KEY_BUFF],*buff;
+ uchar lastkey[MARIA_MAX_KEY_BUFF],*buff;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_search");
DBUG_PRINT("enter",("pos: %lu nextflag: %u lastpos: %lu",
(ulong) pos, nextflag, (ulong) info->cur_row.lastpos));
- DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_len););
+ DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, key););
if (pos == HA_OFFSET_ERROR)
{
@@ -79,23 +78,25 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_RETURN(1); /* Search at upper levels */
}
- if (!(buff= _ma_fetch_keypage(info,keyinfo, pos,
+ if (!(buff= _ma_fetch_keypage(info, keyinfo, pos,
PAGECACHE_LOCK_LEFT_UNLOCKED,
DFLT_INIT_HITS, info->keyread_buff,
test(!(nextflag & SEARCH_SAVE_BUFF)), 0)))
goto err;
DBUG_DUMP("page", buff, _ma_get_page_used(info->s, buff));
- flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
- &keypos,lastkey, &last_key);
+ flag= (*keyinfo->bin_search)(key, buff, nextflag, &keypos, lastkey,
+ &last_key_not_used);
if (flag == MARIA_FOUND_WRONG_KEY)
DBUG_RETURN(-1);
- _ma_get_used_and_nod(info->s, buff, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(info->s, buff);
+ _ma_get_used_and_nod_with_flag(info->s, page_flag, buff, used_length,
+ nod_flag);
maxpos= buff + used_length -1;
if (flag)
{
- if ((error= _ma_search(info,keyinfo,key,key_len,nextflag,
+ if ((error= _ma_search(info, key, nextflag,
_ma_kpos(nod_flag,keypos))) <= 0)
DBUG_RETURN(error);
@@ -110,12 +111,13 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
else
{
+ /* Found matching key */
if ((nextflag & SEARCH_FIND) && nod_flag &&
((keyinfo->flag & (HA_NOSAME | HA_NULL_PART)) != HA_NOSAME ||
- key_len != USE_WHOLE_KEY))
+ (key->flag & SEARCH_PART_KEY) || info->s->base.born_transactional))
{
- if ((error= _ma_search(info,keyinfo,key,key_len,SEARCH_FIND,
- _ma_kpos(nod_flag,keypos))) >= 0 ||
+ if ((error= _ma_search(info, key, nextflag,
+ _ma_kpos(nod_flag,keypos))) >= 0 ||
my_errno != HA_ERR_KEY_NOT_FOUND)
DBUG_RETURN(error);
info->last_keypage= HA_OFFSET_ERROR; /* Buffer not in mem */
@@ -133,15 +135,21 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
maxpos=buff+(maxpos-old_buff);
}
+ info->last_key.keyinfo= keyinfo;
if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0)
{
uint not_used[2];
- if (_ma_get_prev_key(info,keyinfo, buff, info->lastkey, keypos,
- &info->lastkey_length))
+ if (_ma_get_prev_key(&info->last_key, buff, keypos))
goto err;
+ /*
+ We have to use key->flag >> 1 here to transform
+ SEARCH_PAGE_KEY_HAS_TRANSID to SEARCH_USER_KEY_HAS_TRANSID
+ */
if (!(nextflag & SEARCH_SMALLER) &&
- ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey, (uchar*) key, key_len,
- SEARCH_FIND, not_used))
+ ha_key_cmp(keyinfo->seg, info->last_key.data, key->data,
+ key->data_length + key->ref_length,
+ SEARCH_FIND | (key->flag >> 1) | info->last_key.flag,
+ not_used))
{
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
goto err;
@@ -149,12 +157,17 @@ int _ma_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
else
{
- info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey);
- if (!info->lastkey_length)
+ /* Set info->last_key to temporarily point to last key value */
+ info->last_key.data= lastkey;
+ /* Get key value (if not packed key) and position after key */
+ if (!(*keyinfo->get_key)(&info->last_key, page_flag, nod_flag, &keypos))
goto err;
- memcpy(info->lastkey,lastkey,info->lastkey_length);
+ memcpy(info->lastkey_buff, lastkey,
+ info->last_key.data_length + info->last_key.ref_length);
+ info->last_key.data= info->lastkey_buff;
}
- info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length);
+ info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
+ info->cur_row.trid= _ma_trid_from_key(&info->last_key);
/* Save position for a possible read next / previous */
info->int_keypos= info->keyread_buff+ (keypos-buff);
info->int_maxpos= info->keyread_buff+ (maxpos-buff);
@@ -176,25 +189,50 @@ err:
} /* _ma_search */
- /* Search after key in page-block */
- /* If packed key puts smaller or identical key in buff */
- /* ret_pos point to where find or bigger key starts */
- /* ARGSUSED */
+/*
+ Search after key in page-block
+
+ @fn _ma_bin_search
+ @param key Search after this key
+ @param page Start of data page
+ @param comp_flag How key should be compared
+ @param ret_pos
+ @param buff Buffer for holding a key (not used here)
+ @param last_key
+
+ @note
+ If keys are packed, then smaller or identical key is stored in buff
+
+ @return
+ @retval <0, 0 , >0 depending on if if found is smaller, equal or bigger than
+ 'key'
+ @retval ret_pos Points to where the identical or bigger key starts
+ @retval last_key Set to 1 if key is the last key in the page.
+*/
-int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *page, const uchar *key, uint key_len,
- uint comp_flag, uchar **ret_pos,
+int _ma_bin_search(const MARIA_KEY *key, uchar *page,
+ uint32 comp_flag, uchar **ret_pos,
uchar *buff __attribute__((unused)), my_bool *last_key)
{
int flag;
+ uint page_flag;
uint start, mid, end, save_end, totlength, nod_flag, used_length;
uint not_used[2];
- MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_SHARE *share= keyinfo->share;
DBUG_ENTER("_ma_bin_search");
LINT_INIT(flag);
- _ma_get_used_and_nod(share, page, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(share, page);
+ if (page_flag & KEYPAGE_FLAG_HAS_TRANSID)
+ {
+ /* Keys have varying length, can't use binary search */
+ DBUG_RETURN(_ma_seq_search(key, page, comp_flag, ret_pos, buff, last_key));
+ }
+
+ _ma_get_used_and_nod_with_flag(share, page_flag, page, used_length,
+ nod_flag);
totlength= keyinfo->keylength + nod_flag;
DBUG_ASSERT(used_length >= share->keypage_header + nod_flag + totlength);
@@ -208,16 +246,18 @@ int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
while (start != end)
{
mid= (start+end)/2;
- if ((flag=ha_key_cmp(keyinfo->seg,(uchar*) page+(uint) mid*totlength,
- key, key_len, comp_flag, not_used))
+ if ((flag=ha_key_cmp(keyinfo->seg, page + (uint) mid * totlength,
+ key->data, key->data_length + key->ref_length,
+ comp_flag, not_used))
>= 0)
end=mid;
else
start=mid+1;
}
if (mid != start)
- flag=ha_key_cmp(keyinfo->seg, (uchar*) page+(uint) start*totlength,
- key, key_len, comp_flag, not_used);
+ flag=ha_key_cmp(keyinfo->seg, page + (uint) start * totlength,
+ key->data, key->data_length + key->ref_length, comp_flag,
+ not_used);
if (flag < 0)
start++; /* point at next, bigger key */
*ret_pos= (page + (uint) start * totlength);
@@ -227,54 +267,63 @@ int _ma_bin_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
} /* _ma_bin_search */
-/*
- Locate a packed key in a key page.
+/**
+ Locate a packed key in a key page.
- SYNOPSIS
- _ma_seq_search()
- info Open table information.
- keyinfo Key definition information.
- page Key page (beginning).
- key Search key.
- key_len Length to use from search key or USE_WHOLE_KEY
- comp_flag Search flags like SEARCH_SAME etc.
- ret_pos RETURN Position in key page behind this key.
- buff RETURN Copy of previous or identical unpacked key.
- last_key RETURN If key is last in page.
-
- DESCRIPTION
- Used instead of _ma_bin_search() when key is packed.
- Puts smaller or identical key in buff.
- Key is searched sequentially.
-
- RETURN
- > 0 Key in 'buff' is smaller than search key.
- 0 Key in 'buff' is identical to search key.
- < 0 Not found.
+ @fn _ma_seq_search()
+ @param key Search key.
+ @param page Key page (beginning).
+ @param comp_flag Search flags like SEARCH_SAME etc.
+ @param ret_pos
+ @param buff Buffer for holding temp keys
+ @param last_key
+
+ @description
+ Used instead of _ma_bin_search() when key is packed.
+ Puts smaller or identical key in buff.
+ Key is searched sequentially.
+
+ @todo
+ Don't copy key to buffer if we are not using key with prefix packing
+
+ @return
+ @retval > 0 Key in 'buff' is smaller than search key.
+ @retval 0 Key in 'buff' is identical to search key.
+ @retval < 0 Not found.
+
+ @retval ret_pos Points to where the identical or bigger key starts
+ @retval last_key Set to 1 if key is the last key in the page
+ @retval buff Copy of previous or identical unpacked key
*/
-int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *page, const uchar *key, uint key_len,
- uint comp_flag, uchar **ret_pos,
+int _ma_seq_search(const MARIA_KEY *key, uchar *page,
+ uint32 comp_flag, uchar **ret_pos,
uchar *buff, my_bool *last_key)
{
- MARIA_SHARE *share= info->s;
int flag;
- uint nod_flag, length, used_length, not_used[2];
- uchar t_buff[HA_MAX_KEY_BUFF], *end;
+ uint page_flag, nod_flag, length, used_length, not_used[2];
+ uchar t_buff[MARIA_MAX_KEY_BUFF], *end;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_SHARE *share= keyinfo->share;
+ MARIA_KEY tmp_key;
DBUG_ENTER("_ma_seq_search");
LINT_INIT(flag);
LINT_INIT(length);
- _ma_get_used_and_nod(share, page, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(share, page);
+ _ma_get_used_and_nod_with_flag(share, page_flag, page, used_length,
+ nod_flag);
end= page + used_length;
page+= share->keypage_header + nod_flag;
*ret_pos= (uchar*) page;
t_buff[0]=0; /* Avoid bugs */
+
+ tmp_key.data= t_buff;
+ tmp_key.keyinfo= keyinfo;
while (page < end)
{
- length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
+ length=(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &page);
if (length == 0 || page > end)
{
maria_print_error(share, HA_ERR_CRASHED);
@@ -284,8 +333,10 @@ int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
length, (long) page, (long) end));
DBUG_RETURN(MARIA_FOUND_WRONG_KEY);
}
- if ((flag= ha_key_cmp(keyinfo->seg, t_buff, key,
- key_len,comp_flag, not_used)) >= 0)
+ if ((flag= ha_key_cmp(keyinfo->seg, t_buff, key->data,
+ key->data_length + key->ref_length,
+ comp_flag | tmp_key.flag,
+ not_used)) >= 0)
break;
#ifdef EXTRA_DEBUG
DBUG_PRINT("loop",("page: 0x%lx key: '%s' flag: %d", (long) page, t_buff,
@@ -302,12 +353,20 @@ int _ma_seq_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
} /* _ma_seq_search */
-int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *page, const uchar *key, uint key_len,
- uint nextflag, uchar **ret_pos, uchar *buff,
+/**
+ Search for key on key page with string prefix compression
+
+ @notes
+ This is an optimized function compared to calling _ma_get_pack_key()
+ for each key in the buffer
+
+ Same interface as for _ma_seq_search()
+*/
+
+int _ma_prefix_search(const MARIA_KEY *key, uchar *page,
+ uint32 nextflag, uchar **ret_pos, uchar *buff,
my_bool *last_key)
{
- MARIA_SHARE *share= info->s;
/*
my_flag is raw comparison result to be changed according to
SEARCH_NO_FIND,SEARCH_LAST and HA_REVERSE_SORT flags.
@@ -315,16 +374,18 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
*/
int flag=0, my_flag=-1;
uint nod_flag, used_length, length, len, matched, cmplen, kseg_len;
- uint prefix_len,suffix_len;
+ uint page_flag, prefix_len,suffix_len;
int key_len_skip, seg_len_pack, key_len_left;
uchar *end;
uchar *vseg, *saved_vseg, *saved_from;
- uchar *sort_order= keyinfo->seg->charset->sort_order;
- uchar tt_buff[HA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
+ uchar tt_buff[MARIA_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
uchar *saved_to;
const uchar *kseg;
uint saved_length=0, saved_prefix_len=0;
uint length_pack;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_SHARE *share= keyinfo->share;
+ uchar *sort_order= keyinfo->seg->charset->sort_order;
DBUG_ENTER("_ma_prefix_search");
LINT_INIT(length);
@@ -335,17 +396,21 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
LINT_INIT(saved_vseg);
t_buff[0]=0; /* Avoid bugs */
- _ma_get_used_and_nod(share, page, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(share, page);
+ _ma_get_used_and_nod_with_flag(share, page_flag, page, used_length,
+ nod_flag);
+ page_flag&= KEYPAGE_FLAG_HAS_TRANSID; /* For faster test in loop */
end= page + used_length;
page+= share->keypage_header + nod_flag;
*ret_pos= page;
- kseg= key;
+ kseg= key->data;
get_key_pack_length(kseg_len, length_pack, kseg);
key_len_skip=length_pack+kseg_len;
- key_len_left=(int) key_len- (int) key_len_skip;
- /* If key_len is 0, then lenght_pack is 1, then key_len_left is -1. */
- cmplen=(key_len_left>=0) ? kseg_len : key_len-length_pack;
+ key_len_left=(int) (key->data_length + key->ref_length) - (int) key_len_skip;
+ /* If key_len is 0, then length_pack is 1, then key_len_left is -1. */
+ cmplen= ((key_len_left>=0) ? kseg_len :
+ (key->data_length + key->ref_length - length_pack));
DBUG_PRINT("info",("key: '%.*s'",kseg_len,kseg));
/*
@@ -367,6 +432,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
while (page < end)
{
uint packed= *page & 128;
+ uint key_flag;
vseg= (uchar*) page;
if (keyinfo->seg->length >= 127)
@@ -411,13 +477,12 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
DBUG_PRINT("loop",("page: '%.*s%.*s'",prefix_len,t_buff+seg_len_pack,
suffix_len,vseg));
{
+ /* Calculate length of one key */
uchar *from= vseg+suffix_len;
HA_KEYSEG *keyseg;
- uint l;
for (keyseg=keyinfo->seg+1 ; keyseg->type ; keyseg++ )
{
-
if (keyseg->flag & HA_NULL_PART)
{
if (!(*from++))
@@ -425,14 +490,21 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
- get_key_length(l,from);
+ uint key_part_length;
+ get_key_length(key_part_length,from);
+ from+= key_part_length;
}
else
- l=keyseg->length;
-
- from+=l;
+ from+= keyseg->length;
}
from+= keyseg->length;
+ key_flag=0;
+
+ if (page_flag && key_has_transid(from-1))
+ {
+ from+= transid_packed_length(from);
+ key_flag= SEARCH_PAGE_KEY_HAS_TRANSID;
+ }
page= (uchar*) from+nod_flag;
length= (uint) (from-vseg);
}
@@ -482,7 +554,8 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
/*
** len cmplen seg_left_len more_segs
** < matched=len; continue search
- ** > = prefix ? found : (matched=len; continue search)
+ ** > = prefix ? found : (matched=len;
+ * continue search)
** > < - ok, found
** = < - ok, found
** = = - ok, found
@@ -535,7 +608,8 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
{
uint not_used[2];
if ((flag = ha_key_cmp(keyinfo->seg+1,vseg,
- k, key_len_left, nextflag, not_used)) >= 0)
+ k, key_len_left, nextflag | key_flag,
+ not_used)) >= 0)
break;
}
else
@@ -582,7 +656,7 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
} /* _ma_prefix_search */
- /* Get pos to a key_block */
+/* Get pos to a key_block */
my_off_t _ma_kpos(uint nod_flag, const uchar *after_key)
{
@@ -618,7 +692,7 @@ my_off_t _ma_kpos(uint nod_flag, const uchar *after_key)
} /* _kpos */
- /* Save pos to a key_block */
+/* Save pos to a key_block */
void _ma_kpointer(register MARIA_HA *info, register uchar *buff, my_off_t pos)
{
@@ -645,14 +719,14 @@ void _ma_kpointer(register MARIA_HA *info, register uchar *buff, my_off_t pos)
} /* _ma_kpointer */
- /* Calc pos to a data-record from a key */
+/* Calc pos to a data-record from a key */
-MARIA_RECORD_POS _ma_dpos(MARIA_HA *info, uint nod_flag,
- const uchar *after_key)
+MARIA_RECORD_POS _ma_row_pos_from_key(const MARIA_KEY *key)
{
my_off_t pos;
- after_key-=(nod_flag + info->s->rec_reflength);
- switch (info->s->rec_reflength) {
+ const uchar *after_key= key->data + key->data_length;
+ MARIA_SHARE *share= key->keyinfo->share;
+ switch (share->rec_reflength) {
#if SIZEOF_OFF_T > 4
case 8: pos= (my_off_t) mi_uint8korr(after_key); break;
case 7: pos= (my_off_t) mi_uint7korr(after_key); break;
@@ -670,18 +744,36 @@ MARIA_RECORD_POS _ma_dpos(MARIA_HA *info, uint nod_flag,
default:
pos=0L; /* Shut compiler up */
}
- return info->s->keypos_to_recpos(info, pos);
+ return (*share->keypos_to_recpos)(share, pos);
}
-/* Calc position from a record pointer ( in delete link chain ) */
+/**
+ Get trid from a key
+
+ @param key Maria key read from a page
-MARIA_RECORD_POS _ma_rec_pos(MARIA_HA *info, uchar *ptr)
+ @retval 0 If key doesn't have a trid
+ @retval trid
+*/
+
+TrID _ma_trid_from_key(const MARIA_KEY *key)
{
- MARIA_SHARE *s= info->s;
+ if (!(key->flag & (SEARCH_PAGE_KEY_HAS_TRANSID |
+ SEARCH_USER_KEY_HAS_TRANSID)))
+ return 0;
+ return transid_get_packed(key->keyinfo->share,
+ key->data + key->data_length +
+ key->keyinfo->share->rec_reflength);
+}
+
+
+/* Calc position from a record pointer ( in delete link chain ) */
+MARIA_RECORD_POS _ma_rec_pos(MARIA_SHARE *share, uchar *ptr)
+{
my_off_t pos;
- switch (s->rec_reflength) {
+ switch (share->rec_reflength) {
#if SIZEOF_OFF_T > 4
case 8:
pos= (my_off_t) mi_uint8korr(ptr);
@@ -708,7 +800,7 @@ MARIA_RECORD_POS _ma_rec_pos(MARIA_HA *info, uchar *ptr)
case 7:
case 6:
case 5:
- ptr+= (s->rec_reflength-4);
+ ptr+= (share->rec_reflength-4);
/* fall through */
#endif
case 4:
@@ -728,18 +820,18 @@ MARIA_RECORD_POS _ma_rec_pos(MARIA_HA *info, uchar *ptr)
break;
default: abort(); /* Impossible */
}
- return (*s->keypos_to_recpos)(info, pos);
+ return (*share->keypos_to_recpos)(share, pos);
}
/* save position to record */
-void _ma_dpointer(MARIA_HA *info, uchar *buff, my_off_t pos)
+void _ma_dpointer(MARIA_SHARE *share, uchar *buff, my_off_t pos)
{
if (pos != HA_OFFSET_ERROR)
- pos= (*info->s->recpos_to_keypos)(info, pos);
+ pos= (*share->recpos_to_keypos)(share, pos);
- switch (info->s->rec_reflength) {
+ switch (share->rec_reflength) {
#if SIZEOF_OFF_T > 4
case 8: mi_int8store(buff,pos); break;
case 7: mi_int7store(buff,pos); break;
@@ -763,24 +855,24 @@ void _ma_dpointer(MARIA_HA *info, uchar *buff, my_off_t pos)
} /* _ma_dpointer */
-my_off_t _ma_static_keypos_to_recpos(MARIA_HA *info, my_off_t pos)
+my_off_t _ma_static_keypos_to_recpos(MARIA_SHARE *share, my_off_t pos)
{
- return pos * info->s->base.pack_reclength;
+ return pos * share->base.pack_reclength;
}
-my_off_t _ma_static_recpos_to_keypos(MARIA_HA *info, my_off_t pos)
+my_off_t _ma_static_recpos_to_keypos(MARIA_SHARE *share, my_off_t pos)
{
- return pos / info->s->base.pack_reclength;
+ return pos / share->base.pack_reclength;
}
-my_off_t _ma_transparent_recpos(MARIA_HA *info __attribute__((unused)),
+my_off_t _ma_transparent_recpos(MARIA_SHARE *share __attribute__((unused)),
my_off_t pos)
{
return pos;
}
-my_off_t _ma_transaction_keypos_to_recpos(MARIA_HA *info
+my_off_t _ma_transaction_keypos_to_recpos(MARIA_SHARE *share
__attribute__((unused)),
my_off_t pos)
{
@@ -788,7 +880,7 @@ my_off_t _ma_transaction_keypos_to_recpos(MARIA_HA *info
return pos >> 1;
}
-my_off_t _ma_transaction_recpos_to_keypos(MARIA_HA *info
+my_off_t _ma_transaction_recpos_to_keypos(MARIA_SHARE *share
__attribute__((unused)),
my_off_t pos)
{
@@ -798,48 +890,89 @@ my_off_t _ma_transaction_recpos_to_keypos(MARIA_HA *info
/*
@brief Get key from key-block
- @param nod_flag Is set to nod length if we on nod
+ @param key Should contain previous key. Will contain new key
+ @param page_flag Flag on page block
+ @param nod_flag Is set to nod length if we on nod
@param page Points at previous key; Its advanced to point at next key
- @param key Should contain previous key
@notes
Same as _ma_get_key but used with fixed length keys
- @retval Returns length of found key + pointers
+ @return
+ @retval key_length + length of data pointer (without nod length)
*/
-uint _ma_get_static_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page, uchar *key)
+uint _ma_get_static_key(MARIA_KEY *key, uint page_flag, uint nod_flag,
+ register uchar **page)
{
- memcpy((uchar*) key,(uchar*) *page,
- (size_t) (keyinfo->keylength+nod_flag));
- *page+=keyinfo->keylength+nod_flag;
- return(keyinfo->keylength);
+ register MARIA_KEYDEF *keyinfo= key->keyinfo;
+ size_t key_length= keyinfo->keylength;
+
+ key->ref_length= keyinfo->share->rec_reflength;
+ key->data_length= key_length - key->ref_length;
+ key->flag= 0;
+ if (page_flag & KEYPAGE_FLAG_HAS_TRANSID)
+ {
+ uchar *end= *page + keyinfo->keylength;
+ if (key_has_transid(end-1))
+ {
+ uint trans_length= transid_packed_length(end);
+ key->ref_length+= trans_length;
+ key_length+= trans_length;
+ key->flag= SEARCH_PAGE_KEY_HAS_TRANSID;
+ }
+ }
+ key_length+= nod_flag;
+ memcpy(key->data, *page, key_length);
+ *page+= key_length;
+ return key_length - nod_flag;
} /* _ma_get_static_key */
+/**
+ Skip over static length key from key-block
+
+ @fn _ma_skip_pack_key()
+ @param key Keyinfo and buffer that can be used
+ @param nod_flag If nod: Length of node pointer, else zero.
+ @param key Points at key
+
+ @retval pointer to next key
+*/
+
+uchar *_ma_skip_static_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar *page)
+{
+ page+= key->keyinfo->keylength;
+ if ((page_flag & KEYPAGE_FLAG_HAS_TRANSID) && key_has_transid(page-1))
+ page+= transid_packed_length(page);
+ return page+ nod_flag;
+}
+
+
/*
- get key witch is packed against previous key or key with a NULL column.
+ get key which is packed against previous key or key with a NULL column.
SYNOPSIS
_ma_get_pack_key()
- keyinfo key definition information.
- nod_flag If nod: Length of node pointer, else zero.
- page_pos RETURN position in key page behind this key.
- key IN/OUT in: prev key, out: unpacked key.
+ @param int_key Should contain previous key. Will contain new key
+ @param page_flag page_flag from page
+ @param nod_flag If nod: Length of node pointer, else zero.
+ @param page_pos Points at previous key; Its advanced to point at next key
- RETURN
- key_length + length of data pointer
+ @return
+ @retval key_length + length of data pointer
*/
-uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page_pos, register uchar *key)
+uint _ma_get_pack_key(MARIA_KEY *int_key, uint page_flag,
+ uint nod_flag, uchar **page_pos)
{
reg1 HA_KEYSEG *keyseg;
- uchar *start_key,*page=*page_pos;
+ uchar *page= *page_pos;
uint length;
+ uchar *key= int_key->data;
+ MARIA_KEYDEF *keyinfo= int_key->keyinfo;
- start_key=key;
for (keyseg=keyinfo->seg ; keyseg->type ;keyseg++)
{
if (keyseg->flag & HA_PACK_KEY)
@@ -959,32 +1092,109 @@ uint _ma_get_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
key+=length;
page+=length;
}
- length=keyseg->length+nod_flag;
- bmove((uchar*) key,(uchar*) page,length);
+
+ int_key->data_length= (key - int_key->data);
+ int_key->flag= 0;
+ length= keyseg->length;
+ if (page_flag & KEYPAGE_FLAG_HAS_TRANSID)
+ {
+ uchar *end= page + length;
+ if (key_has_transid(end-1))
+ {
+ length+= transid_packed_length(end);
+ int_key->flag= SEARCH_PAGE_KEY_HAS_TRANSID;
+ }
+ }
+ int_key->ref_length= length;
+ length+= nod_flag;
+ bmove(key, page, length);
*page_pos= page+length;
- return ((uint) (key-start_key)+keyseg->length);
+
+ return (int_key->data_length + int_key->ref_length);
} /* _ma_get_pack_key */
+/**
+ skip key which is packed against previous key or key with a NULL column.
-/* key that is packed relatively to previous */
+ @fn _ma_skip_pack_key()
+ @param key Keyinfo and buffer that can be used
+ @param nod_flag If nod: Length of node pointer, else zero.
+ @param key Points at key
-uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page_pos, register uchar *key)
+ @retval pointer to next key
+*/
+
+uchar *_ma_skip_pack_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar *page)
{
reg1 HA_KEYSEG *keyseg;
- uchar *start_key,*page,*page_end,*from,*from_end;
+ for (keyseg= key->keyinfo->seg ; keyseg->type ; keyseg++)
+ {
+ if (keyseg->flag & HA_PACK_KEY)
+ {
+ /* key with length, packed to previous key */
+ uint packed= *page & 128, length;
+ if (keyseg->length >= 127)
+ {
+ length= mi_uint2korr(page) & 32767;
+ page+= 2;
+ }
+ else
+ length= *page++ & 127;
+
+ if (packed)
+ {
+ if (length == 0) /* Same key */
+ continue;
+ get_key_length(length,page);
+ page+= length;
+ continue;
+ }
+ page+= length;
+ }
+ else
+ {
+ if (keyseg->flag & HA_NULL_PART)
+ if (!*page++)
+ continue;
+ if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
+ {
+ uint length;
+ get_key_length(length,page);
+ page+=length;
+ }
+ else
+ page+= keyseg->length;
+ }
+ }
+ page+= keyseg->length;
+ if ((page_flag & KEYPAGE_FLAG_HAS_TRANSID) && key_has_transid(page-1))
+ page+= transid_packed_length(page);
+ return page + nod_flag;
+}
+
+
+/* Read key that is packed relatively to previous */
+
+uint _ma_get_binary_pack_key(MARIA_KEY *int_key, uint page_flag, uint nod_flag,
+ register uchar **page_pos)
+{
+ reg1 HA_KEYSEG *keyseg;
+ uchar *page, *page_end, *from, *from_end, *key;
uint length,tmp;
+ MARIA_KEYDEF *keyinfo= int_key->keyinfo;
DBUG_ENTER("_ma_get_binary_pack_key");
page= *page_pos;
- page_end=page+HA_MAX_KEY_BUFF+1;
- start_key=key;
+ page_end=page + MARIA_MAX_KEY_BUFF + 1;
+ key= int_key->data;
/*
Keys are compressed the following way:
- prefix length Packed length of prefix common with prev key. (1 or 3 bytes)
+ prefix length Packed length of prefix common with prev key.
+ (1 or 3 bytes)
for each key segment:
[is null] Null indicator if can be null (1 byte, zero means null)
[length] Packed length if varlength (1 or 3 bytes)
@@ -1046,10 +1256,10 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
/* Get length of dynamic length key part */
if ((length= (uint) (uchar) (*key++ = *from++)) == 255)
{
- /* If prefix is used up, switch to rest. */
+ /* If prefix is used up, switch to rest. */
if (from == from_end) { from=page; from_end=page_end; }
length= ((uint) (uchar) ((*key++ = *from++))) << 8;
- /* If prefix is used up, switch to rest. */
+ /* If prefix is used up, switch to rest. */
if (from == from_end) { from=page; from_end=page_end; }
length+= (uint) (uchar) ((*key++ = *from++));
}
@@ -1075,19 +1285,22 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
If we have mixed key blocks with data pointer and key block pointer,
we have to copy both.
*/
- length=keyseg->length+nod_flag;
+ int_key->data_length= (key - int_key->data);
+ int_key->ref_length= length= keyseg->length;
+ int_key->flag= 0;
if ((tmp=(uint) (from_end-from)) <= length)
{
- /* Remaining length is less or equal max possible length. */
- memcpy(key+tmp,page,length-tmp); /* Get last part of key */
- *page_pos= page+length-tmp;
+ /* Skip over the last common part of the data */
+ key+= tmp;
+ length-= tmp;
+ from= page;
}
else
{
/*
Remaining length is greater than max possible length.
This can happen only if we switched to the new key bytes already.
- 'page_end' is calculated with MI_MAX_KEY_BUFF. So it can be far
+ 'page_end' is calculated with MARIA_MAX_KEY_BUFF. So it can be far
behind the real end of the key.
*/
if (from_end != page_end)
@@ -1097,11 +1310,52 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0); /* Error */
}
- /* Copy data pointer and, if appropriate, key block pointer. */
- memcpy((uchar*) key,(uchar*) from,(size_t) length);
- *page_pos= from+length;
}
- DBUG_RETURN((uint) (key-start_key)+keyseg->length);
+ if (page_flag & KEYPAGE_FLAG_HAS_TRANSID)
+ {
+ uchar *end= from + length;
+ if (key_has_transid(end-1))
+ {
+ uint trans_length= transid_packed_length(end);
+ length+= trans_length;
+ int_key->ref_length+= trans_length;
+ int_key->flag= SEARCH_PAGE_KEY_HAS_TRANSID;
+ }
+ }
+
+ /* Copy rest of data ptr and, if appropriate, trans_id and node_ptr */
+ memcpy(key, from, length);
+ *page_pos= from + length + nod_flag;
+
+ DBUG_RETURN(int_key->data_length + int_key->ref_length);
+}
+
+/**
+ skip key which is ptefix packed against previous key
+
+ @fn _ma_skip_binary_key()
+ @param key Keyinfo and buffer that can be used
+ @param nod_flag If nod: Length of node pointer, else zero.
+ @param key Points at key
+
+ @note
+ We have to copy the key as otherwise we don't know how much left
+ data there is of the key.
+
+ @todo
+ Implement more efficient version of this. We can ignore to copy any rest
+ key parts that are not null or not packed. We also don't have to copy
+ rowid or transid.
+
+ @retval pointer to next key
+*/
+
+uchar *_ma_skip_binary_pack_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar *page)
+{
+ if (!_ma_get_binary_pack_key(key, page_flag, nod_flag, &page))
+ return 0;
+ return page;
}
@@ -1111,35 +1365,40 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
@return pointer to next key
*/
-uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page,
- uchar *key, uchar *keypos, uint *return_key_length)
+uchar *_ma_get_key(MARIA_KEY *key, uchar *page, uchar *keypos)
{
- uint nod_flag;
+ uint page_flag, nod_flag;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_get_key");
- nod_flag=_ma_test_if_nod(info->s, page);
- if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
+ page_flag= _ma_get_keypage_flag(keyinfo->share, page);
+ nod_flag= _ma_test_if_nod(keyinfo->share, page);
+
+ if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
+ ! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
- bmove((uchar*) key,(uchar*) keypos,keyinfo->keylength+nod_flag);
+ bmove(key->data, keypos, keyinfo->keylength+nod_flag);
+ key->ref_length= keyinfo->share->rec_reflength;
+ key->data_length= keyinfo->keylength - key->ref_length;
+ key->flag= 0;
DBUG_RETURN(keypos+keyinfo->keylength+nod_flag);
}
else
{
- page+= info->s->keypage_header + nod_flag;
- key[0]=0; /* safety */
+ page+= keyinfo->share->keypage_header + nod_flag;
+ key->data[0]= 0; /* safety */
while (page <= keypos)
{
- *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
- if (*return_key_length == 0)
+ if (!(*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{
- maria_print_error(info->s, HA_ERR_CRASHED);
+ maria_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
}
}
DBUG_PRINT("exit",("page: 0x%lx length: %u", (long) page,
- *return_key_length));
+ key->data_length + key->ref_length));
DBUG_RETURN(page);
} /* _ma_get_key */
@@ -1152,95 +1411,118 @@ uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page,
@retval 1 error
*/
-static my_bool _ma_get_prev_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page, uchar *key, uchar *keypos,
- uint *return_key_length)
+static my_bool _ma_get_prev_key(MARIA_KEY *key, uchar *page, uchar *keypos)
{
- uint nod_flag;
+ uint page_flag, nod_flag;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_get_prev_key");
- nod_flag=_ma_test_if_nod(info->s, page);
- if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
+ page_flag= _ma_get_keypage_flag(keyinfo->share, page);
+ nod_flag= _ma_test_if_nod(keyinfo->share, page);
+
+ if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
+ ! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
- *return_key_length=keyinfo->keylength;
- bmove((uchar*) key,(uchar*) keypos- *return_key_length-nod_flag,
- *return_key_length);
+ bmove(key->data, keypos - keyinfo->keylength - nod_flag,
+ keyinfo->keylength);
+ key->ref_length= keyinfo->share->rec_reflength;
+ key->data_length= keyinfo->keylength - key->ref_length;
+ key->flag= 0;
DBUG_RETURN(0);
}
else
{
- page+= info->s->keypage_header + nod_flag;
- key[0]=0; /* safety */
+ page+= keyinfo->share->keypage_header + nod_flag;
+ key->data[0]= 0; /* safety */
+ DBUG_ASSERT(page != keypos);
while (page < keypos)
{
- *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
- if (*return_key_length == 0)
+ if (! (*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{
- maria_print_error(info->s, HA_ERR_CRASHED);
+ maria_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(1);
}
}
}
DBUG_RETURN(0);
-} /* _ma_get_key */
+} /* _ma_get_prev_key */
/*
@brief Get last key from key-page before 'endpos'
@note
- endpos may be either end of buffer or start of a key
+ endpos may be either end of buffer or start of a key
@return
@retval pointer to where key starts
*/
-uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page,
- uchar *lastkey, uchar *endpos, uint *return_key_length)
+uchar *_ma_get_last_key(MARIA_KEY *key, uchar *page, uchar *endpos)
{
- uint nod_flag;
+ uint page_flag,nod_flag;
uchar *lastpos;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_get_last_key");
DBUG_PRINT("enter",("page: 0x%lx endpos: 0x%lx", (long) page,
(long) endpos));
- nod_flag= _ma_test_if_nod(info->s, page);
- if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
+ page_flag= _ma_get_keypage_flag(keyinfo->share, page);
+ nod_flag= _ma_test_if_nod(keyinfo->share, page);
+ if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
+ ! (page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
- lastpos=endpos-keyinfo->keylength-nod_flag;
- *return_key_length=keyinfo->keylength;
+ lastpos= endpos-keyinfo->keylength-nod_flag;
+ key->ref_length= keyinfo->share->rec_reflength;
+ key->data_length= keyinfo->keylength - key->ref_length;
+ key->flag= 0;
if (lastpos > page)
- bmove((uchar*) lastkey,(uchar*) lastpos,keyinfo->keylength+nod_flag);
+ bmove(key->data, lastpos, keyinfo->keylength + nod_flag);
}
else
{
- page+= info->s->keypage_header + nod_flag;
+ page+= keyinfo->share->keypage_header + nod_flag;
lastpos= page;
- lastkey[0]=0;
+ key->data[0]=0; /* safety */
while (page < endpos)
{
- lastpos=page;
- *return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,lastkey);
- if (*return_key_length == 0)
+ lastpos= page;
+ if (!(*keyinfo->get_key)(key, page_flag, nod_flag, &page))
{
DBUG_PRINT("error",("Couldn't find last key: page: 0x%lx",
(long) page));
- maria_print_error(info->s, HA_ERR_CRASHED);
+ maria_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
}
}
- DBUG_PRINT("exit",("lastpos: 0x%lx length: %u", (long) lastpos,
- *return_key_length));
+ DBUG_PRINT("exit",("lastpos: 0x%lx length: %u", (ulong) lastpos,
+ key->data_length + key->ref_length));
DBUG_RETURN(lastpos);
} /* _ma_get_last_key */
-/* Calculate length of key */
+/**
+ Calculate length of unpacked key
+
+ @param info Maria handler
+ @param keyinfo key handler
+ @param key data for key
+
+ @notes
+ This function is very seldom used. It's mainly used for debugging
+ or when calculating a key length from a stored key in batch insert.
+
+ This function does *NOT* calculate length of transid size!
+ This function can't be used against a prefix packed key on a page
+
+ @return
+ @retval total length for key
+*/
-uint _ma_keylength(MARIA_KEYDEF *keyinfo, register const uchar *key)
+uint _ma_keylength(MARIA_KEYDEF *keyinfo, const uchar *key)
{
reg1 HA_KEYSEG *keyseg;
const uchar *start;
@@ -1299,16 +1581,6 @@ uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, register const uchar *key,
}
-/* Move a key */
-
-uchar *_ma_move_key(MARIA_KEYDEF *keyinfo, uchar *to, const uchar *from)
-{
- reg1 uint length;
- memcpy(to, from, (size_t) (length= _ma_keylength(keyinfo, from)));
- return to+length;
-}
-
-
/*
Find next/previous record with same key
@@ -1316,18 +1588,20 @@ uchar *_ma_move_key(MARIA_KEYDEF *keyinfo, uchar *to, const uchar *from)
This can't be used when database is touched after last read
*/
-int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length, uint nextflag, my_off_t pos)
+int _ma_search_next(register MARIA_HA *info, MARIA_KEY *key,
+ uint32 nextflag, my_off_t pos)
{
int error;
- uint nod_flag;
- uchar lastkey[HA_MAX_KEY_BUFF];
+ uint page_flag,nod_flag;
+ uchar lastkey[MARIA_MAX_KEY_BUFF];
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_KEY tmp_key;
DBUG_ENTER("_ma_search_next");
- DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu page_changed %d keyread_buff_used: %d",
+ DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: 0x%lx page_changed %d keyread_buff_used: %d",
nextflag, (ulong) info->cur_row.lastpos,
(ulong) info->int_keypos,
info->page_changed, info->keyread_buff_used));
- DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
+ DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, key););
/*
Force full read if we are at last key or if we are not on a leaf
@@ -1341,8 +1615,8 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->page_changed ||
(info->int_keytree_version != keyinfo->version &&
(info->int_nod_flag || info->keyread_buff_used)))
- DBUG_RETURN(_ma_search(info,keyinfo,key, USE_WHOLE_KEY,
- nextflag | SEARCH_SAVE_BUFF, pos));
+ DBUG_RETURN(_ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
+ pos));
if (info->keyread_buff_used)
{
@@ -1354,57 +1628,71 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
/* Last used buffer is in info->keyread_buff */
- nod_flag= _ma_test_if_nod(info->s, info->keyread_buff);
+ page_flag= _ma_get_keypage_flag(keyinfo->share, info->keyread_buff);
+ nod_flag= _ma_test_if_nod(keyinfo->share, info->keyread_buff);
+
+ tmp_key.data= lastkey;
+ info->last_key.keyinfo= tmp_key.keyinfo= keyinfo;
if (nextflag & SEARCH_BIGGER) /* Next key */
{
- my_off_t tmp_pos= _ma_kpos(nod_flag,info->int_keypos);
- if (tmp_pos != HA_OFFSET_ERROR)
+ if (nod_flag)
{
- if ((error= _ma_search(info,keyinfo,key, USE_WHOLE_KEY,
- nextflag | SEARCH_SAVE_BUFF, tmp_pos)) <=0)
+ my_off_t tmp_pos= _ma_kpos(nod_flag,info->int_keypos);
+
+ if ((error= _ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
+ tmp_pos)) <=0)
DBUG_RETURN(error);
}
- memcpy(lastkey,key,key_length);
- if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,
- &info->int_keypos,lastkey)))
+ if (keyinfo->flag & (HA_PACK_KEY | HA_BINARY_PACK_KEY) &&
+ info->last_key.data != key->data)
+ memcpy(info->last_key.data, key->data,
+ key->data_length + key->ref_length);
+ if (!(*keyinfo->get_key)(&info->last_key, page_flag, nod_flag,
+ &info->int_keypos))
DBUG_RETURN(-1);
}
else /* Previous key */
{
- uint length;
/* Find start of previous key */
- info->int_keypos= _ma_get_last_key(info,keyinfo,info->keyread_buff,lastkey,
- info->int_keypos, &length);
+ info->int_keypos= _ma_get_last_key(&tmp_key, info->keyread_buff,
+ info->int_keypos);
if (!info->int_keypos)
DBUG_RETURN(-1);
if (info->int_keypos == info->keyread_buff + info->s->keypage_header)
- DBUG_RETURN(_ma_search(info,keyinfo,key, USE_WHOLE_KEY,
- nextflag | SEARCH_SAVE_BUFF, pos));
- if ((error= _ma_search(info,keyinfo,key, USE_WHOLE_KEY,
- nextflag | SEARCH_SAVE_BUFF,
- _ma_kpos(nod_flag,info->int_keypos))) <= 0)
+ {
+ /* Previous key was first key, read key before this one */
+ DBUG_RETURN(_ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
+ pos));
+ }
+ if (nod_flag &&
+ (error= _ma_search(info, key, nextflag | SEARCH_SAVE_BUFF,
+ _ma_kpos(nod_flag,info->int_keypos))) <= 0)
DBUG_RETURN(error);
/* QQ: We should be able to optimize away the following call */
- if (! _ma_get_last_key(info,keyinfo,info->keyread_buff,lastkey,
- info->int_keypos,&info->lastkey_length))
+ if (! _ma_get_last_key(&info->last_key, info->keyread_buff,
+ info->int_keypos))
DBUG_RETURN(-1);
}
- memcpy(info->lastkey,lastkey,info->lastkey_length);
- info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length);
+ info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
+ info->cur_row.trid= _ma_trid_from_key(&info->last_key);
DBUG_PRINT("exit",("found key at %lu",(ulong) info->cur_row.lastpos));
DBUG_RETURN(0);
} /* _ma_search_next */
- /* Search after position for the first row in an index */
- /* This is stored in info->cur_row.lastpos */
+/**
+ Search after position for the first row in an index
+
+ @return
+ Found row is stored in info->cur_row.lastpos
+*/
int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
register my_off_t pos)
{
- uint nod_flag;
+ uint page_flag, nod_flag;
uchar *page;
MARIA_SHARE *share= info->s;
DBUG_ENTER("_ma_search_first");
@@ -1424,12 +1712,14 @@ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->cur_row.lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(-1);
}
- nod_flag=_ma_test_if_nod(share, info->keyread_buff);
+ page_flag= _ma_get_keypage_flag(share, info->keyread_buff);
+ nod_flag= _ma_test_if_nod(share, info->keyread_buff);
page= info->keyread_buff + share->keypage_header + nod_flag;
} while ((pos= _ma_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
- if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
- info->lastkey)))
+ info->last_key.keyinfo= keyinfo;
+
+ if (!(*keyinfo->get_key)(&info->last_key, page_flag, nod_flag, &page))
DBUG_RETURN(-1); /* Crashed */
info->int_keypos=page;
@@ -1439,20 +1729,25 @@ int _ma_search_first(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->int_keytree_version=keyinfo->version;
info->last_search_keypage=info->last_keypage;
info->page_changed=info->keyread_buff_used=0;
- info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length);
+ info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
+ info->cur_row.trid= _ma_trid_from_key(&info->last_key);
DBUG_PRINT("exit",("found key at %lu", (ulong) info->cur_row.lastpos));
DBUG_RETURN(0);
} /* _ma_search_first */
- /* Search after position for the last row in an index */
- /* This is stored in info->cur_row.lastpos */
+/**
+ Search after position for the last row in an index
+
+ @return
+ Found row is stored in info->cur_row.lastpos
+*/
int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
register my_off_t pos)
{
- uint nod_flag;
+ uint page_flag, nod_flag;
uchar *buff,*end_of_page;
DBUG_ENTER("_ma_search_last");
@@ -1473,14 +1768,18 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->cur_row.lastpos= HA_OFFSET_ERROR;
DBUG_RETURN(-1);
}
- _ma_get_used_and_nod(info->s, buff, used_length, nod_flag);
+ page_flag= _ma_get_keypage_flag(info->s, info->keyread_buff);
+ _ma_get_used_and_nod_with_flag(info->s, page_flag, buff, used_length,
+ nod_flag);
end_of_page= buff + used_length;
} while ((pos= _ma_kpos(nod_flag, end_of_page)) != HA_OFFSET_ERROR);
- if (!_ma_get_last_key(info, keyinfo, buff, info->lastkey, end_of_page,
- &info->lastkey_length))
+ info->last_key.keyinfo= keyinfo;
+
+ if (!_ma_get_last_key(&info->last_key, buff, end_of_page))
DBUG_RETURN(-1);
- info->cur_row.lastpos= _ma_dpos(info,0,info->lastkey+info->lastkey_length);
+ info->cur_row.lastpos= _ma_row_pos_from_key(&info->last_key);
+ info->cur_row.trid= _ma_trid_from_key(&info->last_key);
info->int_keypos= info->int_maxpos= end_of_page;
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
@@ -1509,27 +1808,29 @@ int _ma_search_last(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
/* Static length key */
int
-_ma_calc_static_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag,
+_ma_calc_static_key_length(const MARIA_KEY *key, uint nod_flag,
uchar *next_pos __attribute__((unused)),
uchar *org_key __attribute__((unused)),
uchar *prev_key __attribute__((unused)),
- const uchar *key, MARIA_KEY_PARAM *s_temp)
+ MARIA_KEY_PARAM *s_temp)
{
- s_temp->key= key;
- return (int) (s_temp->move_length= keyinfo->keylength + nod_flag);
+ s_temp->key= key->data;
+ return (int) (s_temp->move_length= key->data_length + key->ref_length +
+ nod_flag);
}
/* Variable length key */
int
-_ma_calc_var_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag,
+_ma_calc_var_key_length(const MARIA_KEY *key, uint nod_flag,
uchar *next_pos __attribute__((unused)),
uchar *org_key __attribute__((unused)),
uchar *prev_key __attribute__((unused)),
- const uchar *key, MARIA_KEY_PARAM *s_temp)
+ MARIA_KEY_PARAM *s_temp)
{
- s_temp->key= key;
- return (int) (s_temp->move_length= _ma_keylength(keyinfo,key)+nod_flag);
+ s_temp->key= key->data;
+ return (int) (s_temp->move_length= key->data_length + key->ref_length +
+ nod_flag);
}
/**
@@ -1554,22 +1855,23 @@ _ma_calc_var_key_length(MARIA_KEYDEF *keyinfo,uint nod_flag,
*/
int
-_ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
- uchar *next_key,
- uchar *org_key, uchar *prev_key, const uchar *key,
+_ma_calc_var_pack_key_length(const MARIA_KEY *int_key, uint nod_flag,
+ uchar *next_key, uchar *org_key, uchar *prev_key,
MARIA_KEY_PARAM *s_temp)
{
reg1 HA_KEYSEG *keyseg;
int length;
uint key_length,ref_length,org_key_length=0,
length_pack,new_key_length,diff_flag,pack_marker;
- const uchar *start,*end,*key_end;
+ const uchar *key, *start, *end, *key_end;
uchar *sort_order;
my_bool same_length;
+ MARIA_KEYDEF *keyinfo= int_key->keyinfo;
+ key= int_key->data;
length_pack=s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
same_length=0; keyseg=keyinfo->seg;
- key_length= _ma_keylength(keyinfo,key)+nod_flag;
+ key_length= int_key->data_length + int_key->ref_length + nod_flag;
sort_order=0;
if ((keyinfo->flag & HA_FULLTEXT) &&
@@ -1840,15 +2142,17 @@ _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
/* Length of key which is prefix compressed */
-int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
+int _ma_calc_bin_pack_key_length(const MARIA_KEY *int_key,
+ uint nod_flag,
uchar *next_key,
uchar *org_key, uchar *prev_key,
- const uchar *key,
MARIA_KEY_PARAM *s_temp)
{
uint length,key_length,ref_length;
+ const uchar *key= int_key->data;
- s_temp->totlength=key_length= _ma_keylength(keyinfo,key)+nod_flag;
+ s_temp->totlength= key_length= (int_key->data_length + int_key->ref_length+
+ nod_flag);
#ifdef HAVE_purify
s_temp->n_length= s_temp->n_ref_length=0; /* For valgrind */
#endif
diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c
index d7c50d03790..fbbf0b365db 100644
--- a/storage/maria/ma_sort.c
+++ b/storage/maria/ma_sort.c
@@ -225,8 +225,9 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
if (my_b_inited(&tempfile_for_exceptions))
{
MARIA_HA *idx=info->sort_info->info;
- uint keyno=info->key;
- uint key_length, ref_length=idx->s->rec_reflength;
+ uint16 key_length;
+ MARIA_KEY key;
+ key.keyinfo= idx->s->keyinfo + info->key;
if (!no_messages)
printf(" - Adding exceptions\n"); /* purecov: tested */
@@ -239,8 +240,12 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
&& !my_b_read(&tempfile_for_exceptions,(uchar*)sort_keys,
(uint) key_length))
{
- if (_ma_ck_write(idx,keyno,(uchar*) sort_keys,key_length-ref_length))
- goto err;
+ key.data= (uchar*) sort_keys;
+ key.ref_length= idx->s->rec_reflength;
+ key.data_length= key_length - key.ref_length;
+ key.flag= 0;
+ if (_ma_ck_write(idx, &key))
+ goto err;
}
}
@@ -615,7 +620,7 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param)
}
if (my_b_inited(&sinfo->tempfile_for_exceptions))
{
- uint key_length;
+ uint16 key_length;
if (param->testflag & T_VERBOSE)
printf("Key %d - Dumping 'long' keys\n", sinfo->key+1);
@@ -634,10 +639,19 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param)
uchar maria_ft_buf[HA_FT_MAXBYTELEN + HA_FT_WLEN + 10];
if (key_length > sizeof(maria_ft_buf) ||
my_b_read(&sinfo->tempfile_for_exceptions, (uchar*)maria_ft_buf,
- (uint)key_length) ||
- _ma_ck_write(info, sinfo->key, maria_ft_buf,
- key_length - info->s->rec_reflength))
- got_error=1;
+ (uint) key_length))
+ got_error= 1;
+ else
+ {
+ MARIA_KEY tmp_key;
+ tmp_key.keyinfo= info->s->keyinfo + sinfo->key;
+ tmp_key.data= maria_ft_buf;
+ tmp_key.ref_length= info->s->rec_reflength;
+ tmp_key.data_length= key_length - info->s->rec_reflength;
+ tmp_key.flag= 0;
+ if (_ma_ck_write(info, &tmp_key))
+ got_error=1;
+ }
}
}
}
@@ -719,7 +733,7 @@ static int write_keys_varlen(MARIA_SORT_PARAM *info,
static int write_key(MARIA_SORT_PARAM *info, uchar *key,
IO_CACHE *tempfile)
{
- uint key_length=info->real_key_length;
+ uint16 key_length=info->real_key_length;
DBUG_ENTER("write_key");
if (!my_b_inited(tempfile) &&
@@ -836,7 +850,6 @@ static uint read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek,
uint sort_length)
{
register uint count;
- uint16 length_of_key = 0;
uint idx;
uchar *buffp;
@@ -846,6 +859,7 @@ static uint read_to_buffer_varlen(IO_CACHE *fromfile, BUFFPEK *buffpek,
for (idx=1;idx<=count;idx++)
{
+ uint16 length_of_key;
if (my_pread(fromfile->file,(uchar*)&length_of_key,sizeof(length_of_key),
buffpek->file_pos,MYF_RW))
return((uint) -1);
diff --git a/storage/maria/ma_sp_defs.h b/storage/maria/ma_sp_defs.h
index a70695bea3a..398bf99c52e 100644
--- a/storage/maria/ma_sp_defs.h
+++ b/storage/maria/ma_sp_defs.h
@@ -40,8 +40,9 @@ enum wkbByteOrder
wkbNDR = 1 /* Little Endian */
};
-uint _ma_sp_make_key(register MARIA_HA *info, uint keynr, uchar *key,
- const uchar *record, my_off_t filepos);
+MARIA_KEY *_ma_sp_make_key(MARIA_HA *info, MARIA_KEY *ret_key, uint keynr,
+ uchar *key, const uchar *record, my_off_t filepos,
+ ulonglong trid);
#endif /*HAVE_SPATIAL*/
#endif /* _SP_DEFS_H */
diff --git a/storage/maria/ma_sp_key.c b/storage/maria/ma_sp_key.c
index 3c0833366fd..d9e6b5570f2 100644
--- a/storage/maria/ma_sp_key.c
+++ b/storage/maria/ma_sp_key.c
@@ -14,6 +14,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "maria_def.h"
+#include "ma_blockrec.h" /* For ROW_FLAG_TRANSID */
+#include <trnman.h>
#ifdef HAVE_SPATIAL
@@ -31,8 +33,14 @@ static int sp_get_geometry_mbr(uchar *(*wkb), uchar *end, uint n_dims,
double *mbr, int top);
static int sp_mbr_from_wkb(uchar (*wkb), uint size, uint n_dims, double *mbr);
-uint _ma_sp_make_key(register MARIA_HA *info, uint keynr, uchar *key,
- const uchar *record, my_off_t filepos)
+
+/**
+ Create spactial key
+*/
+
+MARIA_KEY *_ma_sp_make_key(MARIA_HA *info, MARIA_KEY *ret_key, uint keynr,
+ uchar *key, const uchar *record, my_off_t filepos,
+ ulonglong trid)
{
HA_KEYSEG *keyseg;
MARIA_KEYDEF *keyinfo = &info->s->keyinfo[keynr];
@@ -42,17 +50,20 @@ uint _ma_sp_make_key(register MARIA_HA *info, uint keynr, uchar *key,
uchar *dptr;
double mbr[SPDIMS * 2];
uint i;
+ DBUG_ENTER("_ma_sp_make_key");
keyseg = &keyinfo->seg[-1];
pos = record + keyseg->start;
+ ret_key->data= key;
dlen = _ma_calc_blob_length(keyseg->bit_start, pos);
memcpy_fixed(&dptr, pos + keyseg->bit_start, sizeof(char*));
if (!dptr)
{
my_errno= HA_ERR_NULL_IN_SPATIAL;
- return 0;
+ DBUG_RETURN(0);
}
+
sp_mbr_from_wkb(dptr + 4, dlen - 4, SPDIMS, mbr); /* SRID */
for (i = 0, keyseg = keyinfo->seg; keyseg->type; keyseg++, i++)
@@ -60,8 +71,8 @@ uint _ma_sp_make_key(register MARIA_HA *info, uint keynr, uchar *key,
uint length = keyseg->length, start= keyseg->start;
double val;
- DBUG_ASSERT(length == sizeof(double));
- DBUG_ASSERT(!(start % sizeof(double)));
+ DBUG_ASSERT(length == 8);
+ DBUG_ASSERT(!(start % 8));
DBUG_ASSERT(start < sizeof(mbr));
DBUG_ASSERT(keyseg->type == HA_KEYTYPE_DOUBLE);
@@ -78,28 +89,36 @@ uint _ma_sp_make_key(register MARIA_HA *info, uint keynr, uchar *key,
if (keyseg->flag & HA_SWAP_KEY)
{
- uchar buf[sizeof(double)];
-
- float8store(buf, val);
- pos= &buf[length];
- while (pos > buf)
- *key++ = *--pos;
+ mi_float8store(key, val);
}
else
{
float8store((uchar *)key, val);
- key += length;
}
+ key += length;
len+= length;
}
- _ma_dpointer(info, key, filepos);
- return len;
+ _ma_dpointer(info->s, key, filepos);
+ ret_key->keyinfo= keyinfo;
+ ret_key->data_length= len;
+ ret_key->ref_length= info->s->rec_reflength;
+ ret_key->flag= 0;
+ if (_ma_have_versioning(info) && trid)
+ {
+ ret_key->ref_length+= transid_store_packed(info,
+ key + ret_key->ref_length,
+ trid);
+ }
+ DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, ret_key););
+ DBUG_RETURN(ret_key);
}
+
/*
-Calculate minimal bounding rectangle (mbr) of the spatial object
-stored in "well-known binary representation" (wkb) format.
+ Calculate minimal bounding rectangle (mbr) of the spatial object
+ stored in "well-known binary representation" (wkb) format.
*/
+
static int sp_mbr_from_wkb(uchar *wkb, uint size, uint n_dims, double *mbr)
{
uint i;
diff --git a/storage/maria/ma_state.c b/storage/maria/ma_state.c
index 4dae0c3cc03..fa394d45012 100644
--- a/storage/maria/ma_state.c
+++ b/storage/maria/ma_state.c
@@ -186,6 +186,8 @@ void _ma_reset_state(MARIA_HA *info)
/* Set the current history to current state */
share->state_history->state= share->state.state;
+ /* Set current table handler to point to new history state */
+ info->state= info->state_start= &share->state_history->state;
for (history= history->next ; history ; history= next)
{
next= history->next;
@@ -446,7 +448,8 @@ my_bool _ma_block_check_status(void *param __attribute__((unused)))
void maria_versioning(MARIA_HA *info, my_bool versioning)
{
/* For now, this is a hack */
- _ma_block_get_status((void*) info, versioning);
+ if (info->s->have_versioning)
+ _ma_block_get_status((void*) info, versioning);
}
@@ -476,3 +479,48 @@ void _ma_copy_nontrans_state_information(MARIA_HA *info)
info->s->state.state.records= info->state->records;
info->s->state.state.checksum= info->state->checksum;
}
+
+
+/****************************************************************************
+ Virtual functions to check if row is visible
+****************************************************************************/
+
+/**
+ Row is always visible
+ This is for tables without concurrent insert
+*/
+
+my_bool _ma_row_visible_always(MARIA_HA *info __attribute__((unused)))
+{
+ return 1;
+}
+
+
+/**
+ Row visibility for non transactional tables with concurrent insert
+
+ @implementation
+ When we got our table lock, we saved the current
+ data_file_length. Concurrent inserts always go to the end of the
+ file. So we can test if the found key references a new record.
+*/
+
+my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info)
+{
+ return info->cur_row.lastpos < info->state->data_file_length;
+}
+
+
+/**
+ Row visibility for transactional tables with versioning
+
+
+ @TODO
+ Add test if found key was marked deleted and it was deleted by
+ us. In that case we should return 0
+*/
+
+my_bool _ma_row_visible_transactional_table(MARIA_HA *info)
+{
+ return trnman_can_read_from(info->trn, info->cur_row.trid);
+}
diff --git a/storage/maria/ma_state.h b/storage/maria/ma_state.h
index eab206633f9..55e8069d3ce 100644
--- a/storage/maria/ma_state.h
+++ b/storage/maria/ma_state.h
@@ -73,3 +73,6 @@ void _ma_set_share_data_file_length(struct st_maria_share *share,
void _ma_copy_nontrans_state_information(MARIA_HA *info);
my_bool _ma_trnman_end_trans_hook(TRN *trn, my_bool commit,
my_bool active_transactions);
+my_bool _ma_row_visible_always(MARIA_HA *info);
+my_bool _ma_row_visible_non_transactional_table(MARIA_HA *info);
+my_bool _ma_row_visible_transactional_table(MARIA_HA *info);
diff --git a/storage/maria/ma_static.c b/storage/maria/ma_static.c
index 923b38dfd9c..07425a5db91 100644
--- a/storage/maria/ma_static.c
+++ b/storage/maria/ma_static.c
@@ -72,15 +72,24 @@ uchar maria_zero_string[]= {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
Position is , == , >= , <= , > , <
*/
-uint maria_read_vec[]=
+uint32 maria_read_vec[]=
{
- SEARCH_FIND, SEARCH_FIND | SEARCH_BIGGER, SEARCH_FIND | SEARCH_SMALLER,
- SEARCH_NO_FIND | SEARCH_BIGGER, SEARCH_NO_FIND | SEARCH_SMALLER,
- SEARCH_FIND | SEARCH_PREFIX, SEARCH_LAST, SEARCH_LAST | SEARCH_SMALLER,
- MBR_CONTAIN, MBR_INTERSECT, MBR_WITHIN, MBR_DISJOINT, MBR_EQUAL
+ SEARCH_FIND, /* HA_READ_KEY_EXACT */
+ SEARCH_FIND | SEARCH_BIGGER, /* HA_READ_KEY_OR_NEXT */
+ SEARCH_FIND | SEARCH_SMALLER, /* HA_READ_KEY_OR_PREV */
+ SEARCH_NO_FIND | SEARCH_BIGGER, /* HA_READ_AFTER_KEY */
+ SEARCH_NO_FIND | SEARCH_SMALLER, /* HA_READ_BEFORE_KEY */
+ SEARCH_FIND | SEARCH_PART_KEY, /* HA_READ_PREFIX */
+ SEARCH_LAST, /* HA_READ_PREFIX_LAST */
+ SEARCH_LAST | SEARCH_SMALLER, /* HA_READ_PREFIX_LAST_OR_PREV */
+ MBR_CONTAIN, /* HA_READ_MBR_CONTAIN */
+ MBR_INTERSECT, /* HA_READ_MBR_INTERSECT */
+ MBR_WITHIN, /* HA_READ_MBR_WITHIN */
+ MBR_DISJOINT, /* HA_READ_MBR_DISJOINT */
+ MBR_EQUAL /* HA_READ_MBR_EQUAL */
};
-uint maria_readnext_vec[]=
+uint32 maria_readnext_vec[]=
{
SEARCH_BIGGER, SEARCH_BIGGER, SEARCH_SMALLER, SEARCH_BIGGER, SEARCH_SMALLER,
SEARCH_BIGGER, SEARCH_SMALLER, SEARCH_SMALLER
diff --git a/storage/maria/ma_statrec.c b/storage/maria/ma_statrec.c
index 43915ff5ec0..d3b457e7dc4 100644
--- a/storage/maria/ma_statrec.c
+++ b/storage/maria/ma_statrec.c
@@ -30,7 +30,7 @@ my_bool _ma_write_static_record(MARIA_HA *info, const uchar *record)
info->s->state.dellink+1,
MYF(MY_NABP)))
goto err;
- info->s->state.dellink= _ma_rec_pos(info, temp);
+ info->s->state.dellink= _ma_rec_pos(info->s, temp);
info->state->del--;
info->state->empty-=info->s->base.pack_reclength;
if (info->s->file_write(info, record, info->s->base.reclength,
@@ -103,7 +103,7 @@ my_bool _ma_delete_static_record(MARIA_HA *info,
info->state->del++;
info->state->empty+=info->s->base.pack_reclength;
temp[0]= '\0'; /* Mark that record is deleted */
- _ma_dpointer(info,temp+1,info->s->state.dellink);
+ _ma_dpointer(info->s, temp+1, info->s->state.dellink);
info->s->state.dellink= info->cur_row.lastpos;
info->rec_cache.seek_not_done=1;
return (info->s->file_write(info, temp, 1+info->s->rec_reflength,
diff --git a/storage/maria/ma_test1.c b/storage/maria/ma_test1.c
index 471db7937f0..bbaf4b187fd 100644
--- a/storage/maria/ma_test1.c
+++ b/storage/maria/ma_test1.c
@@ -89,6 +89,8 @@ int main(int argc,char *argv[])
fprintf(stderr, "Error in initialization\n");
exit(1);
}
+ if (opt_versioning)
+ init_thr_lock();
exit(run_test("test1"));
}
diff --git a/storage/maria/ma_test2.c b/storage/maria/ma_test2.c
index d3b5cca70c5..08d3ae486cf 100644
--- a/storage/maria/ma_test2.c
+++ b/storage/maria/ma_test2.c
@@ -96,6 +96,8 @@ int main(int argc, char *argv[])
fprintf(stderr, "Error in initialization");
exit(1);
}
+ if (opt_versioning)
+ init_thr_lock();
reclength=STANDARD_LENGTH+60+(use_blob ? 8 : 0);
blob_pos=STANDARD_LENGTH+60;
diff --git a/storage/maria/ma_unique.c b/storage/maria/ma_unique.c
index 51c21f0a085..bae58fd70cd 100644
--- a/storage/maria/ma_unique.c
+++ b/storage/maria/ma_unique.c
@@ -18,24 +18,34 @@
#include "maria_def.h"
#include <m_ctype.h>
+/**
+ Check if there exist a row with the same hash
+
+ @notes
+ This function is not versioning safe. For the moment this is not a problem
+ as it's only used for internal temporary tables in MySQL for which there
+ isn't any versioning information.
+*/
+
my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, uchar *record,
ha_checksum unique_hash, my_off_t disk_pos)
{
my_off_t lastpos=info->cur_row.lastpos;
- MARIA_KEYDEF *key= &info->s->keyinfo[def->key];
- uchar *key_buff= info->lastkey2;
+ MARIA_KEYDEF *keyinfo= &info->s->keyinfo[def->key];
+ uchar *key_buff= info->lastkey_buff2;
+ MARIA_KEY key;
DBUG_ENTER("_ma_check_unique");
DBUG_PRINT("enter",("unique_hash: %lu", (ulong) unique_hash));
- maria_unique_store(record+key->seg->start, unique_hash);
- _ma_make_key(info,def->key,key_buff,record,0);
+ maria_unique_store(record+keyinfo->seg->start, unique_hash);
+ /* Can't be spatial so it's ok to call _ma_make_key directly here */
+ _ma_make_key(info, &key, def->key, key_buff, record, 0, 0);
- /* The above changed info->lastkey2. Inform maria_rnext_same(). */
+ /* The above changed info->lastkey_buff2. Inform maria_rnext_same(). */
info->update&= ~HA_STATE_RNEXT_SAME;
- if (_ma_search(info,info->s->keyinfo+def->key,key_buff,
- MARIA_UNIQUE_HASH_LENGTH,
- SEARCH_FIND,info->s->state.key_root[def->key]))
+ DBUG_ASSERT(key.data_length == MARIA_UNIQUE_HASH_LENGTH);
+ if (_ma_search(info, &key, SEARCH_FIND, info->s->state.key_root[def->key]))
{
info->page_changed=1; /* Can't optimize read next */
info->cur_row.lastpos= lastpos;
@@ -55,10 +65,10 @@ my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, uchar *record,
DBUG_PRINT("info",("Found duplicate"));
DBUG_RETURN(1); /* Found identical */
}
- if (_ma_search_next(info,info->s->keyinfo+def->key, info->lastkey,
- MARIA_UNIQUE_HASH_LENGTH, SEARCH_BIGGER,
+ DBUG_ASSERT(info->last_key.data_length == MARIA_UNIQUE_HASH_LENGTH);
+ if (_ma_search_next(info, &info->last_key, SEARCH_BIGGER,
info->s->state.key_root[def->key]) ||
- bcmp((char*) info->lastkey, (char*) key_buff,
+ bcmp((char*) info->last_key.data, (char*) key_buff,
MARIA_UNIQUE_HASH_LENGTH))
{
info->page_changed= 1; /* Can't optimize read next */
diff --git a/storage/maria/ma_update.c b/storage/maria/ma_update.c
index 4a1ba63c6af..29246d2d07e 100644
--- a/storage/maria/ma_update.c
+++ b/storage/maria/ma_update.c
@@ -13,22 +13,26 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* Update an old row in a MARIA table */
-
#include "ma_fulltext.h"
#include "ma_rt_index.h"
+#include "trnman.h"
+
+/**
+ Update an old row in a MARIA table
+*/
int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
{
int flag,key_changed,save_errno;
reg3 my_off_t pos;
uint i;
- uchar old_key[HA_MAX_KEY_BUFF],*new_key;
+ uchar old_key_buff[MARIA_MAX_KEY_BUFF],*new_key_buff;
my_bool auto_key_changed= 0;
ulonglong changed;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo;
DBUG_ENTER("maria_update");
- LINT_INIT(new_key);
+ LINT_INIT(new_key_buff);
LINT_INIT(changed);
DBUG_EXECUTE_IF("maria_pretend_crashed_table_on_usage",
@@ -81,13 +85,13 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
/* Check which keys changed from the original row */
- new_key= info->lastkey2;
+ new_key_buff= info->lastkey_buff2;
changed=0;
- for (i=0 ; i < share->base.keys ; i++)
+ for (i=0, keyinfo= share->keyinfo ; i < share->base.keys ; i++, keyinfo++)
{
if (maria_is_key_active(share->state.key_map, i))
{
- if (share->keyinfo[i].flag & HA_FULLTEXT )
+ if (keyinfo->flag & HA_FULLTEXT )
{
if (_ma_ft_cmp(info,i,oldrec, newrec))
{
@@ -101,27 +105,33 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
key_changed|=HA_STATE_WRITTEN;
}
changed|=((ulonglong) 1 << i);
- if (_ma_ft_update(info,i,old_key,oldrec,newrec,pos))
+ if (_ma_ft_update(info,i,old_key_buff,oldrec,newrec,pos))
goto err;
}
}
else
{
- uint new_length= _ma_make_key(info,i,new_key,newrec,pos);
- uint old_length= _ma_make_key(info,i,old_key,oldrec,pos);
+ MARIA_KEY new_key, old_key;
+
+ (*keyinfo->make_key)(info,&new_key, i, new_key_buff, newrec,
+ pos, info->trn->trid);
+ (*keyinfo->make_key)(info,&old_key, i, old_key_buff,
+ oldrec, pos, info->cur_row.trid);
/* The above changed info->lastkey2. Inform maria_rnext_same(). */
info->update&= ~HA_STATE_RNEXT_SAME;
- if (new_length != old_length ||
- memcmp(old_key, new_key, new_length))
+ if (new_key.data_length != old_key.data_length ||
+ memcmp(old_key.data, new_key.data, new_key.data_length))
{
if ((int) i == info->lastinx)
key_changed|=HA_STATE_WRITTEN; /* Mark that keyfile changed */
changed|=((ulonglong) 1 << i);
- share->keyinfo[i].version++;
- if (share->keyinfo[i].ck_delete(info,i,old_key,old_length)) goto err;
- if (share->keyinfo[i].ck_insert(info,i,new_key,new_length)) goto err;
+ keyinfo->version++;
+ if (keyinfo->ck_delete(info,&old_key))
+ goto err;
+ if (keyinfo->ck_insert(info,&new_key))
+ goto err;
if (share->base.auto_key == i+1)
auto_key_changed=1;
}
@@ -202,16 +212,20 @@ err:
{
if (share->keyinfo[i].flag & HA_FULLTEXT)
{
- if ((flag++ && _ma_ft_del(info,i,new_key,newrec,pos)) ||
- _ma_ft_add(info,i,old_key,oldrec,pos))
+ if ((flag++ && _ma_ft_del(info,i,new_key_buff,newrec,pos)) ||
+ _ma_ft_add(info,i,old_key_buff,oldrec,pos))
break;
}
else
{
- uint new_length= _ma_make_key(info,i,new_key,newrec,pos);
- uint old_length= _ma_make_key(info,i,old_key,oldrec,pos);
- if ((flag++ && _ma_ck_delete(info,i,new_key,new_length)) ||
- _ma_ck_write(info,i,old_key,old_length))
+ MARIA_KEY new_key, old_key;
+ (*share->keyinfo[i].make_key)(info, &new_key, i, new_key_buff,
+ newrec, pos,
+ info->trn->trid);
+ (*share->keyinfo[i].make_key)(info, &old_key, i, old_key_buff,
+ oldrec, pos, info->cur_row.trid);
+ if ((flag++ && _ma_ck_delete(info, &new_key)) ||
+ _ma_ck_write(info, &old_key))
break;
}
}
diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c
index 9695a3d3bab..06ea4d9c845 100644
--- a/storage/maria/ma_write.c
+++ b/storage/maria/ma_write.c
@@ -25,26 +25,22 @@
/* Functions declared in this file */
-static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uint comp_flag, uchar *key, uint key_length, my_off_t page,
+static int w_search(register MARIA_HA *info, uint32 comp_flag,
+ MARIA_KEY *key, my_off_t page,
my_off_t father_page, uchar *father_buff,
MARIA_PINNED_PAGE *father_page_link, uchar *father_keypos,
my_bool insert_last);
static int _ma_balance_page(MARIA_HA *info,MARIA_KEYDEF *keyinfo,
- uchar *key, uchar *curr_buff, my_off_t page,
+ MARIA_KEY *key, uchar *curr_buff, my_off_t page,
my_off_t father_page, uchar *father_buff,
uchar *father_keypos,
MARIA_KEY_PARAM *s_temp);
-static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page, uchar *key,
- uint *return_key_length, uchar **after_key);
-static int _ma_ck_write_tree(register MARIA_HA *info, uint keynr,uchar *key,
- uint key_length);
-static int _ma_ck_write_btree(register MARIA_HA *info, uint keynr,uchar *key,
- uint key_length);
-static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length,
- my_off_t *root, uint comp_flag);
+static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEY *int_key,
+ uchar *page, uchar **after_key);
+static my_bool _ma_ck_write_tree(register MARIA_HA *info, MARIA_KEY *key);
+static my_bool _ma_ck_write_btree(register MARIA_HA *info, MARIA_KEY *key);
+static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEY *key,
+ my_off_t *root, uint32 comp_flag);
static my_bool _ma_log_split(MARIA_HA *info, my_off_t page, const uchar *buff,
uint org_length, uint new_length,
const uchar *key_pos,
@@ -101,6 +97,7 @@ int maria_write(MARIA_HA *info, uchar *record)
uchar *buff;
my_bool lock_tree= share->lock_key_trees;
my_bool fatal_error;
+ MARIA_KEYDEF *keyinfo;
DBUG_ENTER("maria_write");
DBUG_PRINT("enter",("index_file: %d data_file: %d",
share->kfile.file, info->dfile.file));
@@ -157,9 +154,10 @@ int maria_write(MARIA_HA *info, uchar *record)
}
/* Write all keys to indextree */
- buff= info->lastkey2;
- for (i=0 ; i < share->base.keys ; i++)
+ buff= info->lastkey_buff2;
+ for (i=0, keyinfo= share->keyinfo ; i < share->base.keys ; i++, keyinfo++)
{
+ MARIA_KEY int_key;
if (maria_is_key_active(share->state.key_map, i))
{
my_bool local_lock_tree= (lock_tree &&
@@ -167,27 +165,28 @@ int maria_write(MARIA_HA *info, uchar *record)
is_tree_inited(&info->bulk_insert[i])));
if (local_lock_tree)
{
- rw_wrlock(&share->key_root_lock[i]);
- share->keyinfo[i].version++;
+ rw_wrlock(&keyinfo->root_lock);
+ keyinfo->version++;
}
- if (share->keyinfo[i].flag & HA_FULLTEXT )
+ if (keyinfo->flag & HA_FULLTEXT )
{
if (_ma_ft_add(info,i, buff,record,filepos))
{
if (local_lock_tree)
- rw_unlock(&share->key_root_lock[i]);
+ rw_unlock(&keyinfo->root_lock);
DBUG_PRINT("error",("Got error: %d on write",my_errno));
goto err;
}
}
else
{
- if (share->keyinfo[i].ck_insert(info,i,buff,
- _ma_make_key(info,i,buff,record,
- filepos)))
+ if (keyinfo->ck_insert(info,
+ (*keyinfo->make_key)(info, &int_key, i,
+ buff, record, filepos,
+ info->trn->trid)))
{
if (local_lock_tree)
- rw_unlock(&share->key_root_lock[i]);
+ rw_unlock(&keyinfo->root_lock);
DBUG_PRINT("error",("Got error: %d on write",my_errno));
goto err;
}
@@ -197,7 +196,7 @@ int maria_write(MARIA_HA *info, uchar *record)
info->update&= ~HA_STATE_RNEXT_SAME;
if (local_lock_tree)
- rw_unlock(&share->key_root_lock[i]);
+ rw_unlock(&keyinfo->root_lock);
}
}
if (share->calc_write_checksum)
@@ -275,33 +274,36 @@ err:
my_bool local_lock_tree= (lock_tree &&
!(info->bulk_insert &&
is_tree_inited(&info->bulk_insert[i])));
+ keyinfo= share->keyinfo + i;
if (local_lock_tree)
- rw_wrlock(&share->key_root_lock[i]);
+ rw_wrlock(&keyinfo->root_lock);
/**
@todo RECOVERY BUG
The key deletes below should generate CLR_ENDs
*/
- if (share->keyinfo[i].flag & HA_FULLTEXT)
+ if (keyinfo->flag & HA_FULLTEXT)
{
if (_ma_ft_del(info,i,buff,record,filepos))
{
if (local_lock_tree)
- rw_unlock(&share->key_root_lock[i]);
+ rw_unlock(&keyinfo->root_lock);
break;
}
}
else
{
- uint key_length= _ma_make_key(info,i,buff,record,filepos);
- if (_ma_ck_delete(info,i,buff,key_length))
+ MARIA_KEY key;
+ if (_ma_ck_delete(info,
+ (*keyinfo->make_key)(info, &key, i, buff, record,
+ filepos, info->trn->trid)))
{
if (local_lock_tree)
- rw_unlock(&share->key_root_lock[i]);
+ rw_unlock(&keyinfo->root_lock);
break;
}
}
if (local_lock_tree)
- rw_unlock(&share->key_root_lock[i]);
+ rw_unlock(&keyinfo->root_lock);
}
}
}
@@ -330,17 +332,24 @@ err2:
} /* maria_write */
- /* Write one key to btree */
+/*
+ Write one key to btree
+
+ TODO
+ Remove this function and have bulk insert change keyinfo->ck_insert
+ to point to the right function
+*/
-int _ma_ck_write(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
+my_bool _ma_ck_write(MARIA_HA *info, MARIA_KEY *key)
{
DBUG_ENTER("_ma_ck_write");
- if (info->bulk_insert && is_tree_inited(&info->bulk_insert[keynr]))
+ if (info->bulk_insert &&
+ is_tree_inited(&info->bulk_insert[key->keyinfo->key_nr]))
{
- DBUG_RETURN(_ma_ck_write_tree(info, keynr, key, key_length));
+ DBUG_RETURN(_ma_ck_write_tree(info, key));
}
- DBUG_RETURN(_ma_ck_write_btree(info, keynr, key, key_length));
+ DBUG_RETURN(_ma_ck_write_btree(info, key));
} /* _ma_ck_write */
@@ -348,25 +357,24 @@ int _ma_ck_write(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
Insert key into btree (normal case)
**********************************************************************/
-static int _ma_ck_write_btree(register MARIA_HA *info, uint keynr, uchar *key,
- uint key_length)
+static my_bool _ma_ck_write_btree(MARIA_HA *info, MARIA_KEY *key)
{
int error;
- MARIA_KEYDEF *keyinfo=info->s->keyinfo+keynr;
- my_off_t *root=&info->s->state.key_root[keynr];
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ my_off_t *root= &info->s->state.key_root[keyinfo->key_nr];
DBUG_ENTER("_ma_ck_write_btree");
- error= _ma_ck_write_btree_with_log(info, keyinfo, key, key_length,
- root, keyinfo->write_comp_flag);
+ error= _ma_ck_write_btree_with_log(info, key, root,
+ keyinfo->write_comp_flag | key->flag);
if (info->ft1_to_ft2)
{
if (!error)
- error= _ma_ft_convert_to_ft2(info, keynr, key);
+ error= _ma_ft_convert_to_ft2(info, key);
delete_dynamic(info->ft1_to_ft2);
my_free((uchar*)info->ft1_to_ft2, MYF(0));
info->ft1_to_ft2=0;
}
- DBUG_RETURN(error);
+ DBUG_RETURN(error != 0);
} /* _ma_ck_write_btree */
@@ -377,28 +385,32 @@ static int _ma_ck_write_btree(register MARIA_HA *info, uint keynr, uchar *key,
@retval 0 ok
*/
-static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length,
- my_off_t *root, uint comp_flag)
+static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEY *key,
+ my_off_t *root, uint32 comp_flag)
{
MARIA_SHARE *share= info->s;
LSN lsn= LSN_IMPOSSIBLE;
int error;
my_off_t new_root= *root;
- uchar key_buff[HA_MAX_KEY_BUFF];
+ uchar key_buff[MARIA_MAX_KEY_BUFF];
+ MARIA_KEY org_key;
DBUG_ENTER("_ma_ck_write_btree_with_log");
if (share->now_transactional)
{
/* Save original value as the key may change */
- memcpy(key_buff, key, key_length + share->rec_reflength);
+ org_key= *key;
+ memcpy(key_buff, key->data, key->data_length + key->ref_length);
}
- error= _ma_ck_real_write_btree(info, keyinfo, key, key_length, &new_root,
- comp_flag);
+ error= _ma_ck_real_write_btree(info, key, &new_root, comp_flag);
if (!error && share->now_transactional)
- error= _ma_write_undo_key_insert(info, keyinfo, key_buff, key_length,
- root, new_root, &lsn);
+ {
+ /* Log the original value */
+ *key= org_key;
+ key->data= key_buff;
+ error= _ma_write_undo_key_insert(info, key, root, new_root, &lsn);
+ }
else
{
*root= new_root;
@@ -417,19 +429,17 @@ static int _ma_ck_write_btree_with_log(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
@retval 0 ok
*/
-int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length, my_off_t *root,
- uint comp_flag)
+int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEY *key, my_off_t *root,
+ uint32 comp_flag)
{
int error;
DBUG_ENTER("_ma_ck_real_write_btree");
/* key_length parameter is used only if comp_flag is SEARCH_FIND */
if (*root == HA_OFFSET_ERROR ||
- (error= w_search(info, keyinfo, comp_flag, key, key_length,
- *root, (my_off_t) 0, (uchar*) 0,
+ (error= w_search(info, comp_flag, key, *root, (my_off_t) 0, (uchar*) 0,
(MARIA_PINNED_PAGE *) 0, (uchar*) 0, 1)) > 0)
- error= _ma_enlarge_root(info, keyinfo, key, root);
+ error= _ma_enlarge_root(info, key, root);
DBUG_RETURN(error);
} /* _ma_ck_real_write_btree */
@@ -441,28 +451,32 @@ int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
@retval 0 ok
*/
-int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, const uchar *key,
- my_off_t *root)
+int _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key, my_off_t *root)
{
- uint t_length, nod_flag, page_length;
+ uint t_length, page_flag, nod_flag, page_length;
MARIA_KEY_PARAM s_temp;
MARIA_SHARE *share= info->s;
MARIA_PINNED_PAGE tmp_page_link, *page_link= &tmp_page_link;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
int res= 0;
DBUG_ENTER("_ma_enlarge_root");
nod_flag= (*root != HA_OFFSET_ERROR) ? share->base.key_reflength : 0;
/* Store pointer to prev page if nod */
_ma_kpointer(info, info->buff + share->keypage_header, *root);
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar*) 0,
- (uchar*) 0, (uchar*) 0, key,&s_temp);
+ t_length= (*keyinfo->pack_key)(key, nod_flag, (uchar*) 0,
+ (uchar*) 0, (uchar*) 0, &s_temp);
page_length= share->keypage_header + t_length + nod_flag;
bzero(info->buff, share->keypage_header);
_ma_store_keynr(share, info->buff, keyinfo->key_nr);
_ma_store_page_used(share, info->buff, page_length);
+ page_flag= 0;
if (nod_flag)
- _ma_store_keypage_flag(share, info->buff, KEYPAGE_FLAG_ISNOD);
+ page_flag|= KEYPAGE_FLAG_ISNOD;
+ if (key->flag & (SEARCH_USER_KEY_HAS_TRANSID | SEARCH_PAGE_KEY_HAS_TRANSID))
+ page_flag|= KEYPAGE_FLAG_HAS_TRANSID;
+ _ma_store_keypage_flag(share, info->buff, page_flag);
(*keyinfo->store_key)(keyinfo, info->buff + share->keypage_header +
nod_flag, &s_temp);
@@ -479,7 +493,6 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, const uchar *key,
*/
bzero(info->buff + page_length, share->block_size - page_length);
-
if (share->now_transactional &&
_ma_log_new(info, *root, info->buff, page_length, keyinfo->key_nr, 1))
res= -1;
@@ -500,41 +513,44 @@ int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo, const uchar *key,
@retval > 0 Key should be stored in higher tree
*/
-static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uint comp_flag, uchar *key, uint key_length, my_off_t page,
- my_off_t father_page, uchar *father_buff,
+static int w_search(register MARIA_HA *info, uint32 comp_flag, MARIA_KEY *key,
+ my_off_t page, my_off_t father_page, uchar *father_buff,
MARIA_PINNED_PAGE *father_page_link, uchar *father_keypos,
my_bool insert_last)
{
int error,flag;
- uint nod_flag, search_key_length;
+ uint page_flag, nod_flag;
uchar *temp_buff,*keypos;
- uchar keybuff[HA_MAX_KEY_BUFF];
+ uchar keybuff[MARIA_MAX_KEY_BUFF];
my_bool was_last_key;
my_off_t next_page, dup_key_pos;
MARIA_PINNED_PAGE *page_link;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("w_search");
DBUG_PRINT("enter",("page: %ld", (long) page));
- search_key_length= (comp_flag & SEARCH_FIND) ? key_length : USE_WHOLE_KEY;
if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
- HA_MAX_KEY_BUFF*2)))
+ MARIA_MAX_KEY_BUFF*2)))
DBUG_RETURN(-1);
if (!_ma_fetch_keypage(info, keyinfo, page, PAGECACHE_LOCK_WRITE,
DFLT_INIT_HITS, temp_buff, 0, &page_link))
goto err;
- flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,search_key_length,
- comp_flag, &keypos, keybuff, &was_last_key);
- nod_flag= _ma_test_if_nod(share, temp_buff);
+ flag= (*keyinfo->bin_search)(key, temp_buff, comp_flag, &keypos,
+ keybuff, &was_last_key);
+ page_flag= _ma_get_keypage_flag(share, temp_buff);
+ nod_flag= _ma_test_if_nod(share, temp_buff);
if (flag == 0)
{
- uint tmp_key_length;
+ MARIA_KEY tmp_key;
/* get position to record with duplicated key */
- tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff);
- if (tmp_key_length)
- dup_key_pos= _ma_dpos(info,0,keybuff+tmp_key_length);
+
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= keybuff;
+
+ if ((*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &keypos))
+ dup_key_pos= _ma_row_pos_from_key(&tmp_key);
else
dup_key_pos= HA_OFFSET_ERROR;
@@ -549,8 +565,7 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
if (subkeys >= 0)
{
/* normal word, one-level tree structure */
- flag=(*keyinfo->bin_search)(info, keyinfo, temp_buff, key,
- USE_WHOLE_KEY, comp_flag,
+ flag=(*keyinfo->bin_search)(key, temp_buff, comp_flag,
&keypos, keybuff, &was_last_key);
}
else
@@ -562,9 +577,8 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
key+=off;
/* we'll modify key entry 'in vivo' */
keypos-= keyinfo->keylength + nod_flag;
- error= _ma_ck_real_write_btree(info, keyinfo, key, 0,
- &root, comp_flag);
- _ma_dpointer(info, keypos+HA_FT_WLEN, root);
+ error= _ma_ck_real_write_btree(info, key, &root, comp_flag);
+ _ma_dpointer(share, keypos+HA_FT_WLEN, root);
subkeys--; /* should there be underflow protection ? */
DBUG_ASSERT(subkeys < 0);
ft_intXstore(keypos, subkeys);
@@ -594,10 +608,10 @@ static int w_search(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
insert_last=0;
next_page= _ma_kpos(nod_flag,keypos);
if (next_page == HA_OFFSET_ERROR ||
- (error= w_search(info, keyinfo, comp_flag, key, key_length, next_page,
+ (error= w_search(info, comp_flag, key, next_page,
page, temp_buff, page_link, keypos, insert_last)) > 0)
{
- error= _ma_insert(info, keyinfo, key, temp_buff, keypos, page, keybuff,
+ error= _ma_insert(info, key, temp_buff, keypos, page, keybuff,
father_page, father_buff, father_page_link,
father_keypos, insert_last);
page_link->changed= 1;
@@ -625,10 +639,11 @@ err:
anc_buff Key page (beginning).
key_pos Position in key page where to insert.
anc_page Page number for anc_buff
- key_buff Copy of previous key.
+ key_buff Copy of previous key if keys where packed.
+ father_page position of parent key page in file.
father_buff parent key page for balancing.
+ father_page_link Link to father page for marking page changed
father_key_pos position in parent key page for balancing.
- father_page position of parent key page in file.
insert_last If to append at end of page.
DESCRIPTION
@@ -645,36 +660,34 @@ err:
2 If key contains key to upper level (from split space)
*/
-int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *key, uchar *anc_buff, uchar *key_pos, my_off_t anc_page,
- uchar *key_buff, my_off_t father_page, uchar *father_buff,
- MARIA_PINNED_PAGE *father_page_link, uchar *father_key_pos,
- my_bool insert_last)
+int _ma_insert(register MARIA_HA *info, MARIA_KEY *key, uchar *anc_buff,
+ uchar *key_pos, my_off_t anc_page, uchar *key_buff,
+ my_off_t father_page, uchar *father_buff,
+ MARIA_PINNED_PAGE *father_page_link,
+ uchar *father_key_pos, my_bool insert_last)
{
uint a_length, nod_flag, org_anc_length;
int t_length;
uchar *endpos, *prev_key;
MARIA_KEY_PARAM s_temp;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_insert");
DBUG_PRINT("enter",("key_pos: 0x%lx", (ulong) key_pos));
- DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,
- USE_WHOLE_KEY););
+ DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, key););
_ma_get_used_and_nod(share, anc_buff, a_length, nod_flag);
org_anc_length= a_length;
endpos= anc_buff+ a_length;
prev_key= (key_pos == anc_buff + share->keypage_header + nod_flag ?
(uchar*) 0 : key_buff);
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,
- (key_pos == endpos ? (uchar*) 0 : key_pos),
- prev_key, prev_key,
- key,&s_temp);
+ t_length= (*keyinfo->pack_key)(key, nod_flag,
+ (key_pos == endpos ? (uchar*) 0 : key_pos),
+ prev_key, prev_key, &s_temp);
#ifndef DBUG_OFF
- if (key_pos != anc_buff + share->keypage_header + nod_flag &&
- (keyinfo->flag & (HA_BINARY_PACK_KEY | HA_PACK_KEY)))
+ if (prev_key && (keyinfo->flag & (HA_BINARY_PACK_KEY | HA_PACK_KEY)))
{
- DBUG_DUMP("prev_key",(uchar*) key_buff, _ma_keylength(keyinfo,key_buff));
+ DBUG_DUMP("prev_key",(uchar*) prev_key, _ma_keylength(keyinfo,prev_key));
}
if (keyinfo->flag & HA_PACK_KEY)
{
@@ -692,7 +705,8 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
- bmove_upp((uchar*) endpos+t_length,(uchar*) endpos,(uint) (endpos-key_pos));
+ bmove_upp((uchar*) endpos+t_length,(uchar*) endpos,
+ (uint) (endpos-key_pos));
}
else
{
@@ -706,6 +720,9 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
(*keyinfo->store_key)(keyinfo,key_pos,&s_temp);
a_length+=t_length;
+
+ if (key->flag & (SEARCH_USER_KEY_HAS_TRANSID | SEARCH_PAGE_KEY_HAS_TRANSID))
+ _ma_mark_page_with_transid(share, anc_buff);
_ma_store_page_used(share, anc_buff, a_length);
/*
@@ -724,7 +741,8 @@ int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
Let's consider converting.
We'll compare 'key' and the first key at anc_buff
*/
- const uchar *a= key, *b= anc_buff + share->keypage_header + nod_flag;
+ const uchar *a= key->data;
+ const uchar *b= anc_buff + share->keypage_header + nod_flag;
uint alen, blen, ft2len= share->ft2_keyinfo.keylength;
/* the very first key on the page is always unpacked */
DBUG_ASSERT((*b & 128) == 0);
@@ -783,8 +801,15 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
/* Page is full */
if (nod_flag)
insert_last=0;
+ /*
+ TODO:
+ Remove 'born_transactional' here.
+ The only reason for having it here is that the current
+ _ma_balance_page_ can't handle variable length keys.
+ */
if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)) &&
- father_buff && !insert_last && !info->quick_mode)
+ father_buff && !insert_last && !info->quick_mode &&
+ !info->s->base.born_transactional)
{
s_temp.key_pos= key_pos;
father_page_link->changed= 1;
@@ -792,7 +817,7 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
father_page, father_buff, father_key_pos,
&s_temp));
}
- DBUG_RETURN(_ma_split_page(info, keyinfo, key, anc_page,
+ DBUG_RETURN(_ma_split_page(info, key, anc_page,
anc_buff, org_anc_length,
key_pos, s_temp.changed_length, t_length,
key_buff, insert_last));
@@ -823,20 +848,22 @@ ChangeSet@1.2562, 2008-04-09 07:41:40+02:00, serg@janus.mylan +9 -0
@retval -1 error
*/
-int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *key, my_off_t split_page, uchar *split_buff,
+int _ma_split_page(MARIA_HA *info, MARIA_KEY *key, my_off_t split_page,
+ uchar *split_buff,
uint org_split_length,
uchar *inserted_key_pos, uint changed_length,
int move_length,
uchar *key_buff, my_bool insert_last_key)
{
uint length,a_length,key_ref_length,t_length,nod_flag,key_length;
- uint page_length, split_length;
+ uint page_length, split_length, page_flag;
uchar *key_pos,*pos, *after_key, *new_buff;
my_off_t new_pos;
MARIA_KEY_PARAM s_temp;
MARIA_PINNED_PAGE tmp_page_link, *page_link= &tmp_page_link;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
+ MARIA_KEY tmp_key;
int res;
DBUG_ENTER("_ma_split_page");
@@ -846,18 +873,21 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
info->page_changed=1; /* Info->buff is used */
info->keyread_buff_used=1;
new_buff= info->buff;
- nod_flag= _ma_test_if_nod(share, split_buff);
+ page_flag= _ma_get_keypage_flag(share, split_buff);
+ nod_flag= _ma_test_if_nod(share, split_buff);
key_ref_length= share->keypage_header + nod_flag;
+
+ tmp_key.data= key_buff;
+ tmp_key.keyinfo= keyinfo;
if (insert_last_key)
- key_pos= _ma_find_last_pos(info, keyinfo, split_buff,
- key_buff, &key_length,
- &after_key);
+ key_pos= _ma_find_last_pos(info, &tmp_key, split_buff, &after_key);
else
- key_pos= _ma_find_half_pos(info, nod_flag, keyinfo, split_buff, key_buff,
- &key_length, &after_key);
+ key_pos= _ma_find_half_pos(info, &tmp_key, nod_flag, split_buff,
+ &after_key);
if (!key_pos)
DBUG_RETURN(-1);
+ key_length= tmp_key.data_length + tmp_key.ref_length;
split_length= (uint) (key_pos - split_buff);
a_length= _ma_get_page_used(share, split_buff);
_ma_store_page_used(share, split_buff, split_length);
@@ -875,15 +905,16 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
if ((new_pos= _ma_new(info, PAGECACHE_PRIORITY_HIGH, &page_link)) ==
HA_OFFSET_ERROR)
DBUG_RETURN(-1);
- _ma_kpointer(info, _ma_move_key(keyinfo,key,key_buff),new_pos);
+
+ _ma_copy_key(key, &tmp_key);
+ _ma_kpointer(info, key->data + key_length, new_pos);
/* Store new page */
- if (!(*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff))
+ if (!(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &key_pos))
DBUG_RETURN(-1);
- t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar *) 0,
- (uchar*) 0, (uchar*) 0,
- key_buff, &s_temp);
+ t_length=(*keyinfo->pack_key)(&tmp_key, nod_flag, (uchar *) 0,
+ (uchar*) 0, (uchar*) 0, &s_temp);
length=(uint) ((split_buff + a_length) - key_pos);
memcpy((uchar*) new_buff+key_ref_length+t_length,(uchar*) key_pos,
(size_t) length);
@@ -891,8 +922,8 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
page_length= length + t_length + key_ref_length;
bzero(new_buff, share->keypage_header);
- if (nod_flag)
- _ma_store_keypage_flag(share, new_buff, KEYPAGE_FLAG_ISNOD);
+ /* Copy KEYFLAG_FLAG_ISNODE and KEYPAGE_FLAG_HAS_TRANSID from parent page */
+ _ma_store_keypage_flag(share, new_buff, page_flag);
_ma_store_page_used(share, new_buff, page_length);
/* Copy key number */
new_buff[share->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_KEYID_SIZE -
@@ -918,7 +949,7 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
KEY_OP_NONE, (uchar*) 0, 0, 0))
res= -1;
- DBUG_DUMP("key",(uchar*) key, _ma_keylength(keyinfo,key));
+ DBUG_DUMP_KEY("middle_key", key);
DBUG_RETURN(res);
} /* _ma_split_page */
@@ -932,98 +963,123 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
after_key will contain the position to where the next key starts
*/
-uchar *_ma_find_half_pos(MARIA_HA *info, uint nod_flag, MARIA_KEYDEF *keyinfo,
- uchar *page, uchar *key, uint *return_key_length,
- uchar **after_key)
+uchar *_ma_find_half_pos(MARIA_HA *info, MARIA_KEY *key, uint nod_flag,
+ uchar *page, uchar **after_key)
{
- uint keys,length,key_ref_length;
+ uint keys, length, key_ref_length, page_flag;
uchar *end,*lastpos;
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
DBUG_ENTER("_ma_find_half_pos");
key_ref_length= share->keypage_header + nod_flag;
+ page_flag= _ma_get_keypage_flag(share, page);
length= _ma_get_page_used(share, page) - key_ref_length;
page+= key_ref_length; /* Point to first key */
if (!(keyinfo->flag &
(HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
- HA_BINARY_PACK_KEY)))
+ HA_BINARY_PACK_KEY)) && !(page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
- key_ref_length=keyinfo->keylength+nod_flag;
+ key_ref_length= keyinfo->keylength+nod_flag;
+ key->data_length= keyinfo->keylength - info->s->rec_reflength;
+ key->ref_length= info->s->rec_reflength;
+ key->flag= 0;
keys=length/(key_ref_length*2);
- *return_key_length=keyinfo->keylength;
end=page+keys*key_ref_length;
*after_key=end+key_ref_length;
- memcpy(key,end,key_ref_length);
+ memcpy(key->data, end, key_ref_length);
DBUG_RETURN(end);
}
end=page+length/2-key_ref_length; /* This is aprox. half */
- *key='\0';
+ key->data[0]= 0; /* Safety */
do
{
lastpos=page;
- if (!(length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key)))
+ if (!(length= (*keyinfo->get_key)(key, page_flag, nod_flag, &page)))
DBUG_RETURN(0);
} while (page < end);
- *return_key_length=length;
- *after_key=page;
+ *after_key= page;
DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx half: 0x%lx",
(long) lastpos, (long) page, (long) end));
DBUG_RETURN(lastpos);
} /* _ma_find_half_pos */
-/*
- Split buffer at last key
- Returns pointer to the start of the key before the last key
- key will contain the last key
+/**
+ Find second to last key on leaf page
+
+ @notes
+ Used to split buffer at last key. In this case the next to last
+ key will be moved to parent page and last key will be on it's own page.
+
+ @TODO
+ Add one argument for 'last key value' to get_key so that one can
+ do the loop without having to copy the found key the whole time
+
+ @return
+ @retval Pointer to the start of the key before the last key
+ @retval int_key will contain the last key
*/
-static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page,
- uchar *key, uint *return_key_length,
- uchar **after_key)
+static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEY *int_key,
+ uchar *page, uchar **after_key)
{
- uint keys,length,last_length,key_ref_length;
- uchar *end,*lastpos,*prevpos;
- uchar key_buff[HA_MAX_KEY_BUFF];
+ uint keys, length, key_ref_length, page_flag;
+ uint last_data_length, last_ref_length;
+ uchar *key, *end, *lastpos,*prevpos;
+ uchar key_buff[MARIA_MAX_KEY_BUFF];
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= int_key->keyinfo;
DBUG_ENTER("_ma_find_last_pos");
key_ref_length= share->keypage_header;
+ page_flag= _ma_get_keypage_flag(share, page);
length= _ma_get_page_used(share, page) - key_ref_length;
page+=key_ref_length;
if (!(keyinfo->flag &
(HA_PACK_KEY | HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY |
- HA_BINARY_PACK_KEY)))
+ HA_BINARY_PACK_KEY)) && !(page_flag & KEYPAGE_FLAG_HAS_TRANSID))
{
- keys=length/keyinfo->keylength-2;
- *return_key_length=length=keyinfo->keylength;
+ keys= length / keyinfo->keylength - 2;
+ length= keyinfo->keylength;
+ int_key->data_length= length - info->s->rec_reflength;
+ int_key->ref_length= info->s->rec_reflength;
+ int_key->flag= 0;
end=page+keys*length;
*after_key=end+length;
- memcpy(key,end,length);
+ memcpy(int_key->data, end, length);
DBUG_RETURN(end);
}
LINT_INIT(prevpos);
- LINT_INIT(last_length);
+ LINT_INIT(last_data_length);
+ LINT_INIT(last_ref_length);
end=page+length-key_ref_length;
- *key='\0';
+ key= int_key->data;
+
length=0;
lastpos=page;
+ int_key->data= key_buff;
+ key_buff[0]= 0; /* Safety */
+
while (page < end)
{
prevpos=lastpos; lastpos=page;
- last_length=length;
+ last_data_length= int_key->data_length;
+ last_ref_length= int_key->ref_length;
memcpy(key, key_buff, length); /* previous key */
- if (!(length=(*keyinfo->get_key)(keyinfo,0,&page,key_buff)))
+ if (!(length=(*keyinfo->get_key)(int_key, page_flag, 0, &page)))
{
maria_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
}
- *return_key_length=last_length;
+ int_key->data= key;
+ int_key->data_length= last_data_length;
+ int_key->ref_length= last_ref_length;
+
*after_key=lastpos;
DBUG_PRINT("exit",("returns: 0x%lx page: 0x%lx end: 0x%lx",
(long) prevpos,(long) page,(long) end));
@@ -1047,7 +1103,7 @@ static uchar *_ma_find_last_pos(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
*/
static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, uchar *curr_buff,
+ MARIA_KEY *key, uchar *curr_buff,
my_off_t curr_page,
my_off_t father_page, uchar *father_buff,
uchar *father_key_pos, MARIA_KEY_PARAM *s_temp)
@@ -1061,7 +1117,7 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uint keys, tmp_length, extra_buff_length;
uchar *pos,*buff,*extra_buff, *parting_key;
my_off_t next_page,new_pos;
- uchar tmp_part_key[HA_MAX_KEY_BUFF];
+ uchar tmp_part_key[MARIA_MAX_KEY_BUFF];
DBUG_ENTER("_ma_balance_page");
k_length=keyinfo->keylength;
@@ -1325,13 +1381,16 @@ static int _ma_balance_page(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
memcpy(parting_key, father_key_pos, (size_t) k_length);
/* Move new parting keys up to caller */
- memcpy((right ? key : father_key_pos),pos,(size_t) k_length);
- memcpy((right ? father_key_pos : key),tmp_part_key, k_length);
+ memcpy((right ? key->data : father_key_pos),pos,(size_t) k_length);
+ memcpy((right ? father_key_pos : key->data),tmp_part_key, k_length);
if ((new_pos= _ma_new(info, DFLT_INIT_HITS, &new_page_link))
== HA_OFFSET_ERROR)
goto err;
- _ma_kpointer(info,key+k_length,new_pos);
+ _ma_kpointer(info,key->data+k_length,new_pos);
+ /* This is safe as long we are using not keys with transid */
+ key->data_length= k_length - info->s->rec_reflength;
+ key->ref_length= info->s->rec_reflength;
if (share->now_transactional)
{
@@ -1441,17 +1500,17 @@ typedef struct {
} bulk_insert_param;
-static int _ma_ck_write_tree(register MARIA_HA *info, uint keynr, uchar *key,
- uint key_length)
+static my_bool _ma_ck_write_tree(register MARIA_HA *info, MARIA_KEY *key)
{
- int error;
+ my_bool error;
+ uint keynr= key->keyinfo->key_nr;
DBUG_ENTER("_ma_ck_write_tree");
- error= (tree_insert(&info->bulk_insert[keynr], key,
- key_length + info->s->rec_reflength,
- info->bulk_insert[keynr].custom_arg) ? 0 :
- HA_ERR_OUT_OF_MEM) ;
-
+ /* Store ref_length as this is always constant */
+ info->bulk_insert_ref_length= key->ref_length;
+ error= tree_insert(&info->bulk_insert[keynr], key->data,
+ key->data_length + key->ref_length,
+ info->bulk_insert[keynr].custom_arg) == 0;
DBUG_RETURN(error);
} /* _ma_ck_write_tree */
@@ -1474,30 +1533,40 @@ static int keys_free(uchar *key, TREE_FREE mode, bulk_insert_param *param)
and to be safe I'd better use local lastkey.
*/
MARIA_SHARE *share= param->info->s;
- uchar lastkey[HA_MAX_KEY_BUFF];
+ uchar lastkey[MARIA_MAX_KEY_BUFF];
uint keylen;
- MARIA_KEYDEF *keyinfo;
+ MARIA_KEYDEF *keyinfo= share->keyinfo + param->keynr;
+ MARIA_KEY tmp_key;
switch (mode) {
case free_init:
if (share->lock_key_trees)
{
- rw_wrlock(&share->key_root_lock[param->keynr]);
- share->keyinfo[param->keynr].version++;
+ rw_wrlock(&keyinfo->root_lock);
+ keyinfo->version++;
}
return 0;
case free_free:
- keyinfo=share->keyinfo+param->keynr;
+ /* Note: keylen doesn't contain transid lengths */
keylen= _ma_keylength(keyinfo, key);
- memcpy(lastkey, key, keylen);
- return _ma_ck_write_btree(param->info, param->keynr, lastkey,
- keylen - share->rec_reflength);
+ tmp_key.data= lastkey;
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data_length= keylen - share->rec_reflength;
+ tmp_key.ref_length= param->info->bulk_insert_ref_length;
+ tmp_key.flag= (param->info->bulk_insert_ref_length ==
+ share->rec_reflength ? 0 : SEARCH_USER_KEY_HAS_TRANSID);
+ /*
+ We have to copy key as ma_ck_write_btree may need the buffer for
+ copying middle key up if tree is growing
+ */
+ memcpy(lastkey, key, tmp_key.data_length + tmp_key.ref_length);
+ return _ma_ck_write_btree(param->info, &tmp_key);
case free_end:
if (share->lock_key_trees)
- rw_unlock(&share->key_root_lock[param->keynr]);
+ rw_unlock(&keyinfo->root_lock);
return 0;
}
- return -1;
+ return 1;
}
@@ -1599,48 +1668,50 @@ void maria_end_bulk_insert(MARIA_HA *info, my_bool abort)
****************************************************************************/
-int _ma_write_undo_key_insert(MARIA_HA *info,
- const MARIA_KEYDEF *keyinfo,
- const uchar *key, uint key_length,
+int _ma_write_undo_key_insert(MARIA_HA *info, const MARIA_KEY *key,
my_off_t *root, my_off_t new_root, LSN *res_lsn)
{
MARIA_SHARE *share= info->s;
+ MARIA_KEYDEF *keyinfo= key->keyinfo;
uchar log_data[LSN_STORE_SIZE + FILEID_STORE_SIZE +
KEY_NR_STORE_SIZE];
+ const uchar *key_value;
LEX_CUSTRING log_array[TRANSLOG_INTERNAL_PARTS + 2];
struct st_msg_to_write_hook_for_undo_key msg;
+ uint key_length;
/* Save if we need to write a clr record */
lsn_store(log_data, info->trn->undo_lsn);
key_nr_store(log_data + LSN_STORE_SIZE + FILEID_STORE_SIZE,
keyinfo->key_nr);
- key_length+= share->rec_reflength;
+ key_length= key->data_length + key->ref_length;
log_array[TRANSLOG_INTERNAL_PARTS + 0].str= log_data;
log_array[TRANSLOG_INTERNAL_PARTS + 0].length= sizeof(log_data);
- log_array[TRANSLOG_INTERNAL_PARTS + 1].str= key;
+ log_array[TRANSLOG_INTERNAL_PARTS + 1].str= key->data;
log_array[TRANSLOG_INTERNAL_PARTS + 1].length= key_length;
msg.root= root;
msg.value= new_root;
msg.auto_increment= 0;
- if (share->base.auto_key == ((uint)keyinfo->key_nr + 1))
+ key_value= key->data;
+ if (share->base.auto_key == ((uint) keyinfo->key_nr + 1))
{
const HA_KEYSEG *keyseg= keyinfo->seg;
+ uchar reversed[MARIA_MAX_KEY_BUFF];
if (keyseg->flag & HA_SWAP_KEY)
{
/* We put key from log record to "data record" packing format... */
- uchar reversed[HA_MAX_KEY_BUFF];
- const uchar *key_ptr= key, *key_end= key + keyseg->length;
+ const uchar *key_ptr= key->data, *key_end= key->data + keyseg->length;
uchar *to= reversed + keyseg->length;
do
{
*--to= *key_ptr++;
} while (key_ptr != key_end);
- key= to;
+ key_value= to;
}
/* ... so that we can read it with: */
msg.auto_increment=
- ma_retrieve_auto_increment(key, keyseg->type);
+ ma_retrieve_auto_increment(key_value, keyseg->type);
/* and write_hook_for_undo_key_insert() will pick this. */
}
diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c
index b64a7379c50..767b0c8218d 100644
--- a/storage/maria/maria_chk.c
+++ b/storage/maria/maria_chk.c
@@ -1677,6 +1677,17 @@ static int maria_sort_records(HA_CHECK *param,
param->error_printed=0;
DBUG_RETURN(0); /* Nothing to do */
}
+ if (keyinfo->flag & HA_BINARY_PACK_KEY)
+ {
+ _ma_check_print_warning(param,
+ "Can't sort table '%s' on a key with prefix "
+ "packing %d",
+ name,sort_key+1);
+ param->error_printed=0;
+ DBUG_RETURN(0);
+ }
+
+
if (share->data_file_type == COMPRESSED_RECORD)
{
_ma_check_print_warning(param,"Can't sort read-only table '%s'", name);
@@ -1822,17 +1833,21 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info,
File new_file,my_bool update_index)
{
MARIA_SHARE *share= info->s;
- uint nod_flag,used_length,key_length;
+ uint page_flag, nod_flag,used_length;
uchar *temp_buff,*keypos,*endpos;
my_off_t next_page,rec_pos;
- uchar lastkey[HA_MAX_KEY_BUFF];
+ uchar lastkey[MARIA_MAX_KEY_BUFF];
char llbuff[22];
MARIA_SORT_INFO *sort_info= sort_param->sort_info;
HA_CHECK *param=sort_info->param;
+ MARIA_KEY tmp_key;
DBUG_ENTER("sort_record_index");
- nod_flag=_ma_test_if_nod(share, buff);
+ page_flag= _ma_get_keypage_flag(share, buff);
+ nod_flag= _ma_test_if_nod(share, buff);
temp_buff=0;
+ tmp_key.keyinfo= keyinfo;
+ tmp_key.data= lastkey;
if (nod_flag)
{
@@ -1866,10 +1881,9 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info,
}
_sanity(__FILE__,__LINE__);
if (keypos >= endpos ||
- (key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey))
- == 0)
+ !(*keyinfo->get_key)(&tmp_key, page_flag, nod_flag, &keypos))
break;
- rec_pos= _ma_dpos(info,0,lastkey+key_length);
+ rec_pos= _ma_row_pos_from_key(&tmp_key);
if ((*share->read_record)(info,sort_param->record,rec_pos))
{
@@ -1878,10 +1892,10 @@ static int sort_record_index(MARIA_SORT_PARAM *sort_param,MARIA_HA *info,
}
if (rec_pos != sort_param->filepos && update_index)
{
- _ma_dpointer(info,keypos-nod_flag-share->rec_reflength,
+ _ma_dpointer(share, keypos - nod_flag - tmp_key.ref_length,
sort_param->filepos);
if (maria_movepoint(info,sort_param->record,rec_pos,sort_param->filepos,
- sort_key))
+ sort_key))
{
_ma_check_print_error(param,"%d when updating key-pointers",my_errno);
goto err;
diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h
index 7d124119e5a..c1160993607 100644
--- a/storage/maria/maria_def.h
+++ b/storage/maria/maria_def.h
@@ -75,12 +75,13 @@ typedef struct st_maria_state_info
} header;
MARIA_STATUS_INFO state;
+ /* maria_ha->state points here for crash-safe but not versioned tables */
+ MARIA_STATUS_INFO common;
ha_rows split; /* number of split blocks */
my_off_t dellink; /* Link to next removed block */
pgcache_page_no_t first_bitmap_with_space;
ulonglong auto_increment;
- ulong process; /* process that updated table last */
- ulong unique; /* Unique number for this process */
+ TrID create_trid; /* Minum trid for file */
ulong update_count; /* Updated for each write lock */
ulong status;
double *rec_per_key_part;
@@ -135,6 +136,7 @@ typedef struct st_maria_state_info
#define MARIA_FILE_OPEN_COUNT_OFFSET 0
#define MARIA_FILE_CHANGED_OFFSET 2
#define MARIA_FILE_CREATE_RENAME_LSN_OFFSET 4
+#define MARIA_FILE_CREATE_TRID_OFFSET (4 + LSN_STORE_SIZE*3 + 11*8)
#define MARIA_STATE_KEY_SIZE (8 + 4)
#define MARIA_STATE_KEYBLOCK_SIZE 8
@@ -143,11 +145,14 @@ typedef struct st_maria_state_info
#define MARIA_KEYDEF_SIZE (2+ 5*2)
#define MARIA_UNIQUEDEF_SIZE (2+1+1)
#define HA_KEYSEG_SIZE (6+ 2*2 + 4*2)
+#define MARIA_MAX_KEY_BUFF (HA_MAX_KEY_BUFF + MAX_PACK_TRANSID_SIZE)
#define MARIA_COLUMNDEF_SIZE (2*7+1+1+4)
#define MARIA_BASE_INFO_SIZE (MY_UUID_SIZE + 5*8 + 6*4 + 11*2 + 6 + 5*2 + 1 + 16)
#define MARIA_INDEX_BLOCK_MARGIN 16 /* Safety margin for .MYI tables */
/* Internal management bytes needed to store 2 keys on an index page */
-#define MARIA_INDEX_OVERHEAD_SIZE (TRANSID_SIZE * 2)
+#define MAX_PACK_TRANSID_SIZE (TRANSID_SIZE+1)
+#define MIN_TRANSID_PACK_PREFIX (256-TRANSID_SIZE*2)
+#define MARIA_INDEX_OVERHEAD_SIZE (MAX_PACK_TRANSID_SIZE * 2)
#define MARIA_DELETE_KEY_NR 255 /* keynr for deleted blocks */
/*
@@ -323,8 +328,9 @@ typedef struct st_maria_share
/* Compare a row in memory with a row on disk */
my_bool (*compare_unique)(MARIA_HA *, MARIA_UNIQUEDEF *,
const uchar *record, MARIA_RECORD_POS pos);
- my_off_t (*keypos_to_recpos)(MARIA_HA *info, my_off_t pos);
- my_off_t (*recpos_to_keypos)(MARIA_HA *info, my_off_t pos);
+ my_off_t (*keypos_to_recpos)(struct st_maria_share *share, my_off_t pos);
+ my_off_t (*recpos_to_keypos)(struct st_maria_share *share, my_off_t pos);
+ my_bool (*row_is_visible)(MARIA_HA *);
/* Mapings to read/write the data file */
size_t (*file_read)(MARIA_HA *, uchar *, size_t, my_off_t, myf);
@@ -374,13 +380,13 @@ typedef struct st_maria_share
(FALSE, TRUE) is impossible.
*/
my_bool now_transactional;
+ my_bool have_versioning;
my_bool used_key_del; /* != 0 if key_del is locked */
#ifdef THREAD
THR_LOCK lock;
void (*lock_restore_status)(void *);
pthread_mutex_t intern_lock; /* Locking for use with _locking */
pthread_cond_t intern_cond;
- rw_lock_t *key_root_lock;
#endif
my_off_t mmaped_length;
uint nonmmaped_inserts; /* counter of writing in
@@ -460,6 +466,7 @@ struct st_maria_handler
MARIA_STATUS_INFO *state_start; /* State at start of transaction */
MARIA_ROW cur_row; /* The active row that we just read */
MARIA_ROW new_row; /* Storage for a row during update */
+ MARIA_KEY last_key; /* Last found key */
MARIA_BLOCK_SCAN scan, *scan_save;
MARIA_BLOB *blobs; /* Pointer to blobs */
MARIA_BIT_BUFF bit_buff;
@@ -473,7 +480,8 @@ struct st_maria_handler
MYSQL_FTPARSER_PARAM *ftparser_param; /* share info between init/deinit */
uchar *buff; /* page buffer */
uchar *keyread_buff; /* Buffer for last key read */
- uchar *lastkey, *lastkey2; /* Last used search key */
+ uchar *lastkey_buff; /* Last used search key */
+ uchar *lastkey_buff2;
uchar *first_mbr_key; /* Searhed spatial key */
uchar *rec_buff; /* Temp buffer for recordpack */
uchar *blob_buff; /* Temp buffer for blobs */
@@ -510,12 +518,14 @@ struct st_maria_handler
uint opt_flag; /* Optim. for space/speed */
uint update; /* If file changed since open */
int lastinx; /* Last used index */
- uint lastkey_length; /* Length of key in lastkey */
uint last_rkey_length; /* Last length in maria_rkey() */
+ uint *last_rtree_keypos; /* Last key positions for rtrees */
+ uint bulk_insert_ref_length; /* Lenght of row ref during bi */
uint non_flushable_state;
enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */
- uint save_lastkey_length;
- uint pack_key_length; /* For MARIAMRG */
+ uint save_lastkey_data_length;
+ uint save_lastkey_ref_length;
+ uint pack_key_length; /* For MARIA_MRG */
myf lock_wait; /* is 0 or MY_SHORT_WAIT */
int errkey; /* Got last error on this key */
int lock_type; /* How database was locked */
@@ -588,7 +598,10 @@ struct st_maria_handler
#define MAX_KEYPAGE_HEADER_SIZE (LSN_STORE_SIZE + KEYPAGE_USED_SIZE + \
KEYPAGE_KEYID_SIZE + KEYPAGE_FLAG_SIZE + \
TRANSID_SIZE)
-#define KEYPAGE_FLAG_ISNOD 1
+#define KEYPAGE_FLAG_ISNOD 1
+#define KEYPAGE_FLAG_HAS_TRANSID 2
+/* Position to KEYPAGE_FLAG for transactional tables */
+#define KEYPAGE_TRANSFLAG_OFFSET LSN_STORE_SIZE + TRANSID_SIZE + KEYPAGE_KEYID_SIZE
#define _ma_get_page_used(share,x) \
((uint) mi_uint2korr((x) + (share)->keypage_header - KEYPAGE_USED_SIZE))
@@ -599,8 +612,13 @@ struct st_maria_handler
#define _ma_get_used_and_nod(share,buff,length,nod) \
{ \
- nod= _ma_test_if_nod((share),(buff)); \
- length= _ma_get_page_used((share),(buff)); \
+ (nod)= _ma_test_if_nod((share),(buff)); \
+ (length)= _ma_get_page_used((share),(buff)); \
+}
+#define _ma_get_used_and_nod_with_flag(share,flag,buff,length,nod) \
+{ \
+ (nod)= (((flag) & KEYPAGE_FLAG_ISNOD) ? (share)->base.key_reflength : 0); \
+ (length)= _ma_get_page_used((share),(buff)); \
}
#define _ma_store_keynr(share, x, nr) x[(share)->keypage_header - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE - KEYPAGE_USED_SIZE]= (nr)
#define _ma_get_keynr(share, x) ((uchar) x[(share)->keypage_header - KEYPAGE_KEYID_SIZE - KEYPAGE_FLAG_SIZE - KEYPAGE_USED_SIZE])
@@ -610,6 +628,7 @@ struct st_maria_handler
transid_korr((buff) + LSN_STORE_SIZE)
#define _ma_get_keypage_flag(share,x) x[(share)->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE]
#define _ma_store_keypage_flag(share,x,flag) x[(share)->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE]= (flag)
+#define _ma_mark_page_with_transid(share, x) x[(share)->keypage_header - KEYPAGE_USED_SIZE - KEYPAGE_FLAG_SIZE]|= KEYPAGE_FLAG_HAS_TRANSID
/*
@@ -647,6 +666,7 @@ struct st_maria_handler
#else
#define maria_print_error(SHARE, ERRNO) while (0)
#endif
+#define DBUG_DUMP_KEY(name, key) DBUG_DUMP(name, (key)->data, (key)->data_length + (key)->ref_length)
/* Functions to store length of space packed keys, VARCHAR or BLOB keys */
@@ -674,6 +694,7 @@ struct st_maria_handler
#define maria_max_key_length() ((maria_block_size - MAX_KEYPAGE_HEADER_SIZE)/2 - MARIA_INDEX_OVERHEAD_SIZE)
#define get_pack_length(length) ((length) >= 255 ? 3 : 1)
+#define _ma_have_versioning(info) ((info)->row_flag & ROW_FLAG_TRANSID)
#define MARIA_MIN_BLOCK_LENGTH 20 /* Because of delete-link */
/* Don't use to small record-blocks */
@@ -732,7 +753,7 @@ extern pthread_mutex_t THR_LOCK_maria;
extern LIST *maria_open_list;
extern uchar maria_file_magic[], maria_pack_file_magic[];
extern uchar maria_uuid[MY_UUID_SIZE];
-extern uint maria_read_vec[], maria_readnext_vec[];
+extern uint32 maria_read_vec[], maria_readnext_vec[];
extern uint maria_quick_table_bits;
extern char *maria_data_root;
extern uchar maria_zero_string[];
@@ -782,47 +803,38 @@ extern my_bool _ma_update_static_record(MARIA_HA *, MARIA_RECORD_POS,
const uchar *, const uchar *);
extern my_bool _ma_delete_static_record(MARIA_HA *info, const uchar *record);
extern my_bool _ma_cmp_static_record(MARIA_HA *info, const uchar *record);
-extern int _ma_ck_write(MARIA_HA *info, uint keynr, uchar *key,
- uint length);
-extern int _ma_enlarge_root(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- const uchar *key, MARIA_RECORD_POS *root);
-extern int _ma_insert(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
- uchar *key, uchar *anc_buff, uchar *key_pos,
- my_off_t anc_page, uchar *key_buff, my_off_t father_page,
- uchar *father_buff, MARIA_PINNED_PAGE *father_page_link,
+extern my_bool _ma_ck_write(MARIA_HA *info, MARIA_KEY *key);
+extern int _ma_enlarge_root(MARIA_HA *info, MARIA_KEY *key,
+ MARIA_RECORD_POS *root);
+extern int _ma_insert(MARIA_HA *info, MARIA_KEY *key, uchar *anc_buff,
+ uchar *key_pos, my_off_t anc_page, uchar *key_buff,
+ my_off_t father_page, uchar *father_buff,
+ MARIA_PINNED_PAGE *father_page_link,
uchar *father_key_pos, my_bool insert_last);
-extern int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length,
- MARIA_RECORD_POS *root, uint comp_flag);
-extern int _ma_split_page(register MARIA_HA *info,
- register MARIA_KEYDEF *keyinfo,
- uchar *key, my_off_t split_page, uchar *split_buff,
- uint org_split_length,
+extern int _ma_ck_real_write_btree(MARIA_HA *info, MARIA_KEY *key,
+ MARIA_RECORD_POS *root, uint32 comp_flag);
+extern int _ma_split_page(MARIA_HA *info, MARIA_KEY *key, my_off_t split_page,
+ uchar *split_buff, uint org_split_length,
uchar *inserted_key_pos, uint changed_length,
int move_length,
uchar *key_buff, my_bool insert_last_key);
-extern uchar *_ma_find_half_pos(MARIA_HA *info, uint nod_flag,
- MARIA_KEYDEF *keyinfo,
- uchar *page, uchar *key,
- uint *return_key_length,
- uchar ** after_key);
-extern int _ma_calc_static_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
+extern uchar *_ma_find_half_pos(MARIA_HA *info, MARIA_KEY *key, uint nod_flag,
+ uchar *page, uchar ** after_key);
+extern int _ma_calc_static_key_length(const MARIA_KEY *key, uint nod_flag,
uchar *key_pos, uchar *org_key,
- uchar *key_buff, const uchar *key,
+ uchar *key_buff,
MARIA_KEY_PARAM *s_temp);
-extern int _ma_calc_var_key_length(MARIA_KEYDEF *keyinfo, uint nod_flag,
+extern int _ma_calc_var_key_length(const MARIA_KEY *key, uint nod_flag,
uchar *key_pos, uchar *org_key,
- uchar *key_buff, const uchar *key,
+ uchar *key_buff,
MARIA_KEY_PARAM *s_temp);
-extern int _ma_calc_var_pack_key_length(MARIA_KEYDEF *keyinfo,
- uint nod_flag, uchar *key_pos,
+extern int _ma_calc_var_pack_key_length(const MARIA_KEY *key,
+ uint nod_flag, uchar *next_key,
uchar *org_key, uchar *prev_key,
- const uchar *key,
MARIA_KEY_PARAM *s_temp);
-extern int _ma_calc_bin_pack_key_length(MARIA_KEYDEF *keyinfo,
- uint nod_flag, uchar *key_pos,
+extern int _ma_calc_bin_pack_key_length(const MARIA_KEY *key,
+ uint nod_flag, uchar *next_key,
uchar *org_key, uchar *prev_key,
- const uchar *key,
MARIA_KEY_PARAM *s_temp);
extern void _ma_store_static_key(MARIA_KEYDEF *keyinfo, uchar *key_pos,
MARIA_KEY_PARAM *s_temp);
@@ -835,10 +847,8 @@ extern void _ma_store_pack_key(MARIA_KEYDEF *keyinfo, uchar *key_pos,
extern void _ma_store_bin_pack_key(MARIA_KEYDEF *keyinfo, uchar *key_pos,
MARIA_KEY_PARAM *s_temp);
-extern int _ma_ck_delete(MARIA_HA *info, uint keynr, uchar *key,
- uint key_length);
-extern int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length,
+extern int _ma_ck_delete(MARIA_HA *info, MARIA_KEY *key);
+extern int _ma_ck_real_delete(register MARIA_HA *info, MARIA_KEY *key,
my_off_t *root);
extern int _ma_readinfo(MARIA_HA *info, int lock_flag, int check_keybuffer);
extern int _ma_writeinfo(MARIA_HA *info, uint options);
@@ -849,54 +859,55 @@ extern my_bool _ma_set_uuid(MARIA_HA *info, my_bool reset_uuid);
extern my_bool _ma_check_if_zero(uchar *pos, size_t size);
extern int _ma_decrement_open_count(MARIA_HA *info);
extern int _ma_check_index(MARIA_HA *info, int inx);
-extern int _ma_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key,
- uint key_len, uint nextflag, my_off_t pos);
-extern int _ma_bin_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page, const uchar *key, uint key_len,
- uint comp_flag, uchar **ret_pos, uchar *buff,
+extern int _ma_search(MARIA_HA *info, MARIA_KEY *key, uint32 nextflag,
+ my_off_t pos);
+extern int _ma_bin_search( const MARIA_KEY *key, uchar *page,
+ uint32 comp_flag, uchar **ret_pos, uchar *buff,
my_bool *was_last_key);
-extern int _ma_seq_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page, const uchar *key, uint key_len,
+extern int _ma_seq_search(const MARIA_KEY *key, uchar *page,
uint comp_flag, uchar ** ret_pos, uchar *buff,
my_bool *was_last_key);
-extern int _ma_prefix_search(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page, const uchar *key, uint key_len,
- uint comp_flag, uchar ** ret_pos, uchar *buff,
+extern int _ma_prefix_search(const MARIA_KEY *key, uchar *page,
+ uint32 comp_flag, uchar ** ret_pos, uchar *buff,
my_bool *was_last_key);
extern my_off_t _ma_kpos(uint nod_flag, const uchar *after_key);
extern void _ma_kpointer(MARIA_HA *info, uchar *buff, my_off_t pos);
-extern MARIA_RECORD_POS _ma_dpos(MARIA_HA *info, uint nod_flag,
- const uchar *after_key);
-extern MARIA_RECORD_POS _ma_rec_pos(MARIA_HA *info, uchar *ptr);
-extern void _ma_dpointer(MARIA_HA *info, uchar *buff, MARIA_RECORD_POS pos);
-extern uint _ma_get_static_key(MARIA_KEYDEF *keyinfo, uint nod_flag,
- uchar **page, uchar *key);
-extern uint _ma_get_pack_key(MARIA_KEYDEF *keyinfo, uint nod_flag,
- uchar **page, uchar *key);
-extern uint _ma_get_binary_pack_key(MARIA_KEYDEF *keyinfo, uint nod_flag,
- uchar ** page_pos, uchar *key);
-extern uchar *_ma_get_last_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *keypos, uchar *lastkey,
- uchar *endpos, uint *return_key_length);
-extern uchar *_ma_get_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *page, uchar *key, uchar *keypos,
- uint *return_key_length);
+MARIA_RECORD_POS _ma_row_pos_from_key(const MARIA_KEY *key);
+TrID _ma_trid_from_key(const MARIA_KEY *key);
+extern MARIA_RECORD_POS _ma_rec_pos(MARIA_SHARE *share, uchar *ptr);
+extern void _ma_dpointer(MARIA_SHARE *share, uchar *buff,
+ MARIA_RECORD_POS pos);
+extern uint _ma_get_static_key(MARIA_KEY *key, uint page_flag, uint nod_flag,
+ uchar **page);
+extern uchar *_ma_skip_static_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar *page);
+extern uint _ma_get_pack_key(MARIA_KEY *key, uint page_flag, uint nod_flag,
+ uchar **page);
+extern uchar *_ma_skip_pack_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar *page);
+extern uint _ma_get_binary_pack_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar **page_pos);
+uchar *_ma_skip_binary_pack_key(MARIA_KEY *key, uint page_flag,
+ uint nod_flag, uchar *page);
+extern uchar *_ma_get_last_key(MARIA_KEY *key, uchar *keypos, uchar *endpos);
+extern uchar *_ma_get_key(MARIA_KEY *key, uchar *page, uchar *keypos);
extern uint _ma_keylength(MARIA_KEYDEF *keyinfo, const uchar *key);
-extern uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, register const uchar *key,
+extern uint _ma_keylength_part(MARIA_KEYDEF *keyinfo, const uchar *key,
HA_KEYSEG *end);
-extern uchar *_ma_move_key(MARIA_KEYDEF *keyinfo, uchar *to, const uchar *from);
-extern int _ma_search_next(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
- uchar *key, uint key_length, uint nextflag,
- my_off_t pos);
+extern uchar *_qq_move_key(MARIA_KEYDEF *keyinfo, uchar *to,
+ const uchar *from);
+
+extern int _ma_search_next(MARIA_HA *info, MARIA_KEY *key,
+ uint32 nextflag, my_off_t pos);
extern int _ma_search_first(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t pos);
extern int _ma_search_last(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
my_off_t pos);
-extern my_off_t _ma_static_keypos_to_recpos(MARIA_HA *info, my_off_t pos);
-extern my_off_t _ma_static_recpos_to_keypos(MARIA_HA *info, my_off_t pos);
-extern my_off_t _ma_transparent_recpos(MARIA_HA *info, my_off_t pos);
-extern my_off_t _ma_transaction_keypos_to_recpos(MARIA_HA *info, my_off_t pos);
-extern my_off_t _ma_transaction_recpos_to_keypos(MARIA_HA *info, my_off_t pos);
+extern my_off_t _ma_static_keypos_to_recpos(MARIA_SHARE *share, my_off_t pos);
+extern my_off_t _ma_static_recpos_to_keypos(MARIA_SHARE *share, my_off_t pos);
+extern my_off_t _ma_transparent_recpos(MARIA_SHARE *share, my_off_t pos);
+extern my_off_t _ma_transaction_keypos_to_recpos(MARIA_SHARE *, my_off_t pos);
+extern my_off_t _ma_transaction_recpos_to_keypos(MARIA_SHARE *, my_off_t pos);
extern uchar *_ma_fetch_keypage(MARIA_HA *info,
const MARIA_KEYDEF *keyinfo,
@@ -910,11 +921,24 @@ extern int _ma_write_keypage(MARIA_HA *info,
extern int _ma_dispose(MARIA_HA *info, my_off_t pos, my_bool page_not_read);
extern my_off_t _ma_new(register MARIA_HA *info, int level,
MARIA_PINNED_PAGE **page_link);
-extern uint _ma_make_key(MARIA_HA *info, uint keynr, uchar *key,
- const uchar *record, MARIA_RECORD_POS filepos);
-extern uint _ma_pack_key(MARIA_HA *info, uint keynr, uchar *key,
- const uchar *old, key_part_map keypart_map,
- HA_KEYSEG ** last_used_keyseg);
+extern my_bool _ma_compact_keypage(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
+ my_off_t page_pos, uchar *page,
+ TrID min_read_from);
+extern uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid);
+extern ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from);
+#define transid_packed_length(data) \
+ ((data)[0] < MIN_TRANSID_PACK_PREFIX ? 1 : \
+ (uint) (257 - (uchar) (data)[0]))
+#define key_has_transid(key) (*(key) & 1)
+
+extern MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr,
+ uchar *key, const uchar *record,
+ MARIA_RECORD_POS filepos, ulonglong trid);
+extern MARIA_KEY *_ma_pack_key(MARIA_HA *info, MARIA_KEY *int_key,
+ uint keynr, uchar *key,
+ const uchar *old, key_part_map keypart_map,
+ HA_KEYSEG ** last_used_keyseg);
+extern void _ma_copy_key(MARIA_KEY *to, const MARIA_KEY *from);
extern int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS);
extern my_bool _ma_read_cache(IO_CACHE *info, uchar *buff,
MARIA_RECORD_POS pos, size_t length,
@@ -931,8 +955,9 @@ extern int _ma_write_part_record(MARIA_HA *info, my_off_t filepos,
ulong length, my_off_t next_filepos,
uchar ** record, ulong *reclength,
int *flag);
-extern void _ma_print_key(FILE *stream, HA_KEYSEG *keyseg,
- const uchar *key, uint length);
+extern void _ma_print_key(FILE *stream, MARIA_KEY *key);
+extern void _ma_print_keydata(FILE *stream, HA_KEYSEG *keyseg,
+ const uchar *key, uint length);
extern my_bool _ma_once_init_pack_row(MARIA_SHARE *share, File dfile);
extern my_bool _ma_once_end_pack_row(MARIA_SHARE *share);
extern int _ma_read_pack_record(MARIA_HA *info, uchar *buf,
@@ -1103,11 +1128,11 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
int _ma_sync_table_files(const MARIA_HA *info);
int _ma_initialize_data_file(MARIA_SHARE *share, File dfile);
int _ma_update_state_lsns(MARIA_SHARE *share,
- LSN lsn, my_bool do_sync, my_bool
- update_create_rename_lsn);
-int _ma_update_state_lsns_sub(MARIA_SHARE *share,
- LSN lsn, my_bool do_sync, my_bool
- update_create_rename_lsn);
+ LSN lsn, TrID create_trid, my_bool do_sync,
+ my_bool update_create_rename_lsn);
+int _ma_update_state_lsns_sub(MARIA_SHARE *share, LSN lsn,
+ TrID create_trid, my_bool do_sync,
+ my_bool update_create_rename_lsn);
void _ma_set_data_pagecache_callbacks(PAGECACHE_FILE *file,
MARIA_SHARE *share);
void _ma_set_index_pagecache_callbacks(PAGECACHE_FILE *file,
diff --git a/storage/maria/maria_ftdump.c b/storage/maria/maria_ftdump.c
index d691cbe0c3b..978082adb78 100644
--- a/storage/maria/maria_ftdump.c
+++ b/storage/maria/maria_ftdump.c
@@ -111,16 +111,16 @@ int main(int argc,char *argv[])
while (!(error=maria_rnext(info,NULL,inx)))
{
- keylen=*(info->lastkey);
+ keylen=*(info->lastkey_buff);
- subkeys=ft_sintXkorr(info->lastkey+keylen+1);
+ subkeys=ft_sintXkorr(info->lastkey_buff + keylen + 1);
if (subkeys >= 0)
weight=*(float*)&subkeys;
#ifdef HAVE_SNPRINTF
- snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey+1);
+ snprintf(buf,MAX_LEN,"%.*s",(int) keylen,info->lastkey_buff+1);
#else
- sprintf(buf,"%.*s",(int) keylen,info->lastkey+1);
+ sprintf(buf,"%.*s",(int) keylen,info->lastkey_buff+1);
#endif
my_casedn_str(default_charset_info,buf);
total++;
diff --git a/storage/maria/trnman.c b/storage/maria/trnman.c
index 1c2385e9476..b24203f4535 100644
--- a/storage/maria/trnman.c
+++ b/storage/maria/trnman.c
@@ -149,12 +149,12 @@ int trnman_init(TrID initial_trid)
*/
active_list_max.trid= active_list_min.trid= 0;
- active_list_max.min_read_from= ~(ulong) 0;
+ active_list_max.min_read_from= ~(TrID) 0;
active_list_max.next= active_list_min.prev= 0;
active_list_max.prev= &active_list_min;
active_list_min.next= &active_list_max;
- committed_list_max.commit_trid= ~(ulong) 0;
+ committed_list_max.commit_trid= ~(TrID) 0;
committed_list_max.next= committed_list_min.prev= 0;
committed_list_max.prev= &committed_list_min;
committed_list_min.next= &committed_list_max;
@@ -783,7 +783,10 @@ TRN *trnman_get_any_trn()
/**
- Returns the minimum existing transaction id.
+ Returns the minimum existing transaction id
+
+ @notes
+ This can only be called when we have at least one running transaction.
*/
TrID trnman_get_min_trid()
@@ -803,6 +806,29 @@ TrID trnman_get_min_trid()
/**
+ Returns the minimum possible transaction id
+
+ @notes
+ If there is no transactions running, returns number for next running
+ transaction.
+ If one has an active transaction, the returned number will be less or
+ equal to this. If one is not running in a transaction one will ge the
+ number for the next started transaction. This is used in create table
+ to get a safe minimum trid to use.
+*/
+
+TrID trnman_get_min_safe_trid()
+{
+ TrID trid;
+ pthread_mutex_lock(&LOCK_trn_list);
+ trid= min(active_list_min.next->min_read_from,
+ global_trid_generator);
+ pthread_mutex_unlock(&LOCK_trn_list);
+ return trid;
+}
+
+
+/**
Returns maximum transaction id given to a transaction so far.
*/
diff --git a/storage/maria/trnman_public.h b/storage/maria/trnman_public.h
index 0005e556eb1..ee69895ea4f 100644
--- a/storage/maria/trnman_public.h
+++ b/storage/maria/trnman_public.h
@@ -59,6 +59,7 @@ TRN *trnman_recreate_trn_from_recovery(uint16 shortid, TrID longid);
TRN *trnman_get_any_trn(void);
TrID trnman_get_min_trid(void);
TrID trnman_get_max_trid(void);
+TrID trnman_get_min_safe_trid();
my_bool trnman_exists_active_transactions(TrID min_id, TrID max_id,
my_bool trnman_is_locked);
#define TRANSID_SIZE 6
diff --git a/storage/maria/unittest/ma_test_all-t b/storage/maria/unittest/ma_test_all-t
index d64662cb9ac..7b3bcd9ff8a 100755
--- a/storage/maria/unittest/ma_test_all-t
+++ b/storage/maria/unittest/ma_test_all-t
@@ -8,7 +8,7 @@ use File::Basename;
$|= 1;
$^W = 1; # warnings, because env cannot parse 'perl -w'
-$VER= "1.3";
+$VER= "1.4";
$opt_version= 0;
$opt_help= 0;
@@ -40,9 +40,15 @@ sub run_tests
my $nr_tests= 0;
my $flag_exit= 0;
- if (!GetOptions("help", "version", "verbose", "abort-on-error",
- "valgrind=s", "silent=s", "number-of-tests",
- "run-tests=s"))
+ if (!GetOptions("help" => \$opt_help,
+ "version" => \$opt_version,
+ "verbose" => \$opt_verbose,
+ "abort-on-error" => \$opt_abort_on_error,
+ "valgrind=s" => \$opt_valgrind,
+ "silent=s" => \$opt_silent,
+ "number-of-tests" => \$opt_number_of_tests,
+ "run-tests=s" => \$opt_run_tests,
+ "start-from=s" => \$opt_run_tests))
{
$flag_exit= 1;
}
@@ -103,7 +109,8 @@ sub run_tests
if (defined($opt_run_tests))
{
- if ($opt_run_tests =~ m/^(\d+)$/)
+ if ($opt_run_tests =~ m/^(\d+)$/ ||
+ $opt_run_tests =~ m/^(\d+)\.+$/)
{
$test_begin= $1;
}
@@ -389,8 +396,8 @@ sub run_pack_tests()
"$maria_exe_path/maria_chk$suffix -se test2",
$NEW_TEST,
"$maria_exe_path/ma_test1$suffix $silent -c $row_type",
- "cp test1.MAD test2.MAD",
- "cp test1.MAI test2.MAI",
+ "cp test1.MAD test2.MAD",
+ "cp test1.MAI test2.MAI",
"$maria_exe_path/maria_pack$suffix --force -s --join=test3 test1 test2",
"$maria_exe_path/maria_chk -s test3",
"$maria_exe_path/maria_chk -s --safe-recover test3",
@@ -673,9 +680,11 @@ Options
--abort-on-error Abort at once in case of error.
--number-of-tests Print the total number of tests and exit.
--run-tests=... Test number(s) that should be run. You can give just
- one number or a range. For example 45..89
- Use this with caution, because some of the tests
+ one number or a range. For example 45..89. To run a specific
+ test alone, for example test 215, use --run-tests=215..215
+ Use this option with caution, because some of the tests
might depend on previous ones.
+--start-from=... Alias for --run-tests
--silent=... Silent option passed to ma_test* tests ('$opt_silent')
--valgrind=... Options for valgrind.
('$opt_valgrind')
diff --git a/storage/myisam/mi_check.c b/storage/myisam/mi_check.c
index 7ee1b4702ad..d05d30543ed 100644
--- a/storage/myisam/mi_check.c
+++ b/storage/myisam/mi_check.c
@@ -755,7 +755,10 @@ static int chk_index(HA_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
}
if (keyinfo->flag & HA_NOSAME)
- comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* Not real duplicates */
+ {
+ /* Not real duplicates */
+ comp_flag= SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT;
+ }
else
comp_flag=SEARCH_SAME; /* Keys in positionorder */
nod_flag=mi_test_if_nod(buff);
@@ -3795,7 +3798,8 @@ static int sort_key_write(MI_SORT_PARAM *sort_param, const void *a)
if (sort_info->key_block->inited)
{
cmp=ha_key_cmp(sort_param->seg, (uchar*) sort_info->key_block->lastkey,
- (uchar*) a, USE_WHOLE_KEY,SEARCH_FIND | SEARCH_UPDATE,
+ (uchar*) a, USE_WHOLE_KEY,
+ SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT,
diff_pos);
if (param->stats_method == MI_STATS_METHOD_NULLS_NOT_EQUAL)
ha_key_cmp(sort_param->seg, (uchar*) sort_info->key_block->lastkey,
diff --git a/storage/myisam/mi_delete.c b/storage/myisam/mi_delete.c
index 88b31d616de..8ebdb477183 100644
--- a/storage/myisam/mi_delete.c
+++ b/storage/myisam/mi_delete.c
@@ -171,8 +171,9 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
goto err;
}
if ((error=d_search(info,keyinfo,
- (keyinfo->flag & HA_FULLTEXT ? SEARCH_FIND | SEARCH_UPDATE
- : SEARCH_SAME),
+ (keyinfo->flag & HA_FULLTEXT ?
+ SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT :
+ SEARCH_SAME),
key,key_length,old_root,root_buff)) >0)
{
if (error == 2)
diff --git a/storage/myisam/mi_range.c b/storage/myisam/mi_range.c
index 0efccae9972..aabbe1277c4 100644
--- a/storage/myisam/mi_range.c
+++ b/storage/myisam/mi_range.c
@@ -152,7 +152,7 @@ static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key,
operations with a comment like "Not real duplicates", whatever this
means. From the condition above we can see that 'skip_end_space' is
always false for these operations. The result is that trailing space
- counts in key comparison and hence, emtpy strings ('', string length
+ counts in key comparison and hence, empty strings ('', string length
zero, but not NULL) compare less that strings starting with control
characters and these in turn compare less than strings starting with
blanks.
@@ -166,7 +166,7 @@ static ha_rows _mi_record_pos(MI_INFO *info, const uchar *key,
This is the reason that we add the SEARCH_UPDATE flag here. It makes
the key estimation compare in the same way like key write operations
- do. Olny so we will find the keys where they have been inserted.
+ do. Only so we will find the keys where they have been inserted.
Adding the flag unconditionally does not hurt as it is used in the
above mentioned condition only. So it can safely be used together
diff --git a/storage/myisam/mi_write.c b/storage/myisam/mi_write.c
index 0f2350ded12..6d9dea51177 100644
--- a/storage/myisam/mi_write.c
+++ b/storage/myisam/mi_write.c
@@ -272,7 +272,7 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
comp_flag=SEARCH_BIGGER; /* Put after same key */
else if (keyinfo->flag & (HA_NOSAME|HA_FULLTEXT))
{
- comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No duplicates */
+ comp_flag=SEARCH_FIND | SEARCH_UPDATE | SEARCH_INSERT; /* No duplicates */
if (keyinfo->flag & HA_NULL_ARE_EQUAL)
comp_flag|= SEARCH_NULL_ARE_EQUAL;
}
diff --git a/storage/myisam/rt_index.c b/storage/myisam/rt_index.c
index 9db7fe88030..86d556c879a 100644
--- a/storage/myisam/rt_index.c
+++ b/storage/myisam/rt_index.c
@@ -378,7 +378,6 @@ err1:
int rtree_get_first(MI_INFO *info, uint keynr, uint key_length)
{
my_off_t root;
- MI_KEYDEF *keyinfo = info->s->keyinfo + keynr;
if ((root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
{
@@ -389,7 +388,7 @@ int rtree_get_first(MI_INFO *info, uint keynr, uint key_length)
info->rtree_recursion_depth = -1;
info->buff_used = 1;
- return rtree_get_req(info, &keyinfo[keynr], key_length, root, 0);
+ return rtree_get_req(info, info->s->keyinfo + keynr, key_length, root, 0);
}
@@ -436,7 +435,7 @@ int rtree_get_next(MI_INFO *info, uint keynr, uint key_length)
return -1;
}
- return rtree_get_req(info, &keyinfo[keynr], key_length, root, 0);
+ return rtree_get_req(info, keyinfo, key_length, root, 0);
}
}