~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to storage/myisam/mi_key.c

  • Committer: Jim Winstead
  • Date: 2008-07-19 02:56:45 UTC
  • mto: (202.1.8 codestyle)
  • mto: This revision was merged to the branch mainline in revision 207.
  • Revision ID: jimw@mysql.com-20080719025645-w2pwytebgzusjzjb
Various fixes to enable compilation on Mac OS X, and remove the glib dependency.
Temporarily disables tab-completion in the drizzle client until an appropriate
autoconf check can be added/enabled.

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