Merge joreland@bk-internal.mysql.com:/home/bk/mysql-5.0

into mysql.com:/home/jonas/src/mysql-5.0
This commit is contained in:
joreland@mysql.com 2004-12-20 16:32:34 +01:00
commit 5703971fd2
76 changed files with 2125 additions and 622 deletions

View file

@ -45,6 +45,7 @@ cxx_warnings="$global_warnings -Woverloaded-virtual -Wsign-promo -Wreorder -Wcto
alpha_cflags="-mcpu=ev6 -Wa,-mev6" # Not used yet
pentium_cflags="-mcpu=pentiumpro"
pentium64_cflags="-mcpu=nocona -m64"
ppc_cflags="-mpowerpc -mcpu=powerpc"
sparc_cflags=""

View file

@ -0,0 +1,29 @@
#! /bin/sh
path=`dirname $0`
. "$path/SETUP.sh"
extra_flags="$pentium64_cflags $debug_cflags -USAFEMALLOC -UFORCE_INIT_OF_VARS -DHAVE_purify -DMYSQL_SERVER_SUFFIX=-valgrind-max"
c_warnings="$c_warnings $debug_extra_warnings"
cxx_warnings="$cxx_warnings $debug_extra_warnings"
extra_configs="$pentium_configs $debug_configs"
# We want to test isam when building with valgrind
extra_configs="$extra_configs --with-berkeley-db --with-innodb --with-isam --with-embedded-server --with-openssl --with-vio --with-raid --with-ndbcluster"
. "$path/FINISH.sh"
if test -z "$just_print"
then
set +v +x
echo "\
******************************************************************************
Note that by default BUILD/compile-pentium-valgrind-max calls 'configure' with
--enable-assembler. When Valgrind detects an error involving an assembly
function (for example an uninitialized value used as an argument of an
assembly function), Valgrind will not print the stacktrace and 'valgrind
--gdb-attach=yes' will not work either. If you need a stacktrace in those
cases, you have to run BUILD/compile-pentium-valgrind-max with the
--disable-assembler argument.
******************************************************************************"
fi

View file

@ -978,7 +978,7 @@ uint length)
{
fprintf(_db_fp_, "%s: ", state->func);
}
sprintf(dbuff,"%s: Memory: %lx Bytes: (%d)\n",
sprintf(dbuff,"%s: Memory: 0x%lx Bytes: (%d)\n",
keyword,(ulong) memory, length);
(void) fputs(dbuff,_db_fp_);

View file

@ -123,7 +123,7 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
blength, records))
!= i)
{
DBUG_PRINT("error",("Record in wrong link: Link %d Record: %lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
DBUG_PRINT("error",("Record in wrong link: Link %d Record: 0x%lx Record-link %d", i,hash_info->ptr_to_rec,rec_link));
error=1;
}
else
@ -180,7 +180,7 @@ static int check_one_rb_key(HP_INFO *info, uint keynr, ulong records,
key_length, SEARCH_FIND | SEARCH_SAME, &not_used))
{
error= 1;
DBUG_PRINT("error",("Record in wrong link: key: %d Record: %lx\n",
DBUG_PRINT("error",("Record in wrong link: key: %d Record: 0x%lx\n",
keynr, recpos));
}
else

View file

@ -77,14 +77,31 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
case HA_KEYTYPE_INT8:
keyinfo->seg[j].flag|= HA_SWAP_KEY;
break;
case HA_KEYTYPE_VARBINARY:
case HA_KEYTYPE_VARBINARY1:
/* Case-insensitiveness is handled in coll->hash_sort */
keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT;
keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
/* fall_through */
case HA_KEYTYPE_VARTEXT:
case HA_KEYTYPE_VARTEXT1:
if (!my_binary_compare(keyinfo->seg[j].charset))
keyinfo->flag|= HA_END_SPACE_KEY;
keyinfo->flag|= HA_VAR_LENGTH_KEY;
/* Save number of bytes used to store length */
keyinfo->seg[j].bit_start= 1;
break;
case HA_KEYTYPE_VARBINARY2:
/* Case-insensitiveness is handled in coll->hash_sort */
/* fall_through */
case HA_KEYTYPE_VARTEXT2:
if (!my_binary_compare(keyinfo->seg[j].charset))
keyinfo->flag|= HA_END_SPACE_KEY;
keyinfo->flag|= HA_VAR_LENGTH_KEY;
/* Save number of bytes used to store length */
keyinfo->seg[j].bit_start= 2;
/*
Make future comparison simpler by only having to check for
one type
*/
keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT1;
break;
default:
break;

View file

@ -24,7 +24,7 @@ int heap_delete(HP_INFO *info, const byte *record)
HP_SHARE *share=info->s;
HP_KEYDEF *keydef, *end, *p_lastinx;
DBUG_ENTER("heap_delete");
DBUG_PRINT("enter",("info: %lx record: %lx",info,record));
DBUG_PRINT("enter",("info: %lx record: 0x%lx",info,record));
test_active(info);
@ -139,7 +139,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
/* Save for heap_rnext/heap_rprev */
info->current_hash_ptr=last_ptr;
info->current_ptr = last_ptr ? last_ptr->ptr_to_rec : 0;
DBUG_PRINT("info",("Corrected current_ptr to point at: %lx",
DBUG_PRINT("info",("Corrected current_ptr to point at: 0x%lx",
info->current_ptr));
}
empty=pos;

View file

@ -271,18 +271,21 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
}
cs->coll->hash_sort(cs, pos, length, &nr, &nr2);
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
{
CHARSET_INFO *cs= seg->charset;
uint pack_length= 2; /* Key packing is constant */
uint length= uint2korr(pos);
if (cs->mbmaxlen > 1)
{
uint char_length;
char_length= my_charpos(cs, pos +2, pos +2 + length,
char_length= my_charpos(cs, pos +pack_length,
pos +pack_length + length,
seg->length/cs->mbmaxlen);
set_if_smaller(length, char_length);
}
cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
cs->coll->hash_sort(cs, pos+pack_length, length, &nr, &nr2);
key+= pack_length;
}
else
{
@ -293,6 +296,7 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
}
}
}
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
return((ulong) nr);
}
@ -300,7 +304,6 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
/*register*/
ulong nr=1, nr2=4;
HA_KEYSEG *seg,*endseg;
@ -327,18 +330,20 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
{
CHARSET_INFO *cs= seg->charset;
uint length= uint2korr(pos);
uint pack_length= seg->bit_start;
uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
if (cs->mbmaxlen > 1)
{
uint char_length;
char_length= my_charpos(cs, pos + 2 , pos + 2 + length,
char_length= my_charpos(cs, pos + pack_length,
pos + pack_length + length,
seg->length/cs->mbmaxlen);
set_if_smaller(length, char_length);
}
cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
cs->coll->hash_sort(cs, pos+pack_length, length, &nr, &nr2);
}
else
{
@ -349,7 +354,8 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
}
}
return((ulong) nr);
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
return(nr);
}
#else
@ -392,10 +398,13 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
{
uint pack_length= 2; /* Key packing is constant */
uint length= uint2korr(pos);
seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
seg->charset->hash_sort(seg->charset, pos+pack_length, length, &nr,
NULL);
key+= pack_length;
}
else
{
@ -406,7 +415,8 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
}
}
}
return((ulong) nr);
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
return(nr);
}
/* Calc hashvalue for a key in a record */
@ -418,7 +428,7 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
{
uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
uchar *pos=(uchar*) rec+seg->start;
if (seg->null_bit)
{
if (rec[seg->null_pos] & seg->null_bit)
@ -431,13 +441,16 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
{
uint length= uint2korr(pos);
seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
uint pack_length= seg->bit_start;
uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
seg->charset->hash_sort(seg->charset, pos+pack_length,
length, &nr, NULL);
}
else
{
uchar *end= pos+seg->length;
for ( ; pos < end ; pos++)
{
nr *=16777619;
@ -445,7 +458,8 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
}
}
return((ulong) nr);
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
return(nr);
}
#endif
@ -510,13 +524,25 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2,
pos2,char_length2, 0))
return 1;
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
{
uchar *pos1= (uchar*)rec1 + seg->start;
uchar *pos2= (uchar*)rec2 + seg->start;
uint char_length1= uint2korr(pos1);
uint char_length2= uint2korr(pos2);
uchar *pos1= (uchar*) rec1 + seg->start;
uchar *pos2= (uchar*) rec2 + seg->start;
uint char_length1, char_length2;
uint pack_length= seg->bit_start;
CHARSET_INFO *cs= seg->charset;
if (pack_length == 1)
{
char_length1= (uint) *(uchar*) pos1++;
char_length2= (uint) *(uchar*) pos2++;
}
else
{
char_length1= uint2korr(pos1);
char_length2= uint2korr(pos2);
pos1+= 2;
pos2+= 2;
}
if (cs->mbmaxlen > 1)
{
uint char_length= seg->length / cs->mbmaxlen;
@ -527,8 +553,8 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2,
}
if (cs->coll->strnncollsp(seg->charset,
pos1+2, char_length1,
pos2+2, char_length2,
pos1, char_length1,
pos2, char_length2,
seg->flag & HA_END_SPACE_ARE_EQUAL ?
0 : diff_if_only_endspace_difference))
return 1;
@ -585,28 +611,31 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
(uchar*) key, char_length_key, 0))
return 1;
}
else if (seg->type == HA_KEYTYPE_VARTEXT)
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
{
uchar *pos= (uchar*) rec + seg->start;
CHARSET_INFO *cs= seg->charset;
uint char_length_rec= uint2korr(pos);
uint pack_length= seg->bit_start;
uint char_length_rec= (pack_length == 1 ? (uint) *(uchar*) pos :
uint2korr(pos));
/* Key segments are always packed with 2 bytes */
uint char_length_key= uint2korr(key);
pos+= pack_length;
key+= 2; /* skip key pack length */
if (cs->mbmaxlen > 1)
{
uint char_length= seg->length / cs->mbmaxlen;
char_length_key= my_charpos(cs, key+2, key +2 + char_length_key,
char_length_key= my_charpos(cs, key, key + char_length_key,
char_length);
set_if_smaller(char_length_key, seg->length);
char_length_rec= my_charpos(cs, pos +2 , pos + 2 + char_length_rec,
char_length_rec= my_charpos(cs, pos, pos + char_length_rec,
char_length);
set_if_smaller(char_length_rec, seg->length);
}
if (cs->coll->strnncollsp(seg->charset,
(uchar*) pos+2, char_length_rec,
(uchar*) key+2, char_length_key, 0))
(uchar*) pos, char_length_rec,
(uchar*) key, char_length_key, 0))
return 1;
}
else
@ -638,6 +667,8 @@ void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
char_length / cs->mbmaxlen);
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
}
if (seg->type == HA_KEYTYPE_VARTEXT1)
char_length+= seg->bit_start; /* Copy also length */
memcpy(key,rec+seg->start,(size_t) char_length);
key+= char_length;
}
@ -707,11 +738,13 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
{
uchar *pos= (uchar*) rec + seg->start;
uint length= seg->length;
uint tmp_length= uint2korr(pos);
uint pack_length= seg->bit_start;
uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
uint2korr(pos));
CHARSET_INFO *cs= seg->charset;
char_length= length/cs->mbmaxlen;
pos+=2; /* Skip VARCHAR length */
pos+= pack_length; /* Skip VARCHAR length */
set_if_smaller(length,tmp_length);
FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);

View file

@ -63,7 +63,7 @@ HP_INFO *heap_open(const char *name, int mode)
#ifndef DBUG_OFF
info->opt_flag= READ_CHECK_USED; /* Check when changing */
#endif
DBUG_PRINT("exit",("heap: %lx reclength: %d records_in_block: %d",
DBUG_PRINT("exit",("heap: 0x%lx reclength: %d records_in_block: %d",
info,share->reclength,share->block.records_in_block));
DBUG_RETURN(info);
}
@ -82,7 +82,7 @@ HP_SHARE *hp_find_named_heap(const char *name)
info= (HP_SHARE*) pos->data;
if (!strcmp(name, info->name))
{
DBUG_PRINT("exit", ("Old heap_database: %lx",info));
DBUG_PRINT("exit", ("Old heap_database: 0x%lx",info));
DBUG_RETURN(info);
}
}

View file

@ -23,7 +23,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
HP_SHARE *share= info->s;
HP_KEYDEF *keyinfo= share->keydef + inx;
DBUG_ENTER("heap_rkey");
DBUG_PRINT("enter",("base: %lx inx: %d",info,inx));
DBUG_PRINT("enter",("base: 0x%lx inx: %d",info,inx));
if ((uint) inx >= share->keys)
{

View file

@ -29,7 +29,7 @@ int heap_rrnd(register HP_INFO *info, byte *record, byte *pos)
{
HP_SHARE *share=info->s;
DBUG_ENTER("heap_rrnd");
DBUG_PRINT("enter",("info: %lx pos: %lx",info,pos));
DBUG_PRINT("enter",("info: 0x%lx pos: %lx",info,pos));
info->lastinx= -1;
if (!(info->current_ptr= pos))
@ -44,7 +44,7 @@ int heap_rrnd(register HP_INFO *info, byte *record, byte *pos)
}
info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
memcpy(record,info->current_ptr,(size_t) share->reclength);
DBUG_PRINT("exit",("found record at %lx",info->current_ptr));
DBUG_PRINT("exit",("found record at 0x%lx",info->current_ptr));
info->current_hash_ptr=0; /* Can't use rnext */
DBUG_RETURN(0);
} /* heap_rrnd */
@ -64,7 +64,7 @@ int heap_rrnd_old(register HP_INFO *info, byte *record, ulong pos)
{
HP_SHARE *share=info->s;
DBUG_ENTER("heap_rrnd");
DBUG_PRINT("enter",("info: %lx pos: %ld",info,pos));
DBUG_PRINT("enter",("info: 0x%lx pos: %ld",info,pos));
info->lastinx= -1;
if (pos == (ulong) -1)
@ -98,7 +98,7 @@ end:
}
info->update=HA_STATE_PREV_FOUND | HA_STATE_NEXT_FOUND | HA_STATE_AKTIV;
memcpy(record,info->current_ptr,(size_t) share->reclength);
DBUG_PRINT("exit",("found record at %lx",info->current_ptr));
DBUG_PRINT("exit",("found record at 0x%lx",info->current_ptr));
info->current_hash_ptr=0; /* Can't use rnext */
DBUG_RETURN(0);
} /* heap_rrnd */

View file

@ -138,7 +138,7 @@ static byte *next_free_record_pos(HP_SHARE *info)
pos=info->del_link;
info->del_link= *((byte**) pos);
info->deleted--;
DBUG_PRINT("exit",("Used old position: %lx",pos));
DBUG_PRINT("exit",("Used old position: 0x%lx",pos));
DBUG_RETURN(pos);
}
if (!(block_pos=(info->records % info->block.records_in_block)))

View file

@ -181,9 +181,13 @@ enum ha_base_keytype {
HA_KEYTYPE_INT24=12,
HA_KEYTYPE_UINT24=13,
HA_KEYTYPE_INT8=14,
HA_KEYTYPE_VARTEXT=15, /* Key is sorted as letters */
HA_KEYTYPE_VARBINARY=16, /* Key is sorted as unsigned chars */
HA_KEYTYPE_BIT=17
/* Varchar (0-255 bytes) with length packed with 1 byte */
HA_KEYTYPE_VARTEXT1=15, /* Key is sorted as letters */
HA_KEYTYPE_VARBINARY1=16, /* Key is sorted as unsigned chars */
/* Varchar (0-65535 bytes) with length packed with 2 bytes */
HA_KEYTYPE_VARTEXT2=17, /* Key is sorted as letters */
HA_KEYTYPE_VARBINARY2=18, /* Key is sorted as unsigned chars */
HA_KEYTYPE_BIT=19
};
#define HA_MAX_KEYTYPE 31 /* Must be log2-1 */
@ -233,6 +237,7 @@ enum ha_base_keytype {
Only needed for internal temporary tables.
*/
#define HA_END_SPACE_ARE_EQUAL 512
#define HA_BIT_PART 1024
/* optionbits for database */
#define HA_OPTION_PACK_RECORD 1
@ -391,4 +396,6 @@ typedef ulong ha_rows;
#define MAX_FILE_SIZE LONGLONG_MAX
#endif
#define HA_VARCHAR_PACKLENGTH(field_length) ((field_length) < 256 ? 1 :2)
#endif /* _my_base_h */

View file

@ -40,8 +40,18 @@ most significant bytes and bits are written below less significant.
(1) byte offset (2) bit usage within byte
downward from
origin -> 1 8 bits pointer to next record (relative)
2 8 bits pointer to next record (relative)
origin -> 1 8 bits relative offset of next record
2 8 bits relative offset of next record
the relative offset is an unsigned 16-bit
integer:
(offset_of_next_record
- offset_of_this_record) mod 64Ki,
where mod is the modulo as a non-negative
number;
we can calculate the the offset of the next
record with the formula:
relative_offset + offset_of_this_record
mod UNIV_PAGE_SIZE
3 3 bits status:
000=conventional record
001=node pointer record (inside B-tree)
@ -252,26 +262,37 @@ UNIV_INLINE
ulint
rec_get_next_offs(
/*==============*/
/* out: the page offset of the next chained record */
/* out: the page offset of the next chained record, or
0 if none */
rec_t* rec, /* in: physical record */
ibool comp) /* in: TRUE=compact page format */
{
ulint field_value;
ut_ad(REC_NEXT_MASK == 0xFFFFUL);
ut_ad(REC_NEXT_SHIFT == 0);
field_value = mach_read_from_2(rec - REC_NEXT);
if (comp) {
lint ret = (signed short) rec_get_bit_field_2(rec, REC_NEXT,
REC_NEXT_MASK, REC_NEXT_SHIFT);
#if UNIV_PAGE_SIZE <= 32768
/* with 64 KiB page size, the pointer will "wrap around",
and the following assertions are invalid */
ut_ad(ret + ut_align_offset(rec, UNIV_PAGE_SIZE) <
UNIV_PAGE_SIZE);
/* Note that for 64 KiB pages, field_value can 'wrap around'
and the debug assertion is not valid */
ut_ad((int16_t)field_value
+ ut_align_offset(rec, UNIV_PAGE_SIZE)
< UNIV_PAGE_SIZE);
#endif
return(ret ? ut_align_offset(rec + ret, UNIV_PAGE_SIZE) : 0);
}
else {
ulint ret = rec_get_bit_field_2(rec, REC_NEXT,
REC_NEXT_MASK, REC_NEXT_SHIFT);
ut_ad(ret < UNIV_PAGE_SIZE);
return(ret);
if (field_value == 0) {
return(0);
}
return(ut_align_offset(rec + field_value, UNIV_PAGE_SIZE));
} else {
ut_ad(field_value < UNIV_PAGE_SIZE);
return(field_value);
}
}
@ -284,21 +305,31 @@ rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
ibool comp, /* in: TRUE=compact page format */
ulint next) /* in: offset of the next record */
ulint next) /* in: offset of the next record, or 0 if none */
{
ut_ad(rec);
ut_ad(UNIV_PAGE_SIZE > next);
ut_ad(REC_NEXT_MASK == 0xFFFFUL);
ut_ad(REC_NEXT_SHIFT == 0);
if (comp) {
rec_set_bit_field_2(rec, next
? (next - ut_align_offset(rec, UNIV_PAGE_SIZE))
#ifdef UNIV_DEBUG /* avoid an assertion failure */
& (REC_NEXT_MASK >> REC_NEXT_SHIFT)
#endif
: 0, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT);
ulint field_value;
if (next) {
/* The following two statements calculate
next - offset_of_rec mod 64Ki, where mod is the modulo
as a non-negative number */
field_value = (ulint)((lint)next
- (lint)ut_align_offset(rec, UNIV_PAGE_SIZE));
field_value &= REC_NEXT_MASK;
} else {
field_value = 0;
}
mach_write_to_2(rec - REC_NEXT, field_value);
} else {
rec_set_bit_field_2(rec, next,
REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT);
mach_write_to_2(rec - REC_NEXT, next);
}
}

View file

@ -105,11 +105,19 @@ trx_rollback(
Rollback or clean up transactions which have no user session. If the
transaction already was committed, then we clean up a possible insert
undo log. If the transaction was not yet committed, then we roll it back.
Note: this is done in a background thread */
Note: this is done in a background thread. */
void *
trx_rollback_or_clean_all_without_sess(void *);
/*============================================*/
#ifndef __WIN__
void*
#else
ulint
#endif
trx_rollback_or_clean_all_without_sess(
/*===================================*/
/* out: a dummy parameter */
void* arg __attribute__((unused)));
/* in: a dummy parameter required by
os_thread_create */
/********************************************************************
Finishes a transaction rollback. */

View file

@ -2937,7 +2937,6 @@ recv_recovery_from_checkpoint_finish(void)
#ifndef UNIV_LOG_DEBUG
recv_sys_free();
#endif
if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
os_thread_create(trx_rollback_or_clean_all_without_sess,
(void *)&i, &recovery_thread_id);

View file

@ -565,7 +565,7 @@ os_mem_alloc_large(
if (ptr) {
if (set_to_zero) {
#ifdef UNIV_SET_MEM_TO_ZERO
memset(ret, '\0', size);
memset(ptr, '\0', size);
#endif
}

View file

@ -1403,15 +1403,13 @@ NetWare. */
fsp_header_inc_size(0, sum_of_new_sizes, &mtr);
mtr_commit(&mtr);
}
if (recv_needed_recovery) {
ut_print_timestamp(stderr);
fprintf(stderr,
" InnoDB: Flushing modified pages from the buffer pool...\n");
}
/* Immediately write the log record about increased tablespace
size to disk, so that it is durable even if mysqld would crash
quickly */
log_make_checkpoint_at(ut_dulint_max, TRUE);
log_buffer_flush_to_disk();
}
#ifdef UNIV_LOG_ARCHIVE
/* Archiving is always off under MySQL */

View file

@ -30,9 +30,13 @@ Created 3/26/1996 Heikki Tuuri
/* This many pages must be undone before a truncate is tried within rollback */
#define TRX_ROLL_TRUNC_THRESHOLD 1
/* In crash recovery, the current trx to be rolled back */
trx_t* trx_roll_crash_recv_trx = NULL;
/* In crash recovery we set this to the undo n:o of the current trx to be
rolled back. Then we can print how many % the rollback has progressed. */
ib_longlong trx_roll_max_undo_no;
/* Auxiliary variable which tells the previous progress % we printed */
ulint trx_roll_progress_printed_pct;
@ -332,11 +336,19 @@ trx_savept_take(
Rollback or clean up transactions which have no user session. If the
transaction already was committed, then we clean up a possible insert
undo log. If the transaction was not yet committed, then we roll it back.
Note: this is done in a background thread */
Note: this is done in a background thread. */
void *
trx_rollback_or_clean_all_without_sess(void *i)
/*========================================*/
#ifndef __WIN__
void*
#else
ulint
#endif
trx_rollback_or_clean_all_without_sess(
/*===================================*/
/* out: a dummy parameter */
void* arg __attribute__((unused)))
/* in: a dummy parameter required by
os_thread_create */
{
mem_heap_t* heap;
que_fork_t* fork;
@ -361,9 +373,9 @@ trx_rollback_or_clean_all_without_sess(void *i)
if (UT_LIST_GET_FIRST(trx_sys->trx_list)) {
fprintf(stderr,
"InnoDB: Starting rollback of uncommitted transactions\n");
"InnoDB: Starting in background the rollback of uncommitted transactions\n");
} else {
os_thread_exit(i);
goto leave_function;
}
loop:
heap = mem_heap_create(512);
@ -373,7 +385,6 @@ loop:
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
while (trx) {
if ((trx->sess || (trx->conc_state == TRX_NOT_STARTED))) {
trx = UT_LIST_GET_NEXT(trx_list, trx);
} else if (trx->conc_state == TRX_PREPARED) {
@ -386,17 +397,17 @@ loop:
mutex_exit(&kernel_mutex);
if (trx == NULL) {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Rollback of uncommitted transactions completed\n");
" InnoDB: Rollback of uncommitted transactions completed\n");
mem_heap_free(heap);
os_thread_exit(i);
goto leave_function;
}
trx->sess = trx_dummy_sess;
if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n",
(ulong) ut_dulint_get_high(trx->id),
@ -425,21 +436,28 @@ loop:
ut_a(thr == que_fork_start_command(fork));
trx_roll_crash_recv_trx = trx;
trx_roll_max_undo_no = ut_conv_dulint_to_longlong(trx->undo_no);
trx_roll_progress_printed_pct = 0;
rows_to_undo = trx_roll_max_undo_no;
if (rows_to_undo > 1000000000) {
rows_to_undo = rows_to_undo / 1000000;
unit = "M";
}
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo",
" InnoDB: Rolling back trx with id %lu %lu, %lu%s rows to undo\n",
(ulong) ut_dulint_get_high(trx->id),
(ulong) ut_dulint_get_low(trx->id),
(ulong) rows_to_undo, unit);
mutex_exit(&kernel_mutex);
trx->mysql_thread_id = os_thread_get_curr_id();
trx->mysql_process_no = os_proc_get_number();
if (trx->dict_operation) {
row_mysql_lock_data_dictionary(trx);
}
@ -454,7 +472,7 @@ loop:
fprintf(stderr,
"InnoDB: Waiting for rollback of trx id %lu to end\n",
(ulong) ut_dulint_get_low(trx->id));
(ulong) ut_dulint_get_low(trx->id));
os_thread_sleep(100000);
mutex_enter(&kernel_mutex);
@ -493,9 +511,23 @@ loop:
(ulong) ut_dulint_get_low(trx->id));
mem_heap_free(heap);
trx_roll_crash_recv_trx = NULL;
goto loop;
os_thread_exit(i); /* not reached */
leave_function:
/* We count the number of threads in os_thread_exit(). A created
thread should always use that to exit and not use return() to exit. */
os_thread_exit(NULL);
/* The following is dummy code to keep the compiler happy: */
#ifndef __WIN__
return(NULL);
#else
return(0);
#endif
}
/***********************************************************************
@ -856,16 +888,17 @@ try_again:
ut_ad(ut_dulint_cmp(ut_dulint_add(undo_no, 1), trx->undo_no) == 0);
/* We print rollback progress info if we are in a crash recovery
and the transaction has at least 1000 row operations to undo */
and the transaction has at least 1000 row operations to undo. */
if (srv_is_being_started && trx_roll_max_undo_no > 1000) {
progress_pct = 100 - (ulint)
if (trx == trx_roll_crash_recv_trx && trx_roll_max_undo_no > 1000) {
progress_pct = 100 - (ulint)
((ut_conv_dulint_to_longlong(undo_no) * 100)
/ trx_roll_max_undo_no);
if (progress_pct != trx_roll_progress_printed_pct) {
if (trx_roll_progress_printed_pct == 0) {
fprintf(stderr,
"\nInnoDB: Progress in percents: %lu", (ulong) progress_pct);
"\nInnoDB: Progress in percents: %lu\n", (ulong) progress_pct);
} else {
fprintf(stderr,
" %lu", (ulong) progress_pct);

View file

@ -25,9 +25,9 @@ char ft_boolean_syntax[]="+ -><()~*:\"\"&|";
const HA_KEYSEG ft_keysegs[FT_SEGS]={
{
HA_KEYTYPE_VARTEXT, /* type */
HA_KEYTYPE_VARTEXT2, /* type */
63, /* language (will be overwritten) */
0, 0, 0, /* null_bit, bit_start, bit_end */
0, 2, 0, /* null_bit, bit_start, bit_end */
HA_VAR_LENGTH_PART | HA_PACK_KEY, /* flag */
HA_FT_MAXBYTELEN, /* length */
HA_FT_WLEN, /* start */

View file

@ -79,24 +79,24 @@ static int run_test(const char *filename)
recinfo[0].length= (extra_field == FIELD_BLOB ? 4 + mi_portable_sizeof_char_ptr :
extra_length);
if (extra_field == FIELD_VARCHAR)
recinfo[0].length+=2;
recinfo[0].length+= HA_VARCHAR_PACKLENGTH(extra_length);
recinfo[1].type=key_field;
recinfo[1].length= (key_field == FIELD_BLOB ? 4+mi_portable_sizeof_char_ptr :
key_length);
if (key_field == FIELD_VARCHAR)
recinfo[1].length+=2;
recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
keyinfo[0].keysegs=1;
keyinfo[0].seg[0].type= key_type;
keyinfo[0].seg[0].flag= (key_field == FIELD_BLOB)?HA_BLOB_PART:
(key_field == FIELD_VARCHAR)?HA_VAR_LENGTH_PART:0;
keyinfo[0].seg[0].flag= (key_field == FIELD_BLOB) ? HA_BLOB_PART:
(key_field == FIELD_VARCHAR) ? HA_VAR_LENGTH_PART:0;
keyinfo[0].seg[0].start=recinfo[0].length;
keyinfo[0].seg[0].length=key_length;
keyinfo[0].seg[0].null_bit= 0;
keyinfo[0].seg[0].null_pos=0;
keyinfo[0].seg[0].language=MY_CHARSET_CURRENT;
keyinfo[0].seg[0].language= default_charset_info->number;
keyinfo[0].flag = (no_fulltext?HA_PACK_KEY:HA_FULLTEXT);
if (!silent)
@ -155,33 +155,42 @@ static int run_test(const char *filename)
if (!silent)
printf("- Reading rows with key\n");
for (i=0 ; i < NQUERIES ; i++)
{ FT_DOCLIST *result;
{
FT_DOCLIST *result;
result=ft_nlq_init_search(file,0,(char*) query[i],strlen(query[i]),1);
if(!result) {
if(!result)
{
printf("Query %d: `%s' failed with errno %3d\n",i,query[i],my_errno);
continue;
}
printf("Query %d: `%s'. Found: %d. Top five documents:\n",
i,query[i],result->ndocs);
for(j=0;j<5;j++) { double w; int err;
err=ft_nlq_read_next(result, read_record);
if(err==HA_ERR_END_OF_FILE) {
printf("No more matches!\n");
break;
} else if (err) {
printf("ft_read_next %d failed with errno %3d\n",j,my_errno);
break;
}
w=ft_nlq_get_relevance(result);
if(key_field == FIELD_VARCHAR) {
uint l;
char *p;
p=recinfo[0].length+read_record;
l=uint2korr(p);
printf("%10.7f: %.*s\n",w,(int) l,p+2);
} else
printf("%10.7f: %.*s\n",w,recinfo[1].length,
recinfo[0].length+read_record);
i,query[i],result->ndocs);
for (j=0;j<5;j++)
{
double w; int err;
err= ft_nlq_read_next(result, read_record);
if (err==HA_ERR_END_OF_FILE)
{
printf("No more matches!\n");
break;
}
else if (err)
{
printf("ft_read_next %d failed with errno %3d\n",j,my_errno);
break;
}
w=ft_nlq_get_relevance(result);
if (key_field == FIELD_VARCHAR)
{
uint l;
char *p;
p=recinfo[0].length+read_record;
l=uint2korr(p);
printf("%10.7f: %.*s\n",w,(int) l,p+2);
}
else
printf("%10.7f: %.*s\n",w,recinfo[1].length,
recinfo[0].length+read_record);
}
ft_nlq_close_search(result);
}
@ -215,9 +224,14 @@ void create_record(char *pos, int n)
else if (recinfo[0].type == FIELD_VARCHAR)
{
uint tmp;
strnmov(pos+2,data[n].f0,keyinfo[0].seg[0].length);
tmp=strlen(pos+2);
int2store(pos,tmp);
/* -1 is here because pack_length is stored in seg->length */
uint pack_length= HA_VARCHAR_PACKLENGTH(keyinfo[0].seg[0].length-1);
strnmov(pos+pack_length,data[n].f0,keyinfo[0].seg[0].length);
tmp=strlen(pos+pack_length);
if (pack_length == 1)
*pos= (char) tmp;
else
int2store(pos,tmp);
pos+=recinfo[0].length;
}
else
@ -239,9 +253,14 @@ void create_record(char *pos, int n)
else if (recinfo[1].type == FIELD_VARCHAR)
{
uint tmp;
strnmov(pos+2,data[n].f2,keyinfo[0].seg[0].length);
tmp=strlen(pos+2);
int2store(pos,tmp);
/* -1 is here because pack_length is stored in seg->length */
uint pack_length= HA_VARCHAR_PACKLENGTH(keyinfo[0].seg[0].length-1);
strnmov(pos+pack_length,data[n].f2,keyinfo[0].seg[0].length);
tmp=strlen(pos+1);
if (pack_length == 1)
*pos= (char) tmp;
else
int2store(pos,tmp);
pos+=recinfo[1].length;
}
else

View file

@ -58,29 +58,27 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi)
DBUG_ENTER("_mi_ft_segiterator");
if (!ftsi->num)
{
DBUG_RETURN(0);
}
else
ftsi->num--;
ftsi->num--;
if (!ftsi->seg)
{
DBUG_RETURN(1);
}
else
ftsi->seg--;
ftsi->seg--;
if (ftsi->seg->null_bit &&
(ftsi->rec[ftsi->seg->null_pos] & ftsi->seg->null_bit))
{
ftsi->pos=0;
DBUG_RETURN(1);
ftsi->pos=0;
DBUG_RETURN(1);
}
ftsi->pos= ftsi->rec+ftsi->seg->start;
if (ftsi->seg->flag & HA_VAR_LENGTH_PART)
{
ftsi->len=uint2korr(ftsi->pos);
ftsi->pos+=2; /* Skip VARCHAR length */
uint pack_length= (ftsi->seg->bit_start);
ftsi->len= (pack_length == 1 ? (uint) *(uchar*) ftsi->pos :
uint2korr(ftsi->pos));
ftsi->pos+= pack_length; /* Skip VARCHAR length */
DBUG_RETURN(1);
}
if (ftsi->seg->flag & HA_BLOB_PART)
@ -296,9 +294,11 @@ uint _ft_make_key(MI_INFO *info, uint keynr, byte *keybuf, FT_WORD *wptr,
DBUG_RETURN(_mi_make_key(info,keynr,(uchar*) keybuf,buf,filepos));
}
/*
convert key value to ft2
*/
uint _mi_ft_convert_to_ft2(MI_INFO *info, uint keynr, uchar *key)
{
my_off_t root;
@ -316,9 +316,12 @@ uint _mi_ft_convert_to_ft2(MI_INFO *info, uint keynr, uchar *key)
get_key_full_length_rdonly(key_length, key);
while (_mi_ck_delete(info, keynr, key, key_length) == 0)
/* nothing to do here.
_mi_ck_delete() will populate info->ft1_to_ft2 with deleted keys
*/;
{
/*
nothing to do here.
_mi_ck_delete() will populate info->ft1_to_ft2 with deleted keys
*/
}
/* creating pageful of keys */
mi_putint(info->buff,length+2,0);

View file

@ -280,7 +280,8 @@ int chk_size(MI_CHECK *param, register MI_INFO *info)
size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
if ((skr=(my_off_t) info->state->key_file_length) != size)
{
if (skr > size)
/* Don't give error if file generated by myisampack */
if (skr > size && info->s->state.key_map)
{
error=1;
mi_check_print_error(param,

View file

@ -40,8 +40,12 @@ ha_checksum mi_checksum(MI_INFO *info, const byte *buf)
}
case FIELD_VARCHAR:
{
length=uint2korr(buf);
pos=buf+2;
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length-1);
if (pack_length == 1)
length= (ulong) *(uchar*) buf;
else
length= uint2korr(buf);
pos= buf+pack_length;
break;
}
default:

View file

@ -43,7 +43,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
myf create_flag;
uint fields,length,max_key_length,packed,pointer,real_length_diff,
key_length,info_length,key_segs,options,min_key_length_skip,
base_pos,varchar_count,long_varchar_count,varchar_length,
base_pos,long_varchar_count,varchar_length,
max_key_block_length,unique_key_parts,fulltext_keys,offset;
ulong reclength, real_reclength,min_pack_length;
char filename[FN_REFLEN],linkname[FN_REFLEN], *linkname_ptr;
@ -99,7 +99,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Start by checking fields and field-types used */
reclength=varchar_count=varchar_length=long_varchar_count=packed=
reclength=varchar_length=long_varchar_count=packed=
min_pack_length=pack_reclength=0;
for (rec=recinfo, fields=0 ;
fields != columns ;
@ -130,14 +130,15 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
}
else if (type == FIELD_VARCHAR)
{
varchar_count++;
varchar_length+=rec->length-2;
varchar_length+= rec->length-1; /* Used for min_pack_length */
packed--;
pack_reclength+=1;
if (test(rec->length > 257))
{ /* May be packed on 3 bytes */
pack_reclength++;
min_pack_length++;
/* We must test for 257 as length includes pack-length */
if (test(rec->length >= 257))
{
long_varchar_count++;
pack_reclength+=2;
pack_reclength+= 2; /* May be packed on 3 bytes */
}
}
else if (type != FIELD_SKIP_ZERO)
@ -169,12 +170,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* We can't use checksum with static length rows */
if (!(options & HA_OPTION_PACK_RECORD))
options&= ~HA_OPTION_CHECKSUM;
if (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD))
min_pack_length+=varchar_count; /* Min length to pack */
else
{
min_pack_length+=varchar_length+2*varchar_count;
}
if (!(options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
min_pack_length+= varchar_length;
if (flags & HA_CREATE_TMP_TABLE)
options|= HA_OPTION_TMP_TABLE;
if (flags & HA_CREATE_CHECKSUM || (options & HA_OPTION_CHECKSUM))
@ -220,7 +217,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
reclength=pointer+1; /* reserve place for delete link */
}
else
reclength+=long_varchar_count; /* We need space for this! */
reclength+= long_varchar_count; /* We need space for varchar! */
max_key_length=0; tot_length=0 ; key_segs=0;
fulltext_keys=0;
@ -261,7 +258,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
j++, keyseg++)
{
if (keyseg->type != HA_KEYTYPE_BINARY &&
keyseg->type != HA_KEYTYPE_VARBINARY)
keyseg->type != HA_KEYTYPE_VARBINARY1 &&
keyseg->type != HA_KEYTYPE_VARBINARY2)
{
my_errno=HA_WRONG_CREATE_OPTION;
goto err;
@ -285,11 +283,22 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
j++, keyseg++)
{
if (keyseg->type != HA_KEYTYPE_TEXT &&
keyseg->type != HA_KEYTYPE_VARTEXT)
keyseg->type != HA_KEYTYPE_VARTEXT1 &&
keyseg->type != HA_KEYTYPE_VARTEXT2)
{
my_errno=HA_WRONG_CREATE_OPTION;
goto err;
}
if (!(keyseg->flag & HA_BLOB_PART) &&
(keyseg->type == HA_KEYTYPE_VARTEXT1 ||
keyseg->type == HA_KEYTYPE_VARTEXT2))
{
/* Make a flag that this is a VARCHAR */
keyseg->flag|= HA_VAR_LENGTH_PART;
/* Store in bit_start number of bytes used to pack the length */
keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1)?
1 : 2);
}
}
fulltext_keys++;
@ -345,10 +354,19 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
case HA_KEYTYPE_INT8:
keyseg->flag|= HA_SWAP_KEY;
break;
case HA_KEYTYPE_VARTEXT:
case HA_KEYTYPE_VARBINARY:
case HA_KEYTYPE_VARTEXT1:
case HA_KEYTYPE_VARTEXT2:
case HA_KEYTYPE_VARBINARY1:
case HA_KEYTYPE_VARBINARY2:
if (!(keyseg->flag & HA_BLOB_PART))
{
/* Make a flag that this is a VARCHAR */
keyseg->flag|= HA_VAR_LENGTH_PART;
/* Store in bit_start number of bytes used to pack the length */
keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
keyseg->type == HA_KEYTYPE_VARBINARY1) ?
1 : 2);
}
break;
default:
break;
@ -368,6 +386,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
}
if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
DBUG_ASSERT(!test_all_bits(keyseg->flag,
(HA_VAR_LENGTH_PART | HA_BLOB_PART)));
keydef->flag|=HA_VAR_LENGTH_KEY;
length++; /* At least one length byte */
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
@ -646,11 +666,31 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Save unique definition */
for (i=0 ; i < share.state.header.uniques ; i++)
{
HA_KEYSEG *keyseg_end;
keyseg= uniquedefs[i].seg;
if (mi_uniquedef_write(file, &uniquedefs[i]))
goto err;
for (j=0 ; j < uniquedefs[i].keysegs ; j++)
for (keyseg= uniquedefs[i].seg, keyseg_end= keyseg+ uniquedefs[i].keysegs;
keyseg < keyseg_end;
keyseg++)
{
if (mi_keyseg_write(file, &uniquedefs[i].seg[j]))
switch (keyseg->type) {
case HA_KEYTYPE_VARTEXT1:
case HA_KEYTYPE_VARTEXT2:
case HA_KEYTYPE_VARBINARY1:
case HA_KEYTYPE_VARBINARY2:
if (!(keyseg->flag & HA_BLOB_PART))
{
keyseg->flag|= HA_VAR_LENGTH_PART;
keyseg->bit_start= ((keyseg->type == HA_KEYTYPE_VARTEXT1 ||
keyseg->type == HA_KEYTYPE_VARBINARY1) ?
1 : 2);
}
break;
default:
break;
}
if (mi_keyseg_write(file, keyseg))
goto err;
}
}

View file

@ -131,9 +131,21 @@ void _mi_print_key(FILE *stream, register HA_KEYSEG *keyseg,
key=end;
break;
}
case HA_KEYTYPE_BIT:
{
uint i;
fputs("0x",stream);
for (i=0 ; i < keyseg->length ; i++)
fprintf(stream, "%02x", (uint) *key++);
key= end;
break;
}
#endif
case HA_KEYTYPE_VARTEXT: /* VARCHAR and TEXT */
case HA_KEYTYPE_VARBINARY: /* VARBINARY and BLOB */
case HA_KEYTYPE_VARTEXT1: /* VARCHAR and TEXT */
case HA_KEYTYPE_VARTEXT2: /* VARCHAR and TEXT */
case HA_KEYTYPE_VARBINARY1: /* VARBINARY and BLOB */
case HA_KEYTYPE_VARBINARY2: /* VARBINARY and BLOB */
{
uint tmp_length;
get_key_length(tmp_length,key);

View file

@ -768,11 +768,21 @@ uint _mi_rec_pack(MI_INFO *info, register byte *to, register const byte *from)
}
else if (type == FIELD_VARCHAR)
{
uint tmp_length=uint2korr(from);
store_key_length_inc(to,tmp_length);
memcpy(to,from+2,tmp_length);
to+=tmp_length;
continue;
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
uint tmp_length;
if (pack_length == 1)
{
tmp_length= (uint) *(uchar*) from;
*to++= *from;
}
else
{
tmp_length= uint2korr(from);
store_key_length_inc(to,tmp_length);
}
memcpy(to, from+pack_length,tmp_length);
to+= tmp_length;
continue;
}
else
{
@ -878,9 +888,20 @@ my_bool _mi_rec_check(MI_INFO *info,const char *record, byte *rec_buff,
}
else if (type == FIELD_VARCHAR)
{
uint tmp_length=uint2korr(record);
to+=get_pack_length(tmp_length)+tmp_length;
continue;
uint pack_length= HA_VARCHAR_PACKLENGTH(rec->length -1);
uint tmp_length;
if (pack_length == 1)
{
tmp_length= (uint) *(uchar*) record;
to+= 1+ tmp_length;
continue;
}
else
{
tmp_length= uint2korr(record);
to+= get_pack_length(tmp_length)+tmp_length;
}
continue;
}
else
{
@ -894,9 +915,7 @@ my_bool _mi_rec_check(MI_INFO *info,const char *record, byte *rec_buff,
}
}
else
{
to+=length;
}
to+= length;
}
if (packed_length != (uint) (to - rec_buff) + test(info->s->calc_checksum) ||
(bit != 1 && (flag & ~(bit - 1))))
@ -947,13 +966,27 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
{
if (type == FIELD_VARCHAR)
{
get_key_length(length,from);
if (length > rec_length-2)
goto err;
int2store(to,length);
memcpy(to+2,from,length);
from+=length;
continue;
uint pack_length= HA_VARCHAR_PACKLENGTH(rec_length-1);
if (pack_length == 1)
{
length= (uint) *(uchar*) from;
if (length > rec_length-1)
goto err;
*to= *from++;
}
else
{
get_key_length(length, from);
if (length > rec_length-2)
goto err;
int2store(to,length);
}
if (from+length > from_end)
goto err;
memcpy(to+pack_length, from, length);
from+= length;
min_pack_length--;
continue;
}
if (flag & bit)
{
@ -1021,15 +1054,17 @@ ulong _mi_rec_unpack(register MI_INFO *info, register byte *to, byte *from,
if (min_pack_length > (uint) (from_end - from))
goto err;
min_pack_length-=rec_length;
memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
memcpy(to, (byte*) from, (size_t) rec_length);
from+=rec_length;
}
}
if (info->s->calc_checksum)
from++;
if (to == to_end && from == from_end && (bit == 1 || !(flag & ~(bit-1))))
DBUG_RETURN(found_length);
err:
my_errno=HA_ERR_RECORD_DELETED;
my_errno= HA_ERR_WRONG_IN_RECORD;
DBUG_PRINT("error",("to_end: %lx -> %lx from_end: %lx -> %lx",
to,to_end,from,from_end));
DBUG_DUMP("from",(byte*) info->rec_buff,info->s->base.min_pack_length);

View file

@ -34,10 +34,20 @@
static int _mi_put_key_in_record(MI_INFO *info,uint keynr,byte *record);
/*
** Make a intern key from a record
** Ret: Length of key
*/
/*
Make a intern key from a record
SYNOPSIS
_mi_make_key()
info MyiSAM handler
keynr key number
key Store created key here
record Record
filepos Position to record in the data file
RETURN
Length of key
*/
uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
const byte *record, my_off_t filepos)
@ -117,8 +127,10 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
}
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint tmp_length=uint2korr(pos);
pos+=2; /* Skip VARCHAR length */
uint pack_length= keyseg->bit_start;
uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
uint2korr(pos));
pos+= pack_length; /* Skip VARCHAR length */
set_if_smaller(length,tmp_length);
FIX_LENGTH(cs, pos, length, char_length);
store_key_length_inc(key,char_length);
@ -398,9 +410,12 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
goto err;
#endif
/* Store key length */
int2store(record+keyseg->start, length);
if (keyseg->bit_start == 1)
*(uchar*) (record+keyseg->start)= (uchar) length;
else
int2store(record+keyseg->start, length);
/* And key data */
memcpy(record+keyseg->start+2,(byte*) key, length);
memcpy(record+keyseg->start + keyseg->bit_start, (byte*) key, length);
key+= length;
}
else if (keyseg->flag & HA_BLOB_PART)

View file

@ -314,7 +314,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
{
disk_pos=mi_keyseg_read(disk_pos, pos);
if (pos->type == HA_KEYTYPE_TEXT || pos->type == HA_KEYTYPE_VARTEXT)
if (pos->type == HA_KEYTYPE_TEXT ||
pos->type == HA_KEYTYPE_VARTEXT1 ||
pos->type == HA_KEYTYPE_VARTEXT2)
{
if (!pos->language)
pos->charset=default_charset_info;
@ -389,7 +391,9 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
for (j=0 ; j < share->uniqueinfo[i].keysegs; j++,pos++)
{
disk_pos=mi_keyseg_read(disk_pos, pos);
if (pos->type == HA_KEYTYPE_TEXT || pos->type == HA_KEYTYPE_VARTEXT)
if (pos->type == HA_KEYTYPE_TEXT ||
pos->type == HA_KEYTYPE_VARTEXT1 ||
pos->type == HA_KEYTYPE_VARTEXT2)
{
if (!pos->language)
pos->charset=default_charset_info;

View file

@ -91,8 +91,10 @@ static void uf_zero(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
uchar *to,uchar *end);
static void uf_blob(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end);
static void uf_varchar(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end);
static void uf_varchar1(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end);
static void uf_varchar2(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end);
static void decode_bytes(MI_COLUMNDEF *rec,MI_BIT_BUFF *bit_buff,
uchar *to,uchar *end);
static uint decode_pos(MI_BIT_BUFF *bit_buff,MI_DECODE_TREE *decode_tree);
@ -522,14 +524,16 @@ static void (*get_unpack_function(MI_COLUMNDEF *rec))
case FIELD_BLOB:
return &uf_blob;
case FIELD_VARCHAR:
return &uf_varchar;
if (rec->length <= 256) /* 255 + 1 byte length */
return &uf_varchar1;
return &uf_varchar2;
case FIELD_LAST:
default:
return 0; /* This should never happend */
}
}
/* De different functions to unpack a field */
/* The different functions to unpack a field */
static void uf_zerofill_skip_zero(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end)
@ -773,7 +777,22 @@ static void uf_blob(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
}
}
static void uf_varchar(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
static void uf_varchar1(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end __attribute__((unused)))
{
if (get_bit(bit_buff))
to[0]= 0; /* Zero lengths */
else
{
ulong length=get_bits(bit_buff,rec->space_length_bits);
*to= (uchar) length;
decode_bytes(rec,bit_buff,to+1,to+1+length);
}
}
static void uf_varchar2(MI_COLUMNDEF *rec, MI_BIT_BUFF *bit_buff,
uchar *to, uchar *end __attribute__((unused)))
{
if (get_bit(bit_buff))

View file

@ -425,7 +425,8 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
if (len < cmplen)
{
if ((keyinfo->seg->type != HA_KEYTYPE_TEXT &&
keyinfo->seg->type != HA_KEYTYPE_VARTEXT))
keyinfo->seg->type != HA_KEYTYPE_VARTEXT1 &&
keyinfo->seg->type != HA_KEYTYPE_VARTEXT2))
my_flag= -1;
else
{
@ -1371,7 +1372,8 @@ _mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
sort_order=0;
if ((keyinfo->flag & HA_FULLTEXT) &&
((keyseg->type == HA_KEYTYPE_TEXT) ||
(keyseg->type == HA_KEYTYPE_VARTEXT)) &&
(keyseg->type == HA_KEYTYPE_VARTEXT1) ||
(keyseg->type == HA_KEYTYPE_VARTEXT2)) &&
!use_strnxfrm(keyseg->charset))
sort_order=keyseg->charset->sort_order;

View file

@ -75,11 +75,11 @@ static int run_test(const char *filename)
recinfo[1].length= (key_field == FIELD_BLOB ? 4+mi_portable_sizeof_char_ptr :
key_length);
if (key_field == FIELD_VARCHAR)
recinfo[1].length+=2;
recinfo[1].length+= HA_VARCHAR_PACKLENGTH(key_length);;
recinfo[2].type=extra_field;
recinfo[2].length= (extra_field == FIELD_BLOB ? 4 + mi_portable_sizeof_char_ptr : 24);
if (extra_field == FIELD_VARCHAR)
recinfo[2].length+=2;
recinfo[2].length+= HA_VARCHAR_PACKLENGTH(recinfo[2].length);
if (opt_unique)
{
recinfo[3].type=FIELD_CHECK;
@ -88,6 +88,9 @@ static int run_test(const char *filename)
rec_length=recinfo[0].length+recinfo[1].length+recinfo[2].length+
recinfo[3].length;
if (key_type == HA_KEYTYPE_VARTEXT1 &&
key_length > 255)
key_type= HA_KEYTYPE_VARTEXT2;
/* Define a key over the first column */
keyinfo[0].seg=keyseg;
@ -330,7 +333,8 @@ static void create_key_part(char *key,uint rownr)
{
sprintf(key,"%*d",keyinfo[0].seg[0].length,rownr);
}
else if (keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT)
else if (keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT1 ||
keyinfo[0].seg[0].type == HA_KEYTYPE_VARTEXT2)
{ /* Alpha record */
/* Create a key that may be easily packed */
bfill(key,keyinfo[0].seg[0].length,rownr < 10 ? 'A' : 'B');
@ -410,11 +414,14 @@ static void create_record(char *record,uint rownr)
}
else if (recinfo[1].type == FIELD_VARCHAR)
{
uint tmp;
create_key_part(pos+2,rownr);
tmp=strlen(pos+2);
int2store(pos,tmp);
pos+=recinfo[1].length;
uint tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
create_key_part(pos+pack_length,rownr);
tmp= strlen(pos+pack_length);
if (pack_length == 1)
*(uchar*) pos= (uchar) tmp;
else
int2store(pos,tmp);
pos+= recinfo[1].length;
}
else
{
@ -434,10 +441,13 @@ static void create_record(char *record,uint rownr)
}
else if (recinfo[2].type == FIELD_VARCHAR)
{
uint tmp;
sprintf(pos+2,"... row: %d", rownr);
tmp=strlen(pos+2);
int2store(pos,tmp);
uint tmp, pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
sprintf(pos+pack_length, "... row: %d", rownr);
tmp= strlen(pos+pack_length);
if (pack_length == 1)
*(uchar*) pos= (uchar) tmp;
else
int2store(pos,tmp);
}
else
{
@ -466,8 +476,9 @@ static void update_record(char *record)
}
else if (recinfo[1].type == FIELD_VARCHAR)
{
uint length=uint2korr(pos);
my_casedn(default_charset_info,pos+2,length);
uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
uint length= pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos);
my_casedn(default_charset_info,pos+pack_length,length);
pos+=recinfo[1].length;
}
else
@ -493,10 +504,14 @@ static void update_record(char *record)
else if (recinfo[2].type == FIELD_VARCHAR)
{
/* Second field is longer than 10 characters */
uint length=uint2korr(pos);
bfill(pos+2+length,recinfo[2].length-length-2,'.');
length=recinfo[2].length-2;
int2store(pos,length);
uint pack_length= HA_VARCHAR_PACKLENGTH(recinfo[1].length-1);
uint length= pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos);
bfill(pos+pack_length+length,recinfo[2].length-length-pack_length,'.');
length=recinfo[2].length-pack_length;
if (pack_length == 1)
*(uchar*) pos= (uchar) length;
else
int2store(pos,length);
}
else
{
@ -519,7 +534,7 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"insert_rows", 'i', "Undocumented", (gptr*) &insert_count,
(gptr*) &insert_count, 0, GET_UINT, REQUIRED_ARG, 1000, 0, 0, 0, 0, 0},
{"key_alpha", 'a', "Undocumented",
{"key_alpha", 'a', "Use a key of type HA_KEYTYPE_TEXT",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_binary_pack", 'B', "Undocumented",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@ -535,9 +550,9 @@ static struct my_option my_long_options[] =
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_space_pack", 'p', "Undocumented",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_varchar", 'w', "Undocumented",
{"key_varchar", 'w', "Test VARCHAR keys",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"null_fields", 'N', "Undocumented",
{"null_fields", 'N', "Define fields with NULL",
(gptr*) &null_fields, (gptr*) &null_fields, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{"row_fixed_size", 'S', "Undocumented",
@ -604,7 +619,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
key_field=FIELD_BLOB; /* blob key */
extra_field= FIELD_BLOB;
pack_seg|= HA_BLOB_PART;
key_type= HA_KEYTYPE_VARTEXT;
key_type= HA_KEYTYPE_VARTEXT1;
break;
case 'k':
if (key_length < 4 || key_length > MI_MAX_KEY_LENGTH)
@ -616,11 +631,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case 'w':
key_field=FIELD_VARCHAR; /* varchar keys */
extra_field= FIELD_VARCHAR;
key_type= HA_KEYTYPE_VARTEXT;
key_type= HA_KEYTYPE_VARTEXT1;
pack_seg|= HA_VAR_LENGTH_PART;
create_flag|= HA_PACK_RECORD;
break;
case 'K': /* Use key cacheing */
case 'K': /* Use key cacheing */
key_cacheing=1;
break;
case 'V':

View file

@ -67,6 +67,7 @@ int main(int argc,char **argv)
bzero((char*) keyinfo,sizeof(keyinfo));
bzero((char*) recinfo,sizeof(recinfo));
bzero((char*) keyseg,sizeof(keyseg));
keyinfo[0].seg= &keyseg[0][0];
keyinfo[0].seg[0].start=0;
keyinfo[0].seg[0].length=8;

View file

@ -1,3 +1,6 @@
myisamchk: MyISAM file test1
myisamchk: warning: Size of indexfile is: 1024 Should be: 2048
MyISAM-table 'test1' is usable but should be fixed
mi_test2 -s -L -K -R1 -m2000 ; Should give error 135
Error: 135 in write at record: 1105
got error: 135 when using MyISAM-database
@ -5,46 +8,46 @@ myisamchk: MyISAM file test2
myisamchk: warning: Datafile is almost full, 65532 of 65534 used
MyISAM-table 'test2' is usable but should be fixed
Commands Used count Errors Recover errors
open 17 0 0
write 850 0 0
update 85 0 0
delete 850 0 0
close 17 0 0
extra 102 0 0
Total 1921 0 0
open 1 0 0
write 50 0 0
update 5 0 0
delete 50 0 0
close 1 0 0
extra 6 0 0
Total 113 0 0
Commands Used count Errors Recover errors
open 18 0 0
write 900 0 0
update 90 0 0
delete 900 0 0
close 18 0 0
extra 108 0 0
Total 2034 0 0
open 2 0 0
write 100 0 0
update 10 0 0
delete 100 0 0
close 2 0 0
extra 12 0 0
Total 226 0 0
real 0m1.054s
user 0m0.410s
sys 0m0.640s
real 0m0.791s
user 0m0.137s
sys 0m0.117s
real 0m1.077s
user 0m0.550s
sys 0m0.530s
real 0m0.659s
user 0m0.252s
sys 0m0.102s
real 0m1.100s
user 0m0.420s
sys 0m0.680s
real 0m0.571s
user 0m0.188s
sys 0m0.098s
real 0m0.783s
user 0m0.590s
sys 0m0.200s
real 0m1.111s
user 0m0.236s
sys 0m0.037s
real 0m0.764s
user 0m0.560s
sys 0m0.210s
real 0m0.621s
user 0m0.242s
sys 0m0.022s
real 0m0.699s
user 0m0.570s
sys 0m0.130s
real 0m0.698s
user 0m0.248s
sys 0m0.021s
real 0m0.991s
user 0m0.630s
sys 0m0.350s
real 0m0.683s
user 0m0.265s
sys 0m0.079s

View file

@ -95,8 +95,10 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
pos= record+keyseg->start;
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint tmp_length=uint2korr(pos);
pos+=2; /* Skip VARCHAR length */
uint pack_length= keyseg->bit_start;
uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
uint2korr(pos));
pos+= pack_length; /* Skip VARCHAR length */
set_if_smaller(length,tmp_length);
}
else if (keyseg->flag & HA_BLOB_PART)
@ -107,7 +109,8 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
length=tmp_length; /* The whole blob */
}
end= pos+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
type == HA_KEYTYPE_VARTEXT2)
{
keyseg->charset->coll->hash_sort(keyseg->charset,
(const uchar*) pos, length, &seed1,
@ -157,12 +160,21 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
pos_b= b+keyseg->start;
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
a_length= uint2korr(pos_a);
b_length= uint2korr(pos_b);
pos_a+= 2; /* Skip VARCHAR length */
pos_b+= 2;
set_if_smaller(a_length, keyseg->length);
set_if_smaller(b_length, keyseg->length);
uint pack_length= keyseg->bit_start;
if (pack_length == 1)
{
a_length= (uint) *(uchar*) pos_a++;
b_length= (uint) *(uchar*) pos_b++;
}
else
{
a_length= uint2korr(pos_a);
b_length= uint2korr(pos_b);
pos_a+= 2; /* Skip VARCHAR length */
pos_b+= 2;
}
set_if_smaller(a_length, keyseg->length); /* Safety */
set_if_smaller(b_length, keyseg->length); /* safety */
}
else if (keyseg->flag & HA_BLOB_PART)
{
@ -182,7 +194,8 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
memcpy_fixed((byte*) &pos_a,pos_a+keyseg->bit_start,sizeof(char*));
memcpy_fixed((byte*) &pos_b,pos_b+keyseg->bit_start,sizeof(char*));
}
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
type == HA_KEYTYPE_VARTEXT2)
{
if (mi_compare_text(keyseg->charset, (uchar *) pos_a, a_length,
(uchar *) pos_b, b_length, 0, 1))

View file

@ -849,9 +849,11 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
}
else if (count->field_type == FIELD_VARCHAR)
{
length=uint2korr(start_pos);
pos=start_pos+2;
end_pos=start_pos+length;
uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
length= (pack_length == 1 ? (uint) *(uchar*) start_pos :
uint2korr(start_pos));
pos= start_pos+pack_length;
end_pos= pos+length;
set_if_bigger(count->max_length,length);
}
if (count->field_length <= 8 &&
@ -1833,17 +1835,19 @@ static int compress_isam_file(PACK_MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
}
case FIELD_VARCHAR:
{
ulong col_length= uint2korr(start_pos);
uint pack_length= HA_VARCHAR_PACKLENGTH(count->field_length-1);
ulong col_length= (pack_length == 1 ? (uint) *(uchar*) start_pos :
uint2korr(start_pos));
if (!col_length)
{
write_bits(1,1); /* Empty varchar */
}
else
{
byte *end=start_pos+2+col_length;
byte *end=start_pos+pack_length+col_length;
write_bits(0,1);
write_bits(col_length,count->length_bits);
for (start_pos+=2 ; start_pos < end ; start_pos++)
for (start_pos+=pack_length ; start_pos < end ; start_pos++)
write_bits(tree->code[(uchar) *start_pos],
(uint) tree->code_len[(uchar) *start_pos]);
}

View file

@ -92,6 +92,66 @@ select sql_big_result c,count(t) from t1 group by c limit 10;
select t,count(*) from t1 group by t limit 10;
select t,count(t) from t1 group by t limit 10;
select sql_big_result t,count(t) from t1 group by t limit 10;
#
# Test varchar > 255 bytes
#
alter table t1 modify v varchar(300), drop key v, drop key v_2, add key v (v);
show create table t1;
select count(*) from t1 where v='a';
select count(*) from t1 where v='a ';
select count(*) from t1 where v between 'a' and 'a ';
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
select count(*) from t1 where v like 'a%';
select count(*) from t1 where v like 'a %';
explain select count(*) from t1 where v='a ';
explain select count(*) from t1 where v like 'a%';
explain select count(*) from t1 where v between 'a' and 'a ';
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
explain select * from t1 where v='a';
# GROUP BY
select v,count(*) from t1 group by v limit 10;
select v,count(t) from t1 group by v limit 10;
select sql_big_result v,count(t) from t1 group by v limit 10;
#
# Test varchar > 255 bytes, key < 255
#
alter table t1 drop key v, add key v (v(30));
show create table t1;
select count(*) from t1 where v='a';
select count(*) from t1 where v='a ';
select count(*) from t1 where v between 'a' and 'a ';
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
select count(*) from t1 where v like 'a%';
select count(*) from t1 where v like 'a %';
explain select count(*) from t1 where v='a ';
explain select count(*) from t1 where v like 'a%';
explain select count(*) from t1 where v between 'a' and 'a ';
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
explain select * from t1 where v='a';
# GROUP BY
select v,count(*) from t1 group by v limit 10;
select v,count(t) from t1 group by v limit 10;
select sql_big_result v,count(t) from t1 group by v limit 10;
#
# Test varchar > 512 (special case for GROUP BY becasue of
# CONVERT_IF_BIGGER_TO_BLOB define)
#
alter table t1 modify v varchar(600), drop key v, add key v (v);
show create table t1;
select v,count(*) from t1 group by v limit 10;
select v,count(t) from t1 group by v limit 10;
select sql_big_result v,count(t) from t1 group by v limit 10;
drop table t1;
#

View file

@ -1578,6 +1578,217 @@ f 10
g 10
h 10
i 10
alter table t1 modify v varchar(300), drop key v, drop key v_2, add key v (v);
Warnings:
Warning 1071 Specified key was too long; max key length is 255 bytes
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(300) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `c` (`c`),
KEY `t` (`t`(10)),
KEY `v` (`v`(255))
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
select count(*) from t1 where v='a';
count(*)
10
select count(*) from t1 where v='a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
count(*)
10
select count(*) from t1 where v like 'a%';
count(*)
11
select count(*) from t1 where v like 'a %';
count(*)
9
explain select count(*) from t1 where v='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 258 const 10 Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 258 NULL 11 Using where
explain select count(*) from t1 where v between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 258 NULL 10 Using where
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 258 NULL 10 Using where
explain select * from t1 where v='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 258 const 10 Using where
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
alter table t1 drop key v, add key v (v(30));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(300) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `c` (`c`),
KEY `t` (`t`(10)),
KEY `v` (`v`(30))
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
select count(*) from t1 where v='a';
count(*)
10
select count(*) from t1 where v='a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
count(*)
10
select count(*) from t1 where v like 'a%';
count(*)
11
select count(*) from t1 where v like 'a %';
count(*)
9
explain select count(*) from t1 where v='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 33 const 10 Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 33 NULL 11 Using where
explain select count(*) from t1 where v between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 33 NULL 10 Using where
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 33 NULL 10 Using where
explain select * from t1 where v='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 33 const 10 Using where
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
alter table t1 modify v varchar(600), drop key v, add key v (v);
Warnings:
Warning 1071 Specified key was too long; max key length is 255 bytes
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(600) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `c` (`c`),
KEY `t` (`t`(10)),
KEY `v` (`v`(255))
) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
drop table t1;
create table t1 (a char(10), unique (a));
insert into t1 values ('a ');

View file

@ -471,7 +471,7 @@ character_sets CREATE TEMPORARY TABLE `character_sets` (
`DEFAULT_COLLATE_NAME` varchar(60) NOT NULL default '',
`DESCRIPTION` varchar(60) NOT NULL default '',
`MAXLEN` bigint(3) NOT NULL default '0'
) ENGINE=HEAP DEFAULT CHARSET=utf8 MAX_ROWS=2252
) ENGINE=HEAP DEFAULT CHARSET=utf8 MAX_ROWS=2267
set names latin2;
SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
Table Create Table
@ -480,7 +480,7 @@ character_sets CREATE TEMPORARY TABLE `character_sets` (
`DEFAULT_COLLATE_NAME` varchar(60) NOT NULL default '',
`DESCRIPTION` varchar(60) NOT NULL default '',
`MAXLEN` bigint(3) NOT NULL default '0'
) ENGINE=HEAP DEFAULT CHARSET=utf8 MAX_ROWS=2252
) ENGINE=HEAP DEFAULT CHARSET=utf8 MAX_ROWS=2267
set names latin1;
create table t1 select * from information_schema.CHARACTER_SETS
where CHARACTER_SET_NAME like "latin1";

View file

@ -1421,19 +1421,19 @@ insert t2 select * from t1;
insert t3 select * from t1;
checksum table t1, t2, t3, t4 quick;
Table Checksum
test.t1 272226711
test.t1 2948697075
test.t2 NULL
test.t3 NULL
test.t4 NULL
checksum table t1, t2, t3, t4;
Table Checksum
test.t1 272226711
test.t1 2948697075
test.t2 968604391
test.t3 968604391
test.t4 NULL
checksum table t1, t2, t3, t4 extended;
Table Checksum
test.t1 272226711
test.t1 3092701434
test.t2 968604391
test.t3 968604391
test.t4 NULL

View file

@ -513,18 +513,18 @@ insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
insert t2 select * from t1;
checksum table t1, t2, t3 quick;
Table Checksum
test.t1 272226711
test.t1 2948697075
test.t2 NULL
test.t3 NULL
checksum table t1, t2, t3;
Table Checksum
test.t1 272226711
test.t2 272226711
test.t1 2948697075
test.t2 3092701434
test.t3 NULL
checksum table t1, t2, t3 extended;
Table Checksum
test.t1 272226711
test.t2 272226711
test.t1 3092701434
test.t2 3092701434
test.t3 NULL
drop table t1,t2;
create table t1 (a int, key (a));
@ -849,6 +849,213 @@ f 10
g 10
h 10
i 10
alter table t1 modify v varchar(300), drop key v, drop key v_2, add key v (v);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(300) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `c` (`c`),
KEY `t` (`t`(10)),
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1 where v='a';
count(*)
10
select count(*) from t1 where v='a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
count(*)
10
select count(*) from t1 where v like 'a%';
count(*)
11
select count(*) from t1 where v like 'a %';
count(*)
9
explain select count(*) from t1 where v='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 303 const 7 Using where; Using index
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 303 NULL 8 Using where; Using index
explain select count(*) from t1 where v between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 303 NULL 7 Using where; Using index
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 303 NULL 7 Using where; Using index
explain select * from t1 where v='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 303 const 7 Using where
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
alter table t1 drop key v, add key v (v(30));
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(300) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `c` (`c`),
KEY `t` (`t`(10)),
KEY `v` (`v`(30))
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1 where v='a';
count(*)
10
select count(*) from t1 where v='a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ';
count(*)
10
select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
count(*)
10
select count(*) from t1 where v like 'a%';
count(*)
11
select count(*) from t1 where v like 'a %';
count(*)
9
explain select count(*) from t1 where v='a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 33 const 7 Using where
explain select count(*) from t1 where v like 'a%';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 33 NULL 8 Using where
explain select count(*) from t1 where v between 'a' and 'a ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 33 NULL 7 Using where
explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 33 NULL 7 Using where
explain select * from t1 where v='a';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 33 const 7 Using where
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
alter table t1 modify v varchar(600), drop key v, add key v (v);
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`v` varchar(600) default NULL,
`c` char(10) default NULL,
`t` text,
KEY `c` (`c`),
KEY `t` (`t`(10)),
KEY `v` (`v`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select v,count(*) from t1 group by v limit 10;
v count(*)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
select sql_big_result v,count(t) from t1 group by v limit 10;
v count(t)
a 1
a 10
b 10
c 10
d 10
e 10
f 10
g 10
h 10
i 10
drop table t1;
create table t1 (a char(10), unique (a));
insert into t1 values ('a ');

View file

@ -278,7 +278,7 @@ t2 MyISAM 9 Fixed 0 0 0 64424509439 1024 0 NULL # # # latin1_swedish_ci NULL
prepare stmt4 from ' show table status from test like ''t9%'' ';
execute stmt4;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t9 MyISAM 10 Dynamic 2 222 444 4294967295 2048 0 NULL # # # latin1_swedish_ci NULL
t9 MyISAM 10 Dynamic 2 220 440 4294967295 2048 0 NULL # # # latin1_swedish_ci NULL
prepare stmt4 from ' show status like ''Threads_running'' ';
execute stmt4;
Variable_name Value

View file

@ -314,57 +314,57 @@ insert into t2 values (1),(2);
insert into t3 values (1,1),(2,2);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 HEAP 9 Fixed 2 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 2 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 2 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t1 HEAP 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 2 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
insert into t1 values (3),(4);
insert into t2 values (3),(4);
insert into t3 values (3,3),(4,4);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 HEAP 9 Fixed 4 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 4 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 4 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t1 HEAP 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 4 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 HEAP 9 Fixed 5 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 5 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 5 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t1 HEAP 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 5 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1 where a=3;
delete from t2 where b=3;
delete from t3 where a=3;
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 HEAP 9 Fixed 4 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 4 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 4 9 # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
t1 HEAP 9 Fixed 4 # # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 4 # # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 4 # # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1;
delete from t2;
delete from t3;
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 HEAP 9 Fixed 0 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 0 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 0 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t1 HEAP 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 0 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 HEAP 9 Fixed 1 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 1 5 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 1 9 # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t1 HEAP 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 1 # # # # 0 NULL NULL NULL NULL latin1_swedish_ci NULL
delete from t1 where a=5;
delete from t2 where b=5;
delete from t3 where a=5;
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 HEAP 9 Fixed 0 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 0 5 # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 0 9 # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
t1 HEAP 9 Fixed 0 # # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t2 HEAP 9 Fixed 0 # # # # 5 NULL NULL NULL NULL latin1_swedish_ci NULL
t3 HEAP 9 Fixed 0 # # # # 9 NULL NULL NULL NULL latin1_swedish_ci NULL
drop table t1, t2, t3;
create database mysqltest;
show create database mysqltest;

View file

@ -321,6 +321,12 @@ select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2;
a+0 b+0 c+0
4 0 3
4 0 23
select a+0, b+0, c+0 from t1 where a = 4 and b = 1;
a+0 b+0 c+0
4 1 100
select a+0, b+0, c+0 from t1 where a = 4 and b = 1 and c=100;
a+0 b+0 c+0
4 1 100
select a+0, b+0, c+0 from t1 order by b desc;
a+0 b+0 c+0
2 1 4

View file

@ -68,3 +68,311 @@ create table t1 (v varbinary(20));
insert into t1 values('a');
insert into t1 values('a ');
alter table t1 add primary key (v);
drop table t1;
create table t1 (v varchar(254), index (v));
insert into t1 values ("This is a test ");
insert into t1 values ("Some sample data");
insert into t1 values (" garbage ");
insert into t1 values (" This is a test ");
insert into t1 values ("This is a test");
insert into t1 values ("Hello world");
insert into t1 values ("Foo bar");
insert into t1 values ("This is a test");
insert into t1 values ("MySQL varchar test");
insert into t1 values ("test MySQL varchar");
insert into t1 values ("This is a long string to have some random length data included");
insert into t1 values ("Short string");
insert into t1 values ("VSS");
insert into t1 values ("Some samples");
insert into t1 values ("Bar foo");
insert into t1 values ("Bye");
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using index
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where; Using index
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using index
alter table t1 change v v varchar(255);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort
alter table t1 change v v varchar(256);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort
alter table t1 change v v varchar(257);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort
alter table t1 change v v varchar(258);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort
alter table t1 change v v varchar(259);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort
alter table t1 change v v varchar(258);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort
alter table t1 change v v varchar(257);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort
alter table t1 change v v varchar(256);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort
alter table t1 change v v varchar(255);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using filesort
alter table t1 change v v varchar(254);
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 3 Using where; Using index
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 257 const 3 Using where; Using index
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 257 NULL 2 Using where; Using index
alter table t1 change v v varchar(253);
alter table t1 change v v varchar(254), drop key v;
alter table t1 change v v varchar(300), add key (v(10));
select * from t1 where v like 'This is a test' order by v;
v
This is a test
This is a test
select * from t1 where v='This is a test' order by v;
v
This is a test
This is a test
This is a test
select * from t1 where v like 'S%' order by v;
v
Short string
Some sample data
Some samples
explain select * from t1 where v like 'This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL 4 Using where; Using filesort
explain select * from t1 where v='This is a test' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref v v 13 const 4 Using where
explain select * from t1 where v like 'S%' order by v;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range v v 13 NULL 2 Using where; Using filesort
drop table t1;

View file

@ -824,7 +824,7 @@ select a from t1;
drop table t1;
#
# bug#2686 - index_merge select on BerkeleyDB table with varchar PK causes mysqld to crash
# bug#2686 - index_merge select on BerkeleyDB table with varchar PK crashes
#
create table t1(
@ -842,7 +842,8 @@ select substring(pk1, 1, 4), substring(pk1, 4001),
drop table t1;
#
# bug#2688 - Wrong index_merge query results for BDB table with variable length primary key
# bug#2688 - Wrong index_merge query results for BDB table with
# variable length primary key
#
create table t1 (

View file

@ -236,37 +236,37 @@ CREATE TABLE t3 (
insert into t1 values (1),(2);
insert into t2 values (1),(2);
insert into t3 values (1,1),(2,2);
--replace_column 7 # 8 # 9 #
--replace_column 6 # 7 # 8 # 9 #
show table status;
insert into t1 values (3),(4);
insert into t2 values (3),(4);
insert into t3 values (3,3),(4,4);
--replace_column 7 # 8 # 9 #
--replace_column 6 # 7 # 8 # 9 #
show table status;
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
--replace_column 7 # 8 # 9 #
--replace_column 6 # 7 # 8 # 9 #
show table status;
delete from t1 where a=3;
delete from t2 where b=3;
delete from t3 where a=3;
--replace_column 7 # 8 # 9 #
--replace_column 6 # 7 # 8 # 9 #
show table status;
delete from t1;
delete from t2;
delete from t3;
--replace_column 7 # 8 # 9 #
--replace_column 6 # 7 # 8 # 9 #
show table status;
insert into t1 values (5);
insert into t2 values (5);
insert into t3 values (5,5);
--replace_column 7 # 8 # 9 #
--replace_column 6 # 7 # 8 # 9 #
show table status;
delete from t1 where a=5;
delete from t2 where b=5;
delete from t3 where a=5;
--replace_column 7 # 8 # 9 #
--replace_column 6 # 7 # 8 # 9 #
show table status;
drop table t1, t2, t3;

View file

@ -88,6 +88,8 @@ select hex(min(b)) from t1 where a = 4;
select hex(min(c)) from t1 where a = 4 and b = 0;
select hex(max(b)) from t1;
select a+0, b+0, c+0 from t1 where a = 4 and b = 0 limit 2;
select a+0, b+0, c+0 from t1 where a = 4 and b = 1;
select a+0, b+0, c+0 from t1 where a = 4 and b = 1 and c=100;
select a+0, b+0, c+0 from t1 order by b desc;
select a+0, b+0, c+0 from t1 order by c;
drop table t1;
@ -101,6 +103,6 @@ drop table t1;
# Some magic numbers
create table t1 (a bit(7), key(a));
insert into t1 values (44), (57);
insert into t1 values (44), (57);
select a+0 from t1;
drop table t1;

View file

@ -32,3 +32,68 @@ create table t1 (v varbinary(20));
insert into t1 values('a');
insert into t1 values('a ');
alter table t1 add primary key (v);
drop table t1;
#
# Test with varchar of lengths 254,255,256,258 & 258 to ensure we don't
# have any problems with varchar with one or two byte length_bytes
#
create table t1 (v varchar(254), index (v));
insert into t1 values ("This is a test ");
insert into t1 values ("Some sample data");
insert into t1 values (" garbage ");
insert into t1 values (" This is a test ");
insert into t1 values ("This is a test");
insert into t1 values ("Hello world");
insert into t1 values ("Foo bar");
insert into t1 values ("This is a test");
insert into t1 values ("MySQL varchar test");
insert into t1 values ("test MySQL varchar");
insert into t1 values ("This is a long string to have some random length data included");
insert into t1 values ("Short string");
insert into t1 values ("VSS");
insert into t1 values ("Some samples");
insert into t1 values ("Bar foo");
insert into t1 values ("Bye");
let $i= 255;
let $j= 5;
while ($j)
{
select * from t1 where v like 'This is a test' order by v;
select * from t1 where v='This is a test' order by v;
select * from t1 where v like 'S%' order by v;
explain select * from t1 where v like 'This is a test' order by v;
explain select * from t1 where v='This is a test' order by v;
explain select * from t1 where v like 'S%' order by v;
eval alter table t1 change v v varchar($i);
inc $i;
dec $j;
}
let $i= 258;
let $j= 6;
while ($j)
{
select * from t1 where v like 'This is a test' order by v;
select * from t1 where v='This is a test' order by v;
select * from t1 where v like 'S%' order by v;
explain select * from t1 where v like 'This is a test' order by v;
explain select * from t1 where v='This is a test' order by v;
explain select * from t1 where v like 'S%' order by v;
eval alter table t1 change v v varchar($i);
dec $i;
dec $j;
}
alter table t1 change v v varchar(254), drop key v;
# Test with length(varchar) > 256 and key < 256 (to ensure things works with
# different kind of packing
alter table t1 change v v varchar(300), add key (v(10));
select * from t1 where v like 'This is a test' order by v;
select * from t1 where v='This is a test' order by v;
select * from t1 where v like 'S%' order by v;
explain select * from t1 where v like 'This is a test' order by v;
explain select * from t1 where v='This is a test' order by v;
explain select * from t1 where v like 'S%' order by v;
drop table t1;

View file

@ -28,7 +28,7 @@
LIST *list_add(LIST *root, LIST *element)
{
DBUG_ENTER("list_add");
DBUG_PRINT("enter",("root: 0x%lx element: %lx", root, element));
DBUG_PRINT("enter",("root: 0x%lx element: 0x%lx", root, element));
if (root)
{
if (root->prev) /* If add in mid of list */

View file

@ -207,7 +207,8 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
b+=length;
}
break;
case HA_KEYTYPE_VARTEXT:
case HA_KEYTYPE_VARTEXT1:
case HA_KEYTYPE_VARTEXT2:
{
int a_length,b_length,pack_length;
get_key_length(a_length,a);
@ -229,7 +230,8 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
break;
}
break;
case HA_KEYTYPE_VARBINARY:
case HA_KEYTYPE_VARBINARY1:
case HA_KEYTYPE_VARBINARY2:
{
int a_length,b_length,pack_length;
get_key_length(a_length,a);

View file

@ -185,7 +185,7 @@ extern "C" {
uint my_raid_write(File fd,const byte *Buffer, uint Count, myf MyFlags)
{
DBUG_ENTER("my_raid_write");
DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d",
DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
fd, Buffer, Count, MyFlags));
if (is_raid(fd))
{
@ -198,7 +198,7 @@ extern "C" {
uint my_raid_read(File fd, byte *Buffer, uint Count, myf MyFlags)
{
DBUG_ENTER("my_raid_read");
DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u MyFlags: %d",
DBUG_PRINT("enter",("Fd: %d Buffer: 0x%lx Count: %u MyFlags: %d",
fd, Buffer, Count, MyFlags));
if (is_raid(fd))
{
@ -212,8 +212,9 @@ extern "C" {
myf MyFlags)
{
DBUG_ENTER("my_raid_pread");
DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d",
Filedes, Buffer, Count, offset, MyFlags));
DBUG_PRINT("enter",
("Fd: %d Buffer: 0x%lx Count: %u offset: %u MyFlags: %d",
Filedes, Buffer, Count, offset, MyFlags));
if (is_raid(Filedes))
{
assert(offset != MY_FILEPOS_ERROR);
@ -231,8 +232,9 @@ extern "C" {
my_off_t offset, myf MyFlags)
{
DBUG_ENTER("my_raid_pwrite");
DBUG_PRINT("enter",("Fd: %d Buffer: %lx Count: %u offset: %u MyFlags: %d",
Filedes, Buffer, Count, offset, MyFlags));
DBUG_PRINT("enter",
("Fd: %d Buffer: 0x %lx Count: %u offset: %u MyFlags: %d",
Filedes, Buffer, Count, offset, MyFlags));
if (is_raid(Filedes))
{
assert(offset != MY_FILEPOS_ERROR);

View file

@ -191,9 +191,11 @@ void Mysql_connection_thread::run()
int Mysql_connection_thread::check_connection()
{
ulong pkt_len=0; // to hold client reply length
/* maximum size of the version string */
enum { MAX_VERSION_LENGTH= 80 };
/* buffer for the first packet */ /* packet contains: */
char buff[mysqlmanager_version_length + 1 + // server version, 0-ended
char buff[MAX_VERSION_LENGTH + 1 + // server version, 0-ended
4 + // connection id
SCRAMBLE_LENGTH + 2 + // scramble (in 2 pieces)
18]; // server variables: flags,

View file

@ -16,6 +16,10 @@
#include "priv.h"
/*
The following string must be less then 80 characters, as
mysql_connection.cc relies on it
*/
const char mysqlmanager_version[] = "0.2-alpha";
const int mysqlmanager_version_length= sizeof(mysqlmanager_version) - 1;

View file

@ -329,6 +329,27 @@ bool Field::field_cast_compatible(Field::field_cast_enum type)
}
/*
Interpret field value as an integer but return the result as a string.
This is used for printing bit_fields as numbers while debugging
*/
String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_flag)
{
CHARSET_INFO *cs= &my_charset_bin;
uint length= 21;
longlong value= val_int();
if (val_buffer->alloc(length))
return 0;
length= (uint) cs->cset->longlong10_to_str(cs, (char*) val_buffer->ptr(),
length, unsigned_flag ? 10 : -10,
value);
val_buffer->length(length);
return val_buffer;
}
/****************************************************************************
** Functions for the base classes
** This is an unpacked number.
@ -500,6 +521,22 @@ Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table)
return tmp;
}
Field *Field::new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit)
{
Field *tmp;
if ((tmp= new_field(root, new_table)))
{
tmp->ptr= new_ptr;
tmp->null_ptr= new_null_ptr;
tmp->null_bit= new_null_bit;
}
return tmp;
}
/****************************************************************************
Field_null, a field that always return NULL
****************************************************************************/
@ -4657,7 +4694,19 @@ Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
}
/****************************************************************************
** VARCHAR type (Not available for the end user yet)
VARCHAR type
Data in field->ptr is stored as:
1 or 2 bytes length-prefix-header (from Field_varstring::length_bytes)
data
NOTE:
When VARCHAR is stored in a key (for handler::index_read() etc) it's always
stored with a 2 byte prefix. (Just like blob keys).
Normally length_bytes is calculated as (field_length < 256 : 1 ? 2)
The exception is if there is a prefix key field that is part of a long
VARCHAR, in which case field_length for this may be 1 but the length_bytes
is 2.
****************************************************************************/
@ -4686,8 +4735,11 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
from,from+length,
field_length/
field_charset->mbmaxlen);
memcpy(ptr + HA_KEY_BLOB_LENGTH, from, copy_length);
int2store(ptr, copy_length);
memcpy(ptr + length_bytes, from, copy_length);
if (length_bytes == 1)
*ptr= (uchar) copy_length;
else
int2store(ptr, copy_length);
if (copy_length < length)
error= 1;
@ -4700,91 +4752,117 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
int Field_varstring::store(longlong nr)
{
char buff[64];
int l;
CHARSET_INFO *cs=charset();
l= (cs->cset->longlong10_to_str)(cs,buff,sizeof(buff),-10,nr);
return Field_varstring::store(buff,(uint)l,cs);
uint length;
length= (uint) (field_charset->cset->longlong10_to_str)(field_charset,
buff,
sizeof(buff),
-10,nr);
return Field_varstring::store(buff, length, field_charset);
}
double Field_varstring::val_real(void)
{
int not_used;
uint length=uint2korr(ptr)+HA_KEY_BLOB_LENGTH;
CHARSET_INFO *cs=charset();
return my_strntod(cs, ptr+HA_KEY_BLOB_LENGTH, length, (char**)0, &not_used);
uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
return my_strntod(field_charset, ptr+length_bytes, length, (char**) 0,
&not_used);
}
longlong Field_varstring::val_int(void)
{
int not_used;
uint length=uint2korr(ptr)+HA_KEY_BLOB_LENGTH;
CHARSET_INFO *cs=charset();
return my_strntoll(cs,ptr+HA_KEY_BLOB_LENGTH,length,10,NULL, &not_used);
uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
return my_strntoll(field_charset, ptr+length_bytes, length, 10, NULL,
&not_used);
}
String *Field_varstring::val_str(String *val_buffer __attribute__((unused)),
String *val_ptr)
{
uint length=uint2korr(ptr);
val_ptr->set((const char*) ptr+HA_KEY_BLOB_LENGTH,length,field_charset);
uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
val_ptr->set((const char*) ptr+length_bytes, length, field_charset);
return val_ptr;
}
int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
{
uint a_length=uint2korr(a_ptr);
uint b_length=uint2korr(b_ptr);
uint a_length, b_length;
int diff;
if (length_bytes == 1)
{
a_length= (uint) (uchar) *a_ptr;
b_length= (uint) (uchar) *b_ptr;
}
else
{
a_length= uint2korr(a_ptr);
b_length= uint2korr(b_ptr);
}
diff= field_charset->coll->strnncollsp(field_charset,
(const uchar*) a_ptr+
HA_KEY_BLOB_LENGTH,
length_bytes,
a_length,
(const uchar*) b_ptr+
HA_KEY_BLOB_LENGTH,
length_bytes,
b_length,0);
return diff;
}
/*
NOTE: varstring and blob keys are ALWAYS stored with a 2 byte length prefix
*/
int Field_varstring::key_cmp(const byte *key_ptr, uint max_key_length)
{
char *blob1;
uint length= uint2korr(ptr);
CHARSET_INFO *cs= charset();
uint char_length= max_key_length / cs->mbmaxlen;
uint length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
uint char_length= max_key_length / field_charset->mbmaxlen;
char_length= my_charpos(cs, ptr + HA_KEY_BLOB_LENGTH,
ptr + HA_KEY_BLOB_LENGTH + length, char_length);
char_length= my_charpos(field_charset, ptr + length_bytes,
ptr + length_bytes + length, char_length);
set_if_smaller(length, char_length);
return cs->coll->strnncollsp(cs,
(const uchar*) ptr+2, length,
(const uchar*) key_ptr+HA_KEY_BLOB_LENGTH,
uint2korr(key_ptr), 0);
return field_charset->coll->strnncollsp(field_charset,
(const uchar*) ptr + length_bytes,
length,
(const uchar*) key_ptr+
HA_KEY_BLOB_LENGTH,
uint2korr(key_ptr), 0);
}
/*
Compare to key segments (always 2 byte length prefix)
NOTE
This is used only to compare key segments created for index_read().
(keys are created and compared in key.cc)
*/
int Field_varstring::key_cmp(const byte *a,const byte *b)
{
CHARSET_INFO *cs= charset();
return cs->coll->strnncollsp(cs,
(const uchar*) a + HA_KEY_BLOB_LENGTH,
uint2korr(a),
(const uchar*) b + HA_KEY_BLOB_LENGTH,
uint2korr(b),
0);
return field_charset->coll->strnncollsp(field_charset,
(const uchar*) a +
HA_KEY_BLOB_LENGTH,
uint2korr(a),
(const uchar*) b +
HA_KEY_BLOB_LENGTH,
uint2korr(b),
0);
}
void Field_varstring::sort_string(char *to,uint length)
{
uint tot_length= uint2korr(ptr);
uint tot_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
tot_length= my_strnxfrm(field_charset,
(uchar*) to, length,
(uchar*) ptr+HA_KEY_BLOB_LENGTH,
(uchar*) ptr + length_bytes,
tot_length);
if (tot_length < length)
field_charset->cset->fill(field_charset, to+tot_length,length-tot_length,
@ -4792,6 +4870,18 @@ void Field_varstring::sort_string(char *to,uint length)
}
enum ha_base_keytype Field_varstring::key_type() const
{
enum ha_base_keytype res;
if (binary())
res= length_bytes == 1 ? HA_KEYTYPE_VARBINARY1 : HA_KEYTYPE_VARBINARY2;
else
res= length_bytes == 1 ? HA_KEYTYPE_VARTEXT1 : HA_KEYTYPE_VARTEXT2;
return res;
}
void Field_varstring::sql_type(String &res) const
{
THD *thd= table->in_use;
@ -4809,13 +4899,102 @@ void Field_varstring::sql_type(String &res) const
}
/*
Functions to create a packed row.
Here the number of length bytes are depending on the given max_length
*/
char *Field_varstring::pack(char *to, const char *from, uint max_length)
{
uint length=uint2korr(from);
uint length= length_bytes == 1 ? (uint) (uchar) *from : uint2korr(from);
set_if_smaller(max_length, field_length);
if (length > max_length)
length=max_length;
*to++= (char) (length & 255);
if (max_length > 255)
*to++= (char) (length >> 8);
if (length)
memcpy(to, from+length_bytes, length);
return to+length;
}
char *Field_varstring::pack_key(char *to, const char *key, uint max_length)
{
uint length= length_bytes == 1 ? (uint) (uchar) *key : uint2korr(key);
uint char_length= ((field_charset->mbmaxlen > 1) ?
max_length/field_charset->mbmaxlen : max_length);
key+= length_bytes;
if (length > char_length)
{
char_length= my_charpos(field_charset, key, key+length, char_length);
set_if_smaller(length, char_length);
}
*to++= (char) (length & 255);
if (max_length > 255)
*to++= (char) (length >> 8);
if (length)
memcpy(to, key, length);
return to+length;
}
/*
Unpack a key into a record buffer.
SYNOPSIS
unpack_key()
to Pointer into the record buffer.
key Pointer to the packed key.
max_length Key length limit from key description.
DESCRIPTION
A VARCHAR key has a maximum size of 64K-1.
In its packed form, the length field is one or two bytes long,
depending on 'max_length'.
RETURN
Pointer to end of 'key' (To the next key part if multi-segment key)
*/
const char *Field_varstring::unpack_key(char *to, const char *key,
uint max_length)
{
/* get length of the blob key */
uint32 length= *((uchar*) key++);
if (max_length > 255)
length+= (*((uchar*) key++)) << 8;
/* put the length into the record buffer */
if (length_bytes == 1)
*ptr= (uchar) length;
else
int2store(ptr, length);
memcpy(ptr + length_bytes, key, length);
return key + length;
}
/*
Create a packed key that will be used for storage in the index tree
SYNOPSIS
pack_key_from_key_image()
to Store packed key segment here
from Key segment (as given to index_read())
max_length Max length of key
RETURN
end of key storage
*/
char *Field_varstring::pack_key_from_key_image(char *to, const char *from,
uint max_length)
{
/* Key length is always stored as 2 bytes */
uint length= uint2korr(from);
if (length > max_length)
length= max_length;
*to++= (char) (length & 255);
if (max_length > 255)
*to++= (char) (length >> 8);
if (length)
@ -4824,34 +5003,15 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length)
}
char *Field_varstring::pack_key(char *to, const char *from, uint max_length)
{
uint length=uint2korr(from);
uint char_length= ((field_charset->mbmaxlen > 1) ?
max_length/field_charset->mbmaxlen : max_length);
from+= HA_KEY_BLOB_LENGTH;
if (length > char_length)
{
char_length= my_charpos(field_charset, from, from+length, char_length);
set_if_smaller(length, char_length);
}
*to++= (char) (length & 255);
if (max_length > 255)
*to++= (char) (length >> 8);
if (length)
memcpy(to, from, length);
return to+length;
}
/*
unpack field packed with Field_varstring::pack()
*/
const char *Field_varstring::unpack(char *to, const char *from)
{
uint length;
if (field_length <= 255)
{
if (length_bytes == 1)
length= (uint) (uchar) (*to= *from++);
to[1]=0;
}
else
{
length= uint2korr(from);
@ -4859,7 +5019,7 @@ const char *Field_varstring::unpack(char *to, const char *from)
to[1]= *from++;
}
if (length)
memcpy(to+HA_KEY_BLOB_LENGTH, from, length);
memcpy(to+ length_bytes, from, length);
return from+length;
}
@ -4867,12 +5027,11 @@ const char *Field_varstring::unpack(char *to, const char *from)
int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length,
my_bool insert_or_update)
{
uint a_length;
uint b_length;
uint a_length, b_length;
if (key_length > 255)
{
a_length=uint2korr(a); a+= HA_KEY_BLOB_LENGTH;
b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
a_length=uint2korr(a); a+= 2;
b_length=uint2korr(b); b+= 2;
}
else
{
@ -4889,8 +5048,8 @@ int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length,
int Field_varstring::pack_cmp(const char *b, uint key_length,
my_bool insert_or_update)
{
char *a= ptr+HA_KEY_BLOB_LENGTH;
uint a_length= uint2korr(ptr);
char *a= ptr+ length_bytes;
uint a_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
uint b_length;
uint char_length= ((field_charset->mbmaxlen > 1) ?
key_length / field_charset->mbmaxlen : key_length);
@ -4919,7 +5078,7 @@ int Field_varstring::pack_cmp(const char *b, uint key_length,
uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+HA_KEY_BLOB_LENGTH;
return uint2korr(data_ptr)+2;
return (uint) ((uchar) *data_ptr)+1;
}
@ -4932,13 +5091,14 @@ uint Field_varstring::max_packed_col_length(uint max_length)
void Field_varstring::get_key_image(char *buff, uint length, imagetype type)
{
uint f_length= uint2korr(ptr);
uint f_length= length_bytes == 1 ? (uint) (uchar) *ptr : uint2korr(ptr);
uint char_length= length / field_charset->mbmaxlen;
char_length= my_charpos(field_charset, ptr, ptr + HA_KEY_BLOB_LENGTH,
char_length= my_charpos(field_charset, ptr, ptr + length_bytes,
char_length);
set_if_smaller(f_length, char_length);
/* Key is always stored with 2 bytes */
int2store(buff,f_length);
memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+HA_KEY_BLOB_LENGTH, f_length);
memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+length_bytes, f_length);
if (f_length < length)
{
/*
@ -4952,18 +5112,12 @@ void Field_varstring::get_key_image(char *buff, uint length, imagetype type)
void Field_varstring::set_key_image(char *buff,uint length)
{
length=uint2korr(buff); // Real length is here
length= uint2korr(buff); // Real length is here
(void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length,
field_charset);
}
int Field_varstring::cmp_binary_offset(uint row_offset)
{
return cmp_binary(ptr, ptr+row_offset);
}
int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr,
uint32 max_length)
{
@ -4971,13 +5125,49 @@ int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr,
uint diff;
uint32 a_length,b_length;
a_length= uint2korr(a_ptr);
b_length= uint2korr(b_ptr);
if (length_bytes == 1)
{
a_length= (uint) (uchar) *a_ptr;
b_length= (uint) (uchar) *b_ptr;
}
else
{
a_length= uint2korr(a_ptr);
b_length= uint2korr(b_ptr);
}
set_if_smaller(a_length, max_length);
set_if_smaller(b_length, max_length);
if (a_length != b_length)
return 1;
return memcmp(a_ptr+2, b_ptr+2, a_length);
return memcmp(a_ptr+length_bytes, b_ptr+length_bytes, a_length);
}
Field *Field_varstring::new_field(MEM_ROOT *root, struct st_table *new_table)
{
Field_varstring *res= (Field_varstring*) Field::new_field(root, new_table);
if (res)
res->length_bytes= length_bytes;
return res;
}
Field *Field_varstring::new_key_field(MEM_ROOT *root,
struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit)
{
Field_varstring *res;
if ((res= (Field_varstring*) Field::new_key_field(root,
new_table,
new_ptr,
new_null_ptr,
new_null_bit)))
{
/* Keys length prefixes are always packed with 2 bytes */
res->length_bytes= 2;
}
return res;
}
@ -5234,18 +5424,6 @@ int Field_blob::cmp(const char *a_ptr, const char *b_ptr)
}
int Field_blob::cmp_offset(uint row_offset)
{
return Field_blob::cmp(ptr,ptr+row_offset);
}
int Field_blob::cmp_binary_offset(uint row_offset)
{
return cmp_binary(ptr, ptr+row_offset);
}
int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
uint32 max_length)
{
@ -5432,8 +5610,7 @@ const char *Field_blob::unpack(char *to, const char *from)
int Field_blob::pack_cmp(const char *a, const char *b, uint key_length,
my_bool insert_or_update)
{
uint a_length;
uint b_length;
uint a_length, b_length;
if (key_length > 255)
{
a_length=uint2korr(a); a+=2;
@ -5539,6 +5716,7 @@ const char *Field_blob::unpack_key(char *to, const char *from, uint max_length)
return from + length;
}
/* Create a packed key that will be used for storage from a MySQL key */
char *Field_blob::pack_key_from_key_image(char *to, const char *from,
@ -6077,6 +6255,43 @@ bool Field_num::eq_def(Field *field)
11 one byte for 'd'
*/
Field_bit::Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
: Field(ptr_arg, len_arg >> 3, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg),
bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7)
{
/*
Ensure that Field::eq() can distinguish between two different bit fields.
(two bit fields that are not null, may have same ptr and null_ptr)
*/
if (!null_ptr_arg)
null_bit= bit_ofs_arg;
}
Field *Field_bit::new_key_field(MEM_ROOT *root,
struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit)
{
Field_bit *res;
if ((res= (Field_bit*) Field::new_key_field(root, new_table,
new_ptr, new_null_ptr,
new_null_bit)))
{
/* Move bits normally stored in null_pointer to new_ptr */
res->bit_ptr= (uchar*) new_ptr;
res->bit_ofs= 0;
if (bit_len)
res->ptr++; // Store rest of data here
}
return res;
}
void Field_bit::make_field(Send_field *field)
{
/* table_cache_key is not set for temp tables */
@ -6198,7 +6413,7 @@ int Field_bit::key_cmp(const byte *str, uint length)
{
int flag;
uchar bits= get_rec_bits(bit_ptr, bit_ofs, bit_len);
if ((flag= (int) (bits - *str)))
if ((flag= (int) (bits - *(uchar*) str)))
return flag;
str++;
length--;
@ -6284,15 +6499,22 @@ void create_field::create_length_to_internal_length(void)
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VARCHAR:
length*= charset->mbmaxlen;
key_length*= charset->mbmaxlen;
key_length= length;
pack_length= calc_pack_length(sql_type, length);
break;
case MYSQL_TYPE_ENUM:
case MYSQL_TYPE_SET:
/* Pack_length already calculated in sql_parse.cc */
length*= charset->mbmaxlen;
key_length= pack_length;
break;
case MYSQL_TYPE_BIT:
pack_length= calc_pack_length(sql_type, length);
/* We need one extra byte to store the bits we save among the null bits */
key_length= pack_length+ test(length & 7);
break;
default:
/* do nothing */
key_length= pack_length= calc_pack_length(sql_type, length);
break;
}
}
@ -6323,7 +6545,7 @@ uint32 calc_pack_length(enum_field_types type,uint32 length)
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
case FIELD_TYPE_DECIMAL: return (length);
case MYSQL_TYPE_VARCHAR: return (length+HA_KEY_BLOB_LENGTH);
case MYSQL_TYPE_VARCHAR: return (length + (length < 256 ? 1: 2));
case FIELD_TYPE_YEAR:
case FIELD_TYPE_TINY : return 1;
case FIELD_TYPE_SHORT : return 2;
@ -6423,7 +6645,9 @@ Field *make_field(char *ptr, uint32 field_length,
unireg_check, field_name, table,
field_charset);
if (field_type == MYSQL_TYPE_VARCHAR)
return new Field_varstring(ptr,field_length,null_pos,null_bit,
return new Field_varstring(ptr,field_length,
HA_VARCHAR_PACKLENGTH(field_length),
null_pos,null_bit,
unireg_check, field_name, table,
field_charset);
return 0; // Error
@ -6573,9 +6797,8 @@ create_field::create_field(Field *old_field,Field *orig_field)
case MYSQL_TYPE_SET:
case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
/* These are corrected in create_length_to_internal_length */
/* This is corrected in create_length_to_internal_length */
length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
key_length/= charset->mbmaxlen;
break;
#ifdef HAVE_SPATIAL
case FIELD_TYPE_GEOMETRY:

View file

@ -113,9 +113,14 @@ public:
This trickery is used to decrease a number of malloc calls.
*/
virtual String *val_str(String*,String *)=0;
String *Field::val_int_as_str(String *val_buffer, my_bool unsigned_flag);
virtual Item_result result_type () const=0;
virtual Item_result cmp_type () const { return result_type(); }
bool eq(Field *field) { return ptr == field->ptr && null_ptr == field->null_ptr; }
bool eq(Field *field)
{
return (ptr == field->ptr && null_ptr == field->null_ptr &&
null_bit == field->null_bit);
}
virtual bool eq_def(Field *field);
virtual uint32 pack_length() const { return (uint32) field_length; }
virtual void reset(void) { bzero(ptr,pack_length()); }
@ -139,10 +144,9 @@ public:
virtual int cmp(const char *,const char *)=0;
virtual int cmp_binary(const char *a,const char *b, uint32 max_length=~0L)
{ return memcmp(a,b,pack_length()); }
virtual int cmp_offset(uint row_offset)
{ return memcmp(ptr,ptr+row_offset,pack_length()); }
virtual int cmp_binary_offset(uint row_offset)
{ return memcmp(ptr,ptr+row_offset,pack_length()); }
int cmp_offset(uint row_offset) { return cmp(ptr,ptr+row_offset); }
int cmp_binary_offset(uint row_offset)
{ return cmp_binary(ptr, ptr+row_offset); };
virtual int key_cmp(const byte *a,const byte *b)
{ return cmp((char*) a,(char*) b); }
virtual int key_cmp(const byte *str, uint length)
@ -185,7 +189,10 @@ public:
virtual bool can_be_compared_as_longlong() const { return FALSE; }
virtual void free() {}
virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table);
inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
virtual Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
virtual void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
{
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
}
@ -935,26 +942,31 @@ public:
class Field_varstring :public Field_str {
public:
Field_varstring(char *ptr_arg, uint32 len_arg,uchar *null_ptr_arg,
/* Store number of bytes used to store length (1 or 2) */
uint32 length_bytes;
Field_varstring(char *ptr_arg,
uint32 len_arg, uint length_bytes_arg,
uchar *null_ptr_arg,
uchar null_bit_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str(ptr_arg, len_arg, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg, cs)
unireg_check_arg, field_name_arg, table_arg, cs),
length_bytes(length_bytes_arg)
{}
Field_varstring(uint32 len_arg,bool maybe_null_arg,
const char *field_name_arg,
struct st_table *table_arg, CHARSET_INFO *cs)
:Field_str((char*) 0,len_arg, maybe_null_arg ? (uchar*) "": 0,0,
NONE, field_name_arg, table_arg, cs)
NONE, field_name_arg, table_arg, cs),
length_bytes(len_arg < 256 ? 1 :2)
{}
enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
enum ha_base_keytype key_type() const;
bool zero_pack() const { return 0; }
void reset(void) { bzero(ptr,field_length+2); }
uint32 pack_length() const { return (uint32) field_length+2; }
void reset(void) { bzero(ptr,field_length+length_bytes); }
uint32 pack_length() const { return (uint32) field_length+length_bytes; }
uint32 key_length() const { return (uint32) field_length; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(longlong nr);
@ -969,12 +981,13 @@ public:
void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
char *pack_key(char *to, const char *from, uint max_length);
char *pack_key_from_key_image(char* to, const char *from, uint max_length);
const char *unpack(char* to, const char *from);
const char *unpack_key(char* to, const char *from, uint max_length);
int pack_cmp(const char *a, const char *b, uint key_length,
my_bool insert_or_update);
int pack_cmp(const char *b, uint key_length,my_bool insert_or_update);
int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
int cmp_binary_offset(uint row_offset);
int key_cmp(const byte *,const byte*);
int key_cmp(const byte *str, uint length);
uint packed_col_length(const char *to, uint length);
@ -984,6 +997,10 @@ public:
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
field_cast_enum field_cast_type() { return FIELD_CAST_VARSTRING; }
Field *new_field(MEM_ROOT *root, struct st_table *new_table);
Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
};
@ -1006,7 +1023,7 @@ public:
}
enum_field_types type() const { return FIELD_TYPE_BLOB;}
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
{ return binary() ? HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2; }
int store(const char *to,uint length,CHARSET_INFO *charset);
int store(double nr);
int store(longlong nr);
@ -1015,9 +1032,7 @@ public:
String *val_str(String*,String *);
int cmp(const char *,const char*);
int cmp(const char *a, uint32 a_length, const char *b, uint32 b_length);
int cmp_offset(uint offset);
int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
int cmp_binary_offset(uint row_offset);
int key_cmp(const byte *,const byte*);
int key_cmp(const byte *str, uint length);
uint32 key_length() const { return 0; }
@ -1064,9 +1079,9 @@ public:
return 0;
}
char *pack(char *to, const char *from, uint max_length= ~(uint) 0);
const char *unpack(char *to, const char *from);
char *pack_key(char *to, const char *from, uint max_length);
char *pack_key_from_key_image(char* to, const char *from, uint max_length);
const char *unpack(char *to, const char *from);
const char *unpack_key(char* to, const char *from, uint max_length);
int pack_cmp(const char *a, const char *b, uint key_length,
my_bool insert_or_update);
@ -1101,7 +1116,7 @@ public:
:Field_blob(len_arg, maybe_null_arg, field_name_arg,
table_arg, &my_charset_bin)
{ geom_type= geom_type_arg; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_VARBINARY2; }
enum_field_types type() const { return FIELD_TYPE_GEOMETRY; }
void sql_type(String &str) const;
int store(const char *to, uint length, CHARSET_INFO *charset);
@ -1190,11 +1205,7 @@ public:
Field_bit(char *ptr_arg, uint32 len_arg, uchar *null_ptr_arg,
uchar null_bit_arg, uchar *bit_ptr_arg, uchar bit_ofs_arg,
enum utype unireg_check_arg, const char *field_name_arg,
struct st_table *table_arg)
: Field(ptr_arg, len_arg >> 3, null_ptr_arg, null_bit_arg,
unireg_check_arg, field_name_arg, table_arg),
bit_ptr(bit_ptr_arg), bit_ofs(bit_ofs_arg), bit_len(len_arg & 7)
{ }
struct st_table *table_arg);
enum_field_types type() const { return FIELD_TYPE_BIT; }
enum ha_base_keytype key_type() const { return HA_KEYTYPE_BIT; }
uint32 key_length() const { return (uint32) field_length + (bit_len > 0); }
@ -1226,6 +1237,9 @@ public:
field_cast_enum field_cast_type() { return FIELD_CAST_BIT; }
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
const char *unpack(char* to, const char *from);
Field *new_key_field(MEM_ROOT *root, struct st_table *new_table,
char *new_ptr, uchar *new_null_ptr,
uint new_null_bit);
};

View file

@ -305,7 +305,8 @@ static void do_field_string(Copy_field *copy)
char buff[MAX_FIELD_WIDTH];
copy->tmp.set_quick(buff,sizeof(buff),copy->tmp.charset());
copy->from_field->val_str(&copy->tmp);
copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),copy->tmp.charset());
copy->to_field->store(copy->tmp.c_ptr_quick(),copy->tmp.length(),
copy->tmp.charset());
}
@ -350,7 +351,23 @@ static void do_expand_string(Copy_field *copy)
copy->to_length-copy->from_length, ' ');
}
static void do_varstring(Copy_field *copy)
static void do_varstring1(Copy_field *copy)
{
uint length= (uint) *(uchar*) copy->from_ptr;
if (length > copy->to_length- 1)
{
length=copy->to_length - 1;
if (current_thd->count_cuted_fields)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_TRUNCATED, 1);
}
*(uchar*) copy->to_ptr= (uchar) length;
memcpy(copy->to_ptr+1, copy->from_ptr + 1, length);
}
static void do_varstring2(Copy_field *copy)
{
uint length=uint2korr(copy->from_ptr);
if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
@ -508,9 +525,15 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
}
else if (to->charset() != from->charset())
return do_field_string;
else if (to->real_type() == MYSQL_TYPE_VARCHAR && to_length !=
from_length)
return do_varstring;
else if (to->real_type() == MYSQL_TYPE_VARCHAR)
{
if (((Field_varstring*) to)->length_bytes !=
((Field_varstring*) from)->length_bytes)
return do_field_string;
if (to_length != from_length)
return (((Field_varstring*) to)->length_bytes == 1 ?
do_varstring1 : do_varstring2);
}
else if (to_length < from_length)
return do_cut_string;
else if (to_length > from_length)
@ -590,6 +613,12 @@ void field_conv(Field *to,Field *from)
char buff[MAX_FIELD_WIDTH];
String result(buff,sizeof(buff),from->charset());
from->val_str(&result);
/*
We use c_ptr_quick() here to make it easier if to is a float/double
as the conversion routines will do a copy of the result doesn't
end with \0. Can be replaced with .ptr() when we have our own
string->double conversion.
*/
to->store(result.c_ptr_quick(),result.length(),from->charset());
}
else if (from->result_type() == REAL_RESULT)

View file

@ -356,7 +356,8 @@ ulong ha_berkeley::index_flags(uint idx, uint part, bool all_parts) const
}
switch (table->key_info[idx].key_part[i].field->key_type()) {
case HA_KEYTYPE_TEXT:
case HA_KEYTYPE_VARTEXT:
case HA_KEYTYPE_VARTEXT1:
case HA_KEYTYPE_VARTEXT2:
/*
As BDB stores only one copy of equal strings, we can't use key read
on these. Binary collations do support key read though.
@ -391,6 +392,7 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key)
KEY_PART_INFO *key_part= key->key_part, *end=key_part+key->key_parts;
uint key_length=new_key->size;
DBUG_DUMP("key_in_index", saved_key_ptr, saved_key->size);
for (; key_part != end && (int) key_length > 0; key_part++)
{
int cmp;
@ -745,11 +747,11 @@ void ha_berkeley::unpack_row(char *record, DBT *row)
void ha_berkeley::unpack_key(char *record, DBT *key, uint index)
{
KEY *key_info=table->key_info+index;
KEY *key_info= table->key_info+index;
KEY_PART_INFO *key_part= key_info->key_part,
*end=key_part+key_info->key_parts;
*end= key_part+key_info->key_parts;
char *pos= (char*) key->data;
char *pos=(char*) key->data;
for (; key_part != end; key_part++)
{
if (key_part->null_bit)
@ -773,8 +775,10 @@ void ha_berkeley::unpack_key(char *record, DBT *key, uint index)
/*
Create a packed key from from a row
This will never fail as the key buffer is pre allocated.
Create a packed key from a row. This key will be written as such
to the index tree.
This will never fail as the key buffer is pre-allocated.
*/
DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
@ -820,7 +824,10 @@ DBT *ha_berkeley::create_key(DBT *key, uint keynr, char *buff,
/*
Create a packed key from from a MySQL unpacked key
Create a packed key from from a MySQL unpacked key (like the one that is
sent from the index_read()
This key is to be used to read a row
*/
DBT *ha_berkeley::pack_key(DBT *key, uint keynr, char *buff,
@ -1457,7 +1464,7 @@ int ha_berkeley::read_row(int error, char *buf, uint keynr, DBT *row,
int ha_berkeley::index_read_idx(byte * buf, uint keynr, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
statistic_increment(table->in_use->status_var.ha_read_key_count,&LOCK_status);
table->in_use->status_var.ha_read_key_count++;
DBUG_ENTER("index_read_idx");
current_row.flags=DB_DBT_REALLOC;
active_index=MAX_KEY;
@ -1476,10 +1483,9 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
int error;
KEY *key_info= &table->key_info[active_index];
int do_prev= 0;
DBUG_ENTER("ha_berkeley::index_read");
statistic_increment(table->in_use->status_var.ha_read_key_count,&LOCK_status);
table->in_use->status_var.ha_read_key_count++;
bzero((char*) &row,sizeof(row));
if (find_flag == HA_READ_BEFORE_KEY)
{
@ -1679,6 +1685,7 @@ DBT *ha_berkeley::get_pos(DBT *to, byte *pos)
pos+=key_part->field->packed_col_length((char*) pos,key_part->length);
to->size= (uint) (pos- (byte*) to->data);
}
DBUG_DUMP("key", (char*) to->data, to->size);
return to;
}

View file

@ -488,8 +488,10 @@ int ha_heap::create(const char *name, TABLE *table_arg,
else
{
if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
seg->type != HA_KEYTYPE_VARTEXT &&
seg->type != HA_KEYTYPE_VARBINARY)
seg->type != HA_KEYTYPE_VARTEXT1 &&
seg->type != HA_KEYTYPE_VARTEXT2 &&
seg->type != HA_KEYTYPE_VARBINARY1 &&
seg->type != HA_KEYTYPE_VARBINARY2)
seg->type= HA_KEYTYPE_BINARY;
}
seg->start= (uint) key_part->offset;

View file

@ -926,8 +926,11 @@ int ha_myisam::enable_indexes(uint mode)
{
sql_print_warning("Warning: Enabling keys got errno %d, retrying",
my_errno);
thd->clear_error();
param.testflag&= ~(T_REP_BY_SORT | T_QUICK);
error= (repair(thd,param,0) != HA_ADMIN_OK);
if (!error && thd->net.report_error)
error= HA_ERR_CRASHED;
}
info(HA_STATUS_CONST);
thd->proc_info=save_proc_info;
@ -1406,7 +1409,8 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
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=0;
keydef[i].seg[j].bit_start= keydef[i].seg[j].bit_end=
keydef[i].seg[j].bit_pos= 0;
keydef[i].seg[j].language = field->charset()->number;
if (field->null_ptr)
@ -1478,11 +1482,10 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
break;
if (found->flags & BLOB_FLAG)
{
recinfo_pos->type= (int) FIELD_BLOB;
}
else if (!(options & HA_OPTION_PACK_RECORD) ||
found->type() == MYSQL_TYPE_VARCHAR)
else if (found->type() == MYSQL_TYPE_VARCHAR)
recinfo_pos->type= FIELD_VARCHAR;
else if (!(options & HA_OPTION_PACK_RECORD))
recinfo_pos->type= (int) FIELD_NORMAL;
else if (found->zero_pack())
recinfo_pos->type= (int) FIELD_SKIP_ZERO;

View file

@ -1214,7 +1214,7 @@ int composite_key_cmp(void* arg, byte* key1, byte* key2)
{
Field* f = *field;
int len = *lengths++;
int res = f->key_cmp(key1, key2);
int res = f->cmp(key1, key2);
if (res)
return res;
key1 += len;
@ -1668,7 +1668,7 @@ int group_concat_key_cmp_with_distinct(void* arg, byte* key1,
{
int res;
uint offset= (uint) (field->ptr - record);
if ((res= field->key_cmp(key1 + offset, key2 + offset)))
if ((res= field->cmp(key1 + offset, key2 + offset)))
return res;
}
}
@ -1702,7 +1702,7 @@ int group_concat_key_cmp_with_order(void* arg, byte* key1, byte* key2)
{
int res;
uint offset= (uint) (field->ptr - record);
if ((res= field->key_cmp(key1 + offset, key2 + offset)))
if ((res= field->cmp(key1 + offset, key2 + offset)))
return (*order_item)->asc ? res : -res;
}
}

View file

@ -250,54 +250,54 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info,
bool key_cmp_if_same(TABLE *table,const byte *key,uint idx,uint key_length)
{
uint length;
uint store_length;
KEY_PART_INFO *key_part;
const byte *key_end= key + key_length;;
for (key_part=table->key_info[idx].key_part;
(int) key_length > 0;
key_part++, key+=length, key_length-=length)
key < key_end ;
key_part++, key+= store_length)
{
uint length;
store_length= key_part->store_length;
if (key_part->null_bit)
{
key_length--;
if (*key != test(table->record[0][key_part->null_offset] &
key_part->null_bit))
return 1;
if (*key)
{
length=key_part->store_length;
continue;
}
key++;
store_length--;
}
if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART |
HA_BIT_PART))
{
if (key_part->field->key_cmp(key, key_part->length))
return 1;
length=key_part->length+HA_KEY_BLOB_LENGTH;
continue;
}
else
length= min((uint) (key_end-key), store_length);
if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
FIELDFLAG_PACK)))
{
length=min(key_length,key_part->length);
if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
FIELDFLAG_PACK)))
CHARSET_INFO *cs= key_part->field->charset();
uint char_length= key_part->length / cs->mbmaxlen;
const byte *pos= table->record[0] + key_part->offset;
if (length > char_length)
{
CHARSET_INFO *cs= key_part->field->charset();
uint char_length= key_part->length / cs->mbmaxlen;
const byte *pos= table->record[0] + key_part->offset;
if (length > char_length)
{
char_length= my_charpos(cs, pos, pos + length, char_length);
set_if_smaller(char_length, length);
}
if (cs->coll->strnncollsp(cs,
(const uchar*) key, length,
(const uchar*) pos, char_length, 0))
return 1;
char_length= my_charpos(cs, pos, pos + length, char_length);
set_if_smaller(char_length, length);
}
else if (memcmp(key,table->record[0]+key_part->offset,length))
return 1;
if (cs->coll->strnncollsp(cs,
(const uchar*) key, length,
(const uchar*) pos, char_length, 0))
return 1;
continue;
}
if (memcmp(key,table->record[0]+key_part->offset,length))
return 1;
}
return 0;
}

View file

@ -746,7 +746,7 @@ int QUICK_RANGE_SELECT::init()
void QUICK_RANGE_SELECT::range_end()
{
if (file->inited != handler::NONE)
file->ha_index_end();
file->ha_index_or_rnd_end();
}
@ -3687,7 +3687,8 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
}
/* Get local copy of key */
copies= 1;
if (field->key_type() == HA_KEYTYPE_VARTEXT)
if (field->key_type() == HA_KEYTYPE_VARTEXT1 ||
field->key_type() == HA_KEYTYPE_VARTEXT2)
copies= 2;
str= str2= (char*) alloc_root(param->mem_root,
(key_part->store_length)*copies+1);
@ -4999,7 +5000,9 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
char *min_key,uint min_key_flag, char *max_key,
uint max_key_flag)
{
ha_rows records=0,tmp;
ha_rows records=0, tmp;
uint tmp_min_flag, tmp_max_flag, keynr, min_key_length, max_key_length;
char *tmp_min_key, *tmp_max_key;
param->max_key_part=max(param->max_key_part,key_tree->part);
if (key_tree->left != &null_element)
@ -5017,13 +5020,12 @@ check_quick_keys(PARAM *param,uint idx,SEL_ARG *key_tree,
return records;
}
uint tmp_min_flag,tmp_max_flag,keynr;
char *tmp_min_key=min_key,*tmp_max_key=max_key;
tmp_min_key= min_key;
tmp_max_key= max_key;
key_tree->store(param->key[idx][key_tree->part].store_length,
&tmp_min_key,min_key_flag,&tmp_max_key,max_key_flag);
uint min_key_length= (uint) (tmp_min_key- param->min_key);
uint max_key_length= (uint) (tmp_max_key- param->max_key);
min_key_length= (uint) (tmp_min_key- param->min_key);
max_key_length= (uint) (tmp_max_key- param->max_key);
if (param->is_ror_scan)
{
@ -5888,7 +5890,7 @@ int QUICK_RANGE_SELECT::get_next()
SYNOPSIS
QUICK_RANGE_SELECT::get_next_prefix()
prefix_length length of cur_prefix
cur_prefix prefix of a key to be searached for
cur_prefix prefix of a key to be searched for
DESCRIPTION
Each subsequent call to the method retrieves the first record that has a
@ -7402,7 +7404,8 @@ TRP_GROUP_MIN_MAX::make_quick(PARAM *param, bool retrieve_full_rows,
quick->quick_prefix_select= NULL; /* Can't construct a quick select. */
else
/* Make a QUICK_RANGE_SELECT to be used for group prefix retrieval. */
quick->quick_prefix_select= get_quick_select(param, param_idx, index_tree,
quick->quick_prefix_select= get_quick_select(param, param_idx,
index_tree,
&quick->alloc);
/*
@ -8446,7 +8449,10 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
store_length--;
}
field->set_key_image((char*) key, key_part->length);
field->val_str(&tmp);
if (field->type() == MYSQL_TYPE_BIT)
(void) field->val_int_as_str(&tmp, 1);
else
field->val_str(&tmp);
fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
if (key+store_length < key_end)
fputc('/',DBUG_FILE);

View file

@ -2467,6 +2467,8 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
bool found_unaliased_non_uniq= 0;
uint unaliased_counter;
LINT_INIT(unaliased_counter); // Dependent on found_unaliased
*unaliased= FALSE;
if (find->type() == Item::FIELD_ITEM || find->type() == Item::REF_ITEM)

View file

@ -268,13 +268,8 @@ int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
unit->cleanup();
}
else
{
free_tmp_table(thd, table);
unit->cleanup();
}
lex->current_select= save_current_select;
if (res)
free_tmp_table(thd, table);
}
return res;
}

View file

@ -4900,11 +4900,9 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
break;
case MYSQL_TYPE_VARCHAR:
/*
We can't use pack_length as this includes the field length
Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
if they don't have a default value
*/
new_field->key_length= new_field->length;
max_field_charlength= MAX_FIELD_VARCHARLENGTH;
break;
case MYSQL_TYPE_STRING:
@ -5105,16 +5103,12 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(1);
}
if (!new_field->pack_length)
new_field->pack_length= calc_pack_length(new_field->sql_type,
new_field->length);
if (!new_field->key_length)
new_field->key_length= new_field->pack_length;
lex->create_list.push_back(new_field);
lex->last_field=new_field;
DBUG_RETURN(0);
}
/* Store position for column in ALTER TABLE .. ADD column */
void store_position_for_column(const char *name)

View file

@ -2041,10 +2041,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
thd->cleanup_after_query();
if (stmt->state == Item_arena::PREPARED)
{
thd->current_arena= thd;
stmt->state= Item_arena::EXECUTED;
}
DBUG_VOID_RETURN;
}

View file

@ -235,9 +235,7 @@ bool handle_select(THD *thd, LEX *lex, select_result *result)
res|= thd->net.report_error;
if (unlikely(res))
{
/*
If we have real error reported erly then this will be ignored
*/
/* If we had a another error reported earlier then this will be ignored */
result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
result->abort();
}
@ -4873,7 +4871,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
&keyinfo->key_part[i],
(char*) key_buff,maybe_null);
/*
Remeber if we are going to use REF_OR_NULL
Remember if we are going to use REF_OR_NULL
But only if field _really_ can be null i.e. we force JT_REF
instead of JT_REF_OR_NULL in case if field can't be null
*/
@ -7538,7 +7536,7 @@ static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
{
Field *new_field;
if (convert_blob_length && org_field->flags & BLOB_FLAG)
if (convert_blob_length && (org_field->flags & BLOB_FLAG))
new_field= new Field_varstring(convert_blob_length,
org_field->maybe_null(),
org_field->field_name, table,
@ -7806,7 +7804,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
else for (ORDER *tmp=group ; tmp ; tmp=tmp->next)
{
(*tmp->item)->marker=4; // Store null in key
if ((*tmp->item)->max_length >= MAX_CHAR_WIDTH)
if ((*tmp->item)->max_length >= CONVERT_IF_BIGGER_TO_BLOB)
using_unique_constraint=1;
}
if (param->group_length >= MAX_BLOB_WIDTH)
@ -8151,37 +8149,40 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
key_part_info->null_bit=0;
key_part_info->field= field;
key_part_info->offset= field->offset();
key_part_info->length= (uint16) field->pack_length();
key_part_info->length= (uint16) field->key_length();
key_part_info->type= (uint8) field->key_type();
key_part_info->key_type =
((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
(ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT) ?
(ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
(ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
0 : FIELDFLAG_BINARY;
if (!using_unique_constraint)
{
group->buff=(char*) group_buff;
if (!(group->field=field->new_field(thd->mem_root,table)))
if (!(group->field= field->new_key_field(thd->mem_root,table,
(char*) group_buff +
test(maybe_null),
field->null_ptr,
field->null_bit)))
goto err; /* purecov: inspected */
if (maybe_null)
{
/*
To be able to group on NULL, we reserve place in group_buff
for the NULL flag just before the column.
To be able to group on NULL, we reserved place in group_buff
for the NULL flag just before the column. (see above).
The field data is after this flag.
The NULL flag is updated by 'end_update()' and 'end_write()'
The NULL flag is updated in 'end_update()' and 'end_write()'
*/
keyinfo->flags|= HA_NULL_ARE_EQUAL; // def. that NULL == NULL
key_part_info->null_bit=field->null_bit;
key_part_info->null_offset= (uint) (field->null_ptr -
(uchar*) table->record[0]);
group->field->move_field((char*) ++group->buff);
group_buff++;
group->buff++; // Pointer to field data
group_buff++; // Skipp null flag
}
else
group->field->move_field((char*) group_buff);
/* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */
key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL;
group_buff+= key_part_info->length;
group_buff+= group->field->pack_length();
}
keyinfo->key_length+= key_part_info->length;
}
@ -8245,7 +8246,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
key_part_info->type= (uint8) (*reg_field)->key_type();
key_part_info->key_type =
((ha_base_keytype) key_part_info->type == HA_KEYTYPE_TEXT ||
(ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT) ?
(ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT1 ||
(ha_base_keytype) key_part_info->type == HA_KEYTYPE_VARTEXT2) ?
0 : FIELDFLAG_BINARY;
}
}
@ -8295,8 +8297,8 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
MI_KEYDEF keydef;
MI_UNIQUEDEF uniquedef;
KEY *keyinfo=param->keyinfo;
DBUG_ENTER("create_myisam_tmp_table");
if (table->keys)
{ // Get keys for ni_create
bool using_unique_constraint=0;
@ -8344,19 +8346,18 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
{
seg->type=
((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT);
seg->bit_start=seg->length - table->blob_ptr_size;
HA_KEYTYPE_VARBINARY2 : HA_KEYTYPE_VARTEXT2);
seg->bit_start= field->pack_length() - table->blob_ptr_size;
seg->flag= HA_BLOB_PART;
seg->length=0; // Whole blob in unique constraint
}
else
{
seg->type= ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT);
seg->type= keyinfo->key_part[i].type;
/* Tell handler if it can do suffic space compression */
if (field->real_type() == MYSQL_TYPE_STRING &&
keyinfo->key_part[i].length > 4)
seg->flag|=HA_SPACE_PACK;
seg->flag|= HA_SPACE_PACK;
}
if (!(field->flags & NOT_NULL_FLAG))
{
@ -8365,7 +8366,7 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
/*
We are using a GROUP BY on something that contains NULL
In this case we have to tell MyISAM that two NULL should
on INSERT be compared as equal
on INSERT be regarded at the same value
*/
if (!using_unique_constraint)
keydef.flag|= HA_NULL_ARE_EQUAL;
@ -8649,21 +8650,19 @@ do_select(JOIN *join,List<Item> *fields,TABLE *table,Procedure *procedure)
}
if (table)
{
int tmp;
int tmp, new_errno= 0;
if ((tmp=table->file->extra(HA_EXTRA_NO_CACHE)))
{
DBUG_PRINT("error",("extra(HA_EXTRA_NO_CACHE) failed"));
my_errno= tmp;
error= -1;
new_errno= tmp;
}
if ((tmp=table->file->ha_index_or_rnd_end()))
{
DBUG_PRINT("error",("ha_index_or_rnd_end() failed"));
my_errno= tmp;
error= -1;
new_errno= tmp;
}
if (error == -1)
table->file->print_error(my_errno,MYF(0));
if (new_errno)
table->file->print_error(new_errno,MYF(0));
}
#ifndef DBUG_OFF
if (error)
@ -9835,13 +9834,19 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(0);
}
/* The null bits are already set */
/*
Copy null bits from group key to table
We can't copy all data as the key may have different format
as the row data (for example as with VARCHAR keys)
*/
KEY_PART_INFO *key_part;
for (group=table->group,key_part=table->key_info[0].key_part;
group ;
group=group->next,key_part++)
memcpy(table->record[0]+key_part->offset, group->buff, key_part->length);
{
if (key_part->null_bit)
memcpy(table->record[0]+key_part->offset, group->buff, 1);
}
init_tmptable_sum_functions(join->sum_funcs);
copy_funcs(join->tmp_table_param.items_to_copy);
if ((error=table->file->write_row(table->record[0])))
@ -11651,8 +11656,10 @@ calc_group_buffer(JOIN *join,ORDER *group)
{
if (field->type() == FIELD_TYPE_BLOB)
key_length+=MAX_BLOB_WIDTH; // Can't be used as a key
else if (field->type() == MYSQL_TYPE_VARCHAR)
key_length+= field->field_length + HA_KEY_BLOB_LENGTH;
else
key_length+=field->pack_length();
key_length+= field->pack_length();
}
else if ((*group->item)->result_type() == REAL_RESULT)
key_length+=sizeof(double);

View file

@ -420,15 +420,15 @@ class store_key :public Sql_alloc
:null_ptr(null),err(0)
{
if (field_arg->type() == FIELD_TYPE_BLOB)
to_field=new Field_varstring(ptr, length, (uchar*) null, 1,
{
/* Key segments are always packed with a 2 byte length prefix */
to_field=new Field_varstring(ptr, length, 2, (uchar*) null, 1,
Field::NONE, field_arg->field_name,
field_arg->table, field_arg->charset());
else
{
to_field=field_arg->new_field(thd->mem_root,field_arg->table);
if (to_field)
to_field->move_field(ptr, (uchar*) null, 1);
}
else
to_field=field_arg->new_key_field(thd->mem_root, field_arg->table,
ptr, (uchar*) null, 1);
}
virtual ~store_key() {} /* Not actually needed */
virtual bool copy()=0;

View file

@ -3391,7 +3391,7 @@ int make_schema_select(THD *thd, SELECT_LEX *sel,
/*
Fill temporaty schema tables before SELECT
Fill temporary schema tables before SELECT
SYNOPSIS
get_schema_tables_result()

View file

@ -509,7 +509,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
String conv, *tmp;
for (uint i= 0; (tmp= it++); i++)
{
if (String::needs_conversion(tmp->length(), tmp->charset(), cs, &dummy))
if (String::needs_conversion(tmp->length(), tmp->charset(), cs,
&dummy))
{
uint cnv_errs;
conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
@ -3698,7 +3699,7 @@ copy_data_between_tables(TABLE *from,TABLE *to,
free_io_cache(from);
delete [] copy; // This is never 0
if (to->file->end_bulk_insert() && !error)
if (to->file->end_bulk_insert() && error <= 0)
{
to->file->print_error(my_errno,MYF(0));
error=1;

View file

@ -74,7 +74,7 @@ typedef struct st_key_part_info { /* Info about a key part */
uint16 store_length;
uint16 key_type;
uint16 fieldnr; /* Fieldnum in UNIREG */
uint8 key_part_flag; /* 0 or HA_REVERSE_SORT */
uint16 key_part_flag; /* 0 or HA_REVERSE_SORT */
uint8 type;
uint8 null_bit; /* Position to null_bit */
} KEY_PART_INFO ;

View file

@ -631,6 +631,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
if (!(field->flags & BINARY_FLAG))
keyinfo->flags|= HA_END_SPACE_KEY;
}
if (field->type() == MYSQL_TYPE_BIT)
key_part->key_part_flag|= HA_BIT_PART;
if (i == 0 && key != primary_key)
field->flags |=
((keyinfo->flags & HA_NOSAME) &&

View file

@ -32,7 +32,8 @@ void vio_reset(Vio* vio, enum enum_vio_type type,
my_bool localhost)
{
DBUG_ENTER("vio_reset");
DBUG_PRINT("enter", ("type=%d sd=%d localhost=%d", type, sd, localhost));
DBUG_PRINT("enter", ("type: %d sd: %d localhost: %d", type, sd,
localhost));
bzero((char*) vio, sizeof(*vio));
vio->type = type;
@ -123,7 +124,7 @@ Vio *vio_new(my_socket sd, enum enum_vio_type type, my_bool localhost)
{
Vio *vio;
DBUG_ENTER("vio_new");
DBUG_PRINT("enter", ("sd=%d", sd));
DBUG_PRINT("enter", ("sd: %d", sd));
if ((vio = (Vio*) my_malloc(sizeof(*vio),MYF(MY_WME))))
{
vio_reset(vio, type, sd, 0, localhost);

View file

@ -33,7 +33,7 @@ int vio_read(Vio * vio, gptr buf, int size)
{
int r;
DBUG_ENTER("vio_read");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
#ifdef __WIN__
r = recv(vio->sd, buf, size,0);
@ -56,7 +56,7 @@ int vio_write(Vio * vio, const gptr buf, int size)
{
int r;
DBUG_ENTER("vio_write");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
#ifdef __WIN__
r = send(vio->sd, buf, size,0);
#else
@ -168,7 +168,7 @@ int vio_keepalive(Vio* vio, my_bool set_keep_alive)
int r=0;
uint opt = 0;
DBUG_ENTER("vio_keepalive");
DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int)
set_keep_alive));
if (vio->type != VIO_TYPE_NAMEDPIPE)
{
@ -315,7 +315,7 @@ int vio_read_pipe(Vio * vio, gptr buf, int size)
{
DWORD length;
DBUG_ENTER("vio_read_pipe");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
if (!ReadFile(vio->hPipe, buf, size, &length, NULL))
DBUG_RETURN(-1);
@ -329,7 +329,7 @@ int vio_write_pipe(Vio * vio, const gptr buf, int size)
{
DWORD length;
DBUG_ENTER("vio_write_pipe");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
if (!WriteFile(vio->hPipe, (char*) buf, size, &length, NULL))
DBUG_RETURN(-1);
@ -373,7 +373,7 @@ int vio_read_shared_memory(Vio * vio, gptr buf, int size)
char *current_postion;
DBUG_ENTER("vio_read_shared_memory");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
remain_local = size;
current_postion=buf;
@ -423,7 +423,7 @@ int vio_write_shared_memory(Vio * vio, const gptr buf, int size)
char *current_postion;
DBUG_ENTER("vio_write_shared_memory");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
remain = size;
current_postion = buf;

View file

@ -99,7 +99,7 @@ int vio_ssl_read(Vio * vio, gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_read");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d, ssl_=%p",
DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d, ssl_: 0x%p",
vio->sd, buf, size, vio->ssl_arg));
if ((r= SSL_read((SSL*) vio->ssl_arg, buf, size)) < 0)
@ -117,7 +117,7 @@ int vio_ssl_write(Vio * vio, const gptr buf, int size)
{
int r;
DBUG_ENTER("vio_ssl_write");
DBUG_PRINT("enter", ("sd=%d, buf=%p, size=%d", vio->sd, buf, size));
DBUG_PRINT("enter", ("sd: %d, buf: 0x%p, size: %d", vio->sd, buf, size));
if ((r= SSL_write((SSL*) vio->ssl_arg, buf, size)) < 0)
report_errors();
@ -157,7 +157,7 @@ int vio_ssl_keepalive(Vio* vio, my_bool set_keep_alive)
{
int r=0;
DBUG_ENTER("vio_ssl_keepalive");
DBUG_PRINT("enter", ("sd=%d, set_keep_alive=%d", vio->sd, (int)
DBUG_PRINT("enter", ("sd: %d, set_keep_alive: %d", vio->sd, (int)
set_keep_alive));
if (vio->type != VIO_TYPE_NAMEDPIPE)
{
@ -227,7 +227,7 @@ my_socket vio_ssl_fd(Vio* vio)
my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port)
{
DBUG_ENTER("vio_ssl_peer_addr");
DBUG_PRINT("enter", ("sd=%d", vio->sd));
DBUG_PRINT("enter", ("sd: %d", vio->sd));
if (vio->localhost)
{
strmov(buf,"127.0.0.1");
@ -250,7 +250,7 @@ my_bool vio_ssl_peer_addr(Vio * vio, char *buf, uint16 *port)
*port= 0;
#endif
}
DBUG_PRINT("exit", ("addr=%s", buf));
DBUG_PRINT("exit", ("addr: %s", buf));
DBUG_RETURN(0);
}
@ -279,7 +279,7 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
my_bool net_blocking;
enum enum_vio_type old_type;
DBUG_ENTER("sslaccept");
DBUG_PRINT("enter", ("sd=%d ptr=%p", vio->sd,ptr));
DBUG_PRINT("enter", ("sd: %d ptr: Ox%p", vio->sd,ptr));
old_type= vio->type;
net_blocking = vio_is_blocking(vio);
@ -294,7 +294,8 @@ int sslaccept(struct st_VioSSLAcceptorFd* ptr, Vio* vio, long timeout)
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
}
DBUG_PRINT("info", ("ssl_=%p timeout=%ld",(SSL*) vio->ssl_arg, timeout));
DBUG_PRINT("info", ("ssl_: Ox%p timeout: %ld",
(SSL*) vio->ssl_arg, timeout));
SSL_clear((SSL*) vio->ssl_arg);
SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout);
SSL_set_fd((SSL*) vio->ssl_arg,vio->sd);
@ -352,7 +353,8 @@ int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
my_bool net_blocking;
enum enum_vio_type old_type;
DBUG_ENTER("sslconnect");
DBUG_PRINT("enter", ("sd=%d ptr=%p ctx: %p", vio->sd,ptr,ptr->ssl_context));
DBUG_PRINT("enter", ("sd: %d ptr: 0x%p ctx: 0x%p",
vio->sd,ptr,ptr->ssl_context));
old_type= vio->type;
net_blocking = vio_is_blocking(vio);
@ -367,7 +369,8 @@ int sslconnect(struct st_VioSSLConnectorFd* ptr, Vio* vio, long timeout)
vio_blocking(vio, net_blocking, &unused);
DBUG_RETURN(1);
}
DBUG_PRINT("info", ("ssl_=%p timeout=%ld",(SSL*) vio->ssl_arg, timeout));
DBUG_PRINT("info", ("ssl_: 0x%p timeout: %ld",
(SSL*) vio->ssl_arg, timeout));
SSL_clear((SSL*) vio->ssl_arg);
SSL_SESSION_set_timeout(SSL_get_session((SSL*) vio->ssl_arg), timeout);
SSL_set_fd ((SSL*) vio->ssl_arg, vio->sd);

View file

@ -80,7 +80,7 @@ static int
vio_set_cert_stuff(SSL_CTX *ctx, const char *cert_file, const char *key_file)
{
DBUG_ENTER("vio_set_cert_stuff");
DBUG_PRINT("enter", ("ctx=%p, cert_file=%s, key_file=%s",
DBUG_PRINT("enter", ("ctx: %p, cert_file: %s, key_file: %s",
ctx, cert_file, key_file));
if (cert_file != NULL)
{
@ -131,7 +131,7 @@ vio_verify_callback(int ok, X509_STORE_CTX *ctx)
int err,depth;
DBUG_ENTER("vio_verify_callback");
DBUG_PRINT("enter", ("ok=%d, ctx=%p", ok, ctx));
DBUG_PRINT("enter", ("ok: %d, ctx: 0x%p", ok, ctx));
err_cert=X509_STORE_CTX_get_current_cert(ctx);
err= X509_STORE_CTX_get_error(ctx);
depth= X509_STORE_CTX_get_error_depth(ctx);
@ -220,7 +220,7 @@ new_VioSSLConnectorFd(const char* key_file,
DH *dh;
DBUG_ENTER("new_VioSSLConnectorFd");
DBUG_PRINT("enter",
("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
("key_file: %s, cert_file: %s, ca_path: %s, ca_file: %s, cipher: %s",
key_file, cert_file, ca_path, ca_file, cipher));
if (!(ptr=((struct st_VioSSLConnectorFd*)
@ -315,7 +315,7 @@ new_VioSSLAcceptorFd(const char *key_file,
DH *dh;
DBUG_ENTER("new_VioSSLAcceptorFd");
DBUG_PRINT("enter",
("key_file=%s, cert_file=%s, ca_path=%s, ca_file=%s, cipher=%s",
("key_file: %s, cert_file: %s, ca_path: %s, ca_file: %s, cipher: %s",
key_file, cert_file, ca_path, ca_file, cipher));
ptr= ((struct st_VioSSLAcceptorFd*)