diff options
Diffstat (limited to 'myisam/mi_key.c')
-rw-r--r-- | myisam/mi_key.c | 54 |
1 files changed, 44 insertions, 10 deletions
diff --git a/myisam/mi_key.c b/myisam/mi_key.c index 89f6bc490fa..766ecf334b6 100644 --- a/myisam/mi_key.c +++ b/myisam/mi_key.c @@ -18,6 +18,7 @@ #include "myisamdef.h" #include "m_ctype.h" +#include <assert.h> #ifdef HAVE_IEEEFP_H #include <ieeefp.h> #endif @@ -388,53 +389,86 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf) return(-1); /* Wrong data to read */ } + +/* + Update auto_increment info - /* Update auto_increment info */ + SYNOPSIS + update_auto_increment() + info MyISAM handler + record Row to update + + IMPLEMENTATION + Only replace the auto_increment value if it is higher than the previous + one. For signed columns we don't update the auto increment value if it's + less than zero. +*/ void update_auto_increment(MI_INFO *info,const byte *record) { - ulonglong value; - MI_KEYSEG *keyseg=info->s->keyinfo[info->s->base.auto_key-1].seg; - const uchar *key=(uchar*) record+keyseg->start; + ulonglong value= 0; /* Store unsigned values here */ + longlong s_value= 0; /* Store signed values here */ + MI_KEYSEG *keyseg= info->s->keyinfo[info->s->base.auto_key-1].seg; + const uchar *key= (uchar*) record + keyseg->start; switch (keyseg->type) { case HA_KEYTYPE_INT8: + s_value= (longlong) *(char*)key; + break; case HA_KEYTYPE_BINARY: value=(ulonglong) *(uchar*) key; break; case HA_KEYTYPE_SHORT_INT: + s_value= (longlong) sint2korr(key); + break; case HA_KEYTYPE_USHORT_INT: value=(ulonglong) uint2korr(key); break; case HA_KEYTYPE_LONG_INT: + s_value= (longlong) sint4korr(key); + break; case HA_KEYTYPE_ULONG_INT: value=(ulonglong) uint4korr(key); break; case HA_KEYTYPE_INT24: + s_value= (longlong) sint3korr(key); + break; case HA_KEYTYPE_UINT24: value=(ulonglong) uint3korr(key); break; - case HA_KEYTYPE_FLOAT: /* This shouldn't be used */ + case HA_KEYTYPE_FLOAT: /* This shouldn't be used */ { float f_1; float4get(f_1,key); - value = (ulonglong) f_1; + /* Ignore negative values */ + value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1; break; } - case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */ + case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */ { double f_1; float8get(f_1,key); - value = (ulonglong) f_1; + /* Ignore negative values */ + value = (f_1 < 0.0) ? 0 : (ulonglong) f_1; break; } case HA_KEYTYPE_LONGLONG: + s_value= sint8korr(key); + break; case HA_KEYTYPE_ULONGLONG: value= uint8korr(key); break; default: - value=0; /* Error */ + DBUG_ASSERT(0); + value=0; /* Error */ break; } - set_if_bigger(info->s->state.auto_increment,value); + + /* + The following code works becasue if s_value < 0 then value is 0 + and if s_value == 0 then value will contain either s_value or the + correct value. + */ + set_if_bigger(info->s->state.auto_increment, + (s_value > 0) ? (ulonglong) s_value : value); } |