~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/key.cc

pandora-build v0.100 - Fixes several bugs found by cb1kenobi. Add several thoughts from folks at LCA.

Show diffs side-by-side

added added

removed removed

Lines of Context:
16
16
 
17
17
/* Functions to handle keys and fields in forms */
18
18
 
19
 
#include <drizzled/server_includes.h>
 
19
#include "config.h"
 
20
#include "drizzled/table.h"
 
21
#include "drizzled/key.h"
 
22
#include "drizzled/field/blob.h"
 
23
 
 
24
#include <string>
 
25
 
 
26
#include <algorithm>
 
27
 
 
28
using namespace std;
20
29
 
21
30
/*
22
31
  Search after a key that starts with 'field'
45
54
       key_length is set to length of key before (not including) field
46
55
*/
47
56
 
48
 
int find_ref_key(KEY *key, uint key_count, uchar *record, Field *field,
49
 
                 uint *key_length, uint *keypart)
 
57
int find_ref_key(KEY *key, uint32_t key_count, unsigned char *record, Field *field,
 
58
                 uint32_t *key_length, uint32_t *keypart)
50
59
{
51
60
  register int i;
52
61
  register KEY *key_info;
53
 
  uint fieldpos;
 
62
  uint32_t fieldpos;
54
63
 
55
64
  fieldpos= field->offset(record);
56
65
 
71
80
       i < (int) key_count ;
72
81
       i++, key_info++)
73
82
  {
74
 
    uint j;
 
83
    uint32_t j;
75
84
    KEY_PART_INFO *key_part;
76
85
    *key_length=0;
77
86
    for (j=0, key_part=key_info->key_part ;
90
99
}
91
100
 
92
101
 
93
 
/**
94
 
  Copy part of a record that forms a key or key prefix to a buffer.
95
 
 
96
 
    The function takes a complete table record (as e.g. retrieved by
97
 
    handler::index_read()), and a description of an index on the same table,
98
 
    and extracts the first key_length bytes of the record which are part of a
99
 
    key into to_key. If length == 0 then copy all bytes from the record that
100
 
    form a key.
101
 
 
102
 
  @param to_key      buffer that will be used as a key
103
 
  @param from_record full record to be copied from
104
 
  @param key_info    descriptor of the index
105
 
  @param key_length  specifies length of all keyparts that will be copied
106
 
*/
107
 
 
108
 
void key_copy(uchar *to_key, uchar *from_record, KEY *key_info,
 
102
void key_copy(unsigned char *to_key, unsigned char *from_record, KEY *key_info,
109
103
              unsigned int key_length)
110
104
{
111
 
  uint length;
 
105
  uint32_t length;
112
106
  KEY_PART_INFO *key_part;
113
107
 
114
108
  if (key_length == 0)
126
120
    {
127
121
      key_length-= HA_KEY_BLOB_LENGTH;
128
122
      length= min((uint16_t)key_length, key_part->length);
129
 
      key_part->field->get_key_image(to_key, length, Field::itRAW);
 
123
      key_part->field->get_key_image(to_key, length);
130
124
      to_key+= HA_KEY_BLOB_LENGTH;
131
125
    }
132
126
    else
134
128
      length= min((uint16_t)key_length, key_part->length);
135
129
      Field *field= key_part->field;
136
130
      const CHARSET_INFO * const cs= field->charset();
137
 
      uint bytes= field->get_key_image(to_key, length, Field::itRAW);
 
131
      uint32_t bytes= field->get_key_image(to_key, length);
138
132
      if (bytes < length)
139
133
        cs->cset->fill(cs, (char*) to_key + bytes, length - bytes, ' ');
140
134
    }
148
142
  Zero the null components of key tuple.
149
143
*/
150
144
 
151
 
void key_zero_nulls(uchar *tuple, KEY *key_info)
 
145
void key_zero_nulls(unsigned char *tuple, KEY *key_info)
152
146
{
153
147
  KEY_PART_INFO *key_part= key_info->key_part;
154
148
  KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
173
167
  @param key_length  specifies length of all keyparts that will be restored
174
168
*/
175
169
 
176
 
void key_restore(uchar *to_record, uchar *from_key, KEY *key_info,
 
170
void key_restore(unsigned char *to_record, unsigned char *from_key, KEY *key_info,
177
171
                 uint16_t key_length)
178
172
{
179
 
  uint length;
 
173
  uint32_t length;
180
174
  KEY_PART_INFO *key_part;
181
175
 
182
176
  if (key_length == 0)
185
179
  }
186
180
  for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++)
187
181
  {
188
 
    uchar used_uneven_bits= 0;
 
182
    unsigned char used_uneven_bits= 0;
189
183
    if (key_part->null_bit)
190
184
    {
191
185
      if (*from_key++)
202
196
        restore the part of a record.
203
197
        Maybe this branch is to be removed, but now we
204
198
        have to ignore GCov compaining.
 
199
 
 
200
        This may make more sense once we push down block lengths to the engine (aka partial retrieval).
205
201
      */
206
 
      uint blob_length= uint2korr(from_key);
 
202
      uint32_t blob_length= uint2korr(from_key);
207
203
      Field_blob *field= (Field_blob*) key_part->field;
 
204
 
 
205
      field->setReadSet();
208
206
      from_key+= HA_KEY_BLOB_LENGTH;
209
207
      key_length-= HA_KEY_BLOB_LENGTH;
210
208
      field->set_ptr_offset(to_record - field->table->record[0],
214
212
    else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
215
213
    {
216
214
      Field *field= key_part->field;
217
 
      my_bitmap_map *old_map;
218
 
      my_ptrdiff_t ptrdiff= to_record - field->table->record[0];
 
215
      ptrdiff_t ptrdiff= to_record - field->table->record[0];
 
216
 
 
217
      field->setReadSet();
 
218
      field->setWriteSet();
219
219
      field->move_field_offset(ptrdiff);
220
220
      key_length-= HA_KEY_BLOB_LENGTH;
221
221
      length= min(key_length, key_part->length);
222
 
      old_map= dbug_tmp_use_all_columns(field->table, field->table->write_set);
223
222
      field->set_key_image(from_key, length);
224
 
      dbug_tmp_restore_column_map(field->table->write_set, old_map);
225
223
      from_key+= HA_KEY_BLOB_LENGTH;
226
224
      field->move_field_offset(-ptrdiff);
227
225
    }
241
239
/**
242
240
  Compare if a key has changed.
243
241
 
244
 
  @param table          TABLE
 
242
  @param table          Table
245
243
  @param key            key to compare to row
246
244
  @param idx            Index used
247
245
  @param key_length     Length of key
258
256
    1   Key has changed
259
257
*/
260
258
 
261
 
bool key_cmp_if_same(TABLE *table,const uchar *key,uint idx,uint key_length)
 
259
bool key_cmp_if_same(Table *table,const unsigned char *key,uint32_t idx,uint32_t key_length)
262
260
{
263
 
  uint store_length;
 
261
  uint32_t store_length;
264
262
  KEY_PART_INFO *key_part;
265
 
  const uchar *key_end= key + key_length;;
 
263
  const unsigned char *key_end= key + key_length;;
266
264
 
267
265
  for (key_part=table->key_info[idx].key_part;
268
 
       key < key_end ; 
 
266
       key < key_end ;
269
267
       key_part++, key+= store_length)
270
268
  {
271
 
    uint length;
 
269
    uint32_t length;
272
270
    store_length= key_part->store_length;
273
271
 
274
272
    if (key_part->null_bit)
275
273
    {
276
 
      if (*key != test(table->record[0][key_part->null_offset] & 
 
274
      if (*key != test(table->record[0][key_part->null_offset] &
277
275
                       key_part->null_bit))
278
276
        return 1;
279
277
      if (*key)
288
286
        return 1;
289
287
      continue;
290
288
    }
291
 
    length= min((uint) (key_end-key), store_length);
292
 
    if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
293
 
                                FIELDFLAG_PACK)))
 
289
    length= min((uint32_t) (key_end-key), store_length);
 
290
    if (key_part->field->type() == DRIZZLE_TYPE_VARCHAR)
294
291
    {
295
292
      const CHARSET_INFO * const cs= key_part->field->charset();
296
 
      uint char_length= key_part->length / cs->mbmaxlen;
297
 
      const uchar *pos= table->record[0] + key_part->offset;
 
293
      uint32_t char_length= key_part->length / cs->mbmaxlen;
 
294
      const unsigned char *pos= table->record[0] + key_part->offset;
298
295
      if (length > char_length)
299
296
      {
300
297
        char_length= my_charpos(cs, pos, pos + length, char_length);
301
298
        set_if_smaller(char_length, length);
302
299
      }
303
300
      if (cs->coll->strnncollsp(cs,
304
 
                                (const uchar*) key, length,
305
 
                                (const uchar*) pos, char_length, 0))
 
301
                                (const unsigned char*) key, length,
 
302
                                (const unsigned char*) pos, char_length, 0))
306
303
        return 1;
307
304
      continue;
308
305
    }
315
312
/*
316
313
  unpack key-fields from record to some buffer.
317
314
 
318
 
  This is used mainly to get a good error message.  We temporary 
 
315
  This is used mainly to get a good error message.  We temporary
319
316
  change the column bitmap so that all columns are readable.
320
317
 
321
318
  @param
326
323
     idx        Key number
327
324
*/
328
325
 
329
 
void key_unpack(String *to,TABLE *table,uint idx)
 
326
void key_unpack(String *to, Table *table, uint32_t idx)
330
327
{
331
328
  KEY_PART_INFO *key_part,*key_part_end;
332
329
  Field *field;
333
330
  String tmp;
334
 
  my_bitmap_map *old_map= dbug_tmp_use_all_columns(table, table->read_set);
335
331
 
336
332
  to->length(0);
337
333
  for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
349
345
        continue;
350
346
      }
351
347
    }
352
 
    if ((field=key_part->field))
 
348
    if ((field= key_part->field))
353
349
    {
354
350
      const CHARSET_INFO * const cs= field->charset();
 
351
      field->setReadSet();
355
352
      field->val_str(&tmp);
356
353
      if (cs->mbmaxlen > 1 &&
357
354
          table->field[key_part->fieldnr - 1]->field_length !=
364
361
          which can break a multi-byte characters in the middle.
365
362
          Align, returning not more than "char_length" characters.
366
363
        */
367
 
        uint charpos, char_length= key_part->length / cs->mbmaxlen;
368
 
        if ((charpos= my_charpos(cs, tmp.ptr(),
369
 
                                 tmp.ptr() + tmp.length(),
 
364
        uint32_t charpos, char_length= key_part->length / cs->mbmaxlen;
 
365
        if ((charpos= my_charpos(cs, tmp.c_ptr(),
 
366
                                 tmp.c_ptr() + tmp.length(),
370
367
                                 char_length)) < key_part->length)
371
368
          tmp.length(charpos);
372
369
      }
373
 
      
 
370
 
374
371
      if (key_part->length < field->pack_length())
375
 
        tmp.length(min(tmp.length(),(uint32_t)key_part->length));
 
372
        tmp.length(min(tmp.length(),(uint32_t)key_part->length));
376
373
      to->append(tmp);
377
374
    }
378
375
    else
379
376
      to->append(STRING_WITH_LEN("???"));
380
377
  }
381
 
  dbug_tmp_restore_column_map(table->read_set, old_map);
382
 
  return;
383
378
}
384
379
 
385
380
 
388
383
 
389
384
  SYNOPSIS
390
385
    is_key_used()
391
 
      table   TABLE object with which keys and fields are associated.
 
386
      table   Table object with which keys and fields are associated.
392
387
      idx     Key to be checked.
393
388
      fields  Bitmap of fields to be checked.
394
389
 
395
390
  NOTE
396
 
    This function uses TABLE::tmp_set bitmap so the caller should care
 
391
    This function uses Table::tmp_set bitmap so the caller should care
397
392
    about saving/restoring its state if it also uses this bitmap.
398
393
 
399
394
  RETURN VALUE
401
396
    FALSE  Otherwise
402
397
*/
403
398
 
404
 
bool is_key_used(TABLE *table, uint idx, const MY_BITMAP *fields)
 
399
bool is_key_used(Table *table, uint32_t idx, const MyBitmap *fields)
405
400
{
406
 
  bitmap_clear_all(&table->tmp_set);
 
401
  table->tmp_set.clearAll();
407
402
  table->mark_columns_used_by_index_no_reset(idx, &table->tmp_set);
408
403
  if (bitmap_is_overlapping(&table->tmp_set, fields))
409
404
    return 1;
413
408
    key is not updated
414
409
  */
415
410
  if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY &&
416
 
      (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
 
411
      (table->cursor->getEngine()->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX)))
417
412
    return is_key_used(table, table->s->primary_key, fields);
418
413
  return 0;
419
414
}
433
428
    -   1               Key is larger than range
434
429
*/
435
430
 
436
 
int key_cmp(KEY_PART_INFO *key_part, const uchar *key, uint key_length)
 
431
int key_cmp(KEY_PART_INFO *key_part, const unsigned char *key, uint32_t key_length)
437
432
{
438
 
  uint store_length;
 
433
  uint32_t store_length;
439
434
 
440
 
  for (const uchar *end=key + key_length;
 
435
  for (const unsigned char *end=key + key_length;
441
436
       key < end;
442
437
       key+= store_length, key_part++)
443
438
  {
494
489
    and return the result of the comparison.
495
490
*/
496
491
 
497
 
int key_rec_cmp(void *key, uchar *first_rec, uchar *second_rec)
 
492
int key_rec_cmp(void *key, unsigned char *first_rec, unsigned char *second_rec)
498
493
{
499
494
  KEY *key_info= (KEY*)key;
500
 
  uint key_parts= key_info->key_parts, i= 0;
 
495
  uint32_t key_parts= key_info->key_parts, i= 0;
501
496
  KEY_PART_INFO *key_part= key_info->key_part;
502
 
  uchar *rec0= key_part->field->ptr - key_part->offset;
503
 
  my_ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0;
 
497
  unsigned char *rec0= key_part->field->ptr - key_part->offset;
 
498
  ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0;
504
499
  int result= 0;
505
500
 
506
501
  do