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