summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorunknown <monty@mashka.mysql.fi>2003-09-05 06:42:55 +0300
committerunknown <monty@mashka.mysql.fi>2003-09-05 06:42:55 +0300
commitdd782659d60e63356361d4aa2d8ec9c2202053e4 (patch)
tree5dd76a6d814942ef3e3f103a780cc8adc7877e7d
parent587e80cb2f1248543a4135acf5019014adc9cdad (diff)
downloadmariadb-git-dd782659d60e63356361d4aa2d8ec9c2202053e4.tar.gz
Fixed rare bug in MYISAM introduced in 4.0.3 where the index file header was not updated directly after an UPDATE of split dynamic rows.
myisam/mi_locking.c: Added DBUG info myisam/mi_open.c: Added DBUG info myisam/mi_update.c: More comments Fixed rare bug in MYISAM introduced in 4.0.3 where the index file header was not updated directly after an UPDATE of split dynamic rows. mysql-test/r/myisam.result: Added test case for MyISAM UPDATE bug mysql-test/t/myisam.test: Added test case for MyISAM UPDATE bug
-rw-r--r--myisam/mi_locking.c6
-rw-r--r--myisam/mi_open.c9
-rw-r--r--myisam/mi_update.c32
-rw-r--r--mysql-test/r/myisam.result22
-rw-r--r--mysql-test/t/myisam.test34
5 files changed, 90 insertions, 13 deletions
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index 18daebffa85..a707eb294a9 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -76,6 +76,8 @@ int mi_lock_database(MI_INFO *info, int lock_type)
}
if (!count)
{
+ DBUG_PRINT("info",("changed: %u w_locks: %u",
+ (uint) share->changed, share->w_locks));
if (share->changed && !share->w_locks)
{
share->state.process= share->last_process=share->this_process;
@@ -352,6 +354,8 @@ int _mi_writeinfo(register MI_INFO *info, uint operation)
int error,olderror;
MYISAM_SHARE *share=info->s;
DBUG_ENTER("_mi_writeinfo");
+ DBUG_PRINT("info",("operation: %u tot_locks: %u", operation,
+ share->tot_locks));
error=0;
if (share->tot_locks == 0)
@@ -379,9 +383,7 @@ int _mi_writeinfo(register MI_INFO *info, uint operation)
my_errno=olderror;
}
else if (operation)
- {
share->changed= 1; /* Mark keyfile changed */
- }
DBUG_RETURN(error);
} /* _mi_writeinfo */
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 857ca1486fd..580261d8078 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -730,6 +730,7 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
uchar *ptr=buff;
uint i, keys= (uint) state->header.keys,
key_blocks=state->header.max_block_size;
+ DBUG_ENTER("mi_state_info_write");
memcpy_fixed(ptr,&state->header,sizeof(state->header));
ptr+=sizeof(state->header);
@@ -780,10 +781,10 @@ uint mi_state_info_write(File file, MI_STATE_INFO *state, uint pWrite)
}
if (pWrite & 1)
- return my_pwrite(file,(char*) buff, (uint) (ptr-buff), 0L,
- MYF(MY_NABP | MY_THREADSAFE));
- else
- return my_write(file, (char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
+ DBUG_RETURN(my_pwrite(file,(char*) buff, (uint) (ptr-buff), 0L,
+ MYF(MY_NABP | MY_THREADSAFE)));
+ DBUG_RETURN(my_write(file, (char*) buff, (uint) (ptr-buff),
+ MYF(MY_NABP)));
}
diff --git a/myisam/mi_update.c b/myisam/mi_update.c
index 1614d6ca19d..f9ed969d8b5 100644
--- a/myisam/mi_update.c
+++ b/myisam/mi_update.c
@@ -94,7 +94,14 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
if (_mi_ft_cmp(info,i,oldrec, newrec))
{
if ((int) i == info->lastinx)
+ {
+ /*
+ We are changeing the index we are reading on. Mark that
+ the index data has changed and we need to do a full search
+ when doing read-next
+ */
key_changed|=HA_STATE_WRITTEN;
+ }
changed|=((ulonglong) 1 << i);
if (_mi_ft_update(info,i,(char*) old_key,oldrec,newrec,pos))
goto err;
@@ -121,25 +128,36 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
}
/*
If we are running with external locking, we must update the index file
- that something has changed
+ that something has changed.
*/
if (changed || !my_disable_locking)
- key_changed|= HA_STATE_KEY_CHANGED;
+ key_changed|= HA_STATE_CHANGED;
if (share->calc_checksum)
{
info->checksum=(*share->calc_checksum)(info,newrec);
- key_changed|= HA_STATE_KEY_CHANGED; /* Must update index file */
+ /* Store new checksum in index file header */
+ key_changed|= HA_STATE_CHANGED;
}
{
- /* Don't update index file if data file is not extended */
+ /*
+ Don't update index file if data file is not extended and no status
+ information changed
+ */
MI_STATUS_INFO state;
+ ha_rows org_split;
+ my_off_t org_delete_link;
+
memcpy((char*) &state, (char*) info->state, sizeof(state));
+ org_split= share->state.split;
+ org_delete_link= share->state.dellink;
if ((*share->update_record)(info,pos,newrec))
goto err;
if (!key_changed &&
- memcmp((char*) &state, (char*) info->state, sizeof(state)))
- key_changed|= HA_STATE_KEY_CHANGED; /* Must update index file */
+ (memcmp((char*) &state, (char*) info->state, sizeof(state)) ||
+ org_split != share->state.split ||
+ org_delete_link != share->state.dellink))
+ key_changed|= HA_STATE_CHANGED; /* Must update index file */
}
if (auto_key_changed)
update_auto_increment(info,newrec);
@@ -163,7 +181,7 @@ err:
DBUG_PRINT("error",("key: %d errno: %d",i,my_errno));
save_errno=my_errno;
if (changed)
- key_changed|= HA_STATE_KEY_CHANGED;
+ key_changed|= HA_STATE_CHANGED;
if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
{
info->errkey= (int) i;
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index e78e12c01d5..3052af3499d 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -364,3 +364,25 @@ explain select * from t1 force index (a) where a=0 or a=2;
table type possible_keys key key_len ref rows Extra
t1 range a a 4 NULL 4 Using where
drop table t1,t2;
+create table t1 (a int not null auto_increment primary key, b varchar(255));
+insert into t1 (b) values (repeat('a',100)),(repeat('b',100)),(repeat('c',100));
+update t1 set b=repeat(left(b,1),200) where a=1;
+delete from t1 where (a & 1)= 0;
+update t1 set b=repeat('e',200) where a=1;
+flush tables;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+update t1 set b=repeat(left(b,1),255) where a between 1 and 5;
+update t1 set b=repeat(left(b,1),10) where a between 32 and 43;
+update t1 set b=repeat(left(b,1),2) where a between 64 and 66;
+update t1 set b=repeat(left(b,1),65) where a between 67 and 70;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+insert into t1 (b) values (repeat('z',100));
+update t1 set b="test" where left(b,1) > 'n';
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index 02c92109816..a5490153a17 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -352,3 +352,37 @@ explain select * from t1,t2 force index(c) where t1.a=t2.a;
explain select * from t1 where a=0 or a=2;
explain select * from t1 force index (a) where a=0 or a=2;
drop table t1,t2;
+
+#
+# Test bug when updating a split dynamic row where keys are not changed
+#
+
+create table t1 (a int not null auto_increment primary key, b varchar(255));
+insert into t1 (b) values (repeat('a',100)),(repeat('b',100)),(repeat('c',100));
+update t1 set b=repeat(left(b,1),200) where a=1;
+delete from t1 where (a & 1)= 0;
+update t1 set b=repeat('e',200) where a=1;
+flush tables;
+check table t1;
+
+#
+# check updating with keys
+#
+
+disable_query_log;
+let $1 = 100;
+while ($1)
+{
+ eval insert into t1 (b) values (repeat(char(($1 & 32)+65), $1));
+ dec $1;
+}
+enable_query_log;
+update t1 set b=repeat(left(b,1),255) where a between 1 and 5;
+update t1 set b=repeat(left(b,1),10) where a between 32 and 43;
+update t1 set b=repeat(left(b,1),2) where a between 64 and 66;
+update t1 set b=repeat(left(b,1),65) where a between 67 and 70;
+check table t1;
+insert into t1 (b) values (repeat('z',100));
+update t1 set b="test" where left(b,1) > 'n';
+check table t1;
+drop table t1;