Commit 31d6d018 authored by unknown's avatar unknown

Merge stella.local:/home2/mydev/mysql-5.1-amain

into  stella.local:/home2/mydev/mysql-5.1-axmrg

parents 8a1ede49 490591a5
...@@ -360,6 +360,17 @@ AC_DEFUN([__MYSQL_EMIT_CHECK_PLUGIN],[ ...@@ -360,6 +360,17 @@ AC_DEFUN([__MYSQL_EMIT_CHECK_PLUGIN],[
AC_MSG_ERROR([cannot disable mandatory plugin]) AC_MSG_ERROR([cannot disable mandatory plugin])
fi fi
[mysql_plugin_]$2=yes [mysql_plugin_]$2=yes
],[
case "$with_mysqld_ldflags " in
*"-all-static "*)
# No need to build shared plugins when mysqld is linked with
# -all-static as it won't be able to load them.
if test "X[$mysql_plugin_]$2" != Xyes -a \
"X[$with_plugin_]$2" != Xyes; then
[with_plugin_]$2=no
fi
;;
esac
]) ])
if test "X[$with_plugin_]$2" = Xno; then if test "X[$with_plugin_]$2" = Xno; then
AC_MSG_RESULT([no]) AC_MSG_RESULT([no])
......
...@@ -1750,7 +1750,18 @@ then ...@@ -1750,7 +1750,18 @@ then
LDFLAGS="$LDFLAGS -rdynamic" LDFLAGS="$LDFLAGS -rdynamic"
AC_MSG_RESULT("-rdynamic") AC_MSG_RESULT("-rdynamic")
else else
AC_MSG_RESULT("none") case "$SYSTEM_TYPE$with_mysqld_ldflags " in
*freebsd*"-all-static "*|*dragonfly*"-all-static "*)
AC_MSG_RESULT("none")
;;
*freebsd*|*dragonfly*)
MYSQLD_EXTRA_LDFLAGS="$MYSQLD_EXTRA_LDFLAGS -export-dynamic"
AC_MSG_RESULT("-export-dynamic")
;;
*)
AC_MSG_RESULT("none")
;;
esac
fi fi
dnl Checks for typedefs, structures, and compiler characteristics. dnl Checks for typedefs, structures, and compiler characteristics.
......
...@@ -13,20 +13,20 @@ CREATE TABLE t2 (p POINT, INDEX(p)); ...@@ -13,20 +13,20 @@ CREATE TABLE t2 (p POINT, INDEX(p));
INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)')); INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)'));
INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)')); INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)'));
-- no index, returns 1 as expected # no index, returns 1 as expected
SELECT COUNT(*) FROM t1 WHERE p=POINTFROMTEXT('POINT(1 2)'); SELECT COUNT(*) FROM t1 WHERE p=POINTFROMTEXT('POINT(1 2)');
-- with index, returns 1 as expected # with index, returns 1 as expected
-- EXPLAIN shows that the index is not used though # EXPLAIN shows that the index is not used though
-- due to the "most rows covered anyway, so a scan is more effective" rule # due to the "most rows covered anyway, so a scan is more effective" rule
EXPLAIN EXPLAIN
SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)');
SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)'); SELECT COUNT(*) FROM t2 WHERE p=POINTFROMTEXT('POINT(1 2)');
-- adding another row to the table so that # adding another row to the table so that
-- the "most rows covered" rule doesn't kick in anymore # the "most rows covered" rule doesn't kick in anymore
-- now EXPLAIN shows the index used on the table # now EXPLAIN shows the index used on the table
# and we're getting the wrong result again
INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)')); INSERT INTO t1 VALUES (POINTFROMTEXT('POINT(1 2)'));
INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)')); INSERT INTO t2 VALUES (POINTFROMTEXT('POINT(1 2)'));
EXPLAIN EXPLAIN
......
...@@ -1163,7 +1163,7 @@ CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256)) ...@@ -1163,7 +1163,7 @@ CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256))
ENGINE = $engine_type; ENGINE = $engine_type;
INSERT INTO t1 VALUES (1,2); INSERT INTO t1 VALUES (1,2);
--#echo 1. test for locking: --echo # 1. test for locking:
BEGIN; BEGIN;
--enable_info --enable_info
......
...@@ -811,6 +811,12 @@ quote(name) ...@@ -811,6 +811,12 @@ quote(name)
???????? ????????
???????????????? ????????????????
drop table bug20536; drop table bug20536;
CREATE TABLE t1(a TEXT CHARSET ucs2 COLLATE ucs2_unicode_ci);
INSERT INTO t1 VALUES('abcd');
SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abcd' IN BOOLEAN MODE);
a
abcd
DROP TABLE t1;
End of 4.1 tests End of 4.1 tests
CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3)); CREATE TABLE t1 (a varchar(64) character set ucs2, b decimal(10,3));
INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0); INSERT INTO t1 VALUES ("1.1", 0), ("2.1", 0);
......
...@@ -476,6 +476,12 @@ ALTER TABLE t1 DISABLE KEYS; ...@@ -476,6 +476,12 @@ ALTER TABLE t1 DISABLE KEYS;
SELECT * FROM t1 WHERE MATCH(a) AGAINST('test'); SELECT * FROM t1 WHERE MATCH(a) AGAINST('test');
ERROR HY000: Can't find FULLTEXT index matching the column list ERROR HY000: Can't find FULLTEXT index matching the column list
DROP TABLE t1; DROP TABLE t1;
CREATE TABLE t1(a TEXT);
INSERT INTO t1 VALUES(' aaaaa aaaa');
SELECT * FROM t1 WHERE MATCH(a) AGAINST ('"aaaa"' IN BOOLEAN MODE);
a
aaaaa aaaa
DROP TABLE t1;
CREATE TABLE t1(a VARCHAR(20), FULLTEXT(a)); CREATE TABLE t1(a VARCHAR(20), FULLTEXT(a));
INSERT INTO t1 VALUES('Offside'),('City Of God'); 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);
......
...@@ -1426,6 +1426,7 @@ SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED; ...@@ -1426,6 +1426,7 @@ SET SESSION TRANSACTION ISOLATION LEVEL READ COMMITTED;
CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256)) CREATE TABLE t1 (a INT PRIMARY KEY, b VARCHAR(256))
ENGINE = InnoDB; ENGINE = InnoDB;
INSERT INTO t1 VALUES (1,2); INSERT INTO t1 VALUES (1,2);
# 1. test for locking:
BEGIN; BEGIN;
UPDATE t1 SET b = 12 WHERE a = 1; UPDATE t1 SET b = 12 WHERE a = 1;
affected rows: 1 affected rows: 1
......
...@@ -1987,3 +1987,28 @@ Table Op Msg_type Msg_text ...@@ -1987,3 +1987,28 @@ Table Op Msg_type Msg_text
test.t1 check status OK test.t1 check status OK
DROP TABLE t1; DROP TABLE t1;
End of 5.1 tests End of 5.1 tests
CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2)) ENGINE=MYISAM;
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 MyISAM 10 Fixed 0 # # # 1024 # # # # # # #
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 MyISAM 10 Fixed 1 # # # 3072 # # # # # # #
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 MyISAM 10 Fixed 1 # # # 3072 # # # # # # #
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 MyISAM 10 Fixed 1 # # # 3072 # # # # # # #
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 MyISAM 10 Fixed 1 # # # 3072 # # # # # # #
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 MyISAM 10 Fixed 1 # # # 3072 # # # # # # #
DROP TABLE t1;
drop table if exists t1; drop table if exists t1;
CREATE TABLE t1 (
d DATE NOT NULL
)
PARTITION BY RANGE( YEAR(d) ) (
PARTITION p0 VALUES LESS THAN (1960),
PARTITION p1 VALUES LESS THAN (1970),
PARTITION p2 VALUES LESS THAN (1980),
PARTITION p3 VALUES LESS THAN (1990)
);
ALTER TABLE t1 ADD PARTITION (
PARTITION `p5` VALUES LESS THAN (2010)
COMMENT 'APSTART \' APEND'
);
SELECT * FROM t1 LIMIT 1;
d
DROP TABLE t1;
create table t1 (id int auto_increment, s1 int, primary key (id));
insert into t1 values (null,1);
insert into t1 values (null,6);
select * from t1;
id s1
1 1
2 6
alter table t1 partition by range (id) (
partition p0 values less than (3),
partition p1 values less than maxvalue
);
drop table t1;
create table t1 (a int) create table t1 (a int)
partition by key(a) partition by key(a)
partitions 0.2+e1; partitions 0.2+e1;
......
...@@ -547,6 +547,14 @@ select quote(name) from bug20536; ...@@ -547,6 +547,14 @@ select quote(name) from bug20536;
drop table bug20536; drop table bug20536;
#
# BUG#31159 - fulltext search on ucs2 column crashes server
#
CREATE TABLE t1(a TEXT CHARSET ucs2 COLLATE ucs2_unicode_ci);
INSERT INTO t1 VALUES('abcd');
SELECT * FROM t1 WHERE MATCH(a) AGAINST ('+abcd' IN BOOLEAN MODE);
DROP TABLE t1;
--echo End of 4.1 tests --echo End of 4.1 tests
# #
......
...@@ -399,6 +399,14 @@ ALTER TABLE t1 DISABLE KEYS; ...@@ -399,6 +399,14 @@ ALTER TABLE t1 DISABLE KEYS;
SELECT * FROM t1 WHERE MATCH(a) AGAINST('test'); SELECT * FROM t1 WHERE MATCH(a) AGAINST('test');
DROP TABLE t1; DROP TABLE t1;
#
# BUG#11392 - fulltext search bug
#
CREATE TABLE t1(a TEXT);
INSERT INTO t1 VALUES(' aaaaa aaaa');
SELECT * FROM t1 WHERE MATCH(a) AGAINST ('"aaaa"' IN BOOLEAN MODE);
DROP TABLE t1;
# #
# BUG#29445 - match ... against () never returns # BUG#29445 - match ... against () never returns
# #
......
...@@ -1256,3 +1256,29 @@ CHECK TABLE t1; ...@@ -1256,3 +1256,29 @@ CHECK TABLE t1;
DROP TABLE t1; DROP TABLE t1;
--echo End of 5.1 tests --echo End of 5.1 tests
#
# Bug#4692 - DISABLE/ENABLE KEYS waste a space
#
CREATE TABLE t1 (c1 INT, c2 INT, UNIQUE INDEX (c1), INDEX (c2)) ENGINE=MYISAM;
--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.MYI
#--exec myisamchk -dvv var/master-data/test/t1.MYI
#--exec myisamchk -iev var/master-data/test/t1.MYI
DROP TABLE t1;
...@@ -14,6 +14,50 @@ ...@@ -14,6 +14,50 @@
drop table if exists t1; drop table if exists t1;
--enable_warnings --enable_warnings
#
# Bug #30695: An apostrophe ' in the comment of the ADD PARTITION causes the Server to crash.
#
# To verify the fix for crashing (on unix-type OS)
# uncomment the exec and error rows!
CREATE TABLE t1 (
d DATE NOT NULL
)
PARTITION BY RANGE( YEAR(d) ) (
PARTITION p0 VALUES LESS THAN (1960),
PARTITION p1 VALUES LESS THAN (1970),
PARTITION p2 VALUES LESS THAN (1980),
PARTITION p3 VALUES LESS THAN (1990)
);
ALTER TABLE t1 ADD PARTITION (
PARTITION `p5` VALUES LESS THAN (2010)
COMMENT 'APSTART \' APEND'
);
#--exec sed 's/APSTART \\/APSTART /' var/master-data/test/t1.frm > tmpt1.frm && mv tmpt1.frm var/master-data/test/t1.frm
#--error 1064
SELECT * FROM t1 LIMIT 1;
DROP TABLE t1;
#
# Bug 30878: crashing when alter an auto_increment non partitioned
# table to partitioned
create table t1 (id int auto_increment, s1 int, primary key (id));
insert into t1 values (null,1);
insert into t1 values (null,6);
select * from t1;
alter table t1 partition by range (id) (
partition p0 values less than (3),
partition p1 values less than maxvalue
);
drop table t1;
# #
# Bug 15890: Strange number of partitions accepted # Bug 15890: Strange number of partitions accepted
# #
......
...@@ -161,7 +161,7 @@ select * from information_schema.session_variables where variable_name like 'net ...@@ -161,7 +161,7 @@ select * from information_schema.session_variables where variable_name like 'net
set net_buffer_length=1; set net_buffer_length=1;
show variables like 'net_buffer_length'; show variables like 'net_buffer_length';
select * from information_schema.session_variables where variable_name like 'net_buffer_length'; select * from information_schema.session_variables where variable_name like 'net_buffer_length';
--warning 1292 #warning 1292
set net_buffer_length=2000000000; set net_buffer_length=2000000000;
show variables like 'net_buffer_length'; show variables like 'net_buffer_length';
select * from information_schema.session_variables where variable_name like 'net_buffer_length'; select * from information_schema.session_variables where variable_name like 'net_buffer_length';
......
...@@ -90,12 +90,14 @@ TARGET_LINK_LIBRARIES(mysqld ...@@ -90,12 +90,14 @@ TARGET_LINK_LIBRARIES(mysqld
SET_TARGET_PROPERTIES(mysqld PROPERTIES OUTPUT_NAME mysqld${MYSQLD_EXE_SUFFIX}) SET_TARGET_PROPERTIES(mysqld PROPERTIES OUTPUT_NAME mysqld${MYSQLD_EXE_SUFFIX})
IF(cmake_version EQUAL 20406)
# Work around for 2.4.6 bug, OUTPUT_NAME will not set the right .PDB # Work around for 2.4.6 bug, OUTPUT_NAME will not set the right .PDB
# file name. Note that COMPILE_FLAGS set some temporary pdb during build, # file name. Note that COMPILE_FLAGS set some temporary pdb during build,
# LINK_FLAGS sets the real one. # LINK_FLAGS sets the real one.
SET_TARGET_PROPERTIES(mysqld PROPERTIES SET_TARGET_PROPERTIES(mysqld PROPERTIES
COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb" COMPILE_FLAGS "/Fd${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb"
LINK_FLAGS "/PDB:${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb") LINK_FLAGS "/PDB:${CMAKE_CFG_INTDIR}/mysqld${MYSQLD_EXE_SUFFIX}.pdb")
ENDIF(cmake_version EQUAL 20406)
IF(EMBED_MANIFESTS) IF(EMBED_MANIFESTS)
MYSQL_EMBED_MANIFEST("mysqld" "asInvoker") MYSQL_EMBED_MANIFEST("mysqld" "asInvoker")
......
...@@ -2678,7 +2678,8 @@ int ha_partition::write_row(uchar * buf) ...@@ -2678,7 +2678,8 @@ int ha_partition::write_row(uchar * buf)
uint32 part_id; uint32 part_id;
int error; int error;
longlong func_value; longlong func_value;
bool autoincrement_lock= false; bool autoincrement_lock= FALSE;
my_bitmap_map *old_map;
#ifdef NOT_NEEDED #ifdef NOT_NEEDED
uchar *rec0= m_rec0; uchar *rec0= m_rec0;
#endif #endif
...@@ -2705,8 +2706,17 @@ int ha_partition::write_row(uchar * buf) ...@@ -2705,8 +2706,17 @@ int ha_partition::write_row(uchar * buf)
use autoincrement_lock variable to avoid unnecessary locks. use autoincrement_lock variable to avoid unnecessary locks.
Probably not an ideal solution. Probably not an ideal solution.
*/ */
autoincrement_lock= true; if (table_share->tmp_table == NO_TMP_TABLE)
pthread_mutex_lock(&table_share->mutex); {
/*
Bug#30878 crash when alter table from non partitioned table
to partitioned.
Checking if tmp table then there is no need to lock,
and the table_share->mutex may not be initialised.
*/
autoincrement_lock= TRUE;
pthread_mutex_lock(&table_share->mutex);
}
error= update_auto_increment(); error= update_auto_increment();
/* /*
...@@ -2715,10 +2725,10 @@ int ha_partition::write_row(uchar * buf) ...@@ -2715,10 +2725,10 @@ int ha_partition::write_row(uchar * buf)
the correct partition. We must check and fail if neccessary. the correct partition. We must check and fail if neccessary.
*/ */
if (error) if (error)
DBUG_RETURN(error); goto exit;
} }
my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set); old_map= dbug_tmp_use_all_columns(table, table->read_set);
#ifdef NOT_NEEDED #ifdef NOT_NEEDED
if (likely(buf == rec0)) if (likely(buf == rec0))
#endif #endif
......
...@@ -1856,6 +1856,20 @@ static int add_uint(File fptr, ulonglong number) ...@@ -1856,6 +1856,20 @@ static int add_uint(File fptr, ulonglong number)
return add_string(fptr, buff); return add_string(fptr, buff);
} }
/*
Must escape strings in partitioned tables frm-files,
parsing it later with mysql_unpack_partition will fail otherwise.
*/
static int add_quoted_string(File fptr, const char *quotestr)
{
String orgstr(quotestr, system_charset_info);
String escapedstr;
int err= add_string(fptr, "'");
err+= append_escaped(&escapedstr, &orgstr);
err+= add_string(fptr, escapedstr.c_ptr());
return err + add_string(fptr, "'");
}
static int add_keyword_string(File fptr, const char *keyword, static int add_keyword_string(File fptr, const char *keyword,
bool should_use_quotes, bool should_use_quotes,
const char *keystr) const char *keystr)
...@@ -1866,10 +1880,9 @@ static int add_keyword_string(File fptr, const char *keyword, ...@@ -1866,10 +1880,9 @@ static int add_keyword_string(File fptr, const char *keyword,
err+= add_equal(fptr); err+= add_equal(fptr);
err+= add_space(fptr); err+= add_space(fptr);
if (should_use_quotes) if (should_use_quotes)
err+= add_string(fptr, "'"); err+= add_quoted_string(fptr, keystr);
err+= add_string(fptr, keystr); else
if (should_use_quotes) err+= add_string(fptr, keystr);
err+= add_string(fptr, "'");
return err + add_space(fptr); return err + add_space(fptr);
} }
......
...@@ -6492,7 +6492,7 @@ bool_pri: ...@@ -6492,7 +6492,7 @@ bool_pri:
{ $$= (*$2)(0)->create($1,$3); } { $$= (*$2)(0)->create($1,$3); }
| bool_pri comp_op all_or_any '(' subselect ')' %prec EQ | bool_pri comp_op all_or_any '(' subselect ')' %prec EQ
{ $$= all_any_subquery_creator($1, $2, $3, $5); } { $$= all_any_subquery_creator($1, $2, $3, $5); }
| predicate ; | predicate
; ;
predicate: predicate:
......
...@@ -1784,7 +1784,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias, ...@@ -1784,7 +1784,8 @@ int open_table_from_share(THD *thd, TABLE_SHARE *share, const char *alias,
outparam, is_create_table, outparam, is_create_table,
share->default_part_db_type, share->default_part_db_type,
&work_part_info_used); &work_part_info_used);
outparam->part_info->is_auto_partitioned= share->auto_partitioned; if (!tmp)
outparam->part_info->is_auto_partitioned= share->auto_partitioned;
DBUG_PRINT("info", ("autopartitioned: %u", share->auto_partitioned)); DBUG_PRINT("info", ("autopartitioned: %u", share->auto_partitioned));
/* we should perform the fix_partition_func in either local or /* we should perform the fix_partition_func in either local or
caller's arena depending on work_part_info_used value caller's arena depending on work_part_info_used value
......
...@@ -1376,6 +1376,139 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) ...@@ -1376,6 +1376,139 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend)
} /* chk_data_link */ } /* chk_data_link */
/**
@brief Drop all indexes
@param[in] param check parameters
@param[in] info MI_INFO 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,
mi_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 mi_drop_all_indexes(MI_CHECK *param, MI_INFO *info, my_bool force)
{
MYISAM_SHARE *share= info->s;
MI_STATE_INFO *state= &share->state;
uint i;
int error;
DBUG_ENTER("mi_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],
mi_is_key_active(state->key_map, i)));
if ((state->key_root[i] != HA_OFFSET_ERROR) &&
!mi_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)
{
/*
All of the disabled indexes are empty. We can just recreate them.
Flush dirty blocks of this index file from key cache and remove
all blocks of this index file from key cache.
*/
DBUG_PRINT("repair", ("all disabled are empty: create missing"));
error= flush_key_blocks(share->key_cache, share->kfile,
FLUSH_FORCE_WRITE);
goto end;
}
/*
We do now drop all indexes and declare them disabled. With the
T_CREATE_MISSING_KEYS flag, mi_repair*() will recreate all
disabled indexes and enable them.
*/
mi_clear_all_keys_active(state->key_map);
DBUG_PRINT("repair", ("declared all indexes disabled"));
}
/* Remove all key blocks of this index file from key cache. */
if ((error= flush_key_blocks(share->key_cache, share->kfile,
FLUSH_IGNORE_CHANGED)))
goto end;
/* Clear index root block pointers. */
for (i= 0; i < share->base.keys; i++)
state->key_root[i]= HA_OFFSET_ERROR;
/* Clear the delete chains. */
for (i= 0; i < state->header.max_block_size_index; i++)
state->key_del[i]= HA_OFFSET_ERROR;
/* Reset index file length to end of index file header. */
info->state->key_file_length= share->base.keystart;
DBUG_PRINT("repair", ("dropped all indexes"));
/* error= 0; set by last (error= flush_key_bocks()). */
end:
DBUG_RETURN(error);
}
/* Recover old table by reading each record and writing all keys */ /* Recover old table by reading each record and writing all keys */
/* Save new datafile-name in temp_filename */ /* Save new datafile-name in temp_filename */
...@@ -1383,7 +1516,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1383,7 +1516,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
char * name, int rep_quick) char * name, int 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;
...@@ -1487,25 +1619,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, ...@@ -1487,25 +1619,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info,
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
/* /* This function always recreates all enabled indexes. */
Clear all keys. Note that all key blocks allocated until now remain
"dead" parts of the key file. (Bug #4692)
*/
for (i=0 ; i < info->s->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
/* Drop the delete chain. */
for (i=0 ; i < share->state.header.max_block_size_index ; i++)
share->state.key_del[i]= 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)
mi_set_all_keys_active(share->state.key_map, share->base.keys); mi_set_all_keys_active(share->state.key_map, share->base.keys);
mi_drop_all_indexes(param, info, TRUE);
info->state->key_file_length=share->base.keystart;
lock_memory(param); /* Everything is alloced */ lock_memory(param); /* Everything is alloced */
...@@ -2106,8 +2223,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -2106,8 +2223,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
ulong *rec_per_key_part; ulong *rec_per_key_part;
char llbuff[22]; char llbuff[22];
SORT_INFO sort_info; SORT_INFO sort_info;
ulonglong key_map=share->state.key_map; ulonglong key_map;
DBUG_ENTER("mi_repair_by_sort"); DBUG_ENTER("mi_repair_by_sort");
LINT_INIT(key_map);
start_records=info->state->records; start_records=info->state->records;
got_error=1; got_error=1;
...@@ -2180,25 +2298,14 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -2180,25 +2298,14 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
} }
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
if (!(param->testflag & T_CREATE_MISSING_KEYS))
{ /* Optionally drop indexes and optionally modify the key_map. */
/* mi_drop_all_indexes(param, info, FALSE);
Flush key cache for this file if we are calling this outside key_map= share->state.key_map;
myisamchk if (param->testflag & T_CREATE_MISSING_KEYS)
*/
flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
for (i=0 ; i < share->state.header.max_block_size_index ; i++)
share->state.key_del[i]= HA_OFFSET_ERROR;
info->state->key_file_length=share->base.keystart;
}
else
{ {
if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) /* Invert the copied key_map to recreate all disabled indexes. */
goto err; key_map= ~key_map;
key_map= ~key_map; /* Create the missing keys */
} }
sort_info.info=info; sort_info.info=info;
...@@ -2242,6 +2349,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -2242,6 +2349,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
sort_param.read_cache=param->read_cache; sort_param.read_cache=param->read_cache;
sort_param.keyinfo=share->keyinfo+sort_param.key; sort_param.keyinfo=share->keyinfo+sort_param.key;
sort_param.seg=sort_param.keyinfo->seg; sort_param.seg=sort_param.keyinfo->seg;
/*
Skip this index if it is marked disabled in the copied
(and possibly inverted) key_map.
*/
if (! mi_is_key_active(key_map, sort_param.key)) if (! mi_is_key_active(key_map, sort_param.key))
{ {
/* Remember old statistics for key */ /* Remember old statistics for key */
...@@ -2249,6 +2360,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -2249,6 +2360,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
(char*) (share->state.rec_per_key_part + (char*) (share->state.rec_per_key_part +
(uint) (rec_per_key_part - param->rec_per_key_part)), (uint) (rec_per_key_part - param->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;
} }
...@@ -2329,8 +2442,11 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ...@@ -2329,8 +2442,11 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
if (param->testflag & T_STATISTICS) if (param->testflag & T_STATISTICS)
update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique, update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique,
param->stats_method == MI_STATS_METHOD_IGNORE_NULLS? param->stats_method == MI_STATS_METHOD_IGNORE_NULLS?
sort_param.notnull: NULL,(ulonglong) info->state->records); sort_param.notnull: NULL,
(ulonglong) info->state->records);
/* Enable this index in the permanent (not the copied) key_map. */
mi_set_key_active(share->state.key_map, sort_param.key); mi_set_key_active(share->state.key_map, sort_param.key);
DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key));
if (sort_param.fix_datafile) if (sort_param.fix_datafile)
{ {
...@@ -2531,9 +2647,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, ...@@ -2531,9 +2647,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *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;
SORT_INFO sort_info; SORT_INFO sort_info;
ulonglong key_map=share->state.key_map; ulonglong key_map;
pthread_attr_t thr_attr; pthread_attr_t thr_attr;
DBUG_ENTER("mi_repair_parallel"); DBUG_ENTER("mi_repair_parallel");
LINT_INIT(key_map);
start_records=info->state->records; start_records=info->state->records;
got_error=1; got_error=1;
...@@ -2635,25 +2752,14 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, ...@@ -2635,25 +2752,14 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
} }
info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
if (!(param->testflag & T_CREATE_MISSING_KEYS))
{ /* Optionally drop indexes and optionally modify the key_map. */
/* mi_drop_all_indexes(param, info, FALSE);
Flush key cache for this file if we are calling this outside key_map= share->state.key_map;
myisamchk if (param->testflag & T_CREATE_MISSING_KEYS)
*/
flush_key_blocks(share->key_cache,share->kfile, FLUSH_IGNORE_CHANGED);
/* Clear the pointers to the given rows */
for (i=0 ; i < share->base.keys ; i++)
share->state.key_root[i]= HA_OFFSET_ERROR;
for (i=0 ; i < share->state.header.max_block_size_index ; i++)
share->state.key_del[i]= HA_OFFSET_ERROR;
info->state->key_file_length=share->base.keystart;
}
else
{ {
if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) /* Invert the copied key_map to recreate all disabled indexes. */
goto err; key_map= ~key_map;
key_map= ~key_map; /* Create the missing keys */
} }
sort_info.info=info; sort_info.info=info;
...@@ -2709,6 +2815,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, ...@@ -2709,6 +2815,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *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 (! mi_is_key_active(key_map, key)) if (! mi_is_key_active(key_map, key))
{ {
/* Remember old statistics for key */ /* Remember old statistics for key */
......
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