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>
21
#include <my_handler.h>
24
#include "my_handler_errors.h"
26
int ha_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
27
uchar *b, uint b_length, my_bool part_key,
28
my_bool skip_end_space)
31
return charset_info->coll->strnncollsp(charset_info, a, a_length,
32
b, b_length, (my_bool)!skip_end_space);
33
return charset_info->coll->strnncoll(charset_info, a, a_length,
34
b, b_length, part_key);
38
static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
39
my_bool part_key, my_bool skip_end_space)
41
uint length= min(a_length,b_length);
42
uchar *end= a+ length;
46
if ((flag= (int) *a++ - (int) *b++))
48
if (part_key && b_length < a_length)
50
if (skip_end_space && a_length != b_length)
54
We are using space compression. We have to check if longer key
55
has next character < ' ', in which case it's less than the shorter
56
key that has an implicite space afterwards.
58
This code is identical to the one in
59
strings/ctype-simple.c:my_strnncollsp_simple
61
if (a_length < b_length)
63
/* put shorter key in a */
66
swap= -1; /* swap sign of result */
68
for (end= a + a_length-length; a < end ; a++)
71
return (*a < ' ') ? -swap : swap;
75
return (int) (a_length-b_length);
84
keyseg Array of key segments of key to compare
85
a First key to compare, in format from _mi_pack_key()
86
This is normally key specified by user
87
b Second key to compare. This is always from a row
88
key_length Length of key to compare. This can be shorter than
89
a to just compare sub keys
90
next_flag How keys should be compared
91
If bit SEARCH_FIND is not set the keys includes the row
92
position and this should also be compared
93
diff_pos OUT Number of first keypart where values differ, counting
95
diff_pos[1] OUT (b + diff_pos[1]) points to first value in tuple b
96
that is different from corresponding value in tuple a.
99
Example1: if the function is called for tuples
100
('aaa','bbb') and ('eee','fff'), then
101
diff_pos[0] = 1 (as 'aaa' != 'eee')
102
diff_pos[1] = 0 (offset from beggining of tuple b to 'eee' keypart).
104
Example2: if the index function is called for tuples
105
('aaa','bbb') and ('aaa','fff'),
106
diff_pos[0] = 2 (as 'aaa' != 'eee')
107
diff_pos[1] = 3 (offset from beggining of tuple b to 'fff' keypart,
108
here we assume that first key part is CHAR(3) NOT NULL)
111
Number-keys can't be splited
119
#define FCMP(A,B) ((int) (A) - (int) (B))
121
int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
122
register uchar *b, uint key_length, uint nextflag,
131
uint next_key_length;
135
for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
138
uint piks=! (keyseg->flag & HA_NO_SORT);
140
diff_pos[1]= (uint)(b - orig_b);
142
/* Handle NULL part */
143
if (keyseg->null_bit)
146
if (*a != *b && piks)
148
flag = (int) *a - (int) *b;
149
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
152
if (!*a++) /* If key was NULL */
154
if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
155
nextflag=SEARCH_SAME; /* Allow duplicate keys */
156
else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
159
This is only used from mi_check() to calculate cardinality.
160
It can't be used when searching for a key as this would cause
161
compare of (a,b) and (b,a) to return the same value.
165
next_key_length=key_length;
166
continue; /* To next key part */
169
end= a+ min(keyseg->length,key_length);
170
next_key_length=key_length-keyseg->length;
172
switch ((enum ha_base_keytype) keyseg->type) {
173
case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
174
if (keyseg->flag & HA_SPACE_PACK)
176
int a_length,b_length,pack_length;
177
get_key_length(a_length,a);
178
get_key_pack_length(b_length,pack_length,b);
179
next_key_length=key_length-b_length-pack_length;
182
(flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length,
183
(my_bool) ((nextflag & SEARCH_PREFIX) &&
184
next_key_length <= 0),
185
(my_bool)!(nextflag & SEARCH_PREFIX))))
186
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
193
uint length=(uint) (end-a), a_length=length, b_length=length;
195
(flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length,
196
(my_bool) ((nextflag & SEARCH_PREFIX) &&
197
next_key_length <= 0),
198
(my_bool)!(nextflag & SEARCH_PREFIX))))
199
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
204
case HA_KEYTYPE_BINARY:
206
if (keyseg->flag & HA_SPACE_PACK)
208
int a_length,b_length,pack_length;
209
get_key_length(a_length,a);
210
get_key_pack_length(b_length,pack_length,b);
211
next_key_length=key_length-b_length-pack_length;
214
(flag=compare_bin(a,a_length,b,b_length,
215
(my_bool) ((nextflag & SEARCH_PREFIX) &&
216
next_key_length <= 0),1)))
217
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
224
uint length=keyseg->length;
226
(flag=compare_bin(a,length,b,length,
227
(my_bool) ((nextflag & SEARCH_PREFIX) &&
228
next_key_length <= 0),0)))
229
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
234
case HA_KEYTYPE_VARTEXT1:
235
case HA_KEYTYPE_VARTEXT2:
237
int a_length,b_length,pack_length;
238
get_key_length(a_length,a);
239
get_key_pack_length(b_length,pack_length,b);
240
next_key_length=key_length-b_length-pack_length;
243
(flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length,
244
(my_bool) ((nextflag & SEARCH_PREFIX) &&
245
next_key_length <= 0),
246
(my_bool) ((nextflag & (SEARCH_FIND |
250
HA_END_SPACE_ARE_EQUAL)))))
251
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
257
case HA_KEYTYPE_VARBINARY1:
258
case HA_KEYTYPE_VARBINARY2:
260
int a_length,b_length,pack_length;
261
get_key_length(a_length,a);
262
get_key_pack_length(b_length,pack_length,b);
263
next_key_length=key_length-b_length-pack_length;
266
(flag=compare_bin(a,a_length,b,b_length,
267
(my_bool) ((nextflag & SEARCH_PREFIX) &&
268
next_key_length <= 0), 0)))
269
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
275
case HA_KEYTYPE_INT8:
277
int i_1= (int) *((signed char*) a);
278
int i_2= (int) *((signed char*) b);
279
if (piks && (flag = CMP_NUM(i_1,i_2)))
280
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
285
case HA_KEYTYPE_SHORT_INT:
286
s_1= mi_sint2korr(a);
287
s_2= mi_sint2korr(b);
288
if (piks && (flag = CMP_NUM(s_1,s_2)))
289
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
291
b+= 2; /* sizeof(short int); */
293
case HA_KEYTYPE_USHORT_INT:
296
us_1= mi_sint2korr(a);
297
us_2= mi_sint2korr(b);
298
if (piks && (flag = CMP_NUM(us_1,us_2)))
299
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
301
b+=2; /* sizeof(short int); */
304
case HA_KEYTYPE_LONG_INT:
305
l_1= mi_sint4korr(a);
306
l_2= mi_sint4korr(b);
307
if (piks && (flag = CMP_NUM(l_1,l_2)))
308
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
310
b+= 4; /* sizeof(long int); */
312
case HA_KEYTYPE_ULONG_INT:
313
u_1= mi_sint4korr(a);
314
u_2= mi_sint4korr(b);
315
if (piks && (flag = CMP_NUM(u_1,u_2)))
316
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
318
b+= 4; /* sizeof(long int); */
320
case HA_KEYTYPE_INT24:
323
if (piks && (flag = CMP_NUM(l_1,l_2)))
324
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
328
case HA_KEYTYPE_UINT24:
331
if (piks && (flag = CMP_NUM(l_1,l_2)))
332
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
336
case HA_KEYTYPE_FLOAT:
340
The following may give a compiler warning about floating point
341
comparison not being safe, but this is ok in this context as
342
we are bascily doing sorting
344
if (piks && (flag = CMP_NUM(f_1,f_2)))
345
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
347
b+= 4; /* sizeof(float); */
349
case HA_KEYTYPE_DOUBLE:
353
The following may give a compiler warning about floating point
354
comparison not being safe, but this is ok in this context as
355
we are bascily doing sorting
357
if (piks && (flag = CMP_NUM(d_1,d_2)))
358
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
360
b+= 8; /* sizeof(double); */
362
case HA_KEYTYPE_NUM: /* Numeric key */
367
if (keyseg->flag & HA_REVERSE_SORT)
369
swap_variables(uchar*, a, b);
370
swap_flag=1; /* Remember swap of a & b */
371
end= a+ (int) (end-b);
373
if (keyseg->flag & HA_SPACE_PACK)
375
alength= *a++; blength= *b++;
377
next_key_length=key_length-blength-1;
381
alength= (int) (end-a);
382
blength=keyseg->length;
383
/* remove pre space from keys */
384
for ( ; alength && *a == ' ' ; a++, alength--) ;
385
for ( ; blength && *b == ' ' ; b++, blength--) ;
394
swap_variables(uchar*, a, b);
395
swap_variables(int, alength, blength);
396
swap_flag=1-swap_flag;
397
alength--; blength--;
402
while (alength && (*a == '+' || *a == '0'))
406
while (blength && (*b == '+' || *b == '0'))
410
if (alength != blength)
411
return (alength < blength) ? -1 : 1;
414
return ((int) a[-1] - (int) b[-1]);
422
if (swap_flag) /* Restore pointers */
423
swap_variables(uchar*, a, b);
426
#ifdef HAVE_LONG_LONG
427
case HA_KEYTYPE_LONGLONG:
430
ll_a= mi_sint8korr(a);
431
ll_b= mi_sint8korr(b);
432
if (piks && (flag = CMP_NUM(ll_a,ll_b)))
433
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
438
case HA_KEYTYPE_ULONGLONG:
441
ll_a= mi_uint8korr(a);
442
ll_b= mi_uint8korr(b);
443
if (piks && (flag = CMP_NUM(ll_a,ll_b)))
444
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
450
case HA_KEYTYPE_END: /* Ready */
451
goto end; /* diff_pos is incremented */
456
if (!(nextflag & SEARCH_FIND))
459
if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
460
return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
462
for (i=keyseg->length ; i-- > 0 ; )
466
flag= FCMP(a[-1],b[-1]);
470
if (nextflag & SEARCH_SAME)
471
return (flag); /* read same */
472
if (nextflag & SEARCH_BIGGER)
473
return (flag <= 0 ? -1 : 1); /* read next */
474
return (flag < 0 ? -1 : 1); /* read previous */
481
Find the first NULL value in index-suffix values tuple
485
keyseg Array of keyparts for key suffix
486
a Key suffix value tuple
489
Find the first NULL value in index-suffix values tuple.
492
Consider optimizing this function or its use so we don't search for
493
NULL values in completely NOT NULL index suffixes.
496
First key part that has NULL as value in values tuple, or the last key
497
part (with keyseg->type==HA_TYPE_END) if values tuple doesn't contain
501
HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
503
for (; (enum ha_base_keytype) keyseg->type != HA_KEYTYPE_END; keyseg++)
506
if (keyseg->null_bit)
511
end= a+ keyseg->length;
513
switch ((enum ha_base_keytype) keyseg->type) {
514
case HA_KEYTYPE_TEXT:
515
case HA_KEYTYPE_BINARY:
517
if (keyseg->flag & HA_SPACE_PACK)
520
get_key_length(a_length, a);
527
case HA_KEYTYPE_VARTEXT1:
528
case HA_KEYTYPE_VARTEXT2:
529
case HA_KEYTYPE_VARBINARY1:
530
case HA_KEYTYPE_VARBINARY2:
533
get_key_length(a_length, a);
538
if (keyseg->flag & HA_SPACE_PACK)
545
case HA_KEYTYPE_INT8:
546
case HA_KEYTYPE_SHORT_INT:
547
case HA_KEYTYPE_USHORT_INT:
548
case HA_KEYTYPE_LONG_INT:
549
case HA_KEYTYPE_ULONG_INT:
550
case HA_KEYTYPE_INT24:
551
case HA_KEYTYPE_UINT24:
552
#ifdef HAVE_LONG_LONG
553
case HA_KEYTYPE_LONGLONG:
554
case HA_KEYTYPE_ULONGLONG:
556
case HA_KEYTYPE_FLOAT:
557
case HA_KEYTYPE_DOUBLE:
560
case HA_KEYTYPE_END: /* purecov: inspected */
561
/* keep compiler happy */
572
Register handler error messages for usage with my_error()
575
This is safe to call multiple times as my_error_register()
576
will ignore calls to register already registered error numbers.
580
void my_handler_error_register(void)
583
If you got compilation error here about compile_time_assert array, check
584
that every HA_ERR_xxx constant has a corresponding error message in
585
handler_error_messages[] list (check mysys/ma_handler_errors.h and
588
compile_time_assert(HA_ERR_FIRST + array_elements(handler_error_messages) ==
590
my_error_register(handler_error_messages, HA_ERR_FIRST,
591
HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
595
void my_handler_error_unregister(void)
597
my_error_unregister(HA_ERR_FIRST,
598
HA_ERR_FIRST+ array_elements(handler_error_messages)-1);