~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_key.c

  • Committer: Mark Atwood
  • Date: 2008-10-03 01:39:40 UTC
  • mto: This revision was merged to the branch mainline in revision 437.
  • Revision ID: mark@fallenpegasus.com-20081003013940-mvefjo725dltz41h
rename logging_noop to logging_query

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
/* Functions to handle keys */
17
17
 
18
 
#include "myisam_priv.h"
19
 
#include "drizzled/charset_info.h"
 
18
#include "myisamdef.h"
 
19
#include <mystrings/m_ctype.h>
20
20
#ifdef HAVE_IEEEFP_H
21
21
#include <ieeefp.h>
22
22
#endif
23
 
#include <math.h>
24
 
#include <cassert>
25
 
 
26
 
using namespace drizzled;
27
 
using namespace std;
28
23
 
29
24
#define CHECK_KEYS                              /* Enable safety checks */
30
25
 
32
27
            do {                                                            \
33
28
              if (length > char_length)                                     \
34
29
                char_length= my_charpos(cs, pos, pos+length, char_length);  \
35
 
              drizzled::set_if_smaller(char_length,length);                           \
 
30
              set_if_smaller(char_length,length);                           \
36
31
            } while(0)
37
32
 
38
 
static int _mi_put_key_in_record(MI_INFO *info,uint32_t keynr,unsigned char *record);
 
33
static int _mi_put_key_in_record(MI_INFO *info,uint keynr,uchar *record);
39
34
 
40
35
/*
41
36
  Make a intern key from a record
52
47
    Length of key
53
48
*/
54
49
 
55
 
uint32_t _mi_make_key(register MI_INFO *info, uint32_t keynr, unsigned char *key,
56
 
                      const unsigned char *record, drizzled::internal::my_off_t filepos)
 
50
uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
 
51
                  const uchar *record, my_off_t filepos)
57
52
{
58
 
  unsigned char *pos;
59
 
  unsigned char *start;
 
53
  uchar *pos;
 
54
  uchar *start;
60
55
  register HA_KEYSEG *keyseg;
61
56
 
62
57
  start=key;
63
58
  for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
64
59
  {
65
 
    enum drizzled::ha_base_keytype type=(enum drizzled::ha_base_keytype) keyseg->type;
66
 
    uint32_t length=keyseg->length;
67
 
    uint32_t char_length;
68
 
    const drizzled::CHARSET_INFO * const cs=keyseg->charset;
 
60
    enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
 
61
    uint length=keyseg->length;
 
62
    uint char_length;
 
63
    const CHARSET_INFO * const cs=keyseg->charset;
69
64
 
70
65
    if (keyseg->null_bit)
71
66
    {
80
75
    char_length= ((cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
81
76
                  length);
82
77
 
83
 
    pos= (unsigned char*) record+keyseg->start;
84
 
 
 
78
    pos= (uchar*) record+keyseg->start;
 
79
    if (type == HA_KEYTYPE_BIT)
 
80
    {
 
81
      if (keyseg->bit_length)
 
82
      {
 
83
        uchar bits= get_rec_bits((uchar*) record + keyseg->bit_pos,
 
84
                                 keyseg->bit_start, keyseg->bit_length);
 
85
        *key++= bits;
 
86
        length--;
 
87
      }
 
88
      memcpy(key, pos, length);
 
89
      key+= length;
 
90
      continue;
 
91
    }
85
92
    if (keyseg->flag & HA_SPACE_PACK)
86
93
    {
87
 
      length= cs->cset->lengthsp(cs, (char*) pos, length);
88
 
 
 
94
      if (type != HA_KEYTYPE_NUM)
 
95
      {
 
96
        length= cs->cset->lengthsp(cs, (char*) pos, length);
 
97
      }
 
98
      else
 
99
      {
 
100
        uchar *end= pos + length;
 
101
        while (pos < end && pos[0] == ' ')
 
102
          pos++;
 
103
        length=(uint) (end-pos);
 
104
      }
89
105
      FIX_LENGTH(cs, pos, length, char_length);
90
106
      store_key_length_inc(key,char_length);
91
107
      memcpy(key, pos, char_length);
94
110
    }
95
111
    if (keyseg->flag & HA_VAR_LENGTH_PART)
96
112
    {
97
 
      uint32_t pack_length= (keyseg->bit_start == 1 ? 1 : 2);
98
 
      uint32_t tmp_length= (pack_length == 1 ? (uint) *(unsigned char*) pos :
 
113
      uint pack_length= (keyseg->bit_start == 1 ? 1 : 2);
 
114
      uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
99
115
                        uint2korr(pos));
100
116
      pos+= pack_length;                        /* Skip VARCHAR length */
101
 
      drizzled::set_if_smaller(length,tmp_length);
 
117
      set_if_smaller(length,tmp_length);
102
118
      FIX_LENGTH(cs, pos, length, char_length);
103
119
      store_key_length_inc(key,char_length);
104
120
      memcpy(key, pos, char_length);
107
123
    }
108
124
    else if (keyseg->flag & HA_BLOB_PART)
109
125
    {
110
 
      uint32_t tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
 
126
      uint tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
111
127
      memcpy(&pos, pos+keyseg->bit_start, sizeof(char*));
112
 
      drizzled::set_if_smaller(length,tmp_length);
 
128
      set_if_smaller(length,tmp_length);
113
129
      FIX_LENGTH(cs, pos, length, char_length);
114
130
      store_key_length_inc(key,char_length);
115
131
      memcpy(key, pos, char_length);
118
134
    }
119
135
    else if (keyseg->flag & HA_SWAP_KEY)
120
136
    {                                           /* Numerical column */
121
 
      if (type == drizzled::HA_KEYTYPE_DOUBLE)
 
137
#ifdef HAVE_ISNAN
 
138
      if (type == HA_KEYTYPE_FLOAT)
 
139
      {
 
140
        float nr;
 
141
        float4get(nr,pos);
 
142
        if (isnan(nr))
 
143
        {
 
144
          /* Replace NAN with zero */
 
145
          memset(key, 0, length);
 
146
          key+=length;
 
147
          continue;
 
148
        }
 
149
      }
 
150
      else if (type == HA_KEYTYPE_DOUBLE)
122
151
      {
123
152
        double nr;
124
153
        float8get(nr,pos);
129
158
          continue;
130
159
        }
131
160
      }
 
161
#endif
132
162
      pos+=length;
133
163
      while (length--)
134
164
      {
153
183
  SYNOPSIS
154
184
    _mi_pack_key()
155
185
    info                MyISAM handler
156
 
    uint32_t keynr              key number
 
186
    uint keynr          key number
157
187
    key                 Store packed key here
158
188
    old                 Not packed key
159
189
    keypart_map         bitmap of used keyparts
165
195
     last_use_keyseg    Store pointer to the keyseg after the last used one
166
196
*/
167
197
 
168
 
uint32_t _mi_pack_key(register MI_INFO *info, uint32_t keynr, unsigned char *key, unsigned char *old,
169
 
                      drizzled::key_part_map keypart_map, HA_KEYSEG **last_used_keyseg)
 
198
uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
 
199
                  key_part_map keypart_map, HA_KEYSEG **last_used_keyseg)
170
200
{
171
 
  unsigned char *start_key=key;
 
201
  uchar *start_key=key;
172
202
  HA_KEYSEG *keyseg;
173
203
 
174
204
  /* only key prefixes are supported */
177
207
  for (keyseg= info->s->keyinfo[keynr].seg ; keyseg->type && keypart_map;
178
208
       old+= keyseg->length, keyseg++)
179
209
  {
180
 
    enum drizzled::ha_base_keytype type= (enum drizzled::ha_base_keytype) keyseg->type;
181
 
    uint32_t length= keyseg->length;
182
 
    uint32_t char_length;
183
 
    unsigned char *pos;
184
 
    const drizzled::CHARSET_INFO * const cs=keyseg->charset;
 
210
    enum ha_base_keytype type= (enum ha_base_keytype) keyseg->type;
 
211
    uint length= keyseg->length;
 
212
    uint char_length;
 
213
    uchar *pos;
 
214
    const CHARSET_INFO * const cs=keyseg->charset;
185
215
    keypart_map>>= 1;
186
216
    if (keyseg->null_bit)
187
217
    {
196
226
    pos=old;
197
227
    if (keyseg->flag & HA_SPACE_PACK)
198
228
    {
199
 
      unsigned char *end=pos+length;
200
 
 
201
 
      if (type != drizzled::HA_KEYTYPE_BINARY)
 
229
      uchar *end=pos+length;
 
230
      if (type == HA_KEYTYPE_NUM)
 
231
      {
 
232
        while (pos < end && pos[0] == ' ')
 
233
          pos++;
 
234
      }
 
235
      else if (type != HA_KEYTYPE_BINARY)
202
236
      {
203
237
        while (end > pos && end[-1] == ' ')
204
238
          end--;
213
247
    else if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
214
248
    {
215
249
      /* Length of key-part used with mi_rkey() always 2 */
216
 
      uint32_t tmp_length=uint2korr(pos);
 
250
      uint tmp_length=uint2korr(pos);
217
251
      pos+=2;
218
 
      drizzled::set_if_smaller(length,tmp_length);      /* Safety */
 
252
      set_if_smaller(length,tmp_length);        /* Safety */
219
253
      FIX_LENGTH(cs, pos, length, char_length);
220
254
      store_key_length_inc(key,char_length);
221
255
      old+=2;                                   /* Skip length */
263
297
   1   error
264
298
*/
265
299
 
266
 
static int _mi_put_key_in_record(register MI_INFO *info, uint32_t keynr,
267
 
                                 unsigned char *record)
 
300
static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
 
301
                                 uchar *record)
268
302
{
269
 
  register unsigned char *key;
270
 
  unsigned char *pos,*key_end;
 
303
  register uchar *key;
 
304
  uchar *pos,*key_end;
271
305
  register HA_KEYSEG *keyseg;
272
 
  unsigned char *blob_ptr;
 
306
  uchar *blob_ptr;
273
307
 
274
 
  blob_ptr= (unsigned char*) info->lastkey2;             /* Place to put blob parts */
275
 
  key=(unsigned char*) info->lastkey;                    /* KEy that was read */
 
308
  blob_ptr= (uchar*) info->lastkey2;             /* Place to put blob parts */
 
309
  key=(uchar*) info->lastkey;                    /* KEy that was read */
276
310
  key_end=key+info->lastkey_length;
277
311
  for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
278
312
  {
285
319
      }
286
320
      record[keyseg->null_pos]&= ~keyseg->null_bit;
287
321
    }
 
322
    if (keyseg->type == HA_KEYTYPE_BIT)
 
323
    {
 
324
      uint length= keyseg->length;
288
325
 
 
326
      if (keyseg->bit_length)
 
327
      {
 
328
        uchar bits= *key++;
 
329
        set_rec_bits(bits, record + keyseg->bit_pos, keyseg->bit_start,
 
330
                     keyseg->bit_length);
 
331
        length--;
 
332
      }
 
333
      else
 
334
      {
 
335
        clr_rec_bits(record + keyseg->bit_pos, keyseg->bit_start,
 
336
                     keyseg->bit_length);
 
337
      }
 
338
      memcpy(record + keyseg->start, key, length);
 
339
      key+= length;
 
340
      continue;
 
341
    }
289
342
    if (keyseg->flag & HA_SPACE_PACK)
290
343
    {
291
 
      uint32_t length;
 
344
      uint length;
292
345
      get_key_length(length,key);
293
346
#ifdef CHECK_KEYS
294
347
      if (length > keyseg->length || key+length > key_end)
295
348
        goto err;
296
349
#endif
297
350
      pos= record+keyseg->start;
298
 
 
299
 
      memcpy(pos, key, length);
300
 
      keyseg->charset->cset->fill(keyseg->charset,
301
 
                                  (char*) pos + length,
302
 
                                  keyseg->length - length,
303
 
                                  ' ');
 
351
      if (keyseg->type != (int) HA_KEYTYPE_NUM)
 
352
      {
 
353
        memcpy(pos, key, length);
 
354
        keyseg->charset->cset->fill(keyseg->charset,
 
355
                                    (char*) pos + length,
 
356
                                    keyseg->length - length,
 
357
                                    ' ');
 
358
      }
 
359
      else
 
360
      {
 
361
        memset(pos, ' ', keyseg->length-length);
 
362
        memcpy(pos+keyseg->length-length, key, length);
 
363
      }
304
364
      key+=length;
305
365
      continue;
306
366
    }
307
367
 
308
368
    if (keyseg->flag & HA_VAR_LENGTH_PART)
309
369
    {
310
 
      uint32_t length;
 
370
      uint length;
311
371
      get_key_length(length,key);
312
372
#ifdef CHECK_KEYS
313
373
      if (length > keyseg->length || key+length > key_end)
315
375
#endif
316
376
      /* Store key length */
317
377
      if (keyseg->bit_start == 1)
318
 
        *(unsigned char*) (record+keyseg->start)= (unsigned char) length;
 
378
        *(uchar*) (record+keyseg->start)= (uchar) length;
319
379
      else
320
380
        int2store(record+keyseg->start, length);
321
381
      /* And key data */
324
384
    }
325
385
    else if (keyseg->flag & HA_BLOB_PART)
326
386
    {
327
 
      uint32_t length;
 
387
      uint length;
328
388
      get_key_length(length,key);
329
389
#ifdef CHECK_KEYS
330
390
      if (length > keyseg->length || key+length > key_end)
344
404
    }
345
405
    else if (keyseg->flag & HA_SWAP_KEY)
346
406
    {
347
 
      unsigned char *to=  record+keyseg->start+keyseg->length;
348
 
      unsigned char *end= key+keyseg->length;
 
407
      uchar *to=  record+keyseg->start+keyseg->length;
 
408
      uchar *end= key+keyseg->length;
349
409
#ifdef CHECK_KEYS
350
410
      if (end > key_end)
351
411
        goto err;
375
435
 
376
436
        /* Here when key reads are used */
377
437
 
378
 
int _mi_read_key_record(MI_INFO *info, drizzled::internal::my_off_t filepos, unsigned char *buf)
 
438
int _mi_read_key_record(MI_INFO *info, my_off_t filepos, uchar *buf)
379
439
{
380
440
  fast_mi_writeinfo(info);
381
441
  if (filepos != HA_OFFSET_ERROR)
385
445
      if (_mi_put_key_in_record(info,(uint) info->lastinx,buf))
386
446
      {
387
447
        mi_print_error(info->s, HA_ERR_CRASHED);
388
 
        errno=HA_ERR_CRASHED;
 
448
        my_errno=HA_ERR_CRASHED;
389
449
        return -1;
390
450
      }
391
451
      info->update|= HA_STATE_AKTIV; /* We should find a record */
392
452
      return 0;
393
453
    }
394
 
    errno=HA_ERR_WRONG_INDEX;
 
454
    my_errno=HA_ERR_WRONG_INDEX;
395
455
  }
396
456
  return(-1);                           /* Wrong data to read */
397
457
}
404
464
    mi_check_index_cond()
405
465
      info    MyISAM handler
406
466
      keynr   Index we're running a scan on
407
 
      record  Record buffer to use (it is assumed that index check function
 
467
      record  Record buffer to use (it is assumed that index check function 
408
468
              will look for column values there)
409
469
 
410
470
  RETURN
411
 
    -1  Error
 
471
    -1  Error 
412
472
    0   Index condition is not satisfied, continue scanning
413
473
    1   Index condition is satisfied
414
 
    2   Index condition is not satisfied, end the scan.
 
474
    2   Index condition is not satisfied, end the scan. 
415
475
*/
416
476
 
417
 
int mi_check_index_cond(register MI_INFO *info, uint32_t keynr, unsigned char *record)
 
477
int mi_check_index_cond(register MI_INFO *info, uint keynr, uchar *record)
418
478
{
419
479
  if (_mi_put_key_in_record(info, keynr, record))
420
480
  {
421
481
    mi_print_error(info->s, HA_ERR_CRASHED);
422
 
    errno=HA_ERR_CRASHED;
 
482
    my_errno=HA_ERR_CRASHED;
423
483
    return -1;
424
484
  }
425
485
  return info->index_cond_func(info->index_cond_func_arg);
439
499
    less than zero.
440
500
*/
441
501
 
442
 
uint64_t retrieve_auto_increment(MI_INFO *info,const unsigned char *record)
 
502
uint64_t retrieve_auto_increment(MI_INFO *info,const uchar *record)
443
503
{
444
504
  uint64_t value= 0;                    /* Store unsigned values here */
445
505
  int64_t s_value= 0;                   /* Store signed values here */
446
506
  HA_KEYSEG *keyseg= info->s->keyinfo[info->s->base.auto_key-1].seg;
447
 
  const unsigned char *key= (unsigned char*) record + keyseg->start;
 
507
  const uchar *key= (uchar*) record + keyseg->start;
448
508
 
449
509
  switch (keyseg->type) {
450
 
  case drizzled::HA_KEYTYPE_BINARY:
451
 
    value=(uint64_t)  *(unsigned char*) key;
452
 
    break;
453
 
  case drizzled::HA_KEYTYPE_LONG_INT:
 
510
  case HA_KEYTYPE_INT8:
 
511
    s_value= (int64_t) *(char*)key;
 
512
    break;
 
513
  case HA_KEYTYPE_BINARY:
 
514
    value=(uint64_t)  *(uchar*) key;
 
515
    break;
 
516
  case HA_KEYTYPE_SHORT_INT:
 
517
    s_value= (int64_t) sint2korr(key);
 
518
    break;
 
519
  case HA_KEYTYPE_USHORT_INT:
 
520
    value=(uint64_t) uint2korr(key);
 
521
    break;
 
522
  case HA_KEYTYPE_LONG_INT:
454
523
    s_value= (int64_t) sint4korr(key);
455
524
    break;
456
 
  case drizzled::HA_KEYTYPE_ULONG_INT:
 
525
  case HA_KEYTYPE_ULONG_INT:
457
526
    value=(uint64_t) uint4korr(key);
458
527
    break;
459
 
  case drizzled::HA_KEYTYPE_DOUBLE:                       /* This shouldn't be used */
 
528
  case HA_KEYTYPE_INT24:
 
529
    s_value= (int64_t) sint3korr(key);
 
530
    break;
 
531
  case HA_KEYTYPE_UINT24:
 
532
    value=(uint64_t) uint3korr(key);
 
533
    break;
 
534
  case HA_KEYTYPE_FLOAT:                        /* This shouldn't be used */
 
535
  {
 
536
    float f_1;
 
537
    float4get(f_1,key);
 
538
    /* Ignore negative values */
 
539
    value = (f_1 < (float) 0.0) ? 0 : (uint64_t) f_1;
 
540
    break;
 
541
  }
 
542
  case HA_KEYTYPE_DOUBLE:                       /* This shouldn't be used */
460
543
  {
461
544
    double f_1;
462
545
    float8get(f_1,key);
464
547
    value = (f_1 < 0.0) ? 0 : (uint64_t) f_1;
465
548
    break;
466
549
  }
467
 
  case drizzled::HA_KEYTYPE_LONGLONG:
 
550
  case HA_KEYTYPE_LONGLONG:
468
551
    s_value= sint8korr(key);
469
552
    break;
470
 
  case drizzled::HA_KEYTYPE_ULONGLONG:
 
553
  case HA_KEYTYPE_ULONGLONG:
471
554
    value= uint8korr(key);
472
555
    break;
473
556
  default: