summaryrefslogtreecommitdiff
path: root/storage
diff options
context:
space:
mode:
authorunknown <guilhem@gbichot3.local>2007-03-01 18:23:58 +0100
committerunknown <guilhem@gbichot3.local>2007-03-01 18:23:58 +0100
commit3411bfe05a2a77c6c5b9911237792eb436f16543 (patch)
tree400242e73e0c9b50c2036048184c136608b29219 /storage
parentea57b3d4a066a5507a7e322b53e3acab24a2855e (diff)
downloadmariadb-git-3411bfe05a2a77c6c5b9911237792eb436f16543.tar.gz
merge from MyISAM into Maria (last step of merge of 5.1 into Maria).
Tests: "maria" and "ps_maria" fail like before merge (assertions), "ma_test_all" fails like before merge (ma_test2 segfaults, I'll try to find out why). mysys/mf_pagecache.c: using a more distinctive tag storage/maria/ha_maria.cc: merge from MyISAM into Maria storage/maria/ma_check.c: merge from MyISAM into Maria storage/maria/ma_close.c: TODO as a word storage/maria/ma_create.c: merge from MyISAM into Maria storage/maria/ma_delete_all.c: TODO as a word storage/maria/ma_delete_table.c: TODO as a word storage/maria/ma_dynrec.c: merge from MyISAM into Maria storage/maria/ma_extra.c: merge from MyISAM into Maria storage/maria/ma_ft_boolean_search.c: merge from MyISAM into Maria storage/maria/ma_locking.c: merge from MyISAM into Maria storage/maria/ma_loghandler.c: fix for compiler warning storage/maria/ma_open.c: merge from MyISAM into Maria. I will ask Monty to check the ASKMONTY-marked piece of code. storage/maria/ma_packrec.c: merge from MyISAM into Maria storage/maria/ma_range.c: merge from MyISAM into Maria storage/maria/ma_rename.c: TODO as a word storage/maria/ma_rt_index.c: merge from MyISAM into Maria storage/maria/ma_rt_split.c: merge from MyISAM into Maria storage/maria/ma_search.c: merge from MyISAM into Maria storage/maria/ma_sort.c: merge from MyISAM into Maria storage/maria/ma_update.c: merge from MyISAM into Maria storage/maria/ma_write.c: merge from MyISAM into Maria storage/maria/maria_chk.c: merge from MyISAM into Maria storage/maria/maria_def.h: merge from MyISAM into Maria storage/maria/maria_pack.c: merge from MyISAM into Maria storage/maria/unittest/ma_test_loghandler_pagecache-t.c: fix for compiler warning storage/myisam/ha_myisam.cc: merge from MyISAM into Maria storage/myisammrg/ha_myisammrg.cc: merge from MyISAM into Maria
Diffstat (limited to 'storage')
-rw-r--r--storage/maria/ha_maria.cc608
-rw-r--r--storage/maria/ma_check.c8
-rw-r--r--storage/maria/ma_close.c2
-rw-r--r--storage/maria/ma_create.c15
-rw-r--r--storage/maria/ma_delete_all.c12
-rw-r--r--storage/maria/ma_delete_table.c4
-rw-r--r--storage/maria/ma_dynrec.c18
-rw-r--r--storage/maria/ma_extra.c7
-rw-r--r--storage/maria/ma_ft_boolean_search.c16
-rw-r--r--storage/maria/ma_locking.c9
-rw-r--r--storage/maria/ma_loghandler.c2
-rw-r--r--storage/maria/ma_open.c57
-rw-r--r--storage/maria/ma_packrec.c343
-rw-r--r--storage/maria/ma_range.c1
-rw-r--r--storage/maria/ma_rename.c4
-rw-r--r--storage/maria/ma_rt_index.c3
-rw-r--r--storage/maria/ma_rt_split.c4
-rw-r--r--storage/maria/ma_search.c14
-rw-r--r--storage/maria/ma_sort.c6
-rw-r--r--storage/maria/ma_update.c3
-rw-r--r--storage/maria/ma_write.c4
-rw-r--r--storage/maria/maria_chk.c1
-rw-r--r--storage/maria/maria_def.h1
-rw-r--r--storage/maria/maria_pack.c9
-rw-r--r--storage/maria/unittest/ma_test_loghandler_pagecache-t.c2
-rw-r--r--storage/myisam/ha_myisam.cc12
-rw-r--r--storage/myisammrg/ha_myisammrg.cc18
27 files changed, 868 insertions, 315 deletions
diff --git a/storage/maria/ha_maria.cc b/storage/maria/ha_maria.cc
index 102f987f01a..a5e0722fd4a 100644
--- a/storage/maria/ha_maria.cc
+++ b/storage/maria/ha_maria.cc
@@ -108,6 +108,315 @@ static void _ma_check_print_msg(HA_CHECK *param, const char *msg_type,
return;
}
+
+
+/*
+ Convert TABLE object to Maria key and column definition
+
+ SYNOPSIS
+ table2maria()
+ table_arg in TABLE object.
+ keydef_out out Maria key definition.
+ recinfo_out out Maria column definition.
+ records_out out Number of fields.
+
+ DESCRIPTION
+ This function will allocate and initialize Maria key and column
+ definition for further use in ma_create or for a check for underlying
+ table conformance in merge engine.
+
+ RETURN VALUE
+ 0 OK
+ !0 error code
+*/
+
+int table2maria(TABLE *table_arg, MARIA_KEYDEF **keydef_out,
+ MARIA_COLUMNDEF **recinfo_out, uint *records_out)
+{
+ uint i, j, recpos, minpos, fieldpos, temp_length, length;
+ enum ha_base_keytype type= HA_KEYTYPE_BINARY;
+ byte *record;
+ KEY *pos;
+ MARIA_KEYDEF *keydef;
+ MARIA_COLUMNDEF *recinfo, *recinfo_pos;
+ HA_KEYSEG *keyseg;
+ TABLE_SHARE *share= table_arg->s;
+ uint options= share->db_options_in_use;
+ DBUG_ENTER("table2maria");
+ if (!(my_multi_malloc(MYF(MY_WME),
+ recinfo_out, (share->fields * 2 + 2) * sizeof(MARIA_COLUMNDEF),
+ keydef_out, share->keys * sizeof(MARIA_KEYDEF),
+ &keyseg,
+ (share->key_parts + share->keys) * sizeof(HA_KEYSEG),
+ NullS)))
+ DBUG_RETURN(HA_ERR_OUT_OF_MEM); /* purecov: inspected */
+ keydef= *keydef_out;
+ recinfo= *recinfo_out;
+ pos= table_arg->key_info;
+ for (i= 0; i < share->keys; i++, pos++)
+ {
+ keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
+ keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
+ (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
+ pos->algorithm;
+ keydef[i].block_length= pos->block_size;
+ keydef[i].seg= keyseg;
+ keydef[i].keysegs= pos->key_parts;
+ for (j= 0; j < pos->key_parts; j++)
+ {
+ Field *field= pos->key_part[j].field;
+ type= field->key_type();
+ keydef[i].seg[j].flag= pos->key_part[j].key_part_flag;
+
+ if (options & HA_OPTION_PACK_KEYS ||
+ (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
+ HA_SPACE_PACK_USED)))
+ {
+ if (pos->key_part[j].length > 8 &&
+ (type == HA_KEYTYPE_TEXT ||
+ type == HA_KEYTYPE_NUM ||
+ (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
+ {
+ /* No blobs here */
+ if (j == 0)
+ keydef[i].flag|= HA_PACK_KEY;
+ if (!(field->flags & ZEROFILL_FLAG) &&
+ (field->type() == MYSQL_TYPE_STRING ||
+ field->type() == MYSQL_TYPE_VAR_STRING ||
+ ((int) (pos->key_part[j].length - field->decimals())) >= 4))
+ keydef[i].seg[j].flag|= HA_SPACE_PACK;
+ }
+ else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
+ keydef[i].flag|= HA_BINARY_PACK_KEY;
+ }
+ keydef[i].seg[j].type= (int) type;
+ keydef[i].seg[j].start= pos->key_part[j].offset;
+ keydef[i].seg[j].length= pos->key_part[j].length;
+ keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end=
+ keydef[i].seg[j].bit_length= 0;
+ keydef[i].seg[j].bit_pos= 0;
+ keydef[i].seg[j].language= field->charset()->number;
+
+ if (field->null_ptr)
+ {
+ keydef[i].seg[j].null_bit= field->null_bit;
+ keydef[i].seg[j].null_pos= (uint) (field->null_ptr-
+ (uchar*) table_arg->record[0]);
+ }
+ else
+ {
+ keydef[i].seg[j].null_bit= 0;
+ keydef[i].seg[j].null_pos= 0;
+ }
+ if (field->type() == MYSQL_TYPE_BLOB ||
+ field->type() == MYSQL_TYPE_GEOMETRY)
+ {
+ keydef[i].seg[j].flag|= HA_BLOB_PART;
+ /* save number of bytes used to pack length */
+ keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
+ share->blob_ptr_size);
+ }
+ else if (field->type() == MYSQL_TYPE_BIT)
+ {
+ keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
+ keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
+ keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
+ (uchar*) table_arg->record[0]);
+ }
+ }
+ keyseg+= pos->key_parts;
+ }
+ if (table_arg->found_next_number_field)
+ keydef[share->next_number_index].flag|= HA_AUTO_KEY;
+ record= table_arg->record[0];
+ recpos= 0;
+ recinfo_pos= recinfo;
+ while (recpos < (uint) share->reclength)
+ {
+ Field **field, *found= 0;
+ minpos= share->reclength;
+ length= 0;
+
+ for (field= table_arg->field; *field; field++)
+ {
+ if ((fieldpos= (*field)->offset(record)) >= recpos &&
+ fieldpos <= minpos)
+ {
+ /* skip null fields */
+ if (!(temp_length= (*field)->pack_length_in_rec()))
+ continue; /* Skip null-fields */
+ if (! found || fieldpos < minpos ||
+ (fieldpos == minpos && temp_length < length))
+ {
+ minpos= fieldpos;
+ found= *field;
+ length= temp_length;
+ }
+ }
+ }
+ DBUG_PRINT("loop", ("found: 0x%lx recpos: %d minpos: %d length: %d",
+ (long) found, recpos, minpos, length));
+ if (recpos != minpos)
+ { // Reserved space (Null bits?)
+ bzero((char*) recinfo_pos, sizeof(*recinfo_pos));
+ recinfo_pos->type= FIELD_NORMAL;
+ recinfo_pos++->length= (uint16) (minpos - recpos);
+ }
+ if (!found)
+ break;
+
+ if (found->flags & BLOB_FLAG)
+ recinfo_pos->type= FIELD_BLOB;
+ else if (found->type() == MYSQL_TYPE_VARCHAR)
+ recinfo_pos->type= FIELD_VARCHAR;
+ else if (!(options & HA_OPTION_PACK_RECORD))
+ recinfo_pos->type= FIELD_NORMAL;
+ else if (found->zero_pack())
+ recinfo_pos->type= FIELD_SKIP_ZERO;
+ else
+ recinfo_pos->type= ((length <= 3 ||
+ (found->flags & ZEROFILL_FLAG)) ?
+ FIELD_NORMAL :
+ found->type() == MYSQL_TYPE_STRING ||
+ found->type() == MYSQL_TYPE_VAR_STRING ?
+ FIELD_SKIP_ENDSPACE :
+ FIELD_SKIP_PRESPACE);
+ if (found->null_ptr)
+ {
+ recinfo_pos->null_bit= found->null_bit;
+ recinfo_pos->null_pos= (uint) (found->null_ptr -
+ (uchar*) table_arg->record[0]);
+ }
+ else
+ {
+ recinfo_pos->null_bit= 0;
+ recinfo_pos->null_pos= 0;
+ }
+ (recinfo_pos++)->length= (uint16) length;
+ recpos= minpos + length;
+ DBUG_PRINT("loop", ("length: %d type: %d",
+ recinfo_pos[-1].length,recinfo_pos[-1].type));
+ }
+ *records_out= (uint) (recinfo_pos - recinfo);
+ DBUG_RETURN(0);
+}
+
+
+/*
+ Check for underlying table conformance
+
+ SYNOPSIS
+ maria_check_definition()
+ t1_keyinfo in First table key definition
+ t1_recinfo in First table record definition
+ t1_keys in Number of keys in first table
+ t1_recs in Number of records in first table
+ t2_keyinfo in Second table key definition
+ t2_recinfo in Second table record definition
+ t2_keys in Number of keys in second table
+ t2_recs in Number of records in second table
+ strict in Strict check switch
+
+ DESCRIPTION
+ This function compares two Maria definitions. By intention it was done
+ to compare merge table definition against underlying table definition.
+ It may also be used to compare dot-frm and MAI definitions of Maria
+ table as well to compare different Maria table definitions.
+
+ For merge table it is not required that number of keys in merge table
+ must exactly match number of keys in underlying table. When calling this
+ function for underlying table conformance check, 'strict' flag must be
+ set to false, and converted merge definition must be passed as t1_*.
+
+ Otherwise 'strict' flag must be set to 1 and it is not required to pass
+ converted dot-frm definition as t1_*.
+
+ RETURN VALUE
+ 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).
+*/
+int maria_check_definition(MARIA_KEYDEF *t1_keyinfo,
+ MARIA_COLUMNDEF *t1_recinfo,
+ uint t1_keys, uint t1_recs,
+ MARIA_KEYDEF *t2_keyinfo,
+ MARIA_COLUMNDEF *t2_recinfo,
+ uint t2_keys, uint t2_recs, bool strict)
+{
+ uint i, j;
+ DBUG_ENTER("maria_check_definition");
+ if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
+ {
+ DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
+ t1_keys, t2_keys));
+ DBUG_RETURN(1);
+ }
+ if (t1_recs != t2_recs)
+ {
+ DBUG_PRINT("error", ("Number of recs differs: t1_recs=%u, t2_recs=%u",
+ t1_recs, t2_recs));
+ DBUG_RETURN(1);
+ }
+ for (i= 0; i < t1_keys; i++)
+ {
+ HA_KEYSEG *t1_keysegs= t1_keyinfo[i].seg;
+ HA_KEYSEG *t2_keysegs= t2_keyinfo[i].seg;
+ if (t1_keyinfo[i].keysegs != t2_keyinfo[i].keysegs ||
+ t1_keyinfo[i].key_alg != t2_keyinfo[i].key_alg)
+ {
+ DBUG_PRINT("error", ("Key %d has different definition", i));
+ DBUG_PRINT("error", ("t1_keysegs=%d, t1_key_alg=%d",
+ t1_keyinfo[i].keysegs, t1_keyinfo[i].key_alg));
+ DBUG_PRINT("error", ("t2_keysegs=%d, t2_key_alg=%d",
+ t2_keyinfo[i].keysegs, t2_keyinfo[i].key_alg));
+ DBUG_RETURN(1);
+ }
+ for (j= t1_keyinfo[i].keysegs; j--;)
+ {
+ if (t1_keysegs[j].type != t2_keysegs[j].type ||
+ t1_keysegs[j].language != t2_keysegs[j].language ||
+ t1_keysegs[j].null_bit != t2_keysegs[j].null_bit ||
+ t1_keysegs[j].length != t2_keysegs[j].length)
+ {
+ DBUG_PRINT("error", ("Key segment %d (key %d) has different "
+ "definition", j, i));
+ DBUG_PRINT("error", ("t1_type=%d, t1_language=%d, t1_null_bit=%d, "
+ "t1_length=%d",
+ t1_keysegs[j].type, t1_keysegs[j].language,
+ t1_keysegs[j].null_bit, t1_keysegs[j].length));
+ DBUG_PRINT("error", ("t2_type=%d, t2_language=%d, t2_null_bit=%d, "
+ "t2_length=%d",
+ t2_keysegs[j].type, t2_keysegs[j].language,
+ t2_keysegs[j].null_bit, t2_keysegs[j].length));
+
+ DBUG_RETURN(1);
+ }
+ }
+ }
+ for (i= 0; i < t1_recs; i++)
+ {
+ MARIA_COLUMNDEF *t1_rec= &t1_recinfo[i];
+ MARIA_COLUMNDEF *t2_rec= &t2_recinfo[i];
+ if (t1_rec->type != t2_rec->type ||
+ t1_rec->length != t2_rec->length ||
+ t1_rec->null_bit != t2_rec->null_bit)
+ {
+ DBUG_PRINT("error", ("Field %d has different definition", i));
+ DBUG_PRINT("error", ("t1_type=%d, t1_length=%d, t1_null_bit=%d",
+ t1_rec->type, t1_rec->length, t1_rec->null_bit));
+ DBUG_PRINT("error", ("t2_type=%d, t2_length=%d, t2_null_bit=%d",
+ t2_rec->type, t2_rec->length, t2_rec->null_bit));
+ DBUG_RETURN(1);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
extern "C" {
volatile int *_ma_killed_ptr(HA_CHECK *param)
@@ -315,17 +624,33 @@ bool ha_maria::check_if_locking_is_allowed(uint sql_command,
int ha_maria::open(const char *name, int mode, uint test_if_locked)
{
uint i;
+
+#ifdef NOT_USED
+ /*
+ If the user wants to have memory mapped data files, add an
+ open_flag. Do not memory map temporary tables because they are
+ expected to be inserted and thus extended a lot. Memory mapping is
+ efficient for files that keep their size, but very inefficient for
+ growing files. Using an open_flag instead of calling ma_extra(...
+ HA_EXTRA_MMAP ...) after maxs_open() has the advantage that the
+ mapping is not repeated for every open, but just done on the initial
+ open, when the MyISAM share is created. Everytime the server
+ requires to open a new instance of a table it calls this method. We
+ will always supply HA_OPEN_MMAP for a permanent table. However, the
+ Maria storage engine will ignore this flag if this is a secondary
+ open of a table that is in use by other threads already (if the
+ Maria share exists already).
+ */
+ if (!(test_if_locked & HA_OPEN_TMP_TABLE) && opt_maria_use_mmap)
+ test_if_locked|= HA_OPEN_MMAP;
+#endif
+
if (!(file= maria_open(name, mode, test_if_locked | HA_OPEN_FROM_SQL_LAYER)))
return (my_errno ? my_errno : -1);
if (test_if_locked & (HA_OPEN_IGNORE_IF_LOCKED | HA_OPEN_TMP_TABLE))
VOID(maria_extra(file, HA_EXTRA_NO_WAIT_LOCK, 0));
-#ifdef NOT_USED
- if (!(test_if_locked & HA_OPEN_TMP_TABLE) && opt_maria_use_mmap)
- VOID(maria_extra(file, HA_EXTRA_MMAP, 0));
-#endif
-
info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
VOID(maria_extra(file, HA_EXTRA_WAIT_LOCK, 0));
@@ -684,11 +1009,11 @@ int ha_maria::optimize(THD * thd, HA_CHECK_OPT *check_opt)
}
-int ha_maria::repair(THD *thd, HA_CHECK &param, bool optimize)
+int ha_maria::repair(THD *thd, HA_CHECK &param, bool do_optimize)
{
int error= 0;
uint local_testflag= param.testflag;
- bool optimize_done= !optimize, statistics_done= 0;
+ bool optimize_done= !do_optimize, statistics_done= 0;
const char *old_proc_info= thd->proc_info;
char fixed_name[FN_REFLEN];
MARIA_SHARE *share= file->s;
@@ -712,7 +1037,7 @@ int ha_maria::repair(THD *thd, HA_CHECK &param, bool optimize)
DBUG_RETURN(HA_ADMIN_FAILED);
}
- if (!optimize ||
+ if (!do_optimize ||
((file->state->del || share->state.split != file->state->records) &&
(!(param.testflag & T_QUICK) ||
!(share->state.changed & STATE_NOT_OPTIMIZED_KEYS))))
@@ -1364,47 +1689,47 @@ int ha_maria::rnd_pos(byte * buf, byte *pos)
void ha_maria::position(const byte * record)
{
- my_off_t position= maria_position(file);
- my_store_ptr(ref, ref_length, position);
+ my_off_t row_position= maria_position(file);
+ my_store_ptr(ref, ref_length, row_position);
}
int ha_maria::info(uint flag)
{
- MARIA_INFO info;
+ MARIA_INFO maria_info;
char name_buff[FN_REFLEN];
- (void) maria_status(file, &info, flag);
+ (void) maria_status(file, &maria_info, flag);
if (flag & HA_STATUS_VARIABLE)
{
- stats.records= info.records;
- stats.deleted= info.deleted;
- stats.data_file_length= info.data_file_length;
- stats.index_file_length= info.index_file_length;
- stats.delete_length= info.delete_length;
- stats.check_time= info.check_time;
- stats.mean_rec_length= info.mean_reclength;
+ stats.records= maria_info.records;
+ stats.deleted= maria_info.deleted;
+ stats.data_file_length= maria_info.data_file_length;
+ stats.index_file_length= maria_info.index_file_length;
+ stats.delete_length= maria_info.delete_length;
+ stats.check_time= maria_info.check_time;
+ stats.mean_rec_length= maria_info.mean_reclength;
}
if (flag & HA_STATUS_CONST)
{
TABLE_SHARE *share= table->s;
- stats.max_data_file_length= info.max_data_file_length;
- stats.max_index_file_length= info.max_index_file_length;
- stats.create_time= info.create_time;
- ref_length= info.reflength;
- share->db_options_in_use= info.options;
+ stats.max_data_file_length= maria_info.max_data_file_length;
+ stats.max_index_file_length= maria_info.max_index_file_length;
+ stats.create_time= maria_info.create_time;
+ ref_length= maria_info.reflength;
+ share->db_options_in_use= maria_info.options;
stats.block_size= maria_block_size;
/* Update share */
if (share->tmp_table == NO_TMP_TABLE)
pthread_mutex_lock(&share->mutex);
share->keys_in_use.set_prefix(share->keys);
- share->keys_in_use.intersect_extended(info.key_map);
+ share->keys_in_use.intersect_extended(maria_info.key_map);
share->keys_for_keyread.intersect(share->keys_in_use);
- share->db_record_offset= info.record_offset;
+ share->db_record_offset= maria_info.record_offset;
if (share->key_parts)
memcpy((char*) table->key_info[0].rec_per_key,
- (char*) info.rec_per_key,
+ (char*) maria_info.rec_per_key,
sizeof(table->key_info[0].rec_per_key) * share->key_parts);
if (share->tmp_table == NO_TMP_TABLE)
pthread_mutex_unlock(&share->mutex);
@@ -1414,21 +1739,23 @@ int ha_maria::info(uint flag)
if table is symlinked (Ie; Real name is not same as generated name)
*/
data_file_name= index_file_name= 0;
- fn_format(name_buff, file->filename, "", MARIA_NAME_DEXT, MY_APPEND_EXT);
- if (strcmp(name_buff, info.data_file_name))
- data_file_name= info.data_file_name;
- fn_format(name_buff, file->filename, "", MARIA_NAME_IEXT, MY_APPEND_EXT);
- if (strcmp(name_buff, info.index_file_name))
- index_file_name= info.index_file_name;
+ fn_format(name_buff, file->filename, "", MARIA_NAME_DEXT,
+ MY_APPEND_EXT | MY_UNPACK_FILENAME);
+ if (strcmp(name_buff, maria_info.data_file_name))
+ data_file_name=maria_info.data_file_name;
+ fn_format(name_buff, file->filename, "", MARIA_NAME_IEXT,
+ MY_APPEND_EXT | MY_UNPACK_FILENAME);
+ if (strcmp(name_buff, maria_info.index_file_name))
+ index_file_name=maria_info.index_file_name;
}
if (flag & HA_STATUS_ERRKEY)
{
- errkey= info.errkey;
- my_store_ptr(dup_ref, ref_length, info.dup_key_pos);
+ errkey= maria_info.errkey;
+ my_store_ptr(dup_ref, ref_length, maria_info.dup_key_pos);
}
/* Faster to always update, than to do it based on flag */
- stats.update_time= info.update_time;
- stats.auto_increment_value= info.auto_increment;
+ stats.update_time= maria_info.update_time;
+ stats.auto_increment_value= maria_info.auto_increment;
return 0;
}
@@ -1500,208 +1827,50 @@ void ha_maria::update_create_info(HA_CREATE_INFO *create_info)
int ha_maria::create(const char *name, register TABLE *table_arg,
- HA_CREATE_INFO *info)
+ HA_CREATE_INFO *ha_create_info)
{
int error;
- uint i, j, recpos, minpos, fieldpos, temp_length, length, create_flags= 0;
- bool found_real_auto_increment= 0;
- enum ha_base_keytype type;
+ uint create_flags= 0, records, i;
char buff[FN_REFLEN];
- byte *record;
- KEY *pos;
MARIA_KEYDEF *keydef;
- MARIA_COLUMNDEF *recinfo, *recinfo_pos;
- HA_KEYSEG *keyseg;
+ MARIA_COLUMNDEF *recinfo;
+ MARIA_CREATE_INFO create_info;
TABLE_SHARE *share= table_arg->s;
uint options= share->db_options_in_use;
enum data_file_type row_type;
DBUG_ENTER("ha_maria::create");
-
- type= HA_KEYTYPE_BINARY; // Keep compiler happy
- if (!(my_multi_malloc(MYF(MY_WME),
- &recinfo, (share->fields * 2 + 2) *
- sizeof(MARIA_COLUMNDEF),
- &keydef, share->keys * sizeof(MARIA_KEYDEF),
- &keyseg,
- ((share->key_parts + share->keys) *
- sizeof(HA_KEYSEG)), NullS)))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
-
- pos= table_arg->key_info;
- for (i= 0; i < share->keys; i++, pos++)
- {
- if (pos->flags & HA_USES_PARSER)
- create_flags |= HA_CREATE_RELIES_ON_SQL_LAYER;
- keydef[i].flag= (pos->flags & (HA_NOSAME | HA_FULLTEXT | HA_SPATIAL));
- keydef[i].key_alg= pos->algorithm == HA_KEY_ALG_UNDEF ?
- (pos->flags & HA_SPATIAL ? HA_KEY_ALG_RTREE : HA_KEY_ALG_BTREE) :
- pos->algorithm;
- keydef[i].block_length= pos->block_size;
-
- keydef[i].seg= keyseg;
- keydef[i].keysegs= pos->key_parts;
- for (j= 0; j < pos->key_parts; j++)
- {
- Field *field= pos->key_part[j].field;
- type= field->key_type();
- keydef[i].seg[j].flag= pos->key_part[j].key_part_flag;
-
- if (options & HA_OPTION_PACK_KEYS ||
- (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
- HA_SPACE_PACK_USED)))
- {
- if (pos->key_part[j].length > 8 &&
- (type == HA_KEYTYPE_TEXT ||
- type == HA_KEYTYPE_NUM ||
- (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
- {
- /* No blobs here */
- if (j == 0)
- keydef[i].flag |= HA_PACK_KEY;
- if (!(field->flags & ZEROFILL_FLAG) &&
- (field->type() == MYSQL_TYPE_STRING ||
- field->type() == MYSQL_TYPE_VAR_STRING ||
- ((int) (pos->key_part[j].length - field->decimals())) >= 4))
- keydef[i].seg[j].flag |= HA_SPACE_PACK;
- }
- else if (j == 0 && (!(pos->flags & HA_NOSAME) || pos->key_length > 16))
- keydef[i].flag |= HA_BINARY_PACK_KEY;
- }
- keydef[i].seg[j].type= (int) type;
- keydef[i].seg[j].start= pos->key_part[j].offset;
- keydef[i].seg[j].length= pos->key_part[j].length;
- keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end=
- keydef[i].seg[j].bit_length= 0;
- keydef[i].seg[j].bit_pos= 0;
- keydef[i].seg[j].language= field->charset()->number;
-
- if (field->null_ptr)
- {
- keydef[i].seg[j].null_bit= field->null_bit;
- keydef[i].seg[j].null_pos= (uint) (field->null_ptr -
- (uchar *) table_arg->record[0]);
- }
- else
- {
- keydef[i].seg[j].null_bit= 0;
- keydef[i].seg[j].null_pos= 0;
- }
- if (field->type() == FIELD_TYPE_BLOB ||
- field->type() == FIELD_TYPE_GEOMETRY)
- {
- keydef[i].seg[j].flag |= HA_BLOB_PART;
- /* save number of bytes used to pack length */
- keydef[i].seg[j].bit_start= (uint) (field->pack_length() -
- share->blob_ptr_size);
- }
- else if (field->type() == FIELD_TYPE_BIT)
- {
- keydef[i].seg[j].bit_length= ((Field_bit *) field)->bit_len;
- keydef[i].seg[j].bit_start= ((Field_bit *) field)->bit_ofs;
- keydef[i].seg[j].bit_pos= (uint) (((Field_bit *) field)->bit_ptr -
- (uchar *) table_arg->record[0]);
- }
- }
- keyseg += pos->key_parts;
- }
-
- if (table_arg->found_next_number_field)
+ for (i= 0; i < share->keys; i++)
{
- keydef[share->next_number_index].flag |= HA_AUTO_KEY;
- found_real_auto_increment= share->next_number_key_offset == 0;
- }
-
- record= table_arg->record[0];
- recpos= 0;
- recinfo_pos= recinfo;
- while (recpos < (uint) share->reclength)
- {
- Field **field, *found= 0;
- minpos= share->reclength;
- length= 0;
-
- for (field= table_arg->field; *field; field++)
+ if (table_arg->key_info[i].flags & HA_USES_PARSER)
{
- if ((fieldpos=(*field)->offset(record)) >= recpos &&
- fieldpos <= minpos)
- {
- /* skip null fields */
- if (!(temp_length= (*field)->pack_length_in_rec()))
- continue; /* Skip null-fields */
- if (!found || fieldpos < minpos ||
- (fieldpos == minpos && temp_length < length))
- {
- minpos= fieldpos;
- found= *field;
- length= temp_length;
- }
- }
- }
- DBUG_PRINT("loop", ("found: 0x%lx recpos: %d minpos: %d length: %d",
- (long) found, recpos, minpos, length));
- if (recpos != minpos)
- { // Reserved space (Null bits?)
- bzero((char*) recinfo_pos, sizeof(*recinfo_pos));
- recinfo_pos->type= FIELD_NORMAL;
- recinfo_pos++->length= (uint16) (minpos - recpos);
- }
- if (!found)
+ create_flags|= HA_CREATE_RELIES_ON_SQL_LAYER;
break;
-
- if (found->flags & BLOB_FLAG)
- recinfo_pos->type= FIELD_BLOB;
- else if (found->type() == MYSQL_TYPE_VARCHAR)
- recinfo_pos->type= FIELD_VARCHAR;
- else if (!(options & HA_OPTION_PACK_RECORD))
- recinfo_pos->type= FIELD_NORMAL;
- else if (found->zero_pack())
- recinfo_pos->type= FIELD_SKIP_ZERO;
- else
- recinfo_pos->type= ((length <= 3 ||
- (found->flags & ZEROFILL_FLAG)) ?
- FIELD_NORMAL :
- found->type() == MYSQL_TYPE_STRING ||
- found->type() == MYSQL_TYPE_VAR_STRING ?
- FIELD_SKIP_ENDSPACE : FIELD_SKIP_PRESPACE);
- if (found->null_ptr)
- {
- recinfo_pos->null_bit= found->null_bit;
- recinfo_pos->null_pos= (uint) (found->null_ptr -
- (uchar *) table_arg->record[0]);
}
- else
- {
- recinfo_pos->null_bit= 0;
- recinfo_pos->null_pos= 0;
- }
- (recinfo_pos++)->length= (uint16) length;
- recpos= minpos + length;
- DBUG_PRINT("loop", ("length: %d type: %d",
- recinfo_pos[-1].length, recinfo_pos[-1].type));
-
}
- MARIA_CREATE_INFO create_info;
+ if ((error= table2maria(table_arg, &keydef, &recinfo, &records)))
+ DBUG_RETURN(error); /* purecov: inspected */
bzero((char*) &create_info, sizeof(create_info));
create_info.max_rows= share->max_rows;
create_info.reloc_rows= share->min_rows;
- create_info.with_auto_increment= found_real_auto_increment;
- create_info.auto_increment= (info->auto_increment_value ?
- info->auto_increment_value - 1 : (ulonglong) 0);
+ create_info.with_auto_increment= share->next_number_key_offset == 0;
+ create_info.auto_increment= (ha_create_info->auto_increment_value ?
+ ha_create_info->auto_increment_value -1 :
+ (ulonglong) 0);
create_info.data_file_length= ((ulonglong) share->max_rows *
share->avg_row_length);
- create_info.data_file_name= info->data_file_name;
- create_info.index_file_name= info->index_file_name;
+ create_info.data_file_name= ha_create_info->data_file_name;
+ create_info.index_file_name= ha_create_info->index_file_name;
- if (info->options & HA_LEX_CREATE_TMP_TABLE)
- create_flags |= HA_CREATE_TMP_TABLE;
+ if (ha_create_info->options & HA_LEX_CREATE_TMP_TABLE)
+ create_flags|= HA_CREATE_TMP_TABLE;
if (options & HA_OPTION_PACK_RECORD)
- create_flags |= HA_PACK_RECORD;
+ create_flags|= HA_PACK_RECORD;
if (options & HA_OPTION_CHECKSUM)
- create_flags |= HA_CREATE_CHECKSUM;
+ create_flags|= HA_CREATE_CHECKSUM;
if (options & HA_OPTION_DELAY_KEY_WRITE)
- create_flags |= HA_CREATE_DELAY_KEY_WRITE;
+ create_flags|= HA_CREATE_DELAY_KEY_WRITE;
- switch (info->row_type) {
+ switch (ha_create_info->row_type) {
case ROW_TYPE_FIXED:
row_type= STATIC_RECORD;
break;
@@ -1718,9 +1887,10 @@ int ha_maria::create(const char *name, register TABLE *table_arg,
error=
maria_create(fn_format(buff, name, "", "",
MY_UNPACK_FILENAME | MY_APPEND_EXT),
- row_type, share->keys, keydef, (uint) (recinfo_pos - recinfo),
- recinfo, 0, (MARIA_UNIQUEDEF *) 0, &create_info,
- create_flags);
+ row_type, share->keys, keydef,
+ records, recinfo,
+ 0, (MARIA_UNIQUEDEF *) 0,
+ &create_info, create_flags);
my_free((gptr) recinfo, MYF(0));
DBUG_RETURN(error);
diff --git a/storage/maria/ma_check.c b/storage/maria/ma_check.c
index ccce19de994..a247d36144c 100644
--- a/storage/maria/ma_check.c
+++ b/storage/maria/ma_check.c
@@ -2310,6 +2310,12 @@ int maria_sort_index(HA_CHECK *param, register MARIA_HA *info, my_string name)
MARIA_STATE_INFO old_state;
DBUG_ENTER("maria_sort_index");
+ /* cannot sort index files with R-tree indexes */
+ for (key= 0,keyinfo= &share->keyinfo[0]; key < share->base.keys ;
+ key++,keyinfo++)
+ if (keyinfo->key_alg == HA_KEY_ALG_RTREE)
+ DBUG_RETURN(0);
+
if (!(param->testflag & T_SILENT))
printf("- Sorting index for MARIA-table '%s'\n",name);
@@ -2402,6 +2408,8 @@ static int sort_one_index(HA_CHECK *param, MARIA_HA *info,
char llbuff[22];
DBUG_ENTER("sort_one_index");
+ /* cannot walk over R-tree indices */
+ DBUG_ASSERT(keyinfo->key_alg != HA_KEY_ALG_RTREE);
new_page_pos=param->new_file_pos;
param->new_file_pos+=keyinfo->block_length;
diff --git a/storage/maria/ma_close.c b/storage/maria/ma_close.c
index 2a874079961..508334fcf67 100644
--- a/storage/maria/ma_close.c
+++ b/storage/maria/ma_close.c
@@ -59,7 +59,7 @@ int maria_close(register MARIA_HA *info)
}
flag= !--share->reopen;
/*
- RECOVERYTODO:
+ RECOVERY TODO:
If "flag" is TRUE, in the line below we are going to make the table
unknown to future checkpoints, so it needs to have fsync'ed itself
entirely (bitmap, pages, etc) at this point.
diff --git a/storage/maria/ma_create.c b/storage/maria/ma_create.c
index 59f5f7d1a4d..bd9382ff9b0 100644
--- a/storage/maria/ma_create.c
+++ b/storage/maria/ma_create.c
@@ -921,7 +921,7 @@ int maria_create(const char *name, enum data_file_type record_type,
if (my_close(file,MYF(0)))
goto err;
/*
- RECOVERYTODO
+ RECOVERY TODO
Write a log record describing the CREATE operation (just the file
names, link names, and the full header's content).
For this record to be of any use for Recovery, we need the upper
@@ -967,18 +967,19 @@ uint maria_get_pointer_length(ulonglong file_length, uint def)
if (file_length) /* If not default */
{
#ifdef NOT_YET_READY_FOR_8_BYTE_POINTERS
- if (file_length >= (longlong) 1 << 56)
+ if (file_length >= (ULL(1) << 56))
def=8;
+ else
#endif
- if (file_length >= (longlong) 1 << 48)
+ if (file_length >= (ULL(1) << 48))
def=7;
- if (file_length >= (longlong) 1 << 40)
+ else if (file_length >= (ULL(1) << 40))
def=6;
- else if (file_length >= (longlong) 1 << 32)
+ else if (file_length >= (ULL(1) << 32))
def=5;
- else if (file_length >= (1L << 24))
+ else if (file_length >= (ULL(1) << 24))
def=4;
- else if (file_length >= (1L << 16))
+ else if (file_length >= (ULL(1) << 16))
def=3;
else
def=2;
diff --git a/storage/maria/ma_delete_all.c b/storage/maria/ma_delete_all.c
index 616147c1067..428724ec313 100644
--- a/storage/maria/ma_delete_all.c
+++ b/storage/maria/ma_delete_all.c
@@ -30,7 +30,7 @@ int maria_delete_all_rows(MARIA_HA *info)
{
DBUG_RETURN(my_errno=EACCES);
}
- /* LOCKTODO take X-lock on table here */
+ /* LOCK TODO take X-lock on table here */
if (_ma_readinfo(info,F_WRLCK,1))
DBUG_RETURN(my_errno);
if (_ma_mark_file_changed(info))
@@ -54,7 +54,7 @@ int maria_delete_all_rows(MARIA_HA *info)
*/
flush_key_blocks(share->key_cache, share->kfile, FLUSH_IGNORE_CHANGED);
/*
- RECOVERYTODO Log the two chsize and header modifications and force the
+ RECOVERY TODO Log the two chsize and header modifications and force the
log. So that if crash between the two chsize, we finish the work at
Recovery. For this scenario:
"TRUNCATE TABLE t1; DROP TABLE t1; RENAME TABLE t2 to t1; crash;"
@@ -66,7 +66,7 @@ int maria_delete_all_rows(MARIA_HA *info)
my_chsize(share->kfile, share->base.keystart, 0, MYF(MY_WME)) )
goto err;
/*
- RECOVERYTODO Consider updating ZeroDirtyPagesLSN here. It is
+ RECOVERY TODO Consider updating ZeroDirtyPagesLSN here. It is
not a necessity (it is one only in RENAME commands) but an optional
optimization which will allow some REDO skipping at Recovery.
*/
@@ -78,7 +78,7 @@ int maria_delete_all_rows(MARIA_HA *info)
rw_unlock(&info->s->mmap_lock);
#endif
/*
- RECOVERYTODO Until we have the TRUNCATE log record and take it into
+ RECOVERY TODO Until we have the TRUNCATE log record and take it into
account for log-low-water-mark calculation and use it in Recovery, we need
to sync.
*/
@@ -90,10 +90,10 @@ int maria_delete_all_rows(MARIA_HA *info)
err:
{
int save_errno=my_errno;
- /* RECOVERYTODO log the header modifications */
+ /* RECOVERY TODO log the header modifications */
VOID(_ma_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
- /* RECOVERYTODO until we log above we have to sync */
+ /* RECOVERY TODO until we log above we have to sync */
if (_ma_sync_table_files(info) && !save_errno)
save_errno= my_errno;
allow_break(); /* Allow SIGHUP & SIGINT */
diff --git a/storage/maria/ma_delete_table.c b/storage/maria/ma_delete_table.c
index 5c7b4337b20..47ba56e031c 100644
--- a/storage/maria/ma_delete_table.c
+++ b/storage/maria/ma_delete_table.c
@@ -31,7 +31,7 @@ int maria_delete_table(const char *name)
#ifdef EXTRA_DEBUG
_ma_check_table_is_closed(name,"delete");
#endif
- /* LOCKTODO take X-lock on table here */
+ /* LOCK TODO take X-lock on table here */
#ifdef USE_RAID
{
MARIA_HA *info;
@@ -61,7 +61,7 @@ int maria_delete_table(const char *name)
fn_format(from,name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
/*
- RECOVERYTODO log the two deletes below.
+ RECOVERY TODO log the two deletes below.
Then do the file deletions.
For this log record to be of any use for Recovery, we need the upper MySQL
layer to be crash-safe in DDLs; when it is we should reconsider the moment
diff --git a/storage/maria/ma_dynrec.c b/storage/maria/ma_dynrec.c
index c3d0bf1fb0a..52780ab4f6f 100644
--- a/storage/maria/ma_dynrec.c
+++ b/storage/maria/ma_dynrec.c
@@ -69,6 +69,14 @@ my_bool _ma_dynmap_file(MARIA_HA *info, my_off_t size)
DBUG_PRINT("warning", ("File is too large for mmap"));
DBUG_RETURN(1);
}
+ /*
+ Ingo wonders if it is good to use MAP_NORESERVE. From the Linux man page:
+ MAP_NORESERVE
+ Do not reserve swap space for this mapping. When swap space is
+ reserved, one has the guarantee that it is possible to modify the
+ mapping. When swap space is not reserved one might get SIGSEGV
+ upon a write if no physical memory is available.
+ */
info->s->file_map= (byte*)
my_mmap(0, (size_t)(size + MEMMAP_EXTRA_MARGIN),
info->s->mode==O_RDONLY ? PROT_READ :
@@ -252,7 +260,7 @@ my_bool _ma_write_blob_record(MARIA_HA *info, const byte *record)
_ma_calc_total_blob_length(info,record)+ extra);
if (!(rec_buff=(byte*) my_alloca(reclength)))
{
- my_errno=ENOMEM;
+ my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
return(1);
}
reclength2= _ma_rec_pack(info,
@@ -289,7 +297,7 @@ my_bool _ma_update_blob_record(MARIA_HA *info, MARIA_RECORD_POS pos,
#endif
if (!(rec_buff=(byte*) my_alloca(reclength)))
{
- my_errno=ENOMEM;
+ my_errno= HA_ERR_OUT_OF_MEM; /* purecov: inspected */
return(1);
}
reclength= _ma_rec_pack(info,rec_buff+ALIGN_SIZE(MARIA_MAX_DYN_BLOCK_HEADER),
@@ -1225,8 +1233,10 @@ ulong _ma_rec_unpack(register MARIA_HA *info, register byte *to, byte *from,
{
uint size_length=rec_length- maria_portable_sizeof_char_ptr;
ulong blob_length= _ma_calc_blob_length(size_length,from);
- if ((ulong) (from_end-from) - size_length < blob_length ||
- min_pack_length > (uint) (from_end -(from+size_length+blob_length)))
+ ulong from_left= (ulong) (from_end - from);
+ if (from_left < size_length ||
+ from_left - size_length < blob_length ||
+ from_left - size_length - blob_length < min_pack_length)
goto err;
memcpy((byte*) to,(byte*) from,(size_t) size_length);
from+=size_length;
diff --git a/storage/maria/ma_extra.c b/storage/maria/ma_extra.c
index 90e79362442..59ae18d949a 100644
--- a/storage/maria/ma_extra.c
+++ b/storage/maria/ma_extra.c
@@ -355,7 +355,12 @@ int maria_extra(MARIA_HA *info, enum ha_extra_function function,
case HA_EXTRA_MMAP:
#ifdef HAVE_MMAP
pthread_mutex_lock(&share->intern_lock);
- if (!share->file_map)
+ /*
+ 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.
+ */
+ if (!share->file_map && (share->tot_locks == 1))
{
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 06b044e9e38..af76f0858a7 100644
--- a/storage/maria/ma_ft_boolean_search.c
+++ b/storage/maria/ma_ft_boolean_search.c
@@ -676,7 +676,7 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
FT_SEG_ITERATOR ftsi;
FTB_EXPR *ftbe;
float weight=ftbw->weight;
- int yn=ftbw->flags, ythresh, mode=(ftsi_orig != 0);
+ int yn_flag= ftbw->flags, ythresh, mode=(ftsi_orig != 0);
my_off_t curdoc=ftbw->docid[mode];
struct st_mysql_ftparser *parser= ftb->keynr == NO_SUCH_KEY ?
&ft_default_parser :
@@ -693,13 +693,13 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
}
if (ftbe->nos)
break;
- if (yn & FTB_FLAG_YES)
+ if (yn_flag & FTB_FLAG_YES)
{
weight /= ftbe->ythresh;
ftbe->cur_weight += weight;
if ((int) ++ftbe->yesses == ythresh)
{
- yn=ftbe->flags;
+ yn_flag=ftbe->flags;
weight=ftbe->cur_weight*ftbe->weight;
if (mode && ftbe->phrase)
{
@@ -720,14 +720,14 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
break;
}
else
- if (yn & FTB_FLAG_NO)
+ if (yn_flag & FTB_FLAG_NO)
{
/*
NOTE: special sort function of queue assures that all
- (yn & FTB_FLAG_NO) != 0
+ (yn_flag & FTB_FLAG_NO) != 0
events for every particular subexpression will
"auto-magically" happen BEFORE all the
- (yn & FTB_FLAG_YES) != 0 events. So no
+ (yn_flag & FTB_FLAG_YES) != 0 events. So no
already matched expression can become not-matched again.
*/
++ftbe->nos;
@@ -740,8 +740,8 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
ftbe->cur_weight += weight;
if ((int) ftbe->yesses < ythresh)
break;
- if (!(yn & FTB_FLAG_WONLY))
- yn= ((int) ftbe->yesses++ == ythresh) ? ftbe->flags : FTB_FLAG_WONLY ;
+ if (!(yn_flag & FTB_FLAG_WONLY))
+ yn_flag= ((int) ftbe->yesses++ == ythresh) ? ftbe->flags : FTB_FLAG_WONLY ;
weight*= ftbe->weight;
}
}
diff --git a/storage/maria/ma_locking.c b/storage/maria/ma_locking.c
index 6a0bbe82dcb..e41b2d490dc 100644
--- a/storage/maria/ma_locking.c
+++ b/storage/maria/ma_locking.c
@@ -291,6 +291,15 @@ void _ma_update_status(void* param)
}
}
+
+void _ma_restore_status(void *param)
+{
+ MARIA_HA *info= (MARIA_HA*) param;
+ info->state= &info->s->state.state;
+ info->append_insert_at_end= 0;
+}
+
+
void _ma_copy_status(void* to,void *from)
{
((MARIA_HA*) to)->state= &((MARIA_HA*) from)->save_state;
diff --git a/storage/maria/ma_loghandler.c b/storage/maria/ma_loghandler.c
index 1e9afc7571d..d8a821cb538 100644
--- a/storage/maria/ma_loghandler.c
+++ b/storage/maria/ma_loghandler.c
@@ -799,7 +799,7 @@ static void translog_put_sector_protection(byte *page,
static uint32 translog_crc(byte *area, uint length)
{
- return crc32(0L, area, length);
+ return crc32(0L, (unsigned char*) area, length);
}
diff --git a/storage/maria/ma_open.c b/storage/maria/ma_open.c
index 19113196f15..7c4ad4c4a0a 100644
--- a/storage/maria/ma_open.c
+++ b/storage/maria/ma_open.c
@@ -310,7 +310,13 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
for (j=0 ; j < share->keyinfo[i].keysegs; j++,pos++)
{
disk_pos=_ma_keyseg_read(disk_pos, pos);
-
+ if (pos->flag & HA_BLOB_PART &&
+ ! (share->options & (HA_OPTION_COMPRESS_RECORD |
+ HA_OPTION_PACK_RECORD)))
+ {
+ my_errno= HA_ERR_CRASHED;
+ goto err;
+ }
if (pos->type == HA_KEYTYPE_TEXT ||
pos->type == HA_KEYTYPE_VARTEXT1 ||
pos->type == HA_KEYTYPE_VARTEXT2)
@@ -346,11 +352,11 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
}
else
{
- uint j;
+ uint k;
share->keyinfo[i].seg=pos;
- for (j=0; j < FT_SEGS; j++)
+ for (k=0; k < FT_SEGS; k++)
{
- *pos= ft_keysegs[j];
+ *pos= ft_keysegs[k];
pos[0].language= pos[-1].language;
if (!(pos[0].charset= pos[-1].charset))
{
@@ -444,6 +450,32 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
}
}
share->rec[i].type=(int) FIELD_LAST; /* End marker */
+#ifdef ASKMONTY
+ /*
+ This code was added to mi_open.c in this cset:
+ "ChangeSet 1.1616.2941.5 2007/01/22 16:34:58 svoj@mysql.com
+ BUG#24401 - MySQL server crashes if you try to retrieve data from
+ corrupted table
+ Accessing a table with corrupted column definition results in server
+ crash.
+ This is fixed by refusing to open such tables. Affects MyISAM only.
+ No test case, since it requires crashed table.
+ storage/myisam/mi_open.c 1.80.2.10 2007/01/22 16:34:57 svoj@mysql.com
+ Refuse to open MyISAM table with summary columns length bigger than
+ length of the record."
+
+ The problem is that the "offset" variable was removed (by Monty in the
+ rows-in-block patch). Monty will know how to merge that.
+ Guilhem will make sure to notify him.
+ */
+ if (offset > share->base.reclength)
+ {
+ /* purecov: begin inspected */
+ my_errno= HA_ERR_CRASHED;
+ goto err;
+ /* purecov: end */
+ }
+#endif /* ASKMONTY */
if (_ma_open_datafile(&info, share, -1))
goto err;
@@ -465,6 +497,22 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
_ma_setup_functions(share);
if ((*share->once_init)(share, info.dfile))
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;
#ifdef THREAD
thr_lock_init(&share->lock);
@@ -491,6 +539,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
share->lock.get_status=_ma_get_status;
share->lock.copy_status=_ma_copy_status;
share->lock.update_status=_ma_update_status;
+ share->lock.restore_status=_ma_restore_status;
share->lock.check_status=_ma_check_status;
}
}
diff --git a/storage/maria/ma_packrec.c b/storage/maria/ma_packrec.c
index 7c875e7b91d..4e74653192e 100644
--- a/storage/maria/ma_packrec.c
+++ b/storage/maria/ma_packrec.c
@@ -20,7 +20,10 @@
#define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */
-#if INT_MAX > 65536L
+/* Some definitions to keep in sync with maria_pack.c */
+#define HEAD_LENGTH 32 /* Length of fixed header */
+
+#if INT_MAX > 32767
#define BITS_SAVED 32
#define MAX_QUICK_TABLE_BITS 9 /* Because we may shift in 24 bits */
#else
@@ -42,6 +45,7 @@
{ bits-=(bit+1); break; } \
pos+= *pos
+/* Size in uint16 of a Huffman tree for byte compression of 256 byte values. */
#define OFFSET_TABLE_SIZE 512
static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
@@ -169,7 +173,7 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
uint16 *decode_table,*tmp_buff;
ulong elements,intervall_length;
char *disk_cache,*intervall_buff;
- uchar header[32];
+ uchar header[HEAD_LENGTH];
MARIA_BIT_BUFF bit_buff;
DBUG_ENTER("_ma_read_pack_info");
@@ -185,12 +189,13 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
my_errno=HA_ERR_END_OF_FILE;
goto err0;
}
+ /* Only the first three bytes of magic number are independent of version. */
if (memcmp((byte*) header, (byte*) maria_pack_file_magic, 3))
{
my_errno=HA_ERR_WRONG_IN_RECORD;
goto err0;
}
- share->pack.version= header[3];
+ share->pack.version= header[3]; /* fourth byte of magic number */
share->pack.header_length= uint4korr(header+4);
share->min_pack_length=(uint) uint4korr(header+8);
share->max_pack_length=(uint) uint4korr(header+12);
@@ -206,7 +211,23 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
share->base.min_block_length=share->min_pack_length+1;
if (share->min_pack_length > 254)
share->base.min_block_length+=2;
-
+ DBUG_PRINT("info", ("fixed header length: %u", HEAD_LENGTH));
+ DBUG_PRINT("info", ("total header length: %lu", share->pack.header_length));
+ DBUG_PRINT("info", ("pack file version: %u", share->pack.version));
+ DBUG_PRINT("info", ("min pack length: %lu", share->min_pack_length));
+ DBUG_PRINT("info", ("max pack length: %lu", share->max_pack_length));
+ DBUG_PRINT("info", ("elements of all trees: %lu", elements));
+ DBUG_PRINT("info", ("distinct values bytes: %lu", intervall_length));
+ DBUG_PRINT("info", ("number of code trees: %u", trees));
+ DBUG_PRINT("info", ("bytes for record lgt: %u", share->pack.ref_length));
+ DBUG_PRINT("info", ("record pointer length: %u", rec_reflength));
+
+
+ /*
+ Memory segment #1:
+ - Decode tree heads
+ - Distinct column values
+ */
if (!(share->decode_trees=(MARIA_DECODE_TREE*)
my_malloc((uint) (trees*sizeof(MARIA_DECODE_TREE)+
intervall_length*sizeof(byte)),
@@ -214,10 +235,18 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
goto err0;
intervall_buff=(byte*) (share->decode_trees+trees);
+ /*
+ Memory segment #2:
+ - Decode tables
+ - Quick decode tables
+ - Temporary decode table
+ - Compressed data file header cache
+ This segment will be reallocated after construction of the tables.
+ */
length=(uint) (elements*2+trees*(1 << maria_quick_table_bits));
if (!(share->decode_tables=(uint16*)
my_malloc((length+OFFSET_TABLE_SIZE)*sizeof(uint16)+
- (uint) (share->pack.header_length+7),
+ (uint) (share->pack.header_length - sizeof(header)),
MYF(MY_WME | MY_ZEROFILL))))
goto err1;
tmp_buff=share->decode_tables+length;
@@ -240,17 +269,26 @@ static my_bool _ma_read_pack_info(MARIA_SHARE *share, File file,
share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff,
huff_tree_bits);
share->rec[i].unpack= get_unpack_function(share->rec+i);
+ DBUG_PRINT("info", ("col: %2u type: %2u pack: %u slbits: %2u",
+ i, share->rec[i].base_type, share->rec[i].pack_type,
+ share->rec[i].space_length_bits));
}
skip_to_next_byte(&bit_buff);
+ /*
+ Construct the decoding tables from the file header. Keep track of
+ the used memory.
+ */
decode_table=share->decode_tables;
for (i=0 ; i < trees ; i++)
if (read_huff_table(&bit_buff,share->decode_trees+i,&decode_table,
&intervall_buff,tmp_buff))
goto err3;
+ /* Reallocate the decoding tables to the used size. */
decode_table=(uint16*)
my_realloc((gptr) share->decode_tables,
(uint) ((byte*) decode_table - (byte*) share->decode_tables),
MYF(MY_HOLD_ON_ERROR));
+ /* Fix the table addresses in the tree heads. */
{
long diff=PTR_BYTE_DIFF(decode_table,share->decode_tables);
share->decode_tables=decode_table;
@@ -296,8 +334,23 @@ err0:
}
- /* Read on huff-code-table from datafile */
+/*
+ Read a huff-code-table from datafile.
+ SYNOPSIS
+ read_huff_table()
+ bit_buff Bit buffer pointing at start of the
+ decoding table in the file header cache.
+ decode_tree Pointer to the decode tree head.
+ decode_table IN/OUT Address of a pointer to the next free space.
+ intervall_buff IN/OUT Address of a pointer to the next unused values.
+ tmp_buff Buffer for temporary extraction of a full
+ decoding table as read from bit_buff.
+
+ RETURN
+ 0 OK.
+ 1 Error.
+*/
static uint read_huff_table(MARIA_BIT_BUFF *bit_buff,
MARIA_DECODE_TREE *decode_tree,
uint16 **decode_table, byte **intervall_buff,
@@ -306,19 +359,33 @@ static uint read_huff_table(MARIA_BIT_BUFF *bit_buff,
uint min_chr,elements,char_bits,offset_bits,size,intervall_length,table_bits,
next_free_offset;
uint16 *ptr,*end;
+ DBUG_ENTER("read_huff_table");
- LINT_INIT(ptr);
if (!get_bits(bit_buff,1))
{
+ /* Byte value compression. */
min_chr=get_bits(bit_buff,8);
elements=get_bits(bit_buff,9);
char_bits=get_bits(bit_buff,5);
offset_bits=get_bits(bit_buff,5);
intervall_length=0;
ptr=tmp_buff;
+ ptr=tmp_buff;
+ DBUG_PRINT("info", ("byte value compression"));
+ DBUG_PRINT("info", ("minimum byte value: %u", min_chr));
+ DBUG_PRINT("info", ("number of tree nodes: %u", elements));
+ DBUG_PRINT("info", ("bits for values: %u", char_bits));
+ DBUG_PRINT("info", ("bits for tree offsets: %u", offset_bits));
+ if (elements > 256)
+ {
+ DBUG_PRINT("error", ("ERROR: illegal number of tree elements: %u",
+ elements));
+ DBUG_RETURN(1);
+ }
}
else
{
+ /* Distinct column value compression. */
min_chr=0;
elements=get_bits(bit_buff,15);
intervall_length=get_bits(bit_buff,16);
@@ -326,13 +393,28 @@ static uint read_huff_table(MARIA_BIT_BUFF *bit_buff,
offset_bits=get_bits(bit_buff,5);
decode_tree->quick_table_bits=0;
ptr= *decode_table;
+ DBUG_PRINT("info", ("distinct column value compression"));
+ DBUG_PRINT("info", ("number of tree nodes: %u", elements));
+ DBUG_PRINT("info", ("value buffer length: %u", intervall_length));
+ DBUG_PRINT("info", ("bits for value index: %u", char_bits));
+ DBUG_PRINT("info", ("bits for tree offsets: %u", offset_bits));
}
size=elements*2-2;
+ DBUG_PRINT("info", ("tree size in uint16: %u", size));
+ DBUG_PRINT("info", ("tree size in bytes: %u",
+ size * (uint) sizeof(uint16)));
for (end=ptr+size ; ptr < end ; ptr++)
{
if (get_bit(bit_buff))
+ {
*ptr= (uint16) get_bits(bit_buff,offset_bits);
+ if ((ptr + *ptr >= end) || !*ptr)
+ {
+ DBUG_PRINT("error", ("ERROR: illegal pointer in decode tree"));
+ DBUG_RETURN(1);
+ }
+ }
else
*ptr= (uint16) (IS_CHAR + (get_bits(bit_buff,char_bits) + min_chr));
}
@@ -342,11 +424,15 @@ static uint read_huff_table(MARIA_BIT_BUFF *bit_buff,
decode_tree->intervalls= *intervall_buff;
if (! intervall_length)
{
- table_bits=find_longest_bitstream(tmp_buff, tmp_buff+OFFSET_TABLE_SIZE);
- if (table_bits == (uint) ~0)
- return 1;
+ /* Byte value compression. ptr started from tmp_buff. */
+ /* Find longest Huffman code from begin to end of tree in bits. */
+ table_bits= find_longest_bitstream(tmp_buff, ptr);
+ if (table_bits >= OFFSET_TABLE_SIZE)
+ DBUG_RETURN(1);
if (table_bits > maria_quick_table_bits)
table_bits=maria_quick_table_bits;
+ DBUG_PRINT("info", ("table bits: %u", table_bits));
+
next_free_offset= (1 << table_bits);
make_quick_table(*decode_table,tmp_buff,&next_free_offset,0,table_bits,
table_bits);
@@ -355,96 +441,265 @@ static uint read_huff_table(MARIA_BIT_BUFF *bit_buff,
}
else
{
+ /* Distinct column value compression. ptr started from *decode_table */
(*decode_table)=end;
+ /*
+ get_bits() moves some bytes to a cache buffer in advance. May need
+ to step back.
+ */
bit_buff->pos-= bit_buff->bits/8;
+ /* Copy the distinct column values from the buffer. */
memcpy(*intervall_buff,bit_buff->pos,(size_t) intervall_length);
(*intervall_buff)+=intervall_length;
bit_buff->pos+=intervall_length;
bit_buff->bits=0;
}
- return 0;
+ DBUG_RETURN(0);
}
+/*
+ Make a quick_table for faster decoding.
+
+ SYNOPSIS
+ make_quick_table()
+ to_table Target quick_table and remaining decode table.
+ decode_table Source Huffman (sub-)tree within tmp_buff.
+ next_free_offset IN/OUT Next free offset from to_table.
+ Starts behind quick_table on the top-level.
+ value Huffman bits found so far.
+ bits Remaining bits to be collected.
+ max_bits Total number of bits to collect (table_bits).
+
+ DESCRIPTION
+
+ The quick table is an array of 16-bit values. There exists one value
+ for each possible code representable by max_bits (table_bits) bits.
+ In most cases table_bits is 9. So there are 512 16-bit values.
+
+ If the high-order bit (16) is set (IS_CHAR) then the array slot for
+ this value is a valid Huffman code for a resulting byte value.
+
+ The low-order 8 bits (1..8) are the resulting byte value.
+
+ Bits 9..14 are the length of the Huffman code for this byte value.
+ This means so many bits from the input stream were needed to
+ represent this byte value. The remaining bits belong to later
+ Huffman codes. This also means that for every Huffman code shorter
+ than table_bits there are multiple entires in the array, which
+ differ just in the unused bits.
+
+ If the high-order bit (16) is clear (0) then the remaining bits are
+ the position of the remaining Huffman decode tree segment behind the
+ quick table.
+
+ RETURN
+ void
+*/
+
static void make_quick_table(uint16 *to_table, uint16 *decode_table,
uint *next_free_offset, uint value, uint bits,
uint max_bits)
{
+ DBUG_ENTER("make_quick_table");
+
+ /*
+ When down the table to the requested maximum, copy the rest of the
+ Huffman table.
+ */
if (!bits--)
{
+ /*
+ Remaining left Huffman tree segment starts behind quick table.
+ Remaining right Huffman tree segment starts behind left segment.
+ */
to_table[value]= (uint16) *next_free_offset;
+ /*
+ Re-construct the remaining Huffman tree segment at
+ next_free_offset in to_table.
+ */
*next_free_offset=copy_decode_table(to_table, *next_free_offset,
decode_table);
- return;
+ DBUG_VOID_RETURN;
}
+
+ /* Descent on the left side. Left side bits are clear (0). */
if (!(*decode_table & IS_CHAR))
{
+ /* Not a leaf. Follow the pointer. */
make_quick_table(to_table,decode_table+ *decode_table,
next_free_offset,value,bits,max_bits);
}
else
+ {
+ /*
+ A leaf. A Huffman code is complete. Fill the quick_table
+ array for all possible bit strings starting with this Huffman
+ code.
+ */
fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table);
+ }
+
+ /* Descent on the right side. Right side bits are set (1). */
decode_table++;
value|= (1 << bits);
if (!(*decode_table & IS_CHAR))
{
+ /* Not a leaf. Follow the pointer. */
make_quick_table(to_table,decode_table+ *decode_table,
next_free_offset,value,bits,max_bits);
}
else
+ {
+ /*
+ A leaf. A Huffman code is complete. Fill the quick_table
+ array for all possible bit strings starting with this Huffman
+ code.
+ */
fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table);
- return;
+ }
+
+ DBUG_VOID_RETURN;
}
+/*
+ Fill quick_table for all possible values starting with this Huffman code.
+
+ SYNOPSIS
+ fill_quick_table()
+ table Target quick_table position.
+ bits Unused bits from max_bits.
+ max_bits Total number of bits to collect (table_bits).
+ value The byte encoded by the found Huffman code.
+
+ DESCRIPTION
+
+ Fill the segment (all slots) of the quick_table array with the
+ resulting value for the found Huffman code. There are as many slots
+ as there are combinations representable by the unused bits.
+
+ In most cases we use 9 table bits. Assume a 3-bit Huffman code. Then
+ there are 6 unused bits. Hence we fill 2**6 = 64 slots with the
+ value.
+
+ RETURN
+ void
+*/
+
static void fill_quick_table(uint16 *table, uint bits, uint max_bits,
uint value)
{
uint16 *end;
- value|=(max_bits-bits) << 8;
- for (end=table+ (1 << bits) ;
- table < end ;
- *table++ = (uint16) value | IS_CHAR) ;
+ DBUG_ENTER("fill_quick_table");
+
+ /*
+ Bits 1..8 of value represent the decoded byte value.
+ Bits 9..14 become the length of the Huffman code for this byte value.
+ Bit 16 flags a valid code (IS_CHAR).
+ */
+ value|= (max_bits - bits) << 8 | IS_CHAR;
+
+ for (end= table + (uint) (((uint) 1 << bits)); table < end; table++)
+ {
+ *table= (uint16) value;
+ }
+ DBUG_VOID_RETURN;
}
+/*
+ Reconstruct a decode subtree at the target position.
+
+ SYNOPSIS
+ copy_decode_table()
+ to_pos Target quick_table and remaining decode table.
+ offset Next free offset from to_pos.
+ decode_table Source Huffman subtree within tmp_buff.
+
+ NOTE
+ Pointers in the decode tree are relative to the pointers position.
+
+ RETURN
+ next free offset from to_pos.
+*/
+
static uint copy_decode_table(uint16 *to_pos, uint offset,
uint16 *decode_table)
{
- uint prev_offset;
- prev_offset= offset;
+ uint prev_offset= offset;
+ DBUG_ENTER("copy_decode_table");
+ /* Descent on the left side. */
if (!(*decode_table & IS_CHAR))
{
+ /* Set a pointer to the next target node. */
to_pos[offset]=2;
+ /* Copy the left hand subtree there. */
offset=copy_decode_table(to_pos,offset+2,decode_table+ *decode_table);
}
else
{
+ /* Copy the byte value. */
to_pos[offset]= *decode_table;
+ /* Step behind this node. */
offset+=2;
}
- decode_table++;
+ /* Descent on the right side. */
+ decode_table++;
if (!(*decode_table & IS_CHAR))
{
+ /* Set a pointer to the next free target node. */
to_pos[prev_offset+1]=(uint16) (offset-prev_offset-1);
+ /* Copy the right hand subtree to the entry of that node. */
offset=copy_decode_table(to_pos,offset,decode_table+ *decode_table);
}
else
+ {
+ /* Copy the byte value. */
to_pos[prev_offset+1]= *decode_table;
- return offset;
+ }
+ DBUG_RETURN(offset);
}
+/*
+ Find the length of the longest Huffman code in this table in bits.
+
+ SYNOPSIS
+ find_longest_bitstream()
+ table Code (sub-)table start.
+ end End of code table.
+
+ IMPLEMENTATION
+
+ Recursively follow the branch(es) of the code pair on every level of
+ the tree until two byte values (and no branch) are found. Add one to
+ each level when returning back from each recursion stage.
+
+ 'end' is used for error checking only. A clean tree terminates
+ before reaching 'end'. Hence the exact value of 'end' is not too
+ important. However having it higher than necessary could lead to
+ misbehaviour should 'next' jump into the dirty area.
+
+ RETURN
+ length Length of longest Huffman code in bits.
+ >= OFFSET_TABLE_SIZE Error, broken tree. It does not end before 'end'.
+*/
+
static uint find_longest_bitstream(uint16 *table, uint16 *end)
{
- uint length=1,length2;
+ uint length=1;
+ uint length2;
if (!(*table & IS_CHAR))
{
uint16 *next= table + *table;
if (next > end || next == table)
- return ~0;
+ {
+ DBUG_PRINT("error", ("ERROR: illegal pointer in decode tree"));
+ return OFFSET_TABLE_SIZE;
+ }
length=find_longest_bitstream(next, end)+1;
}
table++;
@@ -452,8 +707,11 @@ static uint find_longest_bitstream(uint16 *table, uint16 *end)
{
uint16 *next= table + *table;
if (next > end || next == table)
- return ~0;
- length2=find_longest_bitstream(table+ *table, end)+1;
+ {
+ DBUG_PRINT("error", ("ERROR: illegal pointer in decode tree"));
+ return OFFSET_TABLE_SIZE;
+ }
+ length2= find_longest_bitstream(next, end) + 1;
length=max(length,length2);
}
return length;
@@ -901,18 +1159,46 @@ static void decode_bytes(MARIA_COLUMNDEF *rec,MARIA_BIT_BUFF *bit_buff,
bit_buff->pos+=4;
bits+=32;
}
- /* First use info in quick_table */
+ /*
+ First use info in quick_table.
+
+ The quick table is an array of 16-bit values. There exists one
+ value for each possible code representable by table_bits bits.
+ In most cases table_bits is 9. So there are 512 16-bit values.
+
+ If the high-order bit (16) is set (IS_CHAR) then the array slot
+ for this value is a valid Huffman code for a resulting byte value.
+
+ The low-order 8 bits (1..8) are the resulting byte value.
+
+ Bits 9..14 are the length of the Huffman code for this byte value.
+ This means so many bits from the input stream were needed to
+ represent this byte value. The remaining bits belong to later
+ Huffman codes. This also means that for every Huffman code shorter
+ than table_bits there are multiple entires in the array, which
+ differ just in the unused bits.
+
+ If the high-order bit (16) is clear (0) then the remaining bits are
+ the position of the remaining Huffman decode tree segment behind the
+ quick table.
+ */
low_byte=(uint) (bit_buff->current_byte >> (bits - table_bits)) & table_and;
low_byte=decode_tree->table[low_byte];
if (low_byte & IS_CHAR)
{
+ /*
+ All Huffman codes of less or equal table_bits length are in the
+ quick table. This is one of them.
+ */
*to++ = (char) (low_byte & 255); /* Found char in quick table */
bits-= ((low_byte >> 8) & 31); /* Remove bits used */
}
else
{ /* Map through rest of decode-table */
+ /* This means that the Huffman code must be longer than table_bits. */
pos=decode_tree->table+low_byte;
bits-=table_bits;
+ /* NOTE: decode_bytes_test_bit() is a macro wich contains a break !!! */
for (;;)
{
low_byte=(uint) (bit_buff->current_byte >> (bits-8));
@@ -1140,6 +1426,11 @@ uint _ma_pack_get_block_info(MARIA_HA *maria, MARIA_BIT_BUFF *bit_buff,
{
head_length+= read_pack_length((uint) maria->s->pack.version,
header + head_length, &info->blob_len);
+ /*
+ Ensure that the record buffer is big enough for the compressed
+ record plus all expanded blobs. [We do not have an extra buffer
+ for the resulting blobs. Sigh.]
+ */
if (_ma_alloc_buffer(rec_buff_p, rec_buff_size_p,
info->rec_len + info->blob_len +
maria->s->base.extra_rec_buff_size))
diff --git a/storage/maria/ma_range.c b/storage/maria/ma_range.c
index d3806aa79bc..4c5a037eb67 100644
--- a/storage/maria/ma_range.c
+++ b/storage/maria/ma_range.c
@@ -170,6 +170,7 @@ static double _ma_search_pos(register MARIA_HA *info,
byte *keypos, *buff;
double offset;
DBUG_ENTER("_ma_search_pos");
+ LINT_INIT(max_keynr);
if (pos == HA_OFFSET_ERROR)
DBUG_RETURN(0.5);
diff --git a/storage/maria/ma_rename.c b/storage/maria/ma_rename.c
index 5d89cc063d7..59a2315b18b 100644
--- a/storage/maria/ma_rename.c
+++ b/storage/maria/ma_rename.c
@@ -33,7 +33,7 @@ int maria_rename(const char *old_name, const char *new_name)
_ma_check_table_is_closed(old_name,"rename old_table");
_ma_check_table_is_closed(new_name,"rename new table2");
#endif
- /* LOCKTODO take X-lock on table here */
+ /* LOCK TODO take X-lock on table here */
#ifdef USE_RAID
{
MARIA_HA *info;
@@ -51,7 +51,7 @@ int maria_rename(const char *old_name, const char *new_name)
fn_format(from,old_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
fn_format(to,new_name,"",MARIA_NAME_IEXT,MY_UNPACK_FILENAME|MY_APPEND_EXT);
/*
- RECOVERYTODO log the two renames below. Update
+ RECOVERY TODO log the two renames below. Update
ZeroDirtyPagesLSN of the table on disk (=> sync the files), this is
needed so that Recovery does not pick a wrong table.
Then do the file renames.
diff --git a/storage/maria/ma_rt_index.c b/storage/maria/ma_rt_index.c
index 8e8ec6c991b..cefbcffcbf9 100644
--- a/storage/maria/ma_rt_index.c
+++ b/storage/maria/ma_rt_index.c
@@ -637,8 +637,6 @@ static int maria_rtree_insert_level(MARIA_HA *info, uint keynr, byte *key,
if ((old_root = info->s->state.key_root[keynr]) == HA_OFFSET_ERROR)
{
- int res;
-
if ((old_root = _ma_new(info, keyinfo, DFLT_INIT_HITS)) == HA_OFFSET_ERROR)
return -1;
info->keybuff_used = 1;
@@ -929,7 +927,6 @@ int maria_rtree_delete(MARIA_HA *info, uint keynr, byte *key, uint key_length)
ulong i;
for (i = 0; i < ReinsertList.n_pages; ++i)
{
- uint nod_flag;
byte *page_buf, *k, *last;
if (!(page_buf = (byte*) my_alloca((uint)keyinfo->block_length)))
diff --git a/storage/maria/ma_rt_split.c b/storage/maria/ma_rt_split.c
index 00c8d18f5e5..a81b2b932ec 100644
--- a/storage/maria/ma_rt_split.c
+++ b/storage/maria/ma_rt_split.c
@@ -188,6 +188,10 @@ static int split_maria_rtree_node(SplitStruct *node, int n_entries,
int next_node;
int i;
SplitStruct *end = node + n_entries;
+ LINT_INIT(a);
+ LINT_INIT(b);
+ LINT_INIT(next);
+ LINT_INIT(next_node);
if (all_size < min_size * 2)
{
diff --git a/storage/maria/ma_search.c b/storage/maria/ma_search.c
index d8738ae4639..991115ad181 100644
--- a/storage/maria/ma_search.c
+++ b/storage/maria/ma_search.c
@@ -477,9 +477,9 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
else
{
/* We have to compare k and vseg as if they were space extended */
- uchar *end= k+ (cmplen - len);
- for ( ; k < end && *k == ' '; k++) ;
- if (k == end)
+ uchar *k_end= k+ (cmplen - len);
+ for ( ; k < k_end && *k == ' '; k++) ;
+ if (k == k_end)
goto cmp_rest; /* should never happen */
if ((uchar) *k < (uchar) ' ')
{
@@ -491,15 +491,15 @@ int _ma_prefix_search(MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
}
else if (len > cmplen)
{
- uchar *end;
+ uchar *vseg_end;
if ((nextflag & SEARCH_PREFIX) && key_len_left == 0)
goto fix_flag;
/* We have to compare k and vseg as if they were space extended */
- for (end=vseg + (len-cmplen) ;
- vseg < end && *vseg == (byte) ' ';
+ for (vseg_end= vseg + (len-cmplen) ;
+ vseg < vseg_end && *vseg == (byte) ' ';
vseg++, matched++) ;
- DBUG_ASSERT(vseg < end);
+ DBUG_ASSERT(vseg < vseg_end);
if ((uchar) *vseg > (uchar) ' ')
{
diff --git a/storage/maria/ma_sort.c b/storage/maria/ma_sort.c
index 9134645f847..2c5524906ad 100644
--- a/storage/maria/ma_sort.c
+++ b/storage/maria/ma_sort.c
@@ -221,9 +221,9 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
if (my_b_inited(&tempfile_for_exceptions))
{
- MARIA_HA *index=info->sort_info->info;
+ MARIA_HA *idx=info->sort_info->info;
uint keyno=info->key;
- uint key_length, ref_length=index->s->rec_reflength;
+ uint key_length, ref_length=idx->s->rec_reflength;
if (!no_messages)
printf(" - Adding exceptions\n"); /* purecov: tested */
@@ -236,7 +236,7 @@ int _ma_create_index_by_sort(MARIA_SORT_PARAM *info, my_bool no_messages,
&& !my_b_read(&tempfile_for_exceptions,(byte*)sort_keys,
(uint) key_length))
{
- if (_ma_ck_write(index,keyno,(byte*) sort_keys,key_length-ref_length))
+ if (_ma_ck_write(idx,keyno,(byte*) sort_keys,key_length-ref_length))
goto err;
}
}
diff --git a/storage/maria/ma_update.c b/storage/maria/ma_update.c
index e3e391dcccc..29018b47bda 100644
--- a/storage/maria/ma_update.c
+++ b/storage/maria/ma_update.c
@@ -206,7 +206,8 @@ int maria_update(register MARIA_HA *info, const byte *oldrec, byte *newrec)
err:
DBUG_PRINT("error",("key: %d errno: %d",i,my_errno));
save_errno=my_errno;
- if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
+ if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_OUT_OF_MEM ||
+ my_errno == HA_ERR_RECORD_FILE_FULL)
{
info->errkey= (int) i;
flag=0;
diff --git a/storage/maria/ma_write.c b/storage/maria/ma_write.c
index 3f1ca59a00a..b672ed1fe23 100644
--- a/storage/maria/ma_write.c
+++ b/storage/maria/ma_write.c
@@ -205,7 +205,8 @@ err:
fatal_error= 0;
if (my_errno == HA_ERR_FOUND_DUPP_KEY ||
my_errno == HA_ERR_RECORD_FILE_FULL ||
- my_errno == HA_ERR_NULL_IN_SPATIAL)
+ my_errno == HA_ERR_NULL_IN_SPATIAL ||
+ my_errno == HA_ERR_OUT_OF_MEM)
{
if (info->bulk_insert)
{
@@ -629,6 +630,7 @@ int _ma_split_page(register MARIA_HA *info, register MARIA_KEYDEF *keyinfo,
my_off_t new_pos;
MARIA_KEY_PARAM s_temp;
DBUG_ENTER("maria_split_page");
+ LINT_INIT(after_key);
DBUG_DUMP("buff",(byte*) buff,maria_getint(buff));
if (info->s->keyinfo+info->lastinx == keyinfo)
diff --git a/storage/maria/maria_chk.c b/storage/maria/maria_chk.c
index 8471d36bec9..533766e35f9 100644
--- a/storage/maria/maria_chk.c
+++ b/storage/maria/maria_chk.c
@@ -727,6 +727,7 @@ get_one_option(int optid,
case 2:
method_conv= MI_STATS_METHOD_IGNORE_NULLS;
break;
+ default: assert(0); /* Impossible */
}
check_param.stats_method= method_conv;
break;
diff --git a/storage/maria/maria_def.h b/storage/maria/maria_def.h
index b174df2fa3e..f4684735938 100644
--- a/storage/maria/maria_def.h
+++ b/storage/maria/maria_def.h
@@ -817,6 +817,7 @@ my_bool _ma_unique_comp(MARIA_UNIQUEDEF *def, const byte *a, const byte *b,
my_bool null_are_equal);
void _ma_get_status(void *param, int concurrent_insert);
void _ma_update_status(void *param);
+void _ma_restore_status(void *param);
void _ma_copy_status(void *to, void *from);
my_bool _ma_check_status(void *param);
diff --git a/storage/maria/maria_pack.c b/storage/maria/maria_pack.c
index 41c519693d5..a76b1027179 100644
--- a/storage/maria/maria_pack.c
+++ b/storage/maria/maria_pack.c
@@ -2696,8 +2696,9 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
}
case FIELD_VARCHAR:
{
- uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
- ulong col_length= (pack_length == 1 ? (uint) *(uchar*) start_pos :
+ uint var_pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
+ ulong col_length= (var_pack_length == 1 ?
+ (uint) *(uchar*) start_pos :
uint2korr(start_pos));
/* Empty varchar are encoded with a single 1 bit. */
if (!col_length)
@@ -2707,7 +2708,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
}
else
{
- byte *end=start_pos+pack_length+col_length;
+ byte *end= start_pos + var_pack_length + col_length;
DBUG_PRINT("fields", ("FIELD_VARCHAR not empty, bits: 1"));
write_bits(0,1);
/* Write the varchar length. */
@@ -2715,7 +2716,7 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
col_length, count->length_bits));
write_bits(col_length,count->length_bits);
/* Encode the varchar bytes. */
- for (start_pos+=pack_length ; start_pos < end ; start_pos++)
+ for (start_pos+= var_pack_length ; start_pos < end ; start_pos++)
{
DBUG_PRINT("fields",
("value: 0x%02x code: 0x%s bits: %2u bin: %s",
diff --git a/storage/maria/unittest/ma_test_loghandler_pagecache-t.c b/storage/maria/unittest/ma_test_loghandler_pagecache-t.c
index 211eb6dea9e..9204d531ea1 100644
--- a/storage/maria/unittest/ma_test_loghandler_pagecache-t.c
+++ b/storage/maria/unittest/ma_test_loghandler_pagecache-t.c
@@ -21,7 +21,7 @@ static PAGECACHE_FILE file1;
int main(int argc, char *argv[])
{
uint pagen;
- uchar long_tr_id[6];
+ byte long_tr_id[6];
PAGECACHE pagecache;
LSN lsn;
MY_STAT st, *stat;
diff --git a/storage/myisam/ha_myisam.cc b/storage/myisam/ha_myisam.cc
index 0113fe80a08..f0bee43c4c6 100644
--- a/storage/myisam/ha_myisam.cc
+++ b/storage/myisam/ha_myisam.cc
@@ -293,7 +293,7 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
Check for underlying table conformance
SYNOPSIS
- check_definition()
+ myisam_check_definition()
t1_keyinfo in First table key definition
t1_recinfo in First table record definition
t1_keys in Number of keys in first table
@@ -323,13 +323,13 @@ int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
1 - Different definitions.
*/
-int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
- uint t1_keys, uint t1_recs,
- MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
- uint t2_keys, uint t2_recs, bool strict)
+int myisam_check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
+ uint t1_keys, uint t1_recs,
+ MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
+ uint t2_keys, uint t2_recs, bool strict)
{
uint i, j;
- DBUG_ENTER("check_definition");
+ DBUG_ENTER("myisam_check_definition");
if ((strict ? t1_keys != t2_keys : t1_keys > t2_keys))
{
DBUG_PRINT("error", ("Number of keys differs: t1_keys=%u, t2_keys=%u",
diff --git a/storage/myisammrg/ha_myisammrg.cc b/storage/myisammrg/ha_myisammrg.cc
index d9e7e1d5700..73f84e307c1 100644
--- a/storage/myisammrg/ha_myisammrg.cc
+++ b/storage/myisammrg/ha_myisammrg.cc
@@ -48,10 +48,12 @@ static const char *ha_myisammrg_exts[] = {
};
extern int table2myisam(TABLE *table_arg, MI_KEYDEF **keydef_out,
MI_COLUMNDEF **recinfo_out, uint *records_out);
-extern int check_definition(MI_KEYDEF *t1_keyinfo, MI_COLUMNDEF *t1_recinfo,
- uint t1_keys, uint t1_recs,
- MI_KEYDEF *t2_keyinfo, MI_COLUMNDEF *t2_recinfo,
- uint t2_keys, uint t2_recs, bool strict);
+extern int myisam_check_definition(MI_KEYDEF *t1_keyinfo,
+ MI_COLUMNDEF *t1_recinfo,
+ uint t1_keys, uint t1_recs,
+ MI_KEYDEF *t2_keyinfo,
+ MI_COLUMNDEF *t2_recinfo,
+ uint t2_keys, uint t2_recs, bool strict);
const char **ha_myisammrg::bas_ext() const
{
@@ -115,10 +117,10 @@ int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
}
for (u_table= file->open_tables; u_table < file->end_table; u_table++)
{
- if (check_definition(keyinfo, recinfo, keys, recs,
- u_table->table->s->keyinfo, u_table->table->s->rec,
- u_table->table->s->base.keys,
- u_table->table->s->base.fields, false))
+ if (myisam_check_definition(keyinfo, recinfo, keys, recs,
+ u_table->table->s->keyinfo, u_table->table->s->rec,
+ u_table->table->s->base.keys,
+ u_table->table->s->base.fields, false))
{
my_free((gptr) recinfo, MYF(0));
error= HA_ERR_WRONG_MRG_TABLE_DEF;