Commit c098d196 authored by unknown's avatar unknown

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
parent 0ed84b06
......@@ -265,8 +265,8 @@ extern struct st_maria_info *maria_clone(struct st_maria_share *share, int mode)
extern int maria_panic(enum ha_panic_function function);
extern int maria_rfirst(struct st_maria_info *file, uchar *buf, int inx);
extern int maria_rkey(struct st_maria_info *file, uchar *buf, int inx,
const uchar *key,
uint key_len, enum ha_rkey_function search_flag);
const uchar *key, key_part_map keypart_map,
enum ha_rkey_function search_flag);
extern int maria_rlast(struct st_maria_info *file, uchar *buf, int inx);
extern int maria_rnext(struct st_maria_info *file, uchar *buf, int inx);
extern int maria_rnext_same(struct st_maria_info *info, uchar *buf);
......
......@@ -2522,10 +2522,8 @@ uchar *key_cache_read(KEY_CACHE *keycache,
int error=0;
uchar *start= buff;
DBUG_ENTER("key_cache_read");
DBUG_PRINT("enter", ("fd: %u pos: %lu page: %lu length: %u",
(uint) file, (ulong) filepos,
(ulong) (filepos / keycache->key_cache_block_size),
length));
DBUG_PRINT("enter", ("fd: %u pos: %lu length: %u",
(uint) file, (ulong) filepos, length));
if (keycache->key_cache_inited)
{
......@@ -2979,10 +2977,10 @@ int key_cache_write(KEY_CACHE *keycache,
int error=0;
DBUG_ENTER("key_cache_write");
DBUG_PRINT("enter",
("fd: %u pos: %lu page: %lu length: %u block_length: %u",
(uint) file, (ulong) filepos,
(ulong) (filepos / keycache->key_cache_block_size),
length, block_length));
("fd: %u pos: %lu length: %u block_length: %u key_block_length:
%u",
(uint) file, (ulong) filepos, length, block_length,
keycache ? keycache->key_cache_block_size : 0));
if (!dont_write)
{
......
......@@ -2767,7 +2767,7 @@ String *Item_xml_str_func::parse_xml(String *raw_xml, String *parsed_xml_buf)
if ((rc= my_xml_parse(&p, raw_xml->ptr(), raw_xml->length())) != MY_XML_OK)
{
char buf[128];
my_snprintf(buf, sizeof(buf)-1, "parse error at line %d pos %u: %s",
my_snprintf(buf, sizeof(buf)-1, "parse error at line %d pos %lu: %s",
my_xml_error_lineno(&p) + 1,
my_xml_error_pos(&p) + 1,
my_xml_error_string(&p));
......
......@@ -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 @@ int ha_maria::dump(THD * thd, int fd)
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
......
......@@ -68,18 +68,21 @@ class ha_maria :public handler
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);
......
......@@ -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);
......
......@@ -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 */
......
......@@ -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))
{
......
......@@ -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))
......
......@@ -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))
{
......
......@@ -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 &&
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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 */
......
......@@ -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;
}
......
......@@ -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)
......
......@@ -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);
......
......@@ -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)
{
......
......@@ -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););
}
......
......@@ -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 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key,
break;
}
}
return res;
DBUG_RETURN(res);
}
......@@ -721,9 +730,10 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, uchar *key,
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 */
}
}
......
......@@ -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*/
......@@ -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*/
......@@ -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;
}
......
......@@ -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 */
......
......@@ -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,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment