Commit ab0fa111 authored by unknown's avatar unknown

Fixed bug in restoring auto-increment value in case of duplicate key with insert or update

Fixed bug when calculating max_key_length that caused some ALTER TABLE to fail if MAX_ROWS was used.
Use maria_block_size instead of MARIA_MIN_KEY_BLOCK_LENGTH
Fixed bug when scanning table with BLOCK format for repair; If table was > bitmap coverage one page block was read twice which caused a lot of duplicate key errors
Could not repeat Bug#34106 "auto_increment is reset to 1 when table is recovered from crash" after this patch.

NOTE: This is an incompatible change, so one must do maria_chk -r on ones old Maria tables!
Sorry, but this was needed to fix the bug with max_key_length and to be able to handle bigger key files with smaller key references


cmd-line-utils/readline/readline.c:
  Fixed compiler warnings
mysql-test/r/maria.result:
  Added more test of auto-increment handling
mysql-test/t/maria.test:
  Added more test of auto-increment handling
mysys/my_pread.c:
  Fixed wrong test
  Removed not needed tests (error is always 1 if readbytes != Count)
mysys/my_read.c:
  Fixed wrong test
storage/maria/ha_maria.cc:
  Disable LOAD INDEX until I got Sanja's extension to pagecache interface
storage/maria/ma_blockrec.c:
  Ensure that info->last_auto_increment is reset properly
storage/maria/ma_check.c:
  Fixed wrong printing of row number in case of duplicate key for --safe-repair
  Safety fix in recreate table so that Column numbers are given to maria_create() in original order
  Added missing HA_OPEN_FOR_REPAIR to maria_open()
  Fixed bug when scanning table with BLOCK format for repair; If table was > bitmap coverage one page block was read twice which caused a lot of duplicate key errors
storage/maria/ma_create.c:
  Use correct value for how much free space there is on a key page
  Remember some missing table option when doing re-create.
  Removed optimization where last packed fields is unpacked; Caused problems for re-create.
storage/maria/ma_delete.c:
  Ensure that info->last_auto_increment is reset properly
  Fix for update to restore autoincrement value on duplicate key
storage/maria/ma_key_recover.c:
  Moved handling of restoring value of auto-increment in case of duplicate key from clr to undo
  This ensures the restoring works both for insert and update and also that this is symetrical to how the auto_increment value is stored
storage/maria/ma_key_recover.h:
  Added new prototype
storage/maria/ma_loghandler.c:
  Added hook to write_hook_for_undo_key_delete()
storage/maria/ma_open.c:
  Fixed wrong calculation of max_key_file_length
storage/maria/ma_page.c:
  Use maria_block_size instead of MARIA_MIN_KEY_BLOCK_LENGTH
  Increase internal buffer (safety fix)
storage/maria/ma_search.c:
  Use maria_block_size instead of MARIA_MIN_KEY_BLOCK_LENGTH
  Note that this is an incompatible change, so one must do maria_chk -r on ones old Maria tables (sorry)
storage/maria/ma_update.c:
  Ensure that info->last_auto_increment is reset properly
storage/maria/ma_write.c:
  Ensure that info->last_auto_increment is reset properly
  Fix for update to restore autoincrement value on duplicate key
storage/maria/maria_chk.c:
  Allow small page_buffer_size
  Fixed printing for --describe to better fit into 80 characters
storage/maria/maria_def.h:
  Added comments
parent b40a6348
......@@ -90,7 +90,6 @@ static void bind_arrow_keys_internal PARAMS((Keymap));
static void bind_arrow_keys PARAMS((void));
static void readline_default_bindings PARAMS((void));
static void reset_default_bindings PARAMS((void));
static int _rl_subseq_result PARAMS((int, Keymap, int, int));
static int _rl_subseq_getchar PARAMS((int));
......@@ -287,7 +286,7 @@ rl_set_prompt (prompt)
{
FREE (rl_prompt);
rl_prompt = prompt ? savestring (prompt) : (char *)NULL;
rl_display_prompt = rl_prompt ? rl_prompt : "";
rl_display_prompt = rl_prompt ? rl_prompt : (char*) "";
rl_visible_prompt_length = rl_expand_prompt (rl_prompt);
return 0;
......@@ -1072,18 +1071,6 @@ readline_default_bindings ()
rl_tty_set_default_bindings (_rl_keymap);
}
/* Reset the default bindings for the terminal special characters we're
interested in back to rl_insert and read the new ones. */
static void
reset_default_bindings ()
{
if (_rl_bind_stty_chars)
{
rl_tty_unset_default_bindings (_rl_keymap);
rl_tty_set_default_bindings (_rl_keymap);
}
}
/* Bind some common arrow key sequences in MAP. */
static void
bind_arrow_keys_internal (map)
......
......@@ -2200,3 +2200,45 @@ id f1
2 test2
drop table t1;
SET SQL_MODE = 'TRADITIONAL';
create table t1 (n int not null primary key auto_increment, c char(1), unique(c));
insert into t1 values(100, "a");
insert into t1 values(300, "b");
insert into t1 values(50, "a");
ERROR 23000: Duplicate entry 'a' for key 'c'
insert into t1 values(null, "c");
select * from t1;
n c
100 a
300 b
301 c
update t1 set n=400,c='a' where n=301;
ERROR 23000: Duplicate entry 'a' for key 'c'
insert into t1 values(null, "d");
select * from t1;
n c
100 a
300 b
301 c
302 d
drop table t1;
create table t1 (n int not null primary key auto_increment, c char(1), unique(c)) transactional=0 row_format=dynamic;
insert into t1 values(100, "a");
insert into t1 values(300, "b");
insert into t1 values(50, "a");
ERROR 23000: Duplicate entry 'a' for key 'c'
insert into t1 values(null, "c");
select * from t1;
n c
100 a
300 b
301 c
update t1 set n=400,c='a' where n=301;
ERROR 23000: Duplicate entry 'a' for key 'c'
insert into t1 values(null, "d");
select * from t1;
n c
100 a
300 b
301 c
302 d
drop table t1;
......@@ -1426,6 +1426,33 @@ SELECT * FROM t1;
drop table t1;
SET SQL_MODE = 'TRADITIONAL';
create table t1 (n int not null primary key auto_increment, c char(1), unique(c));
insert into t1 values(100, "a");
insert into t1 values(300, "b");
--error 1062
insert into t1 values(50, "a");
insert into t1 values(null, "c");
select * from t1;
--error 1062
update t1 set n=400,c='a' where n=301;
insert into t1 values(null, "d");
select * from t1;
drop table t1;
create table t1 (n int not null primary key auto_increment, c char(1), unique(c)) transactional=0 row_format=dynamic;
insert into t1 values(100, "a");
insert into t1 values(300, "b");
--error 1062
insert into t1 values(50, "a");
insert into t1 values(null, "c");
select * from t1;
--error 1062
update t1 set n=400,c='a' where n=301;
insert into t1 values(null, "d");
select * from t1;
drop table t1;
# End of 5.2 tests
--disable_result_log
......
......@@ -66,11 +66,12 @@ size_t my_pread(File Filedes, uchar *Buffer, size_t Count, my_off_t offset,
if ((error= ((readbytes= pread(Filedes, Buffer, Count, offset)) != Count)))
{
my_errno= errno;
if (errno == 0 || (errno == -1 && (MyFlags & (MY_NABP | MY_FNABP))))
if (errno == 0 || (readbytes == (size_t) -1 &&
(MyFlags & (MY_NABP | MY_FNABP))))
my_errno= HA_ERR_FILE_TOO_SHORT;
}
#endif
if (error || readbytes != Count)
if (error)
{
DBUG_PRINT("warning",("Read only %d bytes off %u from %d, errno: %d",
(int) readbytes, (uint) Count,Filedes,my_errno));
......
......@@ -47,7 +47,8 @@ size_t my_read(File Filedes, uchar *Buffer, size_t Count, myf MyFlags)
if ((readbytes= read(Filedes, Buffer, Count)) != Count)
{
my_errno= errno;
if (errno == 0 || (errno == -1 && (MyFlags & (MY_NABP | MY_FNABP))))
if (errno == 0 || (readbytes == (size_t) -1 &&
(MyFlags & (MY_NABP | MY_FNABP))))
my_errno= HA_ERR_FILE_TOO_SHORT;
DBUG_PRINT("warning",("Read only %d bytes off %lu from %d, errno: %d",
(int) readbytes, (ulong) Count, Filedes,
......
......@@ -1491,6 +1491,7 @@ int ha_maria::preload_keys(THD * thd, HA_CHECK_OPT *check_opt)
maria_extra(file, HA_EXTRA_PRELOAD_BUFFER_SIZE,
(void*) &thd->variables.preload_buff_size);
#ifndef NOT_YET
if ((error= maria_preload(file, map, ignore_leaves)))
{
switch (error) {
......@@ -1508,7 +1509,7 @@ int ha_maria::preload_keys(THD * thd, HA_CHECK_OPT *check_opt)
error= HA_ADMIN_FAILED;
goto err;
}
#endif
DBUG_RETURN(HA_ADMIN_OK);
err:
......
......@@ -6415,6 +6415,7 @@ my_bool _ma_apply_undo_row_insert(MARIA_HA *info, LSN undo_lsn,
checksum= 0;
if (share->calc_checksum)
checksum= (ha_checksum) 0 - ha_checksum_korr(header);
info->last_auto_increment= ~ (ulonglong) 0;
if (_ma_write_clr(info, undo_lsn, LOGREC_UNDO_ROW_INSERT,
share->calc_checksum != 0, checksum, &lsn, (void*) 0))
goto err;
......@@ -6815,6 +6816,7 @@ my_bool _ma_apply_undo_row_update(MARIA_HA *info, LSN undo_lsn,
(*share->calc_checksum)(info, current_record));
}
info->last_auto_increment= ~ (ulonglong) 0;
/* Now records are up to date, execute the update to original values */
if (_ma_update_at_original_place(info, page, rownr, length_on_head_page,
extent_count, extent_info,
......
......@@ -2361,11 +2361,11 @@ int maria_repair(HA_CHECK *param, register MARIA_HA *info,
if (my_errno != HA_ERR_FOUND_DUPP_KEY)
goto err;
DBUG_DUMP("record",(uchar*) sort_param.record,share->base.pack_reclength);
_ma_check_print_info(param,
"Duplicate key %2d for record at %10s against new record at %10s",
info->errkey+1,
llstr(sort_param.start_recpos,llbuff),
llstr(info->dup_key_pos,llbuff2));
_ma_check_print_warning(param,
"Duplicate key %2d for record at %10s against new record at %10s",
info->errkey+1,
llstr(sort_param.current_filepos, llbuff),
llstr(info->dup_key_pos,llbuff2));
if (param->testflag & T_VERBOSE)
{
VOID(_ma_make_key(info,(uint) info->errkey,info->lastkey,
......@@ -4972,13 +4972,14 @@ static int sort_key_write(MARIA_SORT_PARAM *sort_param, const uchar *a)
sort_param->keyinfo,
a);
_ma_check_print_warning(param,
"Duplicate key for record at %10s against record at %10s",
llstr(sort_info->info->cur_row.lastpos, llbuff),
llstr(get_record_for_key(sort_info->info,
sort_param->keyinfo,
sort_info->key_block->
lastkey),
llbuff2));
"Duplicate key %2u for record at %10s against record at %10s",
sort_param->key + 1,
llstr(sort_info->info->cur_row.lastpos, llbuff),
llstr(get_record_for_key(sort_info->info,
sort_param->keyinfo,
sort_info->key_block->
lastkey),
llbuff2));
param->testflag|=T_RETRY_WITHOUT_QUICK;
if (sort_info->param->testflag & T_VERBOSE)
_ma_print_key(stdout,sort_param->seg, a, USE_WHOLE_KEY);
......@@ -5409,7 +5410,8 @@ int maria_test_if_almost_full(MARIA_HA *info)
(my_off_t) share->base.max_data_file_length;
}
/* Recreate table with bigger more alloced record-data */
/* Recreate table with bigger more alloced record-data */
int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
{
......@@ -5432,8 +5434,8 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
status_info= (*org_info)->state[0];
info.state= &status_info;
share= *(*org_info)->s;
unpack= (share.options & HA_OPTION_COMPRESS_RECORD) &&
(param->testflag & T_UNPACK);
unpack= ((share.data_file_type == COMPRESSED_RECORD) &&
(param->testflag & T_UNPACK));
if (!(keyinfo=(MARIA_KEYDEF*) my_alloca(sizeof(MARIA_KEYDEF) *
share.base.keys)))
DBUG_RETURN(0);
......@@ -5463,19 +5465,11 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
DBUG_RETURN(1);
}
/* Copy the column definitions */
memcpy((uchar*) columndef,(uchar*) share.columndef,
(size_t) (sizeof(MARIA_COLUMNDEF)*(share.base.fields+1)));
for (column=columndef, end= columndef+share.base.fields;
/* Copy the column definitions in their original order */
for (column= share.columndef, end= share.columndef+share.base.fields;
column != end ;
column++)
{
if (unpack && !(share.options & HA_OPTION_PACK_RECORD) &&
column->type != FIELD_BLOB &&
column->type != FIELD_VARCHAR &&
column->type != FIELD_CHECK)
column->type=(int) FIELD_NORMAL;
}
columndef[column->column_nr]= *column;
/* Change the new key to point at the saved key segments */
memcpy((uchar*) keysegs,(uchar*) share.keyparts,
......@@ -5505,25 +5499,23 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
u_ptr->seg=keyseg;
keyseg+=u_ptr->keysegs+1;
}
file_length=(ulonglong) my_seek(info.dfile.file, 0L, MY_SEEK_END, MYF(0));
if (share.options & HA_OPTION_COMPRESS_RECORD)
share.base.records=max_records=info.state->records;
else if (share.base.min_pack_length)
max_records=(ha_rows) (my_seek(info.dfile.file, 0L, MY_SEEK_END,
MYF(0)) /
(ulong) share.base.min_pack_length);
max_records=(ha_rows) (file_length / share.base.min_pack_length);
else
max_records=0;
unpack= (share.data_file_type == COMPRESSED_RECORD) &&
(param->testflag & T_UNPACK);
share.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
file_length=(ulonglong) my_seek(info.dfile.file, 0L, MY_SEEK_END, MYF(0));
tmp_length= file_length+file_length/10;
set_if_bigger(file_length,param->max_data_file_length);
set_if_bigger(file_length,tmp_length);
set_if_bigger(file_length,(ulonglong) share.base.max_data_file_length);
VOID(maria_close(*org_info));
bzero((char*) &create_info,sizeof(create_info));
create_info.max_rows=max(max_records,share.base.records);
create_info.reloc_rows=share.base.reloc;
......@@ -5544,6 +5536,8 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
*/
create_info.with_auto_increment= TRUE;
create_info.null_bytes= share.base.null_bytes;
create_info.transactional= share.base.born_transactional;
/*
We don't have to handle symlinks here because we are using
HA_DONT_TOUCH_DATA
......@@ -5560,10 +5554,13 @@ int maria_recreate_table(HA_CHECK *param, MARIA_HA **org_info, char *filename)
my_errno);
goto end;
}
*org_info=maria_open(filename,O_RDWR,
(param->testflag & T_WAIT_FOREVER) ? HA_OPEN_WAIT_IF_LOCKED :
(param->testflag & T_DESCRIPT) ? HA_OPEN_IGNORE_IF_LOCKED :
HA_OPEN_ABORT_IF_LOCKED);
*org_info= maria_open(filename,O_RDWR,
(HA_OPEN_FOR_REPAIR |
((param->testflag & T_WAIT_FOREVER) ?
HA_OPEN_WAIT_IF_LOCKED :
(param->testflag & T_DESCRIPT) ?
HA_OPEN_IGNORE_IF_LOCKED :
HA_OPEN_ABORT_IF_LOCKED)));
if (!*org_info)
{
_ma_check_print_error(param,
......@@ -6143,7 +6140,11 @@ static int _ma_safe_scan_block_record(MARIA_SORT_INFO *sort_info,
sort_info->page++; /* In case of errors */
page++;
if (!(page % share->bitmap.pages_covered))
page++; /* Skip bitmap */
{
/* Skip bitmap */
page++;
sort_info->page++;
}
if ((my_off_t) (page + 1) * share->block_size > sort_info->filelength)
DBUG_RETURN(HA_ERR_END_OF_FILE);
if (!(pagecache_read(share->pagecache,
......
......@@ -97,15 +97,18 @@ int maria_create(const char *name, enum data_file_type datafile_type,
{
org_datafile_type= ci->org_data_file_type;
if (!(ci->old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
options=ci->old_options &
(HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM |
HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
options= (ci->old_options &
(HA_OPTION_COMPRESS_RECORD | HA_OPTION_PACK_RECORD |
HA_OPTION_READ_ONLY_DATA | HA_OPTION_CHECKSUM |
HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE |
HA_OPTION_LONG_BLOB_PTR | HA_OPTION_PAGE_CHECKSUM));
else
{
/* Uncompressing rows */
options=ci->old_options &
(HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE | HA_OPTION_DELAY_KEY_WRITE);
options= (ci->old_options &
(HA_OPTION_CHECKSUM | HA_OPTION_TMP_TABLE |
HA_OPTION_DELAY_KEY_WRITE | HA_OPTION_LONG_BLOB_PTR |
HA_OPTION_PAGE_CHECKSUM));
}
}
......@@ -257,31 +260,6 @@ int maria_create(const char *name, enum data_file_type datafile_type,
else
min_pack_length+= 5; /* Min row overhead */
if ((packed & 7) == 1)
{
/*
Not optimal packing, try to remove a 1 uchar length zero-field as
this will get same record length, but smaller pack overhead
*/
while (column != columndef)
{
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;
packed--;
min_pack_length++;
break;
}
}
}
if (flags & HA_CREATE_TMP_TABLE)
{
options|= HA_OPTION_TMP_TABLE;
......@@ -641,7 +619,9 @@ int maria_create(const char *name, enum data_file_type datafile_type,
if (length > max_key_length)
max_key_length= length;
tot_length+= ((max_rows/(ulong) (((uint) maria_block_size-5)/
tot_length+= ((max_rows/(ulong) (((uint) maria_block_size -
MAX_KEYPAGE_HEADER_SIZE -
KEYPAGE_CHECKSUM_SIZE)/
(length*2))) *
maria_block_size);
}
......@@ -652,7 +632,9 @@ int maria_create(const char *name, enum data_file_type datafile_type,
uniquedef->key=keys+i;
unique_key_parts+=uniquedef->keysegs;
share.state.key_root[keys+i]= HA_OFFSET_ERROR;
tot_length+= (max_rows/(ulong) (((uint) maria_block_size-5)/
tot_length+= (max_rows/(ulong) (((uint) maria_block_size -
MAX_KEYPAGE_HEADER_SIZE -
KEYPAGE_CHECKSUM_SIZE) /
((MARIA_UNIQUE_HASH_LENGTH + pointer)*2)))*
(ulong) maria_block_size;
}
......@@ -704,12 +686,16 @@ int maria_create(const char *name, enum data_file_type datafile_type,
share.base.rec_reflength=pointer;
share.base.block_size= maria_block_size;
/* Get estimate for index file length (this may be wrong for FT keys) */
/*
Get estimate for index file length (this may be wrong for FT keys)
This is used for pointers to other key pages.
*/
tmp= (tot_length + maria_block_size * keys *
MARIA_INDEX_BLOCK_MARGIN) / maria_block_size;
/*
use maximum of key_file_length we calculated and key_file_length value we
got from MYI file header (see also mariapack.c:save_state)
got from MAI file header (see also mariapack.c:save_state)
*/
share.base.key_reflength=
maria_get_pointer_length(max(ci->key_file_length,tmp),3);
......
......@@ -71,6 +71,8 @@ int maria_delete(MARIA_HA *info,const uchar *record)
if (_ma_mark_file_changed(info))
goto err;
/* Ensure we don't change the autoincrement value */
info->last_auto_increment= ~(ulonglong) 0;
/* Remove all keys from the index file */
old_key= info->lastkey2;
......@@ -212,6 +214,11 @@ int _ma_ck_delete(register MARIA_HA *info, uint keynr, uchar *key,
msg.root= &share->state.key_root[keynr];
msg.value= new_root;
/*
set autoincrement to 1 if this is an auto_increment key
This is only used if we are now in a rollback of a duplicate key
*/
msg.auto_increment= share->base.auto_key == keynr + 1;
if (translog_write_record(&lsn, log_type,
info->trn, info,
......
......@@ -159,10 +159,6 @@ my_bool write_hook_for_clr_end(enum translog_record_type type
case LOGREC_UNDO_ROW_INSERT:
share->state.state.records--;
share->state.state.checksum+= msg->checksum_delta;
/* Restore auto increment if no one has changed it in between */
if (share->last_auto_increment == tbl_info->last_auto_increment)
share->state.auto_increment= tbl_info->last_auto_increment;
break;
break;
case LOGREC_UNDO_ROW_UPDATE:
share->state.state.checksum+= msg->checksum_delta;
......@@ -212,7 +208,7 @@ my_bool write_hook_for_undo_key(enum translog_record_type type,
/**
Upates "auto_increment" and calls the generic UNDO_KEY hook
Updates "auto_increment" and calls the generic UNDO_KEY hook
@return Operation status, always 0 (success)
*/
......@@ -264,6 +260,32 @@ my_bool write_hook_for_undo_key_insert(enum translog_record_type type,
}
/**
@brief Updates "share->auto_increment" in case of abort and calls
generic UNDO_KEY hook
@return Operation status, always 0 (success)
*/
my_bool write_hook_for_undo_key_delete(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info,
LSN *lsn, void *hook_arg)
{
struct st_msg_to_write_hook_for_undo_key *msg=
(struct st_msg_to_write_hook_for_undo_key *) hook_arg;
MARIA_SHARE *share= tbl_info->s;
if (msg->auto_increment > 0) /* If auto increment key */
{
/* Restore auto increment if no one has changed it in between */
if (share->last_auto_increment == tbl_info->last_auto_increment &&
tbl_info->last_auto_increment != ~(ulonglong) 0)
share->state.auto_increment= tbl_info->last_auto_increment;
}
return write_hook_for_undo_key(type, trn, tbl_info, lsn, hook_arg);
}
/*****************************************************************************
Functions for logging of key page changes
*****************************************************************************/
......
......@@ -55,6 +55,9 @@ extern my_bool write_hook_for_undo_key(enum translog_record_type type,
extern my_bool write_hook_for_undo_key_insert(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info,
LSN *lsn, void *hook_arg);
extern my_bool write_hook_for_undo_key_delete(enum translog_record_type type,
TRN *trn, MARIA_HA *tbl_info,
LSN *lsn, void *hook_arg);
void _ma_unpin_all_pages(MARIA_HA *info, LSN undo_lsn);
my_bool _ma_log_prefix(MARIA_HA *info, my_off_t page,
......
......@@ -543,13 +543,13 @@ static LOG_DESC INIT_LOGREC_UNDO_KEY_INSERT_WITH_ROOT=
static LOG_DESC INIT_LOGREC_UNDO_KEY_DELETE=
{LOGRECTYPE_VARIABLE_LENGTH, 0,
LSN_STORE_SIZE + FILEID_STORE_SIZE + KEY_NR_STORE_SIZE,
NULL, write_hook_for_undo_key, NULL, 1,
NULL, write_hook_for_undo_key_delete, NULL, 1,
"undo_key_delete", LOGREC_LAST_IN_GROUP, NULL, NULL};
static LOG_DESC INIT_LOGREC_UNDO_KEY_DELETE_WITH_ROOT=
{LOGRECTYPE_VARIABLE_LENGTH, 0,
LSN_STORE_SIZE + FILEID_STORE_SIZE + KEY_NR_STORE_SIZE + PAGE_STORE_SIZE,
NULL, write_hook_for_undo_key, NULL, 1,
NULL, write_hook_for_undo_key_delete, NULL, 1,
"undo_key_delete_with_root", LOGREC_LAST_IN_GROUP, NULL, NULL};
static LOG_DESC INIT_LOGREC_PREPARE=
......
......@@ -449,7 +449,7 @@ MARIA_HA *maria_open(const char *name, int mode, uint open_flags)
(ulonglong) 1 << (share->base.rec_reflength*8))-1);
max_key_file_length=
_ma_safe_mul(MARIA_MIN_KEY_BLOCK_LENGTH,
_ma_safe_mul(maria_block_size,
((ulonglong) 1 << (share->base.key_reflength*8))-1);
#if SIZEOF_OFF_T == 4
set_if_smaller(max_data_file_length, INT_MAX32);
......
......@@ -101,7 +101,7 @@ int _ma_write_keypage(register MARIA_HA *info,
_ma_get_used_and_nod(share, buff, page_length, nod);
if (pos < share->base.keystart ||
pos+block_size > info->state->key_file_length ||
(pos & (MARIA_MIN_KEY_BLOCK_LENGTH-1)))
(pos & (maria_block_size-1)))
{
DBUG_PRINT("error",("Trying to write inside key status region: "
"key_start: %lu length: %lu page: %lu",
......@@ -182,7 +182,7 @@ int _ma_write_keypage(register MARIA_HA *info,
int _ma_dispose(register MARIA_HA *info, my_off_t pos, my_bool page_not_read)
{
my_off_t old_link;
uchar buff[MAX_KEYPAGE_HEADER_SIZE+8];
uchar buff[MAX_KEYPAGE_HEADER_SIZE+ 8 + 2];
ulonglong page_no;
MARIA_SHARE *share= info->s;
MARIA_PINNED_PAGE page_link;
......
......@@ -590,11 +590,11 @@ my_off_t _ma_kpos(uint nod_flag, uchar *after_key)
switch (nod_flag) {
#if SIZEOF_OFF_T > 4
case 7:
return mi_uint7korr(after_key)*MARIA_MIN_KEY_BLOCK_LENGTH;
return mi_uint7korr(after_key)*maria_block_size;
case 6:
return mi_uint6korr(after_key)*MARIA_MIN_KEY_BLOCK_LENGTH;
return mi_uint6korr(after_key)*maria_block_size;
case 5:
return mi_uint5korr(after_key)*MARIA_MIN_KEY_BLOCK_LENGTH;
return mi_uint5korr(after_key)*maria_block_size;
#else
case 7:
after_key++;
......@@ -604,13 +604,13 @@ my_off_t _ma_kpos(uint nod_flag, uchar *after_key)
after_key++;
#endif
case 4:
return ((my_off_t) mi_uint4korr(after_key))*MARIA_MIN_KEY_BLOCK_LENGTH;
return ((my_off_t) mi_uint4korr(after_key))*maria_block_size;
case 3:
return ((my_off_t) mi_uint3korr(after_key))*MARIA_MIN_KEY_BLOCK_LENGTH;
return ((my_off_t) mi_uint3korr(after_key))*maria_block_size;
case 2:
return (my_off_t) (mi_uint2korr(after_key)*MARIA_MIN_KEY_BLOCK_LENGTH);
return (my_off_t) (mi_uint2korr(after_key)*maria_block_size);
case 1:
return (uint) (*after_key)*MARIA_MIN_KEY_BLOCK_LENGTH;
return (uint) (*after_key)*maria_block_size;
case 0: /* At leaf page */
default: /* Impossible */
return(HA_OFFSET_ERROR);
......@@ -622,7 +622,7 @@ my_off_t _ma_kpos(uint nod_flag, uchar *after_key)
void _ma_kpointer(register MARIA_HA *info, register uchar *buff, my_off_t pos)
{
pos/=MARIA_MIN_KEY_BLOCK_LENGTH;
pos/=maria_block_size;
switch (info->s->base.key_reflength) {
#if SIZEOF_OFF_T > 4
case 7: mi_int7store(buff,pos); break;
......
......@@ -76,6 +76,9 @@ int maria_update(register MARIA_HA *info, const uchar *oldrec, uchar *newrec)
goto err_end;
}
/* Ensure we don't try to restore auto_increment if it doesn't change */
info->last_auto_increment= ~(ulonglong) 0;
/* Check which keys changed from the original row */
new_key= info->lastkey2;
......
......@@ -138,6 +138,9 @@ int maria_write(MARIA_HA *info, uchar *record)
goto err2;
}
/* Ensure we don't try to restore auto_increment if it doesn't change */
info->last_auto_increment= ~(ulonglong) 0;
if ((info->opt_flag & OPT_NO_ROWS))
filepos= HA_OFFSET_ERROR;
else
......
......@@ -332,7 +332,7 @@ static struct my_option my_long_options[] =
{ "page_buffer_size", OPT_PAGE_BUFFER_SIZE,
"Size of page buffer. Used by --safe-repair",
(uchar**) &check_param.use_buffers, (uchar**) &check_param.use_buffers, 0,
GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, (long) USE_BUFFER_INIT,
GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT, 1024L*1024L,
(long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE, 0},
{ "read_buffer_size", OPT_READ_BUFFER_SIZE, "",
(uchar**) &check_param.read_buffer_length,
......@@ -1466,14 +1466,14 @@ static void descript(HA_CHECK *param, register MARIA_HA *info, char *name)
pos=strmov(pos,null_txt);
*pos=0;
printf("%-4d%-6ld%-3d %-8s%-21s",
printf("%-4d%-6ld%-3d %-8s%-23s",
key+1,(long) keyseg->start+1,keyseg->length,text,buff);
if (share->state.key_root[key] != HA_OFFSET_ERROR)
llstr(share->state.key_root[key],buff);
else
buff[0]=0;
if (param->testflag & T_VERBOSE)
printf("%11.0f %12s %10d",
printf("%9.0f %12s %10d",
share->state.rec_per_key_part[keyseg_nr++],
buff,keyinfo->block_length);
VOID(putchar('\n'));
......
......@@ -65,7 +65,7 @@ typedef struct st_maria_status_info
typedef struct st_maria_state_info
{
struct
{ /* Fileheader */
{ /* Fileheader (24 bytes) */
uchar file_version[4];
uchar options[2];
uchar header_length[2];
......@@ -285,6 +285,10 @@ typedef struct st_maria_share
uchar *file_map; /* mem-map of file if possible */
PAGECACHE *pagecache; /* ref to the current key cache */
MARIA_DECODE_TREE *decode_trees;
/*
Previous auto-increment value. Used to verify if we can restore the
auto-increment counter if we have to abort an insert (duplicate key).
*/
ulonglong last_auto_increment;
uint16 *decode_tables;
uint16 id; /**< 2-byte id by which log records refer to the table */
......@@ -485,7 +489,7 @@ struct st_maria_handler
uint32 int_keytree_version; /* -""- */
int (*read_record)(MARIA_HA *, uchar*, MARIA_RECORD_POS);
invalidator_by_filename invalidator; /* query cache invalidator */
ulonglong last_auto_increment;
ulonglong last_auto_increment; /* auto value at start of statement */
ulong this_unique; /* uniq filenumber or thread */
ulong last_unique; /* last unique number */
ulong this_loop; /* counter for this open */
......
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