~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/hp_hash.c

  • Committer: Monty Taylor
  • Date: 2008-09-16 00:00:48 UTC
  • mto: This revision was merged to the branch mainline in revision 391.
  • Revision ID: monty@inaugust.com-20080916000048-3rvrv3gv9l0ad3gs
Fixed copyright headers in drizzled/

Show diffs side-by-side

added added

removed removed

Lines of Context:
11
11
 
12
12
   You should have received a copy of the GNU General Public License
13
13
   along with this program; if not, write to the Free Software
14
 
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
15
15
 
16
16
/* The hash functions used for saveing keys */
17
17
 
18
 
#include "heap_priv.h"
19
 
 
20
 
#include "drizzled/charset_info.h"
21
 
#include <drizzled/util/test.h>
22
 
 
23
 
#include <math.h>
24
 
#include <string.h>
25
 
 
26
 
#include <cassert>
27
 
 
28
 
using namespace drizzled;
29
 
using namespace std;
30
 
 
31
 
static uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key);
32
 
static int hp_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec, const unsigned char *key);
 
18
#include "heapdef.h"
 
19
#include <mystrings/m_ctype.h>
 
20
 
 
21
 
 
22
 
 
23
/*
 
24
  Find out how many rows there is in the given range
 
25
 
 
26
  SYNOPSIS
 
27
    hp_rb_records_in_range()
 
28
    info                HEAP handler
 
29
    inx                 Index to use
 
30
    min_key             Min key. Is = 0 if no min range
 
31
    max_key             Max key. Is = 0 if no max range
 
32
 
 
33
  NOTES
 
34
    min_key.flag can have one of the following values:
 
35
      HA_READ_KEY_EXACT         Include the key in the range
 
36
      HA_READ_AFTER_KEY         Don't include key in range
 
37
 
 
38
    max_key.flag can have one of the following values:
 
39
      HA_READ_BEFORE_KEY        Don't include key in range
 
40
      HA_READ_AFTER_KEY         Include all 'end_key' values in the range
 
41
 
 
42
  RETURN
 
43
   HA_POS_ERROR         Something is wrong with the index tree.
 
44
   0                    There is no matching keys in the given range
 
45
   number > 0           There is approximately 'number' matching rows in
 
46
                        the range.
 
47
*/
 
48
 
 
49
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx,  key_range *min_key,
 
50
                               key_range *max_key)
 
51
{
 
52
  ha_rows start_pos, end_pos;
 
53
  HP_KEYDEF *keyinfo= info->s->keydef + inx;
 
54
  TREE *rb_tree = &keyinfo->rb_tree;
 
55
  heap_rb_param custom_arg;
 
56
 
 
57
  info->lastinx= inx;
 
58
  custom_arg.keyseg= keyinfo->seg;
 
59
  custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
 
60
  if (min_key)
 
61
  {
 
62
    custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
 
63
                                          (uchar*) min_key->key,
 
64
                                          min_key->keypart_map);
 
65
    start_pos= tree_record_pos(rb_tree, info->recbuf, min_key->flag,
 
66
                               &custom_arg);
 
67
  }
 
68
  else
 
69
  {
 
70
    start_pos= 0;
 
71
  }
 
72
 
 
73
  if (max_key)
 
74
  {
 
75
    custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
 
76
                                          (uchar*) max_key->key,
 
77
                                          max_key->keypart_map);
 
78
    end_pos= tree_record_pos(rb_tree, info->recbuf, max_key->flag,
 
79
                             &custom_arg);
 
80
  }
 
81
  else
 
82
  {
 
83
    end_pos= rb_tree->elements_in_tree + (ha_rows)1;
 
84
  }
 
85
 
 
86
  if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
 
87
    return(HA_POS_ERROR);
 
88
  return(end_pos < start_pos ? (ha_rows) 0 :
 
89
              (end_pos == start_pos ? (ha_rows) 1 : end_pos - start_pos));
 
90
}
33
91
 
34
92
 
35
93
        /* Search after a record based on a key */
36
94
        /* Sets info->current_ptr to found record */
37
95
        /* next_flag:  Search=0, next=1, prev =2, same =3 */
38
96
 
39
 
unsigned char *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const unsigned char *key,
40
 
                uint32_t nextflag)
 
97
uchar *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key,
 
98
                uint nextflag)
41
99
{
42
100
  register HASH_INFO *pos,*prev_ptr;
43
101
  int flag;
44
 
  uint32_t old_nextflag;
45
 
  HP_SHARE *share=info->getShare();
 
102
  uint old_nextflag;
 
103
  HP_SHARE *share=info->s;
46
104
  old_nextflag=nextflag;
47
105
  flag=1;
48
106
  prev_ptr=0;
66
124
        case 2:                                 /* Search previous */
67
125
          if (pos->ptr_to_rec == info->current_ptr)
68
126
          {
69
 
            errno=HA_ERR_KEY_NOT_FOUND; /* If gpos == 0 */
 
127
            my_errno=HA_ERR_KEY_NOT_FOUND;      /* If gpos == 0 */
70
128
            info->current_hash_ptr=prev_ptr;
71
129
            return(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
72
130
          }
91
149
    }
92
150
    while ((pos=pos->next_key));
93
151
  }
94
 
  errno=HA_ERR_KEY_NOT_FOUND;
 
152
  my_errno=HA_ERR_KEY_NOT_FOUND;
95
153
  if (nextflag == 2 && ! info->current_ptr)
96
154
  {
97
155
    /* Do a previous from end */
100
158
  }
101
159
 
102
160
  if (old_nextflag && nextflag)
103
 
    errno=HA_ERR_RECORD_CHANGED;                /* Didn't find old record */
104
 
  info->current_hash_ptr=0;
 
161
    my_errno=HA_ERR_RECORD_CHANGED;             /* Didn't find old record */
 
162
  info->current_hash_ptr=0;  
105
163
  return((info->current_ptr= 0));
106
164
}
107
165
 
111
169
  since last read !
112
170
*/
113
171
 
114
 
unsigned char *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const unsigned char *key,
 
172
uchar *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key,
115
173
                      HASH_INFO *pos)
116
174
{
117
175
  while ((pos= pos->next_key))
122
180
      return (info->current_ptr= pos->ptr_to_rec);
123
181
    }
124
182
  }
125
 
  errno=HA_ERR_KEY_NOT_FOUND;
 
183
  my_errno=HA_ERR_KEY_NOT_FOUND;
126
184
  info->current_hash_ptr=0;
127
185
  return ((info->current_ptr= 0));
128
186
}
135
193
      hashnr     Hash value
136
194
      buffmax    Value such that
137
195
                 2^(n-1) < maxlength <= 2^n = buffmax
138
 
      maxlength
139
 
 
 
196
      maxlength  
 
197
  
140
198
  RETURN
141
199
    Array index, in [0..maxlength)
142
200
*/
167
225
  return;
168
226
}
169
227
 
 
228
#ifndef NEW_HASH_FUNCTION
 
229
 
170
230
        /* Calc hashvalue for a key */
171
231
 
172
 
static uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key)
 
232
uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key)
173
233
{
174
 
  /*register*/
 
234
  /*register*/ 
175
235
  uint32_t nr=1, nr2=4;
176
236
  HA_KEYSEG *seg,*endseg;
177
237
 
178
238
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
179
239
  {
180
 
    unsigned char *pos=(unsigned char*) key;
 
240
    uchar *pos=(uchar*) key;
181
241
    key+=seg->length;
182
242
    if (seg->null_bit)
183
243
    {
195
255
    if (seg->type == HA_KEYTYPE_TEXT)
196
256
    {
197
257
       const CHARSET_INFO * const cs= seg->charset;
198
 
       uint32_t length= seg->length;
 
258
       uint length= seg->length;
199
259
       if (cs->mbmaxlen > 1)
200
260
       {
201
 
         uint32_t char_length;
 
261
         uint char_length;
202
262
         char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
203
263
         set_if_smaller(length, char_length);
204
264
       }
207
267
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
208
268
    {
209
269
       const CHARSET_INFO * const cs= seg->charset;
210
 
       uint32_t pack_length= 2;                     /* Key packing is constant */
211
 
       uint32_t length= uint2korr(pos);
 
270
       uint pack_length= 2;                     /* Key packing is constant */
 
271
       uint length= uint2korr(pos);
212
272
       if (cs->mbmaxlen > 1)
213
273
       {
214
 
         uint32_t char_length;
 
274
         uint char_length;
215
275
         char_length= my_charpos(cs, pos +pack_length,
216
276
                                 pos +pack_length + length,
217
277
                                 seg->length/cs->mbmaxlen);
222
282
    }
223
283
    else
224
284
    {
225
 
      for (; pos < (unsigned char*) key ; pos++)
 
285
      for (; pos < (uchar*) key ; pos++)
226
286
      {
227
287
        nr^=(uint32_t) ((((uint) nr & 63)+nr2)*((uint) *pos)) + (nr << 8);
228
288
        nr2+=3;
234
294
 
235
295
        /* Calc hashvalue for a key in a record */
236
296
 
237
 
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const unsigned char *rec)
 
297
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec)
238
298
{
239
299
  uint32_t nr=1, nr2=4;
240
300
  HA_KEYSEG *seg,*endseg;
241
301
 
242
302
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
243
303
  {
244
 
    unsigned char *pos=(unsigned char*) rec+seg->start,*end=pos+seg->length;
 
304
    uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
245
305
    if (seg->null_bit)
246
306
    {
247
307
      if (rec[seg->null_pos] & seg->null_bit)
253
313
    if (seg->type == HA_KEYTYPE_TEXT)
254
314
    {
255
315
      const CHARSET_INFO * const cs= seg->charset;
256
 
      uint32_t char_length= seg->length;
 
316
      uint char_length= seg->length;
257
317
      if (cs->mbmaxlen > 1)
258
318
      {
259
319
        char_length= my_charpos(cs, pos, pos + char_length,
260
320
                                char_length / cs->mbmaxlen);
261
 
        set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
 
321
        set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
262
322
      }
263
323
      cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
264
324
    }
265
325
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
266
326
    {
267
327
      const CHARSET_INFO * const cs= seg->charset;
268
 
      uint32_t pack_length= seg->bit_start;
269
 
      uint32_t length= (pack_length == 1 ? (uint) *(unsigned char*) pos : uint2korr(pos));
 
328
      uint pack_length= seg->bit_start;
 
329
      uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
270
330
      if (cs->mbmaxlen > 1)
271
331
      {
272
 
        uint32_t char_length;
 
332
        uint char_length;
273
333
        char_length= my_charpos(cs, pos + pack_length,
274
334
                                pos + pack_length + length,
275
335
                                seg->length/cs->mbmaxlen);
289
349
  return(nr);
290
350
}
291
351
 
 
352
#else
 
353
 
 
354
/*
 
355
 * Fowler/Noll/Vo hash
 
356
 *
 
357
 * The basis of the hash algorithm was taken from an idea sent by email to the
 
358
 * IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and
 
359
 * Glenn Fowler (gsf@research.att.com).  Landon Curt Noll (chongo@toad.com)
 
360
 * later improved on their algorithm.
 
361
 *
 
362
 * The magic is in the interesting relationship between the special prime
 
363
 * 16777619 (2^24 + 403) and 2^32 and 2^8.
 
364
 *
 
365
 * This hash produces the fewest collisions of any function that we've seen so
 
366
 * far, and works well on both numbers and strings.
 
367
 */
 
368
 
 
369
uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key)
 
370
{
 
371
  /*
 
372
    Note, if a key consists of a combination of numeric and
 
373
    a text columns, it most likely won't work well.
 
374
    Making text columns work with NEW_HASH_FUNCTION
 
375
    needs also changes in strings/ctype-xxx.c.
 
376
  */
 
377
  uint32_t nr= 1, nr2= 4;
 
378
  HA_KEYSEG *seg,*endseg;
 
379
 
 
380
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
 
381
  {
 
382
    uchar *pos=(uchar*) key;
 
383
    key+=seg->length;
 
384
    if (seg->null_bit)
 
385
    {
 
386
      key++;
 
387
      if (*pos)
 
388
      {
 
389
        nr^= (nr << 1) | 1;
 
390
        /* Add key pack length (2) to key for VARCHAR segments */
 
391
        if (seg->type == HA_KEYTYPE_VARTEXT1)
 
392
          key+= 2;
 
393
        continue;
 
394
      }
 
395
      pos++;
 
396
    }
 
397
    if (seg->type == HA_KEYTYPE_TEXT)
 
398
    {
 
399
      seg->charset->coll->hash_sort(seg->charset, pos, ((uchar*)key)-pos,
 
400
                                    &nr, &nr2);
 
401
    }
 
402
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
 
403
    {
 
404
      uint pack_length= 2;                      /* Key packing is constant */
 
405
      uint length= uint2korr(pos);
 
406
      seg->charset->coll->hash_sort(seg->charset, pos+pack_length, length,
 
407
                                    &nr, &nr2);
 
408
      key+= pack_length;
 
409
    }
 
410
    else
 
411
    {
 
412
      for ( ; pos < (uchar*) key ; pos++)
 
413
      {
 
414
        nr *=16777619; 
 
415
        nr ^=(uint) *pos;
 
416
      }
 
417
    }
 
418
  }
 
419
  return(nr);
 
420
}
 
421
 
 
422
        /* Calc hashvalue for a key in a record */
 
423
 
 
424
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec)
 
425
{
 
426
  uint32_t nr= 1, nr2= 4;
 
427
  HA_KEYSEG *seg,*endseg;
 
428
 
 
429
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
 
430
  {
 
431
    uchar *pos=(uchar*) rec+seg->start;
 
432
    if (seg->null_bit)
 
433
    {
 
434
      if (rec[seg->null_pos] & seg->null_bit)
 
435
      {
 
436
        nr^= (nr << 1) | 1;
 
437
        continue;
 
438
      }
 
439
    }
 
440
    if (seg->type == HA_KEYTYPE_TEXT)
 
441
    {
 
442
      uint char_length= seg->length; /* TODO: fix to use my_charpos() */
 
443
      seg->charset->coll->hash_sort(seg->charset, pos, char_length,
 
444
                                    &nr, &nr2);
 
445
    }
 
446
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
 
447
    {
 
448
      uint pack_length= seg->bit_start;
 
449
      uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
 
450
      seg->charset->coll->hash_sort(seg->charset, pos+pack_length,
 
451
                                    length, &nr, &nr2);
 
452
    }
 
453
    else
 
454
    {
 
455
      uchar *end= pos+seg->length;
 
456
      for ( ; pos < end ; pos++)
 
457
      {
 
458
        nr *=16777619; 
 
459
        nr ^=(uint) *pos;
 
460
      }
 
461
    }
 
462
  }
 
463
  return(nr);
 
464
}
 
465
 
 
466
#endif
 
467
 
 
468
 
292
469
/*
293
470
  Compare keys for two records. Returns 0 if they are identical
294
471
 
298
475
    rec1                Record to compare
299
476
    rec2                Other record to compare
300
477
    diff_if_only_endspace_difference
301
 
                        Different number of end space is significant
 
478
                        Different number of end space is significant    
302
479
 
303
480
  NOTES
304
481
    diff_if_only_endspace_difference is used to allow us to insert
309
486
    <> 0        Key differes
310
487
*/
311
488
 
312
 
int hp_rec_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec1, const unsigned char *rec2,
 
489
int hp_rec_key_cmp(HP_KEYDEF *keydef, const uchar *rec1, const uchar *rec2,
313
490
                   bool diff_if_only_endspace_difference)
314
491
{
315
492
  HA_KEYSEG *seg,*endseg;
327
504
    if (seg->type == HA_KEYTYPE_TEXT)
328
505
    {
329
506
      const CHARSET_INFO * const cs= seg->charset;
330
 
      uint32_t char_length1;
331
 
      uint32_t char_length2;
332
 
      unsigned char *pos1= (unsigned char*)rec1 + seg->start;
333
 
      unsigned char *pos2= (unsigned char*)rec2 + seg->start;
 
507
      uint char_length1;
 
508
      uint char_length2;
 
509
      uchar *pos1= (uchar*)rec1 + seg->start;
 
510
      uchar *pos2= (uchar*)rec2 + seg->start;
334
511
      if (cs->mbmaxlen > 1)
335
512
      {
336
 
        uint32_t char_length= seg->length / cs->mbmaxlen;
 
513
        uint char_length= seg->length / cs->mbmaxlen;
337
514
        char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
338
 
        set_if_smaller(char_length1, (uint32_t)seg->length);
 
515
        set_if_smaller(char_length1, seg->length);
339
516
        char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
340
 
        set_if_smaller(char_length2, (uint32_t)seg->length);
 
517
        set_if_smaller(char_length2, seg->length);
341
518
      }
342
519
      else
343
520
      {
350
527
    }
351
528
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
352
529
    {
353
 
      unsigned char *pos1= (unsigned char*) rec1 + seg->start;
354
 
      unsigned char *pos2= (unsigned char*) rec2 + seg->start;
355
 
      uint32_t char_length1, char_length2;
356
 
      uint32_t pack_length= seg->bit_start;
 
530
      uchar *pos1= (uchar*) rec1 + seg->start;
 
531
      uchar *pos2= (uchar*) rec2 + seg->start;
 
532
      uint char_length1, char_length2;
 
533
      uint pack_length= seg->bit_start;
357
534
      const CHARSET_INFO * const cs= seg->charset;
358
535
      if (pack_length == 1)
359
536
      {
360
 
        char_length1= (uint) *(unsigned char*) pos1++;
361
 
        char_length2= (uint) *(unsigned char*) pos2++;
 
537
        char_length1= (uint) *(uchar*) pos1++;
 
538
        char_length2= (uint) *(uchar*) pos2++;
362
539
      }
363
540
      else
364
541
      {
369
546
      }
370
547
      if (cs->mbmaxlen > 1)
371
548
      {
372
 
        uint32_t safe_length1= char_length1;
373
 
        uint32_t safe_length2= char_length2;
374
 
        uint32_t char_length= seg->length / cs->mbmaxlen;
 
549
        uint safe_length1= char_length1;
 
550
        uint safe_length2= char_length2;
 
551
        uint char_length= seg->length / cs->mbmaxlen;
375
552
        char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
376
553
        set_if_smaller(char_length1, safe_length1);
377
554
        char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
396
573
 
397
574
        /* Compare a key in a record to a whole key */
398
575
 
399
 
static int hp_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec, const unsigned char *key)
 
576
int hp_key_cmp(HP_KEYDEF *keydef, const uchar *rec, const uchar *key)
400
577
{
401
578
  HA_KEYSEG *seg,*endseg;
402
579
 
420
597
    if (seg->type == HA_KEYTYPE_TEXT)
421
598
    {
422
599
      const CHARSET_INFO * const cs= seg->charset;
423
 
      uint32_t char_length_key;
424
 
      uint32_t char_length_rec;
425
 
      unsigned char *pos= (unsigned char*) rec + seg->start;
 
600
      uint char_length_key;
 
601
      uint char_length_rec;
 
602
      uchar *pos= (uchar*) rec + seg->start;
426
603
      if (cs->mbmaxlen > 1)
427
604
      {
428
 
        uint32_t char_length= seg->length / cs->mbmaxlen;
 
605
        uint char_length= seg->length / cs->mbmaxlen;
429
606
        char_length_key= my_charpos(cs, key, key + seg->length, char_length);
430
 
        set_if_smaller(char_length_key, (uint32_t)seg->length);
 
607
        set_if_smaller(char_length_key, seg->length);
431
608
        char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length);
432
 
        set_if_smaller(char_length_rec, (uint32_t)seg->length);
 
609
        set_if_smaller(char_length_rec, seg->length);
433
610
      }
434
611
      else
435
612
      {
436
613
        char_length_key= seg->length;
437
614
        char_length_rec= seg->length;
438
615
      }
439
 
 
 
616
      
440
617
      if (seg->charset->coll->strnncollsp(seg->charset,
441
 
                                          (unsigned char*) pos, char_length_rec,
442
 
                                          (unsigned char*) key, char_length_key, 0))
 
618
                                          (uchar*) pos, char_length_rec,
 
619
                                          (uchar*) key, char_length_key, 0))
443
620
        return 1;
444
621
    }
445
622
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
446
623
    {
447
 
      unsigned char *pos= (unsigned char*) rec + seg->start;
 
624
      uchar *pos= (uchar*) rec + seg->start;
448
625
      const CHARSET_INFO * const cs= seg->charset;
449
 
      uint32_t pack_length= seg->bit_start;
450
 
      uint32_t char_length_rec= (pack_length == 1 ? (uint) *(unsigned char*) pos :
 
626
      uint pack_length= seg->bit_start;
 
627
      uint char_length_rec= (pack_length == 1 ? (uint) *(uchar*) pos :
451
628
                             uint2korr(pos));
452
629
      /* Key segments are always packed with 2 bytes */
453
 
      uint32_t char_length_key= uint2korr(key);
 
630
      uint char_length_key= uint2korr(key);
454
631
      pos+= pack_length;
455
632
      key+= 2;                                  /* skip key pack length */
456
633
      if (cs->mbmaxlen > 1)
457
634
      {
458
 
        uint32_t char_length1, char_length2;
459
 
        char_length1= char_length2= seg->length / cs->mbmaxlen;
 
635
        uint char_length1, char_length2;
 
636
        char_length1= char_length2= seg->length / cs->mbmaxlen; 
460
637
        char_length1= my_charpos(cs, key, key + char_length_key, char_length1);
461
638
        set_if_smaller(char_length_key, char_length1);
462
639
        char_length2= my_charpos(cs, pos, pos + char_length_rec, char_length2);
464
641
      }
465
642
 
466
643
      if (cs->coll->strnncollsp(seg->charset,
467
 
                                (unsigned char*) pos, char_length_rec,
468
 
                                (unsigned char*) key, char_length_key, 0))
 
644
                                (uchar*) pos, char_length_rec,
 
645
                                (uchar*) key, char_length_key, 0))
469
646
        return 1;
470
647
    }
471
648
    else
480
657
 
481
658
        /* Copy a key from a record to a keybuffer */
482
659
 
483
 
void hp_make_key(HP_KEYDEF *keydef, unsigned char *key, const unsigned char *rec)
 
660
void hp_make_key(HP_KEYDEF *keydef, uchar *key, const uchar *rec)
484
661
{
485
662
  HA_KEYSEG *seg,*endseg;
486
663
 
487
664
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
488
665
  {
489
666
    const CHARSET_INFO * const cs= seg->charset;
490
 
    uint32_t char_length= seg->length;
491
 
    unsigned char *pos= (unsigned char*) rec + seg->start;
 
667
    uint char_length= seg->length;
 
668
    uchar *pos= (uchar*) rec + seg->start;
492
669
    if (seg->null_bit)
493
670
      *key++= test(rec[seg->null_pos] & seg->null_bit);
494
671
    if (cs->mbmaxlen > 1)
495
672
    {
496
673
      char_length= my_charpos(cs, pos, pos + seg->length,
497
674
                              char_length / cs->mbmaxlen);
498
 
      set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
 
675
      set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
499
676
    }
500
677
    if (seg->type == HA_KEYTYPE_VARTEXT1)
501
678
      char_length+= seg->bit_start;             /* Copy also length */
511
688
    set_if_smaller(char_length,length);                                 \
512
689
  } while(0)
513
690
 
 
691
 
 
692
uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key, 
 
693
                    const uchar *rec, uchar *recpos)
 
694
{
 
695
  uchar *start_key= key;
 
696
  HA_KEYSEG *seg, *endseg;
 
697
 
 
698
  for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
 
699
  {
 
700
    uint char_length;
 
701
    if (seg->null_bit)
 
702
    {
 
703
      if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
 
704
        continue;
 
705
    }
 
706
    if (seg->flag & HA_SWAP_KEY)
 
707
    {
 
708
      uint length= seg->length;
 
709
      uchar *pos= (uchar*) rec + seg->start;
 
710
      
 
711
#ifdef HAVE_ISNAN
 
712
      if (seg->type == HA_KEYTYPE_FLOAT)
 
713
      {
 
714
        float nr;
 
715
        float4get(nr, pos);
 
716
        if (isnan(nr))
 
717
        {
 
718
          /* Replace NAN with zero */
 
719
          memset(key, 0, length);
 
720
          key+= length;
 
721
          continue;
 
722
        }
 
723
      }
 
724
      else if (seg->type == HA_KEYTYPE_DOUBLE)
 
725
      {
 
726
        double nr;
 
727
        float8get(nr, pos);
 
728
        if (isnan(nr))
 
729
        {
 
730
          memset(key, 0, length);
 
731
          key+= length;
 
732
          continue;
 
733
        }
 
734
      }
 
735
#endif
 
736
      pos+= length;
 
737
      while (length--)
 
738
      {
 
739
        *key++= *--pos;
 
740
      }
 
741
      continue;
 
742
    }
 
743
 
 
744
    if (seg->flag & HA_VAR_LENGTH_PART)
 
745
    {
 
746
      uchar *pos=      (uchar*) rec + seg->start;
 
747
      uint length=     seg->length;
 
748
      uint pack_length= seg->bit_start;
 
749
      uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
 
750
                        uint2korr(pos));
 
751
      const CHARSET_INFO * const cs= seg->charset;
 
752
      char_length= length/cs->mbmaxlen;
 
753
 
 
754
      pos+= pack_length;                        /* Skip VARCHAR length */
 
755
      set_if_smaller(length,tmp_length);
 
756
      FIX_LENGTH(cs, pos, length, char_length);
 
757
      store_key_length_inc(key,char_length);
 
758
      memcpy(key,pos,(size_t) char_length);
 
759
      key+= char_length;
 
760
      continue;
 
761
    }
 
762
 
 
763
    char_length= seg->length;
 
764
    if (seg->charset->mbmaxlen > 1)
 
765
    {
 
766
      char_length= my_charpos(seg->charset, 
 
767
                              rec + seg->start, rec + seg->start + char_length,
 
768
                              char_length / seg->charset->mbmaxlen);
 
769
      set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
 
770
      if (char_length < seg->length)
 
771
        seg->charset->cset->fill(seg->charset, (char*) key + char_length,
 
772
                                 seg->length - char_length, ' ');
 
773
    }
 
774
    memcpy(key, rec + seg->start, (size_t) char_length);
 
775
    key+= seg->length;
 
776
  }
 
777
  memcpy(key, &recpos, sizeof(uchar*));
 
778
  return (uint) (key - start_key);
 
779
}
 
780
 
 
781
 
 
782
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
 
783
                    key_part_map keypart_map)
 
784
{
 
785
  HA_KEYSEG *seg, *endseg;
 
786
  uchar *start_key= key;
 
787
 
 
788
  for (seg= keydef->seg, endseg= seg + keydef->keysegs;
 
789
       seg < endseg && keypart_map; old+= seg->length, seg++)
 
790
  {
 
791
    uint char_length;
 
792
    keypart_map>>= 1;
 
793
    if (seg->null_bit)
 
794
    {
 
795
      if (!(*key++= (char) 1 - *old++))
 
796
        continue;
 
797
      }
 
798
    if (seg->flag & HA_SWAP_KEY)
 
799
    {
 
800
      uint length= seg->length;
 
801
      uchar *pos= (uchar*) old + length;
 
802
      
 
803
      while (length--)
 
804
      {
 
805
        *key++= *--pos;
 
806
      }
 
807
      continue;
 
808
    }
 
809
    if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
 
810
    {
 
811
      /* Length of key-part used with heap_rkey() always 2 */
 
812
      uint tmp_length=uint2korr(old);
 
813
      uint length= seg->length;
 
814
      const CHARSET_INFO * const cs= seg->charset;
 
815
      char_length= length/cs->mbmaxlen;
 
816
 
 
817
      old+= 2;
 
818
      set_if_smaller(length,tmp_length);        /* Safety */
 
819
      FIX_LENGTH(cs, old, length, char_length);
 
820
      store_key_length_inc(key,char_length);
 
821
      memcpy(key, old,(size_t) char_length);
 
822
      key+= char_length;
 
823
      continue;
 
824
    }
 
825
    char_length= seg->length;
 
826
    if (seg->charset->mbmaxlen > 1)
 
827
    {
 
828
      char_length= my_charpos(seg->charset, old, old+char_length,
 
829
                              char_length / seg->charset->mbmaxlen);
 
830
      set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
 
831
      if (char_length < seg->length)
 
832
        seg->charset->cset->fill(seg->charset, (char*) key + char_length, 
 
833
                                 seg->length - char_length, ' ');
 
834
    }
 
835
    memcpy(key, old, (size_t) char_length);
 
836
    key+= seg->length;
 
837
  }
 
838
  return (uint) (key - start_key);
 
839
}
 
840
 
 
841
 
 
842
uint hp_rb_key_length(HP_KEYDEF *keydef, 
 
843
                      const uchar *key __attribute__((unused)))
 
844
{
 
845
  return keydef->length;
 
846
}
 
847
 
 
848
 
 
849
uint hp_rb_null_key_length(HP_KEYDEF *keydef, const uchar *key)
 
850
{
 
851
  const uchar *start_key= key;
 
852
  HA_KEYSEG *seg, *endseg;
 
853
  
 
854
  for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
 
855
  {
 
856
    if (seg->null_bit && !*key++)
 
857
      continue;
 
858
    key+= seg->length;
 
859
  }
 
860
  return (uint) (key - start_key);
 
861
}
 
862
                  
 
863
 
 
864
uint hp_rb_var_key_length(HP_KEYDEF *keydef, const uchar *key)
 
865
{
 
866
  const uchar *start_key= key;
 
867
  HA_KEYSEG *seg, *endseg;
 
868
  
 
869
  for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
 
870
  {
 
871
    uint length= seg->length;
 
872
    if (seg->null_bit && !*key++)
 
873
      continue;
 
874
    if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
 
875
    {
 
876
      get_key_length(length, key);
 
877
    }
 
878
    key+= length;
 
879
  }
 
880
  return (uint) (key - start_key);
 
881
}
 
882
 
 
883
 
514
884
/*
515
885
  Test if any of the key parts are NULL.
516
886
  Return:
518
888
    0 otherwise
519
889
*/
520
890
 
521
 
bool hp_if_null_in_key(HP_KEYDEF *keydef, const unsigned char *record)
 
891
bool hp_if_null_in_key(HP_KEYDEF *keydef, const uchar *record)
522
892
{
523
893
  HA_KEYSEG *seg,*endseg;
524
894
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
544
914
    less than zero.
545
915
*/
546
916
 
547
 
void heap_update_auto_increment(HP_INFO *info, const unsigned char *record)
 
917
void heap_update_auto_increment(HP_INFO *info, const uchar *record)
548
918
{
549
919
  uint64_t value= 0;                    /* Store unsigned values here */
550
920
  int64_t s_value= 0;                   /* Store signed values here */
551
921
 
552
 
  HA_KEYSEG *keyseg= info->getShare()->keydef[info->getShare()->auto_key - 1].seg;
553
 
  const unsigned char *key=  (unsigned char*) record + keyseg->start;
 
922
  HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
 
923
  const uchar *key=  (uchar*) record + keyseg->start;
554
924
 
555
 
  switch (info->getShare()->auto_key_type) {
 
925
  switch (info->s->auto_key_type) {
 
926
  case HA_KEYTYPE_INT8:
 
927
    s_value= (int64_t) *(char*)key;
 
928
    break;
556
929
  case HA_KEYTYPE_BINARY:
557
 
    value=(uint64_t)  *(unsigned char*) key;
 
930
    value=(uint64_t)  *(uchar*) key;
 
931
    break;
 
932
  case HA_KEYTYPE_SHORT_INT:
 
933
    s_value= (int64_t) sint2korr(key);
 
934
    break;
 
935
  case HA_KEYTYPE_USHORT_INT:
 
936
    value=(uint64_t) uint2korr(key);
558
937
    break;
559
938
  case HA_KEYTYPE_LONG_INT:
560
939
    s_value= (int64_t) sint4korr(key);
562
941
  case HA_KEYTYPE_ULONG_INT:
563
942
    value=(uint64_t) uint4korr(key);
564
943
    break;
 
944
  case HA_KEYTYPE_INT24:
 
945
    s_value= (int64_t) sint3korr(key);
 
946
    break;
 
947
  case HA_KEYTYPE_UINT24:
 
948
    value=(uint64_t) uint3korr(key);
 
949
    break;
 
950
  case HA_KEYTYPE_FLOAT:                        /* This shouldn't be used */
 
951
  {
 
952
    float f_1;
 
953
    float4get(f_1,key);
 
954
    /* Ignore negative values */
 
955
    value = (f_1 < (float) 0.0) ? 0 : (uint64_t) f_1;
 
956
    break;
 
957
  }
565
958
  case HA_KEYTYPE_DOUBLE:                       /* This shouldn't be used */
566
959
  {
567
960
    double f_1;
587
980
    and if s_value == 0 then value will contain either s_value or the
588
981
    correct value.
589
982
  */
590
 
  set_if_bigger(info->getShare()->auto_increment,
 
983
  set_if_bigger(info->s->auto_increment,
591
984
                (s_value > 0) ? (uint64_t) s_value : value);
592
985
}