summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorunknown <guilhem@gbichot4.local>2007-07-27 12:06:39 +0200
committerunknown <guilhem@gbichot4.local>2007-07-27 12:06:39 +0200
commita3d2ae4648d739a7ec7820e22c05373fde65b770 (patch)
tree1c7c807fa27f54c3bc16968151fcc79e1f8b4667 /storage
parent662002fc8f6301ec78d2eca14c5f991212d4f67f (diff)
downloadmariadb-git-a3d2ae4648d739a7ec7820e22c05373fde65b770.tar.gz
merging MyISAM changes into Maria (not done in 5.1->maria merge of
Jul 7th). "maria.test" and "ps_maria.test" still fail; "ma_test_all" starts failing (MyISAM has the same issue see BUG#30094). include/maria.h: merging MyISAM changes into Maria mysys/mf_keycache.c: mi_test_all showed "floating point exception", this was already fixed in the latest 5.1, importing fix. sql/item_xmlfunc.cc: compiler warning (already fixed in latest 5.1) storage/maria/ha_maria.cc: merging MyISAM changes into Maria. See #ifdef ASK_MONTY. storage/maria/ha_maria.h: merging MyISAM changes into Maria storage/maria/ma_cache.c: merging MyISAM changes into Maria storage/maria/ma_check.c: merging MyISAM changes into Maria storage/maria/ma_create.c: merging MyISAM changes into Maria storage/maria/ma_dynrec.c: merging MyISAM changes into Maria storage/maria/ma_extra.c: merging MyISAM changes into Maria storage/maria/ma_ft_boolean_search.c: merging MyISAM changes into Maria storage/maria/ma_ft_nlq_search.c: merging MyISAM changes into Maria storage/maria/ma_info.c: merging MyISAM changes into Maria storage/maria/ma_key.c: merging MyISAM changes into Maria storage/maria/ma_loghandler.c: compiler warning (part->length is size_t) storage/maria/ma_open.c: merging MyISAM changes into Maria storage/maria/ma_preload.c: merging MyISAM changes into Maria storage/maria/ma_range.c: merging MyISAM changes into Maria storage/maria/ma_rkey.c: merging MyISAM changes into Maria storage/maria/ma_rt_index.c: merging MyISAM changes into Maria storage/maria/ma_rt_key.c: merging MyISAM changes into Maria storage/maria/ma_rt_split.c: merging MyISAM changes into Maria storage/maria/ma_search.c: merging MyISAM changes into Maria storage/maria/ma_sort.c: merging MyISAM changes into Maria storage/maria/maria_def.h: merging MyISAM changes into Maria
Diffstat (limited to 'storage')
-rw-r--r--storage/maria/ha_maria.cc198
-rw-r--r--storage/maria/ha_maria.h13
-rw-r--r--storage/maria/ma_cache.c4
-rw-r--r--storage/maria/ma_check.c16
-rw-r--r--storage/maria/ma_create.c26
-rw-r--r--storage/maria/ma_dynrec.c14
-rw-r--r--storage/maria/ma_extra.c10
-rw-r--r--storage/maria/ma_ft_boolean_search.c51
-rw-r--r--storage/maria/ma_ft_nlq_search.c8
-rw-r--r--storage/maria/ma_info.c6
-rw-r--r--storage/maria/ma_key.c64
-rw-r--r--storage/maria/ma_loghandler.c4
-rw-r--r--storage/maria/ma_open.c48
-rw-r--r--storage/maria/ma_preload.c13
-rw-r--r--storage/maria/ma_range.c63
-rw-r--r--storage/maria/ma_rkey.c15
-rw-r--r--storage/maria/ma_rt_index.c107
-rw-r--r--storage/maria/ma_rt_key.c18
-rw-r--r--storage/maria/ma_rt_split.c12
-rw-r--r--storage/maria/ma_search.c42
-rw-r--r--storage/maria/ma_sort.c17
-rw-r--r--storage/maria/maria_def.h5
22 files changed, 499 insertions, 255 deletions
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index 05b79d6f10c..d0888278cca 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -114,6 +114,14 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
}
length= (uint) (strxmov(name, param->db_name, ".", param->table_name,
NullS) - name);
+ /*
+ TODO: switch from protocol to push_warning here. The main reason we didn't
+ it yet is parallel repair. Due to following trace:
+ ma_check_print_msg/push_warning/sql_alloc/my_pthread_getspecific_ptr.
+
+ Also we likely need to lock mutex here (in both cases with protocol and
+ push_warning).
+ */
protocol->prepare_for_resend();
protocol->store(name, length, system_charset_info);
protocol->store(param->op_name, system_charset_info);
@@ -353,10 +361,11 @@ int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out,
0 - Equal definitions.
1 - Different definitions.
- NOTES
- This is currently not used. In MyISAM the corresponding function
- (myisam_check_definition()) is used only by MERGE tables
- (in ha_myisammrg.cc).
+ TODO
+ - compare FULLTEXT keys;
+ - compare SPATIAL keys;
+ - compare FIELD_SKIP_ZERO which is converted to FIELD_NORMAL correctly
+ (should be corretly detected in table2maria).
*/
int maria_check_definition(MARIA_KEYDEF *t1_keyinfo,
MARIA_COLUMNDEF *t1_recinfo,
@@ -383,6 +392,28 @@ int maria_check_definition(MARIA_KEYDEF *t1_keyinfo,
{
HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
+ if (t1_keyinfo[i].flag & HA_FULLTEXT && t2_keyinfo[i].flag & HA_FULLTEXT)
+ continue;
+ else if (t1_keyinfo[i].flag & HA_FULLTEXT ||
+ t2_keyinfo[i].flag & HA_FULLTEXT)
+ {
+ DBUG_PRINT("error", ("Key %d has different definition", i));
+ DBUG_PRINT("error", ("t1_fulltext= %d, t2_fulltext=%d",
+ test(t1_keyinfo[i].flag & HA_FULLTEXT),
+ test(t2_keyinfo[i].flag & HA_FULLTEXT)));
+ DBUG_RETURN(1);
+ }
+ if (t1_keyinfo[i].flag & HA_SPATIAL && t2_keyinfo[i].flag & HA_SPATIAL)
+ continue;
+ else if (t1_keyinfo[i].flag & HA_SPATIAL ||
+ t2_keyinfo[i].flag & HA_SPATIAL)
+ {
+ DBUG_PRINT("error", ("Key %d has different definition", i));
+ DBUG_PRINT("error", ("t1_spatial= %d, t2_spatial=%d",
+ test(t1_keyinfo[i].flag & HA_SPATIAL),
+ test(t2_keyinfo[i].flag & HA_SPATIAL)));
+ DBUG_RETURN(1);
+ }
if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs ||
t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg)
{
@@ -419,7 +450,14 @@ int maria_check_definition(MARIA_KEYDEF *t1_keyinfo,
{
MARIA_COLUMNDEF *t1_rec= &t1_recinfo[i];
MARIA_COLUMNDEF *t2_rec= &t2_recinfo[i];
- if (t1_rec->type != t2_rec->type ||
+ /*
+ FIELD_SKIP_ZERO can be changed to FIELD_NORMAL in maria_create,
+ see NOTE1 in ma_create.c
+ */
+ if ((t1_rec->type != t2_rec->type &&
+ !(t1_rec->type == (int) FIELD_SKIP_ZERO &&
+ t1_rec->length == 1 &&
+ t2_rec->type == (int) FIELD_NORMAL)) ||
t1_rec->length != t2_rec->length ||
t1_rec->null_bit != t2_rec->null_bit)
{
@@ -602,7 +640,7 @@ int ha_maria::dump(THD * thd, int fd)
my_seek(data_fd, 0L, MY_SEEK_SET, MYF(MY_WME));
for (; bytes_to_read > 0;)
{
- uint bytes= my_read(data_fd, buf, block_size, MYF(MY_WME));
+ size_t bytes= my_read(data_fd, buf, block_size, MYF(MY_WME));
if (bytes == MY_FILE_ERROR)
{
error= errno;
@@ -644,7 +682,8 @@ err:
bool ha_maria::check_if_locking_is_allowed(uint sql_command,
ulong type, TABLE *table,
- uint count,
+ uint count, uint current,
+ uint *system_count,
bool called_by_privileged_thread)
{
/*
@@ -653,10 +692,13 @@ bool ha_maria::check_if_locking_is_allowed(uint sql_command,
we have to disallow write-locking of these tables with any other tables.
*/
if (table->s->system_table &&
- table->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE && count != 1)
+ table->reginfo.lock_type >= TL_WRITE_ALLOW_WRITE)
+ (*system_count)++;
+
+ /* 'current' is an index, that's why '<=' below. */
+ if (*system_count > 0 && *system_count <= current)
{
- my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0), table->s->db.str,
- table->s->table_name.str);
+ my_error(ER_WRONG_LOCK_OF_SYSTEM_TABLE, MYF(0));
return FALSE;
}
@@ -676,6 +718,9 @@ bool ha_maria::check_if_locking_is_allowed(uint sql_command,
int ha_maria::open(const char *name, int mode, uint test_if_locked)
{
+ MARIA_KEYDEF *keyinfo;
+ MARIA_COLUMNDEF *recinfo= 0;
+ uint recs;
uint i;
#ifdef NOT_USED
@@ -701,6 +746,36 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked)
if (!(file= maria_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
return (my_errno ? my_errno : -1);
+#ifdef ASK_MONTY
+ /*
+ This is a protection for the case of a frm and MAI containing incompatible
+ table definitions (as in BUG#25908). This was merged from MyISAM.
+ But it breaks maria.test and ps_maria.test ("incorrect key file") if the
+ table is BLOCK_RECORD (does it have to do with column reordering done in
+ ma_create.c ?).
+ */
+ if (!table->s->tmp_table) /* No need to perform a check for tmp table */
+ {
+ if ((my_errno= table2maria(table, &keyinfo, &recinfo, &recs)))
+ {
+ /* purecov: begin inspected */
+ DBUG_PRINT("error", ("Failed to convert TABLE object to Maria "
+ "key and column definition"));
+ goto err;
+ /* purecov: end */
+ }
+ if (maria_check_definition(keyinfo, recinfo, table->s->keys, recs,
+ file->s->keyinfo, file->s->columndef,
+ file->s->base.keys, file->s->base.fields, true))
+ {
+ /* purecov: begin inspected */
+ my_errno= HA_ERR_CRASHED;
+ goto err;
+ /* purecov: end */
+ }
+ }
+#endif
+
if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
VOID(maria_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
@@ -731,7 +806,18 @@ int ha_maria::open(const char *name, int mode, uint test_if_locked)
(struct st_mysql_ftparser *)plugin_decl(parser)->info;
table->key_info[i].block_size= file->s->keyinfo[i].block_length;
}
- return (0);
+ my_errno= 0;
+ goto end;
+ err:
+ this->close();
+ end:
+ /*
+ Both recinfo and keydef are allocated by my_multi_malloc(), thus only
+ recinfo must be freed.
+ */
+ if (recinfo)
+ my_free((uchar*) recinfo, MYF(0));
+ return my_errno;
}
@@ -745,7 +831,7 @@ int ha_maria::close(void)
int ha_maria::write_row(uchar * buf)
{
- statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
+ ha_statistic_increment(&SSV::ha_write_count);
/* If we have a timestamp column, update it to the current time */
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
@@ -1064,8 +1150,8 @@ int ha_maria::optimize(THD * thd, HA_CHECK_OPT *check_opt)
param.sort_buffer_length= check_opt->sort_buffer_size;
if ((error= repair(thd, param, 1)) && param.retry_repair)
{
- sql_print_warning("Warning: Optimize table got errno %d, retrying",
- my_errno);
+ sql_print_warning("Warning: Optimize table got errno %d on %s.%s, retrying",
+ my_errno, param.db_name, param.table_name);
param.testflag &= ~T_REP_BY_SORT;
error= repair(thd, param, 1);
}
@@ -1084,6 +1170,22 @@ int ha_maria::repair(THD *thd, HA_CHECK &param, bool do_optimize)
ha_rows rows= file->state->records;
DBUG_ENTER("ha_maria::repair");
+ /*
+ Normally this method is entered with a properly opened table. If the
+ repair fails, it can be repeated with more elaborate options. Under
+ special circumstances it can happen that a repair fails so that it
+ closed the data file and cannot re-open it. In this case file->dfile
+ is set to -1. We must not try another repair without an open data
+ file. (Bug #25289)
+ */
+ if (file->dfile.file == -1)
+ {
+ sql_print_information("Retrying repair of: '%s' failed. "
+ "Please try REPAIR EXTENDED or maria_chk",
+ table->s->path.str);
+ DBUG_RETURN(HA_ADMIN_FAILED);
+ }
+
param.db_name= table->s->db.str;
param.table_name= table->alias;
param.tmpfile_createflag= O_RDWR | O_TRUNC;
@@ -1222,7 +1324,7 @@ int ha_maria::assign_to_keycache(THD * thd, HA_CHECK_OPT *check_opt)
PAGECACHE *new_pagecache= check_opt->pagecache;
const char *errmsg= 0;
int error= HA_ADMIN_OK;
- ulonglong map= ~(ulonglong) 0;
+ ulonglong map;
TABLE_LIST *table_list= table->pos_in_table_list;
DBUG_ENTER("ha_maria::assign_to_keycache");
@@ -1268,9 +1370,10 @@ int ha_maria::preload_keys(THD * thd, HA_CHECK_OPT *check_opt)
{
int error;
const char *errmsg;
- ulonglong map= ~(ulonglong) 0;
+ ulonglong map;
TABLE_LIST *table_list= table->pos_in_table_list;
my_bool ignore_leaves= table_list->ignore_leaves;
+ char buf[ERRMSGSIZE+20];
DBUG_ENTER("ha_maria::preload_keys");
@@ -1298,7 +1401,6 @@ int ha_maria::preload_keys(THD * thd, HA_CHECK_OPT *check_opt)
errmsg= "Failed to allocate buffer";
break;
default:
- char buf[ERRMSGSIZE + 20];
my_snprintf(buf, ERRMSGSIZE,
"Failed to read from index file (errno: %d)", my_errno);
errmsg= buf;
@@ -1427,13 +1529,13 @@ int ha_maria::enable_indexes(uint mode)
T_CREATE_MISSING_KEYS);
param.myf_rw &= ~MY_WAIT_IF_FULL;
param.sort_buffer_length= thd->variables.maria_sort_buff_size;
- param.stats_method= (enum_handler_stats_method) thd->variables.
- maria_stats_method;
+ param.stats_method=
+ (enum_handler_stats_method) thd->variables.maria_stats_method;
param.tmpdir= &mysql_tmpdir_list;
if ((error= (repair(thd, param, 0) != HA_ADMIN_OK)) && param.retry_repair)
{
- sql_print_warning("Warning: Enabling keys got errno %d, retrying",
- my_errno);
+ sql_print_warning("Warning: Enabling keys got errno %d on %s.%s, retrying",
+ my_errno, param.db_name, param.table_name);
/* Repairing by sort failed. Now try standard repair method. */
param.testflag &= ~(T_REP_BY_SORT | T_QUICK);
error= (repair(thd, param, 0) != HA_ADMIN_OK);
@@ -1442,8 +1544,10 @@ int ha_maria::enable_indexes(uint mode)
might have been set by the first repair. They can still be seen
with SHOW WARNINGS then.
*/
+#ifndef EMBEDDED_LIBRARY
if (!error)
thd->clear_error();
+#endif /* EMBEDDED_LIBRARY */
}
info(HA_STATUS_CONST);
thd->proc_info= save_proc_info;
@@ -1607,7 +1711,7 @@ bool ha_maria::is_crashed() const
int ha_maria::update_row(const uchar * old_data, uchar * new_data)
{
- statistic_increment(table->in_use->status_var.ha_update_count, &LOCK_status);
+ ha_statistic_increment(&SSV::ha_update_count);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
return maria_update(file, old_data, new_data);
@@ -1616,41 +1720,41 @@ int ha_maria::update_row(const uchar * old_data, uchar * new_data)
int ha_maria::delete_row(const uchar * buf)
{
- statistic_increment(table->in_use->status_var.ha_delete_count, &LOCK_status);
+ ha_statistic_increment(&SSV::ha_delete_count);
return maria_delete(file, buf);
}
int ha_maria::index_read(uchar * buf, const uchar * key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
DBUG_ASSERT(inited == INDEX);
- statistic_increment(table->in_use->status_var.ha_read_key_count,
- &LOCK_status);
- int error= maria_rkey(file, buf, active_index, key, key_len, find_flag);
+ ha_statistic_increment(&SSV::ha_read_key_count);
+ int error= maria_rkey(file, buf, active_index, key, keypart_map, find_flag);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
}
int ha_maria::index_read_idx(uchar * buf, uint index, const uchar * key,
- uint key_len, enum ha_rkey_function find_flag)
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag)
{
- statistic_increment(table->in_use->status_var.ha_read_key_count,
- &LOCK_status);
- int error= maria_rkey(file, buf, index, key, key_len, find_flag);
+ ha_statistic_increment(&SSV::ha_read_key_count);
+ int error= maria_rkey(file, buf, index, key, keypart_map, find_flag);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
}
-int ha_maria::index_read_last(uchar * buf, const uchar * key, uint key_len)
+int ha_maria::index_read_last(uchar * buf, const uchar * key,
+ key_part_map keypart_map)
{
DBUG_ENTER("ha_maria::index_read_last");
DBUG_ASSERT(inited == INDEX);
- statistic_increment(table->in_use->status_var.ha_read_key_count,
- &LOCK_status);
- int error= maria_rkey(file, buf, active_index, key, key_len,
+ ha_statistic_increment(&SSV::ha_read_key_count);
+ int error= maria_rkey(file, buf, active_index, key, keypart_map,
HA_READ_PREFIX_LAST);
table->status= error ? STATUS_NOT_FOUND : 0;
DBUG_RETURN(error);
@@ -1660,8 +1764,7 @@ int ha_maria::index_read_last(uchar * buf, const uchar * key, uint key_len)
int ha_maria::index_next(uchar * buf)
{
DBUG_ASSERT(inited == INDEX);
- statistic_increment(table->in_use->status_var.ha_read_next_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_next_count);
int error= maria_rnext(file, buf, active_index);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
@@ -1671,8 +1774,7 @@ int ha_maria::index_next(uchar * buf)
int ha_maria::index_prev(uchar * buf)
{
DBUG_ASSERT(inited == INDEX);
- statistic_increment(table->in_use->status_var.ha_read_prev_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_prev_count);
int error= maria_rprev(file, buf, active_index);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
@@ -1682,8 +1784,7 @@ int ha_maria::index_prev(uchar * buf)
int ha_maria::index_first(uchar * buf)
{
DBUG_ASSERT(inited == INDEX);
- statistic_increment(table->in_use->status_var.ha_read_first_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_first_count);
int error= maria_rfirst(file, buf, active_index);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
@@ -1693,8 +1794,7 @@ int ha_maria::index_first(uchar * buf)
int ha_maria::index_last(uchar * buf)
{
DBUG_ASSERT(inited == INDEX);
- statistic_increment(table->in_use->status_var.ha_read_last_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_last_count);
int error= maria_rlast(file, buf, active_index);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
@@ -1706,8 +1806,7 @@ int ha_maria::index_next_same(uchar * buf,
uint length __attribute__ ((unused)))
{
DBUG_ASSERT(inited == INDEX);
- statistic_increment(table->in_use->status_var.ha_read_next_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_next_count);
int error= maria_rnext_same(file, buf);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
@@ -1732,8 +1831,7 @@ int ha_maria::rnd_end()
int ha_maria::rnd_next(uchar *buf)
{
- statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_rnd_next_count);
int error= maria_scan(file, buf);
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
@@ -1748,8 +1846,7 @@ int ha_maria::restart_rnd_next(uchar *buf, uchar *pos)
int ha_maria::rnd_pos(uchar * buf, uchar *pos)
{
- statistic_increment(table->in_use->status_var.ha_read_rnd_count,
- &LOCK_status);
+ ha_statistic_increment(&SSV::ha_read_rnd_count);
int error= maria_rrnd(file, buf, my_get_ptr(pos, ref_length));
table->status= error ? STATUS_NOT_FOUND : 0;
return error;
@@ -2111,7 +2208,8 @@ void ha_maria::get_auto_increment(ulonglong offset, ulonglong increment,
table->key_info + table->s->next_number_index,
table->s->next_number_key_offset);
error= maria_rkey(file, table->record[1], (int) table->s->next_number_index,
- key, table->s->next_number_key_offset, HA_READ_PREFIX_LAST);
+ key, make_prev_keypart_map(table->s->next_number_keypart),
+ HA_READ_PREFIX_LAST);
if (error)
nr= 1;
else
diff --git a/storage/maria/ha_maria.h b/storage/maria/ha_maria.h
index c97919ab86a..7675778ab5b 100644
--- a/storage/maria/ha_maria.h
+++ b/storage/maria/ha_maria.h
@@ -68,18 +68,21 @@ public:
virtual bool check_if_locking_is_allowed(uint sql_command,
ulong type, TABLE * table,
- uint count,
+ uint count, uint current,
+ uint *system_count,
bool called_by_logger_thread);
int open(const char *name, int mode, uint test_if_locked);
int close(void);
int write_row(uchar * buf);
int update_row(const uchar * old_data, uchar * new_data);
int delete_row(const uchar * buf);
- int index_read(uchar * buf, const uchar * key,
- uint key_len, enum ha_rkey_function find_flag);
+ int index_read(uchar * buf, const uchar * key, key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
int index_read_idx(uchar * buf, uint idx, const uchar * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_last(uchar * buf, const uchar * key, uint key_len);
+ key_part_map keypart_map,
+ enum ha_rkey_function find_flag);
+ int index_read_last(uchar * buf, const uchar * key,
+ key_part_map keypart_map);
int index_next(uchar * buf);
int index_prev(uchar * buf);
int index_first(uchar * buf);
diff --git a/storage/maria/ma_cache.c b/storage/maria/ma_cache.c
index 44aa7a15058..6b1f9ec3fae 100644
--- a/storage/maria/ma_cache.c
+++ b/storage/maria/ma_cache.c
@@ -40,7 +40,7 @@ int _ma_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos, uint length,
{
uint read_length,in_buff_length;
my_off_t offset;
- char *in_buff_pos;
+ uchar *in_buff_pos;
DBUG_ENTER("_ma_read_cache");
if (pos < info->pos_in_file)
@@ -61,7 +61,7 @@ int _ma_read_cache(IO_CACHE *info, uchar *buff, my_off_t pos, uint length,
(my_off_t) (info->read_end - info->request_pos))
{
in_buff_pos=info->request_pos+(uint) offset;
- in_buff_length= min(length,(uint) ((char*)(info->read_end)-in_buff_pos));
+ in_buff_length= min(length,(size_t) (info->read_end-in_buff_pos));
memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
if (!(length-=in_buff_length))
DBUG_RETURN(0);
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index 7d936409170..ce4a610cec9 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -344,7 +344,7 @@ int maria_chk_size(HA_CHECK *param, register MARIA_HA *info)
flush_pagecache_blocks(info->s->pagecache,
&info->s->kfile, FLUSH_FORCE_WRITE);
- size= my_seek(info->s->kfile.file, 0L, MY_SEEK_END, MYF(0));
+ size= my_seek(info->s->kfile.file, 0L, MY_SEEK_END, MYF(MY_THREADSAFE));
if ((skr=(my_off_t) info->state->key_file_length) != size)
{
/* Don't give error if file generated by mariapack */
@@ -539,7 +539,7 @@ int maria_chk_key(HA_CHECK *param, register MARIA_HA *info)
maria_extra(info,HA_EXTRA_KEYREAD,0);
bzero(info->lastkey,keyinfo->seg->length);
if (!maria_rkey(info, info->rec_buff, key, (const uchar*) info->lastkey,
- keyinfo->seg->length, HA_READ_KEY_EXACT))
+ (key_part_map)1, HA_READ_KEY_EXACT))
{
/* Don't count this as a real warning, as maria_chk can't correct it */
uint save=param->warning_printed;
@@ -603,7 +603,8 @@ static int chk_index_down(HA_CHECK *param, MARIA_HA *info,
{
/* purecov: begin tested */
/* Give it a chance to fit in the real file size. */
- my_off_t max_length= my_seek(info->s->kfile.file, 0L, MY_SEEK_END, MYF(0));
+ my_off_t max_length= my_seek(info->s->kfile.file, 0L, MY_SEEK_END,
+ MYF(MY_THREADSAFE));
_ma_check_print_error(param, "Invalid key block position: %s "
"key block size: %u file_length: %s",
llstr(page, llbuff), keyinfo->block_length,
@@ -4772,10 +4773,11 @@ int maria_test_if_almost_full(MARIA_HA *info)
{
if (info->s->options & HA_OPTION_COMPRESS_RECORD)
return 0;
- return (my_seek(info->s->kfile.file, 0L, MY_SEEK_END, MYF(0))/10*9 >
- (my_off_t) (info->s->base.max_key_file_length) ||
- my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0)) / 10 * 9 >
- (my_off_t) info->s->base.max_data_file_length);
+ return my_seek(info->s->kfile.file, 0L, MY_SEEK_END,
+ MYF(MY_THREADSAFE))/10*9 >
+ (my_off_t) info->s->base.max_key_file_length ||
+ my_seek(info->dfile.file, 0L, MY_SEEK_END, MYF(0)) / 10 * 9 >
+ (my_off_t) info->s->base.max_data_file_length;
}
/* Recreate table with bigger more alloced record-data */
diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c
index 1736e24a7b6..201c5603c25 100644
--- a/storage/maria/ma_create.c
+++ b/storage/maria/ma_create.c
@@ -239,6 +239,10 @@ int maria_create(const char *name, enum data_file_type datafile_type,
column--;
if (column->type == (int) FIELD_SKIP_ZERO && column->length == 1)
{
+ /*
+ NOTE1: here we change a field type FIELD_SKIP_ZERO ->
+ FIELD_NORMAL
+ */
column->type=(int) FIELD_NORMAL;
column->empty_pos= 0;
column->empty_bit= 0;
@@ -701,6 +705,10 @@ int maria_create(const char *name, enum data_file_type datafile_type,
pthread_mutex_lock(&THR_LOCK_maria);
+ /*
+ NOTE: For test_if_reopen() we need a real path name. Hence we need
+ MY_RETURN_REAL_PATH for every fn_format(filename, ...).
+ */
if (ci->index_file_name)
{
char *iext= strrchr(ci->index_file_name, '.');
@@ -712,13 +720,14 @@ int maria_create(const char *name, enum data_file_type datafile_type,
if ((path= strrchr(ci->index_file_name, FN_LIBCHAR)))
*path= '\0';
fn_format(filename, name, ci->index_file_name, MARIA_NAME_IEXT,
- MY_REPLACE_DIR | MY_UNPACK_FILENAME | MY_APPEND_EXT);
+ MY_REPLACE_DIR | MY_UNPACK_FILENAME |
+ MY_RETURN_REAL_PATH | MY_APPEND_EXT);
}
else
{
fn_format(filename, ci->index_file_name, "", MARIA_NAME_IEXT,
- MY_UNPACK_FILENAME | (have_iext ? MY_REPLACE_EXT :
- MY_APPEND_EXT));
+ MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
+ (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
}
fn_format(linkname, name, "", MARIA_NAME_IEXT,
MY_UNPACK_FILENAME|MY_APPEND_EXT);
@@ -734,10 +743,11 @@ int maria_create(const char *name, enum data_file_type datafile_type,
}
else
{
+ char *iext= strrchr(name, '.');
+ int have_iext= iext && !strcmp(iext, MARIA_NAME_IEXT);
fn_format(filename, name, "", MARIA_NAME_IEXT,
- (MY_UNPACK_FILENAME |
- (flags & HA_DONT_TOUCH_DATA) ? MY_RETURN_REAL_PATH : 0) |
- MY_APPEND_EXT);
+ MY_UNPACK_FILENAME | MY_RETURN_REAL_PATH |
+ (have_iext ? MY_REPLACE_EXT : MY_APPEND_EXT));
linkname_ptr= NullS;
/*
Replace the current file.
@@ -752,6 +762,10 @@ int maria_create(const char *name, enum data_file_type datafile_type,
A TRUNCATE command checks for the table in the cache only and could
be fooled to believe, the table is not open.
Pull the emergency brake in this situation. (Bug #8306)
+
+
+ NOTE: The filename is compared against unique_file_name of every
+ open table. Hence we need a real path here.
*/
if (_ma_test_if_reopen(filename))
{
diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c
index 28b970ef589..246f9787b09 100644
--- a/storage/maria/ma_dynrec.c
+++ b/storage/maria/ma_dynrec.c
@@ -887,7 +887,7 @@ uint _ma_rec_pack(MARIA_HA *info, register uchar *to,
register const uchar *from)
{
uint length,new_length,flag,bit,i;
- char *pos,*end,*startpos,*packpos;
+ uchar *pos,*end,*startpos,*packpos;
enum en_fieldtype type;
reg3 MARIA_COLUMNDEF *column;
MARIA_BLOB *blob;
@@ -941,7 +941,7 @@ uint _ma_rec_pack(MARIA_HA *info, register uchar *to,
pos= (uchar*) from; end= (uchar*) from + length;
if (type == FIELD_SKIP_ENDSPACE)
{ /* Pack trailing spaces */
- while (end > (char*) from && *(end-1) == ' ')
+ while (end > from && *(end-1) == ' ')
end--;
}
else
@@ -1007,8 +1007,8 @@ uint _ma_rec_pack(MARIA_HA *info, register uchar *to,
*packpos= (char) (uchar) flag;
if (info->s->calc_checksum)
*to++= (uchar) info->cur_row.checksum;
- DBUG_PRINT("exit",("packed length: %d",(int) ((char*)to-startpos)));
- DBUG_RETURN((uint) ((char*)to-startpos));
+ DBUG_PRINT("exit",("packed length: %d",(int) (to-startpos)));
+ DBUG_RETURN((uint) (to-startpos));
} /* _ma_rec_pack */
@@ -1018,12 +1018,12 @@ uint _ma_rec_pack(MARIA_HA *info, register uchar *to,
Returns 0 if record is ok.
*/
-my_bool _ma_rec_check(MARIA_HA *info,const char *record, uchar *rec_buff,
+my_bool _ma_rec_check(MARIA_HA *info,const uchar *record, uchar *rec_buff,
ulong packed_length, my_bool with_checksum,
ha_checksum checksum)
{
uint length,new_length,flag,bit,i;
- char *pos,*end,*packpos,*to;
+ uchar *pos,*end,*packpos,*to;
enum en_fieldtype type;
reg3 MARIA_COLUMNDEF *column;
DBUG_ENTER("_ma_rec_check");
@@ -1123,7 +1123,7 @@ my_bool _ma_rec_check(MARIA_HA *info,const char *record, uchar *rec_buff,
else
to+= length;
}
- if (packed_length != (uint) (to - (char*) rec_buff) +
+ if (packed_length != (uint) (to - rec_buff) +
test(info->s->calc_checksum) || (bit != 1 && (flag & ~(bit - 1))))
goto err;
if (with_checksum && ((uchar) checksum != (uchar) *to))
diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c
index 2fc4873d535..9ee3b1a8870 100644
--- a/storage/maria/ma_extra.c
+++ b/storage/maria/ma_extra.c
@@ -379,11 +379,13 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
break; /* Not supported */
pthread_mutex_lock(&share->intern_lock);
/*
- Memory map the data file if it is not already mapped and if there
- are no other threads using this table. intern_lock prevents other
- threads from starting to use the table while we are mapping it.
+ Memory map the data file if it is not already mapped. It is safe
+ to memory map a file while other threads are using file I/O on it.
+ Assigning a new address to a function pointer is an atomic
+ operation. intern_lock prevents that two or more mappings are done
+ at the same time.
*/
- if (!share->file_map && (share->tot_locks == 1))
+ if (!share->file_map)
{
if (_ma_dynmap_file(info, share->state.state.data_file_length))
{
diff --git a/storage/maria/ma_ft_boolean_search.c b/storage/maria/ma_ft_boolean_search.c
index 41661d1c288..e09a076ceaa 100644
--- a/storage/maria/ma_ft_boolean_search.c
+++ b/storage/maria/ma_ft_boolean_search.c
@@ -286,8 +286,8 @@ static int ftb_parse_query_internal(MYSQL_FTPARSER_PARAM *param,
}
-static void _ftb_parse_query(FTB *ftb, uchar *query, uint len,
- struct st_mysql_ftparser *parser)
+static int _ftb_parse_query(FTB *ftb, uchar *query, uint len,
+ struct st_mysql_ftparser *parser)
{
MYSQL_FTPARSER_PARAM *param;
MY_FTB_PARAM ftb_param;
@@ -295,9 +295,9 @@ static void _ftb_parse_query(FTB *ftb, uchar *query, uint len,
DBUG_ASSERT(parser);
if (ftb->state != UNINITIALIZED)
- DBUG_VOID_RETURN;
+ DBUG_RETURN(0);
if (! (param= maria_ftparser_call_initializer(ftb->info, ftb->keynr, 0)))
- DBUG_VOID_RETURN;
+ DBUG_RETURN(1);
ftb_param.ftb= ftb;
ftb_param.depth= 0;
@@ -312,8 +312,7 @@ static void _ftb_parse_query(FTB *ftb, uchar *query, uint len,
param->length= len;
param->flags= 0;
param->mode= MYSQL_FTPARSER_FULL_BOOLEAN_INFO;
- parser->parse(param);
- DBUG_VOID_RETURN;
+ DBUG_RETURN(parser->parse(param));
}
@@ -537,9 +536,10 @@ FT_INFO * maria_ft_init_boolean_search(MARIA_HA *info, uint keynr, uchar *query,
ftbe->phrase= NULL;
ftbe->document= 0;
ftb->root=ftbe;
- _ftb_parse_query(ftb, query, query_len, keynr == NO_SUCH_KEY ?
- &ft_default_parser :
- info->s->keyinfo[keynr].parser);
+ if (unlikely(_ftb_parse_query(ftb, query, query_len,
+ keynr == NO_SUCH_KEY ? &ft_default_parser :
+ info->s->keyinfo[keynr].parser)))
+ goto err;
/*
Hack: instead of init_queue, we'll use reinit queue to be able
to alloc queue with alloc_root()
@@ -621,7 +621,7 @@ static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param,
{
param->mysql_add_word(param, word.pos, word.len, 0);
if (phrase_param->match)
- return 1;
+ break;
}
return 0;
}
@@ -639,6 +639,7 @@ static int ftb_check_phrase_internal(MYSQL_FTPARSER_PARAM *param,
RETURN VALUE
1 is returned if phrase found, 0 else.
+ -1 is returned if error occurs.
*/
static int _ftb_check_phrase(FTB *ftb, const uchar *document, uint len,
@@ -666,12 +667,13 @@ static int _ftb_check_phrase(FTB *ftb, const uchar *document, uint len,
param->length= len;
param->flags= 0;
param->mode= MYSQL_FTPARSER_WITH_STOPWORDS;
- parser->parse(param);
+ if (unlikely(parser->parse(param)))
+ return -1;
DBUG_RETURN(ftb_param.match ? 1 : 0);
}
-static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_orig)
+static int _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_orig)
{
FT_SEG_ITERATOR ftsi;
FTB_EXPR *ftbe;
@@ -703,17 +705,19 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
weight=ftbe->cur_weight*ftbe->weight;
if (mode && ftbe->phrase)
{
- int not_found=1;
+ int found= 0;
memcpy(&ftsi, ftsi_orig, sizeof(ftsi));
- while (_ma_ft_segiterator(&ftsi) && not_found)
+ while (_ma_ft_segiterator(&ftsi) && !found)
{
if (!ftsi.pos)
continue;
- not_found = ! _ftb_check_phrase(ftb, ftsi.pos, ftsi.len,
- ftbe, parser);
+ found= _ftb_check_phrase(ftb, ftsi.pos, ftsi.len, ftbe, parser);
+ if (unlikely(found < 0))
+ return 1;
}
- if (not_found) break;
+ if (!found)
+ break;
} /* ftbe->quot */
}
else
@@ -745,6 +749,7 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
weight*= ftbe->weight;
}
}
+ return 0;
}
@@ -777,7 +782,11 @@ int maria_ft_boolean_read_next(FT_INFO *ftb, char *record)
{
while (curdoc == (ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0])
{
- _ftb_climb_the_tree(ftb, ftbw, 0);
+ if (unlikely(_ftb_climb_the_tree(ftb, ftbw, 0)))
+ {
+ my_errno= HA_ERR_OUT_OF_MEM;
+ goto err;
+ }
/* update queue */
_ft2_search(ftb, ftbw, 0);
@@ -853,7 +862,8 @@ static int ftb_find_relevance_add_word(MYSQL_FTPARSER_PARAM *param,
if (ftbw->docid[1] == ftb->info->cur_row.lastpos)
continue;
ftbw->docid[1]= ftb->info->cur_row.lastpos;
- _ftb_climb_the_tree(ftb, ftbw, ftb_param->ftsi);
+ if (unlikely(_ftb_climb_the_tree(ftb, ftbw, ftb_param->ftsi)))
+ return 1;
}
return(0);
}
@@ -926,7 +936,8 @@ float maria_ft_boolean_find_relevance(FT_INFO *ftb, uchar *record, uint length)
continue;
param->doc= (uchar *)ftsi.pos;
param->length= ftsi.len;
- parser->parse(param);
+ if (unlikely(parser->parse(param)))
+ return 0;
}
ftbe=ftb->root;
if (ftbe->docid[1]==docid && ftbe->cur_weight>0 &&
diff --git a/storage/maria/ma_ft_nlq_search.c b/storage/maria/ma_ft_nlq_search.c
index cad5238d4a5..18b101f0e05 100644
--- a/storage/maria/ma_ft_nlq_search.c
+++ b/storage/maria/ma_ft_nlq_search.c
@@ -258,8 +258,12 @@ FT_INFO *maria_ft_init_nlq_search(MARIA_HA *info, uint keynr, uchar *query,
{
info->update|= HA_STATE_AKTIV;
ftparser_param->flags= MYSQL_FTFLAGS_NEED_COPY;
- _ma_ft_parse(&wtree, info, keynr, record, ftparser_param,
- &wtree.mem_root);
+ if (unlikely(_ma_ft_parse(&wtree, info, keynr, record, ftparser_param,
+ &wtree.mem_root)))
+ {
+ delete_queue(&best);
+ goto err;
+ }
}
}
delete_queue(&best);
diff --git a/storage/maria/ma_info.c b/storage/maria/ma_info.c
index cfb4580a72f..4aecc33f816 100644
--- a/storage/maria/ma_info.c
+++ b/storage/maria/ma_info.c
@@ -57,9 +57,9 @@ int maria_status(MARIA_HA *info, register MARIA_INFO *x, uint flag)
x->keys = share->state.header.keys;
x->check_time = share->state.check_time;
- x->mean_reclength = info->state->records ?
- (ulong) ((info->state->data_file_length-info->state->empty)/
- info->state->records) : (ulong) share->min_pack_length;
+ x->mean_reclength = x->records ?
+ (ulong) ((x->data_file_length - x->delete_length) /x ->records) :
+ (ulong) share->min_pack_length;
}
if (flag & HA_STATUS_ERRKEY)
{
diff --git a/storage/maria/ma_key.c b/storage/maria/ma_key.c
index 83ba6853330..96b8d2af0eb 100644
--- a/storage/maria/ma_key.c
+++ b/storage/maria/ma_key.c
@@ -206,7 +206,7 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key,
uint keynr key number
key Store packed key here
old Not packed key
- k_length Length of 'old' to use
+ keypart_map bitmap of used keyparts
last_used_keyseg out parameter. May be NULL
RETURN
@@ -216,34 +216,37 @@ uint _ma_make_key(register MARIA_HA *info, uint keynr, uchar *key,
*/
uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key,
- const uchar *old, uint k_length, HA_KEYSEG **last_used_keyseg)
+ const uchar *old, key_part_map keypart_map,
+ HA_KEYSEG **last_used_keyseg)
{
uchar *start_key=key;
HA_KEYSEG *keyseg;
my_bool is_ft= info->s->keyinfo[keynr].flag & HA_FULLTEXT;
DBUG_ENTER("_ma_pack_key");
- for (keyseg=info->s->keyinfo[keynr].seg ;
- keyseg->type && (int) k_length > 0;
- old+=keyseg->length, keyseg++)
+ /* "one part" rtree key is 2*SPDIMS part key in Maria */
+ if (info->s->keyinfo[keynr].key_alg == HA_KEY_ALG_RTREE)
+ keypart_map= (((key_part_map)1) << (2*SPDIMS)) - 1;
+
+ /* only key prefixes are supported */
+ DBUG_ASSERT(((keypart_map+1) & keypart_map) == 0);
+
+ for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type && keypart_map;
+ old+= keyseg->length, keyseg++)
{
- enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
- uint length=min((uint) keyseg->length,(uint) k_length);
+ enum ha_base_keytype type= (enum ha_base_keytype) keyseg->type;
+ uint length= keyseg->length;
uint char_length;
const uchar *pos;
CHARSET_INFO *cs=keyseg->charset;
+ keypart_map>>= 1;
if (keyseg->null_bit)
{
- k_length--;
if (!(*key++= (char) 1-*old++)) /* Copy null marker */
{
- k_length-=length;
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
- {
- k_length-=2; /* Skip length */
old+= 2;
- }
continue; /* Found NULL */
}
}
@@ -253,17 +256,16 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key,
if (keyseg->flag & HA_SPACE_PACK)
{
const uchar *end= pos + length;
- if (type != HA_KEYTYPE_NUM)
- {
- while (end > pos && end[-1] == ' ')
- end--;
- }
- else
+ if (type == HA_KEYTYPE_NUM)
{
while (pos < end && pos[0] == ' ')
pos++;
}
- k_length-=length;
+ else if (type != HA_KEYTYPE_BINARY)
+ {
+ while (end > pos && end[-1] == ' ')
+ end--;
+ }
length=(uint) (end-pos);
FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
@@ -275,7 +277,6 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key,
{
/* Length of key-part used with maria_rkey() always 2 */
uint tmp_length=uint2korr(pos);
- k_length-= 2+length;
pos+=2;
set_if_smaller(length,tmp_length); /* Safety */
FIX_LENGTH(cs, pos, length, char_length);
@@ -288,11 +289,8 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key,
else if (keyseg->flag & HA_SWAP_KEY)
{ /* Numerical column */
pos+=length;
- k_length-=length;
while (length--)
- {
*key++ = *--pos;
- }
continue;
}
FIX_LENGTH(cs, pos, length, char_length);
@@ -300,30 +298,10 @@ uint _ma_pack_key(register MARIA_HA *info, uint keynr, uchar *key,
if (length > char_length)
cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
key+= length;
- k_length-=length;
}
if (last_used_keyseg)
*last_used_keyseg= keyseg;
-#ifdef NOT_USED
- if (keyseg->type)
- {
- /* Part-key ; fill with ASCII 0 for easier searching */
- length= (uint) -k_length; /* unused part of last key */
- do
- {
- if (keyseg->flag & HA_NULL_PART)
- length++;
- if (keyseg->flag & HA_SPACE_PACK)
- length+=2;
- else
- length+= keyseg->length;
- keyseg++;
- } while (keyseg->type);
- bzero(key,length);
- key+=length;
- }
-#endif
DBUG_PRINT("exit", ("length: %u", (uint) (key-start_key)));
DBUG_RETURN((uint) (key-start_key));
} /* _ma_pack_key */
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index fd007e2a5ae..9d1514a67c3 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -3553,8 +3553,8 @@ static my_bool translog_relative_LSN_encode(struct st_translog_parts *parts,
COMPRESSED_LSN_MAX_STORE_SIZE)) -
dst_ptr);
parts->record_length-= (economy= lsns_len - part->length);
- DBUG_PRINT("info", ("new length of LSNs: %u economy: %d",
- part->length, economy));
+ DBUG_PRINT("info", ("new length of LSNs: %lu economy: %d",
+ (ulong)part->length, economy));
parts->total_record_length-= economy;
part->str= (char*)dst_ptr;
}
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c
index e6df213609b..67a76144c26 100644
--- a/storage/maria/ma_open.c
+++ b/storage/maria/ma_open.c
@@ -392,7 +392,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
key_parts+=fulltext_keys*FT_SEGS;
if (share->base.max_key_length > maria_max_key_length() ||
- keys > MARIA_MAX_KEY || key_parts >= MARIA_MAX_KEY * HA_MAX_KEY_SEG)
+ keys > MARIA_MAX_KEY || key_parts > MARIA_MAX_KEY * HA_MAX_KEY_SEG)
{
DBUG_PRINT("error",("Wrong key info: Max_key_length: %d keys: %d key_parts: %d", share->base.max_key_length, keys, key_parts));
my_errno=HA_ERR_UNSUPPORTED;
@@ -667,22 +667,6 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
_ma_setup_functions(share);
if ((*share->once_init)(share, info.dfile.file))
goto err;
- if (open_flags & HA_OPEN_MMAP)
- {
- info.s= share;
- if (_ma_dynmap_file(&info, share->state.state.data_file_length))
- {
- /* purecov: begin inspected */
- /* Ignore if mmap fails. Use file I/O instead. */
- DBUG_PRINT("warning", ("mmap failed: errno: %d", errno));
- /* purecov: end */
- }
- else
- {
- share->file_read= _ma_mmap_pread;
- share->file_write= _ma_mmap_pwrite;
- }
- }
share->is_log_table= FALSE;
if (open_flags & HA_OPEN_TMP_TABLE)
share->options|= HA_OPTION_TMP_TABLE;
@@ -721,6 +705,14 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
}
}
#endif
+ /*
+ Memory mapping can only be requested after initializing intern_lock.
+ */
+ if (open_flags & HA_OPEN_MMAP)
+ {
+ info.s= share;
+ maria_extra(&info, HA_EXTRA_MMAP, 0);
+ }
}
else
{
@@ -1022,10 +1014,10 @@ uint _ma_state_info_write(File file, MARIA_STATE_INFO *state, uint pWrite)
}
if (pWrite & 1)
- DBUG_RETURN(my_pwrite(file,(char*) buff, (uint) (ptr-buff), 0L,
- MYF(MY_NABP | MY_THREADSAFE)));
- DBUG_RETURN(my_write(file, (char*) buff, (uint) (ptr-buff),
- MYF(MY_NABP)));
+ DBUG_RETURN(my_pwrite(file, buff, (size_t) (ptr-buff), 0L,
+ MYF(MY_NABP | MY_THREADSAFE)) != 0);
+ DBUG_RETURN(my_write(file, buff, (size_t) (ptr-buff),
+ MYF(MY_NABP)) != 0);
}
@@ -1089,10 +1081,10 @@ uint _ma_state_info_read_dsk(File file, MARIA_STATE_INFO *state, my_bool pRead)
if (pRead)
{
if (my_pread(file, buff, state->state_length,0L, MYF(MY_NABP)))
- return (MY_FILE_ERROR);
+ return 1;
}
else if (my_read(file, buff, state->state_length,MYF(MY_NABP)))
- return (MY_FILE_ERROR);
+ return 1;
_ma_state_info_read(buff, state);
}
return 0;
@@ -1143,7 +1135,7 @@ uint _ma_base_info_write(File file, MARIA_BASE_INFO *base)
*ptr++= base->extra_alloc_procent;
bzero(ptr,16); ptr+= 16; /* extra */
DBUG_ASSERT((ptr - buff) == MARIA_BASE_INFO_SIZE);
- return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
+ return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
}
@@ -1204,7 +1196,7 @@ uint _ma_keydef_write(File file, MARIA_KEYDEF *keydef)
mi_int2store(ptr,keydef->keylength); ptr+= 2;
mi_int2store(ptr,keydef->minlength); ptr+= 2;
mi_int2store(ptr,keydef->maxlength); ptr+= 2;
- return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
+ return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
}
char *_ma_keydef_read(char *ptr, MARIA_KEYDEF *keydef)
@@ -1247,7 +1239,7 @@ int _ma_keyseg_write(File file, const HA_KEYSEG *keyseg)
mi_int4store(ptr, pos);
ptr+=4;
- return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
+ return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
}
@@ -1287,7 +1279,7 @@ uint _ma_uniquedef_write(File file, MARIA_UNIQUEDEF *def)
*ptr++= (uchar) def->key;
*ptr++ = (uchar) def->null_are_equal;
- return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
+ return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
}
char *_ma_uniquedef_read(char *ptr, MARIA_UNIQUEDEF *def)
@@ -1315,7 +1307,7 @@ uint _ma_columndef_write(File file, MARIA_COLUMNDEF *columndef)
mi_int2store(ptr,columndef->empty_pos); ptr+= 2;
(*ptr++)= columndef->null_bit;
(*ptr++)= columndef->empty_bit;
- return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
+ return my_write(file, buff, (size_t) (ptr-buff), MYF(MY_NABP)) != 0;
}
char *_ma_columndef_read(char *ptr, MARIA_COLUMNDEF *columndef)
diff --git a/storage/maria/ma_preload.c b/storage/maria/ma_preload.c
index 35ae8868ee7..138bb94f7d0 100644
--- a/storage/maria/ma_preload.c
+++ b/storage/maria/ma_preload.c
@@ -55,12 +55,17 @@ int maria_preload(MARIA_HA *info, ulonglong key_map, my_bool ignore_leaves)
block_length= keyinfo[0].block_length;
- /* Check whether all indexes use the same block size */
- for (i= 1 ; i < keys ; i++)
+ if (ignore_leaves)
{
- if (keyinfo[i].block_length != block_length)
- DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE);
+ /* Check whether all indexes use the same block size */
+ for (i= 1 ; i < keys ; i++)
+ {
+ if (keyinfo[i].block_length != block_length)
+ DBUG_RETURN(my_errno= HA_ERR_NON_UNIQUE_BLOCK_SIZE);
+ }
}
+ else
+ block_length= share->pagecache->block_size;
length= info->preload_buff_size/block_length * block_length;
set_if_bigger(length, block_length);
diff --git a/storage/maria/ma_range.c b/storage/maria/ma_range.c
index 7250e6796d2..70dd522b8a1 100644
--- a/storage/maria/ma_range.c
+++ b/storage/maria/ma_range.c
@@ -21,12 +21,11 @@
#include "maria_def.h"
#include "ma_rt_index.h"
-static ha_rows _ma_record_pos(MARIA_HA *info,const uchar *key,uint key_len,
- enum ha_rkey_function search_flag);
-static double _ma_search_pos(MARIA_HA *info,MARIA_KEYDEF *keyinfo, uchar *key,
- uint key_len,uint nextflag, my_off_t pos);
-static uint _ma_keynr(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *page,
- uchar *keypos, uint *ret_max_key);
+static ha_rows _ma_record_pos(MARIA_HA *,const uchar *, key_part_map,
+ enum ha_rkey_function);
+static double _ma_search_pos(MARIA_HA *, MARIA_KEYDEF *, uchar *,
+ uint, uint, my_off_t);
+static uint _ma_keynr(MARIA_HA *, MARIA_KEYDEF *, uchar *, uchar *, uint *);
/**
@@ -84,7 +83,7 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
}
key_buff= info->lastkey+info->s->base.max_key_length;
start_key_len= _ma_pack_key(info,inx, key_buff,
- min_key->key, min_key->length,
+ min_key->key, min_key->keypart_map,
(HA_KEYSEG**) 0);
res= maria_rtree_estimate(info, inx, key_buff, start_key_len,
maria_read_vec[min_key->flag]);
@@ -95,13 +94,13 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
case HA_KEY_ALG_BTREE:
default:
start_pos= (min_key ?
- _ma_record_pos(info, min_key->key, min_key->length,
+ _ma_record_pos(info, min_key->key, min_key->keypart_map,
min_key->flag) :
(ha_rows) 0);
end_pos= (max_key ?
- _ma_record_pos(info, max_key->key, max_key->length,
+ _ma_record_pos(info, max_key->key, max_key->keypart_map,
max_key->flag) :
- info->state->records+ (ha_rows) 1);
+ info->state->records + (ha_rows) 1);
res= (end_pos < start_pos ? (ha_rows) 0 :
(end_pos == start_pos ? (ha_rows) 1 : end_pos-start_pos));
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
@@ -126,20 +125,22 @@ ha_rows maria_records_in_range(MARIA_HA *info, int inx, key_range *min_key,
/* Find relative position (in records) for key in index-tree */
-static ha_rows _ma_record_pos(MARIA_HA *info, const uchar *key, uint key_len,
+static ha_rows _ma_record_pos(MARIA_HA *info, const uchar *key,
+ key_part_map keypart_map,
enum ha_rkey_function search_flag)
{
- uint inx=(uint) info->lastinx, nextflag;
+ uint inx=(uint) info->lastinx, nextflag, key_len;
MARIA_KEYDEF *keyinfo=info->s->keyinfo+inx;
uchar *key_buff;
double pos;
DBUG_ENTER("_ma_record_pos");
DBUG_PRINT("enter",("search_flag: %d",search_flag));
+ DBUG_ASSERT(keypart_map);
if (key_len == 0)
key_len= USE_WHOLE_KEY;
key_buff=info->lastkey+info->s->base.max_key_length;
- key_len= _ma_pack_key(info, inx, key_buff, key, key_len,
+ key_len= _ma_pack_key(info, inx, key_buff, key, keypart_map,
(HA_KEYSEG**) 0);
DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, keyinfo->seg,
key_buff, key_len););
@@ -147,8 +148,42 @@ static ha_rows _ma_record_pos(MARIA_HA *info, const uchar *key, uint key_len,
if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST)))
key_len=USE_WHOLE_KEY;
+ /*
+ my_handler.c:mi_compare_text() has a flag 'skip_end_space'.
+ This is set in my_handler.c:ha_key_cmp() in dependence on the
+ compare flags 'nextflag' and the column type.
+
+ TEXT columns are of type HA_KEYTYPE_VARTEXT. In this case the
+ condition is skip_end_space= ((nextflag & (SEARCH_FIND |
+ SEARCH_UPDATE)) == SEARCH_FIND).
+
+ SEARCH_FIND is used for an exact key search. The combination
+ SEARCH_FIND | SEARCH_UPDATE is used in write/update/delete
+ operations with a comment like "Not real duplicates", whatever this
+ means. From the condition above we can see that 'skip_end_space' is
+ always false for these operations. The result is that trailing space
+ counts in key comparison and hence, emtpy strings ('', string length
+ zero, but not NULL) compare less that strings starting with control
+ characters and these in turn compare less than strings starting with
+ blanks.
+
+ When estimating the number of records in a key range, we request an
+ exact search for the minimum key. This translates into a plain
+ SEARCH_FIND flag. Using this alone would lead to a 'skip_end_space'
+ compare. Empty strings would be expected above control characters.
+ Their keys would not be found because they are located below control
+ characters.
+
+ This is the reason that we add the SEARCH_UPDATE flag here. It makes
+ the key estimation compare in the same way like key write operations
+ do. Olny so we will find the keys where they have been inserted.
+
+ Adding the flag unconditionally does not hurt as it is used in the
+ above mentioned condition only. So it can safely be used together
+ with other flags.
+ */
pos= _ma_search_pos(info,keyinfo, key_buff, key_len,
- nextflag | SEARCH_SAVE_BUFF,
+ nextflag | SEARCH_SAVE_BUFF | SEARCH_UPDATE,
info->s->state.key_root[inx]);
if (pos >= 0.0)
{
diff --git a/storage/maria/ma_rkey.c b/storage/maria/ma_rkey.c
index ef8b8468f1f..c9653d30110 100644
--- a/storage/maria/ma_rkey.c
+++ b/storage/maria/ma_rkey.c
@@ -22,7 +22,7 @@
/* Ordinary search_flag is 0 ; Give error if no record with key */
int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
- uint key_len, enum ha_rkey_function search_flag)
+ key_part_map keypart_map, enum ha_rkey_function search_flag)
{
uchar *key_buff;
MARIA_SHARE *share=info->s;
@@ -47,20 +47,21 @@ int maria_rkey(MARIA_HA *info, uchar *buf, int inx, const uchar *key,
key is already packed!; This happens when we are using a MERGE TABLE
*/
key_buff= info->lastkey+info->s->base.max_key_length;
- pack_key_length= key_len;
- bmove(key_buff,key,key_len);
- last_used_keyseg= 0;
+ pack_key_length= keypart_map;
+ bmove(key_buff, key, pack_key_length);
+ last_used_keyseg= info->s->keyinfo[inx].seg + info->last_used_keyseg;
}
else
{
- if (key_len == 0)
- key_len=USE_WHOLE_KEY;
+ DBUG_ASSERT(keypart_map);
/* Save the packed key for later use in the second buffer of lastkey. */
key_buff=info->lastkey+info->s->base.max_key_length;
pack_key_length= _ma_pack_key(info,(uint) inx, key_buff, key,
- key_len, &last_used_keyseg);
+ keypart_map, &last_used_keyseg);
/* Save packed_key_length for use by the MERGE engine. */
info->pack_key_length= pack_key_length;
+ info->last_used_keyseg= (uint16) (last_used_keyseg -
+ info->s->keyinfo[inx].seg);
DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, keyinfo->seg,
key_buff, pack_key_length););
}
diff --git a/storage/maria/ma_rt_index.c b/storage/maria/ma_rt_index.c
index 4d99eade9b5..4980233fc11 100644
--- a/storage/maria/ma_rt_index.c
+++ b/storage/maria/ma_rt_index.c
@@ -187,6 +187,7 @@ int maria_rtree_find_first(MARIA_HA *info, uint keynr, uchar *key,
/*
Save searched key, include data pointer.
The data pointer is required if the search_flag contains MBR_DATA.
+ (minimum bounding rectangle)
*/
memcpy(info->first_mbr_key, key, keyinfo->keylength);
info->last_rkey_length = key_length;
@@ -546,16 +547,19 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uint nod_flag;
int res;
uchar *page_buf, *k;
+ DBUG_ENTER("maria_rtree_insert_req");
if (!(page_buf= (uchar*) my_alloca((uint)keyinfo->block_length +
HA_MAX_KEY_BUFF)))
{
my_errno = HA_ERR_OUT_OF_MEM;
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
if (!_ma_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
goto err1;
nod_flag = _ma_test_if_nod(page_buf);
+ DBUG_PRINT("rtree", ("page: %lu level: %d ins_level: %d nod_flag: %u",
+ (ulong) page, level, ins_level, nod_flag));
if ((ins_level == -1 && nod_flag) || /* key: go down to leaf */
(ins_level > -1 && ins_level > level)) /* branch: go down to ins_level */
@@ -609,11 +613,11 @@ static int maria_rtree_insert_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
ok:
my_afree(page_buf);
- return res;
+ DBUG_RETURN(res);
err1:
my_afree(page_buf);
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
@@ -633,18 +637,19 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key,
MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr;
int res;
my_off_t new_page;
+ DBUG_ENTER("maria_rtree_insert_level");
if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
{
if ((old_root = _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
- return -1;
+ DBUG_RETURN(-1);
info->keyread_buff_used = 1;
maria_putint(info->buff, 2, 0);
res = maria_rtree_add_key(info, keyinfo, key, key_length, info->buff, NULL);
if (_ma_write_keypage(info, keyinfo, old_root, DFLT_INIT_HITS, info->buff))
- return 1;
+ DBUG_RETURN(1);
info->s->state.key_root[keynr] = old_root;
- return res;
+ DBUG_RETURN(res);
}
switch ((res = maria_rtree_insert_req(info, keyinfo, key, key_length,
@@ -660,11 +665,12 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key,
my_off_t new_root;
uint nod_flag = info->s->base.key_reflength;
+ DBUG_PRINT("rtree", ("root was split, grow a new root"));
if (!(new_root_buf= (uchar*) my_alloca((uint)keyinfo->block_length +
HA_MAX_KEY_BUFF)))
{
my_errno = HA_ERR_OUT_OF_MEM;
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
maria_putint(new_root_buf, 2, nod_flag);
@@ -694,12 +700,15 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key,
DFLT_INIT_HITS, new_root_buf))
goto err1;
info->s->state.key_root[keynr] = new_root;
+ DBUG_PRINT("rtree", ("new root page: %lu level: %d nod_flag: %u",
+ (ulong) new_root, 0,
+ _ma_test_if_nod(new_root_buf)));
my_afree((uchar*)new_root_buf);
break;
err1:
my_afree((uchar*)new_root_buf);
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
default:
case -1: /* error */
@@ -707,7 +716,7 @@ err1:
break;
}
}
- return res;
+ DBUG_RETURN(res);
}
@@ -721,9 +730,10 @@ err1:
int maria_rtree_insert(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
{
- return (!key_length ||
- (maria_rtree_insert_level(info, keynr, key, key_length, -1) == -1)) ?
- -1 : 0;
+ DBUG_ENTER("maria_rtree_insert");
+ DBUG_RETURN((!key_length ||
+ (maria_rtree_insert_level(info, keynr, key, key_length, -1) == -1)) ?
+ -1 : 0);
}
@@ -738,6 +748,8 @@ int maria_rtree_insert(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
static int maria_rtree_fill_reinsert_list(stPageList *ReinsertList, my_off_t page,
int level)
{
+ DBUG_ENTER("maria_rtree_fill_reinsert_list");
+ DBUG_PRINT("rtree", ("page: %lu level: %d", (ulong) page, level));
if (ReinsertList->n_pages == ReinsertList->m_pages)
{
ReinsertList->m_pages += REINSERT_BUFFER_INC;
@@ -749,10 +761,10 @@ static int maria_rtree_fill_reinsert_list(stPageList *ReinsertList, my_off_t pag
ReinsertList->pages[ReinsertList->n_pages].offs = page;
ReinsertList->pages[ReinsertList->n_pages].level = level;
ReinsertList->n_pages++;
- return 0;
+ DBUG_RETURN(0);
err1:
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
@@ -776,15 +788,18 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uint nod_flag;
int res;
uchar *page_buf, *last, *k;
+ DBUG_ENTER("maria_rtree_delete_req");
if (!(page_buf = (uchar*) my_alloca((uint)keyinfo->block_length)))
{
my_errno = HA_ERR_OUT_OF_MEM;
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
if (!_ma_fetch_keypage(info, keyinfo, page, DFLT_INIT_HITS, page_buf, 0))
goto err1;
nod_flag = _ma_test_if_nod(page_buf);
+ DBUG_PRINT("rtree", ("page: %lu level: %d nod_flag: %u",
+ (ulong) page, level, nod_flag));
k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
last = rt_PAGE_END(page_buf);
@@ -806,6 +821,7 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
rt_PAGE_MIN_SIZE(keyinfo->block_length))
{
/* OK */
+ /* Calculate a new key value (MBR) for the shrinked block. */
if (maria_rtree_set_key_mbr(info, keyinfo, k, key_length,
_ma_kpos(nod_flag, k)))
goto err1;
@@ -815,11 +831,24 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
}
else
{
- /* too small: delete key & add it descendant to reinsert list */
+ /*
+ Too small: delete key & add it descendant to reinsert list.
+ Store position and level of the block so that it can be
+ accessed later for inserting the remaining keys.
+ */
+ DBUG_PRINT("rtree", ("too small. move block to reinsert list"));
if (maria_rtree_fill_reinsert_list(ReinsertList,
_ma_kpos(nod_flag, k),
level + 1))
goto err1;
+ /*
+ Delete the key that references the block. This makes the
+ block disappear from the index. Hence we need to insert
+ its remaining keys later. Note: if the block is a branch
+ block, we do not only remove this block, but the whole
+ subtree. So we need to re-insert its keys on the same
+ level later to reintegrate the subtrees.
+ */
maria_rtree_delete_key(info, page_buf, k, key_length, nod_flag);
if (_ma_write_keypage(info, keyinfo, page,
DFLT_INIT_HITS, page_buf))
@@ -879,11 +908,11 @@ static int maria_rtree_delete_req(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
ok:
my_afree((uchar*)page_buf);
- return res;
+ DBUG_RETURN(res);
err1:
my_afree((uchar*)page_buf);
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
@@ -901,12 +930,15 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
stPageList ReinsertList;
my_off_t old_root;
MARIA_KEYDEF *keyinfo = info->s->keyinfo + keynr;
+ DBUG_ENTER("maria_rtree_delete");
if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
{
my_errno= HA_ERR_END_OF_FILE;
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
+ DBUG_PRINT("rtree", ("starting deletion at root page: %lu",
+ (ulong) old_root));
ReinsertList.pages = NULL;
ReinsertList.n_pages = 0;
@@ -915,12 +947,12 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
switch (maria_rtree_delete_req(info, keyinfo, key, key_length, old_root,
&page_size, &ReinsertList, 0))
{
- case 2:
+ case 2: /* empty */
{
info->s->state.key_root[keynr] = HA_OFFSET_ERROR;
- return 0;
+ DBUG_RETURN(0);
}
- case 0:
+ case 0: /* deleted */
{
uint nod_flag;
ulong i;
@@ -937,16 +969,35 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
DFLT_INIT_HITS, page_buf, 0))
goto err1;
nod_flag = _ma_test_if_nod(page_buf);
+ DBUG_PRINT("rtree", ("reinserting keys from "
+ "page: %lu level: %d nod_flag: %u",
+ (ulong) ReinsertList.pages[i].offs,
+ ReinsertList.pages[i].level, nod_flag));
+
k = rt_PAGE_FIRST_KEY(page_buf, nod_flag);
last = rt_PAGE_END(page_buf);
for (; k < last; k = rt_PAGE_NEXT_KEY(k, key_length, nod_flag))
{
- if (maria_rtree_insert_level(info, keynr, k, key_length,
- ReinsertList.pages[i].level) == -1)
+ int res;
+ if ((res=
+ maria_rtree_insert_level(info, keynr, k, key_length,
+ ReinsertList.pages[i].level)) == -1)
{
my_afree(page_buf);
goto err1;
}
+ if (res)
+ {
+ ulong j;
+ DBUG_PRINT("rtree", ("root has been split, adjust levels"));
+ for (j= i; j < ReinsertList.n_pages; j++)
+ {
+ ReinsertList.pages[j].level++;
+ DBUG_PRINT("rtree", ("keys from page: %lu now level: %d",
+ (ulong) ReinsertList.pages[i].offs,
+ ReinsertList.pages[i].level));
+ }
+ }
}
my_afree(page_buf);
if (_ma_dispose(info, keyinfo, ReinsertList.pages[i].offs,
@@ -973,19 +1024,19 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, uchar *key, uint key_length)
info->s->state.key_root[keynr] = new_root;
}
info->update= HA_STATE_DELETED;
- return 0;
+ DBUG_RETURN(0);
err1:
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
case 1: /* not found */
{
my_errno = HA_ERR_KEY_NOT_FOUND;
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
default:
case -1: /* error */
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
}
}
diff --git a/storage/maria/ma_rt_key.c b/storage/maria/ma_rt_key.c
index 1b9f246081d..b74d5d06690 100644
--- a/storage/maria/ma_rt_key.c
+++ b/storage/maria/ma_rt_key.c
@@ -34,6 +34,7 @@ int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key,
{
uint page_size = maria_data_on_page(page_buf);
uint nod_flag = _ma_test_if_nod(page_buf);
+ DBUG_ENTER("maria_rtree_add_key");
if (page_size + key_length + info->s->base.rec_reflength <=
keyinfo->block_length)
@@ -42,22 +43,27 @@ int maria_rtree_add_key(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key,
if (nod_flag)
{
/* save key */
+ DBUG_ASSERT(_ma_kpos(nod_flag, key) < info->state->key_file_length);
memcpy(rt_PAGE_END(page_buf), key - nod_flag, key_length + nod_flag);
page_size += key_length + nod_flag;
}
else
{
/* save key */
+ DBUG_ASSERT(_ma_dpos(info, nod_flag, key + key_length +
+ info->s->base.rec_reflength) <
+ info->state->data_file_length +
+ info->s->base.pack_reclength);
memcpy(rt_PAGE_END(page_buf), key, key_length +
info->s->base.rec_reflength);
page_size += key_length + info->s->base.rec_reflength;
}
maria_putint(page_buf, page_size, nod_flag);
- return 0;
+ DBUG_RETURN(0);
}
- return (maria_rtree_split_page(info, keyinfo, page_buf, key, key_length,
- new_page) ? -1 : 1);
+ DBUG_RETURN(maria_rtree_split_page(info, keyinfo, page_buf, key, key_length,
+ new_page) ? -1 : 1);
}
@@ -91,11 +97,13 @@ int maria_rtree_delete_key(MARIA_HA *info, uchar *page_buf, uchar *key,
int maria_rtree_set_key_mbr(MARIA_HA *info, MARIA_KEYDEF *keyinfo, uchar *key,
uint key_length, my_off_t child_page)
{
+ DBUG_ENTER("maria_rtree_set_key_mbr");
if (!_ma_fetch_keypage(info, keyinfo, child_page,
DFLT_INIT_HITS, info->buff, 0))
- return -1;
+ DBUG_RETURN(-1);
- return maria_rtree_page_mbr(info, keyinfo->seg, info->buff, key, key_length);
+ DBUG_RETURN(maria_rtree_page_mbr(info, keyinfo->seg,
+ info->buff, key, key_length));
}
#endif /*HAVE_RTREE_KEYS*/
diff --git a/storage/maria/ma_rt_split.c b/storage/maria/ma_rt_split.c
index 9d195d802c1..a91eaa47bea 100644
--- a/storage/maria/ma_rt_split.c
+++ b/storage/maria/ma_rt_split.c
@@ -266,13 +266,15 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
uint full_length= key_length + (nod_flag ? nod_flag :
info->s->base.rec_reflength);
int max_keys= (maria_data_on_page(page)-2) / (full_length);
+ DBUG_ENTER("maria_rtree_split_page");
+ DBUG_PRINT("rtree", ("splitting block"));
n_dim = keyinfo->keysegs / 2;
if (!(coord_buf= (double*) my_alloca(n_dim * 2 * sizeof(double) *
(max_keys + 1 + 4) +
sizeof(SplitStruct) * (max_keys + 1))))
- return -1;
+ DBUG_RETURN(-1); /* purecov: inspected */
task= (SplitStruct *)(coord_buf + n_dim * 2 * (max_keys + 1 + 4));
@@ -343,12 +345,18 @@ int maria_rtree_split_page(MARIA_HA *info, MARIA_KEYDEF *keyinfo,
else
err_code= _ma_write_keypage(info, keyinfo, *new_page_offs,
DFLT_INIT_HITS, new_page);
+ DBUG_PRINT("rtree", ("split new block: %lu", (ulong) *new_page_offs));
my_afree((uchar*)new_page);
split_err:
+ /**
+ @todo the cast below is useless (coord_buf is uchar*); at the moment we
+ changed all "byte" to "uchar", some casts became useless and should be
+ removed.
+ */
my_afree((uchar*) coord_buf);
- return err_code;
+ DBUG_RETURN(err_code);
}
#endif /*HAVE_RTREE_KEYS*/
diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c
index d9bc5cd6264..8cb3e56e646 100644
--- a/storage/maria/ma_search.c
+++ b/storage/maria/ma_search.c
@@ -927,11 +927,16 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
/*
Keys are compressed the following way:
- prefix length Packed length of prefix for the prev key. (1 or 3 bytes)
+ prefix length Packed length of prefix common with prev key. (1 or 3 bytes)
for each key segment:
[is null] Null indicator if can be null (1 byte, zero means null)
[length] Packed length if varlength (1 or 3 bytes)
+ key segment 'length' bytes of key segment value
pointer Reference to the data file (last_keyseg->length).
+
+ get_key_length() is a macro. It gets the prefix length from 'page'
+ and puts it into 'length'. It increments 'page' by 1 or 3, depending
+ on the packed length of the prefix length.
*/
get_key_length(length,page);
if (length)
@@ -946,34 +951,44 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0); /* Wrong key */
}
- from=key; from_end=key+length;
+ /* Key is packed against prev key, take prefix from prev key. */
+ from= key;
+ from_end= key + length;
}
else
{
- from=page; from_end=page_end; /* Not packed key */
+ /* Key is not packed against prev key, take all from page buffer. */
+ from= page;
+ from_end= page_end;
}
/*
- The trouble is that key is split in two parts:
- The first part is in from ...from_end-1.
- The second part starts at page
+ The trouble is that key can be split in two parts:
+ The first part (prefix) is in from .. from_end - 1.
+ The second part starts at page.
+ The split can be at every byte position. So we need to check for
+ the end of the first part before using every byte.
*/
for (keyseg=keyinfo->seg ; keyseg->type ;keyseg++)
{
if (keyseg->flag & HA_NULL_PART)
{
+ /* If prefix is used up, switch to rest. */
if (from == from_end) { from=page; from_end=page_end; }
if (!(*key++ = *from++))
continue; /* Null part */
}
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
- /* Get length of dynamic length key part */
+ /* If prefix is used up, switch to rest. */
if (from == from_end) { from=page; from_end=page_end; }
+ /* Get length of dynamic length key part */
if ((length= (uint) (uchar) (*key++ = *from++)) == 255)
{
+ /* If prefix is used up, switch to rest. */
if (from == from_end) { from=page; from_end=page_end; }
length= ((uint) (uchar) ((*key++ = *from++))) << 8;
+ /* If prefix is used up, switch to rest. */
if (from == from_end) { from=page; from_end=page_end; }
length+= (uint) (uchar) ((*key++ = *from++));
}
@@ -994,14 +1009,26 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
key+=length;
from+=length;
}
+ /*
+ Last segment (type == 0) contains length of data pointer.
+ If we have mixed key blocks with data pointer and key block pointer,
+ we have to copy both.
+ */
length=keyseg->length+nod_flag;
if ((tmp=(uint) (from_end-from)) <= length)
{
+ /* Remaining length is less or equal max possible length. */
memcpy(key+tmp,page,length-tmp); /* Get last part of key */
*page_pos= page+length-tmp;
}
else
{
+ /*
+ Remaining length is greater than max possible length.
+ This can happen only if we switched to the new key bytes already.
+ 'page_end' is calculated with MI_MAX_KEY_BUFF. So it can be far
+ behind the real end of the key.
+ */
if (from_end != page_end)
{
DBUG_PRINT("error",("Error when unpacking key"));
@@ -1009,6 +1036,7 @@ uint _ma_get_binary_pack_key(register MARIA_KEYDEF *keyinfo, uint nod_flag,
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0); /* Error */
}
+ /* Copy data pointer and, if appropriate, key block pointer. */
memcpy((uchar*) key,(uchar*) from,(size_t) length);
*page_pos= from+length;
}
diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c
index bc2b75807d9..2851a3a09dd 100644
--- a/storage/maria/ma_sort.c
+++ b/storage/maria/ma_sort.c
@@ -138,8 +138,9 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
while (memavl >= MIN_SORT_MEMORY)
{
- if ((my_off_t) (records+1)*(sort_length+sizeof(char*)) <=
- (my_off_t) memavl)
+ if ((records < UINT_MAX32) &&
+ ((my_off_t) (records + 1) *
+ (sort_length + sizeof(char*)) <= (my_off_t) memavl))
keys= records+1;
else
do
@@ -151,7 +152,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
keys < (uint) maxbuffer)
{
_ma_check_print_error(info->sort_info->param,
- "sort_buffer_size is to small");
+ "maria_sort_buffer_size is too small");
goto err;
}
}
@@ -175,7 +176,8 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
}
if (memavl < MIN_SORT_MEMORY)
{
- _ma_check_print_error(info->sort_info->param,"Sort buffer to small"); /* purecov: tested */
+ _ma_check_print_error(info->sort_info->param, "Maria sort buffer"
+ " too small"); /* purecov: tested */
goto err; /* purecov: tested */
}
(*info->lock_in_memory)(info->sort_info->param);/* Everything is allocated */
@@ -369,7 +371,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg)
keys < (uint) maxbuffer)
{
_ma_check_print_error(sort_param->sort_info->param,
- "sort_buffer_size is to small");
+ "maria_sort_buffer_size is too small");
goto err;
}
}
@@ -397,7 +399,7 @@ pthread_handler_t _ma_thr_find_all_keys(void *arg)
if (memavl < MIN_SORT_MEMORY)
{
_ma_check_print_error(sort_param->sort_info->param,
- "Sort buffer too small");
+ "Maria sort buffer too small");
goto err; /* purecov: tested */
}
@@ -775,7 +777,7 @@ static int NEAR_F merge_many_buff(MARIA_SORT_PARAM *info, uint keys,
{
if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
buffpek+i,buffpek+i+MERGEBUFF-1))
- break; /* purecov: inspected */
+ goto cleanup;
}
if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
buffpek+i,buffpek+ *maxbuffer))
@@ -785,6 +787,7 @@ static int NEAR_F merge_many_buff(MARIA_SORT_PARAM *info, uint keys,
temp=from_file; from_file=to_file; to_file=temp;
*maxbuffer= (int) (lastbuff-buffpek)-1;
}
+cleanup:
close_cached_file(to_file); /* This holds old result */
if (to_file == t_file)
*t_file=t_file2; /* Copy result file */
diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h
index 62f37077ceb..e2dc7d3be86 100644
--- a/storage/maria/maria_def.h
+++ b/storage/maria/maria_def.h
@@ -442,6 +442,7 @@ struct st_maria_info
enum ha_rkey_function last_key_func; /* CONTAIN, OVERLAP, etc */
uint save_lastkey_length;
uint pack_key_length; /* For MARIAMRG */
+ uint16 last_used_keyseg; /* For MARIAMRG */
int errkey; /* Got last error on this key */
int lock_type; /* How database was locked */
int tmp_lock_type; /* When locked by readinfo */
@@ -749,7 +750,7 @@ extern my_off_t _ma_new(MARIA_HA *info, MARIA_KEYDEF *keyinfo, int level);
extern uint _ma_make_key(MARIA_HA *info, uint keynr, uchar *key,
const uchar *record, MARIA_RECORD_POS filepos);
extern uint _ma_pack_key(MARIA_HA *info, uint keynr, uchar *key,
- const uchar *old, uint key_length,
+ const uchar *old, key_part_map keypart_map,
HA_KEYSEG ** last_used_keyseg);
extern int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS);
extern int _ma_read_cache(IO_CACHE *info, uchar *buff, MARIA_RECORD_POS pos,
@@ -760,7 +761,7 @@ extern my_bool _ma_alloc_buffer(uchar **old_addr, size_t *old_size,
size_t new_size);
extern ulong _ma_rec_unpack(MARIA_HA *info, uchar *to, uchar *from,
ulong reclength);
-extern my_bool _ma_rec_check(MARIA_HA *info, const char *record,
+extern my_bool _ma_rec_check(MARIA_HA *info, const uchar *record,
uchar *packpos, ulong packed_length,
my_bool with_checkum, ha_checksum checksum);
extern int _ma_write_part_record(MARIA_HA *info, my_off_t filepos,