1
/* Copyright (C) 2000-2006 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
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 */
16
/* The hash functions used for saveing keys */
24
Find out how many rows there is in the given range
27
hp_rb_records_in_range()
30
min_key Min key. Is = 0 if no min range
31
max_key Max key. Is = 0 if no max range
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
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
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
49
ha_rows hp_rb_records_in_range(HP_INFO *info, int inx, key_range *min_key,
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
DBUG_ENTER("hp_rb_records_in_range");
59
custom_arg.keyseg= keyinfo->seg;
60
custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
63
custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
64
(uchar*) min_key->key,
65
min_key->keypart_map);
66
start_pos= tree_record_pos(rb_tree, info->recbuf, min_key->flag,
76
custom_arg.key_length= hp_rb_pack_key(keyinfo, (uchar*) info->recbuf,
77
(uchar*) max_key->key,
78
max_key->keypart_map);
79
end_pos= tree_record_pos(rb_tree, info->recbuf, max_key->flag,
84
end_pos= rb_tree->elements_in_tree + (ha_rows)1;
87
DBUG_PRINT("info",("start_pos: %lu end_pos: %lu", (ulong) start_pos,
89
if (start_pos == HA_POS_ERROR || end_pos == HA_POS_ERROR)
90
DBUG_RETURN(HA_POS_ERROR);
91
DBUG_RETURN(end_pos < start_pos ? (ha_rows) 0 :
92
(end_pos == start_pos ? (ha_rows) 1 : end_pos - start_pos));
96
/* Search after a record based on a key */
97
/* Sets info->current_ptr to found record */
98
/* next_flag: Search=0, next=1, prev =2, same =3 */
100
uchar *hp_search(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key,
103
register HASH_INFO *pos,*prev_ptr;
106
HP_SHARE *share=info->s;
107
DBUG_ENTER("hp_search");
108
old_nextflag=nextflag;
114
pos=hp_find_hash(&keyinfo->block, hp_mask(hp_hashnr(keyinfo, key),
115
share->blength, share->records));
118
if (!hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
121
case 0: /* Search after key */
122
DBUG_PRINT("exit", ("found key at 0x%lx", (long) pos->ptr_to_rec));
123
info->current_hash_ptr=pos;
124
DBUG_RETURN(info->current_ptr= pos->ptr_to_rec);
125
case 1: /* Search next */
126
if (pos->ptr_to_rec == info->current_ptr)
129
case 2: /* Search previous */
130
if (pos->ptr_to_rec == info->current_ptr)
132
my_errno=HA_ERR_KEY_NOT_FOUND; /* If gpos == 0 */
133
info->current_hash_ptr=prev_ptr;
134
DBUG_RETURN(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
136
prev_ptr=pos; /* Prev. record found */
138
case 3: /* Search same */
139
if (pos->ptr_to_rec == info->current_ptr)
141
info->current_hash_ptr=pos;
142
DBUG_RETURN(info->current_ptr);
148
flag=0; /* Reset flag */
149
if (hp_find_hash(&keyinfo->block,
150
hp_mask(hp_rec_hashnr(keyinfo, pos->ptr_to_rec),
151
share->blength, share->records)) != pos)
152
break; /* Wrong link */
155
while ((pos=pos->next_key));
157
my_errno=HA_ERR_KEY_NOT_FOUND;
158
if (nextflag == 2 && ! info->current_ptr)
160
/* Do a previous from end */
161
info->current_hash_ptr=prev_ptr;
162
DBUG_RETURN(info->current_ptr=prev_ptr ? prev_ptr->ptr_to_rec : 0);
165
if (old_nextflag && nextflag)
166
my_errno=HA_ERR_RECORD_CHANGED; /* Didn't find old record */
167
DBUG_PRINT("exit",("Error: %d",my_errno));
168
info->current_hash_ptr=0;
169
DBUG_RETURN((info->current_ptr= 0));
174
Search next after last read; Assumes that the table hasn't changed
178
uchar *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const uchar *key,
181
DBUG_ENTER("hp_search_next");
183
while ((pos= pos->next_key))
185
if (! hp_key_cmp(keyinfo, pos->ptr_to_rec, key))
187
info->current_hash_ptr=pos;
188
DBUG_RETURN (info->current_ptr= pos->ptr_to_rec);
191
my_errno=HA_ERR_KEY_NOT_FOUND;
192
DBUG_PRINT("exit",("Error: %d",my_errno));
193
info->current_hash_ptr=0;
194
DBUG_RETURN ((info->current_ptr= 0));
199
Calculate position number for hash value.
203
buffmax Value such that
204
2^(n-1) < maxlength <= 2^n = buffmax
208
Array index, in [0..maxlength)
211
ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
213
if ((hashnr & (buffmax-1)) < maxlength) return (hashnr & (buffmax-1));
214
return (hashnr & ((buffmax >> 1) -1));
220
next_link -> ... -> X -> pos
222
next_link -> ... -> X -> newlink
225
void hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
232
while ((next_link=next_link->next_key) != pos);
233
old_link->next_key=newlink;
237
#ifndef NEW_HASH_FUNCTION
239
/* Calc hashvalue for a key */
241
ulong hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key)
245
HA_KEYSEG *seg,*endseg;
247
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
249
uchar *pos=(uchar*) key;
253
key++; /* Skip null byte */
254
if (*pos) /* Found null */
257
/* Add key pack length (2) to key for VARCHAR segments */
258
if (seg->type == HA_KEYTYPE_VARTEXT1)
264
if (seg->type == HA_KEYTYPE_TEXT)
266
CHARSET_INFO *cs= seg->charset;
267
uint length= seg->length;
268
if (cs->mbmaxlen > 1)
271
char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
272
set_if_smaller(length, char_length);
274
cs->coll->hash_sort(cs, pos, length, &nr, &nr2);
276
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
278
CHARSET_INFO *cs= seg->charset;
279
uint pack_length= 2; /* Key packing is constant */
280
uint length= uint2korr(pos);
281
if (cs->mbmaxlen > 1)
284
char_length= my_charpos(cs, pos +pack_length,
285
pos +pack_length + length,
286
seg->length/cs->mbmaxlen);
287
set_if_smaller(length, char_length);
289
cs->coll->hash_sort(cs, pos+pack_length, length, &nr, &nr2);
294
for (; pos < (uchar*) key ; pos++)
296
nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos)) + (nr << 8);
301
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
305
/* Calc hashvalue for a key in a record */
307
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec)
310
HA_KEYSEG *seg,*endseg;
312
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
314
uchar *pos=(uchar*) rec+seg->start,*end=pos+seg->length;
317
if (rec[seg->null_pos] & seg->null_bit)
323
if (seg->type == HA_KEYTYPE_TEXT)
325
CHARSET_INFO *cs= seg->charset;
326
uint char_length= seg->length;
327
if (cs->mbmaxlen > 1)
329
char_length= my_charpos(cs, pos, pos + char_length,
330
char_length / cs->mbmaxlen);
331
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
333
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
335
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
337
CHARSET_INFO *cs= seg->charset;
338
uint pack_length= seg->bit_start;
339
uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
340
if (cs->mbmaxlen > 1)
343
char_length= my_charpos(cs, pos + pack_length,
344
pos + pack_length + length,
345
seg->length/cs->mbmaxlen);
346
set_if_smaller(length, char_length);
348
cs->coll->hash_sort(cs, pos+pack_length, length, &nr, &nr2);
352
for (; pos < end ; pos++)
354
nr^=(ulong) ((((uint) nr & 63)+nr2)*((uint) *pos))+ (nr << 8);
359
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
366
* Fowler/Noll/Vo hash
368
* The basis of the hash algorithm was taken from an idea sent by email to the
369
* IEEE Posix P1003.2 mailing list from Phong Vo (kpv@research.att.com) and
370
* Glenn Fowler (gsf@research.att.com). Landon Curt Noll (chongo@toad.com)
371
* later improved on their algorithm.
373
* The magic is in the interesting relationship between the special prime
374
* 16777619 (2^24 + 403) and 2^32 and 2^8.
376
* This hash produces the fewest collisions of any function that we've seen so
377
* far, and works well on both numbers and strings.
380
ulong hp_hashnr(register HP_KEYDEF *keydef, register const uchar *key)
383
Note, if a key consists of a combination of numeric and
384
a text columns, it most likely won't work well.
385
Making text columns work with NEW_HASH_FUNCTION
386
needs also changes in strings/ctype-xxx.c.
389
HA_KEYSEG *seg,*endseg;
391
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
393
uchar *pos=(uchar*) key;
401
/* Add key pack length (2) to key for VARCHAR segments */
402
if (seg->type == HA_KEYTYPE_VARTEXT1)
408
if (seg->type == HA_KEYTYPE_TEXT)
410
seg->charset->coll->hash_sort(seg->charset, pos, ((uchar*)key)-pos,
413
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
415
uint pack_length= 2; /* Key packing is constant */
416
uint length= uint2korr(pos);
417
seg->charset->coll->hash_sort(seg->charset, pos+pack_length, length,
423
for ( ; pos < (uchar*) key ; pos++)
430
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
434
/* Calc hashvalue for a key in a record */
436
ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const uchar *rec)
439
HA_KEYSEG *seg,*endseg;
441
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
443
uchar *pos=(uchar*) rec+seg->start;
446
if (rec[seg->null_pos] & seg->null_bit)
452
if (seg->type == HA_KEYTYPE_TEXT)
454
uint char_length= seg->length; /* TODO: fix to use my_charpos() */
455
seg->charset->coll->hash_sort(seg->charset, pos, char_length,
458
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
460
uint pack_length= seg->bit_start;
461
uint length= (pack_length == 1 ? (uint) *(uchar*) pos : uint2korr(pos));
462
seg->charset->coll->hash_sort(seg->charset, pos+pack_length,
467
uchar *end= pos+seg->length;
468
for ( ; pos < end ; pos++)
475
DBUG_PRINT("exit", ("hash: 0x%lx", nr));
483
Compare keys for two records. Returns 0 if they are identical
487
keydef Key definition
488
rec1 Record to compare
489
rec2 Other record to compare
490
diff_if_only_endspace_difference
491
Different number of end space is significant
494
diff_if_only_endspace_difference is used to allow us to insert
495
'a' and 'a ' when there is an an unique key.
502
int hp_rec_key_cmp(HP_KEYDEF *keydef, const uchar *rec1, const uchar *rec2,
503
my_bool diff_if_only_endspace_difference)
505
HA_KEYSEG *seg,*endseg;
507
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
511
if ((rec1[seg->null_pos] & seg->null_bit) !=
512
(rec2[seg->null_pos] & seg->null_bit))
514
if (rec1[seg->null_pos] & seg->null_bit)
517
if (seg->type == HA_KEYTYPE_TEXT)
519
CHARSET_INFO *cs= seg->charset;
522
uchar *pos1= (uchar*)rec1 + seg->start;
523
uchar *pos2= (uchar*)rec2 + seg->start;
524
if (cs->mbmaxlen > 1)
526
uint char_length= seg->length / cs->mbmaxlen;
527
char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
528
set_if_smaller(char_length1, seg->length);
529
char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
530
set_if_smaller(char_length2, seg->length);
534
char_length1= char_length2= seg->length;
536
if (seg->charset->coll->strnncollsp(seg->charset,
538
pos2,char_length2, 0))
541
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
543
uchar *pos1= (uchar*) rec1 + seg->start;
544
uchar *pos2= (uchar*) rec2 + seg->start;
545
uint char_length1, char_length2;
546
uint pack_length= seg->bit_start;
547
CHARSET_INFO *cs= seg->charset;
548
if (pack_length == 1)
550
char_length1= (uint) *(uchar*) pos1++;
551
char_length2= (uint) *(uchar*) pos2++;
555
char_length1= uint2korr(pos1);
556
char_length2= uint2korr(pos2);
560
if (cs->mbmaxlen > 1)
562
uint safe_length1= char_length1;
563
uint safe_length2= char_length2;
564
uint char_length= seg->length / cs->mbmaxlen;
565
char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
566
set_if_smaller(char_length1, safe_length1);
567
char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
568
set_if_smaller(char_length2, safe_length2);
571
if (cs->coll->strnncollsp(seg->charset,
574
seg->flag & HA_END_SPACE_ARE_EQUAL ?
575
0 : diff_if_only_endspace_difference))
580
if (bcmp(rec1+seg->start,rec2+seg->start,seg->length))
587
/* Compare a key in a record to a whole key */
589
int hp_key_cmp(HP_KEYDEF *keydef, const uchar *rec, const uchar *key)
591
HA_KEYSEG *seg,*endseg;
593
for (seg=keydef->seg,endseg=seg+keydef->keysegs ;
595
key+= (seg++)->length)
599
int found_null=test(rec[seg->null_pos] & seg->null_bit);
600
if (found_null != (int) *key++)
604
/* Add key pack length (2) to key for VARCHAR segments */
605
if (seg->type == HA_KEYTYPE_VARTEXT1)
610
if (seg->type == HA_KEYTYPE_TEXT)
612
CHARSET_INFO *cs= seg->charset;
613
uint char_length_key;
614
uint char_length_rec;
615
uchar *pos= (uchar*) rec + seg->start;
616
if (cs->mbmaxlen > 1)
618
uint char_length= seg->length / cs->mbmaxlen;
619
char_length_key= my_charpos(cs, key, key + seg->length, char_length);
620
set_if_smaller(char_length_key, seg->length);
621
char_length_rec= my_charpos(cs, pos, pos + seg->length, char_length);
622
set_if_smaller(char_length_rec, seg->length);
626
char_length_key= seg->length;
627
char_length_rec= seg->length;
630
if (seg->charset->coll->strnncollsp(seg->charset,
631
(uchar*) pos, char_length_rec,
632
(uchar*) key, char_length_key, 0))
635
else if (seg->type == HA_KEYTYPE_VARTEXT1) /* Any VARCHAR segments */
637
uchar *pos= (uchar*) rec + seg->start;
638
CHARSET_INFO *cs= seg->charset;
639
uint pack_length= seg->bit_start;
640
uint char_length_rec= (pack_length == 1 ? (uint) *(uchar*) pos :
642
/* Key segments are always packed with 2 bytes */
643
uint char_length_key= uint2korr(key);
645
key+= 2; /* skip key pack length */
646
if (cs->mbmaxlen > 1)
648
uint char_length1, char_length2;
649
char_length1= char_length2= seg->length / cs->mbmaxlen;
650
char_length1= my_charpos(cs, key, key + char_length_key, char_length1);
651
set_if_smaller(char_length_key, char_length1);
652
char_length2= my_charpos(cs, pos, pos + char_length_rec, char_length2);
653
set_if_smaller(char_length_rec, char_length2);
656
if (cs->coll->strnncollsp(seg->charset,
657
(uchar*) pos, char_length_rec,
658
(uchar*) key, char_length_key, 0))
663
if (bcmp(rec+seg->start,key,seg->length))
671
/* Copy a key from a record to a keybuffer */
673
void hp_make_key(HP_KEYDEF *keydef, uchar *key, const uchar *rec)
675
HA_KEYSEG *seg,*endseg;
677
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
679
CHARSET_INFO *cs= seg->charset;
680
uint char_length= seg->length;
681
uchar *pos= (uchar*) rec + seg->start;
683
*key++= test(rec[seg->null_pos] & seg->null_bit);
684
if (cs->mbmaxlen > 1)
686
char_length= my_charpos(cs, pos, pos + seg->length,
687
char_length / cs->mbmaxlen);
688
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
690
if (seg->type == HA_KEYTYPE_VARTEXT1)
691
char_length+= seg->bit_start; /* Copy also length */
692
memcpy(key,rec+seg->start,(size_t) char_length);
697
#define FIX_LENGTH(cs, pos, length, char_length) \
699
if (length > char_length) \
700
char_length= my_charpos(cs, pos, pos+length, char_length); \
701
set_if_smaller(char_length,length); \
705
uint hp_rb_make_key(HP_KEYDEF *keydef, uchar *key,
706
const uchar *rec, uchar *recpos)
708
uchar *start_key= key;
709
HA_KEYSEG *seg, *endseg;
711
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
716
if (!(*key++= 1 - test(rec[seg->null_pos] & seg->null_bit)))
719
if (seg->flag & HA_SWAP_KEY)
721
uint length= seg->length;
722
uchar *pos= (uchar*) rec + seg->start;
725
if (seg->type == HA_KEYTYPE_FLOAT)
731
/* Replace NAN with zero */
737
else if (seg->type == HA_KEYTYPE_DOUBLE)
757
if (seg->flag & HA_VAR_LENGTH_PART)
759
uchar *pos= (uchar*) rec + seg->start;
760
uint length= seg->length;
761
uint pack_length= seg->bit_start;
762
uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
764
CHARSET_INFO *cs= seg->charset;
765
char_length= length/cs->mbmaxlen;
767
pos+= pack_length; /* Skip VARCHAR length */
768
set_if_smaller(length,tmp_length);
769
FIX_LENGTH(cs, pos, length, char_length);
770
store_key_length_inc(key,char_length);
771
memcpy((uchar*) key,(uchar*) pos,(size_t) char_length);
776
char_length= seg->length;
777
if (seg->charset->mbmaxlen > 1)
779
char_length= my_charpos(seg->charset,
780
rec + seg->start, rec + seg->start + char_length,
781
char_length / seg->charset->mbmaxlen);
782
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
783
if (char_length < seg->length)
784
seg->charset->cset->fill(seg->charset, (char*) key + char_length,
785
seg->length - char_length, ' ');
787
memcpy(key, rec + seg->start, (size_t) char_length);
790
memcpy(key, &recpos, sizeof(uchar*));
791
return (uint) (key - start_key);
795
uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
796
key_part_map keypart_map)
798
HA_KEYSEG *seg, *endseg;
799
uchar *start_key= key;
801
for (seg= keydef->seg, endseg= seg + keydef->keysegs;
802
seg < endseg && keypart_map; old+= seg->length, seg++)
808
if (!(*key++= (char) 1 - *old++))
811
if (seg->flag & HA_SWAP_KEY)
813
uint length= seg->length;
814
uchar *pos= (uchar*) old + length;
822
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
824
/* Length of key-part used with heap_rkey() always 2 */
825
uint tmp_length=uint2korr(old);
826
uint length= seg->length;
827
CHARSET_INFO *cs= seg->charset;
828
char_length= length/cs->mbmaxlen;
831
set_if_smaller(length,tmp_length); /* Safety */
832
FIX_LENGTH(cs, old, length, char_length);
833
store_key_length_inc(key,char_length);
834
memcpy((uchar*) key, old,(size_t) char_length);
838
char_length= seg->length;
839
if (seg->charset->mbmaxlen > 1)
841
char_length= my_charpos(seg->charset, old, old+char_length,
842
char_length / seg->charset->mbmaxlen);
843
set_if_smaller(char_length, seg->length); /* QQ: ok to remove? */
844
if (char_length < seg->length)
845
seg->charset->cset->fill(seg->charset, (char*) key + char_length,
846
seg->length - char_length, ' ');
848
memcpy(key, old, (size_t) char_length);
851
return (uint) (key - start_key);
855
uint hp_rb_key_length(HP_KEYDEF *keydef,
856
const uchar *key __attribute__((unused)))
858
return keydef->length;
862
uint hp_rb_null_key_length(HP_KEYDEF *keydef, const uchar *key)
864
const uchar *start_key= key;
865
HA_KEYSEG *seg, *endseg;
867
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
869
if (seg->null_bit && !*key++)
873
return (uint) (key - start_key);
877
uint hp_rb_var_key_length(HP_KEYDEF *keydef, const uchar *key)
879
const uchar *start_key= key;
880
HA_KEYSEG *seg, *endseg;
882
for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
884
uint length= seg->length;
885
if (seg->null_bit && !*key++)
887
if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
889
get_key_length(length, key);
893
return (uint) (key - start_key);
898
Test if any of the key parts are NULL.
900
1 if any of the key parts was NULL
904
my_bool hp_if_null_in_key(HP_KEYDEF *keydef, const uchar *record)
906
HA_KEYSEG *seg,*endseg;
907
for (seg=keydef->seg,endseg=seg+keydef->keysegs ; seg < endseg ; seg++)
909
if (seg->null_bit && (record[seg->null_pos] & seg->null_bit))
917
Update auto_increment info
920
update_auto_increment()
925
Only replace the auto_increment value if it is higher than the previous
926
one. For signed columns we don't update the auto increment value if it's
930
void heap_update_auto_increment(HP_INFO *info, const uchar *record)
932
ulonglong value= 0; /* Store unsigned values here */
933
longlong s_value= 0; /* Store signed values here */
935
HA_KEYSEG *keyseg= info->s->keydef[info->s->auto_key - 1].seg;
936
const uchar *key= (uchar*) record + keyseg->start;
938
switch (info->s->auto_key_type) {
939
case HA_KEYTYPE_INT8:
940
s_value= (longlong) *(char*)key;
942
case HA_KEYTYPE_BINARY:
943
value=(ulonglong) *(uchar*) key;
945
case HA_KEYTYPE_SHORT_INT:
946
s_value= (longlong) sint2korr(key);
948
case HA_KEYTYPE_USHORT_INT:
949
value=(ulonglong) uint2korr(key);
951
case HA_KEYTYPE_LONG_INT:
952
s_value= (longlong) sint4korr(key);
954
case HA_KEYTYPE_ULONG_INT:
955
value=(ulonglong) uint4korr(key);
957
case HA_KEYTYPE_INT24:
958
s_value= (longlong) sint3korr(key);
960
case HA_KEYTYPE_UINT24:
961
value=(ulonglong) uint3korr(key);
963
case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
967
/* Ignore negative values */
968
value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1;
971
case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */
975
/* Ignore negative values */
976
value = (f_1 < 0.0) ? 0 : (ulonglong) f_1;
979
case HA_KEYTYPE_LONGLONG:
980
s_value= sint8korr(key);
982
case HA_KEYTYPE_ULONGLONG:
983
value= uint8korr(key);
992
The following code works becasue if s_value < 0 then value is 0
993
and if s_value == 0 then value will contain either s_value or the
996
set_if_bigger(info->s->auto_increment,
997
(s_value > 0) ? (ulonglong) s_value : value);