mirror of
https://github.com/MariaDB/server.git
synced 2026-05-08 08:04:29 +02:00
Merge of changes in MyISAM since December 16 -> April 1
Fixes bugs: Bug#28837 MyISAM storage engine error (134) doing delete with self-join Bug#31277 myisamchk --unpack corrupts table Bug#4692 DISABLE/ENABLE KEYS waste a space Bug#31305 myisam tables crash when they are near capacity BitKeeper/etc/ignore: added unittest/tmp/* mysql-test/r/maria.result: Moved missing tests from myisam.test to maria.test mysql-test/t/maria.test: Moved missing tests from myisam.test to maria.test storage/maria/ha_maria.cc: Merge of changes in MyISAM since December 16 -> April 1 Fixes bug in self join (Bug#28837: MyISAM storage engine error (134) doing delete with self-join) storage/maria/ha_maria.h: Merge of changes in MyISAM since December 16 -> April 1 storage/maria/ma_blockrec.c: Merge of changes in MyISAM since December 16 -> April 1 Fixes bug in self join (Bug#28837: MyISAM storage engine error (134) doing delete with self-join) The problem is that we may be using a cached key page with old information. Versioning will fix this storage/maria/ma_check.c: Merge of changes in MyISAM since December 16 -> April 1 This fixes a problem with pack_reclength not beeing big enough (Bug #31277 myisamchk --unpack corrupts table) BUG#4692 - DISABLE/ENABLE KEYS waste a space storage/maria/ma_delete.c: Indentation fixes storage/maria/ma_dynrec.c: Merge of changes in MyISAM since December 16 -> April 1 Fixes Bug#31305 myisam tables crash when they are near capacity. (This uses a simpler fix than in MyISAM by remembering the length of the current row) storage/maria/ma_ft_boolean_search.c: Merge of all changes from myisam/ft_boolean_search.c (This file had not been kept up to date) storage/maria/ma_open.c: Merge of changes in MyISAM since December 16 -> April 1 Calculate default_rec_buff_size more exact to be sure it's always big enough storage/maria/ma_packrec.c: Merge of changes in MyISAM since December 16 -> April 1 Update default_rec_buff_size to be big enough to hold one packed row Related to Bug#31277 myisamchk --unpack corrupts table storage/maria/ma_rnext_same.c: Indentation fixes storage/maria/ma_rt_index.c: Merge of changes in MyISAM since December 16 -> April 1 storage/maria/ma_rt_mbr.c: Merge of changes in MyISAM since December 16 -> April 1 (Added comment) storage/maria/ma_search.c: Merge of changes in MyISAM since December 16 -> April 1 (Added comment) storage/maria/ma_sort.c: Merge of changes in MyISAM since December 16 -> April 1 storage/maria/ma_statrec.c: Indentation fixes storage/maria/ma_test2.c: Indentation fixes storage/maria/maria_chk.c: Indentation fixes storage/maria/maria_pack.c: Merge of changes in MyISAM since December 16 -> April 1
This commit is contained in:
parent
c63e18f43c
commit
3651e3285d
21 changed files with 499 additions and 124 deletions
|
|
@ -3078,3 +3078,4 @@ ma_test_recovery.output
|
||||||
test?.MA?
|
test?.MA?
|
||||||
dbug/tests
|
dbug/tests
|
||||||
storage/maria/unittest/tmp/*
|
storage/maria/unittest/tmp/*
|
||||||
|
unittest/tmp/*
|
||||||
|
|
|
||||||
|
|
@ -1663,6 +1663,88 @@ create table t3 (c1 int) pack_keys=default;
|
||||||
create table t4 (c1 int) pack_keys=2;
|
create table t4 (c1 int) pack_keys=2;
|
||||||
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2' at line 1
|
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '2' at line 1
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
CREATE TABLE t1(a INT, b INT, KEY inx (a), UNIQUE KEY uinx (b));
|
||||||
|
INSERT INTO t1(a,b) VALUES (1,1),(2,2),(3,3),(4,4),(5,5);
|
||||||
|
SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
ALTER TABLE t1 DISABLE KEYS;
|
||||||
|
SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
SELECT a FROM t1 USE INDEX (inx) WHERE a=1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
SELECT b FROM t1 FORCE INDEX (uinx) WHERE b=1;
|
||||||
|
b
|
||||||
|
1
|
||||||
|
SELECT b FROM t1 USE INDEX (uinx) WHERE b=1;
|
||||||
|
b
|
||||||
|
1
|
||||||
|
SELECT a FROM t1 FORCE INDEX (inx,uinx) WHERE a=1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
ALTER TABLE t1 ENABLE KEYS;
|
||||||
|
SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
|
||||||
|
a
|
||||||
|
1
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2));
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
|
||||||
|
t1 MARIA 10 Page 0 # # # 8192 # # # # # # #
|
||||||
|
INSERT INTO t1 VALUES (1,1);
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
|
||||||
|
t1 MARIA 10 Page 1 # # # 24576 # # # # # # #
|
||||||
|
ALTER TABLE t1 DISABLE KEYS;
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
|
||||||
|
t1 MARIA 10 Page 1 # # # 24576 # # # # # # #
|
||||||
|
ALTER TABLE t1 ENABLE KEYS;
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
|
||||||
|
t1 MARIA 10 Page 1 # # # 24576 # # # # # # #
|
||||||
|
ALTER TABLE t1 DISABLE KEYS;
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
|
||||||
|
t1 MARIA 10 Page 1 # # # 24576 # # # # # # #
|
||||||
|
ALTER TABLE t1 ENABLE KEYS;
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
|
||||||
|
t1 MARIA 10 Page 1 # # # 24576 # # # # # # #
|
||||||
|
# Enable keys with parallel repair
|
||||||
|
SET @@maria_repair_threads=2;
|
||||||
|
ALTER TABLE t1 DISABLE KEYS;
|
||||||
|
ALTER TABLE t1 ENABLE KEYS;
|
||||||
|
SET @@maria_repair_threads=1;
|
||||||
|
CHECK TABLE t1 EXTENDED;
|
||||||
|
Table Op Msg_type Msg_text
|
||||||
|
test.t1 check status OK
|
||||||
|
DROP TABLE t1;
|
||||||
|
CREATE TABLE t1 (id int NOT NULL, ref int NOT NULL, INDEX (id));
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
INSERT INTO t2 (id, ref) VALUES (1,3), (2,1), (3,2), (4,5), (4,4);
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
SELECT * FROM t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
id ref ref
|
||||||
|
4 4 5
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id ref
|
||||||
|
1 3
|
||||||
|
2 1
|
||||||
|
3 2
|
||||||
|
4 5
|
||||||
|
4 4
|
||||||
|
DELETE FROM a USING t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
id ref
|
||||||
|
1 3
|
||||||
|
2 1
|
||||||
|
3 2
|
||||||
|
4 5
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
End of 5.0 tests
|
||||||
create table t1 (a int not null, key `a` (a) key_block_size=1024);
|
create table t1 (a int not null, key `a` (a) key_block_size=1024);
|
||||||
show create table t1;
|
show create table t1;
|
||||||
Table Create Table
|
Table Create Table
|
||||||
|
|
@ -2272,3 +2354,12 @@ check table t1 extended;
|
||||||
Table Op Msg_type Msg_text
|
Table Op Msg_type Msg_text
|
||||||
test.t1 check status OK
|
test.t1 check status OK
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
CREATE TABLE t1(a VARCHAR(20), FULLTEXT(a)) transactional=0;
|
||||||
|
INSERT INTO t1 VALUES('Offside'),('City Of God');
|
||||||
|
SELECT a FROM t1 WHERE MATCH a AGAINST ('+city of*' IN BOOLEAN MODE);
|
||||||
|
a
|
||||||
|
City Of God
|
||||||
|
SELECT a FROM t1 WHERE MATCH a AGAINST ('+city (of)*' IN BOOLEAN MODE);
|
||||||
|
a
|
||||||
|
City Of God
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
|
||||||
|
|
@ -1035,6 +1035,75 @@ create table t3 (c1 int) pack_keys=default;
|
||||||
create table t4 (c1 int) pack_keys=2;
|
create table t4 (c1 int) pack_keys=2;
|
||||||
drop table t1, t2, t3;
|
drop table t1, t2, t3;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#28476: force index on a disabled maria index gives error 124
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1(a INT, b INT, KEY inx (a), UNIQUE KEY uinx (b));
|
||||||
|
INSERT INTO t1(a,b) VALUES (1,1),(2,2),(3,3),(4,4),(5,5);
|
||||||
|
SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
|
||||||
|
ALTER TABLE t1 DISABLE KEYS;
|
||||||
|
SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
|
||||||
|
SELECT a FROM t1 USE INDEX (inx) WHERE a=1;
|
||||||
|
SELECT b FROM t1 FORCE INDEX (uinx) WHERE b=1;
|
||||||
|
SELECT b FROM t1 USE INDEX (uinx) WHERE b=1;
|
||||||
|
SELECT a FROM t1 FORCE INDEX (inx,uinx) WHERE a=1;
|
||||||
|
ALTER TABLE t1 ENABLE KEYS;
|
||||||
|
SELECT a FROM t1 FORCE INDEX (inx) WHERE a=1;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#4692 - DISABLE/ENABLE KEYS waste a space
|
||||||
|
#
|
||||||
|
CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2));
|
||||||
|
--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
INSERT INTO t1 VALUES (1,1);
|
||||||
|
--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
ALTER TABLE t1 DISABLE KEYS;
|
||||||
|
--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
ALTER TABLE t1 ENABLE KEYS;
|
||||||
|
--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
ALTER TABLE t1 DISABLE KEYS;
|
||||||
|
--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
ALTER TABLE t1 ENABLE KEYS;
|
||||||
|
--replace_column 6 # 7 # 8 # 10 # 11 # 12 # 13 # 14 # 15 # 16 #
|
||||||
|
SHOW TABLE STATUS LIKE 't1';
|
||||||
|
#--exec ls -log var/master-data/test/t1
|
||||||
|
#--exec maria_chk -dvv var/master-data/test/t1
|
||||||
|
#--exec maria_chk -iev var/master-data/test/t1
|
||||||
|
--echo # Enable keys with parallel repair
|
||||||
|
SET @@maria_repair_threads=2;
|
||||||
|
ALTER TABLE t1 DISABLE KEYS;
|
||||||
|
ALTER TABLE t1 ENABLE KEYS;
|
||||||
|
SET @@maria_repair_threads=1;
|
||||||
|
CHECK TABLE t1 EXTENDED;
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# Bug#28837: Maria storage engine error (134) doing delete with self-join
|
||||||
|
#
|
||||||
|
|
||||||
|
CREATE TABLE t1 (id int NOT NULL, ref int NOT NULL, INDEX (id));
|
||||||
|
CREATE TABLE t2 LIKE t1;
|
||||||
|
|
||||||
|
INSERT INTO t2 (id, ref) VALUES (1,3), (2,1), (3,2), (4,5), (4,4);
|
||||||
|
INSERT INTO t1 SELECT * FROM t2;
|
||||||
|
|
||||||
|
SELECT * FROM t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
DELETE FROM a USING t1 AS a INNER JOIN t1 AS b USING (id) WHERE a.ref < b.ref;
|
||||||
|
SELECT * FROM t1;
|
||||||
|
|
||||||
|
DROP TABLE t1, t2;
|
||||||
|
|
||||||
|
--echo End of 5.0 tests
|
||||||
|
|
||||||
|
|
||||||
#
|
#
|
||||||
# Test of key_block_size
|
# Test of key_block_size
|
||||||
#
|
#
|
||||||
|
|
@ -1490,6 +1559,15 @@ delete from t1 where i = 10;
|
||||||
check table t1 extended;
|
check table t1 extended;
|
||||||
drop table t1;
|
drop table t1;
|
||||||
|
|
||||||
|
#
|
||||||
|
# BUG#29445 - match ... against () never returns
|
||||||
|
#
|
||||||
|
CREATE TABLE t1(a VARCHAR(20), FULLTEXT(a)) transactional=0;
|
||||||
|
INSERT INTO t1 VALUES('Offside'),('City Of God');
|
||||||
|
SELECT a FROM t1 WHERE MATCH a AGAINST ('+city of*' IN BOOLEAN MODE);
|
||||||
|
SELECT a FROM t1 WHERE MATCH a AGAINST ('+city (of)*' IN BOOLEAN MODE);
|
||||||
|
DROP TABLE t1;
|
||||||
|
|
||||||
# End of 5.1 tests
|
# End of 5.1 tests
|
||||||
|
|
||||||
--disable_result_log
|
--disable_result_log
|
||||||
|
|
|
||||||
|
|
@ -273,6 +273,10 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
|
||||||
definition for further use in ma_create or for a check for underlying
|
definition for further use in ma_create or for a check for underlying
|
||||||
table conformance in merge engine.
|
table conformance in merge engine.
|
||||||
|
|
||||||
|
The caller needs to free *recinfo_out after use. Since *recinfo_out
|
||||||
|
and *keydef_out are allocated with a my_multi_malloc, *keydef_out
|
||||||
|
is freed automatically when *recinfo_out is freed.
|
||||||
|
|
||||||
RETURN VALUE
|
RETURN VALUE
|
||||||
0 OK
|
0 OK
|
||||||
# error code
|
# error code
|
||||||
|
|
@ -1649,9 +1653,9 @@ int ha_maria::enable_indexes(uint mode)
|
||||||
param.testflag &= ~(T_REP_BY_SORT | T_QUICK);
|
param.testflag &= ~(T_REP_BY_SORT | T_QUICK);
|
||||||
error= (repair(thd, param, 0) != HA_ADMIN_OK);
|
error= (repair(thd, param, 0) != HA_ADMIN_OK);
|
||||||
/*
|
/*
|
||||||
If the standard repair succeeded, clear all error messages which
|
If the standard repair succeeded, clear all error messages which
|
||||||
might have been set by the first repair. They can still be seen
|
might have been set by the first repair. They can still be seen
|
||||||
with SHOW WARNINGS then.
|
with SHOW WARNINGS then.
|
||||||
*/
|
*/
|
||||||
if (!error)
|
if (!error)
|
||||||
thd->clear_error();
|
thd->clear_error();
|
||||||
|
|
@ -1974,9 +1978,17 @@ int ha_maria::index_next_same(uchar * buf,
|
||||||
const uchar *key __attribute__ ((unused)),
|
const uchar *key __attribute__ ((unused)),
|
||||||
uint length __attribute__ ((unused)))
|
uint length __attribute__ ((unused)))
|
||||||
{
|
{
|
||||||
|
int error;
|
||||||
DBUG_ASSERT(inited == INDEX);
|
DBUG_ASSERT(inited == INDEX);
|
||||||
ha_statistic_increment(&SSV::ha_read_next_count);
|
ha_statistic_increment(&SSV::ha_read_next_count);
|
||||||
int error= maria_rnext_same(file, buf);
|
/*
|
||||||
|
TODO: Delete this loop in Maria 1.5 as versioning will ensure this never
|
||||||
|
happens
|
||||||
|
*/
|
||||||
|
do
|
||||||
|
{
|
||||||
|
error= maria_rnext_same(file,buf);
|
||||||
|
} while (error == HA_ERR_RECORD_DELETED);
|
||||||
table->status= error ? STATUS_NOT_FOUND : 0;
|
table->status= error ? STATUS_NOT_FOUND : 0;
|
||||||
return error;
|
return error;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -157,6 +157,9 @@ public:
|
||||||
*engine_callback,
|
*engine_callback,
|
||||||
ulonglong *engine_data);
|
ulonglong *engine_data);
|
||||||
#endif
|
#endif
|
||||||
|
MARIA_HA *file_ptr(void)
|
||||||
|
{
|
||||||
|
return file;
|
||||||
|
}
|
||||||
static int implicit_commit(THD *thd);
|
static int implicit_commit(THD *thd);
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -4770,8 +4770,8 @@ int _ma_read_block_record(MARIA_HA *info, uchar *record,
|
||||||
if (!(data= get_record_position(buff, block_size, offset, &end_of_data)))
|
if (!(data= get_record_position(buff, block_size, offset, &end_of_data)))
|
||||||
{
|
{
|
||||||
DBUG_PRINT("error", ("Wrong directory entry in data block"));
|
DBUG_PRINT("error", ("Wrong directory entry in data block"));
|
||||||
my_errno= HA_ERR_WRONG_IN_RECORD; /* File crashed */
|
my_errno= HA_ERR_RECORD_DELETED; /* File crashed */
|
||||||
DBUG_RETURN(HA_ERR_WRONG_IN_RECORD);
|
DBUG_RETURN(HA_ERR_RECORD_DELETED);
|
||||||
}
|
}
|
||||||
DBUG_RETURN(_ma_read_block_record2(info, record, data, end_of_data));
|
DBUG_RETURN(_ma_read_block_record2(info, record, data, end_of_data));
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -489,7 +489,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
|
||||||
|
|
||||||
if ((!(param->testflag & T_SILENT)))
|
if ((!(param->testflag & T_SILENT)))
|
||||||
printf ("- check data record references index: %d\n",key+1);
|
printf ("- check data record references index: %d\n",key+1);
|
||||||
if (keyinfo->flag & HA_FULLTEXT)
|
if (keyinfo->flag & (HA_FULLTEXT | HA_SPATIAL))
|
||||||
full_text_keys++;
|
full_text_keys++;
|
||||||
if (share->state.key_root[key] == HA_OFFSET_ERROR)
|
if (share->state.key_root[key] == HA_OFFSET_ERROR)
|
||||||
{
|
{
|
||||||
|
|
@ -1914,7 +1914,7 @@ int maria_chk_data_link(HA_CHECK *param, MARIA_HA *info, my_bool extend)
|
||||||
puts("- check record links");
|
puts("- check record links");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(record= (uchar*) my_malloc(share->base.pack_reclength,MYF(0))))
|
if (!(record= (uchar*) my_malloc(share->base.default_rec_buff_size, MYF(0))))
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,"Not enough memory for record");
|
_ma_check_print_error(param,"Not enough memory for record");
|
||||||
DBUG_RETURN(-1);
|
DBUG_RETURN(-1);
|
||||||
|
|
@ -2199,6 +2199,121 @@ static int initialize_variables_for_repair(HA_CHECK *param,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
@brief Drop all indexes
|
||||||
|
|
||||||
|
@param[in] param check parameters
|
||||||
|
@param[in] info MARIA_HA handle
|
||||||
|
@param[in] force if to force drop all indexes
|
||||||
|
|
||||||
|
@return status
|
||||||
|
@retval 0 OK
|
||||||
|
@retval != 0 Error
|
||||||
|
|
||||||
|
@note
|
||||||
|
Once allocated, index blocks remain part of the key file forever.
|
||||||
|
When indexes are disabled, no block is freed. When enabling indexes,
|
||||||
|
no block is freed either. The new indexes are create from new
|
||||||
|
blocks. (Bug #4692)
|
||||||
|
|
||||||
|
Before recreating formerly disabled indexes, the unused blocks
|
||||||
|
must be freed. There are two options to do this:
|
||||||
|
- Follow the tree of disabled indexes, add all blocks to the
|
||||||
|
deleted blocks chain. Would require a lot of random I/O.
|
||||||
|
- Drop all blocks by clearing all index root pointers and all
|
||||||
|
delete chain pointers and resetting key_file_length to the end
|
||||||
|
of the index file header. This requires to recreate all indexes,
|
||||||
|
even those that may still be intact.
|
||||||
|
The second method is probably faster in most cases.
|
||||||
|
|
||||||
|
When disabling indexes, MySQL disables either all indexes or all
|
||||||
|
non-unique indexes. When MySQL [re-]enables disabled indexes
|
||||||
|
(T_CREATE_MISSING_KEYS), then we either have "lost" blocks in the
|
||||||
|
index file, or there are no non-unique indexes. In the latter case,
|
||||||
|
maria_repair*() would not be called as there would be no disabled
|
||||||
|
indexes.
|
||||||
|
|
||||||
|
If there would be more unique indexes than disabled (non-unique)
|
||||||
|
indexes, we could do the first method. But this is not implemented
|
||||||
|
yet. By now we drop and recreate all indexes when repair is called.
|
||||||
|
|
||||||
|
However, there is an exception. Sometimes MySQL disables non-unique
|
||||||
|
indexes when the table is empty (e.g. when copying a table in
|
||||||
|
mysql_alter_table()). When enabling the non-unique indexes, they
|
||||||
|
are still empty. So there is no index block that can be lost. This
|
||||||
|
optimization is implemented in this function.
|
||||||
|
|
||||||
|
Note that in normal repair (T_CREATE_MISSING_KEYS not set) we
|
||||||
|
recreate all enabled indexes unconditonally. We do not change the
|
||||||
|
key_map. Otherwise we invert the key map temporarily (outside of
|
||||||
|
this function) and recreate the then "seemingly" enabled indexes.
|
||||||
|
When we cannot use the optimization, and drop all indexes, we
|
||||||
|
pretend that all indexes were disabled. By the inversion, we will
|
||||||
|
then recrate all indexes.
|
||||||
|
*/
|
||||||
|
|
||||||
|
static int maria_drop_all_indexes(HA_CHECK *param, MARIA_HA *info,
|
||||||
|
my_bool force)
|
||||||
|
{
|
||||||
|
MARIA_SHARE *share= info->s;
|
||||||
|
MARIA_STATE_INFO *state= &share->state;
|
||||||
|
uint i;
|
||||||
|
DBUG_ENTER("maria_drop_all_indexes");
|
||||||
|
|
||||||
|
/*
|
||||||
|
If any of the disabled indexes has a key block assigned, we must
|
||||||
|
drop and recreate all indexes to avoid losing index blocks.
|
||||||
|
|
||||||
|
If we want to recreate disabled indexes only _and_ all of these
|
||||||
|
indexes are empty, we don't need to recreate the existing indexes.
|
||||||
|
*/
|
||||||
|
if (!force && (param->testflag & T_CREATE_MISSING_KEYS))
|
||||||
|
{
|
||||||
|
DBUG_PRINT("repair", ("creating missing indexes"));
|
||||||
|
for (i= 0; i < share->base.keys; i++)
|
||||||
|
{
|
||||||
|
DBUG_PRINT("repair", ("index #: %u key_root: 0x%lx active: %d",
|
||||||
|
i, (long) state->key_root[i],
|
||||||
|
maria_is_key_active(state->key_map, i)));
|
||||||
|
if ((state->key_root[i] != HA_OFFSET_ERROR) &&
|
||||||
|
!maria_is_key_active(state->key_map, i))
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
This index has at least one key block and it is disabled.
|
||||||
|
We would lose its block(s) if would just recreate it.
|
||||||
|
So we need to drop and recreate all indexes.
|
||||||
|
*/
|
||||||
|
DBUG_PRINT("repair", ("nonempty and disabled: recreate all"));
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (i >= share->base.keys)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
/*
|
||||||
|
We do now drop all indexes and declare them disabled. With the
|
||||||
|
T_CREATE_MISSING_KEYS flag, maria_repair*() will recreate all
|
||||||
|
disabled indexes and enable them.
|
||||||
|
*/
|
||||||
|
maria_clear_all_keys_active(state->key_map);
|
||||||
|
DBUG_PRINT("repair", ("declared all indexes disabled"));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Clear index root block pointers. */
|
||||||
|
for (i= 0; i < share->base.keys; i++)
|
||||||
|
state->key_root[i]= HA_OFFSET_ERROR;
|
||||||
|
|
||||||
|
/* Drop the delete chain. */
|
||||||
|
share->state.key_del= HA_OFFSET_ERROR;
|
||||||
|
|
||||||
|
/* Reset index file length to end of index file header. */
|
||||||
|
info->state->key_file_length= share->base.keystart;
|
||||||
|
|
||||||
|
end:
|
||||||
|
DBUG_RETURN(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Recover old table by reading each record and writing all keys
|
Recover old table by reading each record and writing all keys
|
||||||
|
|
||||||
|
|
@ -2225,7 +2340,6 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
||||||
char *name, my_bool rep_quick)
|
char *name, my_bool rep_quick)
|
||||||
{
|
{
|
||||||
int error, got_error;
|
int error, got_error;
|
||||||
uint i;
|
|
||||||
ha_rows start_records,new_header_length;
|
ha_rows start_records,new_header_length;
|
||||||
my_off_t del;
|
my_off_t del;
|
||||||
File new_file;
|
File new_file;
|
||||||
|
|
@ -2317,9 +2431,9 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sort_param.record= (uchar *) my_malloc((uint)
|
if (!(sort_param.record=
|
||||||
share->base.pack_reclength,
|
(uchar *) my_malloc((uint)
|
||||||
MYF(0))) ||
|
share->base.default_rec_buff_size, MYF(0))) ||
|
||||||
_ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size,
|
_ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size,
|
||||||
share->base.default_rec_buff_size))
|
share->base.default_rec_buff_size))
|
||||||
{
|
{
|
||||||
|
|
@ -2337,24 +2451,9 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
||||||
info->state->records=info->state->del=share->state.split=0;
|
info->state->records=info->state->del=share->state.split=0;
|
||||||
info->state->empty=0;
|
info->state->empty=0;
|
||||||
|
|
||||||
/*
|
|
||||||
Clear all keys. Note that all key blocks allocated until now remain
|
|
||||||
"dead" parts of the key file. (Bug #4692)
|
|
||||||
*/
|
|
||||||
for (i=0 ; i < share->base.keys ; i++)
|
|
||||||
share->state.key_root[i]= HA_OFFSET_ERROR;
|
|
||||||
|
|
||||||
/* Drop the delete chain. */
|
|
||||||
share->state.key_del= HA_OFFSET_ERROR;
|
|
||||||
|
|
||||||
/*
|
|
||||||
If requested, activate (enable) all keys in key_map. In this case,
|
|
||||||
all indexes will be (re-)built.
|
|
||||||
*/
|
|
||||||
if (param->testflag & T_CREATE_MISSING_KEYS)
|
if (param->testflag & T_CREATE_MISSING_KEYS)
|
||||||
maria_set_all_keys_active(share->state.key_map, share->base.keys);
|
maria_set_all_keys_active(share->state.key_map, share->base.keys);
|
||||||
|
maria_drop_all_indexes(param, info, TRUE);
|
||||||
info->state->key_file_length=share->base.keystart;
|
|
||||||
|
|
||||||
maria_lock_memory(param); /* Everything is alloced */
|
maria_lock_memory(param); /* Everything is alloced */
|
||||||
|
|
||||||
|
|
@ -2368,7 +2467,8 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
|
||||||
{
|
{
|
||||||
if (my_errno != HA_ERR_FOUND_DUPP_KEY)
|
if (my_errno != HA_ERR_FOUND_DUPP_KEY)
|
||||||
goto err;
|
goto err;
|
||||||
DBUG_DUMP("record",(uchar*) sort_param.record,share->base.pack_reclength);
|
DBUG_DUMP("record", (uchar*) sort_param.record,
|
||||||
|
share->base.default_rec_buff_size);
|
||||||
_ma_check_print_warning(param,
|
_ma_check_print_warning(param,
|
||||||
"Duplicate key %2d for record at %10s against new record at %10s",
|
"Duplicate key %2d for record at %10s against new record at %10s",
|
||||||
info->errkey+1,
|
info->errkey+1,
|
||||||
|
|
@ -3257,11 +3357,12 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
||||||
double *rec_per_key_part;
|
double *rec_per_key_part;
|
||||||
char llbuff[22];
|
char llbuff[22];
|
||||||
MARIA_SORT_INFO sort_info;
|
MARIA_SORT_INFO sort_info;
|
||||||
ulonglong key_map= share->state.key_map;
|
ulonglong key_map;
|
||||||
myf sync_dir= ((share->now_transactional && !share->temporary) ?
|
myf sync_dir= ((share->now_transactional && !share->temporary) ?
|
||||||
MY_SYNC_DIR : 0);
|
MY_SYNC_DIR : 0);
|
||||||
my_bool scan_inited= 0;
|
my_bool scan_inited= 0;
|
||||||
DBUG_ENTER("maria_repair_by_sort");
|
DBUG_ENTER("maria_repair_by_sort");
|
||||||
|
LINT_INIT(key_map);
|
||||||
|
|
||||||
got_error= 1;
|
got_error= 1;
|
||||||
new_file= -1;
|
new_file= -1;
|
||||||
|
|
@ -3338,8 +3439,9 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(sort_param.record=(uchar*) my_malloc((uint) share->base.pack_reclength,
|
if (!(sort_param.record=
|
||||||
MYF(0))) ||
|
(uchar*) my_malloc((size_t) share->base.default_rec_buff_size,
|
||||||
|
MYF(0))) ||
|
||||||
_ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size,
|
_ma_alloc_buffer(&sort_param.rec_buff, &sort_param.rec_buff_size,
|
||||||
share->base.default_rec_buff_size))
|
share->base.default_rec_buff_size))
|
||||||
{
|
{
|
||||||
|
|
@ -3347,16 +3449,14 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!(param->testflag & T_CREATE_MISSING_KEYS))
|
/* Optionally drop indexes and optionally modify the key_map */
|
||||||
|
maria_drop_all_indexes(param, info, FALSE);
|
||||||
|
key_map= share->state.key_map;
|
||||||
|
if (param->testflag & T_CREATE_MISSING_KEYS)
|
||||||
{
|
{
|
||||||
/* Clear the pointers to the given rows */
|
/* Invert the copied key_map to recreate all disabled indexes. */
|
||||||
for (i=0 ; i < share->base.keys ; i++)
|
key_map= ~key_map;
|
||||||
share->state.key_root[i]= HA_OFFSET_ERROR;
|
|
||||||
share->state.key_del= HA_OFFSET_ERROR;
|
|
||||||
info->state->key_file_length=share->base.keystart;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
key_map= ~key_map; /* Create the missing keys */
|
|
||||||
|
|
||||||
param->read_cache.end_of_file= sort_info.filelength;
|
param->read_cache.end_of_file= sort_info.filelength;
|
||||||
sort_param.wordlist=NULL;
|
sort_param.wordlist=NULL;
|
||||||
|
|
@ -3374,6 +3474,10 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
||||||
rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++)
|
rec_per_key_part+=sort_param.keyinfo->keysegs, sort_param.key++)
|
||||||
{
|
{
|
||||||
sort_param.keyinfo=share->keyinfo+sort_param.key;
|
sort_param.keyinfo=share->keyinfo+sort_param.key;
|
||||||
|
/*
|
||||||
|
Skip this index if it is marked disabled in the copied
|
||||||
|
(and possibly inverted) key_map.
|
||||||
|
*/
|
||||||
if (! maria_is_key_active(key_map, sort_param.key))
|
if (! maria_is_key_active(key_map, sort_param.key))
|
||||||
{
|
{
|
||||||
/* Remember old statistics for key */
|
/* Remember old statistics for key */
|
||||||
|
|
@ -3381,6 +3485,8 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
||||||
(char*) (share->state.rec_per_key_part +
|
(char*) (share->state.rec_per_key_part +
|
||||||
(uint) (rec_per_key_part - param->new_rec_per_key_part)),
|
(uint) (rec_per_key_part - param->new_rec_per_key_part)),
|
||||||
sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part));
|
sort_param.keyinfo->keysegs*sizeof(*rec_per_key_part));
|
||||||
|
DBUG_PRINT("repair", ("skipping seemingly disabled index #: %u",
|
||||||
|
sort_param.key));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -3492,6 +3598,7 @@ int maria_repair_by_sort(HA_CHECK *param, register MARIA_HA *info,
|
||||||
sort_param.notnull : NULL),
|
sort_param.notnull : NULL),
|
||||||
(ulonglong) info->state->records);
|
(ulonglong) info->state->records);
|
||||||
maria_set_key_active(share->state.key_map, sort_param.key);
|
maria_set_key_active(share->state.key_map, sort_param.key);
|
||||||
|
DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key));
|
||||||
|
|
||||||
if (_ma_flush_table_files_before_swap(param, info))
|
if (_ma_flush_table_files_before_swap(param, info))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
@ -3743,11 +3850,12 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
||||||
IO_CACHE new_data_cache; /* For non-quick repair. */
|
IO_CACHE new_data_cache; /* For non-quick repair. */
|
||||||
IO_CACHE_SHARE io_share;
|
IO_CACHE_SHARE io_share;
|
||||||
MARIA_SORT_INFO sort_info;
|
MARIA_SORT_INFO sort_info;
|
||||||
ulonglong key_map=share->state.key_map;
|
ulonglong key_map;
|
||||||
pthread_attr_t thr_attr;
|
pthread_attr_t thr_attr;
|
||||||
myf sync_dir= ((share->now_transactional && !share->temporary) ?
|
myf sync_dir= ((share->now_transactional && !share->temporary) ?
|
||||||
MY_SYNC_DIR : 0);
|
MY_SYNC_DIR : 0);
|
||||||
DBUG_ENTER("maria_repair_parallel");
|
DBUG_ENTER("maria_repair_parallel");
|
||||||
|
LINT_INIT(key_map);
|
||||||
|
|
||||||
got_error= 1;
|
got_error= 1;
|
||||||
new_file= -1;
|
new_file= -1;
|
||||||
|
|
@ -3768,19 +3876,19 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
||||||
/*
|
/*
|
||||||
Quick repair (not touching data file, rebuilding indexes):
|
Quick repair (not touching data file, rebuilding indexes):
|
||||||
{
|
{
|
||||||
Read cache is (MI_CHECK *param)->read_cache using info->dfile.file.
|
Read cache is (HA_CHECK *param)->read_cache using info->dfile.file.
|
||||||
}
|
}
|
||||||
|
|
||||||
Non-quick repair (rebuilding data file and indexes):
|
Non-quick repair (rebuilding data file and indexes):
|
||||||
{
|
{
|
||||||
Master thread:
|
Master thread:
|
||||||
|
|
||||||
Read cache is (MI_CHECK *param)->read_cache using info->dfile.file.
|
Read cache is (HA_CHECK *param)->read_cache using info->dfile.file.
|
||||||
Write cache is (MI_INFO *info)->rec_cache using new_file.
|
Write cache is (MARIA_INFO *info)->rec_cache using new_file.
|
||||||
|
|
||||||
Slave threads:
|
Slave threads:
|
||||||
|
|
||||||
Read cache is new_data_cache synced to master rec_cache.
|
Read cache is new_data_cache synced to master rec_cache.
|
||||||
|
|
||||||
The final assignment of the filedescriptor for rec_cache is done
|
The final assignment of the filedescriptor for rec_cache is done
|
||||||
after the cache creation.
|
after the cache creation.
|
||||||
|
|
@ -3843,17 +3951,14 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
||||||
info->rec_cache.file=new_file;
|
info->rec_cache.file=new_file;
|
||||||
}
|
}
|
||||||
|
|
||||||
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
|
/* Optionally drop indexes and optionally modify the key_map. */
|
||||||
if (!(param->testflag & T_CREATE_MISSING_KEYS))
|
maria_drop_all_indexes(param, info, FALSE);
|
||||||
|
key_map= share->state.key_map;
|
||||||
|
if (param->testflag & T_CREATE_MISSING_KEYS)
|
||||||
{
|
{
|
||||||
/* Clear the pointers to the given rows */
|
/* Invert the copied key_map to recreate all disabled indexes. */
|
||||||
for (i=0 ; i < share->base.keys ; i++)
|
key_map= ~key_map;
|
||||||
share->state.key_root[i]= HA_OFFSET_ERROR;
|
|
||||||
share->state.key_del= HA_OFFSET_ERROR;
|
|
||||||
info->state->key_file_length=share->base.keystart;
|
|
||||||
}
|
}
|
||||||
else
|
|
||||||
key_map= ~key_map; /* Create the missing keys */
|
|
||||||
|
|
||||||
param->read_cache.end_of_file= sort_info.filelength;
|
param->read_cache.end_of_file= sort_info.filelength;
|
||||||
|
|
||||||
|
|
@ -3892,6 +3997,10 @@ int maria_repair_parallel(HA_CHECK *param, register MARIA_HA *info,
|
||||||
sort_param[i].key=key;
|
sort_param[i].key=key;
|
||||||
sort_param[i].keyinfo=share->keyinfo+key;
|
sort_param[i].keyinfo=share->keyinfo+key;
|
||||||
sort_param[i].seg=sort_param[i].keyinfo->seg;
|
sort_param[i].seg=sort_param[i].keyinfo->seg;
|
||||||
|
/*
|
||||||
|
Skip this index if it is marked disabled in the copied
|
||||||
|
(and possibly inverted) key_map.
|
||||||
|
*/
|
||||||
if (! maria_is_key_active(key_map, key))
|
if (! maria_is_key_active(key_map, key))
|
||||||
{
|
{
|
||||||
/* Remember old statistics for key */
|
/* Remember old statistics for key */
|
||||||
|
|
@ -5729,8 +5838,8 @@ void _ma_update_auto_increment_key(HA_CHECK *param, MARIA_HA *info,
|
||||||
We have to use an allocated buffer instead of info->rec_buff as
|
We have to use an allocated buffer instead of info->rec_buff as
|
||||||
_ma_put_key_in_record() may use info->rec_buff
|
_ma_put_key_in_record() may use info->rec_buff
|
||||||
*/
|
*/
|
||||||
if (!(record= (uchar*) my_malloc((uint) share->base.pack_reclength,
|
if (!(record= (uchar*) my_malloc((size_t) share->base.default_rec_buff_size,
|
||||||
MYF(0))))
|
MYF(0))))
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,"Not enough memory for extra record");
|
_ma_check_print_error(param,"Not enough memory for extra record");
|
||||||
DBUG_VOID_RETURN;
|
DBUG_VOID_RETURN;
|
||||||
|
|
|
||||||
|
|
@ -81,7 +81,7 @@ int maria_delete(MARIA_HA *info,const uchar *record)
|
||||||
if (maria_is_key_active(share->state.key_map, i))
|
if (maria_is_key_active(share->state.key_map, i))
|
||||||
{
|
{
|
||||||
share->keyinfo[i].version++;
|
share->keyinfo[i].version++;
|
||||||
if (share->keyinfo[i].flag & HA_FULLTEXT )
|
if (share->keyinfo[i].flag & HA_FULLTEXT)
|
||||||
{
|
{
|
||||||
if (_ma_ft_del(info, i, old_key, record, info->cur_row.lastpos))
|
if (_ma_ft_del(info, i, old_key, record, info->cur_row.lastpos))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
|
||||||
|
|
@ -329,6 +329,29 @@ static my_bool write_dynamic_record(MARIA_HA *info, const uchar *record,
|
||||||
DBUG_ENTER("write_dynamic_record");
|
DBUG_ENTER("write_dynamic_record");
|
||||||
|
|
||||||
flag=0;
|
flag=0;
|
||||||
|
|
||||||
|
/*
|
||||||
|
Check if we have enough room for the new record.
|
||||||
|
First we do simplified check to make usual case faster.
|
||||||
|
Then we do more precise check for the space left.
|
||||||
|
Though it still is not absolutely precise, as
|
||||||
|
we always use MARIA_MAX_DYN_BLOCK_HEADER while it can be
|
||||||
|
less in the most of the cases.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (unlikely(info->s->base.max_data_file_length -
|
||||||
|
info->state->data_file_length <
|
||||||
|
reclength + MARIA_MAX_DYN_BLOCK_HEADER))
|
||||||
|
{
|
||||||
|
if (info->s->base.max_data_file_length - info->state->data_file_length +
|
||||||
|
info->state->empty - info->state->del * MARIA_MAX_DYN_BLOCK_HEADER <
|
||||||
|
reclength + MARIA_MAX_DYN_BLOCK_HEADER)
|
||||||
|
{
|
||||||
|
my_errno=HA_ERR_RECORD_FILE_FULL;
|
||||||
|
DBUG_RETURN(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
do
|
do
|
||||||
{
|
{
|
||||||
if (_ma_find_writepos(info,reclength,&filepos,&length))
|
if (_ma_find_writepos(info,reclength,&filepos,&length))
|
||||||
|
|
@ -771,6 +794,37 @@ static my_bool update_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS filepos,
|
||||||
DBUG_ENTER("update_dynamic_record");
|
DBUG_ENTER("update_dynamic_record");
|
||||||
|
|
||||||
flag=block_info.second_read=0;
|
flag=block_info.second_read=0;
|
||||||
|
/*
|
||||||
|
Check if we have enough room for the record.
|
||||||
|
First we do simplified check to make usual case faster.
|
||||||
|
Then we do more precise check for the space left.
|
||||||
|
Though it still is not absolutely precise, as
|
||||||
|
we always use MARIA_MAX_DYN_BLOCK_HEADER while it can be
|
||||||
|
less in the most of the cases.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/*
|
||||||
|
compare with just the reclength as we're going
|
||||||
|
to get some space from the old replaced record
|
||||||
|
*/
|
||||||
|
if (unlikely(info->s->base.max_data_file_length -
|
||||||
|
info->state->data_file_length < reclength))
|
||||||
|
{
|
||||||
|
/* If new record isn't longer, we can go on safely */
|
||||||
|
if (info->cur_row.total_length < reclength)
|
||||||
|
{
|
||||||
|
if (info->s->base.max_data_file_length - info->state->data_file_length +
|
||||||
|
info->state->empty - info->state->del * MARIA_MAX_DYN_BLOCK_HEADER <
|
||||||
|
reclength - info->cur_row.total_length + MARIA_MAX_DYN_BLOCK_HEADER)
|
||||||
|
{
|
||||||
|
my_errno=HA_ERR_RECORD_FILE_FULL;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Remember length for updated row if it's updated again */
|
||||||
|
info->cur_row.total_length= reclength;
|
||||||
|
|
||||||
while (reclength > 0)
|
while (reclength > 0)
|
||||||
{
|
{
|
||||||
if (filepos != info->s->state.dellink)
|
if (filepos != info->s->state.dellink)
|
||||||
|
|
@ -876,6 +930,7 @@ static my_bool update_dynamic_record(MARIA_HA *info, MARIA_RECORD_POS filepos,
|
||||||
if (block_info.next_filepos != HA_OFFSET_ERROR)
|
if (block_info.next_filepos != HA_OFFSET_ERROR)
|
||||||
if (delete_dynamic_record(info,block_info.next_filepos,1))
|
if (delete_dynamic_record(info,block_info.next_filepos,1))
|
||||||
goto err;
|
goto err;
|
||||||
|
|
||||||
DBUG_RETURN(0);
|
DBUG_RETURN(0);
|
||||||
err:
|
err:
|
||||||
DBUG_RETURN(1);
|
DBUG_RETURN(1);
|
||||||
|
|
@ -1420,6 +1475,7 @@ int _ma_read_dynamic_record(MARIA_HA *info, uchar *buf,
|
||||||
}
|
}
|
||||||
if (block_of_record++ == 0) /* First block */
|
if (block_of_record++ == 0) /* First block */
|
||||||
{
|
{
|
||||||
|
info->cur_row.total_length= block_info.rec_len;
|
||||||
if (block_info.rec_len > (uint) info->s->base.max_pack_length)
|
if (block_info.rec_len > (uint) info->s->base.max_pack_length)
|
||||||
goto panic;
|
goto panic;
|
||||||
if (info->s->base.blobs)
|
if (info->s->base.blobs)
|
||||||
|
|
@ -1752,6 +1808,7 @@ int _ma_read_rnd_dynamic_record(MARIA_HA *info,
|
||||||
}
|
}
|
||||||
if (block_of_record == 0) /* First block */
|
if (block_of_record == 0) /* First block */
|
||||||
{
|
{
|
||||||
|
info->cur_row.total_length= block_info.rec_len;
|
||||||
if (block_info.rec_len > (uint) share->base.max_pack_length)
|
if (block_info.rec_len > (uint) share->base.max_pack_length)
|
||||||
goto panic;
|
goto panic;
|
||||||
info->cur_row.lastpos= filepos;
|
info->cur_row.lastpos= filepos;
|
||||||
|
|
|
||||||
|
|
@ -23,8 +23,14 @@
|
||||||
inside plus subtree. max_docid could be used by any word in plus
|
inside plus subtree. max_docid could be used by any word in plus
|
||||||
subtree, but it could be updated by plus-word only.
|
subtree, but it could be updated by plus-word only.
|
||||||
|
|
||||||
|
Fulltext "smarter index merge" optimization assumes that rows
|
||||||
|
it gets are ordered by doc_id. That is not the case when we
|
||||||
|
search for a word with truncation operator. It may return
|
||||||
|
rows in random order. Thus we may not use "smarter index merge"
|
||||||
|
optimization with "trunc-words".
|
||||||
|
|
||||||
The idea is: there is no need to search for docid smaller than
|
The idea is: there is no need to search for docid smaller than
|
||||||
biggest docid inside current plus subtree.
|
biggest docid inside current plus subtree or any upper plus subtree.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
+word1 word2
|
+word1 word2
|
||||||
|
|
@ -36,6 +42,13 @@
|
||||||
+(word1 -word2) +(+word3 word4)
|
+(word1 -word2) +(+word3 word4)
|
||||||
share same max_docid
|
share same max_docid
|
||||||
max_docid updated by word3
|
max_docid updated by word3
|
||||||
|
+word1 word2 (+word3 word4 (+word5 word6))
|
||||||
|
three subexpressions (including the top-level one),
|
||||||
|
every one has its own max_docid, updated by its plus word.
|
||||||
|
but for the search word6 uses
|
||||||
|
max(word1.max_docid, word3.max_docid, word5.max_docid),
|
||||||
|
while word4 uses, accordingly,
|
||||||
|
max(word1.max_docid, word3.max_docid).
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define FT_CORE
|
#define FT_CORE
|
||||||
|
|
@ -104,14 +117,14 @@ typedef struct st_ftb_word
|
||||||
/* ^^^^^^^^^^^^^^^^^^ FTB_{EXPR,WORD} common section */
|
/* ^^^^^^^^^^^^^^^^^^ FTB_{EXPR,WORD} common section */
|
||||||
my_off_t docid[2]; /* for index search and for scan */
|
my_off_t docid[2]; /* for index search and for scan */
|
||||||
my_off_t key_root;
|
my_off_t key_root;
|
||||||
my_off_t *max_docid;
|
FTB_EXPR *max_docid_expr;
|
||||||
MARIA_KEYDEF *keyinfo;
|
MARIA_KEYDEF *keyinfo;
|
||||||
struct st_ftb_word *prev;
|
struct st_ftb_word *prev;
|
||||||
float weight;
|
float weight;
|
||||||
uint ndepth;
|
uint ndepth;
|
||||||
uint len;
|
uint len;
|
||||||
uchar off;
|
uchar off;
|
||||||
uchar word[1];
|
uchar word[1];
|
||||||
} FTB_WORD;
|
} FTB_WORD;
|
||||||
|
|
||||||
typedef struct st_ft_info
|
typedef struct st_ft_info
|
||||||
|
|
@ -208,13 +221,13 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param,
|
||||||
for (tmp_expr= ftb_param->ftbe; tmp_expr->up; tmp_expr= tmp_expr->up)
|
for (tmp_expr= ftb_param->ftbe; tmp_expr->up; tmp_expr= tmp_expr->up)
|
||||||
if (! (tmp_expr->flags & FTB_FLAG_YES))
|
if (! (tmp_expr->flags & FTB_FLAG_YES))
|
||||||
break;
|
break;
|
||||||
ftbw->max_docid= &tmp_expr->max_docid;
|
ftbw->max_docid_expr= tmp_expr;
|
||||||
/* fall through */
|
/* fall through */
|
||||||
case FT_TOKEN_STOPWORD:
|
case FT_TOKEN_STOPWORD:
|
||||||
if (! ftb_param->up_quot) break;
|
if (! ftb_param->up_quot) break;
|
||||||
phrase_word= (FT_WORD *)alloc_root(&ftb_param->ftb->mem_root, sizeof(FT_WORD));
|
phrase_word= (FT_WORD *)alloc_root(&ftb_param->ftb->mem_root, sizeof(FT_WORD));
|
||||||
tmp_element= (LIST *)alloc_root(&ftb_param->ftb->mem_root, sizeof(LIST));
|
tmp_element= (LIST *)alloc_root(&ftb_param->ftb->mem_root, sizeof(LIST));
|
||||||
phrase_word->pos= (uchar *) word;
|
phrase_word->pos= (uchar*) word;
|
||||||
phrase_word->len= word_len;
|
phrase_word->len= word_len;
|
||||||
tmp_element->data= (void *)phrase_word;
|
tmp_element->data= (void *)phrase_word;
|
||||||
ftb_param->ftbe->phrase= list_add(ftb_param->ftbe->phrase, tmp_element);
|
ftb_param->ftbe->phrase= list_add(ftb_param->ftbe->phrase, tmp_element);
|
||||||
|
|
@ -240,7 +253,7 @@ static int ftb_query_add_word(MYSQL_FTPARSER_PARAM *param,
|
||||||
if (info->yesno > 0) ftbe->up->ythresh++;
|
if (info->yesno > 0) ftbe->up->ythresh++;
|
||||||
ftb_param->ftbe= ftbe;
|
ftb_param->ftbe= ftbe;
|
||||||
ftb_param->depth++;
|
ftb_param->depth++;
|
||||||
ftb_param->up_quot= (uchar *) info->quot;
|
ftb_param->up_quot= (uchar*) info->quot;
|
||||||
break;
|
break;
|
||||||
case FT_TOKEN_RIGHT_PAREN:
|
case FT_TOKEN_RIGHT_PAREN:
|
||||||
if (ftb_param->ftbe->document)
|
if (ftb_param->ftbe->document)
|
||||||
|
|
@ -275,12 +288,12 @@ static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param,
|
||||||
MYSQL_FTPARSER_BOOLEAN_INFO info;
|
MYSQL_FTPARSER_BOOLEAN_INFO info;
|
||||||
CHARSET_INFO *cs= ftb_param->ftb->charset;
|
CHARSET_INFO *cs= ftb_param->ftb->charset;
|
||||||
uchar **start= (uchar**) &query;
|
uchar **start= (uchar**) &query;
|
||||||
char *end= query + len;
|
uchar *end= (uchar*) query + len;
|
||||||
FT_WORD w;
|
FT_WORD w;
|
||||||
|
|
||||||
info.prev= ' ';
|
info.prev= ' ';
|
||||||
info.quot= 0;
|
info.quot= 0;
|
||||||
while (maria_ft_get_word(cs, start, (uchar *) end, &w, &info))
|
while (maria_ft_get_word(cs, start, end, &w, &info))
|
||||||
param->mysql_add_word(param, (char *) w.pos, w.len, &info);
|
param->mysql_add_word(param, (char *) w.pos, w.len, &info);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
@ -308,7 +321,7 @@ static int _ftb_parse_query(FTB *ftb, uchar *query, uint len,
|
||||||
param->mysql_add_word= ftb_query_add_word;
|
param->mysql_add_word= ftb_query_add_word;
|
||||||
param->mysql_ftparam= (void *)&ftb_param;
|
param->mysql_ftparam= (void *)&ftb_param;
|
||||||
param->cs= ftb->charset;
|
param->cs= ftb->charset;
|
||||||
param->doc= (char *) query;
|
param->doc= (char*) query;
|
||||||
param->length= len;
|
param->length= len;
|
||||||
param->flags= 0;
|
param->flags= 0;
|
||||||
param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO;
|
param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO;
|
||||||
|
|
@ -329,8 +342,9 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
|
||||||
int subkeys=1;
|
int subkeys=1;
|
||||||
my_bool can_go_down;
|
my_bool can_go_down;
|
||||||
MARIA_HA *info=ftb->info;
|
MARIA_HA *info=ftb->info;
|
||||||
uint off= 0, extra=HA_FT_WLEN+info->s->base.rec_reflength;
|
uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength;
|
||||||
uchar *lastkey_buf= ftbw->word+ftbw->off;
|
uchar *lastkey_buf= ftbw->word+ftbw->off;
|
||||||
|
LINT_INIT(off);
|
||||||
|
|
||||||
if (ftbw->flags & FTB_FLAG_TRUNC)
|
if (ftbw->flags & FTB_FLAG_TRUNC)
|
||||||
lastkey_buf+=ftbw->len;
|
lastkey_buf+=ftbw->len;
|
||||||
|
|
@ -346,11 +360,17 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
uint sflag= SEARCH_BIGGER;
|
uint sflag= SEARCH_BIGGER;
|
||||||
if (ftbw->docid[0] < *ftbw->max_docid)
|
my_off_t max_docid=0;
|
||||||
|
FTB_EXPR *tmp;
|
||||||
|
|
||||||
|
for (tmp= ftbw->max_docid_expr; tmp; tmp= tmp->up)
|
||||||
|
set_if_bigger(max_docid, tmp->max_docid);
|
||||||
|
|
||||||
|
if (ftbw->docid[0] < max_docid)
|
||||||
{
|
{
|
||||||
sflag|= SEARCH_SAME;
|
sflag|= SEARCH_SAME;
|
||||||
_ma_dpointer(info, (ftbw->word + ftbw->len + HA_FT_WLEN),
|
_ma_dpointer(info, (uchar*) (ftbw->word + ftbw->len + HA_FT_WLEN),
|
||||||
*ftbw->max_docid);
|
max_docid);
|
||||||
}
|
}
|
||||||
r= _ma_search(info, ftbw->keyinfo, lastkey_buf,
|
r= _ma_search(info, ftbw->keyinfo, lastkey_buf,
|
||||||
USE_WHOLE_KEY, sflag, ftbw->key_root);
|
USE_WHOLE_KEY, sflag, ftbw->key_root);
|
||||||
|
|
@ -376,7 +396,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
|
||||||
if (!r && !ftbw->off)
|
if (!r && !ftbw->off)
|
||||||
{
|
{
|
||||||
r= ha_compare_text(ftb->charset,
|
r= ha_compare_text(ftb->charset,
|
||||||
(uchar*) info->lastkey+1,
|
info->lastkey+1,
|
||||||
info->lastkey_length-extra-1,
|
info->lastkey_length-extra-1,
|
||||||
(uchar*) ftbw->word+1,
|
(uchar*) ftbw->word+1,
|
||||||
ftbw->len-1,
|
ftbw->len-1,
|
||||||
|
|
@ -429,8 +449,8 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
|
||||||
memcpy(lastkey_buf+off, info->lastkey, info->lastkey_length);
|
memcpy(lastkey_buf+off, info->lastkey, info->lastkey_length);
|
||||||
}
|
}
|
||||||
ftbw->docid[0]= info->cur_row.lastpos;
|
ftbw->docid[0]= info->cur_row.lastpos;
|
||||||
if (ftbw->flags & FTB_FLAG_YES)
|
if (ftbw->flags & FTB_FLAG_YES && !(ftbw->flags & FTB_FLAG_TRUNC))
|
||||||
*ftbw->max_docid= info->cur_row.lastpos;
|
ftbw->max_docid_expr->max_docid= info->cur_row.lastpos;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -473,7 +493,8 @@ static void _ftb_init_index_search(FT_INFO *ftb)
|
||||||
ftbe->up->flags|= FTB_FLAG_TRUNC, ftbe=ftbe->up)
|
ftbe->up->flags|= FTB_FLAG_TRUNC, ftbe=ftbe->up)
|
||||||
{
|
{
|
||||||
if (ftbe->flags & FTB_FLAG_NO || /* 2 */
|
if (ftbe->flags & FTB_FLAG_NO || /* 2 */
|
||||||
ftbe->up->ythresh - ftbe->up->yweaks >1) /* 1 */
|
ftbe->up->ythresh - ftbe->up->yweaks >
|
||||||
|
(uint) test(ftbe->flags & FTB_FLAG_YES)) /* 1 */
|
||||||
{
|
{
|
||||||
FTB_EXPR *top_ftbe=ftbe->up;
|
FTB_EXPR *top_ftbe=ftbe->up;
|
||||||
ftbw->docid[0]=HA_OFFSET_ERROR;
|
ftbw->docid[0]=HA_OFFSET_ERROR;
|
||||||
|
|
@ -503,8 +524,9 @@ static void _ftb_init_index_search(FT_INFO *ftb)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
FT_INFO * maria_ft_init_boolean_search(MARIA_HA *info, uint keynr, uchar *query,
|
FT_INFO * maria_ft_init_boolean_search(MARIA_HA *info, uint keynr,
|
||||||
uint query_len, CHARSET_INFO *cs)
|
uchar *query,
|
||||||
|
uint query_len, CHARSET_INFO *cs)
|
||||||
{
|
{
|
||||||
FTB *ftb;
|
FTB *ftb;
|
||||||
FTB_EXPR *ftbe;
|
FTB_EXPR *ftbe;
|
||||||
|
|
@ -585,7 +607,7 @@ static int ftb_phrase_add_word(MYSQL_FTPARSER_PARAM *param,
|
||||||
MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam;
|
MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam;
|
||||||
FT_WORD *w= (FT_WORD *)phrase_param->document->data;
|
FT_WORD *w= (FT_WORD *)phrase_param->document->data;
|
||||||
LIST *phrase, *document;
|
LIST *phrase, *document;
|
||||||
w->pos= (uchar *) word;
|
w->pos= (uchar*) word;
|
||||||
w->len= word_len;
|
w->len= word_len;
|
||||||
phrase_param->document= phrase_param->document->prev;
|
phrase_param->document= phrase_param->document->prev;
|
||||||
if (phrase_param->phrase_length > phrase_param->document_length)
|
if (phrase_param->phrase_length > phrase_param->document_length)
|
||||||
|
|
@ -600,8 +622,8 @@ static int ftb_phrase_add_word(MYSQL_FTPARSER_PARAM *param,
|
||||||
{
|
{
|
||||||
FT_WORD *phrase_word= (FT_WORD *)phrase->data;
|
FT_WORD *phrase_word= (FT_WORD *)phrase->data;
|
||||||
FT_WORD *document_word= (FT_WORD *)document->data;
|
FT_WORD *document_word= (FT_WORD *)document->data;
|
||||||
if (my_strnncoll(phrase_param->cs,
|
if (my_strnncoll(phrase_param->cs, (uchar*) phrase_word->pos,
|
||||||
(uchar*) phrase_word->pos, phrase_word->len,
|
phrase_word->len,
|
||||||
(uchar*) document_word->pos, document_word->len))
|
(uchar*) document_word->pos, document_word->len))
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
@ -615,11 +637,11 @@ static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param,
|
||||||
{
|
{
|
||||||
FT_WORD word;
|
FT_WORD word;
|
||||||
MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam;
|
MY_FTB_PHRASE_PARAM *phrase_param= param->mysql_ftparam;
|
||||||
const char *docend= document + len;
|
const uchar *docend= (uchar*) document + len;
|
||||||
while (maria_ft_simple_get_word(phrase_param->cs, (uchar**) &document,
|
while (maria_ft_simple_get_word(phrase_param->cs, (uchar**) &document,
|
||||||
(const uchar *) docend, &word, FALSE))
|
docend, &word, FALSE))
|
||||||
{
|
{
|
||||||
param->mysql_add_word(param, (char *) word.pos, word.len, 0);
|
param->mysql_add_word(param, (char*) word.pos, word.len, 0);
|
||||||
if (phrase_param->match)
|
if (phrase_param->match)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
@ -663,7 +685,7 @@ static int _ftb_check_phrase(FTB *ftb, const uchar *document, uint len,
|
||||||
param->mysql_add_word= ftb_phrase_add_word;
|
param->mysql_add_word= ftb_phrase_add_word;
|
||||||
param->mysql_ftparam= (void *)&ftb_param;
|
param->mysql_ftparam= (void *)&ftb_param;
|
||||||
param->cs= ftb->charset;
|
param->cs= ftb->charset;
|
||||||
param->doc= (char *)document;
|
param->doc= (char *) document;
|
||||||
param->length= len;
|
param->length= len;
|
||||||
param->flags= 0;
|
param->flags= 0;
|
||||||
param->mode= MYSQL_FTPARSER_WITH_STOPWORDS;
|
param->mode= MYSQL_FTPARSER_WITH_STOPWORDS;
|
||||||
|
|
@ -875,10 +897,10 @@ static int ftb_find_relevance_parse(MYSQL_FTPARSER_PARAM *param,
|
||||||
{
|
{
|
||||||
MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam;
|
MY_FTB_FIND_PARAM *ftb_param= param->mysql_ftparam;
|
||||||
FT_INFO *ftb= ftb_param->ftb;
|
FT_INFO *ftb= ftb_param->ftb;
|
||||||
char *end= doc + len;
|
uchar *end= (uchar*) doc + len;
|
||||||
FT_WORD w;
|
FT_WORD w;
|
||||||
while (maria_ft_simple_get_word(ftb->charset, (uchar**) &doc,
|
while (maria_ft_simple_get_word(ftb->charset, (uchar**) &doc,
|
||||||
(const uchar *) end, &w, TRUE))
|
end, &w, TRUE))
|
||||||
param->mysql_add_word(param, (char *) w.pos, w.len, 0);
|
param->mysql_add_word(param, (char *) w.pos, w.len, 0);
|
||||||
return(0);
|
return(0);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -686,23 +686,24 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
|
||||||
share->page_type= PAGECACHE_PLAIN_PAGE;
|
share->page_type= PAGECACHE_PLAIN_PAGE;
|
||||||
share->now_transactional= share->base.born_transactional;
|
share->now_transactional= share->base.born_transactional;
|
||||||
|
|
||||||
if (share->data_file_type == DYNAMIC_RECORD)
|
/* Use pack_reclength as we don't want to modify base.pack_recklength */
|
||||||
|
if (share->state.header.org_data_file_type == DYNAMIC_RECORD)
|
||||||
{
|
{
|
||||||
/* add bits used to pack data to pack_reclength for faster allocation */
|
/* add bits used to pack data to pack_reclength for faster allocation */
|
||||||
share->base.pack_reclength+= share->base.pack_bytes;
|
share->base.pack_reclength+= share->base.pack_bytes;
|
||||||
share->base.extra_rec_buff_size=
|
share->base.extra_rec_buff_size=
|
||||||
(ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER) + MARIA_SPLIT_LENGTH +
|
(ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER) + MARIA_SPLIT_LENGTH +
|
||||||
MARIA_REC_BUFF_OFFSET);
|
MARIA_REC_BUFF_OFFSET);
|
||||||
}
|
}
|
||||||
share->base.default_rec_buff_size= (max(share->base.pack_reclength,
|
|
||||||
share->base.max_key_length) +
|
|
||||||
share->base.extra_rec_buff_size);
|
|
||||||
|
|
||||||
if (share->data_file_type == COMPRESSED_RECORD)
|
if (share->data_file_type == COMPRESSED_RECORD)
|
||||||
{
|
{
|
||||||
/* Need some extra bytes for decode_bytes */
|
/* Need some extra bytes for decode_bytes */
|
||||||
share->base.extra_rec_buff_size= 7;
|
share->base.extra_rec_buff_size+= 7;
|
||||||
}
|
}
|
||||||
|
share->base.default_rec_buff_size= max(share->base.pack_reclength +
|
||||||
|
share->base.extra_rec_buff_size,
|
||||||
|
share->base.max_key_length);
|
||||||
|
|
||||||
disk_pos_assert(disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE,
|
disk_pos_assert(disk_pos + share->base.fields *MARIA_COLUMNDEF_SIZE,
|
||||||
end_pos);
|
end_pos);
|
||||||
for (i= j= 0 ; i < share->base.fields ; i++)
|
for (i= j= 0 ; i < share->base.fields ; i++)
|
||||||
|
|
|
||||||
|
|
@ -200,7 +200,8 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
|
||||||
share->pack.header_length= uint4korr(header+4);
|
share->pack.header_length= uint4korr(header+4);
|
||||||
share->min_pack_length=(uint) uint4korr(header+8);
|
share->min_pack_length=(uint) uint4korr(header+8);
|
||||||
share->max_pack_length=(uint) uint4korr(header+12);
|
share->max_pack_length=(uint) uint4korr(header+12);
|
||||||
set_if_bigger(share->base.pack_reclength,share->max_pack_length);
|
set_if_bigger(share->base.default_rec_buff_size,
|
||||||
|
share->max_pack_length + 7);
|
||||||
elements=uint4korr(header+16);
|
elements=uint4korr(header+16);
|
||||||
intervall_length=uint4korr(header+20);
|
intervall_length=uint4korr(header+20);
|
||||||
trees=uint2korr(header+24);
|
trees=uint2korr(header+24);
|
||||||
|
|
@ -605,7 +606,7 @@ static void fill_quick_table(uint16 *table, uint bits, uint max_bits,
|
||||||
*/
|
*/
|
||||||
value|= (max_bits - bits) << 8 | IS_CHAR;
|
value|= (max_bits - bits) << 8 | IS_CHAR;
|
||||||
|
|
||||||
for (end= table + (uint) (((uint) 1 << bits)); table < end; table++)
|
for (end= table + ((my_ptrdiff_t) 1 << bits); table < end; table++)
|
||||||
{
|
{
|
||||||
*table= (uint16) value;
|
*table= (uint16) value;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -66,8 +66,8 @@ int maria_rnext_same(MARIA_HA *info, uchar *buf)
|
||||||
for (;;)
|
for (;;)
|
||||||
{
|
{
|
||||||
if ((error= _ma_search_next(info,keyinfo,info->lastkey,
|
if ((error= _ma_search_next(info,keyinfo,info->lastkey,
|
||||||
info->lastkey_length,SEARCH_BIGGER,
|
info->lastkey_length,SEARCH_BIGGER,
|
||||||
info->s->state.key_root[inx])))
|
info->s->state.key_root[inx])))
|
||||||
break;
|
break;
|
||||||
if (ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey,
|
if (ha_key_cmp(keyinfo->seg, (uchar*) info->lastkey,
|
||||||
(uchar*) info->lastkey2,
|
(uchar*) info->lastkey2,
|
||||||
|
|
|
||||||
|
|
@ -461,15 +461,16 @@ static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
|
||||||
uint nod_flag)
|
uint nod_flag)
|
||||||
{
|
{
|
||||||
double increase;
|
double increase;
|
||||||
double best_incr= DBL_MAX;
|
double best_incr;
|
||||||
double perimeter;
|
double perimeter;
|
||||||
double best_perimeter;
|
double best_perimeter;
|
||||||
uchar *best_key;
|
uchar *best_key= NULL;
|
||||||
uchar *k= rt_PAGE_FIRST_KEY(page_buf, nod_flag);
|
uchar *k= rt_PAGE_FIRST_KEY(page_buf, nod_flag);
|
||||||
uchar *last= rt_PAGE_END(info, page_buf);
|
uchar *last= rt_PAGE_END(info, page_buf);
|
||||||
|
|
||||||
LINT_INIT(best_perimeter);
|
LINT_INIT(best_perimeter);
|
||||||
LINT_INIT(best_key);
|
LINT_INIT(best_key);
|
||||||
|
LINT_INIT(best_incr);
|
||||||
|
|
||||||
for (; k < last; k= rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
|
for (; k < last; k= rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
|
||||||
{
|
{
|
||||||
|
|
@ -514,22 +515,13 @@ static uchar *maria_rtree_pick_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
|
||||||
&area)) == -1.0)
|
&area)) == -1.0)
|
||||||
return NULL;
|
return NULL;
|
||||||
/* The following should be safe, even if we compare doubles */
|
/* The following should be safe, even if we compare doubles */
|
||||||
if (increase < best_incr)
|
if (!best_key || increase < best_incr ||
|
||||||
|
((increase == best_incr) && (area < best_area)))
|
||||||
{
|
{
|
||||||
best_key= k;
|
best_key= k;
|
||||||
best_area= area;
|
best_area= area;
|
||||||
best_incr= increase;
|
best_incr= increase;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
/* The following should be safe, even if we compare doubles */
|
|
||||||
if ((increase == best_incr) && (area < best_area))
|
|
||||||
{
|
|
||||||
best_key= k;
|
|
||||||
best_area= area;
|
|
||||||
best_incr= increase;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return best_key;
|
return best_key;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -526,6 +526,9 @@ double maria_rtree_overlapping_area(HA_KEYSEG *keyseg, uchar* a, uchar* b,
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Calculates MBR_AREA(a+b) - MBR_AREA(a)
|
Calculates MBR_AREA(a+b) - MBR_AREA(a)
|
||||||
|
Note: when 'a' and 'b' objects are far from each other,
|
||||||
|
the area increase can be really big, so this function
|
||||||
|
can return 'inf' as a result.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
double maria_rtree_area_increase(HA_KEYSEG *keyseg, uchar *a, uchar *b,
|
double maria_rtree_area_increase(HA_KEYSEG *keyseg, uchar *a, uchar *b,
|
||||||
|
|
|
||||||
|
|
@ -1329,11 +1329,12 @@ int _ma_search_next(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
|
||||||
info->page_changed, info->keyread_buff_used));
|
info->page_changed, info->keyread_buff_used));
|
||||||
DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
|
DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
|
||||||
|
|
||||||
/* Force full read if we are at last key or if we are not on a leaf
|
/*
|
||||||
and the key tree has changed since we used it last time
|
Force full read if we are at last key or if we are not on a leaf
|
||||||
Note that even if the key tree has changed since last read, we can use
|
and the key tree has changed since we used it last time
|
||||||
the last read data from the leaf if we haven't used the buffer for
|
Note that even if the key tree has changed since last read, we can use
|
||||||
something else.
|
the last read data from the leaf if we haven't used the buffer for
|
||||||
|
something else.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
if (((nextflag & SEARCH_BIGGER) && info->int_keypos >= info->int_maxpos) ||
|
if (((nextflag & SEARCH_BIGGER) && info->int_keypos >= info->int_maxpos) ||
|
||||||
|
|
|
||||||
|
|
@ -569,9 +569,10 @@ int _ma_thr_write_keys(MARIA_SORT_PARAM *sort_param)
|
||||||
if (!mergebuf)
|
if (!mergebuf)
|
||||||
{
|
{
|
||||||
length=param->sort_buffer_length;
|
length=param->sort_buffer_length;
|
||||||
while (length >= MIN_SORT_MEMORY && !mergebuf)
|
while (length >= MIN_SORT_MEMORY)
|
||||||
{
|
{
|
||||||
mergebuf=my_malloc(length, MYF(0));
|
if ((mergebuf= my_malloc(length, MYF(0))))
|
||||||
|
break;
|
||||||
length=length*3/4;
|
length=length*3/4;
|
||||||
}
|
}
|
||||||
if (!mergebuf)
|
if (!mergebuf)
|
||||||
|
|
@ -909,6 +910,7 @@ merge_buffers(MARIA_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
|
||||||
|
|
||||||
count=error=0;
|
count=error=0;
|
||||||
maxcount=keys/((uint) (Tb-Fb) +1);
|
maxcount=keys/((uint) (Tb-Fb) +1);
|
||||||
|
DBUG_ASSERT(maxcount > 0);
|
||||||
LINT_INIT(to_start_filepos);
|
LINT_INIT(to_start_filepos);
|
||||||
if (to_file)
|
if (to_file)
|
||||||
to_start_filepos=my_b_tell(to_file);
|
to_start_filepos=my_b_tell(to_file);
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@ my_bool _ma_write_static_record(MARIA_HA *info, const uchar *record)
|
||||||
{
|
{
|
||||||
info->rec_cache.seek_not_done=1; /* We have done a seek */
|
info->rec_cache.seek_not_done=1; /* We have done a seek */
|
||||||
if (info->s->file_write(info, record, info->s->base.reclength,
|
if (info->s->file_write(info, record, info->s->base.reclength,
|
||||||
info->state->data_file_length,
|
info->state->data_file_length,
|
||||||
info->s->write_flag))
|
info->s->write_flag))
|
||||||
goto err;
|
goto err;
|
||||||
if (info->s->base.pack_reclength != info->s->base.reclength)
|
if (info->s->base.pack_reclength != info->s->base.reclength)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -39,9 +39,9 @@ static void put_blob_in_record(uchar *blob_pos,char **blob_buffer,
|
||||||
static void copy_key(MARIA_HA *info, uint inx, uchar *record, uchar *key);
|
static void copy_key(MARIA_HA *info, uint inx, uchar *record, uchar *key);
|
||||||
|
|
||||||
static int verbose= 0, testflag= 0, first_key= 0, async_io= 0, pagecacheing= 0;
|
static int verbose= 0, testflag= 0, first_key= 0, async_io= 0, pagecacheing= 0;
|
||||||
static int write_cacheing= 0, do_locking= 0, rec_pointer_size= 0, pack_fields= 1;
|
static int write_cacheing= 0, do_locking= 0, rec_pointer_size= 0;
|
||||||
static int silent= 0, opt_quick_mode= 0, transactional= 0, skip_update= 0;
|
static int silent= 0, opt_quick_mode= 0, transactional= 0, skip_update= 0;
|
||||||
static int die_in_middle_of_transaction= 0;
|
static int die_in_middle_of_transaction= 0, pack_fields= 1;
|
||||||
static int pack_seg= HA_SPACE_PACK, pack_type= HA_PACK_KEY, remove_count= -1;
|
static int pack_seg= HA_SPACE_PACK, pack_type= HA_PACK_KEY, remove_count= -1;
|
||||||
static int create_flag= 0, srand_arg= 0, checkpoint= 0;
|
static int create_flag= 0, srand_arg= 0, checkpoint= 0;
|
||||||
static uint use_blob= 0, update_count= 0;
|
static uint use_blob= 0, update_count= 0;
|
||||||
|
|
|
||||||
|
|
@ -1674,12 +1674,14 @@ static int maria_sort_records(HA_CHECK *param,
|
||||||
_ma_check_print_error(param,"Not enough memory for key block");
|
_ma_check_print_error(param,"Not enough memory for key block");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
if (!(sort_param.record=(uchar*) my_malloc((uint) share->base.pack_reclength,
|
|
||||||
MYF(0))))
|
if (!(sort_param.record=
|
||||||
|
(uchar*) my_malloc((uint) share->base.default_rec_buff_size, MYF(0))))
|
||||||
{
|
{
|
||||||
_ma_check_print_error(param,"Not enough memory for record");
|
_ma_check_print_error(param,"Not enough memory for record");
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn_format(param->temp_filename,name,"", MARIA_NAME_DEXT,2+4+32);
|
fn_format(param->temp_filename,name,"", MARIA_NAME_DEXT,2+4+32);
|
||||||
new_file= my_create(fn_format(param->temp_filename,
|
new_file= my_create(fn_format(param->temp_filename,
|
||||||
param->temp_filename,"",
|
param->temp_filename,"",
|
||||||
|
|
|
||||||
|
|
@ -3184,7 +3184,7 @@ static void fakebigcodes(HUFF_COUNTS *huff_counts, HUFF_COUNTS *end_count)
|
||||||
cur_sort_p= sort_counts;
|
cur_sort_p= sort_counts;
|
||||||
while (cur_count_p < end_count_p)
|
while (cur_count_p < end_count_p)
|
||||||
*(cur_sort_p++)= cur_count_p++;
|
*(cur_sort_p++)= cur_count_p++;
|
||||||
(void) qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp);
|
(void) my_qsort(sort_counts, 256, sizeof(my_off_t*), (qsort_cmp) fakecmp);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Assign faked counts.
|
Assign faked counts.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue