Loading include/my_sys.h +2 −0 Original line number Diff line number Diff line Loading @@ -879,6 +879,8 @@ extern CHARSET_INFO *get_charset(uint cs_number, myf flags); extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags); extern CHARSET_INFO *get_charset_by_csname(const char *cs_name, uint cs_flags, myf my_flags); extern CHARSET_INFO *get_compatible_charset_with_ctype(CHARSET_INFO *original_cs); extern void free_charsets(void); extern char *get_charsets_dir(char *buf); extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2); Loading myisam/ft_parser.c +1 −1 Original line number Diff line number Diff line Loading @@ -188,7 +188,7 @@ byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, const byte *end, do { for (;; doc+= mbl) for (;; doc+= (mbl ? mbl : 1)) { if (doc >= end) DBUG_RETURN(0); if (true_word_char(cs, *doc)) break; Loading myisam/mi_check.c +167 −57 Original line number Diff line number Diff line Loading @@ -1375,6 +1375,139 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) } /* 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; 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 */ /* Save new datafile-name in temp_filename */ Loading @@ -1382,7 +1515,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, my_string name, int rep_quick) { int error,got_error; uint i; ha_rows start_records,new_header_length; my_off_t del; File new_file; Loading Loading @@ -1486,25 +1618,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); /* 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 ; 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. */ /* This function always recreates all enabled indexes. */ if (param->testflag & T_CREATE_MISSING_KEYS) mi_set_all_keys_active(share->state.key_map, share->base.keys); info->state->key_file_length=share->base.keystart; mi_drop_all_indexes(param, info, TRUE); lock_memory(param); /* Everything is alloced */ Loading Loading @@ -2105,8 +2222,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ulong *rec_per_key_part; char llbuff[22]; SORT_INFO sort_info; ulonglong key_map=share->state.key_map; ulonglong key_map; DBUG_ENTER("mi_repair_by_sort"); LINT_INIT(key_map); start_records=info->state->records; got_error=1; Loading Loading @@ -2179,25 +2297,14 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, } info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); if (!(param->testflag & T_CREATE_MISSING_KEYS)) { /* Flush key cache for this file if we are calling this outside myisamchk */ 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 ; i++) share->state.key_del[i]= HA_OFFSET_ERROR; info->state->key_file_length=share->base.keystart; } else /* Optionally drop indexes and optionally modify the key_map. */ mi_drop_all_indexes(param, info, FALSE); key_map= share->state.key_map; if (param->testflag & T_CREATE_MISSING_KEYS) { if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) goto err; key_map= ~key_map; /* Create the missing keys */ /* Invert the copied key_map to recreate all disabled indexes. */ key_map= ~key_map; } sort_info.info=info; Loading Loading @@ -2240,6 +2347,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, sort_param.read_cache=param->read_cache; sort_param.keyinfo=share->keyinfo+sort_param.key; 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)) { /* Remember old statistics for key */ Loading @@ -2247,6 +2358,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, (char*) (share->state.rec_per_key_part + (uint) (rec_per_key_part - param->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; } Loading Loading @@ -2302,8 +2415,11 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, if (param->testflag & T_STATISTICS) update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique, 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); DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key)); if (sort_param.fix_datafile) { Loading Loading @@ -2504,9 +2620,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, IO_CACHE new_data_cache; /* For non-quick repair. */ IO_CACHE_SHARE io_share; SORT_INFO sort_info; ulonglong key_map=share->state.key_map; ulonglong key_map; pthread_attr_t thr_attr; DBUG_ENTER("mi_repair_parallel"); LINT_INIT(key_map); start_records=info->state->records; got_error=1; Loading Loading @@ -2608,25 +2725,14 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, } info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); if (!(param->testflag & T_CREATE_MISSING_KEYS)) { /* Flush key cache for this file if we are calling this outside myisamchk */ 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 ; i++) share->state.key_del[i]= HA_OFFSET_ERROR; info->state->key_file_length=share->base.keystart; } else /* Optionally drop indexes and optionally modify the key_map. */ mi_drop_all_indexes(param, info, FALSE); key_map= share->state.key_map; if (param->testflag & T_CREATE_MISSING_KEYS) { if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) goto err; key_map= ~key_map; /* Create the missing keys */ /* Invert the copied key_map to recreate all disabled indexes. */ key_map= ~key_map; } sort_info.info=info; Loading Loading @@ -2682,6 +2788,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, sort_param[i].key=key; sort_param[i].keyinfo=share->keyinfo+key; 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)) { /* Remember old statistics for key */ Loading mysql-test/include/gis_keys.inc +8 −8 Original line number Diff line number Diff line Loading @@ -13,20 +13,20 @@ CREATE TABLE t2 (p POINT, INDEX(p)); INSERT INTO t1 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)'); -- with index, returns 1 as expected -- EXPLAIN shows that the index is not used though -- due to the "most rows covered anyway, so a scan is more effective" rule # with index, returns 1 as expected # EXPLAIN shows that the index is not used though # due to the "most rows covered anyway, so a scan is more effective" rule EXPLAIN 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 -- the "most rows covered" rule doesn't kick in anymore -- now EXPLAIN shows the index used on the table # adding another row to the table so that # the "most rows covered" rule doesn't kick in anymore # 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 t2 VALUES (POINTFROMTEXT('POINT(1 2)')); EXPLAIN Loading mysql-test/r/csv.result +42 −0 Original line number Diff line number Diff line Loading @@ -5029,4 +5029,46 @@ F7 FE LATIN SMALL LETTER THORN FF LATIN SMALL LETTER Y WITH DIAERESIS drop table t1; create table t1(a datetime) engine=csv; insert into t1 values(); select * from t1; a 0000-00-00 00:00:00 drop table t1; create table t1(a set('foo','bar')) engine=csv; insert into t1 values(); select * from t1; a drop table t1; create table t1(a varchar(32)) engine=csv; insert into t1 values(); select * from t1; a drop table t1; create table t1(a int) engine=csv; insert into t1 values(); select * from t1; a 0 drop table t1; create table t1(a blob) engine=csv; insert into t1 values(); select * from t1; a drop table t1; create table t1(a bit(1)) engine=csv; insert into t1 values(); select BIN(a) from t1; BIN(a) 0 drop table t1; create table t1(a enum('foo','bar') default 'foo') engine=csv; insert into t1 values(); select * from t1; a foo drop table t1; End of 5.0 tests Loading
include/my_sys.h +2 −0 Original line number Diff line number Diff line Loading @@ -879,6 +879,8 @@ extern CHARSET_INFO *get_charset(uint cs_number, myf flags); extern CHARSET_INFO *get_charset_by_name(const char *cs_name, myf flags); extern CHARSET_INFO *get_charset_by_csname(const char *cs_name, uint cs_flags, myf my_flags); extern CHARSET_INFO *get_compatible_charset_with_ctype(CHARSET_INFO *original_cs); extern void free_charsets(void); extern char *get_charsets_dir(char *buf); extern my_bool my_charset_same(CHARSET_INFO *cs1, CHARSET_INFO *cs2); Loading
myisam/ft_parser.c +1 −1 Original line number Diff line number Diff line Loading @@ -188,7 +188,7 @@ byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, const byte *end, do { for (;; doc+= mbl) for (;; doc+= (mbl ? mbl : 1)) { if (doc >= end) DBUG_RETURN(0); if (true_word_char(cs, *doc)) break; Loading
myisam/mi_check.c +167 −57 Original line number Diff line number Diff line Loading @@ -1375,6 +1375,139 @@ int chk_data_link(MI_CHECK *param, MI_INFO *info,int extend) } /* 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; 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 */ /* Save new datafile-name in temp_filename */ Loading @@ -1382,7 +1515,6 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, my_string name, int rep_quick) { int error,got_error; uint i; ha_rows start_records,new_header_length; my_off_t del; File new_file; Loading Loading @@ -1486,25 +1618,10 @@ int mi_repair(MI_CHECK *param, register MI_INFO *info, info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); /* 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 ; 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. */ /* This function always recreates all enabled indexes. */ if (param->testflag & T_CREATE_MISSING_KEYS) mi_set_all_keys_active(share->state.key_map, share->base.keys); info->state->key_file_length=share->base.keystart; mi_drop_all_indexes(param, info, TRUE); lock_memory(param); /* Everything is alloced */ Loading Loading @@ -2105,8 +2222,9 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, ulong *rec_per_key_part; char llbuff[22]; SORT_INFO sort_info; ulonglong key_map=share->state.key_map; ulonglong key_map; DBUG_ENTER("mi_repair_by_sort"); LINT_INIT(key_map); start_records=info->state->records; got_error=1; Loading Loading @@ -2179,25 +2297,14 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, } info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); if (!(param->testflag & T_CREATE_MISSING_KEYS)) { /* Flush key cache for this file if we are calling this outside myisamchk */ 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 ; i++) share->state.key_del[i]= HA_OFFSET_ERROR; info->state->key_file_length=share->base.keystart; } else /* Optionally drop indexes and optionally modify the key_map. */ mi_drop_all_indexes(param, info, FALSE); key_map= share->state.key_map; if (param->testflag & T_CREATE_MISSING_KEYS) { if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) goto err; key_map= ~key_map; /* Create the missing keys */ /* Invert the copied key_map to recreate all disabled indexes. */ key_map= ~key_map; } sort_info.info=info; Loading Loading @@ -2240,6 +2347,10 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, sort_param.read_cache=param->read_cache; sort_param.keyinfo=share->keyinfo+sort_param.key; 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)) { /* Remember old statistics for key */ Loading @@ -2247,6 +2358,8 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, (char*) (share->state.rec_per_key_part + (uint) (rec_per_key_part - param->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; } Loading Loading @@ -2302,8 +2415,11 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info, if (param->testflag & T_STATISTICS) update_key_parts(sort_param.keyinfo, rec_per_key_part, sort_param.unique, 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); DBUG_PRINT("repair", ("set enabled index #: %u", sort_param.key)); if (sort_param.fix_datafile) { Loading Loading @@ -2504,9 +2620,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, IO_CACHE new_data_cache; /* For non-quick repair. */ IO_CACHE_SHARE io_share; SORT_INFO sort_info; ulonglong key_map=share->state.key_map; ulonglong key_map; pthread_attr_t thr_attr; DBUG_ENTER("mi_repair_parallel"); LINT_INIT(key_map); start_records=info->state->records; got_error=1; Loading Loading @@ -2608,25 +2725,14 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, } info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED); if (!(param->testflag & T_CREATE_MISSING_KEYS)) { /* Flush key cache for this file if we are calling this outside myisamchk */ 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 ; i++) share->state.key_del[i]= HA_OFFSET_ERROR; info->state->key_file_length=share->base.keystart; } else /* Optionally drop indexes and optionally modify the key_map. */ mi_drop_all_indexes(param, info, FALSE); key_map= share->state.key_map; if (param->testflag & T_CREATE_MISSING_KEYS) { if (flush_key_blocks(share->key_cache,share->kfile, FLUSH_FORCE_WRITE)) goto err; key_map= ~key_map; /* Create the missing keys */ /* Invert the copied key_map to recreate all disabled indexes. */ key_map= ~key_map; } sort_info.info=info; Loading Loading @@ -2682,6 +2788,10 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info, sort_param[i].key=key; sort_param[i].keyinfo=share->keyinfo+key; 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)) { /* Remember old statistics for key */ Loading
mysql-test/include/gis_keys.inc +8 −8 Original line number Diff line number Diff line Loading @@ -13,20 +13,20 @@ CREATE TABLE t2 (p POINT, INDEX(p)); INSERT INTO t1 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)'); -- with index, returns 1 as expected -- EXPLAIN shows that the index is not used though -- due to the "most rows covered anyway, so a scan is more effective" rule # with index, returns 1 as expected # EXPLAIN shows that the index is not used though # due to the "most rows covered anyway, so a scan is more effective" rule EXPLAIN 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 -- the "most rows covered" rule doesn't kick in anymore -- now EXPLAIN shows the index used on the table # adding another row to the table so that # the "most rows covered" rule doesn't kick in anymore # 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 t2 VALUES (POINTFROMTEXT('POINT(1 2)')); EXPLAIN Loading
mysql-test/r/csv.result +42 −0 Original line number Diff line number Diff line Loading @@ -5029,4 +5029,46 @@ F7 FE LATIN SMALL LETTER THORN FF LATIN SMALL LETTER Y WITH DIAERESIS drop table t1; create table t1(a datetime) engine=csv; insert into t1 values(); select * from t1; a 0000-00-00 00:00:00 drop table t1; create table t1(a set('foo','bar')) engine=csv; insert into t1 values(); select * from t1; a drop table t1; create table t1(a varchar(32)) engine=csv; insert into t1 values(); select * from t1; a drop table t1; create table t1(a int) engine=csv; insert into t1 values(); select * from t1; a 0 drop table t1; create table t1(a blob) engine=csv; insert into t1 values(); select * from t1; a drop table t1; create table t1(a bit(1)) engine=csv; insert into t1 values(); select BIN(a) from t1; BIN(a) 0 drop table t1; create table t1(a enum('foo','bar') default 'foo') engine=csv; insert into t1 values(); select * from t1; a foo drop table t1; End of 5.0 tests