16
16
/* key handling functions */
18
#include "myisamdef.h"
19
#include <mystrings/m_ctype.h>
20
#include <drizzled/util/test.h>
22
static bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *page,
23
unsigned char *key, unsigned char *keypos,
24
uint32_t *return_key_length);
21
static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
22
uchar *key, uchar *keypos,
23
uint *return_key_length);
57
56
int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
58
unsigned char *key, uint32_t key_len, uint32_t nextflag, register my_off_t pos)
57
uchar *key, uint key_len, uint nextflag, register my_off_t pos)
63
unsigned char *keypos,*maxpos;
64
unsigned char lastkey[MI_MAX_KEY_BUFF],*buff;
62
uchar *keypos,*maxpos;
63
uchar lastkey[MI_MAX_KEY_BUFF],*buff;
64
DBUG_ENTER("_mi_search");
65
DBUG_PRINT("enter",("pos: %lu nextflag: %u lastpos: %lu",
66
(ulong) pos, nextflag, (ulong) info->lastpos));
67
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,key_len););
66
69
if (pos == HA_OFFSET_ERROR)
68
71
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
69
72
info->lastpos= HA_OFFSET_ERROR;
70
73
if (!(nextflag & (SEARCH_SMALLER | SEARCH_BIGGER | SEARCH_LAST)))
71
return(-1); /* Not found ; return error */
72
return(1); /* Search at upper levels */
74
DBUG_RETURN(-1); /* Not found ; return error */
75
DBUG_RETURN(1); /* Search at upper levels */
75
78
if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,
76
79
test(!(nextflag & SEARCH_SAVE_BUFF)))))
81
DBUG_DUMP("page",(uchar*) buff,mi_getint(buff));
79
83
flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
80
84
&keypos,lastkey, &last_key);
81
85
if (flag == MI_FOUND_WRONG_KEY)
83
87
nod_flag=mi_test_if_nod(buff);
84
88
maxpos=buff+mi_getint(buff)-1;
88
92
if ((error=_mi_search(info,keyinfo,key,key_len,nextflag,
89
93
_mi_kpos(nod_flag,keypos))) <= 0)
94
98
if (nextflag & (SEARCH_SMALLER | SEARCH_LAST) &&
95
99
keypos == buff+2+nod_flag)
96
return(1); /* Bigger than key */
100
DBUG_RETURN(1); /* Bigger than key */
98
102
else if (nextflag & SEARCH_BIGGER && keypos >= maxpos)
99
return(1); /* Smaller than key */
103
DBUG_RETURN(1); /* Smaller than key */
107
111
if ((error=_mi_search(info,keyinfo,key,key_len,SEARCH_FIND,
108
112
_mi_kpos(nod_flag,keypos))) >= 0 ||
109
113
my_errno != HA_ERR_KEY_NOT_FOUND)
111
115
info->last_keypage= HA_OFFSET_ERROR; /* Buffer not in mem */
114
118
if (pos != info->last_keypage)
116
unsigned char *old_buff=buff;
120
uchar *old_buff=buff;
117
121
if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,
118
122
test(!(nextflag & SEARCH_SAVE_BUFF)))))
152
156
info->page_changed=0;
153
157
info->buff_used= (info->buff != buff); /* If we have to reread buff */
159
DBUG_PRINT("exit",("found key at %lu",(ulong) info->lastpos));
163
DBUG_PRINT("exit",("Error: %d",my_errno));
158
164
info->lastpos= HA_OFFSET_ERROR;
159
165
info->page_changed=1;
161
167
} /* _mi_search */
166
172
/* ret_pos point to where find or bigger key starts */
169
int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *page,
170
unsigned char *key, uint32_t key_len, uint32_t comp_flag, unsigned char **ret_pos,
171
unsigned char *buff __attribute__((unused)), bool *last_key)
175
int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
176
uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
177
uchar *buff __attribute__((unused)), my_bool *last_key)
173
179
register int start,mid,end,save_end;
175
uint32_t totlength,nod_flag,not_used[2];
181
uint totlength,nod_flag,not_used[2];
182
DBUG_ENTER("_mi_bin_search");
177
184
totlength=keyinfo->keylength+(nod_flag=mi_test_if_nod(page));
179
186
save_end=end=(int) ((mi_getint(page)-2-nod_flag)/totlength-1);
187
DBUG_PRINT("test",("mi_getint: %d end: %d",mi_getint(page),end));
180
188
page+=2+nod_flag;
182
190
while (start != end)
196
204
start++; /* point at next, bigger key */
197
205
*ret_pos=page+(uint) start*totlength;
198
206
*last_key= end == save_end;
207
DBUG_PRINT("exit",("flag: %d keypos: %d",flag,start));
200
209
} /* _mi_bin_search */
229
int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *page,
230
unsigned char *key, uint32_t key_len, uint32_t comp_flag, unsigned char **ret_pos,
231
unsigned char *buff, bool *last_key)
238
int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
239
uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
240
uchar *buff, my_bool *last_key)
234
uint32_t nod_flag,length=0,not_used[2];
235
unsigned char t_buff[MI_MAX_KEY_BUFF],*end;
243
uint nod_flag,length,not_used[2];
244
uchar t_buff[MI_MAX_KEY_BUFF],*end;
245
DBUG_ENTER("_mi_seq_search");
237
247
end= page+mi_getint(page);
238
248
nod_flag=mi_test_if_nod(page);
247
257
mi_print_error(info->s, HA_ERR_CRASHED);
248
258
my_errno=HA_ERR_CRASHED;
249
return(MI_FOUND_WRONG_KEY);
260
("Found wrong key: length: %u page: 0x%lx end: 0x%lx",
261
length, (long) page, (long) end));
262
DBUG_RETURN(MI_FOUND_WRONG_KEY);
251
264
if ((flag=ha_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag,
268
DBUG_PRINT("loop",("page: 0x%lx key: '%s' flag: %d", (long) page, t_buff,
254
271
memcpy(buff,t_buff,length);
258
275
memcpy(buff,t_buff,length); /* Result is first key */
259
276
*last_key= page == end;
277
DBUG_PRINT("exit",("flag: %d ret_pos: 0x%lx", flag, (long) *ret_pos));
261
279
} /* _mi_seq_search */
264
int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *page,
265
unsigned char *key, uint32_t key_len, uint32_t nextflag, unsigned char **ret_pos,
266
unsigned char *buff, bool *last_key)
282
int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
283
uchar *key, uint key_len, uint nextflag, uchar **ret_pos,
284
uchar *buff, my_bool *last_key)
269
287
my_flag is raw comparison result to be changed according to
271
289
flag is the value returned by ha_key_cmp and as treated as final
273
291
int flag=0, my_flag=-1;
274
uint32_t nod_flag, length=0, len, matched, cmplen, kseg_len;
275
uint32_t prefix_len=0,suffix_len;
276
int key_len_skip, seg_len_pack=0, key_len_left;
277
unsigned char *end, *kseg, *vseg;
278
unsigned char *sort_order=keyinfo->seg->charset->sort_order;
279
unsigned char tt_buff[MI_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
280
unsigned char *saved_from=NULL, *saved_to=NULL, *saved_vseg=NULL;
281
uint32_t saved_length=0, saved_prefix_len=0;
282
uint32_t length_pack;
292
uint nod_flag, length, len, matched, cmplen, kseg_len;
293
uint prefix_len,suffix_len;
294
int key_len_skip, seg_len_pack, key_len_left;
295
uchar *end, *kseg, *vseg;
296
uchar *sort_order=keyinfo->seg->charset->sort_order;
297
uchar tt_buff[MI_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
298
uchar *saved_from, *saved_to, *saved_vseg;
299
uint saved_length=0, saved_prefix_len=0;
301
DBUG_ENTER("_mi_prefix_search");
285
303
t_buff[0]=0; /* Avoid bugs */
286
304
end= page+mi_getint(page);
294
312
key_len_left=(int) key_len- (int) key_len_skip;
295
313
/* If key_len is 0, then lenght_pack is 1, then key_len_left is -1. */
296
314
cmplen=(key_len_left>=0) ? kseg_len : key_len-length_pack;
315
DBUG_PRINT("info",("key: '%.*s'",kseg_len,kseg));
299
318
Keys are compressed the following way:
356
375
saved_prefix_len=prefix_len;
377
DBUG_PRINT("loop",("page: '%.*s%.*s'",prefix_len,t_buff+seg_len_pack,
359
unsigned char *from=vseg+suffix_len;
380
uchar *from=vseg+suffix_len;
360
381
HA_KEYSEG *keyseg;
363
384
for (keyseg=keyinfo->seg+1 ; keyseg->type ; keyseg++ )
387
408
mi_print_error(info->s, HA_ERR_CRASHED);
388
409
my_errno=HA_ERR_CRASHED;
389
return(MI_FOUND_WRONG_KEY);
411
("Found wrong key: length: %u page: 0x%lx end: %lx",
412
length, (long) page, (long) end));
413
DBUG_RETURN(MI_FOUND_WRONG_KEY);
392
416
if (matched >= prefix_len)
394
418
/* We have to compare. But we can still skip part of the key */
396
unsigned char *k=kseg+prefix_len;
420
uchar *k=kseg+prefix_len;
399
423
If prefix_len > cmplen then we are in the end-space comparison
441
465
/* We have to compare k and vseg as if they were space extended */
442
unsigned char *k_end= k+ (cmplen - len);
466
uchar *k_end= k+ (cmplen - len);
443
467
for ( ; k < k_end && *k == ' '; k++) ;
445
469
goto cmp_rest; /* should never happen */
446
if (*k < (unsigned char) ' ')
470
if (*k < (uchar) ' ')
448
472
my_flag= 1; /* Compared string is smaller */
454
478
else if (len > cmplen)
456
unsigned char *vseg_end;
457
481
if ((nextflag & SEARCH_PREFIX) && key_len_left == 0)
460
484
/* We have to compare k and vseg as if they were space extended */
461
485
for (vseg_end= vseg + (len-cmplen) ;
462
vseg < vseg_end && *vseg == (unsigned char) ' ';
486
vseg < vseg_end && *vseg == (uchar) ' ';
463
487
vseg++, matched++) ;
464
assert(vseg < vseg_end);
488
DBUG_ASSERT(vseg < vseg_end);
466
if (*vseg > (unsigned char) ' ')
490
if (*vseg > (uchar) ' ')
468
492
my_flag= 1; /* Compared string is smaller */
520
544
*last_key= page == end;
546
DBUG_PRINT("exit",("flag: %d ret_pos: 0x%lx", flag, (long) *ret_pos));
523
548
} /* _mi_prefix_search */
526
551
/* Get pos to a key_block */
528
my_off_t _mi_kpos(uint32_t nod_flag, unsigned char *after_key)
553
my_off_t _mi_kpos(uint nod_flag, uchar *after_key)
530
555
after_key-=nod_flag;
531
556
switch (nod_flag) {
562
587
/* Save pos to a key_block */
564
void _mi_kpointer(register MI_INFO *info, register unsigned char *buff, my_off_t pos)
589
void _mi_kpointer(register MI_INFO *info, register uchar *buff, my_off_t pos)
566
591
pos/=MI_MIN_KEY_BLOCK_LENGTH;
567
592
switch (info->s->base.key_reflength) {
580
605
case 4: mi_int4store(buff,pos); break;
581
606
case 3: mi_int3store(buff,pos); break;
582
607
case 2: mi_int2store(buff,(uint) pos); break;
583
case 1: buff[0]= (unsigned char) pos; break;
608
case 1: buff[0]= (uchar) pos; break;
584
609
default: abort(); /* impossible */
586
611
} /* _mi_kpointer */
589
614
/* Calc pos to a data-record from a key */
592
my_off_t _mi_dpos(MI_INFO *info, uint32_t nod_flag, unsigned char *after_key)
617
my_off_t _mi_dpos(MI_INFO *info, uint nod_flag, uchar *after_key)
595
620
after_key-=(nod_flag + info->s->rec_reflength);
620
645
/* Calc position from a record pointer ( in delete link chain ) */
622
my_off_t _mi_rec_pos(MYISAM_SHARE *s, unsigned char *ptr)
647
my_off_t _mi_rec_pos(MYISAM_SHARE *s, uchar *ptr)
625
650
switch (s->rec_reflength) {
678
703
/* save position to record */
680
void _mi_dpointer(MI_INFO *info, unsigned char *buff, my_off_t pos)
705
void _mi_dpointer(MI_INFO *info, uchar *buff, my_off_t pos)
682
707
if (!(info->s->options &
683
708
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) &&
717
742
/* same as _mi_get_key but used with fixed length keys */
719
uint32_t _mi_get_static_key(register MI_KEYDEF *keyinfo, uint32_t nod_flag,
720
register unsigned char **page, register unsigned char *key)
744
uint _mi_get_static_key(register MI_KEYDEF *keyinfo, uint nod_flag,
745
register uchar **page, register uchar *key)
722
memcpy(key, *page, keyinfo->keylength+nod_flag);
747
memcpy((uchar*) key,(uchar*) *page,
748
(size_t) (keyinfo->keylength+nod_flag));
723
749
*page+=keyinfo->keylength+nod_flag;
724
750
return(keyinfo->keylength);
725
751
} /* _mi_get_static_key */
739
765
key_length + length of data pointer
742
uint32_t _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint32_t nod_flag,
743
register unsigned char **page_pos, register unsigned char *key)
768
uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
769
register uchar **page_pos, register uchar *key)
745
771
register HA_KEYSEG *keyseg;
746
unsigned char *start_key,*page=*page_pos;
772
uchar *start_key,*page=*page_pos;
750
776
for (keyseg=keyinfo->seg ; keyseg->type ;keyseg++)
752
778
if (keyseg->flag & HA_PACK_KEY)
754
780
/* key with length, packed to previous key */
755
unsigned char *start=key;
756
uint32_t packed= *page & 128,tot_length,rest_length;
782
uint packed= *page & 128,tot_length,rest_length;
757
783
if (keyseg->length >= 127)
759
785
length=mi_uint2korr(page) & 32767;
778
804
key+= length; /* Same diff_key as prev */
779
805
if (length > keyseg->length)
808
("Found too long null packed key: %u of %u at 0x%lx",
809
length, keyseg->length, (long) *page_pos));
810
DBUG_DUMP("key",(uchar*) *page_pos,16);
781
811
mi_print_error(keyinfo->share, HA_ERR_CRASHED);
782
812
my_errno=HA_ERR_CRASHED;
833
863
if (length > (uint) keyseg->length)
865
DBUG_PRINT("error",("Found too long packed key: %u of %u at 0x%lx",
866
length, keyseg->length, (long) *page_pos));
867
DBUG_DUMP("key",(uchar*) *page_pos,16);
835
868
mi_print_error(keyinfo->share, HA_ERR_CRASHED);
836
869
my_errno=HA_ERR_CRASHED;
837
870
return 0; /* Error */
848
881
if (keyseg->flag &
849
882
(HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
851
unsigned char *tmp=page;
852
885
get_key_length(length,tmp);
853
886
length+=(uint) (tmp-page);
856
889
length=keyseg->length;
858
memcpy(key, page, length);
891
memcpy((uchar*) key,(uchar*) page,(size_t) length);
862
895
length=keyseg->length+nod_flag;
863
memcpy(key,page,length);
896
bmove((uchar*) key,(uchar*) page,length);
864
897
*page_pos= page+length;
865
898
return ((uint) (key-start_key)+keyseg->length);
866
899
} /* _mi_get_pack_key */
870
903
/* key that is packed relatively to previous */
872
uint32_t _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint32_t nod_flag,
873
register unsigned char **page_pos, register unsigned char *key)
905
uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
906
register uchar **page_pos, register uchar *key)
875
908
register HA_KEYSEG *keyseg;
876
unsigned char *start_key,*page,*page_end,*from,*from_end;
909
uchar *start_key,*page,*page_end,*from,*from_end;
911
DBUG_ENTER("_mi_get_binary_pack_key");
880
914
page_end=page+MI_MAX_KEY_BUFF+1;
900
934
if (length > keyinfo->maxlength)
937
("Found too long binary packed key: %u of %u at 0x%lx",
938
length, keyinfo->maxlength, (long) *page_pos));
939
DBUG_DUMP("key",(uchar*) *page_pos,16);
902
940
mi_print_error(keyinfo->share, HA_ERR_CRASHED);
903
941
my_errno=HA_ERR_CRASHED;
904
return(0); /* Wrong key */
942
DBUG_RETURN(0); /* Wrong key */
906
944
/* Key is packed against prev key, take prefix from prev key. */
955
993
from=page; from_end=page_end;
957
memmove(key, from, length);
995
DBUG_PRINT("info",("key: 0x%lx from: 0x%lx length: %u",
996
(long) key, (long) from, length));
997
memmove((uchar*) key, (uchar*) from, (size_t) length);
981
1021
if (from_end != page_end)
1023
DBUG_PRINT("error",("Error when unpacking key"));
983
1024
mi_print_error(keyinfo->share, HA_ERR_CRASHED);
984
1025
my_errno=HA_ERR_CRASHED;
985
return(0); /* Error */
1026
DBUG_RETURN(0); /* Error */
987
1028
/* Copy data pointer and, if appropriate, key block pointer. */
988
memcpy(key, from, length);
1029
memcpy((uchar*) key,(uchar*) from,(size_t) length);
989
1030
*page_pos= from+length;
991
return((uint) (key-start_key)+keyseg->length);
1032
DBUG_RETURN((uint) (key-start_key)+keyseg->length);
995
1036
/* Get key at position without knowledge of previous key */
996
1037
/* Returns pointer to next key */
998
unsigned char *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *page,
999
unsigned char *key, unsigned char *keypos, uint32_t *return_key_length)
1039
uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
1040
uchar *key, uchar *keypos, uint *return_key_length)
1043
DBUG_ENTER("_mi_get_key");
1003
1045
nod_flag=mi_test_if_nod(page);
1004
1046
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
1006
memcpy(key,keypos,keyinfo->keylength+nod_flag);
1007
return(keypos+keyinfo->keylength+nod_flag);
1048
bmove((uchar*) key,(uchar*) keypos,keyinfo->keylength+nod_flag);
1049
DBUG_RETURN(keypos+keyinfo->keylength+nod_flag);
1018
1060
mi_print_error(info->s, HA_ERR_CRASHED);
1019
1061
my_errno=HA_ERR_CRASHED;
1066
DBUG_PRINT("exit",("page: 0x%lx length: %u", (long) page,
1067
*return_key_length));
1025
1069
} /* _mi_get_key */
1028
1072
/* Get key at position without knowledge of previous key */
1029
1073
/* Returns 0 if ok */
1031
static bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *page,
1032
unsigned char *key, unsigned char *keypos,
1033
uint32_t *return_key_length)
1075
static my_bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
1076
uchar *key, uchar *keypos,
1077
uint *return_key_length)
1080
DBUG_ENTER("_mi_get_prev_key");
1037
1082
nod_flag=mi_test_if_nod(page);
1038
1083
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
1040
1085
*return_key_length=keyinfo->keylength;
1041
memcpy(key, keypos - *return_key_length-nod_flag, *return_key_length);
1086
bmove((uchar*) key,(uchar*) keypos- *return_key_length-nod_flag,
1087
*return_key_length);
1064
1110
/* Get last key from key-page */
1065
1111
/* Return pointer to where key starts */
1067
unsigned char *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *page,
1068
unsigned char *lastkey, unsigned char *endpos, uint32_t *return_key_length)
1113
uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
1114
uchar *lastkey, uchar *endpos, uint *return_key_length)
1071
unsigned char *lastpos;
1118
DBUG_ENTER("_mi_get_last_key");
1119
DBUG_PRINT("enter",("page: 0x%lx endpos: 0x%lx", (long) page,
1073
1122
nod_flag=mi_test_if_nod(page);
1074
1123
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
1076
1125
lastpos=endpos-keyinfo->keylength-nod_flag;
1077
1126
*return_key_length=keyinfo->keylength;
1078
1127
if (lastpos > page)
1079
memcpy(lastkey,lastpos,keyinfo->keylength+nod_flag);
1128
bmove((uchar*) lastkey,(uchar*) lastpos,keyinfo->keylength+nod_flag);
1088
1137
*return_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,lastkey);
1089
1138
if (*return_key_length == 0)
1140
DBUG_PRINT("error",("Couldn't find last key: page: 0x%lx",
1091
1142
mi_print_error(info->s, HA_ERR_CRASHED);
1092
1143
my_errno=HA_ERR_CRASHED;
1148
DBUG_PRINT("exit",("lastpos: 0x%lx length: %u", (long) lastpos,
1149
*return_key_length));
1150
DBUG_RETURN(lastpos);
1098
1151
} /* _mi_get_last_key */
1101
1154
/* Calculate length of key */
1103
uint32_t _mi_keylength(MI_KEYDEF *keyinfo, register unsigned char *key)
1156
uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
1105
1158
register HA_KEYSEG *keyseg;
1106
unsigned char *start;
1108
1161
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
1109
1162
return (keyinfo->keylength);
1135
1188
after '0xDF' but find 'ss'
1138
uint32_t _mi_keylength_part(MI_KEYDEF *keyinfo, register unsigned char *key,
1191
uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
1139
1192
HA_KEYSEG *end)
1141
1194
register HA_KEYSEG *keyseg;
1142
unsigned char *start= key;
1144
1197
for (keyseg=keyinfo->seg ; keyseg != end ; keyseg++)
1161
1214
/* Move a key */
1163
unsigned char *_mi_move_key(MI_KEYDEF *keyinfo, unsigned char *to, unsigned char *from)
1216
uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from)
1165
register uint32_t length;
1166
length= _mi_keylength(keyinfo, from);
1167
memcpy(to, from, length);
1218
register uint length;
1219
memcpy((uchar*) to, (uchar*) from,
1220
(size_t) (length=_mi_keylength(keyinfo,from)));
1168
1221
return to+length;
1172
1225
/* This can't be used when database is touched after last read */
1174
1227
int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
1175
unsigned char *key, uint32_t key_length, uint32_t nextflag, my_off_t pos)
1228
uchar *key, uint key_length, uint nextflag, my_off_t pos)
1179
unsigned char lastkey[MI_MAX_KEY_BUFF];
1232
uchar lastkey[MI_MAX_KEY_BUFF];
1233
DBUG_ENTER("_mi_search_next");
1234
DBUG_PRINT("enter",("nextflag: %u lastpos: %lu int_keypos: %lu",
1235
nextflag, (ulong) info->lastpos,
1236
(ulong) info->int_keypos));
1237
DBUG_EXECUTE("key",_mi_print_key(DBUG_FILE,keyinfo->seg,key,key_length););
1181
1239
/* Force full read if we are at last key or if we are not on a leaf
1182
1240
and the key tree has changed since we used it last time
1189
1247
info->page_changed ||
1190
1248
(info->int_keytree_version != keyinfo->version &&
1191
1249
(info->int_nod_flag || info->buff_used)))
1192
return(_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
1250
DBUG_RETURN(_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
1193
1251
nextflag | SEARCH_SAVE_BUFF, pos));
1195
1253
if (info->buff_used)
1197
1255
if (!_mi_fetch_keypage(info,keyinfo,info->last_search_keypage,
1198
1256
DFLT_INIT_HITS,info->buff,0))
1200
1258
info->buff_used=0;
1211
1269
if ((error=_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
1212
1270
nextflag | SEARCH_SAVE_BUFF, tmp_pos)) <=0)
1215
1273
memcpy(lastkey,key,key_length);
1216
1274
if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,
1217
1275
&info->int_keypos,lastkey)))
1220
1278
else /* Previous key */
1223
1281
/* Find start of previous key */
1224
1282
info->int_keypos=_mi_get_last_key(info,keyinfo,info->buff,lastkey,
1225
1283
info->int_keypos, &length);
1226
1284
if (!info->int_keypos)
1228
1286
if (info->int_keypos == info->buff+2)
1229
return(_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
1287
DBUG_RETURN(_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
1230
1288
nextflag | SEARCH_SAVE_BUFF, pos));
1231
1289
if ((error=_mi_search(info,keyinfo,key, USE_WHOLE_KEY,
1232
1290
nextflag | SEARCH_SAVE_BUFF,
1233
1291
_mi_kpos(nod_flag,info->int_keypos))) <= 0)
1236
1294
/* QQ: We should be able to optimize away the following call */
1237
1295
if (! _mi_get_last_key(info,keyinfo,info->buff,lastkey,
1238
1296
info->int_keypos,&info->lastkey_length))
1241
1299
memcpy(info->lastkey,lastkey,info->lastkey_length);
1242
1300
info->lastpos=_mi_dpos(info,0,info->lastkey+info->lastkey_length);
1301
DBUG_PRINT("exit",("found key at %lu",(ulong) info->lastpos));
1244
1303
} /* _mi_search_next */
1250
1309
int _mi_search_first(register MI_INFO *info, register MI_KEYDEF *keyinfo,
1251
1310
register my_off_t pos)
1254
unsigned char *page;
1314
DBUG_ENTER("_mi_search_first");
1256
1316
if (pos == HA_OFFSET_ERROR)
1258
1318
my_errno=HA_ERR_KEY_NOT_FOUND;
1259
1319
info->lastpos= HA_OFFSET_ERROR;
1265
1325
if (!_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,0))
1267
1327
info->lastpos= HA_OFFSET_ERROR;
1270
1330
nod_flag=mi_test_if_nod(info->buff);
1271
1331
page=info->buff+2+nod_flag;
1274
1334
if (!(info->lastkey_length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,
1275
1335
info->lastkey)))
1276
return(-1); /* Crashed */
1336
DBUG_RETURN(-1); /* Crashed */
1278
1338
info->int_keypos=page; info->int_maxpos=info->buff+mi_getint(info->buff)-1;
1279
1339
info->int_nod_flag=nod_flag;
1282
1342
info->page_changed=info->buff_used=0;
1283
1343
info->lastpos=_mi_dpos(info,0,info->lastkey+info->lastkey_length);
1345
DBUG_PRINT("exit",("found key at %lu", (ulong) info->lastpos));
1286
1347
} /* _mi_search_first */
1292
1353
int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo,
1293
1354
register my_off_t pos)
1296
unsigned char *buff,*page;
1358
DBUG_ENTER("_mi_search_last");
1298
1360
if (pos == HA_OFFSET_ERROR)
1300
1362
my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
1301
1363
info->lastpos= HA_OFFSET_ERROR;
1305
1367
buff=info->buff;
1308
1370
if (!_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,buff,0))
1310
1372
info->lastpos= HA_OFFSET_ERROR;
1313
1375
page= buff+mi_getint(buff);
1314
1376
nod_flag=mi_test_if_nod(buff);
1317
1379
if (!_mi_get_last_key(info,keyinfo,buff,info->lastkey,page,
1318
1380
&info->lastkey_length))
1320
1382
info->lastpos=_mi_dpos(info,0,info->lastkey+info->lastkey_length);
1321
1383
info->int_keypos=info->int_maxpos=page;
1322
1384
info->int_nod_flag=nod_flag;
1345
1408
/* Static length key */
1348
_mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,
1349
unsigned char *next_pos __attribute__((unused)),
1350
unsigned char *org_key __attribute__((unused)),
1351
unsigned char *prev_key __attribute__((unused)),
1352
unsigned char *key, MI_KEY_PARAM *s_temp)
1411
_mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
1412
uchar *next_pos __attribute__((unused)),
1413
uchar *org_key __attribute__((unused)),
1414
uchar *prev_key __attribute__((unused)),
1415
uchar *key, MI_KEY_PARAM *s_temp)
1354
1417
s_temp->key=key;
1355
1418
return (int) (s_temp->totlength=keyinfo->keylength+nod_flag);
1358
1421
/* Variable length key */
1361
_mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,
1362
unsigned char *next_pos __attribute__((unused)),
1363
unsigned char *org_key __attribute__((unused)),
1364
unsigned char *prev_key __attribute__((unused)),
1365
unsigned char *key, MI_KEY_PARAM *s_temp)
1424
_mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
1425
uchar *next_pos __attribute__((unused)),
1426
uchar *org_key __attribute__((unused)),
1427
uchar *prev_key __attribute__((unused)),
1428
uchar *key, MI_KEY_PARAM *s_temp)
1367
1430
s_temp->key=key;
1368
1431
return (int) (s_temp->totlength=_mi_keylength(keyinfo,key)+nod_flag);
1391
_mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,unsigned char *next_key,
1392
unsigned char *org_key, unsigned char *prev_key, unsigned char *key,
1454
_mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
1455
uchar *org_key, uchar *prev_key, uchar *key,
1393
1456
MI_KEY_PARAM *s_temp)
1395
1458
register HA_KEYSEG *keyseg;
1397
uint32_t key_length,ref_length,org_key_length=0,
1460
uint key_length,ref_length,org_key_length=0,
1398
1461
length_pack,new_key_length,diff_flag,pack_marker;
1399
unsigned char *start,*end,*key_end,*sort_order;
1462
uchar *start,*end,*key_end,*sort_order;
1463
my_bool same_length;
1402
1465
length_pack=s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
1403
1466
same_length=0; keyseg=keyinfo->seg;
1404
1467
key_length=_mi_keylength(keyinfo,key)+nod_flag;
1470
if ((keyinfo->flag & HA_FULLTEXT) &&
1471
((keyseg->type == HA_KEYTYPE_TEXT) ||
1472
(keyseg->type == HA_KEYTYPE_VARTEXT1) ||
1473
(keyseg->type == HA_KEYTYPE_VARTEXT2)) &&
1474
!use_strnxfrm(keyseg->charset))
1475
sort_order=keyseg->charset->sort_order;
1408
1477
/* diff flag contains how many bytes is needed to pack key */
1409
1478
if (keyseg->length >= 127)
1509
1578
s_temp->totlength=(uint) length;
1510
1579
s_temp->prev_length=0;
1580
DBUG_PRINT("test",("tot_length: %u length: %d uniq_key_length: %u",
1581
key_length, length, s_temp->key_length));
1512
1583
/* If something after that hasn't length=0, test if we can combine */
1513
1584
if ((s_temp->next_key_pos=next_key))
1515
uint32_t packed,n_length;
1586
uint packed,n_length;
1517
1588
packed = *next_key & 128;
1518
1589
if (diff_flag == 2)
1596
1667
if (ref_length+pack_marker > new_ref_length)
1598
uint32_t new_pack_length=new_ref_length-pack_marker;
1669
uint new_pack_length=new_ref_length-pack_marker;
1599
1670
/* We must copy characters from the original key to the next key */
1600
1671
s_temp->part_of_prev_key= new_ref_length;
1601
1672
s_temp->prev_length= ref_length - new_pack_length;
1660
1733
/* Length of key which is prefix compressed */
1663
_mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,unsigned char *next_key,
1664
unsigned char *org_key, unsigned char *prev_key, unsigned char *key,
1736
_mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
1737
uchar *org_key, uchar *prev_key, uchar *key,
1665
1738
MI_KEY_PARAM *s_temp)
1667
uint32_t length,key_length,ref_length;
1740
uint length,key_length,ref_length;
1669
1742
s_temp->totlength=key_length=_mi_keylength(keyinfo,key)+nod_flag;
1670
1743
#ifdef HAVE_purify
1679
1752
As keys may be identical when running a sort in myisamchk, we
1680
1753
have to guard against the case where keys may be identical
1683
1756
end=key+key_length;
1684
1757
for ( ; *key == *prev_key && key < end; key++,prev_key++) ;
1685
1758
s_temp->ref_length= ref_length=(uint) (key-s_temp->key);
1694
1767
if ((s_temp->next_key_pos=next_key)) /* If another key after */
1696
1769
/* pack key against next key */
1697
uint32_t next_length,next_length_pack;
1770
uint next_length,next_length_pack;
1698
1771
get_key_pack_length(next_length,next_length_pack,next_key);
1700
1773
/* If first key and next key is packed (only on delete) */
1701
1774
if (!prev_key && org_key && next_length)
1704
1777
for (key= s_temp->key, end=key+next_length ;
1705
1778
*key == *org_key && key < end;
1706
1779
key++,org_key++) ;
1742
1815
/* store key without compression */
1744
1817
void _mi_store_static_key(MI_KEYDEF *keyinfo __attribute__((unused)),
1745
register unsigned char *key_pos,
1818
register uchar *key_pos,
1746
1819
register MI_KEY_PARAM *s_temp)
1748
memcpy(key_pos, s_temp->key, s_temp->totlength);
1821
memcpy((uchar*) key_pos,(uchar*) s_temp->key,(size_t) s_temp->totlength);
1752
1825
/* store variable length key with prefix compression */
1754
1827
#define store_pack_length(test,pos,length) { \
1755
if (test) { *((pos)++) = (unsigned char) (length); } else \
1756
{ *((pos)++) = (unsigned char) ((length) >> 8); *((pos)++) = (unsigned char) (length); } }
1828
if (test) { *((pos)++) = (uchar) (length); } else \
1829
{ *((pos)++) = (uchar) ((length) >> 8); *((pos)++) = (uchar) (length); } }
1759
1832
void _mi_store_var_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
1760
register unsigned char *key_pos,
1833
register uchar *key_pos,
1761
1834
register MI_KEY_PARAM *s_temp)
1764
unsigned char *start;
1778
1851
/* Not packed against previous key */
1779
1852
store_pack_length(s_temp->pack_marker == 128,key_pos,s_temp->key_length);
1781
assert(key_pos >= start);
1782
length= s_temp->totlength - (key_pos - start);
1783
memcpy(key_pos, s_temp->key, length);
1854
bmove((uchar*) key_pos,(uchar*) s_temp->key,
1855
(length=s_temp->totlength-(uint) (key_pos-start)));
1785
1857
if (!s_temp->next_key_pos) /* No following key */
1821
1893
/* variable length key with prefix compression */
1823
1895
void _mi_store_bin_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
1824
register unsigned char *key_pos,
1896
register uchar *key_pos,
1825
1897
register MI_KEY_PARAM *s_temp)
1827
assert(s_temp->totlength >= s_temp->ref_length);
1828
1899
store_key_length_inc(key_pos,s_temp->ref_length);
1829
memcpy(key_pos,s_temp->key+s_temp->ref_length,
1830
s_temp->totlength - s_temp->ref_length);
1900
memcpy((char*) key_pos,(char*) s_temp->key+s_temp->ref_length,
1901
(size_t) s_temp->totlength-s_temp->ref_length);
1832
1903
if (s_temp->next_key_pos)