~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/heap/hp_hash.c

  • Committer: Jay Pipes
  • Date: 2009-02-21 16:00:06 UTC
  • mto: (907.1.1 trunk-with-temporal)
  • mto: This revision was merged to the branch mainline in revision 908.
  • Revision ID: jpipes@serialcoder-20090221160006-vnk3wt4qbcz62eru
Removes the TIME column type and related time functions.

Show diffs side-by-side

added added

removed removed

Lines of Context:
15
15
 
16
16
/* The hash functions used for saveing keys */
17
17
 
18
 
#include "heap_priv.h"
 
18
#include "heapdef.h"
19
19
 
20
 
#include "drizzled/charset_info.h"
 
20
#include <mystrings/m_ctype.h>
21
21
#include <drizzled/util/test.h>
22
22
 
23
 
#include <math.h>
24
23
#include <string.h>
25
24
 
26
 
#include <cassert>
27
 
 
28
 
using namespace drizzled;
29
 
 
30
 
static uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key);
31
 
static int hp_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec, const unsigned char *key);
32
 
 
33
25
/*
34
26
  Find out how many rows there is in the given range
35
27
 
134
126
        case 2:                                 /* Search previous */
135
127
          if (pos->ptr_to_rec == info->current_ptr)
136
128
          {
137
 
            errno=HA_ERR_KEY_NOT_FOUND; /* If gpos == 0 */
 
129
            my_errno=HA_ERR_KEY_NOT_FOUND;      /* If gpos == 0 */
138
130
            info->current_hash_ptr=prev_ptr;
139
131
            return(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
140
132
          }
159
151
    }
160
152
    while ((pos=pos->next_key));
161
153
  }
162
 
  errno=HA_ERR_KEY_NOT_FOUND;
 
154
  my_errno=HA_ERR_KEY_NOT_FOUND;
163
155
  if (nextflag == 2 && ! info->current_ptr)
164
156
  {
165
157
    /* Do a previous from end */
168
160
  }
169
161
 
170
162
  if (old_nextflag && nextflag)
171
 
    errno=HA_ERR_RECORD_CHANGED;                /* Didn't find old record */
 
163
    my_errno=HA_ERR_RECORD_CHANGED;             /* Didn't find old record */
172
164
  info->current_hash_ptr=0;
173
165
  return((info->current_ptr= 0));
174
166
}
190
182
      return (info->current_ptr= pos->ptr_to_rec);
191
183
    }
192
184
  }
193
 
  errno=HA_ERR_KEY_NOT_FOUND;
 
185
  my_errno=HA_ERR_KEY_NOT_FOUND;
194
186
  info->current_hash_ptr=0;
195
187
  return ((info->current_ptr= 0));
196
188
}
235
227
  return;
236
228
}
237
229
 
 
230
#ifndef NEW_HASH_FUNCTION
 
231
 
238
232
        /* Calc hashvalue for a key */
239
233
 
240
 
static uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key)
 
234
uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key)
241
235
{
242
236
  /*register*/
243
237
  uint32_t nr=1, nr2=4;
326
320
      {
327
321
        char_length= my_charpos(cs, pos, pos + char_length,
328
322
                                char_length / cs->mbmaxlen);
329
 
        set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
 
323
        set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
330
324
      }
331
325
      cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
332
326
    }
357
351
  return(nr);
358
352
}
359
353
 
 
354
#else
 
355
 
 
356
/*
 
357
 * Fowler/Noll/Vo hash
 
358
 *
 
359
 * The basis of the hash algorithm was taken from an idea sent by email to the
 
360
 * IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and
 
361
 * Glenn Fowler (gsf@research.att.com).  Landon Curt Noll (chongo@toad.com)
 
362
 * later improved on their algorithm.
 
363
 *
 
364
 * The magic is in the interesting relationship between the special prime
 
365
 * 16777619 (2^24 + 403) and 2^32 and 2^8.
 
366
 *
 
367
 * This hash produces the fewest collisions of any function that we've seen so
 
368
 * far, and works well on both numbers and strings.
 
369
 */
 
370
 
 
371
uint32_t hp_hashnr(register HP_KEYDEF *keydef, register const unsigned char *key)
 
372
{
 
373
  /*
 
374
    Note, if a key consists of a combination of numeric and
 
375
    a text columns, it most likely won't work well.
 
376
    Making text columns work with NEW_HASH_FUNCTION
 
377
    needs also changes in strings/ctype-xxx.c.
 
378
  */
 
379
  uint32_t nr= 1, nr2= 4;
 
380
  HA_KEYSEG *seg,*endseg;
 
381
 
 
382
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
 
383
  {
 
384
    unsigned char *pos=(unsigned char*) key;
 
385
    key+=seg->length;
 
386
    if (seg->null_bit)
 
387
    {
 
388
      key++;
 
389
      if (*pos)
 
390
      {
 
391
        nr^= (nr << 1) | 1;
 
392
        /* Add key pack length (2) to key for VARCHAR segments */
 
393
        if (seg->type == HA_KEYTYPE_VARTEXT1)
 
394
          key+= 2;
 
395
        continue;
 
396
      }
 
397
      pos++;
 
398
    }
 
399
    if (seg->type == HA_KEYTYPE_TEXT)
 
400
    {
 
401
      seg->charset->coll->hash_sort(seg->charset, pos, ((unsigned char*)key)-pos,
 
402
                                    &nr, &nr2);
 
403
    }
 
404
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
 
405
    {
 
406
      uint32_t pack_length= 2;                      /* Key packing is constant */
 
407
      uint32_t length= uint2korr(pos);
 
408
      seg->charset->coll->hash_sort(seg->charset, pos+pack_length, length,
 
409
                                    &nr, &nr2);
 
410
      key+= pack_length;
 
411
    }
 
412
    else
 
413
    {
 
414
      for ( ; pos < (unsigned char*) key ; pos++)
 
415
      {
 
416
        nr *=16777619;
 
417
        nr ^=(uint) *pos;
 
418
      }
 
419
    }
 
420
  }
 
421
  return(nr);
 
422
}
 
423
 
 
424
        /* Calc hashvalue for a key in a record */
 
425
 
 
426
uint32_t hp_rec_hashnr(register HP_KEYDEF *keydef, register const unsigned char *rec)
 
427
{
 
428
  uint32_t nr= 1, nr2= 4;
 
429
  HA_KEYSEG *seg,*endseg;
 
430
 
 
431
  for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
 
432
  {
 
433
    unsigned char *pos=(unsigned char*) rec+seg->start;
 
434
    if (seg->null_bit)
 
435
    {
 
436
      if (rec[seg->null_pos] & seg->null_bit)
 
437
      {
 
438
        nr^= (nr << 1) | 1;
 
439
        continue;
 
440
      }
 
441
    }
 
442
    if (seg->type == HA_KEYTYPE_TEXT)
 
443
    {
 
444
      uint32_t char_length= seg->length; /* TODO: fix to use my_charpos() */
 
445
      seg->charset->coll->hash_sort(seg->charset, pos, char_length,
 
446
                                    &nr, &nr2);
 
447
    }
 
448
    else if (seg->type == HA_KEYTYPE_VARTEXT1)  /* Any VARCHAR segments */
 
449
    {
 
450
      uint32_t pack_length= seg->bit_start;
 
451
      uint32_t length= (pack_length == 1 ? (uint) *(unsigned char*) pos : uint2korr(pos));
 
452
      seg->charset->coll->hash_sort(seg->charset, pos+pack_length,
 
453
                                    length, &nr, &nr2);
 
454
    }
 
455
    else
 
456
    {
 
457
      unsigned char *end= pos+seg->length;
 
458
      for ( ; pos < end ; pos++)
 
459
      {
 
460
        nr *=16777619;
 
461
        nr ^=(uint) *pos;
 
462
      }
 
463
    }
 
464
  }
 
465
  return(nr);
 
466
}
 
467
 
 
468
#endif
 
469
 
 
470
 
360
471
/*
361
472
  Compare keys for two records. Returns 0 if they are identical
362
473
 
403
514
      {
404
515
        uint32_t char_length= seg->length / cs->mbmaxlen;
405
516
        char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
406
 
        set_if_smaller(char_length1, (uint32_t)seg->length);
 
517
        set_if_smaller(char_length1, seg->length);
407
518
        char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
408
 
        set_if_smaller(char_length2, (uint32_t)seg->length);
 
519
        set_if_smaller(char_length2, seg->length);
409
520
      }
410
521
      else
411
522
      {
464
575
 
465
576
        /* Compare a key in a record to a whole key */
466
577
 
467
 
static int hp_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec, const unsigned char *key)
 
578
int hp_key_cmp(HP_KEYDEF *keydef, const unsigned char *rec, const unsigned char *key)
468
579
{
469
580
  HA_KEYSEG *seg,*endseg;
470
581
 
495
606
      {
496
607
        uint32_t char_length= seg->length / cs->mbmaxlen;
497
608
        char_length_key= my_charpos(cs, key, key + seg->length, char_length);
498
 
        set_if_smaller(char_length_key, (uint32_t)seg->length);
 
609
        set_if_smaller(char_length_key, seg->length);
499
610
        char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length);
500
 
        set_if_smaller(char_length_rec, (uint32_t)seg->length);
 
611
        set_if_smaller(char_length_rec, seg->length);
501
612
      }
502
613
      else
503
614
      {
563
674
    {
564
675
      char_length= my_charpos(cs, pos, pos + seg->length,
565
676
                              char_length / cs->mbmaxlen);
566
 
      set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
 
677
      set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
567
678
    }
568
679
    if (seg->type == HA_KEYTYPE_VARTEXT1)
569
680
      char_length+= seg->bit_start;             /* Copy also length */
599
710
      uint32_t length= seg->length;
600
711
      unsigned char *pos= (unsigned char*) rec + seg->start;
601
712
 
602
 
      if (seg->type == HA_KEYTYPE_DOUBLE)
 
713
#ifdef HAVE_ISNAN
 
714
      if (seg->type == HA_KEYTYPE_FLOAT)
 
715
      {
 
716
        float nr;
 
717
        float4get(nr, pos);
 
718
        if (isnan(nr))
 
719
        {
 
720
          /* Replace NAN with zero */
 
721
          memset(key, 0, length);
 
722
          key+= length;
 
723
          continue;
 
724
        }
 
725
      }
 
726
      else if (seg->type == HA_KEYTYPE_DOUBLE)
603
727
      {
604
728
        double nr;
605
729
        float8get(nr, pos);
610
734
          continue;
611
735
        }
612
736
      }
 
737
#endif
613
738
      pos+= length;
614
739
      while (length--)
615
740
      {
643
768
      char_length= my_charpos(seg->charset,
644
769
                              rec + seg->start, rec + seg->start + char_length,
645
770
                              char_length / seg->charset->mbmaxlen);
646
 
      set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
 
771
      set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
647
772
      if (char_length < seg->length)
648
773
        seg->charset->cset->fill(seg->charset, (char*) key + char_length,
649
774
                                 seg->length - char_length, ' ');
704
829
    {
705
830
      char_length= my_charpos(seg->charset, old, old+char_length,
706
831
                              char_length / seg->charset->mbmaxlen);
707
 
      set_if_smaller(char_length, (uint32_t)seg->length); /* QQ: ok to remove? */
 
832
      set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
708
833
      if (char_length < seg->length)
709
834
        seg->charset->cset->fill(seg->charset, (char*) key + char_length,
710
835
                                 seg->length - char_length, ' ');
800
925
  const unsigned char *key=  (unsigned char*) record + keyseg->start;
801
926
 
802
927
  switch (info->s->auto_key_type) {
 
928
  case HA_KEYTYPE_INT8:
 
929
    s_value= (int64_t) *(char*)key;
 
930
    break;
803
931
  case HA_KEYTYPE_BINARY:
804
932
    value=(uint64_t)  *(unsigned char*) key;
805
933
    break;
 
934
  case HA_KEYTYPE_SHORT_INT:
 
935
    s_value= (int64_t) sint2korr(key);
 
936
    break;
 
937
  case HA_KEYTYPE_USHORT_INT:
 
938
    value=(uint64_t) uint2korr(key);
 
939
    break;
806
940
  case HA_KEYTYPE_LONG_INT:
807
941
    s_value= (int64_t) sint4korr(key);
808
942
    break;
809
943
  case HA_KEYTYPE_ULONG_INT:
810
944
    value=(uint64_t) uint4korr(key);
811
945
    break;
 
946
  case HA_KEYTYPE_INT24:
 
947
    s_value= (int64_t) sint3korr(key);
 
948
    break;
812
949
  case HA_KEYTYPE_UINT24:
813
950
    value=(uint64_t) uint3korr(key);
814
951
    break;
 
952
  case HA_KEYTYPE_FLOAT:                        /* This shouldn't be used */
 
953
  {
 
954
    float f_1;
 
955
    float4get(f_1,key);
 
956
    /* Ignore negative values */
 
957
    value = (f_1 < (float) 0.0) ? 0 : (uint64_t) f_1;
 
958
    break;
 
959
  }
815
960
  case HA_KEYTYPE_DOUBLE:                       /* This shouldn't be used */
816
961
  {
817
962
    double f_1;