MDEV-25102 UNIQUE USING HASH error after ALTER ... DISABLE KEYS

on disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE) the engine does
not know that the long unique is logically unique, because on the
engine level it is not. And the engine disables it,

Change the disable_indexes/enable_indexes API. Instead of the enum
mode, send a key_map of indexes that should be enabled. This way the
server will decide what is unique, not the engine.
This commit is contained in:
Sergei Golubchik 2024-04-27 15:15:37 +02:00
parent 9b2bf09b95
commit 22b3ba9312
23 changed files with 354 additions and 381 deletions

View File

@ -717,4 +717,16 @@ a b
update t1 set b='A' where a=1;
ERROR 23000: Duplicate entry 'A' for key 'b'
drop table t1;
#
# MDEV-25102 UNIQUE USING HASH error after ALTER ... DISABLE KEYS
#
create table t1 (i int, unique key (i) using hash);
alter table t1 disable keys;
insert into t1 values (1),(2);
insert into t1 values (1);
ERROR 23000: Duplicate entry '1' for key 'i'
alter table t1 enable keys;
insert into t1 values (2);
ERROR 23000: Duplicate entry '2' for key 'i'
drop table t1;
# End of 10.5 tests

View File

@ -685,4 +685,17 @@ select * from t1;
update t1 set b='A' where a=1;
drop table t1;
--echo #
--echo # MDEV-25102 UNIQUE USING HASH error after ALTER ... DISABLE KEYS
--echo #
create table t1 (i int, unique key (i) using hash);
alter table t1 disable keys;
insert into t1 values (1),(2);
--error ER_DUP_ENTRY
insert into t1 values (1);
alter table t1 enable keys;
--error ER_DUP_ENTRY
insert into t1 values (2);
drop table t1;
--echo # End of 10.5 tests

View File

@ -26,8 +26,6 @@ PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1324 DEFAULT CHARSET=utf8 ROW_FORMAT=COMPRESSED;
LOCK TABLES cardtest_tbl WRITE;
ALTER TABLE cardtest_tbl DISABLE KEYS;
Warnings:
Note 1031 Storage engine InnoDB of the table `cardtest02`.`cardtest_tbl` doesn't have this option
INSERT INTO cardtest_tbl VALUES
(1,1,'','',1,1466430455,1471454450,NULL,10.00000,1,NULL,'','',NULL,NULL,1,NULL,NULL),
(2,1,'','',1,1466430455,1471454450,NULL,10.00000,1,NULL,'','',NULL,NULL,1,NULL,NULL),

View File

@ -1664,10 +1664,10 @@ bool ha_partition::is_crashed() const
int ha_partition::prepare_new_partition(TABLE *tbl,
HA_CREATE_INFO *create_info,
handler *file, const char *part_name,
partition_element *p_elem,
uint disable_non_uniq_indexes)
partition_element *p_elem)
{
int error;
key_map keys_in_use= table->s->keys_in_use;
DBUG_ENTER("prepare_new_partition");
/*
@ -1723,8 +1723,8 @@ int ha_partition::prepare_new_partition(TABLE *tbl,
goto error_external_lock;
DBUG_PRINT("info", ("partition %s external locked", part_name));
if (disable_non_uniq_indexes)
file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
if (!keys_in_use.is_prefix(table->s->keys))
file->ha_disable_indexes(keys_in_use, true);
DBUG_RETURN(0);
error_external_lock:
@ -2020,13 +2020,6 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
calls
*/
/*
Before creating new partitions check whether indexes are disabled
in the partitions.
*/
uint disable_non_uniq_indexes= indexes_are_disabled();
i= 0;
part_count= 0;
part_it.rewind();
@ -2068,8 +2061,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
prepare_new_partition(table, create_info,
new_file_array[part],
(const char *)part_name_buff,
sub_elem,
disable_non_uniq_indexes))))
sub_elem))))
{
cleanup_new_partition(part_count);
DBUG_RETURN(error);
@ -2095,8 +2087,7 @@ int ha_partition::change_partitions(HA_CREATE_INFO *create_info,
prepare_new_partition(table, create_info,
new_file_array[i],
(const char *)part_name_buff,
part_elem,
disable_non_uniq_indexes))))
part_elem))))
{
cleanup_new_partition(part_count);
DBUG_RETURN(error);
@ -11054,7 +11045,7 @@ int ha_partition::calculate_checksum()
!= 0 Error
*/
int ha_partition::disable_indexes(uint mode)
int ha_partition::disable_indexes(key_map map, bool persist)
{
handler **file;
int error= 0;
@ -11062,7 +11053,7 @@ int ha_partition::disable_indexes(uint mode)
DBUG_ASSERT(bitmap_is_set_all(&(m_part_info->lock_partitions)));
for (file= m_file; *file; file++)
{
if (unlikely((error= (*file)->ha_disable_indexes(mode))))
if (unlikely((error= (*file)->ha_disable_indexes(map, persist))))
break;
}
return error;
@ -11079,7 +11070,7 @@ int ha_partition::disable_indexes(uint mode)
!= 0 Error
*/
int ha_partition::enable_indexes(uint mode)
int ha_partition::enable_indexes(key_map map, bool persist)
{
handler **file;
int error= 0;
@ -11087,7 +11078,7 @@ int ha_partition::enable_indexes(uint mode)
DBUG_ASSERT(bitmap_is_set_all(&(m_part_info->lock_partitions)));
for (file= m_file; *file; file++)
{
if (unlikely((error= (*file)->ha_enable_indexes(mode))))
if (unlikely((error= (*file)->ha_enable_indexes(map, persist))))
break;
}
return error;

View File

@ -575,8 +575,7 @@ private:
void cleanup_new_partition(uint part_count);
int prepare_new_partition(TABLE *table, HA_CREATE_INFO *create_info,
handler *file, const char *part_name,
partition_element *p_elem,
uint disable_non_uniq_indexes);
partition_element *p_elem);
/*
delete_table and rename_table uses very similar logic which
is packed into this routine.
@ -1578,8 +1577,8 @@ public:
Enable/Disable Indexes are only supported by HEAP and MyISAM.
-------------------------------------------------------------------------
*/
int disable_indexes(uint mode) override;
int enable_indexes(uint mode) override;
int disable_indexes(key_map map, bool persist) override;
int enable_indexes(key_map map, bool persist) override;
int indexes_are_disabled() override;
/*

View File

@ -4909,32 +4909,48 @@ handler::ha_check_and_repair(THD *thd)
/**
Disable indexes: public interface.
@param map has 0 for all indexes that should be disabled
@param persist indexes should stay disabled after server restart
Currently engines don't support disabling an arbitrary subset of indexes.
In particular, if the change is persistent:
* auto-increment index should not be disabled
* unique indexes should not be disabled
if unique or auto-increment indexes are disabled (non-persistently),
the caller should only insert data that does not require
auto-inc generation and does not violate uniqueness
@sa handler::disable_indexes()
*/
int
handler::ha_disable_indexes(uint mode)
handler::ha_disable_indexes(key_map map, bool persist)
{
DBUG_ASSERT(table->s->tmp_table != NO_TMP_TABLE || m_lock_type != F_UNLCK);
mark_trx_read_write();
return disable_indexes(mode);
return disable_indexes(map, persist);
}
/**
Enable indexes: public interface.
@param map has 1 for all indexes that should be enabled
@param persist indexes should stay enabled after server restart
@sa handler::enable_indexes()
*/
int
handler::ha_enable_indexes(uint mode)
handler::ha_enable_indexes(key_map map, bool persist)
{
DBUG_ASSERT(table->s->tmp_table != NO_TMP_TABLE || m_lock_type != F_UNLCK);
mark_trx_read_write();
return enable_indexes(mode);
return enable_indexes(map, persist);
}

View File

@ -445,12 +445,6 @@ enum chf_create_flags {
#define HA_FAST_CHANGE_PARTITION (1UL << 13)
#define HA_PARTITION_ONE_PHASE (1UL << 14)
/* operations for disable/enable indexes */
#define HA_KEY_SWITCH_NONUNIQ 0
#define HA_KEY_SWITCH_ALL 1
#define HA_KEY_SWITCH_NONUNIQ_SAVE 2
#define HA_KEY_SWITCH_ALL_SAVE 3
/*
Note: the following includes binlog and closing 0.
TODO remove the limit, use dynarrays
@ -3439,8 +3433,8 @@ public:
int ha_optimize(THD* thd, HA_CHECK_OPT* check_opt);
int ha_analyze(THD* thd, HA_CHECK_OPT* check_opt);
bool ha_check_and_repair(THD *thd);
int ha_disable_indexes(uint mode);
int ha_enable_indexes(uint mode);
int ha_disable_indexes(key_map map, bool persist);
int ha_enable_indexes(key_map map, bool persist);
int ha_discard_or_import_tablespace(my_bool discard);
int ha_rename_table(const char *from, const char *to);
void ha_drop_table(const char *name);
@ -4950,8 +4944,8 @@ public:
virtual int analyze(THD* thd, HA_CHECK_OPT* check_opt)
{ return HA_ADMIN_NOT_IMPLEMENTED; }
virtual bool check_and_repair(THD *thd) { return TRUE; }
virtual int disable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
virtual int enable_indexes(uint mode) { return HA_ERR_WRONG_COMMAND; }
virtual int disable_indexes(key_map map, bool persist) { return HA_ERR_WRONG_COMMAND; }
virtual int enable_indexes(key_map map, bool persist) { return HA_ERR_WRONG_COMMAND; }
virtual int discard_or_import_tablespace(my_bool discard)
{ return (my_errno=HA_ERR_WRONG_COMMAND); }
virtual void drop_table(const char *name);

View File

@ -20401,7 +20401,7 @@ create_internal_tmp_table_from_heap(THD *thd, TABLE *table,
if (open_tmp_table(&new_table))
goto err1;
if (table->file->indexes_are_disabled())
new_table.file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
new_table.file->ha_disable_indexes(key_map(0), false);
table->file->ha_index_or_rnd_end();
if (table->file->ha_rnd_init_with_error(1))
DBUG_RETURN(1);

View File

@ -7955,14 +7955,28 @@ bool alter_table_manage_keys(TABLE *table, int indexes_were_disabled,
switch (keys_onoff) {
case Alter_info::ENABLE:
DEBUG_SYNC(table->in_use, "alter_table_enable_indexes");
error= table->file->ha_enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
error= table->file->ha_enable_indexes(key_map(table->s->keys), true);
break;
case Alter_info::LEAVE_AS_IS:
if (!indexes_were_disabled)
break;
/* fall through */
case Alter_info::DISABLE:
error= table->file->ha_disable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE);
{
key_map map= table->s->keys_in_use;
bool do_clear= false;
for (uint i=0; i < table->s->keys; i++)
{
if (!(table->s->key_info[i].flags & HA_NOSAME) &&
i != table->s->next_number_index)
{
map.clear_bit(i);
do_clear= true;
}
}
if (do_clear)
error= table->file->ha_disable_indexes(map, true);
}
}
if (unlikely(error))

View File

@ -485,7 +485,7 @@ bool select_unit_ext::disable_index_if_needed(SELECT_LEX *curr_sl)
!curr_sl->next_select()) )
{
is_index_enabled= false;
if (table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL))
if (table->file->ha_disable_indexes(key_map(0), false))
return false;
table->no_keyread=1;
return true;
@ -2086,7 +2086,7 @@ bool st_select_lex_unit::optimize()
/* re-enabling indexes for next subselect iteration */
if ((union_result->force_enable_index_if_needed() || union_distinct))
{
if(table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL))
if(table->file->ha_enable_indexes(key_map(table->s->keys), false))
DBUG_ASSERT(0);
else
table->no_keyread= 0;
@ -2186,7 +2186,7 @@ bool st_select_lex_unit::exec()
union_result->table && union_result->table->is_created())
{
union_result->table->file->ha_delete_all_rows();
union_result->table->file->ha_enable_indexes(HA_KEY_SWITCH_ALL);
union_result->table->file->ha_enable_indexes(key_map(table->s->keys), false);
}
}
@ -2253,7 +2253,7 @@ bool st_select_lex_unit::exec()
{
// This is UNION DISTINCT, so there should be a fake_select_lex
DBUG_ASSERT(fake_select_lex != NULL);
if (unlikely(table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL)))
if (table->file->ha_disable_indexes(key_map(0), false))
DBUG_RETURN(TRUE);
table->no_keyread=1;
}

View File

@ -9226,7 +9226,8 @@ bool TABLE::insert_all_rows_into_tmp_table(THD *thd,
}
if (file->indexes_are_disabled())
tmp_table->file->ha_disable_indexes(HA_KEY_SWITCH_ALL);
tmp_table->file->ha_disable_indexes(key_map(0), false);
file->ha_index_or_rnd_end();
if (unlikely(file->ha_rnd_init_with_error(1)))

View File

@ -440,31 +440,22 @@ int ha_heap::external_lock(THD *thd, int lock_type)
SYNOPSIS
disable_indexes()
mode mode of operation:
HA_KEY_SWITCH_NONUNIQ disable all non-unique keys
HA_KEY_SWITCH_ALL disable all keys
HA_KEY_SWITCH_NONUNIQ_SAVE dis. non-uni. and make persistent
HA_KEY_SWITCH_ALL_SAVE dis. all keys and make persistent
DESCRIPTION
Disable indexes and clear keys to use for scanning.
IMPLEMENTATION
HA_KEY_SWITCH_NONUNIQ is not implemented.
HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP.
HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP.
See handler::ha_disable_indexes()
RETURN
0 ok
HA_ERR_WRONG_COMMAND mode not implemented.
*/
int ha_heap::disable_indexes(uint mode)
int ha_heap::disable_indexes(key_map map, bool persist)
{
int error;
if (mode == HA_KEY_SWITCH_ALL)
if (!persist)
{
DBUG_ASSERT(map.is_clear_all());
if (!(error= heap_disable_indexes(file)))
set_keys_for_scanning();
}
@ -482,11 +473,6 @@ int ha_heap::disable_indexes(uint mode)
SYNOPSIS
enable_indexes()
mode mode of operation:
HA_KEY_SWITCH_NONUNIQ enable all non-unique keys
HA_KEY_SWITCH_ALL enable all keys
HA_KEY_SWITCH_NONUNIQ_SAVE en. non-uni. and make persistent
HA_KEY_SWITCH_ALL_SAVE en. all keys and make persistent
DESCRIPTION
Enable indexes and set keys to use for scanning.
@ -495,10 +481,7 @@ int ha_heap::disable_indexes(uint mode)
since the heap storage engine cannot repair the indexes.
To be sure, call handler::delete_all_rows() before.
IMPLEMENTATION
HA_KEY_SWITCH_NONUNIQ is not implemented.
HA_KEY_SWITCH_NONUNIQ_SAVE is not implemented with HEAP.
HA_KEY_SWITCH_ALL_SAVE is not implemented with HEAP.
See also handler::ha_enable_indexes()
RETURN
0 ok
@ -506,12 +489,13 @@ int ha_heap::disable_indexes(uint mode)
HA_ERR_WRONG_COMMAND mode not implemented.
*/
int ha_heap::enable_indexes(uint mode)
int ha_heap::enable_indexes(key_map map, bool persist)
{
int error;
if (mode == HA_KEY_SWITCH_ALL)
if (!persist)
{
DBUG_ASSERT(map.is_prefix(table->s->keys));
if (!(error= heap_enable_indexes(file)))
set_keys_for_scanning();
}

View File

@ -101,8 +101,8 @@ public:
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
int reset_auto_increment(ulonglong value);
int disable_indexes(uint mode);
int enable_indexes(uint mode);
int disable_indexes(key_map map, bool persist);
int enable_indexes(key_map map, bool persist);
int indexes_are_disabled(void);
ha_rows records_in_range(uint inx, const key_range *start_key,
const key_range *end_key, page_range *pages);

View File

@ -1924,40 +1924,45 @@ int ha_maria::preload_keys(THD * thd, HA_CHECK_OPT *check_opt)
SYNOPSIS
disable_indexes()
mode mode of operation:
HA_KEY_SWITCH_NONUNIQ disable all non-unique keys
HA_KEY_SWITCH_ALL disable all keys
HA_KEY_SWITCH_NONUNIQ_SAVE dis. non-uni. and make persistent
HA_KEY_SWITCH_ALL_SAVE dis. all keys and make persistent
IMPLEMENTATION
HA_KEY_SWITCH_NONUNIQ is not implemented.
HA_KEY_SWITCH_ALL_SAVE is not implemented.
DESCRIPTION
See handler::ha_disable_indexes()
RETURN
0 ok
HA_ERR_WRONG_COMMAND mode not implemented.
*/
int ha_maria::disable_indexes(uint mode)
int ha_maria::disable_indexes(key_map map, bool persist)
{
int error;
if (mode == HA_KEY_SWITCH_ALL)
if (!persist)
{
/* call a storage engine function to switch the key map */
DBUG_ASSERT(map.is_clear_all());
error= maria_disable_indexes(file);
}
else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
{
maria_extra(file, HA_EXTRA_NO_KEYS, 0);
info(HA_STATUS_CONST); // Read new key info
error= 0;
}
else
{
/* mode not implemented */
error= HA_ERR_WRONG_COMMAND;
/* auto-inc key cannot be disabled */
if (table->s->next_number_index < MAX_KEY)
DBUG_ASSERT(map.is_set(table->s->next_number_index));
/* unique keys cannot be disabled either */
for (uint i=0; i < table->s->keys; i++)
DBUG_ASSERT(!(table->key_info[i].flags & HA_NOSAME) || map.is_set(i));
ulonglong ullmap= map.to_ulonglong();
/* make sure auto-inc key is enabled even if it's > 64 */
if (map.length() > MARIA_KEYMAP_BITS &&
table->s->next_number_index < MAX_KEY)
maria_set_key_active(ullmap, table->s->next_number_index);
maria_extra(file, HA_EXTRA_NO_KEYS, &ullmap);
info(HA_STATUS_CONST); // Read new key info
error= 0;
}
return error;
}
@ -1968,21 +1973,14 @@ int ha_maria::disable_indexes(uint mode)
SYNOPSIS
enable_indexes()
mode mode of operation:
HA_KEY_SWITCH_NONUNIQ enable all non-unique keys
HA_KEY_SWITCH_ALL enable all keys
HA_KEY_SWITCH_NONUNIQ_SAVE en. non-uni. and make persistent
HA_KEY_SWITCH_ALL_SAVE en. all keys and make persistent
DESCRIPTION
Enable indexes, which might have been disabled by disable_index() before.
The modes without _SAVE work only if both data and indexes are empty,
since the MARIA repair would enable them persistently.
If persist=false, it works only if both data and indexes are empty,
since the Aria repair would enable them persistently.
To be sure in these cases, call handler::delete_all_rows() before.
IMPLEMENTATION
HA_KEY_SWITCH_NONUNIQ is not implemented.
HA_KEY_SWITCH_ALL_SAVE is not implemented.
See also handler::ha_enable_indexes()
RETURN
0 ok
@ -1991,18 +1989,19 @@ int ha_maria::disable_indexes(uint mode)
HA_ERR_WRONG_COMMAND mode not implemented.
*/
int ha_maria::enable_indexes(uint mode)
int ha_maria::enable_indexes(key_map map, bool persist)
{
int error;
ha_rows start_rows= file->state->records;
DBUG_PRINT("info", ("ha_maria::enable_indexes mode: %d", mode));
DBUG_PRINT("info", ("ha_maria::enable_indexes mode: %d", persist));
if (maria_is_all_keys_active(file->s->state.key_map, file->s->base.keys))
{
/* All indexes are enabled already. */
return 0;
}
if (mode == HA_KEY_SWITCH_ALL)
DBUG_ASSERT(map.is_prefix(table->s->keys));
if (!persist)
{
error= maria_enable_indexes(file);
/*
@ -2011,7 +2010,7 @@ int ha_maria::enable_indexes(uint mode)
but mode==HA_KEY_SWITCH_ALL forbids it.
*/
}
else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
else
{
THD *thd= table->in_use;
HA_CHECK *param= (HA_CHECK*) thd->alloc(sizeof *param);
@ -2076,11 +2075,6 @@ int ha_maria::enable_indexes(uint mode)
info(HA_STATUS_CONST);
thd_proc_info(thd, save_proc_info);
}
else
{
/* mode not implemented */
error= HA_ERR_WRONG_COMMAND;
}
DBUG_EXECUTE_IF("maria_flush_whole_log",
{
DBUG_PRINT("maria_flush_whole_log", ("now"));
@ -2292,7 +2286,7 @@ int ha_maria::end_bulk_insert()
}
if (!abort && can_enable_indexes)
if ((error= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE)))
if ((error= enable_indexes(key_map(table->s->keys), true)))
first_error= first_error ? first_error : error;
if (bulk_insert_single_undo != BULK_INSERT_NONE)

View File

@ -122,8 +122,8 @@ public:
int external_lock(THD * thd, int lock_type) override;
int start_stmt(THD *thd, thr_lock_type lock_type) override final;
int delete_all_rows(void) override final;
int disable_indexes(uint mode) override final;
int enable_indexes(uint mode) override final;
int disable_indexes(key_map map, bool persist) override final;
int enable_indexes(key_map map, bool persist) override final;
int indexes_are_disabled(void) override final;
void start_bulk_insert(ha_rows rows, uint flags) override final;
int end_bulk_insert() override final;

View File

@ -239,25 +239,17 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
break;
/* we're going to modify pieces of the state, stall Checkpoint */
mysql_mutex_lock(&share->intern_lock);
if (info->lock_type == F_UNLCK)
{
mysql_mutex_unlock(&share->intern_lock);
error= 1; /* Not possibly if not lock */
break;
}
mysql_mutex_lock(&share->intern_lock);
if (maria_is_any_key_active(share->state.key_map))
{
MARIA_KEYDEF *key= share->keyinfo;
uint i;
for (i =0 ; i < share->base.keys ; i++,key++)
{
if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1)
{
maria_clear_key_active(share->state.key_map, i);
info->update|= HA_STATE_CHANGED;
}
}
if (share->state.key_map != *(ulonglong*)extra_arg)
info->update|= HA_STATE_CHANGED;
share->state.key_map= *(ulonglong*)extra_arg;
if (!share->changed)
{

View File

@ -4337,9 +4337,9 @@ int ha_mroonga::wrapper_open(const char *name, int mode, uint open_options)
// TODO: implemented by "reindex" instead of "remove and recreate".
// Because "remove and recreate" invalidates opened indexes by
// other threads.
error = wrapper_disable_indexes_mroonga(HA_KEY_SWITCH_ALL);
error = wrapper_disable_indexes_mroonga(key_map(table->s->keys), false);
if (!error) {
error = wrapper_enable_indexes_mroonga(HA_KEY_SWITCH_ALL);
error = wrapper_enable_indexes_mroonga(key_map(table->s->keys), false);
}
}
}
@ -13625,197 +13625,184 @@ int ha_mroonga::generic_disable_index(int i, KEY *key_info)
DBUG_RETURN(error);
}
int ha_mroonga::wrapper_disable_indexes_mroonga(uint mode)
int ha_mroonga::wrapper_disable_indexes_mroonga(key_map map, bool persist)
{
int error = 0;
MRN_DBUG_ENTER_METHOD();
if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
uint i;
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (share->wrap_key_nr[i] < MAX_KEY) {
continue;
}
if (!grn_index_tables[i]) {
DBUG_PRINT("info", ("mroonga: keys are disabled already %u", i));
DBUG_RETURN(0);
}
uint i;
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (share->wrap_key_nr[i] < MAX_KEY) {
continue;
}
if (!grn_index_tables[i]) {
DBUG_PRINT("info", ("mroonga: keys are disabled already %u", i));
DBUG_RETURN(0);
}
}
KEY *key_info = table_share->key_info;
for (i = 0; i < table_share->keys; i++) {
if (!(key_info[i].flags & HA_FULLTEXT) &&
!mrn_is_geo_key(&key_info[i])) {
continue;
}
KEY *key_info = table_share->key_info;
for (i = 0; i < table_share->keys; i++) {
if (!(key_info[i].flags & HA_FULLTEXT) &&
!mrn_is_geo_key(&key_info[i])) {
continue;
}
int sub_error = generic_disable_index(i, key_info);
if (error != 0 && sub_error != 0) {
error = sub_error;
}
int sub_error = generic_disable_index(i, key_info);
if (error != 0 && sub_error != 0) {
error = sub_error;
}
} else {
error = HA_ERR_WRONG_COMMAND;
}
DBUG_RETURN(error);
}
int ha_mroonga::wrapper_disable_indexes(uint mode)
int ha_mroonga::wrapper_disable_indexes(key_map map, bool persist)
{
int error = 0;
MRN_DBUG_ENTER_METHOD();
MRN_SET_WRAP_SHARE_KEY(share, table->s);
MRN_SET_WRAP_TABLE_KEY(this, table);
error = wrap_handler->ha_disable_indexes(mode);
error = wrap_handler->ha_disable_indexes(map, persist);
MRN_SET_BASE_SHARE_KEY(share, table->s);
MRN_SET_BASE_TABLE_KEY(this, table);
if (error == HA_ERR_WRONG_COMMAND) {
error = 0;
}
if (!error) {
error = wrapper_disable_indexes_mroonga(mode);
error = wrapper_disable_indexes_mroonga(map, persist);
}
DBUG_RETURN(error);
}
int ha_mroonga::storage_disable_indexes(uint mode)
int ha_mroonga::storage_disable_indexes(key_map map, bool persist)
{
int error = 0;
MRN_DBUG_ENTER_METHOD();
if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
uint i;
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (!grn_index_tables[i]) {
DBUG_PRINT("info", ("mroonga: keys are disabled already %u", i));
DBUG_RETURN(0);
}
uint i;
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (!grn_index_tables[i]) {
DBUG_PRINT("info", ("mroonga: keys are disabled already %u", i));
DBUG_RETURN(0);
}
}
KEY *key_info = table_share->key_info;
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (map.is_set(i)) {
continue;
}
KEY *key_info = table_share->key_info;
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE &&
(key_info[i].flags & HA_NOSAME)) {
continue;
}
int sub_error = generic_disable_index(i, key_info);
if (error != 0 && sub_error != 0) {
error = sub_error;
}
int sub_error = generic_disable_index(i, key_info);
if (error != 0 && sub_error != 0) {
error = sub_error;
}
} else {
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
DBUG_RETURN(error);
}
int ha_mroonga::disable_indexes(uint mode)
int ha_mroonga::disable_indexes(key_map map, bool persist)
{
int error = 0;
MRN_DBUG_ENTER_METHOD();
if (share->wrapper_mode)
{
error = wrapper_disable_indexes(mode);
error = wrapper_disable_indexes(map, persist);
} else {
error = storage_disable_indexes(mode);
error = storage_disable_indexes(map, persist);
}
DBUG_RETURN(error);
}
int ha_mroonga::wrapper_enable_indexes_mroonga(uint mode)
int ha_mroonga::wrapper_enable_indexes_mroonga(key_map map, bool persist)
{
int error = 0;
MRN_DBUG_ENTER_METHOD();
if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
uint i, j;
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (share->wrap_key_nr[i] < MAX_KEY) {
continue;
}
if (!grn_index_columns[i]) {
break;
}
uint i, j;
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (i == table_share->keys) {
DBUG_PRINT("info", ("mroonga: keys are enabled already"));
DBUG_RETURN(0);
if (share->wrap_key_nr[i] < MAX_KEY) {
continue;
}
if (!grn_index_columns[i]) {
break;
}
}
if (i == table_share->keys) {
DBUG_PRINT("info", ("mroonga: keys are enabled already"));
DBUG_RETURN(0);
}
KEY *p_key_info = &table->key_info[table_share->primary_key];
KEY *key_info = table_share->key_info;
uint n_keys = table_share->keys;
MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys);
MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, n_keys);
bitmap_clear_all(table->read_set);
mrn_set_bitmap_by_key(table->read_set, p_key_info);
mrn::PathMapper mapper(share->table_name);
for (i = 0, j = 0; i < n_keys; i++) {
if (!(key_info[i].flags & HA_FULLTEXT) &&
!mrn_is_geo_key(&key_info[i])) {
j++;
continue;
}
KEY *p_key_info = &table->key_info[table_share->primary_key];
KEY *key_info = table_share->key_info;
uint n_keys = table_share->keys;
MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys);
MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, n_keys);
bitmap_clear_all(table->read_set);
mrn_set_bitmap_by_key(table->read_set, p_key_info);
mrn::PathMapper mapper(share->table_name);
for (i = 0, j = 0; i < n_keys; i++) {
if (!(key_info[i].flags & HA_FULLTEXT) &&
!mrn_is_geo_key(&key_info[i])) {
j++;
continue;
}
if ((error = mrn_add_index_param(share, &key_info[i], i)))
{
break;
}
index_tables[i] = NULL;
index_columns[i] = NULL;
if (!grn_index_columns[i]) {
if (
(key_info[i].flags & HA_FULLTEXT) &&
(error = wrapper_create_index_fulltext(mapper.table_name(),
i, &key_info[i],
index_tables, index_columns,
share))
) {
break;
} else if (
mrn_is_geo_key(&key_info[i]) &&
(error = wrapper_create_index_geo(mapper.table_name(),
i, &key_info[i],
index_tables, index_columns,
share))
) {
break;
}
grn_index_columns[i] = index_columns[i];
}
mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
}
if (!error && i > j)
if ((error = mrn_add_index_param(share, &key_info[i], i)))
{
error = wrapper_fill_indexes(ha_thd(), table->key_info, index_columns,
n_keys);
break;
}
bitmap_set_all(table->read_set);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
} else {
error = HA_ERR_WRONG_COMMAND;
index_tables[i] = NULL;
index_columns[i] = NULL;
if (!grn_index_columns[i]) {
if (
(key_info[i].flags & HA_FULLTEXT) &&
(error = wrapper_create_index_fulltext(mapper.table_name(),
i, &key_info[i],
index_tables, index_columns,
share))
) {
break;
} else if (
mrn_is_geo_key(&key_info[i]) &&
(error = wrapper_create_index_geo(mapper.table_name(),
i, &key_info[i],
index_tables, index_columns,
share))
) {
break;
}
grn_index_columns[i] = index_columns[i];
}
mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
}
if (!error && i > j)
{
error = wrapper_fill_indexes(ha_thd(), table->key_info, index_columns,
n_keys);
}
bitmap_set_all(table->read_set);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
DBUG_RETURN(error);
}
int ha_mroonga::wrapper_enable_indexes(uint mode)
int ha_mroonga::wrapper_enable_indexes(key_map map, bool persist)
{
int error = 0;
MRN_DBUG_ENTER_METHOD();
int mroonga_error = wrapper_enable_indexes_mroonga(mode);
int mroonga_error = wrapper_enable_indexes_mroonga(map, persist);
MRN_SET_WRAP_SHARE_KEY(share, table->s);
MRN_SET_WRAP_TABLE_KEY(this, table);
error = wrap_handler->ha_enable_indexes(mode);
error = wrap_handler->ha_enable_indexes(map, persist);
MRN_SET_BASE_SHARE_KEY(share, table->s);
MRN_SET_BASE_TABLE_KEY(this, table);
if (error == HA_ERR_WRONG_COMMAND) {
@ -13824,95 +13811,86 @@ int ha_mroonga::wrapper_enable_indexes(uint mode)
DBUG_RETURN(error);
}
int ha_mroonga::storage_enable_indexes(uint mode)
int ha_mroonga::storage_enable_indexes(key_map map, bool persist)
{
int error = 0;
uint n_keys = table_share->keys;
MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys);
MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, n_keys);
bool have_multiple_column_index = false;
bool skip_unique_key = (mode == HA_KEY_SWITCH_NONUNIQ_SAVE);
MRN_DBUG_ENTER_METHOD();
if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
uint i;
for (i = 0; i < table_share->keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (!grn_index_columns[i]) {
break;
}
uint i;
for (i = 0; i < n_keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (i == table_share->keys) {
DBUG_PRINT("info", ("mroonga: keys are enabled already"));
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
DBUG_RETURN(0);
if (!grn_index_columns[i]) {
break;
}
}
if (i == n_keys) {
DBUG_PRINT("info", ("mroonga: keys are enabled already"));
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
DBUG_RETURN(0);
}
KEY *key_info = table->key_info;
bitmap_clear_all(table->read_set);
mrn::PathMapper mapper(share->table_name);
for (; i < n_keys; i++) {
if (!map.is_set(i)) {
continue;
}
KEY *key_info = table->key_info;
bitmap_clear_all(table->read_set);
mrn::PathMapper mapper(share->table_name);
for (i = 0; i < n_keys; i++) {
if (i == table->s->primary_key) {
continue;
}
if (skip_unique_key && (key_info[i].flags & HA_NOSAME)) {
continue;
}
if ((error = mrn_add_index_param(share, &key_info[i], i)))
if ((error = mrn_add_index_param(share, &key_info[i], i)))
{
break;
}
index_tables[i] = NULL;
if (!grn_index_columns[i]) {
if ((error = storage_create_index(table, mapper.table_name(), grn_table,
share, &key_info[i], index_tables,
index_columns, i)))
{
break;
}
index_tables[i] = NULL;
if (!grn_index_columns[i]) {
if ((error = storage_create_index(table, mapper.table_name(), grn_table,
share, &key_info[i], index_tables,
index_columns, i)))
{
break;
}
if (
KEY_N_KEY_PARTS(&(key_info[i])) != 1 &&
!(key_info[i].flags & HA_FULLTEXT)
) {
mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
have_multiple_column_index = true;
}
grn_index_tables[i] = index_tables[i];
grn_index_columns[i] = index_columns[i];
} else {
index_columns[i] = NULL;
if (
KEY_N_KEY_PARTS(&(key_info[i])) != 1 &&
!(key_info[i].flags & HA_FULLTEXT)
) {
mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
have_multiple_column_index = true;
}
grn_index_tables[i] = index_tables[i];
grn_index_columns[i] = index_columns[i];
} else {
index_columns[i] = NULL;
}
if (!error && have_multiple_column_index)
{
error = storage_add_index_multiple_columns(key_info, n_keys,
index_tables,
index_columns,
skip_unique_key);
}
bitmap_set_all(table->read_set);
} else {
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
if (!error && have_multiple_column_index)
{
bool skip_unique_key= !table->s->keys_in_use.is_clear_all();
error = storage_add_index_multiple_columns(key_info, n_keys,
index_tables,
index_columns,
skip_unique_key);
}
bitmap_set_all(table->read_set);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
DBUG_RETURN(error);
}
int ha_mroonga::enable_indexes(uint mode)
int ha_mroonga::enable_indexes(key_map map, bool persist)
{
int error = 0;
MRN_DBUG_ENTER_METHOD();
share->disable_keys = false;
if (share->wrapper_mode)
{
error = wrapper_enable_indexes(mode);
error = wrapper_enable_indexes(map, persist);
} else {
error = storage_enable_indexes(mode);
error = storage_enable_indexes(map, persist);
}
DBUG_RETURN(error);
}

View File

@ -542,8 +542,8 @@ public:
bool is_crashed() const mrn_override;
bool auto_repair(int error) const mrn_override;
bool auto_repair() const;
int disable_indexes(uint mode) mrn_override;
int enable_indexes(uint mode) mrn_override;
int disable_indexes(key_map map, bool persist) mrn_override;
int enable_indexes(key_map map, bool persist) mrn_override;
int check(THD* thd, HA_CHECK_OPT* check_opt) mrn_override;
int repair(THD* thd, HA_CHECK_OPT* check_opt) mrn_override;
bool check_and_repair(THD *thd) mrn_override;
@ -1140,12 +1140,12 @@ private:
bool wrapper_auto_repair(int error) const;
bool storage_auto_repair(int error) const;
int generic_disable_index(int i, KEY *key_info);
int wrapper_disable_indexes_mroonga(uint mode);
int wrapper_disable_indexes(uint mode);
int storage_disable_indexes(uint mode);
int wrapper_enable_indexes_mroonga(uint mode);
int wrapper_enable_indexes(uint mode);
int storage_enable_indexes(uint mode);
int wrapper_disable_indexes_mroonga(key_map map, bool persist);
int wrapper_disable_indexes(key_map map, bool persist);
int storage_disable_indexes(key_map map, bool persist);
int wrapper_enable_indexes_mroonga(key_map map, bool persist);
int wrapper_enable_indexes(key_map map, bool persist);
int storage_enable_indexes(key_map map, bool persist);
int wrapper_check(THD* thd, HA_CHECK_OPT* check_opt);
int storage_check(THD* thd, HA_CHECK_OPT* check_opt);
int wrapper_fill_indexes(THD *thd, KEY *key_info,

View File

@ -1569,40 +1569,37 @@ int ha_myisam::preload_keys(THD* thd, HA_CHECK_OPT *check_opt)
SYNOPSIS
disable_indexes()
mode mode of operation:
HA_KEY_SWITCH_NONUNIQ disable all non-unique keys
HA_KEY_SWITCH_ALL disable all keys
HA_KEY_SWITCH_NONUNIQ_SAVE dis. non-uni. and make persistent
HA_KEY_SWITCH_ALL_SAVE dis. all keys and make persistent
IMPLEMENTATION
HA_KEY_SWITCH_NONUNIQ is not implemented.
HA_KEY_SWITCH_ALL_SAVE is not implemented.
DESCRIPTION
See handler::ha_disable_indexes()
RETURN
0 ok
HA_ERR_WRONG_COMMAND mode not implemented.
*/
int ha_myisam::disable_indexes(uint mode)
int ha_myisam::disable_indexes(key_map map, bool persist)
{
int error;
if (mode == HA_KEY_SWITCH_ALL)
if (!persist)
{
/* call a storage engine function to switch the key map */
DBUG_ASSERT(map.is_clear_all());
error= mi_disable_indexes(file);
}
else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
{
mi_extra(file, HA_EXTRA_NO_KEYS, 0);
info(HA_STATUS_CONST); // Read new key info
error= 0;
}
else
{
/* mode not implemented */
error= HA_ERR_WRONG_COMMAND;
ulonglong ullmap= map.to_ulonglong();
/* make sure auto-inc key is enabled even if it's > 64 */
if (map.length() > MI_KEYMAP_BITS &&
table->s->next_number_index < MAX_KEY)
mi_set_key_active(ullmap, table->s->next_number_index);
mi_extra(file, HA_EXTRA_NO_KEYS, &ullmap);
info(HA_STATUS_CONST); // Read new key info
error= 0;
}
return error;
}
@ -1613,21 +1610,14 @@ int ha_myisam::disable_indexes(uint mode)
SYNOPSIS
enable_indexes()
mode mode of operation:
HA_KEY_SWITCH_NONUNIQ enable all non-unique keys
HA_KEY_SWITCH_ALL enable all keys
HA_KEY_SWITCH_NONUNIQ_SAVE en. non-uni. and make persistent
HA_KEY_SWITCH_ALL_SAVE en. all keys and make persistent
DESCRIPTION
Enable indexes, which might have been disabled by disable_index() before.
The modes without _SAVE work only if both data and indexes are empty,
If persist=false, it works only if both data and indexes are empty,
since the MyISAM repair would enable them persistently.
To be sure in these cases, call handler::delete_all_rows() before.
IMPLEMENTATION
HA_KEY_SWITCH_NONUNIQ is not implemented.
HA_KEY_SWITCH_ALL_SAVE is not implemented.
See also handler::ha_enable_indexes()
RETURN
0 ok
@ -1636,7 +1626,7 @@ int ha_myisam::disable_indexes(uint mode)
HA_ERR_WRONG_COMMAND mode not implemented.
*/
int ha_myisam::enable_indexes(uint mode)
int ha_myisam::enable_indexes(key_map map, bool persist)
{
int error;
DBUG_ENTER("ha_myisam::enable_indexes");
@ -1650,7 +1640,8 @@ int ha_myisam::enable_indexes(uint mode)
DBUG_RETURN(0);
}
if (mode == HA_KEY_SWITCH_ALL)
DBUG_ASSERT(map.is_prefix(table->s->keys));
if (!persist)
{
error= mi_enable_indexes(file);
/*
@ -1659,7 +1650,7 @@ int ha_myisam::enable_indexes(uint mode)
but mode==HA_KEY_SWITCH_ALL forbids it.
*/
}
else if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE)
else
{
THD *thd= table->in_use;
int was_error= thd->is_error();
@ -1719,11 +1710,6 @@ int ha_myisam::enable_indexes(uint mode)
restore_vcos_after_repair();
}
else
{
/* mode not implemented */
error= HA_ERR_WRONG_COMMAND;
}
DBUG_RETURN(error);
}
@ -1886,7 +1872,7 @@ int ha_myisam::end_bulk_insert()
setting the indexes as active and trying to recreate them.
*/
if (((first_error= enable_indexes(HA_KEY_SWITCH_NONUNIQ_SAVE)) != 0) &&
if (((first_error= enable_indexes(key_map(table->s->keys), true))) &&
table->in_use->killed)
{
delete_all_rows();

View File

@ -109,8 +109,8 @@ class ha_myisam final : public handler
int external_lock(THD *thd, int lock_type);
int delete_all_rows(void);
int reset_auto_increment(ulonglong value);
int disable_indexes(uint mode);
int enable_indexes(uint mode);
int disable_indexes(key_map map, bool persist);
int enable_indexes(key_map map, bool persist);
int indexes_are_disabled(void);
void start_bulk_insert(ha_rows rows, uint flags);
int end_bulk_insert();

View File

@ -225,16 +225,9 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
}
if (mi_is_any_key_active(share->state.key_map))
{
MI_KEYDEF *key=share->keyinfo;
uint i;
for (i=0 ; i < share->base.keys ; i++,key++)
{
if (!(key->flag & HA_NOSAME) && info->s->base.auto_key != i+1)
{
mi_clear_key_active(share->state.key_map, i);
info->update|= HA_STATE_CHANGED;
}
}
if (share->state.key_map != *(ulonglong*)extra_arg)
info->update|= HA_STATE_CHANGED;
share->state.key_map= *(ulonglong*)extra_arg;
if (!share->changed)
{

View File

@ -11774,27 +11774,35 @@ bool ha_spider::auto_repair() const
}
int ha_spider::disable_indexes(
uint mode
key_map map, bool persist
) {
int error_num;
backup_error_status();
DBUG_ENTER("ha_spider::disable_indexes");
DBUG_PRINT("info",("spider this=%p", this));
if ((error_num = spider_db_disable_keys(this)))
DBUG_RETURN(check_error_mode(error_num));
DBUG_RETURN(0);
if (persist)
{
if ((error_num = spider_db_disable_keys(this)))
DBUG_RETURN(check_error_mode(error_num));
DBUG_RETURN(0);
}
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}
int ha_spider::enable_indexes(
uint mode
key_map map, bool persist
) {
int error_num;
backup_error_status();
DBUG_ENTER("ha_spider::enable_indexes");
DBUG_PRINT("info",("spider this=%p", this));
if ((error_num = spider_db_enable_keys(this)))
DBUG_RETURN(check_error_mode(error_num));
DBUG_RETURN(0);
if (persist)
{
if ((error_num = spider_db_enable_keys(this)))
DBUG_RETURN(check_error_mode(error_num));
DBUG_RETURN(0);
}
DBUG_RETURN(HA_ERR_WRONG_COMMAND);
}

View File

@ -791,10 +791,10 @@ public:
bool auto_repair() const;
#endif
int disable_indexes(
uint mode
key_map map, bool persist
);
int enable_indexes(
uint mode
key_map map, bool persist
);
int check(
THD* thd,