Commit 38d024b5 authored by unknown's avatar unknown

merge

parents 7b8d4af1 f0c53638
......@@ -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
......
......@@ -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
......
......@@ -134,6 +134,12 @@ extern size_t my_bcmp(const uchar *s1,const uchar *s2,size_t len);
#define bzero_if_purify(A,B)
#endif /* HAVE_purify */
#if defined(_lint) || defined(FORCE_INIT_OF_VARS)
#define LINT_INIT_STRUCT(var) bzero(&var, sizeof(var)) /* No uninitialize-warning */
#else
#define LINT_INIT_STRUCT(var)
#endif
#ifndef bmove512
extern void bmove512(uchar *dst,const uchar *src,size_t len);
#endif
......
......@@ -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;
......
......@@ -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
......
......@@ -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);
......
......@@ -8,7 +8,6 @@ connection default;
let $default_db=`select database()`;
connection admin;
-- echo * shut down mysqld, removed logs, restarted it
append_file $MYSQLTEST_VARDIR/tmp/master0.expect;
wait-maria_empty_logs.inc
......@@ -72,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".
# Restore current database as the effect of "use" was lost after restart
--disable_query_log
eval use $default_db;
--enable_query_log
......@@ -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;
......
......@@ -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;
......@@ -12,7 +12,6 @@ insert into t2 select * from t2;
insert into t2 select * from t2;
insert into t2 select * from t2;
* shut down mysqld, removed logs, restarted it
use mysqltest;
create table t1 (a varchar(100)) engine=maria transactional=1;
show create table t1;
Table Create Table
......@@ -28,7 +27,6 @@ show engine maria logs;
Type Name Status
MARIA Size 24576 maria_log.00000001 unknown
* shut down mysqld, removed logs, restarted it
use mysqltest;
truncate table t1;
insert into t1 select * from t2;
show engine maria logs;
......@@ -36,7 +34,6 @@ Type Name Status
MARIA Size 16384 maria_log.00000001 unknown
drop table t1;
* shut down mysqld, removed logs, restarted it
use mysqltest;
create table t1 (a varchar(100)) engine=maria transactional=1;
insert into t1 values('a');
create table if not exists t1 select * from t2;
......@@ -46,7 +43,6 @@ show engine maria logs;
Type Name Status
MARIA Size 24576 maria_log.00000001 unknown
* shut down mysqld, removed logs, restarted it
use mysqltest;
drop table t1;
create table t1 engine=maria transactional=1 select * from t2;
show engine maria logs;
......
* shut down mysqld, removed logs, restarted it
use test;
set global storage_engine=maria;
set session storage_engine=maria;
set global maria_log_file_size=4294967295;
......
......@@ -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
......
......@@ -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");
......
......@@ -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',
......
......@@ -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);
......
......@@ -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
......
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
......@@ -32,13 +32,13 @@ 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 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);
......@@ -68,24 +68,24 @@ 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
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
......@@ -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
......@@ -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;
......
......@@ -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;
......@@ -3,6 +3,7 @@
# pre-requisites for maria_empty_logs
connect (admin, 127.0.0.1, root,,test,,);
#
--enable_reconnect
connection default;
--enable_reconnect
......@@ -68,8 +69,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;
......
......@@ -1518,6 +1518,30 @@ alter table t1 engine=maria;
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"
......
......@@ -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;
......@@ -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)
......
......@@ -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;
......
......@@ -90,7 +90,8 @@ CLEANFILES = @server_scripts@ \
mysql_find_rows \
mysqlhotcopy \
mysqldumpslow \
mysqld_multi
mysqld_multi \
$(EXTRA_PROGRAMS)
pkgplugindir = $(pkglibdir)/plugin
......
......@@ -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),
......
......@@ -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
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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)
......
This diff is collapsed.
......@@ -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
......
......@@ -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*/
......@@ -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;
......
This diff is collapsed.
......@@ -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;
}
......@@ -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);
......
......@@ -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))
......
......@@ -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;
......
......@@ -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));
}
......@@ -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;
......
......@@ -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 *);
......@@ -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;
......
......@@ -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)
......
This diff is collapsed.
......@@ -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,
......
......@@ -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;
......
......@@ -1675,7 +1675,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),
......@@ -3209,8 +3209,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);
......@@ -5007,7 +5007,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);
......@@ -5092,7 +5092,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 */
......@@ -6366,7 +6366,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);
......@@ -6381,8 +6381,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);
......@@ -6852,7 +6851,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);
......@@ -7290,7 +7289,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
......
......@@ -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 */
......
This diff is collapsed.
......@@ -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);
}
......@@ -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 @@ static double _ma_search_pos(register MARIA_HA *info,
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);
......
......@@ -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;
......
......@@ -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);
......
......@@ -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 */
......
......@@ -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;
......
......@@ -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;
......
......@@ -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)
......
......@@ -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))
......
......@@ -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);
......
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
......@@ -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 */
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment