~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to plugin/memory/hp_hash.cc

  • Committer: Brian Aker
  • Date: 2010-12-18 18:24:57 UTC
  • mfrom: (1999.6.3 trunk)
  • Revision ID: brian@tangent.org-20101218182457-yi1wd0so2hml1k1w
Merge in Lee's copyright header fix

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
15
15
 
16
16
/* The hash functions used for saveing keys */
17
17
 
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
 
}
 
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);
91
33
 
92
34
 
93
35
        /* Search after a record based on a key */
94
36
        /* Sets info->current_ptr to found record */
95
37
        /* next_flag:  Search=0, next=1, prev =2, same =3 */
96
38
 
97
 
uchar *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key,
98
 
                uint nextflag)
 
39
unsigned char *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const unsigned char *key,
 
40
                uint32_t nextflag)
99
41
{
100
42
  register HASH_INFO *pos,*prev_ptr;
101
43
  int flag;
102
 
  uint old_nextflag;
103
 
  HP_SHARE *share=info->s;
 
44
  uint32_t old_nextflag;
 
45
  HP_SHARE *share=info->getShare();
104
46
  old_nextflag=nextflag;
105
47
  flag=1;
106
48
  prev_ptr=0;
124
66
        case 2:                                 /* Search previous */
125
67
          if (pos->ptr_to_rec == info->current_ptr)
126
68
          {
127
 
            my_errno=HA_ERR_KEY_NOT_FOUND;      /* If gpos == 0 */
 
69
            errno=HA_ERR_KEY_NOT_FOUND; /* If gpos == 0 */
128
70
            info->current_hash_ptr=prev_ptr;
129
71
            return(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
130
72
          }
149
91
    }
150
92
    while ((pos=pos->next_key));
151
93
  }
152
 
  my_errno=HA_ERR_KEY_NOT_FOUND;
 
94
  errno=HA_ERR_KEY_NOT_FOUND;
153
95
  if (nextflag == 2 && ! info->current_ptr)
154
96
  {
155
97
    /* Do a previous from end */
158
100
  }
159
101
 
160
102
  if (old_nextflag && nextflag)
161
 
    my_errno=HA_ERR_RECORD_CHANGED;             /* Didn't find old record */
162
 
  info->current_hash_ptr=0;  
 
103
    errno=HA_ERR_RECORD_CHANGED;                /* Didn't find old record */
 
104
  info->current_hash_ptr=0;
163
105
  return((info->current_ptr= 0));
164
106
}
165
107
 
169
111
  since last read !
170
112
*/
171
113
 
172
 
uchar *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key,
 
114
unsigned char *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const unsigned char *key,
173
115
                      HASH_INFO *pos)
174
116
{
175
117
  while ((pos= pos->next_key))
180
122
      return (info->current_ptr= pos->ptr_to_rec);
181
123
    }
182
124
  }
183
 
  my_errno=HA_ERR_KEY_NOT_FOUND;
 
125
  errno=HA_ERR_KEY_NOT_FOUND;
184
126
  info->current_hash_ptr=0;
185
127
  return ((info->current_ptr= 0));
186
128
}
193
135
      hashnr     Hash value
194
136
      buffmax    Value such that
195
137
                 2^(n-1) < maxlength <= 2^n = buffmax
196
 
      maxlength  
197
 
  
 
138
      maxlength
 
139
 
198
140
  RETURN
199
141
    Array index, in [0..maxlength)
200
142
*/
225
167
  return;
226
168
}
227
169
 
228
 
#ifndef NEW_HASH_FUNCTION
229
 
 
230
170
        /* Calc hashvalue for a key */
231
171
 
232
 
uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key)
 
172
static uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key)
233
173
{
234
 
  /*register*/ 
 
174
  /*register*/
235
175
  uint32_t nr=1, nr2=4;
236
176
  HA_KEYSEG *seg,*endseg;
237
177
 
238
178
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
239
179
  {
240
 
    uchar *pos=(uchar*) key;
 
180
    unsigned char *pos=(unsigned char*) key;
241
181
    key+=seg->length;
242
182
    if (seg->null_bit)
243
183
    {
255
195
    if (seg->type == HA_KEYTYPE_TEXT)
256
196
    {
257
197
       const CHARSET_INFO * const cs= seg->charset;
258
 
       uint length= seg->length;
 
198
       uint32_t length= seg->length;
259
199
       if (cs->mbmaxlen > 1)
260
200
       {
261
 
         uint char_length;
 
201
         uint32_t char_length;
262
202
         char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
263
203
         set_if_smaller(length, char_length);
264
204
       }
267
207
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
268
208
    {
269
209
       const CHARSET_INFO * const cs= seg->charset;
270
 
       uint pack_length= 2;                     /* Key packing is constant */
271
 
       uint length= uint2korr(pos);
 
210
       uint32_t pack_length= 2;                     /* Key packing is constant */
 
211
       uint32_t length= uint2korr(pos);
272
212
       if (cs->mbmaxlen > 1)
273
213
       {
274
 
         uint char_length;
 
214
         uint32_t char_length;
275
215
         char_length= my_charpos(cs, pos +pack_length,
276
216
                                 pos +pack_length + length,
277
217
                                 seg->length/cs->mbmaxlen);
282
222
    }
283
223
    else
284
224
    {
285
 
      for (; pos < (uchar*) key ; pos++)
 
225
      for (; pos < (unsigned char*) key ; pos++)
286
226
      {
287
227
        nr^=(uint32_t) ((((uint) nr & 63)+nr2)*((uint) *pos)) + (nr << 8);
288
228
        nr2+=3;
294
234
 
295
235
        /* Calc hashvalue for a key in a record */
296
236
 
297
 
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec)
 
237
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const unsigned char *rec)
298
238
{
299
239
  uint32_t nr=1, nr2=4;
300
240
  HA_KEYSEG *seg,*endseg;
301
241
 
302
242
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
303
243
  {
304
 
    uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
 
244
    unsigned char *pos=(unsigned char*) rec+seg->start,*end=pos+seg->length;
305
245
    if (seg->null_bit)
306
246
    {
307
247
      if (rec[seg->null_pos] & seg->null_bit)
313
253
    if (seg->type == HA_KEYTYPE_TEXT)
314
254
    {
315
255
      const CHARSET_INFO * const cs= seg->charset;
316
 
      uint char_length= seg->length;
 
256
      uint32_t char_length= seg->length;
317
257
      if (cs->mbmaxlen > 1)
318
258
      {
319
259
        char_length= my_charpos(cs, pos, pos + char_length,
320
260
                                char_length / cs->mbmaxlen);
321
 
        set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
 
261
        set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
322
262
      }
323
263
      cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
324
264
    }
325
265
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
326
266
    {
327
267
      const CHARSET_INFO * const cs= seg->charset;
328
 
      uint pack_length= seg->bit_start;
329
 
      uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
 
268
      uint32_t pack_length= seg->bit_start;
 
269
      uint32_t length= (pack_length == 1 ? (uint) *(unsigned char*) pos : uint2korr(pos));
330
270
      if (cs->mbmaxlen > 1)
331
271
      {
332
 
        uint char_length;
 
272
        uint32_t char_length;
333
273
        char_length= my_charpos(cs, pos + pack_length,
334
274
                                pos + pack_length + length,
335
275
                                seg->length/cs->mbmaxlen);
349
289
  return(nr);
350
290
}
351
291
 
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
 
 
469
292
/*
470
293
  Compare keys for two records. Returns 0 if they are identical
471
294
 
475
298
    rec1                Record to compare
476
299
    rec2                Other record to compare
477
300
    diff_if_only_endspace_difference
478
 
                        Different number of end space is significant    
 
301
                        Different number of end space is significant
479
302
 
480
303
  NOTES
481
304
    diff_if_only_endspace_difference is used to allow us to insert
486
309
    <> 0        Key differes
487
310
*/
488
311
 
489
 
int hp_rec_key_cmp(HP_KEYDEF *keydef, const uchar *rec1, const uchar *rec2,
 
312
int hp_rec_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec1, const unsigned char *rec2,
490
313
                   bool diff_if_only_endspace_difference)
491
314
{
492
315
  HA_KEYSEG *seg,*endseg;
504
327
    if (seg->type == HA_KEYTYPE_TEXT)
505
328
    {
506
329
      const CHARSET_INFO * const cs= seg->charset;
507
 
      uint char_length1;
508
 
      uint char_length2;
509
 
      uchar *pos1= (uchar*)rec1 + seg->start;
510
 
      uchar *pos2= (uchar*)rec2 + seg->start;
 
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;
511
334
      if (cs->mbmaxlen > 1)
512
335
      {
513
 
        uint char_length= seg->length / cs->mbmaxlen;
 
336
        uint32_t char_length= seg->length / cs->mbmaxlen;
514
337
        char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
515
 
        set_if_smaller(char_length1, seg->length);
 
338
        set_if_smaller(char_length1, (uint32_t)seg->length);
516
339
        char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
517
 
        set_if_smaller(char_length2, seg->length);
 
340
        set_if_smaller(char_length2, (uint32_t)seg->length);
518
341
      }
519
342
      else
520
343
      {
527
350
    }
528
351
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
529
352
    {
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;
 
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;
534
357
      const CHARSET_INFO * const cs= seg->charset;
535
358
      if (pack_length == 1)
536
359
      {
537
 
        char_length1= (uint) *(uchar*) pos1++;
538
 
        char_length2= (uint) *(uchar*) pos2++;
 
360
        char_length1= (uint) *(unsigned char*) pos1++;
 
361
        char_length2= (uint) *(unsigned char*) pos2++;
539
362
      }
540
363
      else
541
364
      {
546
369
      }
547
370
      if (cs->mbmaxlen > 1)
548
371
      {
549
 
        uint safe_length1= char_length1;
550
 
        uint safe_length2= char_length2;
551
 
        uint char_length= seg->length / cs->mbmaxlen;
 
372
        uint32_t safe_length1= char_length1;
 
373
        uint32_t safe_length2= char_length2;
 
374
        uint32_t char_length= seg->length / cs->mbmaxlen;
552
375
        char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
553
376
        set_if_smaller(char_length1, safe_length1);
554
377
        char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
573
396
 
574
397
        /* Compare a key in a record to a whole key */
575
398
 
576
 
int hp_key_cmp(HP_KEYDEF *keydef, const uchar *rec, const uchar *key)
 
399
static int hp_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec, const unsigned char *key)
577
400
{
578
401
  HA_KEYSEG *seg,*endseg;
579
402
 
597
420
    if (seg->type == HA_KEYTYPE_TEXT)
598
421
    {
599
422
      const CHARSET_INFO * const cs= seg->charset;
600
 
      uint char_length_key;
601
 
      uint char_length_rec;
602
 
      uchar *pos= (uchar*) rec + seg->start;
 
423
      uint32_t char_length_key;
 
424
      uint32_t char_length_rec;
 
425
      unsigned char *pos= (unsigned char*) rec + seg->start;
603
426
      if (cs->mbmaxlen > 1)
604
427
      {
605
 
        uint char_length= seg->length / cs->mbmaxlen;
 
428
        uint32_t char_length= seg->length / cs->mbmaxlen;
606
429
        char_length_key= my_charpos(cs, key, key + seg->length, char_length);
607
 
        set_if_smaller(char_length_key, seg->length);
 
430
        set_if_smaller(char_length_key, (uint32_t)seg->length);
608
431
        char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length);
609
 
        set_if_smaller(char_length_rec, seg->length);
 
432
        set_if_smaller(char_length_rec, (uint32_t)seg->length);
610
433
      }
611
434
      else
612
435
      {
613
436
        char_length_key= seg->length;
614
437
        char_length_rec= seg->length;
615
438
      }
616
 
      
 
439
 
617
440
      if (seg->charset->coll->strnncollsp(seg->charset,
618
 
                                          (uchar*) pos, char_length_rec,
619
 
                                          (uchar*) key, char_length_key, 0))
 
441
                                          (unsigned char*) pos, char_length_rec,
 
442
                                          (unsigned char*) key, char_length_key, 0))
620
443
        return 1;
621
444
    }
622
445
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
623
446
    {
624
 
      uchar *pos= (uchar*) rec + seg->start;
 
447
      unsigned char *pos= (unsigned char*) rec + seg->start;
625
448
      const CHARSET_INFO * const cs= seg->charset;
626
 
      uint pack_length= seg->bit_start;
627
 
      uint char_length_rec= (pack_length == 1 ? (uint) *(uchar*) pos :
 
449
      uint32_t pack_length= seg->bit_start;
 
450
      uint32_t char_length_rec= (pack_length == 1 ? (uint) *(unsigned char*) pos :
628
451
                             uint2korr(pos));
629
452
      /* Key segments are always packed with 2 bytes */
630
 
      uint char_length_key= uint2korr(key);
 
453
      uint32_t char_length_key= uint2korr(key);
631
454
      pos+= pack_length;
632
455
      key+= 2;                                  /* skip key pack length */
633
456
      if (cs->mbmaxlen > 1)
634
457
      {
635
 
        uint char_length1, char_length2;
636
 
        char_length1= char_length2= seg->length / cs->mbmaxlen; 
 
458
        uint32_t char_length1, char_length2;
 
459
        char_length1= char_length2= seg->length / cs->mbmaxlen;
637
460
        char_length1= my_charpos(cs, key, key + char_length_key, char_length1);
638
461
        set_if_smaller(char_length_key, char_length1);
639
462
        char_length2= my_charpos(cs, pos, pos + char_length_rec, char_length2);
641
464
      }
642
465
 
643
466
      if (cs->coll->strnncollsp(seg->charset,
644
 
                                (uchar*) pos, char_length_rec,
645
 
                                (uchar*) key, char_length_key, 0))
 
467
                                (unsigned char*) pos, char_length_rec,
 
468
                                (unsigned char*) key, char_length_key, 0))
646
469
        return 1;
647
470
    }
648
471
    else
657
480
 
658
481
        /* Copy a key from a record to a keybuffer */
659
482
 
660
 
void hp_make_key(HP_KEYDEF *keydef, uchar *key, const uchar *rec)
 
483
void hp_make_key(HP_KEYDEF *keydef, unsigned char *key, const unsigned char *rec)
661
484
{
662
485
  HA_KEYSEG *seg,*endseg;
663
486
 
664
487
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
665
488
  {
666
489
    const CHARSET_INFO * const cs= seg->charset;
667
 
    uint char_length= seg->length;
668
 
    uchar *pos= (uchar*) rec + seg->start;
 
490
    uint32_t char_length= seg->length;
 
491
    unsigned char *pos= (unsigned char*) rec + seg->start;
669
492
    if (seg->null_bit)
670
493
      *key++= test(rec[seg->null_pos] & seg->null_bit);
671
494
    if (cs->mbmaxlen > 1)
672
495
    {
673
496
      char_length= my_charpos(cs, pos, pos + seg->length,
674
497
                              char_length / cs->mbmaxlen);
675
 
      set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
 
498
      set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
676
499
    }
677
500
    if (seg->type == HA_KEYTYPE_VARTEXT1)
678
501
      char_length+= seg->bit_start;             /* Copy also length */
688
511
    set_if_smaller(char_length,length);                                 \
689
512
  } while(0)
690
513
 
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
 
 
884
514
/*
885
515
  Test if any of the key parts are NULL.
886
516
  Return:
888
518
    0 otherwise
889
519
*/
890
520
 
891
 
bool hp_if_null_in_key(HP_KEYDEF *keydef, const uchar *record)
 
521
bool hp_if_null_in_key(HP_KEYDEF *keydef, const unsigned char *record)
892
522
{
893
523
  HA_KEYSEG *seg,*endseg;
894
524
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
914
544
    less than zero.
915
545
*/
916
546
 
917
 
void heap_update_auto_increment(HP_INFO *info, const uchar *record)
 
547
void heap_update_auto_increment(HP_INFO *info, const unsigned char *record)
918
548
{
919
549
  uint64_t value= 0;                    /* Store unsigned values here */
920
550
  int64_t s_value= 0;                   /* Store signed values here */
921
551
 
922
 
  HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
923
 
  const uchar *key=  (uchar*) record + keyseg->start;
 
552
  HA_KEYSEG *keyseg= info->getShare()->keydef[info->getShare()->auto_key - 1].seg;
 
553
  const unsigned char *key=  (unsigned char*) record + keyseg->start;
924
554
 
925
 
  switch (info->s->auto_key_type) {
926
 
  case HA_KEYTYPE_INT8:
927
 
    s_value= (int64_t) *(char*)key;
928
 
    break;
 
555
  switch (info->getShare()->auto_key_type) {
929
556
  case HA_KEYTYPE_BINARY:
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);
 
557
    value=(uint64_t)  *(unsigned char*) key;
937
558
    break;
938
559
  case HA_KEYTYPE_LONG_INT:
939
560
    s_value= (int64_t) sint4korr(key);
941
562
  case HA_KEYTYPE_ULONG_INT:
942
563
    value=(uint64_t) uint4korr(key);
943
564
    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
 
  }
958
565
  case HA_KEYTYPE_DOUBLE:                       /* This shouldn't be used */
959
566
  {
960
567
    double f_1;
980
587
    and if s_value == 0 then value will contain either s_value or the
981
588
    correct value.
982
589
  */
983
 
  set_if_bigger(info->s->auto_increment,
 
590
  set_if_bigger(info->getShare()->auto_increment,
984
591
                (s_value > 0) ? (uint64_t) s_value : value);
985
592
}