~jlukas79/+junk/mysql-server

« back to all changes in this revision

Viewing changes to storage/maria/ma_key.c

manual merge 6.0-main --> 6.0-bka-review

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
 
2
 
 
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.
 
6
 
 
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.
 
11
 
 
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 */
 
15
 
 
16
/* Functions to handle keys */
 
17
 
 
18
#include "maria_def.h"
 
19
#include "m_ctype.h"
 
20
#include "ma_sp_defs.h"
 
21
#include "ma_blockrec.h"                        /* For ROW_FLAG_TRANSID */
 
22
#include "trnman.h"
 
23
#ifdef HAVE_IEEEFP_H
 
24
#include <ieeefp.h>
 
25
#endif
 
26
 
 
27
#define CHECK_KEYS                              /* Enable safety checks */
 
28
 
 
29
static int _ma_put_key_in_record(MARIA_HA *info,uint keynr,uchar *record);
 
30
 
 
31
#define FIX_LENGTH(cs, pos, length, char_length)                            \
 
32
            do {                                                            \
 
33
              if (length > char_length)                                     \
 
34
                char_length= (uint) my_charpos(cs, pos, pos+length, char_length); \
 
35
              set_if_smaller(char_length,length);                           \
 
36
            } while(0)
 
37
 
 
38
 
 
39
/**
 
40
  Store trid in a packed format as part of a key
 
41
 
 
42
  @fn    transid_store_packed
 
43
  @param info   Maria handler
 
44
  @param to     End of key to which we should store a packed transid
 
45
  @param trid   Trid to be stored
 
46
 
 
47
  @notes
 
48
 
 
49
  Keys that have a transid has the lowest bit set for the last byte of the key
 
50
  This function sets this bit for the key.
 
51
 
 
52
  Trid is max 6 bytes long
 
53
 
 
54
  First Trid it's converted to a smaller number by using
 
55
  trid= trid - create_trid.
 
56
  Then trid is then shifted up one bit so that we can use the
 
57
  lowest bit as a marker if it's followed by another trid.
 
58
 
 
59
  Trid is then stored as follows:
 
60
 
 
61
  if trid < 256-12
 
62
    one byte
 
63
  else
 
64
    one byte prefix (256-length_of_trid_in_bytes) followed by data
 
65
    in high-byte-first order
 
66
 
 
67
  Prefix bytes 244 to 249 are reserved for negative transid, that can be used
 
68
  when we pack transid relative to each other on a key block.
 
69
 
 
70
  We have to store transid in high-byte-first order to be able to do a
 
71
  fast byte-per-byte comparision of them without packing them up.
 
72
*/
 
73
 
 
74
uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid)
 
75
{
 
76
  uchar *start;
 
77
  uint length;
 
78
  uchar buff[8];
 
79
  DBUG_ASSERT(trid < (LL(1) << (MAX_PACK_TRANSID_SIZE*8)));
 
80
  DBUG_ASSERT(trid >= info->s->state.create_trid);
 
81
 
 
82
  trid= (trid - info->s->state.create_trid) << 1;
 
83
 
 
84
  /* Mark that key contains transid */
 
85
  to[-1]|= 1;
 
86
 
 
87
  if (trid < MIN_TRANSID_PACK_PREFIX)
 
88
  {
 
89
    to[0]= (uchar) trid;
 
90
    return 1;
 
91
  }
 
92
  start= to;
 
93
 
 
94
  /* store things in low-byte-first-order in buff */
 
95
  to= buff;
 
96
  do
 
97
  {
 
98
    *to++= (uchar) trid;
 
99
    trid= trid>>8;
 
100
  } while (trid);
 
101
 
 
102
  length= (uint) (to - buff);
 
103
  start[0]= (uchar) (256 - length);             /* Store length prefix */
 
104
  start++;
 
105
  /* Copy things in high-byte-first order to output buffer */
 
106
  do
 
107
  {
 
108
    *start++= *--to;
 
109
  } while (to != buff);
 
110
  return length+1;
 
111
}
 
112
 
 
113
 
 
114
/**
 
115
   Read packed transid
 
116
 
 
117
   @fn    transid_get_packed
 
118
   @param info   Maria handler
 
119
   @param from   Transid is stored here
 
120
 
 
121
   See transid_store_packed() for how transid is packed
 
122
 
 
123
*/
 
124
 
 
125
ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from)
 
126
{
 
127
  ulonglong value;
 
128
  uint length;
 
129
 
 
130
  if (from[0] < MIN_TRANSID_PACK_PREFIX)
 
131
    value= (ulonglong) from[0];
 
132
  else
 
133
  {
 
134
    value= 0;
 
135
    for (length= (uint) (256 - from[0]), value= (ulonglong) from[1], from+=2;
 
136
         --length ;
 
137
         from++)
 
138
      value= (value << 8) + ((ulonglong) *from);
 
139
  }
 
140
  return (value >> 1) + share->state.create_trid;
 
141
}
 
142
 
 
143
 
 
144
/*
 
145
  Make a normal (not spatial or fulltext) intern key from a record
 
146
 
 
147
  SYNOPSIS
 
148
    _ma_make_key()
 
149
    info                MyiSAM handler
 
150
    int_key             Store created key here
 
151
    keynr               key number
 
152
    key                 Buffer used to store key data
 
153
    record              Record
 
154
    filepos             Position to record in the data file
 
155
 
 
156
  NOTES
 
157
    This is used to generate keys from the record on insert, update and delete
 
158
 
 
159
  RETURN
 
160
    key
 
161
*/
 
162
 
 
163
MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr,
 
164
                        uchar *key, const uchar *record,
 
165
                        MARIA_RECORD_POS filepos, ulonglong trid)
 
166
{
 
167
  const uchar *pos;
 
168
  reg1 HA_KEYSEG *keyseg;
 
169
  my_bool is_ft;
 
170
  DBUG_ENTER("_ma_make_key");
 
171
 
 
172
  int_key->data= key;
 
173
  int_key->flag= 0;                             /* Always return full key */
 
174
  int_key->keyinfo= info->s->keyinfo + keynr;
 
175
 
 
176
  is_ft= int_key->keyinfo->flag & HA_FULLTEXT;
 
177
  for (keyseg= int_key->keyinfo->seg ; keyseg->type ;keyseg++)
 
178
  {
 
179
    enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
 
180
    uint length=keyseg->length;
 
181
    uint char_length;
 
182
    CHARSET_INFO *cs=keyseg->charset;
 
183
 
 
184
    if (keyseg->null_bit)
 
185
    {
 
186
      if (record[keyseg->null_pos] & keyseg->null_bit)
 
187
      {
 
188
        *key++= 0;                              /* NULL in key */
 
189
        continue;
 
190
      }
 
191
      *key++=1;                                 /* Not NULL */
 
192
    }
 
193
 
 
194
    char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
 
195
                  length);
 
196
 
 
197
    pos= record+keyseg->start;
 
198
    if (type == HA_KEYTYPE_BIT)
 
199
    {
 
200
      if (keyseg->bit_length)
 
201
      {
 
202
        uchar bits= get_rec_bits(record + keyseg->bit_pos,
 
203
                                 keyseg->bit_start, keyseg->bit_length);
 
204
        *key++= (char) bits;
 
205
        length--;
 
206
      }
 
207
      memcpy(key, pos, length);
 
208
      key+= length;
 
209
      continue;
 
210
    }
 
211
    if (keyseg->flag & HA_SPACE_PACK)
 
212
    {
 
213
      if (type != HA_KEYTYPE_NUM)
 
214
      {
 
215
        length= (uint) cs->cset->lengthsp(cs, (const char*)pos, length);
 
216
      }
 
217
      else
 
218
      {
 
219
        const uchar *end= pos + length;
 
220
        while (pos < end && pos[0] == ' ')
 
221
          pos++;
 
222
        length= (uint) (end-pos);
 
223
      }
 
224
      FIX_LENGTH(cs, pos, length, char_length);
 
225
      store_key_length_inc(key,char_length);
 
226
      memcpy(key, pos, (size_t) char_length);
 
227
      key+=char_length;
 
228
      continue;
 
229
    }
 
230
    if (keyseg->flag & HA_VAR_LENGTH_PART)
 
231
    {
 
232
      uint pack_length= (keyseg->bit_start == 1 ? 1 : 2);
 
233
      uint tmp_length= (pack_length == 1 ? (uint) *pos :
 
234
                        uint2korr(pos));
 
235
      pos+= pack_length;                        /* Skip VARCHAR length */
 
236
      set_if_smaller(length,tmp_length);
 
237
      FIX_LENGTH(cs, pos, length, char_length);
 
238
      store_key_length_inc(key,char_length);
 
239
      memcpy(key,pos,(size_t) char_length);
 
240
      key+= char_length;
 
241
      continue;
 
242
    }
 
243
    else if (keyseg->flag & HA_BLOB_PART)
 
244
    {
 
245
      uint tmp_length= _ma_calc_blob_length(keyseg->bit_start,pos);
 
246
      uchar *blob_pos;
 
247
      memcpy_fixed(&blob_pos, pos+keyseg->bit_start,sizeof(char*));
 
248
      set_if_smaller(length,tmp_length);
 
249
      FIX_LENGTH(cs, blob_pos, length, char_length);
 
250
      store_key_length_inc(key,char_length);
 
251
      memcpy(key, blob_pos, (size_t) char_length);
 
252
      key+= char_length;
 
253
      continue;
 
254
    }
 
255
    else if (keyseg->flag & HA_SWAP_KEY)
 
256
    {                                           /* Numerical column */
 
257
#ifdef HAVE_ISNAN
 
258
      if (type == HA_KEYTYPE_FLOAT)
 
259
      {
 
260
        float nr;
 
261
        float4get(nr,pos);
 
262
        if (isnan(nr))
 
263
        {
 
264
          /* Replace NAN with zero */
 
265
          bzero(key,length);
 
266
          key+=length;
 
267
          continue;
 
268
        }
 
269
      }
 
270
      else if (type == HA_KEYTYPE_DOUBLE)
 
271
      {
 
272
        double nr;
 
273
        float8get(nr,pos);
 
274
        if (isnan(nr))
 
275
        {
 
276
          bzero(key,length);
 
277
          key+=length;
 
278
          continue;
 
279
        }
 
280
      }
 
281
#endif
 
282
      pos+=length;
 
283
      while (length--)
 
284
      {
 
285
        *key++ = *--pos;
 
286
      }
 
287
      continue;
 
288
    }
 
289
    FIX_LENGTH(cs, pos, length, char_length);
 
290
    memcpy(key, pos, char_length);
 
291
    if (length > char_length)
 
292
      cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
 
293
    key+= length;
 
294
  }
 
295
  _ma_dpointer(info->s, key, filepos);
 
296
  int_key->data_length= (key - int_key->data);
 
297
  int_key->ref_length= info->s->rec_reflength;
 
298
  int_key->flag= 0;
 
299
  if (_ma_have_versioning(info) && trid)
 
300
  {
 
301
    int_key->ref_length+= transid_store_packed(info,
 
302
                                               key + int_key->ref_length,
 
303
                                               (TrID) trid);
 
304
    int_key->flag|= SEARCH_USER_KEY_HAS_TRANSID;
 
305
  }
 
306
 
 
307
  DBUG_PRINT("exit",("keynr: %d",keynr));
 
308
  DBUG_DUMP_KEY("key", int_key);
 
309
  DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, int_key););
 
310
  DBUG_RETURN(int_key);
 
311
} /* _ma_make_key */
 
312
 
 
313
 
 
314
/*
 
315
  Pack a key to intern format from given format (c_rkey)
 
316
 
 
317
  SYNOPSIS
 
318
    _ma_pack_key()
 
319
    info                MARIA handler
 
320
    int_key             Store key here
 
321
    keynr               key number
 
322
    key                 Buffer for key data
 
323
    old                 Original not packed key
 
324
    keypart_map         bitmap of used keyparts
 
325
    last_used_keyseg    out parameter.  May be NULL
 
326
 
 
327
   RETURN
 
328
   int_key
 
329
 
 
330
     last_use_keyseg    Store pointer to the keyseg after the last used one
 
331
*/
 
332
 
 
333
MARIA_KEY *_ma_pack_key(register MARIA_HA *info, MARIA_KEY *int_key,
 
334
                        uint keynr, uchar *key,
 
335
                        const uchar *old, key_part_map keypart_map,
 
336
                        HA_KEYSEG **last_used_keyseg)
 
337
{
 
338
  HA_KEYSEG *keyseg;
 
339
  my_bool is_ft;
 
340
  DBUG_ENTER("_ma_pack_key");
 
341
 
 
342
  int_key->data= key;
 
343
  int_key->keyinfo= info->s->keyinfo + keynr;
 
344
 
 
345
  /* "one part" rtree key is 2*SPDIMS part key in Maria */
 
346
  if (int_key->keyinfo->key_alg == HA_KEY_ALG_RTREE)
 
347
    keypart_map= (((key_part_map)1) << (2*SPDIMS)) - 1;
 
348
 
 
349
  /* only key prefixes are supported */
 
350
  DBUG_ASSERT(((keypart_map+1) & keypart_map) == 0);
 
351
 
 
352
  is_ft= int_key->keyinfo->flag & HA_FULLTEXT;
 
353
  for (keyseg=int_key->keyinfo->seg ; keyseg->type && keypart_map;
 
354
       old+= keyseg->length, keyseg++)
 
355
  {
 
356
    enum ha_base_keytype type= (enum ha_base_keytype) keyseg->type;
 
357
    uint length= keyseg->length;
 
358
    uint char_length;
 
359
    const uchar *pos;
 
360
    CHARSET_INFO *cs=keyseg->charset;
 
361
 
 
362
    keypart_map>>= 1;
 
363
    if (keyseg->null_bit)
 
364
    {
 
365
      if (!(*key++= (char) 1-*old++))                   /* Copy null marker */
 
366
      {
 
367
        if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
 
368
          old+= 2;
 
369
        continue;                                       /* Found NULL */
 
370
      }
 
371
    }
 
372
    char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
 
373
                  length);
 
374
    pos= old;
 
375
    if (keyseg->flag & HA_SPACE_PACK)
 
376
    {
 
377
      const uchar *end= pos + length;
 
378
      if (type == HA_KEYTYPE_NUM)
 
379
      {
 
380
        while (pos < end && pos[0] == ' ')
 
381
          pos++;
 
382
      }
 
383
      else if (type != HA_KEYTYPE_BINARY)
 
384
      {
 
385
        while (end > pos && end[-1] == ' ')
 
386
          end--;
 
387
      }
 
388
      length=(uint) (end-pos);
 
389
      FIX_LENGTH(cs, pos, length, char_length);
 
390
      store_key_length_inc(key,char_length);
 
391
      memcpy(key,pos,(size_t) char_length);
 
392
      key+= char_length;
 
393
      continue;
 
394
    }
 
395
    else if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
 
396
    {
 
397
      /* Length of key-part used with maria_rkey() always 2 */
 
398
      uint tmp_length=uint2korr(pos);
 
399
      pos+=2;
 
400
      set_if_smaller(length,tmp_length);        /* Safety */
 
401
      FIX_LENGTH(cs, pos, length, char_length);
 
402
      store_key_length_inc(key,char_length);
 
403
      old+=2;                                   /* Skip length */
 
404
      memcpy(key, pos,(size_t) char_length);
 
405
      key+= char_length;
 
406
      continue;
 
407
    }
 
408
    else if (keyseg->flag & HA_SWAP_KEY)
 
409
    {                                           /* Numerical column */
 
410
      pos+=length;
 
411
      while (length--)
 
412
        *key++ = *--pos;
 
413
      continue;
 
414
    }
 
415
    FIX_LENGTH(cs, pos, length, char_length);
 
416
    memcpy(key, pos, char_length);
 
417
    if (length > char_length)
 
418
      cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
 
419
    key+= length;
 
420
  }
 
421
  if (last_used_keyseg)
 
422
    *last_used_keyseg= keyseg;
 
423
 
 
424
  /* set flag to SEARCH_PART_KEY if we are not using all key parts */
 
425
  int_key->flag= keyseg->type ? SEARCH_PART_KEY : 0;
 
426
  int_key->ref_length= 0;
 
427
  int_key->data_length= (key - int_key->data);
 
428
 
 
429
  DBUG_PRINT("exit", ("length: %u", int_key->data_length));
 
430
  DBUG_RETURN(int_key);
 
431
} /* _ma_pack_key */
 
432
 
 
433
 
 
434
/**
 
435
   Copy a key
 
436
*/
 
437
 
 
438
void _ma_copy_key(MARIA_KEY *to, const MARIA_KEY *from)
 
439
{
 
440
  memcpy(to->data, from->data, from->data_length + from->ref_length);
 
441
  to->keyinfo=     from->keyinfo;
 
442
  to->data_length= from->data_length;
 
443
  to->ref_length=  from->ref_length;
 
444
  to->flag=        from->flag;
 
445
}
 
446
 
 
447
 
 
448
/*
 
449
  Store found key in record
 
450
 
 
451
  SYNOPSIS
 
452
    _ma_put_key_in_record()
 
453
    info                MARIA handler
 
454
    keynr               Key number that was used
 
455
    record              Store key here
 
456
 
 
457
    Last read key is in info->lastkey
 
458
 
 
459
 NOTES
 
460
   Used when only-keyread is wanted
 
461
 
 
462
 RETURN
 
463
   0   ok
 
464
   1   error
 
465
*/
 
466
 
 
467
static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr,
 
468
                                 uchar *record)
 
469
{
 
470
  reg2 uchar *key;
 
471
  uchar *pos,*key_end;
 
472
  reg1 HA_KEYSEG *keyseg;
 
473
  uchar *blob_ptr;
 
474
  DBUG_ENTER("_ma_put_key_in_record");
 
475
 
 
476
  blob_ptr= info->lastkey_buff2;         /* Place to put blob parts */
 
477
  key= info->last_key.data;               /* Key that was read */
 
478
  key_end= key + info->last_key.data_length;
 
479
  for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
 
480
  {
 
481
    if (keyseg->null_bit)
 
482
    {
 
483
      if (!*key++)
 
484
      {
 
485
        record[keyseg->null_pos]|= keyseg->null_bit;
 
486
        continue;
 
487
      }
 
488
      record[keyseg->null_pos]&= ~keyseg->null_bit;
 
489
    }
 
490
    if (keyseg->type == HA_KEYTYPE_BIT)
 
491
    {
 
492
      uint length= keyseg->length;
 
493
 
 
494
      if (keyseg->bit_length)
 
495
      {
 
496
        uchar bits= *key++;
 
497
        set_rec_bits(bits, record + keyseg->bit_pos, keyseg->bit_start,
 
498
                     keyseg->bit_length);
 
499
        length--;
 
500
      }
 
501
      else
 
502
      {
 
503
        clr_rec_bits(record + keyseg->bit_pos, keyseg->bit_start,
 
504
                     keyseg->bit_length);
 
505
      }
 
506
      memcpy(record + keyseg->start, key, length);
 
507
      key+= length;
 
508
      continue;
 
509
    }
 
510
    if (keyseg->flag & HA_SPACE_PACK)
 
511
    {
 
512
      uint length;
 
513
      get_key_length(length,key);
 
514
#ifdef CHECK_KEYS
 
515
      if (length > keyseg->length || key+length > key_end)
 
516
        goto err;
 
517
#endif
 
518
      pos= record+keyseg->start;
 
519
      if (keyseg->type != (int) HA_KEYTYPE_NUM)
 
520
      {
 
521
        memcpy(pos,key,(size_t) length);
 
522
        keyseg->charset->cset->fill(keyseg->charset,
 
523
                                    (char*) pos + length,
 
524
                                    keyseg->length - length,
 
525
                                    ' ');
 
526
      }
 
527
      else
 
528
      {
 
529
        bfill(pos,keyseg->length-length,' ');
 
530
        memcpy(pos+keyseg->length-length,key,(size_t) length);
 
531
      }
 
532
      key+=length;
 
533
      continue;
 
534
    }
 
535
 
 
536
    if (keyseg->flag & HA_VAR_LENGTH_PART)
 
537
    {
 
538
      uint length;
 
539
      get_key_length(length,key);
 
540
#ifdef CHECK_KEYS
 
541
      if (length > keyseg->length || key+length > key_end)
 
542
        goto err;
 
543
#endif
 
544
      /* Store key length */
 
545
      if (keyseg->bit_start == 1)
 
546
        *(uchar*) (record+keyseg->start)= (uchar) length;
 
547
      else
 
548
        int2store(record+keyseg->start, length);
 
549
      /* And key data */
 
550
      memcpy(record+keyseg->start + keyseg->bit_start, key, length);
 
551
      key+= length;
 
552
    }
 
553
    else if (keyseg->flag & HA_BLOB_PART)
 
554
    {
 
555
      uint length;
 
556
      get_key_length(length,key);
 
557
#ifdef CHECK_KEYS
 
558
      if (length > keyseg->length || key+length > key_end)
 
559
        goto err;
 
560
#endif
 
561
      memcpy(record+keyseg->start+keyseg->bit_start,
 
562
             (char*) &blob_ptr,sizeof(char*));
 
563
      memcpy(blob_ptr,key,length);
 
564
      blob_ptr+=length;
 
565
 
 
566
      /* The above changed info->lastkey2. Inform maria_rnext_same(). */
 
567
      info->update&= ~HA_STATE_RNEXT_SAME;
 
568
 
 
569
      _ma_store_blob_length(record+keyseg->start,
 
570
                            (uint) keyseg->bit_start,length);
 
571
      key+=length;
 
572
    }
 
573
    else if (keyseg->flag & HA_SWAP_KEY)
 
574
    {
 
575
      uchar *to=  record+keyseg->start+keyseg->length;
 
576
      uchar *end= key+keyseg->length;
 
577
#ifdef CHECK_KEYS
 
578
      if (end > key_end)
 
579
        goto err;
 
580
#endif
 
581
      do
 
582
      {
 
583
         *--to= *key++;
 
584
      } while (key != end);
 
585
      continue;
 
586
    }
 
587
    else
 
588
    {
 
589
#ifdef CHECK_KEYS
 
590
      if (key+keyseg->length > key_end)
 
591
        goto err;
 
592
#endif
 
593
      memcpy(record+keyseg->start, key, (size_t) keyseg->length);
 
594
      key+= keyseg->length;
 
595
    }
 
596
  }
 
597
  DBUG_RETURN(0);
 
598
 
 
599
err:
 
600
  DBUG_RETURN(1);                               /* Crashed row */
 
601
} /* _ma_put_key_in_record */
 
602
 
 
603
 
 
604
        /* Here when key reads are used */
 
605
 
 
606
int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
 
607
{
 
608
  fast_ma_writeinfo(info);
 
609
  if (filepos != HA_OFFSET_ERROR)
 
610
  {
 
611
    if (info->lastinx >= 0)
 
612
    {                           /* Read only key */
 
613
      if (_ma_put_key_in_record(info,(uint) info->lastinx,buf))
 
614
      {
 
615
        maria_print_error(info->s, HA_ERR_CRASHED);
 
616
        my_errno=HA_ERR_CRASHED;
 
617
        return -1;
 
618
      }
 
619
      info->update|= HA_STATE_AKTIV; /* We should find a record */
 
620
      return 0;
 
621
    }
 
622
    my_errno=HA_ERR_WRONG_INDEX;
 
623
  }
 
624
  return(-1);                           /* Wrong data to read */
 
625
}
 
626
 
 
627
 
 
628
/*
 
629
  Retrieve auto_increment info
 
630
 
 
631
  SYNOPSIS
 
632
    retrieve_auto_increment()
 
633
    key                         Auto-increment key
 
634
    key_type                    Key's type
 
635
 
 
636
  NOTE
 
637
    'key' should in "record" format, that is, how it is packed in a record
 
638
    (this matters with HA_SWAP_KEY).
 
639
 
 
640
  IMPLEMENTATION
 
641
    For signed columns we don't retrieve the auto increment value if it's
 
642
    less than zero.
 
643
*/
 
644
 
 
645
ulonglong ma_retrieve_auto_increment(const uchar *key, uint8 key_type)
 
646
{
 
647
  ulonglong value= 0;                   /* Store unsigned values here */
 
648
  longlong s_value= 0;                  /* Store signed values here */
 
649
 
 
650
  switch (key_type) {
 
651
  case HA_KEYTYPE_INT8:
 
652
    s_value= (longlong) *(const char*)key;
 
653
    break;
 
654
  case HA_KEYTYPE_BINARY:
 
655
    value=(ulonglong)  *key;
 
656
    break;
 
657
  case HA_KEYTYPE_SHORT_INT:
 
658
    s_value= (longlong) sint2korr(key);
 
659
    break;
 
660
  case HA_KEYTYPE_USHORT_INT:
 
661
    value=(ulonglong) uint2korr(key);
 
662
    break;
 
663
  case HA_KEYTYPE_LONG_INT:
 
664
    s_value= (longlong) sint4korr(key);
 
665
    break;
 
666
  case HA_KEYTYPE_ULONG_INT:
 
667
    value=(ulonglong) uint4korr(key);
 
668
    break;
 
669
  case HA_KEYTYPE_INT24:
 
670
    s_value= (longlong) sint3korr(key);
 
671
    break;
 
672
  case HA_KEYTYPE_UINT24:
 
673
    value=(ulonglong) uint3korr(key);
 
674
    break;
 
675
  case HA_KEYTYPE_FLOAT:                        /* This shouldn't be used */
 
676
  {
 
677
    float f_1;
 
678
    float4get(f_1,key);
 
679
    /* Ignore negative values */
 
680
    value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1;
 
681
    break;
 
682
  }
 
683
  case HA_KEYTYPE_DOUBLE:                       /* This shouldn't be used */
 
684
  {
 
685
    double f_1;
 
686
    float8get(f_1,key);
 
687
    /* Ignore negative values */
 
688
    value = (f_1 < 0.0) ? 0 : (ulonglong) f_1;
 
689
    break;
 
690
  }
 
691
  case HA_KEYTYPE_LONGLONG:
 
692
    s_value= sint8korr(key);
 
693
    break;
 
694
  case HA_KEYTYPE_ULONGLONG:
 
695
    value= uint8korr(key);
 
696
    break;
 
697
  default:
 
698
    DBUG_ASSERT(0);
 
699
    value=0;                                    /* Error */
 
700
    break;
 
701
  }
 
702
 
 
703
  /*
 
704
    The following code works becasue if s_value < 0 then value is 0
 
705
    and if s_value == 0 then value will contain either s_value or the
 
706
    correct value.
 
707
  */
 
708
  return (s_value > 0) ? (ulonglong) s_value : value;
 
709
}