1
/* Copyright (C) 2002-2006 MySQL AB
3
This library is free software; you can redistribute it and/or
4
modify it under the terms of the GNU Library General Public
5
License as published by the Free Software Foundation; version 2
8
This library is distributed in the hope that it will be useful,
9
but WITHOUT ANY WARRANTY; without even the implied warranty of
10
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
11
Library General Public License for more details.
13
You should have received a copy of the GNU Library General Public
14
License along with this library; if not, write to the Free
15
Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
18
#include <my_global.h>
19
#include "my_handler.h"
21
int mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
22
uchar *b, uint b_length, my_bool part_key,
23
my_bool skip_end_space)
26
return charset_info->coll->strnncollsp(charset_info, a, a_length,
27
b, b_length, (my_bool)!skip_end_space);
28
return charset_info->coll->strnncoll(charset_info, a, a_length,
29
b, b_length, part_key);
33
static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
34
my_bool part_key, my_bool skip_end_space)
36
uint length= min(a_length,b_length);
37
uchar *end= a+ length;
41
if ((flag= (int) *a++ - (int) *b++))
43
if (part_key && b_length < a_length)
45
if (skip_end_space && a_length != b_length)
49
We are using space compression. We have to check if longer key
50
has next character < ' ', in which case it's less than the shorter
51
key that has an implicite space afterwards.
53
This code is identical to the one in
54
strings/ctype-simple.c:my_strnncollsp_simple
56
if (a_length < b_length)
58
/* put shorter key in a */
61
swap= -1; /* swap sign of result */
63
for (end= a + a_length-length; a < end ; a++)
66
return (*a < ' ') ? -swap : swap;
70
return (int) (a_length-b_length);
79
keyseg Array of key segments of key to compare
80
a First key to compare, in format from _mi_pack_key()
81
This is normally key specified by user
82
b Second key to compare. This is always from a row
83
key_length Length of key to compare. This can be shorter than
84
a to just compare sub keys
85
next_flag How keys should be compared
86
If bit SEARCH_FIND is not set the keys includes the row
87
position and this should also be compared
88
diff_pos OUT Number of first keypart where values differ, counting
90
diff_pos[1] OUT (b + diff_pos[1]) points to first value in tuple b
91
that is different from corresponding value in tuple a.
94
Example1: if the function is called for tuples
95
('aaa','bbb') and ('eee','fff'), then
96
diff_pos[0] = 1 (as 'aaa' != 'eee')
97
diff_pos[1] = 0 (offset from beggining of tuple b to 'eee' keypart).
99
Example2: if the index function is called for tuples
100
('aaa','bbb') and ('aaa','fff'),
101
diff_pos[0] = 2 (as 'aaa' != 'eee')
102
diff_pos[1] = 3 (offset from beggining of tuple b to 'fff' keypart,
103
here we assume that first key part is CHAR(3) NOT NULL)
106
Number-keys can't be splited
114
#define FCMP(A,B) ((int) (A) - (int) (B))
116
int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
117
register uchar *b, uint key_length, uint nextflag,
126
uint next_key_length;
130
for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
133
uint piks=! (keyseg->flag & HA_NO_SORT);
135
diff_pos[1]= (uint)(b - orig_b);
137
/* Handle NULL part */
138
if (keyseg->null_bit)
141
if (*a != *b && piks)
143
flag = (int) *a - (int) *b;
144
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
147
if (!*a++) /* If key was NULL */
149
if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
150
nextflag=SEARCH_SAME; /* Allow duplicate keys */
151
else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
154
This is only used from mi_check() to calculate cardinality.
155
It can't be used when searching for a key as this would cause
156
compare of (a,b) and (b,a) to return the same value.
160
next_key_length=key_length;
161
continue; /* To next key part */
164
end= a+ min(keyseg->length,key_length);
165
next_key_length=key_length-keyseg->length;
167
switch ((enum ha_base_keytype) keyseg->type) {
168
case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
169
if (keyseg->flag & HA_SPACE_PACK)
171
int a_length,b_length,pack_length;
172
get_key_length(a_length,a);
173
get_key_pack_length(b_length,pack_length,b);
174
next_key_length=key_length-b_length-pack_length;
177
(flag=mi_compare_text(keyseg->charset,a,a_length,b,b_length,
178
(my_bool) ((nextflag & SEARCH_PREFIX) &&
179
next_key_length <= 0),
180
(my_bool)!(nextflag & SEARCH_PREFIX))))
181
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
188
uint length=(uint) (end-a), a_length=length, b_length=length;
190
(flag= mi_compare_text(keyseg->charset, a, a_length, b, b_length,
191
(my_bool) ((nextflag & SEARCH_PREFIX) &&
192
next_key_length <= 0),
193
(my_bool)!(nextflag & SEARCH_PREFIX))))
194
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
199
case HA_KEYTYPE_BINARY:
201
if (keyseg->flag & HA_SPACE_PACK)
203
int a_length,b_length,pack_length;
204
get_key_length(a_length,a);
205
get_key_pack_length(b_length,pack_length,b);
206
next_key_length=key_length-b_length-pack_length;
209
(flag=compare_bin(a,a_length,b,b_length,
210
(my_bool) ((nextflag & SEARCH_PREFIX) &&
211
next_key_length <= 0),1)))
212
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
219
uint length=keyseg->length;
221
(flag=compare_bin(a,length,b,length,
222
(my_bool) ((nextflag & SEARCH_PREFIX) &&
223
next_key_length <= 0),0)))
224
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
229
case HA_KEYTYPE_VARTEXT1:
230
case HA_KEYTYPE_VARTEXT2:
232
int a_length,b_length,pack_length;
233
get_key_length(a_length,a);
234
get_key_pack_length(b_length,pack_length,b);
235
next_key_length=key_length-b_length-pack_length;
238
(flag= mi_compare_text(keyseg->charset,a,a_length,b,b_length,
239
(my_bool) ((nextflag & SEARCH_PREFIX) &&
240
next_key_length <= 0),
241
(my_bool) ((nextflag & (SEARCH_FIND |
245
HA_END_SPACE_ARE_EQUAL)))))
246
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
252
case HA_KEYTYPE_VARBINARY1:
253
case HA_KEYTYPE_VARBINARY2:
255
int a_length,b_length,pack_length;
256
get_key_length(a_length,a);
257
get_key_pack_length(b_length,pack_length,b);
258
next_key_length=key_length-b_length-pack_length;
261
(flag=compare_bin(a,a_length,b,b_length,
262
(my_bool) ((nextflag & SEARCH_PREFIX) &&
263
next_key_length <= 0), 0)))
264
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
270
case HA_KEYTYPE_INT8:
272
int i_1= (int) *((signed char*) a);
273
int i_2= (int) *((signed char*) b);
274
if (piks && (flag = CMP_NUM(i_1,i_2)))
275
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
280
case HA_KEYTYPE_SHORT_INT:
281
s_1= mi_sint2korr(a);
282
s_2= mi_sint2korr(b);
283
if (piks && (flag = CMP_NUM(s_1,s_2)))
284
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
286
b+= 2; /* sizeof(short int); */
288
case HA_KEYTYPE_USHORT_INT:
291
us_1= mi_sint2korr(a);
292
us_2= mi_sint2korr(b);
293
if (piks && (flag = CMP_NUM(us_1,us_2)))
294
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
296
b+=2; /* sizeof(short int); */
299
case HA_KEYTYPE_LONG_INT:
300
l_1= mi_sint4korr(a);
301
l_2= mi_sint4korr(b);
302
if (piks && (flag = CMP_NUM(l_1,l_2)))
303
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
305
b+= 4; /* sizeof(long int); */
307
case HA_KEYTYPE_ULONG_INT:
308
u_1= mi_sint4korr(a);
309
u_2= mi_sint4korr(b);
310
if (piks && (flag = CMP_NUM(u_1,u_2)))
311
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
313
b+= 4; /* sizeof(long int); */
315
case HA_KEYTYPE_INT24:
318
if (piks && (flag = CMP_NUM(l_1,l_2)))
319
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
323
case HA_KEYTYPE_UINT24:
326
if (piks && (flag = CMP_NUM(l_1,l_2)))
327
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
331
case HA_KEYTYPE_FLOAT:
335
The following may give a compiler warning about floating point
336
comparison not being safe, but this is ok in this context as
337
we are bascily doing sorting
339
if (piks && (flag = CMP_NUM(f_1,f_2)))
340
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
342
b+= 4; /* sizeof(float); */
344
case HA_KEYTYPE_DOUBLE:
348
The following may give a compiler warning about floating point
349
comparison not being safe, but this is ok in this context as
350
we are bascily doing sorting
352
if (piks && (flag = CMP_NUM(d_1,d_2)))
353
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
355
b+= 8; /* sizeof(double); */
357
case HA_KEYTYPE_NUM: /* Numeric key */
362
if (keyseg->flag & HA_REVERSE_SORT)
364
swap_variables(uchar*, a, b);
365
swap_flag=1; /* Remember swap of a & b */
366
end= a+ (int) (end-b);
368
if (keyseg->flag & HA_SPACE_PACK)
370
alength= *a++; blength= *b++;
372
next_key_length=key_length-blength-1;
376
alength= (int) (end-a);
377
blength=keyseg->length;
378
/* remove pre space from keys */
379
for ( ; alength && *a == ' ' ; a++, alength--) ;
380
for ( ; blength && *b == ' ' ; b++, blength--) ;
389
swap_variables(uchar*, a, b);
390
swap_variables(int, alength, blength);
391
swap_flag=1-swap_flag;
392
alength--; blength--;
397
while (alength && (*a == '+' || *a == '0'))
401
while (blength && (*b == '+' || *b == '0'))
405
if (alength != blength)
406
return (alength < blength) ? -1 : 1;
409
return ((int) a[-1] - (int) b[-1]);
417
if (swap_flag) /* Restore pointers */
418
swap_variables(uchar*, a, b);
421
#ifdef HAVE_LONG_LONG
422
case HA_KEYTYPE_LONGLONG:
425
ll_a= mi_sint8korr(a);
426
ll_b= mi_sint8korr(b);
427
if (piks && (flag = CMP_NUM(ll_a,ll_b)))
428
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
433
case HA_KEYTYPE_ULONGLONG:
436
ll_a= mi_uint8korr(a);
437
ll_b= mi_uint8korr(b);
438
if (piks && (flag = CMP_NUM(ll_a,ll_b)))
439
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
445
case HA_KEYTYPE_END: /* Ready */
446
goto end; /* diff_pos is incremented */
451
if (!(nextflag & SEARCH_FIND))
454
if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
455
return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
457
for (i=keyseg->length ; i-- > 0 ; )
461
flag= FCMP(a[-1],b[-1]);
465
if (nextflag & SEARCH_SAME)
466
return (flag); /* read same */
467
if (nextflag & SEARCH_BIGGER)
468
return (flag <= 0 ? -1 : 1); /* read next */
469
return (flag < 0 ? -1 : 1); /* read previous */
476
Find the first NULL value in index-suffix values tuple
480
keyseg Array of keyparts for key suffix
481
a Key suffix value tuple
484
Find the first NULL value in index-suffix values tuple.
485
TODO Consider optimizing this fuction or its use so we don't search for
486
NULL values in completely NOT NULL index suffixes.
489
First key part that has NULL as value in values tuple, or the last key part
490
(with keyseg->type==HA_TYPE_END) if values tuple doesn't contain NULLs.
493
HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
495
for (; (enum ha_base_keytype) keyseg->type != HA_KEYTYPE_END; keyseg++)
498
if (keyseg->null_bit)
503
end= a+ keyseg->length;
505
switch ((enum ha_base_keytype) keyseg->type) {
506
case HA_KEYTYPE_TEXT:
507
case HA_KEYTYPE_BINARY:
509
if (keyseg->flag & HA_SPACE_PACK)
512
get_key_length(a_length, a);
519
case HA_KEYTYPE_VARTEXT1:
520
case HA_KEYTYPE_VARTEXT2:
521
case HA_KEYTYPE_VARBINARY1:
522
case HA_KEYTYPE_VARBINARY2:
525
get_key_length(a_length, a);
530
if (keyseg->flag & HA_SPACE_PACK)
537
case HA_KEYTYPE_INT8:
538
case HA_KEYTYPE_SHORT_INT:
539
case HA_KEYTYPE_USHORT_INT:
540
case HA_KEYTYPE_LONG_INT:
541
case HA_KEYTYPE_ULONG_INT:
542
case HA_KEYTYPE_INT24:
543
case HA_KEYTYPE_UINT24:
544
#ifdef HAVE_LONG_LONG
545
case HA_KEYTYPE_LONGLONG:
546
case HA_KEYTYPE_ULONGLONG:
548
case HA_KEYTYPE_FLOAT:
549
case HA_KEYTYPE_DOUBLE:
552
case HA_KEYTYPE_END: /* purecov: inspected */
553
/* keep compiler happy */