18
18
#include "myisamdef.h"
19
19
#include <mystrings/m_ctype.h>
20
#include <mystrings/m_string.h>
21
#include <drizzled/util/test.h>
21
static bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
22
uchar *key, uchar *keypos,
23
uint *return_key_length);
23
static bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *page,
24
unsigned char *key, unsigned char *keypos,
25
uint32_t *return_key_length);
56
58
int _mi_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
57
uchar *key, uint key_len, uint nextflag, register my_off_t pos)
59
unsigned char *key, uint32_t key_len, uint32_t nextflag, register my_off_t pos)
62
uchar *keypos,*maxpos;
63
uchar lastkey[MI_MAX_KEY_BUFF],*buff;
64
unsigned char *keypos,*maxpos;
65
unsigned char lastkey[MI_MAX_KEY_BUFF],*buff;
65
67
if (pos == HA_OFFSET_ERROR)
113
115
if (pos != info->last_keypage)
115
uchar *old_buff=buff;
117
unsigned char *old_buff=buff;
116
118
if (!(buff=_mi_fetch_keypage(info,keyinfo,pos,DFLT_INIT_HITS,info->buff,
117
119
test(!(nextflag & SEARCH_SAVE_BUFF)))))
123
125
if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0)
127
uint32_t not_used[2];
126
128
if (_mi_get_prev_key(info,keyinfo, buff, info->lastkey, keypos,
127
129
&info->lastkey_length))
165
167
/* ret_pos point to where find or bigger key starts */
168
int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
169
uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
170
uchar *buff __attribute__((unused)), bool *last_key)
170
int _mi_bin_search(MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *page,
171
unsigned char *key, uint32_t key_len, uint32_t comp_flag, unsigned char **ret_pos,
172
unsigned char *buff, bool *last_key)
172
175
register int start,mid,end,save_end;
174
uint totlength,nod_flag,not_used[2];
177
uint32_t totlength,nod_flag,not_used[2];
176
179
totlength=keyinfo->keylength+(nod_flag=mi_test_if_nod(page));
228
int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
229
uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
230
uchar *buff, bool *last_key)
231
int _mi_seq_search(MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *page,
232
unsigned char *key, uint32_t key_len, uint32_t comp_flag, unsigned char **ret_pos,
233
unsigned char *buff, bool *last_key)
233
uint nod_flag,length=0,not_used[2];
234
uchar t_buff[MI_MAX_KEY_BUFF],*end;
236
uint32_t nod_flag,length=0,not_used[2];
237
unsigned char t_buff[MI_MAX_KEY_BUFF],*end;
236
239
end= page+mi_getint(page);
237
240
nod_flag=mi_test_if_nod(page);
260
263
} /* _mi_seq_search */
263
int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
264
uchar *key, uint key_len, uint nextflag, uchar **ret_pos,
265
uchar *buff, bool *last_key)
266
int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, unsigned char *page,
267
unsigned char *key, uint32_t key_len, uint32_t nextflag, unsigned char **ret_pos,
268
unsigned char *buff, bool *last_key)
268
271
my_flag is raw comparison result to be changed according to
270
273
flag is the value returned by ha_key_cmp and as treated as final
272
275
int flag=0, my_flag=-1;
273
uint nod_flag, length=0, len, matched, cmplen, kseg_len;
274
uint prefix_len=0,suffix_len;
276
uint32_t nod_flag, length=0, len, matched, cmplen, kseg_len;
277
uint32_t prefix_len=0,suffix_len;
275
278
int key_len_skip, seg_len_pack=0, key_len_left;
276
uchar *end, *kseg, *vseg;
277
uchar *sort_order=keyinfo->seg->charset->sort_order;
278
uchar tt_buff[MI_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
279
uchar *saved_from=NULL, *saved_to=NULL, *saved_vseg=NULL;
280
uint saved_length=0, saved_prefix_len=0;
279
unsigned char *end, *kseg, *vseg;
280
unsigned char *sort_order=keyinfo->seg->charset->sort_order;
281
unsigned char tt_buff[MI_MAX_KEY_BUFF+2], *t_buff=tt_buff+2;
282
unsigned char *saved_from=NULL, *saved_to=NULL, *saved_vseg=NULL;
283
uint32_t saved_length=0, saved_prefix_len=0;
284
uint32_t length_pack;
284
287
t_buff[0]=0; /* Avoid bugs */
391
394
if (matched >= prefix_len)
393
396
/* We have to compare. But we can still skip part of the key */
395
uchar *k=kseg+prefix_len;
398
unsigned char *k=kseg+prefix_len;
398
401
If prefix_len > cmplen then we are in the end-space comparison
440
443
/* We have to compare k and vseg as if they were space extended */
441
uchar *k_end= k+ (cmplen - len);
444
unsigned char *k_end= k+ (cmplen - len);
442
445
for ( ; k < k_end && *k == ' '; k++) ;
444
447
goto cmp_rest; /* should never happen */
445
if (*k < (uchar) ' ')
448
if (*k < (unsigned char) ' ')
447
450
my_flag= 1; /* Compared string is smaller */
453
456
else if (len > cmplen)
458
unsigned char *vseg_end;
456
459
if ((nextflag & SEARCH_PREFIX) && key_len_left == 0)
459
462
/* We have to compare k and vseg as if they were space extended */
460
463
for (vseg_end= vseg + (len-cmplen) ;
461
vseg < vseg_end && *vseg == (uchar) ' ';
464
vseg < vseg_end && *vseg == (unsigned char) ' ';
462
465
vseg++, matched++) ;
463
466
assert(vseg < vseg_end);
465
if (*vseg > (uchar) ' ')
468
if (*vseg > (unsigned char) ' ')
467
470
my_flag= 1; /* Compared string is smaller */
561
564
/* Save pos to a key_block */
563
void _mi_kpointer(register MI_INFO *info, register uchar *buff, my_off_t pos)
566
void _mi_kpointer(register MI_INFO *info, register unsigned char *buff, my_off_t pos)
565
568
pos/=MI_MIN_KEY_BLOCK_LENGTH;
566
569
switch (info->s->base.key_reflength) {
579
582
case 4: mi_int4store(buff,pos); break;
580
583
case 3: mi_int3store(buff,pos); break;
581
584
case 2: mi_int2store(buff,(uint) pos); break;
582
case 1: buff[0]= (uchar) pos; break;
585
case 1: buff[0]= (unsigned char) pos; break;
583
586
default: abort(); /* impossible */
585
588
} /* _mi_kpointer */
588
591
/* Calc pos to a data-record from a key */
591
my_off_t _mi_dpos(MI_INFO *info, uint nod_flag, uchar *after_key)
594
my_off_t _mi_dpos(MI_INFO *info, uint32_t nod_flag, unsigned char *after_key)
594
597
after_key-=(nod_flag + info->s->rec_reflength);
619
622
/* Calc position from a record pointer ( in delete link chain ) */
621
my_off_t _mi_rec_pos(MYISAM_SHARE *s, uchar *ptr)
624
my_off_t _mi_rec_pos(MYISAM_SHARE *s, unsigned char *ptr)
624
627
switch (s->rec_reflength) {
677
680
/* save position to record */
679
void _mi_dpointer(MI_INFO *info, uchar *buff, my_off_t pos)
682
void _mi_dpointer(MI_INFO *info, unsigned char *buff, my_off_t pos)
681
684
if (!(info->s->options &
682
685
(HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) &&
716
719
/* same as _mi_get_key but used with fixed length keys */
718
uint _mi_get_static_key(register MI_KEYDEF *keyinfo, uint nod_flag,
719
register uchar **page, register uchar *key)
721
uint32_t _mi_get_static_key(register MI_KEYDEF *keyinfo, uint32_t nod_flag,
722
register unsigned char **page, register unsigned char *key)
721
724
memcpy(key, *page, keyinfo->keylength+nod_flag);
722
725
*page+=keyinfo->keylength+nod_flag;
738
741
key_length + length of data pointer
741
uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
742
register uchar **page_pos, register uchar *key)
744
uint32_t _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint32_t nod_flag,
745
register unsigned char **page_pos, register unsigned char *key)
744
747
register HA_KEYSEG *keyseg;
745
uchar *start_key,*page=*page_pos;
748
unsigned char *start_key,*page=*page_pos;
749
752
for (keyseg=keyinfo->seg ; keyseg->type ;keyseg++)
751
754
if (keyseg->flag & HA_PACK_KEY)
753
756
/* key with length, packed to previous key */
755
uint packed= *page & 128,tot_length,rest_length;
757
unsigned char *start=key;
758
uint32_t packed= *page & 128,tot_length,rest_length;
756
759
if (keyseg->length >= 127)
758
761
length=mi_uint2korr(page) & 32767;
804
807
else if (tot_length < 255 && *start == 255)
806
memcpy(key+1,key+3,length);
809
memmove(key+1,key+3,length);
869
872
/* key that is packed relatively to previous */
871
uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
872
register uchar **page_pos, register uchar *key)
874
uint32_t _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint32_t nod_flag,
875
register unsigned char **page_pos, register unsigned char *key)
874
877
register HA_KEYSEG *keyseg;
875
uchar *start_key,*page,*page_end,*from,*from_end;
878
unsigned char *start_key,*page,*page_end,*from,*from_end;
879
882
page_end=page+MI_MAX_KEY_BUFF+1;
994
997
/* Get key at position without knowledge of previous key */
995
998
/* Returns pointer to next key */
997
uchar *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
998
uchar *key, uchar *keypos, uint *return_key_length)
1000
unsigned char *_mi_get_key(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *page,
1001
unsigned char *key, unsigned char *keypos, uint32_t *return_key_length)
1002
1005
nod_flag=mi_test_if_nod(page);
1003
1006
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
1005
memcpy(key,keypos,keyinfo->keylength+nod_flag);
1008
memmove(key,keypos,keyinfo->keylength+nod_flag);
1006
1009
return(keypos+keyinfo->keylength+nod_flag);
1027
1030
/* Get key at position without knowledge of previous key */
1028
1031
/* Returns 0 if ok */
1030
static bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
1031
uchar *key, uchar *keypos,
1032
uint *return_key_length)
1033
static bool _mi_get_prev_key(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *page,
1034
unsigned char *key, unsigned char *keypos,
1035
uint32_t *return_key_length)
1036
1039
nod_flag=mi_test_if_nod(page);
1037
1040
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
1039
1042
*return_key_length=keyinfo->keylength;
1040
memcpy(key, keypos - *return_key_length-nod_flag, *return_key_length);
1043
memmove(key, keypos - *return_key_length-nod_flag, *return_key_length);
1063
1066
/* Get last key from key-page */
1064
1067
/* Return pointer to where key starts */
1066
uchar *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, uchar *page,
1067
uchar *lastkey, uchar *endpos, uint *return_key_length)
1069
unsigned char *_mi_get_last_key(MI_INFO *info, MI_KEYDEF *keyinfo, unsigned char *page,
1070
unsigned char *lastkey, unsigned char *endpos, uint32_t *return_key_length)
1073
unsigned char *lastpos;
1072
1075
nod_flag=mi_test_if_nod(page);
1073
1076
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
1075
1078
lastpos=endpos-keyinfo->keylength-nod_flag;
1076
1079
*return_key_length=keyinfo->keylength;
1077
1080
if (lastpos > page)
1078
memcpy(lastkey,lastpos,keyinfo->keylength+nod_flag);
1081
memmove(lastkey,lastpos,keyinfo->keylength+nod_flag);
1100
1103
/* Calculate length of key */
1102
uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
1105
uint32_t _mi_keylength(MI_KEYDEF *keyinfo, register unsigned char *key)
1104
1107
register HA_KEYSEG *keyseg;
1108
unsigned char *start;
1107
1110
if (! (keyinfo->flag & (HA_VAR_LENGTH_KEY | HA_BINARY_PACK_KEY)))
1108
1111
return (keyinfo->keylength);
1134
1137
after '0xDF' but find 'ss'
1137
uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
1140
uint32_t _mi_keylength_part(MI_KEYDEF *keyinfo, register unsigned char *key,
1138
1141
HA_KEYSEG *end)
1140
1143
register HA_KEYSEG *keyseg;
1144
unsigned char *start= key;
1143
1146
for (keyseg=keyinfo->seg ; keyseg != end ; keyseg++)
1160
1163
/* Move a key */
1162
uchar *_mi_move_key(MI_KEYDEF *keyinfo, uchar *to, uchar *from)
1165
unsigned char *_mi_move_key(MI_KEYDEF *keyinfo, unsigned char *to, unsigned char *from)
1164
register uint length;
1167
register uint32_t length;
1165
1168
length= _mi_keylength(keyinfo, from);
1166
1169
memcpy(to, from, length);
1167
1170
return to+length;
1171
1174
/* This can't be used when database is touched after last read */
1173
1176
int _mi_search_next(register MI_INFO *info, register MI_KEYDEF *keyinfo,
1174
uchar *key, uint key_length, uint nextflag, my_off_t pos)
1177
unsigned char *key, uint32_t key_length, uint32_t nextflag, my_off_t pos)
1178
uchar lastkey[MI_MAX_KEY_BUFF];
1181
unsigned char lastkey[MI_MAX_KEY_BUFF];
1180
1183
/* Force full read if we are at last key or if we are not on a leaf
1181
1184
and the key tree has changed since we used it last time
1219
1222
else /* Previous key */
1222
1225
/* Find start of previous key */
1223
1226
info->int_keypos=_mi_get_last_key(info,keyinfo,info->buff,lastkey,
1224
1227
info->int_keypos, &length);
1291
1294
int _mi_search_last(register MI_INFO *info, register MI_KEYDEF *keyinfo,
1292
1295
register my_off_t pos)
1298
unsigned char *buff,*page;
1297
1300
if (pos == HA_OFFSET_ERROR)
1344
1347
/* Static length key */
1347
_mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
1348
uchar *next_pos __attribute__((unused)),
1349
uchar *org_key __attribute__((unused)),
1350
uchar *prev_key __attribute__((unused)),
1351
uchar *key, MI_KEY_PARAM *s_temp)
1350
_mi_calc_static_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,
1351
unsigned char *next_pos,
1352
unsigned char *org_key,
1353
unsigned char *prev_key,
1354
unsigned char *key, MI_KEY_PARAM *s_temp)
1353
1359
s_temp->key=key;
1354
1360
return (int) (s_temp->totlength=keyinfo->keylength+nod_flag);
1357
1363
/* Variable length key */
1360
_mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint nod_flag,
1361
uchar *next_pos __attribute__((unused)),
1362
uchar *org_key __attribute__((unused)),
1363
uchar *prev_key __attribute__((unused)),
1364
uchar *key, MI_KEY_PARAM *s_temp)
1366
_mi_calc_var_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,
1367
unsigned char *next_pos,
1368
unsigned char *org_key,
1369
unsigned char *prev_key,
1370
unsigned char *key, MI_KEY_PARAM *s_temp)
1366
1375
s_temp->key=key;
1367
1376
return (int) (s_temp->totlength=_mi_keylength(keyinfo,key)+nod_flag);
1390
_mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
1391
uchar *org_key, uchar *prev_key, uchar *key,
1399
_mi_calc_var_pack_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,
1400
unsigned char *next_key,
1401
unsigned char *org_key,
1402
unsigned char *prev_key,
1392
1404
MI_KEY_PARAM *s_temp)
1394
1406
register HA_KEYSEG *keyseg;
1396
uint key_length,ref_length,org_key_length=0,
1408
uint32_t key_length,ref_length,org_key_length=0,
1397
1409
length_pack,new_key_length,diff_flag,pack_marker;
1398
uchar *start,*end,*key_end,*sort_order;
1410
unsigned char *start,*end,*key_end,*sort_order;
1399
1411
bool same_length;
1401
1413
length_pack=s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
1511
1523
/* If something after that hasn't length=0, test if we can combine */
1512
1524
if ((s_temp->next_key_pos=next_key))
1514
uint packed,n_length;
1526
uint32_t packed,n_length;
1516
1528
packed = *next_key & 128;
1517
1529
if (diff_flag == 2)
1595
1607
if (ref_length+pack_marker > new_ref_length)
1597
uint new_pack_length=new_ref_length-pack_marker;
1609
uint32_t new_pack_length=new_ref_length-pack_marker;
1598
1610
/* We must copy characters from the original key to the next key */
1599
1611
s_temp->part_of_prev_key= new_ref_length;
1600
1612
s_temp->prev_length= ref_length - new_pack_length;
1659
1671
/* Length of key which is prefix compressed */
1662
_mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint nod_flag,uchar *next_key,
1663
uchar *org_key, uchar *prev_key, uchar *key,
1674
_mi_calc_bin_pack_key_length(MI_KEYDEF *keyinfo,uint32_t nod_flag,unsigned char *next_key,
1675
unsigned char *org_key, unsigned char *prev_key, unsigned char *key,
1664
1676
MI_KEY_PARAM *s_temp)
1666
uint length,key_length,ref_length;
1678
uint32_t length,key_length,ref_length;
1668
1680
s_temp->totlength=key_length=_mi_keylength(keyinfo,key)+nod_flag;
1669
1681
#ifdef HAVE_purify
1678
1690
As keys may be identical when running a sort in myisamchk, we
1679
1691
have to guard against the case where keys may be identical
1682
1694
end=key+key_length;
1683
1695
for ( ; *key == *prev_key && key < end; key++,prev_key++) ;
1684
1696
s_temp->ref_length= ref_length=(uint) (key-s_temp->key);
1693
1705
if ((s_temp->next_key_pos=next_key)) /* If another key after */
1695
1707
/* pack key against next key */
1696
uint next_length,next_length_pack;
1708
uint32_t next_length,next_length_pack;
1697
1709
get_key_pack_length(next_length,next_length_pack,next_key);
1699
1711
/* If first key and next key is packed (only on delete) */
1700
1712
if (!prev_key && org_key && next_length)
1703
1715
for (key= s_temp->key, end=key+next_length ;
1704
1716
*key == *org_key && key < end;
1705
1717
key++,org_key++) ;
1741
1753
/* store key without compression */
1743
void _mi_store_static_key(MI_KEYDEF *keyinfo __attribute__((unused)),
1744
register uchar *key_pos,
1755
void _mi_store_static_key(MI_KEYDEF *keyinfo,
1756
register unsigned char *key_pos,
1745
1757
register MI_KEY_PARAM *s_temp)
1747
1760
memcpy(key_pos, s_temp->key, s_temp->totlength);
1751
1764
/* store variable length key with prefix compression */
1753
1766
#define store_pack_length(test,pos,length) { \
1754
if (test) { *((pos)++) = (uchar) (length); } else \
1755
{ *((pos)++) = (uchar) ((length) >> 8); *((pos)++) = (uchar) (length); } }
1758
void _mi_store_var_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
1759
register uchar *key_pos,
1767
if (test) { *((pos)++) = (unsigned char) (length); } else \
1768
{ *((pos)++) = (unsigned char) ((length) >> 8); *((pos)++) = (unsigned char) (length); } }
1771
void _mi_store_var_pack_key(MI_KEYDEF *keyinfo,
1772
register unsigned char *key_pos,
1760
1773
register MI_KEY_PARAM *s_temp)
1777
unsigned char *start;
1780
1794
assert(key_pos >= start);
1781
1795
length= s_temp->totlength - (key_pos - start);
1782
memcpy(key_pos, s_temp->key, length);
1796
memmove(key_pos, s_temp->key, length);
1784
1798
if (!s_temp->next_key_pos) /* No following key */
1820
1834
/* variable length key with prefix compression */
1822
void _mi_store_bin_pack_key(MI_KEYDEF *keyinfo __attribute__((unused)),
1823
register uchar *key_pos,
1836
void _mi_store_bin_pack_key(MI_KEYDEF *keyinfo,
1837
register unsigned char *key_pos,
1824
1838
register MI_KEY_PARAM *s_temp)
1826
1841
assert(s_temp->totlength >= s_temp->ref_length);
1827
1842
store_key_length_inc(key_pos,s_temp->ref_length);
1828
1843
memcpy(key_pos,s_temp->key+s_temp->ref_length,