~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to mysys/my_handler.c

  • Committer: brian
  • Date: 2008-06-25 05:29:13 UTC
  • Revision ID: brian@localhost.localdomain-20080625052913-6upwo0jsrl4lnapl
clean slate

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 
 *
4
 
 *  Copyright (C) 2008 Sun Microsystems
5
 
 *
6
 
 *  This program is free software; you can redistribute it and/or modify
7
 
 *  it under the terms of the GNU General Public License as published by
8
 
 *  the Free Software Foundation; version 2 of the License.
9
 
 *
10
 
 *  This program is distributed in the hope that it will be useful,
11
 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 
 *  GNU General Public License for more details.
14
 
 *
15
 
 *  You should have received a copy of the GNU General Public License
16
 
 *  along with this program; if not, write to the Free Software
17
 
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 
 */
19
 
 
20
 
#include "config.h"
21
 
 
22
 
#include "drizzled/charset_info.h"
23
 
#include <drizzled/base.h>
24
 
#include <plugin/myisam/my_handler.h>
25
 
#include "drizzled/internal/my_sys.h"
26
 
 
27
 
#include <cassert>
28
 
#include <algorithm>
29
 
 
30
 
using namespace drizzled;
31
 
using namespace std;
32
 
 
33
 
template<class T>
34
 
int CMP_NUM(const T& a, const T&b)
35
 
{
36
 
  return (a < b) ? -1 : (a == b) ? 0 : 1;
37
 
}
38
 
 
39
 
 
40
 
int ha_compare_text(const CHARSET_INFO * const charset_info, unsigned char *a, uint32_t a_length,
41
 
                    unsigned char *b, uint32_t b_length, bool part_key,
42
 
                    bool skip_end_space)
 
1
/* Copyright (C) 2002-2006 MySQL AB
 
2
   
 
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
 
6
   of the License.
 
7
   
 
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.
 
12
 
 
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,
 
16
   MA 02111-1307, USA */
 
17
 
 
18
#include <my_global.h>
 
19
#include <m_ctype.h>
 
20
#include <my_base.h>
 
21
#include <my_handler.h>
 
22
#include <my_sys.h>
 
23
 
 
24
#include "my_handler_errors.h"
 
25
 
 
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)
43
29
{
44
30
  if (!part_key)
45
31
    return charset_info->coll->strnncollsp(charset_info, a, a_length,
46
 
                                           b, b_length, (bool)!skip_end_space);
 
32
                                           b, b_length, (my_bool)!skip_end_space);
47
33
  return charset_info->coll->strnncoll(charset_info, a, a_length,
48
34
                                       b, b_length, part_key);
49
35
}
50
36
 
51
37
 
52
 
static int compare_bin(unsigned char *a, uint32_t a_length, unsigned char *b, uint32_t b_length,
53
 
                       bool part_key, bool skip_end_space)
 
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)
54
40
{
55
 
  uint32_t length= min(a_length,b_length);
56
 
  unsigned char *end= a+ length;
 
41
  uint length= min(a_length,b_length);
 
42
  uchar *end= a+ length;
57
43
  int flag;
58
44
 
59
45
  while (a < end)
104
90
    next_flag   How keys should be compared
105
91
                If bit SEARCH_FIND is not set the keys includes the row
106
92
                position and this should also be compared
107
 
    diff_pos    OUT Number of first keypart where values differ, counting
 
93
    diff_pos    OUT Number of first keypart where values differ, counting 
108
94
                from one.
109
95
    diff_pos[1] OUT  (b + diff_pos[1]) points to first value in tuple b
110
96
                      that is different from corresponding value in tuple a.
111
 
 
112
 
  EXAMPLES
 
97
  
 
98
  EXAMPLES 
113
99
   Example1: if the function is called for tuples
114
100
     ('aaa','bbb') and ('eee','fff'), then
115
101
     diff_pos[0] = 1 (as 'aaa' != 'eee')
132
118
 
133
119
#define FCMP(A,B) ((int) (A) - (int) (B))
134
120
 
135
 
int ha_key_cmp(register HA_KEYSEG *keyseg, register unsigned char *a,
136
 
               register unsigned char *b, uint32_t key_length, uint32_t nextflag,
137
 
               uint32_t *diff_pos)
 
121
int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
 
122
               register uchar *b, uint key_length, uint nextflag,
 
123
               uint *diff_pos)
138
124
{
139
125
  int flag;
140
 
  int32_t l_1,l_2;
141
 
  uint32_t u_1,u_2;
 
126
  int16 s_1,s_2;
 
127
  int32 l_1,l_2;
 
128
  uint32 u_1,u_2;
 
129
  float f_1,f_2;
142
130
  double d_1,d_2;
143
 
  uint32_t next_key_length;
144
 
  unsigned char *orig_b= b;
 
131
  uint next_key_length;
 
132
  uchar *orig_b= b;
145
133
 
146
134
  *diff_pos=0;
147
135
  for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
148
136
  {
149
 
    unsigned char *end;
150
 
    uint32_t piks=! (keyseg->flag & HA_NO_SORT);
 
137
    uchar *end;
 
138
    uint piks=! (keyseg->flag & HA_NO_SORT);
151
139
    (*diff_pos)++;
152
140
    diff_pos[1]= (uint)(b - orig_b);
153
141
 
178
166
        continue;                               /* To next key part */
179
167
      }
180
168
    }
181
 
    end= a+ min((uint32_t)keyseg->length,key_length);
 
169
    end= a+ min(keyseg->length,key_length);
182
170
    next_key_length=key_length-keyseg->length;
183
171
 
184
172
    switch ((enum ha_base_keytype) keyseg->type) {
192
180
 
193
181
        if (piks &&
194
182
            (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length,
195
 
                                  (bool) ((nextflag & SEARCH_PREFIX) &&
 
183
                                  (my_bool) ((nextflag & SEARCH_PREFIX) &&
196
184
                                             next_key_length <= 0),
197
 
                                  (bool)!(nextflag & SEARCH_PREFIX))))
 
185
                                  (my_bool)!(nextflag & SEARCH_PREFIX))))
198
186
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
199
187
        a+=a_length;
200
188
        b+=b_length;
202
190
      }
203
191
      else
204
192
      {
205
 
        uint32_t length=(uint) (end-a), a_length=length, b_length=length;
 
193
        uint length=(uint) (end-a), a_length=length, b_length=length;
206
194
        if (piks &&
207
195
            (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length,
208
 
                                   (bool) ((nextflag & SEARCH_PREFIX) &&
 
196
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
209
197
                                              next_key_length <= 0),
210
 
                                   (bool)!(nextflag & SEARCH_PREFIX))))
 
198
                                   (my_bool)!(nextflag & SEARCH_PREFIX))))
211
199
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
212
200
        a=end;
213
201
        b+=length;
214
202
      }
215
203
      break;
216
204
    case HA_KEYTYPE_BINARY:
 
205
    case HA_KEYTYPE_BIT:
217
206
      if (keyseg->flag & HA_SPACE_PACK)
218
207
      {
219
208
        int a_length,b_length,pack_length;
223
212
 
224
213
        if (piks &&
225
214
            (flag=compare_bin(a,a_length,b,b_length,
226
 
                              (bool) ((nextflag & SEARCH_PREFIX) &&
 
215
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
227
216
                                         next_key_length <= 0),1)))
228
217
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
229
218
        a+=a_length;
232
221
      }
233
222
      else
234
223
      {
235
 
        uint32_t length=keyseg->length;
 
224
        uint length=keyseg->length;
236
225
        if (piks &&
237
226
            (flag=compare_bin(a,length,b,length,
238
 
                              (bool) ((nextflag & SEARCH_PREFIX) &&
 
227
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
239
228
                                         next_key_length <= 0),0)))
240
229
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
241
230
        a+=length;
252
241
 
253
242
        if (piks &&
254
243
            (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length,
255
 
                                   (bool) ((nextflag & SEARCH_PREFIX) &&
 
244
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
256
245
                                              next_key_length <= 0),
257
 
                                   (bool) ((nextflag & (SEARCH_FIND |
 
246
                                   (my_bool) ((nextflag & (SEARCH_FIND |
258
247
                                                           SEARCH_UPDATE)) ==
259
248
                                              SEARCH_FIND &&
260
249
                                              ! (keyseg->flag &
264
253
        b+= b_length;
265
254
        break;
266
255
      }
 
256
      break;
267
257
    case HA_KEYTYPE_VARBINARY1:
268
258
    case HA_KEYTYPE_VARBINARY2:
269
259
      {
274
264
 
275
265
        if (piks &&
276
266
            (flag=compare_bin(a,a_length,b,b_length,
277
 
                              (bool) ((nextflag & SEARCH_PREFIX) &&
 
267
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
278
268
                                         next_key_length <= 0), 0)))
279
269
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
280
270
        a+=a_length;
281
271
        b+=b_length;
282
272
        break;
283
273
      }
 
274
      break;
 
275
    case HA_KEYTYPE_INT8:
 
276
    {
 
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);
 
281
      a= end;
 
282
      b++;
 
283
      break;
 
284
    }
 
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);
 
290
      a=  end;
 
291
      b+= 2; /* sizeof(short int); */
 
292
      break;
 
293
    case HA_KEYTYPE_USHORT_INT:
 
294
      {
 
295
        uint16 us_1,us_2;
 
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);
 
300
        a=  end;
 
301
        b+=2; /* sizeof(short int); */
 
302
        break;
 
303
      }
284
304
    case HA_KEYTYPE_LONG_INT:
285
305
      l_1= mi_sint4korr(a);
286
306
      l_2= mi_sint4korr(b);
297
317
      a=  end;
298
318
      b+= 4; /* sizeof(long int); */
299
319
      break;
 
320
    case HA_KEYTYPE_INT24:
 
321
      l_1=mi_sint3korr(a);
 
322
      l_2=mi_sint3korr(b);
 
323
      if (piks && (flag = CMP_NUM(l_1,l_2)))
 
324
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
325
      a=  end;
 
326
      b+= 3;
 
327
      break;
 
328
    case HA_KEYTYPE_UINT24:
 
329
      l_1=mi_uint3korr(a);
 
330
      l_2=mi_uint3korr(b);
 
331
      if (piks && (flag = CMP_NUM(l_1,l_2)))
 
332
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
333
      a=  end;
 
334
      b+= 3;
 
335
      break;
 
336
    case HA_KEYTYPE_FLOAT:
 
337
      mi_float4get(f_1,a);
 
338
      mi_float4get(f_2,b);
 
339
      /*
 
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
 
343
      */
 
344
      if (piks && (flag = CMP_NUM(f_1,f_2)))
 
345
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
346
      a=  end;
 
347
      b+= 4; /* sizeof(float); */
 
348
      break;
300
349
    case HA_KEYTYPE_DOUBLE:
301
350
      mi_float8get(d_1,a);
302
351
      mi_float8get(d_2,b);
310
359
      a=  end;
311
360
      b+= 8;  /* sizeof(double); */
312
361
      break;
 
362
    case HA_KEYTYPE_NUM:                                /* Numeric key */
 
363
    {
 
364
      int swap_flag= 0;
 
365
      int alength,blength;
 
366
 
 
367
      if (keyseg->flag & HA_REVERSE_SORT)
 
368
      {
 
369
        swap_variables(uchar*, a, b);
 
370
        swap_flag=1;                            /* Remember swap of a & b */
 
371
        end= a+ (int) (end-b);
 
372
      }
 
373
      if (keyseg->flag & HA_SPACE_PACK)
 
374
      {
 
375
        alength= *a++; blength= *b++;
 
376
        end=a+alength;
 
377
        next_key_length=key_length-blength-1;
 
378
      }
 
379
      else
 
380
      {
 
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--) ;
 
386
      }
 
387
      if (piks)
 
388
      {
 
389
        if (*a == '-')
 
390
        {
 
391
          if (*b != '-')
 
392
            return -1;
 
393
          a++; b++;
 
394
          swap_variables(uchar*, a, b);
 
395
          swap_variables(int, alength, blength);
 
396
          swap_flag=1-swap_flag;
 
397
          alength--; blength--;
 
398
          end=a+alength;
 
399
        }
 
400
        else if (*b == '-')
 
401
          return 1;
 
402
        while (alength && (*a == '+' || *a == '0'))
 
403
        {
 
404
          a++; alength--;
 
405
        }
 
406
        while (blength && (*b == '+' || *b == '0'))
 
407
        {
 
408
          b++; blength--;
 
409
        }
 
410
        if (alength != blength)
 
411
          return (alength < blength) ? -1 : 1;
 
412
        while (a < end)
 
413
          if (*a++ !=  *b++)
 
414
            return ((int) a[-1] - (int) b[-1]);
 
415
      }
 
416
      else
 
417
      {
 
418
        b+=(end-a);
 
419
        a=end;
 
420
      }
 
421
 
 
422
      if (swap_flag)                            /* Restore pointers */
 
423
        swap_variables(uchar*, a, b);
 
424
      break;
 
425
    }
 
426
#ifdef HAVE_LONG_LONG
313
427
    case HA_KEYTYPE_LONGLONG:
314
428
    {
315
 
      int64_t ll_a,ll_b;
 
429
      longlong ll_a,ll_b;
316
430
      ll_a= mi_sint8korr(a);
317
431
      ll_b= mi_sint8korr(b);
318
432
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
323
437
    }
324
438
    case HA_KEYTYPE_ULONGLONG:
325
439
    {
326
 
      uint64_t ll_a,ll_b;
 
440
      ulonglong ll_a,ll_b;
327
441
      ll_a= mi_uint8korr(a);
328
442
      ll_b= mi_uint8korr(b);
329
443
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
332
446
      b+= 8;
333
447
      break;
334
448
    }
 
449
#endif
335
450
    case HA_KEYTYPE_END:                        /* Ready */
336
451
      goto end;                                 /* diff_pos is incremented */
337
452
    }
340
455
end:
341
456
  if (!(nextflag & SEARCH_FIND))
342
457
  {
343
 
    uint32_t i;
 
458
    uint i;
344
459
    if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
345
460
      return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
346
461
    flag=0;
383
498
    NULLs.
384
499
*/
385
500
 
386
 
HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, unsigned char *a)
 
501
HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, uchar *a)
387
502
{
388
503
  for (; (enum ha_base_keytype) keyseg->type != HA_KEYTYPE_END; keyseg++)
389
504
  {
390
 
    unsigned char *end;
 
505
    uchar *end;
391
506
    if (keyseg->null_bit)
392
507
    {
393
508
      if (!*a++)
398
513
    switch ((enum ha_base_keytype) keyseg->type) {
399
514
    case HA_KEYTYPE_TEXT:
400
515
    case HA_KEYTYPE_BINARY:
 
516
    case HA_KEYTYPE_BIT:
401
517
      if (keyseg->flag & HA_SPACE_PACK)
402
518
      {
403
519
        int a_length;
418
534
        a+= a_length;
419
535
        break;
420
536
      }
 
537
    case HA_KEYTYPE_NUM:
 
538
      if (keyseg->flag & HA_SPACE_PACK)
 
539
      {
 
540
        int alength= *a++;
 
541
        end= a+alength;
 
542
      }
 
543
      a= end;
 
544
      break;
 
545
    case HA_KEYTYPE_INT8:
 
546
    case HA_KEYTYPE_SHORT_INT:
 
547
    case HA_KEYTYPE_USHORT_INT:
421
548
    case HA_KEYTYPE_LONG_INT:
422
549
    case HA_KEYTYPE_ULONG_INT:
 
550
    case HA_KEYTYPE_INT24:
 
551
    case HA_KEYTYPE_UINT24:
 
552
#ifdef HAVE_LONG_LONG
423
553
    case HA_KEYTYPE_LONGLONG:
424
554
    case HA_KEYTYPE_ULONGLONG:
 
555
#endif
 
556
    case HA_KEYTYPE_FLOAT:
425
557
    case HA_KEYTYPE_DOUBLE:
426
558
      a= end;
427
559
      break;
428
 
    case HA_KEYTYPE_END:
 
560
    case HA_KEYTYPE_END:                        /* purecov: inspected */
429
561
      /* keep compiler happy */
430
 
      assert(0);
 
562
      DBUG_ASSERT(0);
431
563
      break;
432
564
    }
433
565
  }
436
568
 
437
569
 
438
570
 
 
571
/*
 
572
  Register handler error messages for usage with my_error()
 
573
 
 
574
  NOTES
 
575
    This is safe to call multiple times as my_error_register()
 
576
    will ignore calls to register already registered error numbers.
 
577
*/
 
578
 
 
579
 
 
580
void my_handler_error_register(void)
 
581
{
 
582
  /*
 
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
 
586
    include/my_base.h).
 
587
  */
 
588
  compile_time_assert(HA_ERR_FIRST + array_elements(handler_error_messages) ==
 
589
                      HA_ERR_LAST + 1);
 
590
  my_error_register(handler_error_messages, HA_ERR_FIRST,
 
591
                    HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
 
592
}
 
593
 
 
594
 
 
595
void my_handler_error_unregister(void)
 
596
{
 
597
  my_error_unregister(HA_ERR_FIRST,
 
598
                      HA_ERR_FIRST+ array_elements(handler_error_messages)-1);
 
599
}