summaryrefslogtreecommitdiff
path: root/myisam
diff options
context:
space:
mode:
Diffstat (limited to 'myisam')
-rw-r--r--myisam/Makefile.am2
-rw-r--r--myisam/ft_boolean_search.c92
-rw-r--r--myisam/ft_parser.c39
-rw-r--r--myisam/ft_static.c36
-rw-r--r--myisam/ft_stopwords.c2
-rw-r--r--myisam/ft_test1.c85
-rw-r--r--myisam/ft_update.c35
-rw-r--r--myisam/ftdefs.h3
-rw-r--r--myisam/mi_check.c7
-rw-r--r--myisam/mi_checksum.c8
-rw-r--r--myisam/mi_create.c97
-rw-r--r--myisam/mi_dbug.c16
-rw-r--r--myisam/mi_delete.c47
-rw-r--r--myisam/mi_dynrec.c75
-rw-r--r--myisam/mi_extra.c7
-rw-r--r--myisam/mi_info.c33
-rw-r--r--myisam/mi_key.c78
-rw-r--r--myisam/mi_keycache.c1
-rw-r--r--myisam/mi_locking.c6
-rw-r--r--myisam/mi_open.c52
-rw-r--r--myisam/mi_packrec.c38
-rw-r--r--myisam/mi_page.c2
-rw-r--r--myisam/mi_range.c19
-rw-r--r--myisam/mi_rkey.c1
-rw-r--r--myisam/mi_search.c33
-rw-r--r--myisam/mi_test1.c71
-rw-r--r--myisam/mi_test3.c1
-rw-r--r--myisam/mi_test_all.res73
-rw-r--r--myisam/mi_unique.c74
-rw-r--r--myisam/mi_update.c9
-rw-r--r--myisam/mi_write.c14
-rw-r--r--myisam/myisamchk.c8
-rw-r--r--myisam/myisamdef.h5
-rw-r--r--myisam/myisampack.c19
-rw-r--r--myisam/sort.c3
35 files changed, 752 insertions, 339 deletions
diff --git a/myisam/Makefile.am b/myisam/Makefile.am
index 378e8107814..e77e46cb7a3 100644
--- a/myisam/Makefile.am
+++ b/myisam/Makefile.am
@@ -17,7 +17,7 @@
EXTRA_DIST = mi_test_all.sh mi_test_all.res
pkgdata_DATA = mi_test_all mi_test_all.res
-INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
+INCLUDES = -I$(top_srcdir)/include
LDADD = @CLIENT_EXTRA_LDFLAGS@ libmyisam.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/dbug/libdbug.a \
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 62c68322595..530f0d56c4c 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -68,7 +68,7 @@ struct st_ftb_expr
my_off_t docid[2];
float weight;
float cur_weight;
- byte *quot, *qend;
+ LIST *phrase; /* phrase words */
uint yesses; /* number of "yes" words matched */
uint nos; /* number of "no" words matched */
uint ythresh; /* number of "yes" words in expr */
@@ -132,20 +132,22 @@ static int FTB_WORD_cmp_list(CHARSET_INFO *cs, FTB_WORD **a, FTB_WORD **b)
}
static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
- FTB_EXPR *up, uint depth)
+ FTB_EXPR *up, uint depth, byte *up_quot)
{
byte res;
FTB_PARAM param;
FT_WORD w;
FTB_WORD *ftbw;
FTB_EXPR *ftbe;
+ FT_WORD *phrase_word;
+ LIST *phrase_list;
uint extra=HA_FT_WLEN+ftb->info->s->rec_reflength; /* just a shortcut */
if (ftb->state != UNINITIALIZED)
return;
param.prev=' ';
- param.quot=up->quot;
+ param.quot= up_quot;
while ((res=ft_get_word(ftb->charset,start,end,&w,&param)))
{
int r=param.plusminus;
@@ -172,6 +174,14 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
if (param.yesno > 0) up->ythresh++;
queue_insert(& ftb->queue, (byte *)ftbw);
ftb->with_scan|=(param.trunc & FTB_FLAG_TRUNC);
+ case 4: /* not indexed word (stopword or too short/long) */
+ if (! up_quot) break;
+ phrase_word= (FT_WORD *)alloc_root(&ftb->mem_root, sizeof(FT_WORD));
+ phrase_list= (LIST *)alloc_root(&ftb->mem_root, sizeof(LIST));
+ phrase_word->pos= w.pos;
+ phrase_word->len= w.len;
+ phrase_list->data= (void *)phrase_word;
+ up->phrase= list_add(up->phrase, phrase_list);
break;
case 2: /* left bracket */
ftbe=(FTB_EXPR *)alloc_root(&ftb->mem_root, sizeof(FTB_EXPR));
@@ -182,13 +192,14 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
ftbe->up=up;
ftbe->ythresh=ftbe->yweaks=0;
ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR;
- if ((ftbe->quot=param.quot)) ftb->with_scan|=2;
+ ftbe->phrase= NULL;
+ if (param.quot) ftb->with_scan|=2;
if (param.yesno > 0) up->ythresh++;
- _ftb_parse_query(ftb, start, end, ftbe, depth+1);
+ _ftb_parse_query(ftb, start, end, ftbe, depth+1, param.quot);
param.quot=0;
break;
case 3: /* right bracket */
- if (up->quot) up->qend=param.quot;
+ if (up_quot) up->phrase= list_reverse(up->phrase);
return;
}
}
@@ -211,6 +222,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
uint off, extra=HA_FT_WLEN+info->s->base.rec_reflength;
byte *lastkey_buf=ftbw->word+ftbw->off;
+ LINT_INIT(off);
if (ftbw->flags & FTB_FLAG_TRUNC)
lastkey_buf+=ftbw->len;
@@ -409,12 +421,12 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
ftbe->weight=1;
ftbe->flags=FTB_FLAG_YES;
ftbe->nos=1;
- ftbe->quot=0;
ftbe->up=0;
ftbe->ythresh=ftbe->yweaks=0;
ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR;
+ ftbe->phrase= NULL;
ftb->root=ftbe;
- _ftb_parse_query(ftb, &query, query+query_len, ftbe, 0);
+ _ftb_parse_query(ftb, &query, query+query_len, ftbe, 0, NULL);
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
sizeof(FTB_WORD *)*ftb->queue.elements);
memcpy(ftb->list, ftb->queue.root+1, sizeof(FTB_WORD *)*ftb->queue.elements);
@@ -430,29 +442,45 @@ err:
}
-/* returns 1 if str0 ~= /\bstr1\b/ */
-static int _ftb_strstr(const byte *s0, const byte *e0,
- const byte *s1, const byte *e1,
- CHARSET_INFO *cs)
+/*
+ Checks if given buffer matches phrase list.
+
+ SYNOPSIS
+ _ftb_check_phrase()
+ s0 start of buffer
+ e0 end of buffer
+ phrase broken into list phrase
+ cs charset info
+
+ RETURN VALUE
+ 1 is returned if phrase found, 0 else.
+*/
+
+static int _ftb_check_phrase(const byte *s0, const byte *e0,
+ LIST *phrase, CHARSET_INFO *cs)
{
- const byte *p0= s0;
- my_bool s_after= true_word_char(cs, s1[0]);
- my_bool e_before= true_word_char(cs, e1[-1]);
- uint p0_len;
- my_match_t m[2];
+ FT_WORD h_word;
+ const byte *h_start= s0;
+ DBUG_ENTER("_ftb_strstr");
+ DBUG_ASSERT(phrase);
- while (p0 < e0)
+ while (ft_simple_get_word(cs, (byte **)&h_start, e0, &h_word, FALSE))
{
- if (cs->coll->instr(cs, p0, e0 - p0, s1, e1 - s1, m, 2) != 2)
- return(0);
- if ((!s_after || p0 + m[1].beg == s0 || !true_word_char(cs, p0[m[1].beg-1])) &&
- (!e_before || p0 + m[1].end == e0 || !true_word_char(cs, p0[m[1].end])))
- return(1);
- p0+= m[1].beg;
- p0+= (p0_len= my_mbcharlen(cs, *(uchar *)p0)) ? p0_len : 1;
+ FT_WORD *n_word;
+ LIST *phrase_element= phrase;
+ const byte *h_start1= h_start;
+ for (;;)
+ {
+ n_word= (FT_WORD *)phrase_element->data;
+ if (my_strnncoll(cs, h_word.pos, h_word.len, n_word->pos, n_word->len))
+ break;
+ if (! (phrase_element= phrase_element->next))
+ DBUG_RETURN(1);
+ if (! ft_simple_get_word(cs, (byte **)&h_start1, e0, &h_word, FALSE))
+ DBUG_RETURN(0);
+ }
}
-
- return(0);
+ DBUG_RETURN(0);
}
@@ -483,7 +511,7 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
{
yn=ftbe->flags;
weight=ftbe->cur_weight*ftbe->weight;
- if (mode && ftbe->quot)
+ if (mode && ftbe->phrase)
{
int not_found=1;
@@ -492,8 +520,8 @@ static void _ftb_climb_the_tree(FTB *ftb, FTB_WORD *ftbw, FT_SEG_ITERATOR *ftsi_
{
if (!ftsi.pos)
continue;
- not_found = ! _ftb_strstr(ftsi.pos, ftsi.pos+ftsi.len,
- ftbe->quot, ftbe->qend, ftb->charset);
+ not_found = ! _ftb_check_phrase(ftsi.pos, ftsi.pos+ftsi.len,
+ ftbe->phrase, ftb->charset);
}
if (not_found) break;
} /* ftbe->quot */
@@ -641,8 +669,8 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
continue;
end=ftsi.pos+ftsi.len;
- while (ft_simple_get_word(ftb->charset,
- (byte **) &ftsi.pos, (byte *) end, &word))
+ while (ft_simple_get_word(ftb->charset, (byte **) &ftsi.pos,
+ (byte *) end, &word, TRUE))
{
int a, b, c;
for (a=0, b=ftb->queue.elements, c=(a+b)/2; b-a>1; c=(a+b)/2)
diff --git a/myisam/ft_parser.c b/myisam/ft_parser.c
index 0b1e68b0d70..2fad2363ae2 100644
--- a/myisam/ft_parser.c
+++ b/myisam/ft_parser.c
@@ -93,12 +93,14 @@ my_bool ft_boolean_check_syntax_string(const byte *str)
return 0;
}
-/* returns:
- * 0 - eof
- * 1 - word found
- * 2 - left bracket
- * 3 - right bracket
- */
+/*
+ RETURN VALUE
+ 0 - eof
+ 1 - word found
+ 2 - left bracket
+ 3 - right bracket
+ 4 - stopword found
+*/
byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end,
FT_WORD *word, FTB_PARAM *param)
{
@@ -161,6 +163,11 @@ byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end,
*start=doc;
return 1;
}
+ else if (length) /* make sure length > 0 (if start contains spaces only) */
+ {
+ *start= doc;
+ return 4;
+ }
}
if (param->quot)
{
@@ -170,18 +177,19 @@ byte ft_get_word(CHARSET_INFO *cs, byte **start, byte *end,
return 0;
}
-byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, byte *end,
- FT_WORD *word)
+byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, const byte *end,
+ FT_WORD *word, my_bool skip_stopwords)
{
byte *doc= *start;
uint mwc, length, mbl;
DBUG_ENTER("ft_simple_get_word");
- while (doc<end)
+ do
{
- for (;doc<end;doc++)
+ for (;; doc++)
{
- if (true_word_char(cs,*doc)) break;
+ if (doc >= end) DBUG_RETURN(0);
+ if (true_word_char(cs, *doc)) break;
}
mwc= length= 0;
@@ -193,13 +201,14 @@ byte ft_simple_get_word(CHARSET_INFO *cs, byte **start, byte *end,
word->len= (uint)(doc-word->pos) - mwc;
- if (length >= ft_min_word_len && length < ft_max_word_len &&
- !is_stopword(word->pos, word->len))
+ if (skip_stopwords == FALSE ||
+ (length >= ft_min_word_len && length < ft_max_word_len &&
+ !is_stopword(word->pos, word->len)))
{
*start= doc;
DBUG_RETURN(1);
}
- }
+ } while (doc < end);
DBUG_RETURN(0);
}
@@ -217,7 +226,7 @@ int ft_parse(TREE *wtree, byte *doc, int doclen, my_bool with_alloc)
FT_WORD w;
DBUG_ENTER("ft_parse");
- while (ft_simple_get_word(wtree->custom_arg, &doc,end,&w))
+ while (ft_simple_get_word(wtree->custom_arg, &doc, end, &w, TRUE))
{
if (with_alloc)
{
diff --git a/myisam/ft_static.c b/myisam/ft_static.c
index 994a94d0c49..e221950f445 100644
--- a/myisam/ft_static.c
+++ b/myisam/ft_static.c
@@ -25,23 +25,25 @@ char ft_boolean_syntax[]="+ -><()~*:\"\"&|";
const HA_KEYSEG ft_keysegs[FT_SEGS]={
{
- HA_KEYTYPE_VARTEXT, /* type */
- 63, /* language (will be overwritten) */
- 0, 0, 0, /* null_bit, bit_start, bit_end */
- HA_VAR_LENGTH | HA_PACK_KEY, /* flag */
- HA_FT_MAXBYTELEN, /* length */
- HA_FT_WLEN, /* start */
- 0, /* null_pos */
- NULL /* charset */
- },
- {
-/*
- Note, this (and the last HA_KEYTYPE_END) segment should NOT
- be packed in any way, otherwise w_search() won't be able to
- update key entry 'in vivo'
-*/
- HA_FT_WTYPE, 63, 0, 0, 0, HA_NO_SORT, HA_FT_WLEN, 0, 0, NULL
- }
+ 0, /* charset */
+ HA_FT_WLEN, /* start */
+ 0, /* null_pos */
+ 0, /* Bit pos */
+ HA_VAR_LENGTH_PART | HA_PACK_KEY, /* flag */
+ HA_FT_MAXBYTELEN, /* length */
+ HA_KEYTYPE_VARTEXT2, /* type */
+ 63, /* language (will be overwritten) */
+ 0, /* null_bit */
+ 2, 0, 0 /* bit_start, bit_end, bit_length */
+},
+{
+ /*
+ Note, this (and the last HA_KEYTYPE_END) segment should NOT
+ be packed in any way, otherwise w_search() won't be able to
+ update key entry 'in vivo'
+ */
+ 0, 0, 0, 0, HA_NO_SORT, HA_FT_WLEN, HA_FT_WTYPE, 63, 0, 0, 0, 0
+}
};
const struct _ft_vft _ft_vft_nlq = {
diff --git a/myisam/ft_stopwords.c b/myisam/ft_stopwords.c
index a4bce6ad4e8..ab51afb0e82 100644
--- a/myisam/ft_stopwords.c
+++ b/myisam/ft_stopwords.c
@@ -81,7 +81,7 @@ int ft_init_stopwords()
goto err0;
len=my_read(fd, buffer, len, MYF(MY_WME));
end=start+len;
- while (ft_simple_get_word(default_charset_info, &start, end, &w))
+ while (ft_simple_get_word(default_charset_info, &start, end, &w, TRUE))
{
if (ft_add_stopword(my_strdup_with_length(w.pos, w.len, MYF(0))))
goto err1;
diff --git a/myisam/ft_test1.c b/myisam/ft_test1.c
index f4884f8ca39..14be9aa1e8c 100644
--- a/myisam/ft_test1.c
+++ b/myisam/ft_test1.c
@@ -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: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
diff --git a/myisam/ft_update.c b/myisam/ft_update.c
index beccc062270..b8cd925bf4f 100644
--- a/myisam/ft_update.c
+++ b/myisam/ft_update.c
@@ -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)
+ 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);
diff --git a/myisam/ftdefs.h b/myisam/ftdefs.h
index ddb9fbfead2..91c679a1e58 100644
--- a/myisam/ftdefs.h
+++ b/myisam/ftdefs.h
@@ -112,7 +112,8 @@ int is_stopword(char *word, uint len);
uint _ft_make_key(MI_INFO *, uint , byte *, FT_WORD *, my_off_t);
byte ft_get_word(CHARSET_INFO *, byte **, byte *, FT_WORD *, FTB_PARAM *);
-byte ft_simple_get_word(CHARSET_INFO *, byte **, byte *, FT_WORD *);
+byte ft_simple_get_word(CHARSET_INFO *, byte **, const byte *,
+ FT_WORD *, my_bool);
typedef struct _st_ft_seg_iterator {
uint num, len;
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index f710d3a8454..2949b39183d 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -281,7 +281,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,
@@ -2043,7 +2044,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
sort_param.key_length+=keyseg[i].length;
if (keyseg[i].flag & HA_SPACE_PACK)
sort_param.key_length+=get_pack_length(keyseg[i].length);
- if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
sort_param.key_length+=2 + test(keyseg[i].length >= 127);
if (keyseg[i].flag & HA_NULL_PART)
sort_param.key_length++;
@@ -2452,7 +2453,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
sort_param[i].key_length+=keyseg->length;
if (keyseg->flag & HA_SPACE_PACK)
sort_param[i].key_length+=get_pack_length(keyseg->length);
- if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
sort_param[i].key_length+=2 + test(keyseg->length >= 127);
if (keyseg->flag & HA_NULL_PART)
sort_param[i].key_length++;
diff --git a/myisam/mi_checksum.c b/myisam/mi_checksum.c
index 95338434211..33a51068fb0 100644
--- a/myisam/mi_checksum.c
+++ b/myisam/mi_checksum.c
@@ -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:
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index d363f3d5b67..8635d6bcf36 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -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;
@@ -223,7 +220,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;
@@ -264,7 +261,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;
@@ -279,8 +277,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
goto err;
#endif /*HAVE_SPATIAL*/
}
- else
- if (keydef->flag & HA_FULLTEXT)
+ else if (keydef->flag & HA_FULLTEXT)
{
keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
@@ -289,11 +286,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++;
@@ -314,7 +322,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Only use HA_PACK_KEY when first segment is a variable length key */
if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
- HA_VAR_LENGTH)))
+ HA_VAR_LENGTH_PART)))
{
/* pack relative to previous key */
keydef->flag&= ~HA_PACK_KEY;
@@ -348,12 +356,27 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
case HA_KEYTYPE_UINT24:
case HA_KEYTYPE_INT8:
keyseg->flag|= HA_SWAP_KEY;
- /* fall through */
+ break;
+ 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;
}
if (keyseg->flag & HA_SPACE_PACK)
{
+ DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART));
keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
length++; /* At least one length byte */
@@ -364,8 +387,10 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
length+=2;
}
}
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+ 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 */
@@ -620,10 +645,12 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
{
HA_KEYSEG sseg;
sseg.type=SPTYPE;
- sseg.language= 7;
+ sseg.language= 7; /* Binary */
sseg.null_bit=0;
sseg.bit_start=0;
sseg.bit_end=0;
+ sseg.bit_length= 0;
+ sseg.bit_pos= 0;
sseg.length=SPLEN;
sseg.null_pos=0;
sseg.start=j*SPLEN;
@@ -656,11 +683,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;
}
}
diff --git a/myisam/mi_dbug.c b/myisam/mi_dbug.c
index 02d1c7d05d6..e782d21afe7 100644
--- a/myisam/mi_dbug.c
+++ b/myisam/mi_dbug.c
@@ -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);
diff --git a/myisam/mi_delete.c b/myisam/mi_delete.c
index b964cb35dd8..cc4a17182f7 100644
--- a/myisam/mi_delete.c
+++ b/myisam/mi_delete.c
@@ -45,6 +45,12 @@ int mi_delete(MI_INFO *info,const byte *record)
/* Test if record is in datafile */
+ DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
+ mi_print_error(info->s, HA_ERR_CRASHED);
+ DBUG_RETURN(my_errno= HA_ERR_CRASHED););
+ DBUG_EXECUTE_IF("my_error_test_undefined_error",
+ mi_print_error(info->s, INT_MAX);
+ DBUG_RETURN(my_errno= INT_MAX););
if (!(info->update & HA_STATE_AKTIV))
{
DBUG_RETURN(my_errno=HA_ERR_KEY_NOT_FOUND); /* No database read */
@@ -109,13 +115,19 @@ err:
mi_sizestore(lastpos,info->lastpos);
myisam_log_command(MI_LOG_DELETE,info,(byte*) lastpos, sizeof(lastpos),0);
if (save_errno != HA_ERR_RECORD_CHANGED)
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* mark table crashed */
+ }
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
info->update|=HA_STATE_WRITTEN; /* Buffer changed */
allow_break(); /* Allow SIGHUP & SIGINT */
my_errno=save_errno;
if (save_errno == HA_ERR_KEY_NOT_FOUND)
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
+ }
DBUG_RETURN(my_errno);
} /* mi_delete */
@@ -142,6 +154,7 @@ static int _mi_ck_real_delete(register MI_INFO *info, MI_KEYDEF *keyinfo,
if ((old_root=*root) == HA_OFFSET_ERROR)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
DBUG_RETURN(my_errno=HA_ERR_CRASHED);
}
if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->block_length+
@@ -253,7 +266,12 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
my_off_t root;
uchar *kpos=keypos;
- tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey);
+ if (!(tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&kpos,lastkey)))
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
+ my_errno= HA_ERR_CRASHED;
+ DBUG_RETURN(-1);
+ }
root=_mi_dpos(info,nod_flag,kpos);
if (subkeys == -1)
{
@@ -302,6 +320,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (!nod_flag)
{
DBUG_PRINT("error",("Didn't find key"));
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED; /* This should newer happend */
goto err;
}
@@ -313,13 +332,10 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{ /* Found key */
uint tmp;
length=mi_getint(anc_buff);
- tmp=remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length,
- &next_block);
- if (tmp == 0)
- {
- DBUG_PRINT("exit",("Return: %d",0));
- DBUG_RETURN(0);
- }
+ if (!(tmp= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length,
+ &next_block)))
+ goto err;
+
length-= tmp;
mi_putint(anc_buff,length,nod_flag);
@@ -368,6 +384,7 @@ static int d_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
my_afree((byte*) leaf_buff);
DBUG_PRINT("exit",("Return: %d",ret_value));
DBUG_RETURN(ret_value);
+
err:
my_afree((byte*) leaf_buff);
DBUG_PRINT("exit",("Error: %d",my_errno));
@@ -559,10 +576,10 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
/* remove key from anc_buff */
- s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
- anc_buff+anc_length,(my_off_t *) 0);
- if (!s_length)
+ if (!(s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
+ anc_buff+anc_length,(my_off_t *) 0)))
goto err;
+
anc_length-=s_length;
mi_putint(anc_buff,anc_length,key_reflength);
@@ -668,10 +685,10 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
mi_putint(buff,buff_length,nod_flag);
/* remove key from anc_buff */
- s_length=remove_key(keyinfo,key_reflength,keypos,anc_key,
- anc_buff+anc_length,(my_off_t *) 0);
- if (!s_length)
+ if (!(s_length= remove_key(keyinfo,key_reflength,keypos,anc_key,
+ anc_buff+anc_length,(my_off_t *) 0)))
goto err;
+
anc_length-=s_length;
mi_putint(anc_buff,anc_length,key_reflength);
@@ -731,6 +748,7 @@ static int underflow(register MI_INFO *info, register MI_KEYDEF *keyinfo,
if (_mi_write_keypage(info,keyinfo,next_page,DFLT_INIT_HITS,buff))
goto err;
DBUG_RETURN(anc_length <= (uint) keyinfo->block_length/2);
+
err:
DBUG_RETURN(-1);
} /* underflow */
@@ -768,6 +786,7 @@ static uint remove_key(MI_KEYDEF *keyinfo, uint nod_flag,
/* Calculate length of key */
if (!(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey))
DBUG_RETURN(0); /* Error */
+
if (next_block && nod_flag)
*next_block= _mi_kpos(nod_flag,keypos);
s_length=(int) (keypos-start);
diff --git a/myisam/mi_dynrec.c b/myisam/mi_dynrec.c
index 43783ca2d36..3a4dafade23 100644
--- a/myisam/mi_dynrec.c
+++ b/myisam/mi_dynrec.c
@@ -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))))
@@ -944,13 +963,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)
{
@@ -1018,15 +1051,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);
diff --git a/myisam/mi_extra.c b/myisam/mi_extra.c
index 4b011ca424f..ba32bb9115a 100644
--- a/myisam/mi_extra.c
+++ b/myisam/mi_extra.c
@@ -15,7 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "myisamdef.h"
-#ifdef HAVE_MMAP
+#ifdef HAVE_SYS_MMAN_H
#include <sys/mman.h>
#endif
@@ -186,7 +186,10 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (info->opt_flag & WRITE_CACHE_USED)
{
if ((error=flush_io_cache(&info->rec_cache)))
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Fatal error found */
+ }
}
break;
case HA_EXTRA_NO_READCHECK:
@@ -285,6 +288,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
{
error=my_errno;
share->changed=1;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Fatal error found */
}
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
@@ -339,6 +343,7 @@ int mi_extra(MI_INFO *info, enum ha_extra_function function, void *extra_arg)
if (error)
{
share->changed=1;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Fatal error found */
}
}
diff --git a/myisam/mi_info.c b/myisam/mi_info.c
index cf63ef63618..bdece9c2ee3 100644
--- a/myisam/mi_info.c
+++ b/myisam/mi_info.c
@@ -105,3 +105,36 @@ int mi_status(MI_INFO *info, register MI_ISAMINFO *x, uint flag)
}
DBUG_RETURN(0);
}
+
+
+/*
+ Write a message to the error log.
+
+ SYNOPSIS
+ mi_report_error()
+ file_name Name of table file (e.g. index_file_name).
+ errcode Error number.
+
+ DESCRIPTION
+ This function supplies my_error() with a table name. Most error
+ messages need one. Since string arguments in error messages are limited
+ to 64 characters by convention, we ensure that in case of truncation,
+ that the end of the index file path is in the message. This contains
+ the most valuable information (the table name and the database name).
+
+ RETURN
+ void
+*/
+
+void mi_report_error(int errcode, const char *file_name)
+{
+ size_t lgt;
+ DBUG_ENTER("mi_report_error");
+ DBUG_PRINT("enter",("errcode %d, table '%s'", errcode, file_name));
+
+ if ((lgt= strlen(file_name)) > 64)
+ file_name+= lgt - 64;
+ my_error(errcode, MYF(ME_NOREFRESH), file_name);
+ DBUG_VOID_RETURN;
+}
+
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 3545756779f..ab5ddd3a378 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -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)
@@ -82,6 +92,19 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
length);
pos= (byte*) record+keyseg->start;
+ if (type == HA_KEYTYPE_BIT)
+ {
+ if (keyseg->bit_length)
+ {
+ uchar bits= get_rec_bits((uchar*) record + keyseg->bit_pos,
+ keyseg->bit_start, keyseg->bit_length);
+ *key++= bits;
+ length--;
+ }
+ memcpy((byte*) key, pos, length);
+ key+= length;
+ continue;
+ }
if (keyseg->flag & HA_SPACE_PACK)
{
end=pos+length;
@@ -102,10 +125,12 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
key+=char_length;
continue;
}
- if (keyseg->flag & HA_VAR_LENGTH)
+ 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);
@@ -161,7 +186,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
FIX_LENGTH(cs, pos, length, char_length);
memcpy((byte*) key, pos, char_length);
if (length > char_length)
- cs->cset->fill(cs, key+char_length, length-char_length, ' ');
+ cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
key+= length;
}
_mi_dpointer(info,key,filepos);
@@ -216,7 +241,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
if (!(*key++= (char) 1-*old++)) /* Copy null marker */
{
k_length-=length;
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
k_length-=2; /* Skip length */
continue; /* Found NULL */
}
@@ -244,7 +269,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
key+= char_length;
continue;
}
- else if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+ else if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
/* Length of key-part used with mi_rkey() always 2 */
uint tmp_length=uint2korr(pos);
@@ -271,7 +296,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
FIX_LENGTH(cs, pos, length, char_length);
memcpy((byte*) key, pos, char_length);
if (length > char_length)
- cs->cset->fill(cs,key+char_length, length-char_length, ' ');
+ cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
key+= length;
k_length-=length;
}
@@ -333,6 +358,26 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
}
record[keyseg->null_pos]&= ~keyseg->null_bit;
}
+ if (keyseg->type == HA_KEYTYPE_BIT)
+ {
+ uint length= keyseg->length;
+
+ if (keyseg->bit_length)
+ {
+ uchar bits= *key++;
+ set_rec_bits(bits, record + keyseg->bit_pos, keyseg->bit_start,
+ keyseg->bit_length);
+ length--;
+ }
+ else
+ {
+ clr_rec_bits(record + keyseg->bit_pos, keyseg->bit_start,
+ keyseg->bit_length);
+ }
+ memcpy(record + keyseg->start, (byte*) key, length);
+ key+= length;
+ continue;
+ }
if (keyseg->flag & HA_SPACE_PACK)
{
uint length;
@@ -356,7 +401,7 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
continue;
}
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint length;
get_key_length(length,key);
@@ -364,7 +409,13 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
if (length > keyseg->length || key+length > key_end)
goto err;
#endif
- memcpy(record+keyseg->start,(byte*) key, length);
+ /* Store key 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 + keyseg->bit_start, (byte*) key, length);
key+= length;
}
else if (keyseg->flag & HA_BLOB_PART)
@@ -426,6 +477,7 @@ int _mi_read_key_record(MI_INFO *info, my_off_t filepos, byte *buf)
{ /* Read only key */
if (_mi_put_key_in_record(info,(uint) info->lastinx,buf))
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return -1;
}
diff --git a/myisam/mi_keycache.c b/myisam/mi_keycache.c
index 99a2fd6db15..fb13f3703a2 100644
--- a/myisam/mi_keycache.c
+++ b/myisam/mi_keycache.c
@@ -79,6 +79,7 @@ int mi_assign_to_key_cache(MI_INFO *info,
if (flush_key_blocks(share->key_cache, share->kfile, FLUSH_RELEASE))
{
error= my_errno;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Mark that table must be checked */
}
diff --git a/myisam/mi_locking.c b/myisam/mi_locking.c
index 66950f62321..789d74680ef 100644
--- a/myisam/mi_locking.c
+++ b/myisam/mi_locking.c
@@ -66,6 +66,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
share->kfile,FLUSH_KEEP))
{
error=my_errno;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info); /* Mark that table must be checked */
}
if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
@@ -73,6 +74,7 @@ int mi_lock_database(MI_INFO *info, int lock_type)
if (end_io_cache(&info->rec_cache))
{
error=my_errno;
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
}
@@ -98,7 +100,10 @@ int mi_lock_database(MI_INFO *info, int lock_type)
else
share->not_flushed=1;
if (error)
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
+ }
}
if (info->lock_type != F_EXTRA_LCK)
{
@@ -285,6 +290,7 @@ void mi_update_status(void* param)
{
if (end_io_cache(&info->rec_cache))
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
}
info->opt_flag&= ~WRITE_CACHE_USED;
diff --git a/myisam/mi_open.c b/myisam/mi_open.c
index 2c85a03c6f4..d65a46a92fb 100644
--- a/myisam/mi_open.c
+++ b/myisam/mi_open.c
@@ -106,6 +106,12 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
share_buff.state.key_del=key_del;
share_buff.key_cache= multi_key_cache_search(name_buff, strlen(name_buff));
+ DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_open",
+ if (strstr(name, "/t1"))
+ {
+ my_errno= HA_ERR_CRASHED;
+ goto err;
+ });
if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
{
if ((errno != EROFS && errno != EACCES) ||
@@ -302,6 +308,7 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
HA_KEYSEG *pos=share->keyparts;
for (i=0 ; i < keys ; i++)
{
+ share->keyinfo[i].share= share;
disk_pos=mi_keydef_read(disk_pos, &share->keyinfo[i]);
disk_pos_assert(disk_pos + share->keyinfo[i].keysegs * HA_KEYSEG_SIZE,
end_pos);
@@ -313,7 +320,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;
@@ -388,7 +397,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;
@@ -596,6 +607,10 @@ MI_INFO *mi_open(const char *name, int mode, uint open_flags)
err:
save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
+ if ((save_errno == HA_ERR_CRASHED) ||
+ (save_errno == HA_ERR_CRASHED_ON_USAGE) ||
+ (save_errno == HA_ERR_CRASHED_ON_REPAIR))
+ mi_report_error(save_errno, name);
switch (errpos) {
case 6:
my_free((gptr) m_info,MYF(0));
@@ -1042,18 +1057,21 @@ int mi_keyseg_write(File file, const HA_KEYSEG *keyseg)
{
uchar buff[HA_KEYSEG_SIZE];
uchar *ptr=buff;
-
- *ptr++ =keyseg->type;
- *ptr++ =keyseg->language;
- *ptr++ =keyseg->null_bit;
- *ptr++ =keyseg->bit_start;
- *ptr++ =keyseg->bit_end;
- *ptr++ =0; /* Not used */
+ ulong pos;
+
+ *ptr++= keyseg->type;
+ *ptr++= keyseg->language;
+ *ptr++= keyseg->null_bit;
+ *ptr++= keyseg->bit_start;
+ *ptr++= keyseg->bit_end;
+ *ptr++= keyseg->bit_length;
mi_int2store(ptr,keyseg->flag); ptr+=2;
mi_int2store(ptr,keyseg->length); ptr+=2;
mi_int4store(ptr,keyseg->start); ptr+=4;
- mi_int4store(ptr,keyseg->null_pos); ptr+=4;
-
+ pos= keyseg->null_bit ? keyseg->null_pos : keyseg->bit_pos;
+ mi_int4store(ptr, pos);
+ ptr+=4;
+
return my_write(file,(char*) buff, (uint) (ptr-buff), MYF(MY_NABP));
}
@@ -1065,12 +1083,19 @@ char *mi_keyseg_read(char *ptr, HA_KEYSEG *keyseg)
keyseg->null_bit = *ptr++;
keyseg->bit_start = *ptr++;
keyseg->bit_end = *ptr++;
- ptr++;
+ keyseg->bit_length = *ptr++;
keyseg->flag = mi_uint2korr(ptr); ptr +=2;
keyseg->length = mi_uint2korr(ptr); ptr +=2;
keyseg->start = mi_uint4korr(ptr); ptr +=4;
keyseg->null_pos = mi_uint4korr(ptr); ptr +=4;
keyseg->charset=0; /* Will be filled in later */
+ if (keyseg->null_bit)
+ keyseg->bit_pos= (uint16)(keyseg->null_pos + (keyseg->null_bit == 7));
+ else
+ {
+ keyseg->bit_pos= (uint16)keyseg->null_pos;
+ keyseg->null_pos= 0;
+ }
return ptr;
}
@@ -1210,7 +1235,10 @@ int mi_enable_indexes(MI_INFO *info)
if (share->state.state.data_file_length ||
(share->state.state.key_file_length != share->base.keystart))
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
error= HA_ERR_CRASHED;
+ }
else
share->state.key_map= ((ulonglong) 1L << share->base.keys) - 1;
return error;
diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c
index 1a71d43a7f1..4b512dd89dd 100644
--- a/myisam/mi_packrec.c
+++ b/myisam/mi_packrec.c
@@ -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);
@@ -515,14 +517,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)
@@ -766,7 +770,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))
@@ -1162,11 +1181,12 @@ static uint max_bit(register uint value)
/*****************************************************************************
Some redefined functions to handle files when we are using memmap
*****************************************************************************/
+#ifdef HAVE_SYS_MMAN_H
+#include <sys/mman.h>
+#endif
#ifdef HAVE_MMAP
-#include <sys/mman.h>
-
static int _mi_read_mempack_record(MI_INFO *info,my_off_t filepos,byte *buf);
static int _mi_read_rnd_mempack_record(MI_INFO*, byte *,my_off_t, my_bool);
@@ -1192,7 +1212,7 @@ my_bool _mi_memmap_file(MI_INFO *info)
DBUG_RETURN(0);
}
file_map=(byte*)
- mmap(0,share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN,PROT_READ,
+ my_mmap(0,(size_t)(share->state.state.data_file_length+MEMMAP_EXTRA_MARGIN),PROT_READ,
MAP_SHARED | MAP_NORESERVE,info->dfile,0L);
if (file_map == (byte*) MAP_FAILED)
{
@@ -1211,7 +1231,7 @@ my_bool _mi_memmap_file(MI_INFO *info)
void _mi_unmap_file(MI_INFO *info)
{
- VOID(munmap((caddr_t) info->s->file_map,
+ VOID(my_munmap(info->s->file_map,
(size_t) info->s->state.state.data_file_length+
MEMMAP_EXTRA_MARGIN));
}
diff --git a/myisam/mi_page.c b/myisam/mi_page.c
index 16713c87e10..5240c063fba 100644
--- a/myisam/mi_page.c
+++ b/myisam/mi_page.c
@@ -40,6 +40,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
{
DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno));
info->last_keypage=HA_OFFSET_ERROR;
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
@@ -51,6 +52,7 @@ uchar *_mi_fetch_keypage(register MI_INFO *info, MI_KEYDEF *keyinfo,
(ulong) page, page_size));
DBUG_DUMP("page", (char*) tmp, keyinfo->block_length);
info->last_keypage = HA_OFFSET_ERROR;
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno = HA_ERR_CRASHED;
tmp = 0;
}
diff --git a/myisam/mi_range.c b/myisam/mi_range.c
index 1e0fd42334e..e78f3b11625 100644
--- a/myisam/mi_range.c
+++ b/myisam/mi_range.c
@@ -172,9 +172,9 @@ static double _mi_search_pos(register MI_INFO *info,
if (flag == MI_FOUND_WRONG_KEY)
DBUG_RETURN(-1); /* error */
/*
- ** Didn't found match. keypos points at next (bigger) key
- * Try to find a smaller, better matching key.
- ** Matches keynr + [0-1]
+ Didn't found match. keypos points at next (bigger) key
+ Try to find a smaller, better matching key.
+ Matches keynr + [0-1]
*/
if (flag > 0 && ! nod_flag)
offset= 1.0;
@@ -185,8 +185,8 @@ static double _mi_search_pos(register MI_INFO *info,
else
{
/*
- ** Found match. Keypos points at the start of the found key
- ** Matches keynr+1
+ Found match. Keypos points at the start of the found key
+ Matches keynr+1
*/
offset=1.0; /* Matches keynr+1 */
if ((nextflag & SEARCH_FIND) && nod_flag &&
@@ -194,8 +194,8 @@ static double _mi_search_pos(register MI_INFO *info,
key_len != USE_WHOLE_KEY))
{
/*
- ** There may be identical keys in the tree. Try to match on of those.
- ** Matches keynr + [0-1]
+ There may be identical keys in the tree. Try to match on of those.
+ Matches keynr + [0-1]
*/
if ((offset=_mi_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
_mi_kpos(nod_flag,keypos))) < 0)
@@ -213,7 +213,8 @@ err:
/* Get keynummer of current key and max number of keys in nod */
-static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, uchar *keypos, uint *ret_max_key)
+static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
+ uchar *keypos, uint *ret_max_key)
{
uint nod_flag,keynr,max_key;
uchar t_buff[MI_MAX_KEY_BUFF],*end;
@@ -222,7 +223,7 @@ static uint _mi_keynr(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page, u
nod_flag=mi_test_if_nod(page);
page+=2+nod_flag;
- if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY| HA_BINARY_PACK_KEY)))
+ if (!(keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
{
*ret_max_key= (uint) (end-page)/(keyinfo->keylength+nod_flag);
return (uint) (keypos-page)/(keyinfo->keylength+nod_flag);
diff --git a/myisam/mi_rkey.c b/myisam/mi_rkey.c
index 12db00337ee..635a7eb2c48 100644
--- a/myisam/mi_rkey.c
+++ b/myisam/mi_rkey.c
@@ -78,6 +78,7 @@ int mi_rkey(MI_INFO *info, byte *buf, int inx, const byte *key, uint key_len,
case HA_KEY_ALG_RTREE:
if (rtree_find_first(info,inx,key_buff,use_key_length,nextflag) < 0)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
goto err;
}
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index 390e32b679d..c669a8be8f8 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -159,6 +159,7 @@ int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
DBUG_PRINT("exit",("found key at %lu",(ulong) info->lastpos));
DBUG_RETURN(0);
+
err:
DBUG_PRINT("exit",("Error: %d",my_errno));
info->lastpos= HA_OFFSET_ERROR;
@@ -256,6 +257,7 @@ int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
if (length == 0 || page > end)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p",
length, page, end));
@@ -386,7 +388,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
if (!(*from++))
continue;
}
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
get_key_length(l,from);
}
@@ -402,6 +404,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
if (page > end)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_PRINT("error",("Found wrong key: length: %u page: %p end: %p",
length, page, end));
@@ -447,7 +450,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
{
@@ -781,6 +785,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
{
if (length > (uint) keyseg->length)
{
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Error */
}
@@ -796,6 +801,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
("Found too long null packed key: %u of %u at %p",
length, keyseg->length, *page_pos));
DBUG_DUMP("key",(char*) *page_pos,16);
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0;
}
@@ -852,6 +858,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
DBUG_PRINT("error",("Found too long packed key: %u of %u at %p",
length, keyseg->length, *page_pos));
DBUG_DUMP("key",(char*) *page_pos,16);
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Error */
}
@@ -865,7 +872,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
continue;
}
if (keyseg->flag &
- (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
uchar *tmp=page;
get_key_length(length,tmp);
@@ -907,6 +914,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
DBUG_PRINT("error",("Found too long binary packed key: %u of %u at %p",
length, keyinfo->maxlength, *page_pos));
DBUG_DUMP("key",(char*) *page_pos,16);
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Wrong key */
}
@@ -930,7 +938,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
if (!(*key++ = *from++))
continue; /* Null part */
}
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
/* Get length of dynamic length key part */
if (from == from_end) { from=page; from_end=page_end; }
@@ -968,6 +976,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
if (from_end != page_end)
{
DBUG_PRINT("error",("Error when unpacking key"));
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
return 0; /* Error */
}
@@ -1002,6 +1011,7 @@ uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
if (*return_key_length == 0)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
@@ -1039,6 +1049,7 @@ static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,key);
if (*return_key_length == 0)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(1);
}
@@ -1079,6 +1090,7 @@ uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
if (*return_key_length == 0)
{
DBUG_PRINT("error",("Couldn't find last key: page: %p", page));
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
@@ -1105,7 +1117,7 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
if (keyseg->flag & HA_NULL_PART)
if (!*key++)
continue;
- if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint length;
get_key_length(length,key);
@@ -1137,7 +1149,7 @@ uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
if (keyseg->flag & HA_NULL_PART)
if (!*key++)
continue;
- if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint length;
get_key_length(length,key);
@@ -1269,8 +1281,10 @@ int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
page=info->buff+2+nod_flag;
} while ((pos=_mi_kpos(nod_flag,page)) != HA_OFFSET_ERROR);
- info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
- info->lastkey);
+ if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
+ info->lastkey)))
+ DBUG_RETURN(-1); /* Crashed */
+
info->int_keypos=page; info->int_maxpos=info->buff+mi_getint(info->buff)-1;
info->int_nod_flag=nod_flag;
info->int_keytree_version=keyinfo->version;
@@ -1405,7 +1419,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;
diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c
index 77c4d3dfbad..aa6cd98ac8e 100644
--- a/myisam/mi_test1.c
+++ b/myisam/mi_test1.c
@@ -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;
@@ -134,7 +137,7 @@ static int run_test(const char *filename)
uniqueseg[1].flag|= HA_BLOB_PART;
}
else if (extra_field == FIELD_VARCHAR)
- uniqueseg[1].flag|= HA_VAR_LENGTH;
+ uniqueseg[1].flag|= HA_VAR_LENGTH_PART;
}
else
uniques=0;
@@ -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');
@@ -372,7 +376,7 @@ static void create_key(char *key,uint rownr)
}
*key++=0;
}
- if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint tmp;
create_key_part(key+2,rownr);
@@ -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,12 +534,12 @@ 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},
{"key_blob", 'b', "Undocumented",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_cache", 'K', "Undocumented", (gptr*) &key_cacheing,
(gptr*) &key_cacheing, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_length", 'k', "Undocumented", (gptr*) &key_length, (gptr*) &key_length,
@@ -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;
- pack_seg|= HA_VAR_LENGTH;
+ 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':
diff --git a/myisam/mi_test3.c b/myisam/mi_test3.c
index 27d23317b5c..be4277cc65c 100644
--- a/myisam/mi_test3.c
+++ b/myisam/mi_test3.c
@@ -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;
diff --git a/myisam/mi_test_all.res b/myisam/mi_test_all.res
index 94355bf1aa2..16b517d3f76 100644
--- a/myisam/mi_test_all.res
+++ b/myisam/mi_test_all.res
@@ -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
diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c
index ad685f4cbdc..f2d5f01be25 100644
--- a/myisam/mi_unique.c
+++ b/myisam/mi_unique.c
@@ -93,10 +93,12 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
}
}
pos= record+keyseg->start;
- if (keyseg->flag & HA_VAR_LENGTH)
+ 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,
@@ -136,7 +139,8 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
{
enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
- uint length=keyseg->length;
+ uint a_length, b_length;
+ a_length= b_length= keyseg->length;
/* If part is NULL it's regarded as different */
if (keyseg->null_bit)
@@ -154,43 +158,59 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
}
pos_a= a+keyseg->start;
pos_b= b+keyseg->start;
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
- uint tmp_length=uint2korr(pos_a);
- if (tmp_length != uint2korr(pos_b))
- return 1;
- pos_a+=2; /* Skip VARCHAR length */
- pos_b+=2;
- set_if_smaller(length,tmp_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)
{
- /* Only compare 'length' characters if length<> 0 */
- uint a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
- uint b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
+ /* Only compare 'length' characters if length != 0 */
+ a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
+ b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
/* Check that a and b are of equal length */
- if (length && a_length > length)
- a_length=length;
- if (!length || length > b_length)
- length=b_length;
- if (length != a_length)
- return 1;
- /* Both strings are at least 'length' long */
+ if (keyseg->length)
+ {
+ /*
+ This is used in some cases when we are not interested in comparing
+ the whole length of the blob.
+ */
+ set_if_smaller(a_length, keyseg->length);
+ set_if_smaller(b_length, keyseg->length);
+ }
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, length,
- (uchar *) pos_b, length, 0, 0))
- return 1;
+ if (mi_compare_text(keyseg->charset, (uchar *) pos_a, a_length,
+ (uchar *) pos_b, b_length, 0, 1))
+ return 1;
}
else
{
- end= pos_a+length;
+ if (a_length != b_length)
+ return 1;
+ end= pos_a+a_length;
while (pos_a != end)
+ {
if (*pos_a++ != *pos_b++)
return 1;
+ }
}
}
return 0;
diff --git a/myisam/mi_update.c b/myisam/mi_update.c
index f62be133ed9..cda60694008 100644
--- a/myisam/mi_update.c
+++ b/myisam/mi_update.c
@@ -34,6 +34,9 @@ int mi_update(register MI_INFO *info, const byte *oldrec, byte *newrec)
LINT_INIT(changed);
LINT_INIT(old_checksum);
+ DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
+ mi_print_error(info->s, HA_ERR_CRASHED);
+ DBUG_RETURN(my_errno= HA_ERR_CRASHED););
if (!(info->update & HA_STATE_AKTIV))
{
DBUG_RETURN(my_errno=HA_ERR_KEY_NOT_FOUND);
@@ -205,7 +208,10 @@ err:
} while (i-- != 0);
}
else
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
+ }
info->update= (HA_STATE_CHANGED | HA_STATE_AKTIV | HA_STATE_ROW_CHANGED |
key_changed);
@@ -214,6 +220,9 @@ err:
VOID(_mi_writeinfo(info,WRITEINFO_UPDATE_KEYFILE));
allow_break(); /* Allow SIGHUP & SIGINT */
if (save_errno == HA_ERR_KEY_NOT_FOUND)
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
save_errno=HA_ERR_CRASHED;
+ }
DBUG_RETURN(my_errno=save_errno);
} /* mi_update */
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index cd9e73fba22..5d7e245c58f 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -52,6 +52,9 @@ int mi_write(MI_INFO *info, byte *record)
DBUG_ENTER("mi_write");
DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile));
+ DBUG_EXECUTE_IF("myisam_pretend_crashed_table_on_usage",
+ mi_print_error(info->s, HA_ERR_CRASHED);
+ DBUG_RETURN(my_errno= HA_ERR_CRASHED););
if (share->options & HA_OPTION_READ_ONLY_DATA)
{
DBUG_RETURN(my_errno=EACCES);
@@ -203,7 +206,10 @@ err:
}
}
else
+ {
+ mi_print_error(info->s, HA_ERR_CRASHED);
mi_mark_crashed(info);
+ }
info->update= (HA_STATE_CHANGED | HA_STATE_WRITTEN | HA_STATE_ROW_CHANGED);
my_errno=save_errno;
err2:
@@ -249,7 +255,7 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
comp_flag=SEARCH_BIGGER; /* Put after same key */
else if (keyinfo->flag & (HA_NOSAME|HA_FULLTEXT))
{
- comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
+ comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No duplicates */
if (keyinfo->flag & HA_NULL_ARE_EQUAL)
comp_flag|= SEARCH_NULL_ARE_EQUAL;
}
@@ -348,6 +354,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
dupp_key_pos=_mi_dpos(info,0,keybuff+tmp_key_length);
else
dupp_key_pos= HA_OFFSET_ERROR;
+
if (keyinfo->flag & HA_FULLTEXT)
{
uint off;
@@ -478,6 +485,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
if (t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
@@ -487,6 +495,7 @@ int _mi_insert(register MI_INFO *info, register MI_KEYDEF *keyinfo,
{
if (-t_length >= keyinfo->maxlength*2+MAX_POINTER_LENGTH)
{
+ mi_print_error(info->s, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(-1);
}
@@ -582,6 +591,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo,
&after_key);
if (!key_pos)
DBUG_RETURN(-1);
+
length=(uint) (key_pos-buff);
a_length=mi_getint(buff);
mi_putint(buff,length,nod_flag);
@@ -602,6 +612,7 @@ int _mi_split_page(register MI_INFO *info, register MI_KEYDEF *keyinfo,
/* Store new page */
if (!(*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff))
DBUG_RETURN(-1);
+
t_length=(*keyinfo->pack_key)(keyinfo,nod_flag,(uchar *) 0,
(uchar*) 0, (uchar*) 0,
key_buff, &s_temp);
@@ -708,6 +719,7 @@ static uchar *_mi_find_last_pos(MI_KEYDEF *keyinfo, uchar *page,
memcpy(key, key_buff, length); /* previous key */
if (!(length=(*keyinfo->get_key)(keyinfo,0,&page,key_buff)))
{
+ mi_print_error(keyinfo->share, HA_ERR_CRASHED);
my_errno=HA_ERR_CRASHED;
DBUG_RETURN(0);
}
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index d53e589e205..519e123e9da 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -50,7 +50,7 @@ static int stopwords_inited= 0;
static MY_TMPDIR myisamchk_tmpdir;
static const char *type_names[]=
-{ "?","char","binary", "short", "long", "float",
+{ "impossible","char","binary", "short", "long", "float",
"double","number","unsigned short",
"unsigned long","longlong","ulonglong","int24",
"uint24","int8","varchar", "varbin","?",
@@ -1699,11 +1699,11 @@ err:
sorting
*/
-static my_bool not_killed= 0;
+static int not_killed= 0;
-volatile my_bool *killed_ptr(MI_CHECK *param __attribute__((unused)))
+volatile int *killed_ptr(MI_CHECK *param __attribute__((unused)))
{
- return &not_killed; /* always NULL */
+ return &not_killed; /* always NULL */
}
/* print warnings and errors */
diff --git a/myisam/myisamdef.h b/myisam/myisamdef.h
index a41bcf5449b..a2d3dedf6df 100644
--- a/myisam/myisamdef.h
+++ b/myisam/myisamdef.h
@@ -356,6 +356,8 @@ typedef struct st_mi_sort_param
#define mi_mark_crashed_on_repair(x) { (x)->s->state.changed|=STATE_CRASHED|STATE_CRASHED_ON_REPAIR ; (x)->update|= HA_STATE_CHANGED; }
#define mi_is_crashed(x) ((x)->s->state.changed & STATE_CRASHED)
#define mi_is_crashed_on_repair(x) ((x)->s->state.changed & STATE_CRASHED_ON_REPAIR)
+#define mi_print_error(SHARE, ERRNO) \
+ mi_report_error((ERRNO), (SHARE)->index_file_name)
/* Functions to store length of space packed keys, VARCHAR or BLOB keys */
@@ -667,6 +669,7 @@ extern void _myisam_log_command(enum myisam_log_commands command,
extern void _myisam_log_record(enum myisam_log_commands command,MI_INFO *info,
const byte *record,my_off_t filepos,
int result);
+extern void mi_report_error(int errcode, const char *file_name);
extern my_bool _mi_memmap_file(MI_INFO *info);
extern void _mi_unmap_file(MI_INFO *info);
extern uint save_pack_length(byte *block_buff,ulong length);
@@ -712,7 +715,7 @@ int mi_open_keyfile(MYISAM_SHARE *share);
void mi_setup_functions(register MYISAM_SHARE *share);
/* Functions needed by mi_check */
-volatile my_bool *killed_ptr(MI_CHECK *param);
+volatile int *killed_ptr(MI_CHECK *param);
void mi_check_print_error _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_warning _VARARGS((MI_CHECK *param, const char *fmt,...));
void mi_check_print_info _VARARGS((MI_CHECK *param, const char *fmt,...));
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index 263a468d96d..352c7954d72 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -747,7 +747,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
static_row_size=1;
for (count=huff_counts ; count < end_count ; count++)
{
- if (count->field_type == FIELD_BLOB || count->field_type == FIELD_VARCHAR)
+ if (count->field_type == FIELD_BLOB ||
+ count->field_type == FIELD_VARCHAR)
{
static_row_size=0;
break;
@@ -848,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 &&
@@ -1832,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]);
}
diff --git a/myisam/sort.c b/myisam/sort.c
index 7c6efa9a05b..9d2af2e8c70 100644
--- a/myisam/sort.c
+++ b/myisam/sort.c
@@ -860,7 +860,8 @@ merge_buffers(MI_SORT_PARAM *info, uint keys, IO_CACHE *from_file,
uchar *strpos;
BUFFPEK *buffpek,**refpek;
QUEUE queue;
- volatile my_bool *killed= killed_ptr(info->sort_info->param);
+ volatile int *killed= killed_ptr(info->sort_info->param);
+
DBUG_ENTER("merge_buffers");
count=error=0;