~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/key.cc

  • Committer: Padraig O'Sullivan
  • Date: 2010-02-10 16:26:01 UTC
  • mto: This revision was merged to the branch mainline in revision 1294.
  • Revision ID: osullivan.padraig@gmail.com-20100210162601-itx2ndl397pc1wr6
Corrected an order of initialization in a few optimizer classes

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
 
17
17
/* Functions to handle keys and fields in forms */
20
20
#include "drizzled/table.h"
21
21
#include "drizzled/key.h"
22
22
#include "drizzled/field/blob.h"
23
 
#include "drizzled/util/test.h"
24
 
 
25
 
#include <boost/dynamic_bitset.hpp>
26
23
 
27
24
#include <string>
28
25
 
60
57
       key_length is set to length of key before (not including) field
61
58
*/
62
59
 
63
 
int find_ref_key(KeyInfo *key, uint32_t key_count, unsigned char *record, Field *field,
 
60
int find_ref_key(KEY *key, uint32_t key_count, unsigned char *record, Field *field,
64
61
                 uint32_t *key_length, uint32_t *keypart)
65
62
{
66
63
  register int i;
67
 
  register KeyInfo *key_info;
 
64
  register KEY *key_info;
68
65
  uint32_t fieldpos;
69
66
 
70
67
  fieldpos= field->offset(record);
87
84
       i++, key_info++)
88
85
  {
89
86
    uint32_t j;
90
 
    KeyPartInfo *key_part;
 
87
    KEY_PART_INFO *key_part;
91
88
    *key_length=0;
92
89
    for (j=0, key_part=key_info->key_part ;
93
90
         j < key_info->key_parts ;
105
102
}
106
103
 
107
104
 
108
 
void key_copy(unsigned char *to_key, unsigned char *from_record, KeyInfo *key_info,
 
105
void key_copy(unsigned char *to_key, unsigned char *from_record, KEY *key_info,
109
106
              unsigned int key_length)
110
107
{
111
108
  uint32_t length;
112
 
  KeyPartInfo *key_part;
 
109
  KEY_PART_INFO *key_part;
113
110
 
114
111
  if (key_length == 0)
115
112
    key_length= key_info->key_length;
148
145
  Zero the null components of key tuple.
149
146
*/
150
147
 
151
 
void key_zero_nulls(unsigned char *tuple, KeyInfo *key_info)
 
148
void key_zero_nulls(unsigned char *tuple, KEY *key_info)
152
149
{
153
 
  KeyPartInfo *key_part= key_info->key_part;
154
 
  KeyPartInfo *key_part_end= key_part + key_info->key_parts;
 
150
  KEY_PART_INFO *key_part= key_info->key_part;
 
151
  KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
155
152
  for (; key_part != key_part_end; key_part++)
156
153
  {
157
154
    if (key_part->null_bit && *tuple)
173
170
  @param key_length  specifies length of all keyparts that will be restored
174
171
*/
175
172
 
176
 
void key_restore(unsigned char *to_record, unsigned char *from_key, KeyInfo *key_info,
 
173
void key_restore(unsigned char *to_record, unsigned char *from_key, KEY *key_info,
177
174
                 uint16_t key_length)
178
175
{
179
176
  uint32_t length;
180
 
  KeyPartInfo *key_part;
 
177
  KEY_PART_INFO *key_part;
181
178
 
182
179
  if (key_length == 0)
183
180
  {
211
208
      field->setReadSet();
212
209
      from_key+= HA_KEY_BLOB_LENGTH;
213
210
      key_length-= HA_KEY_BLOB_LENGTH;
214
 
      field->set_ptr_offset(to_record - field->getTable()->getInsertRecord(),
 
211
      field->set_ptr_offset(to_record - field->table->record[0],
215
212
                            (ulong) blob_length, from_key);
216
213
      length= key_part->length;
217
214
    }
218
215
    else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
219
216
    {
220
217
      Field *field= key_part->field;
221
 
      ptrdiff_t ptrdiff= to_record - field->getTable()->getInsertRecord();
 
218
      ptrdiff_t ptrdiff= to_record - field->table->record[0];
222
219
 
223
220
      field->setReadSet();
224
221
      field->setWriteSet();
265
262
bool key_cmp_if_same(Table *table,const unsigned char *key,uint32_t idx,uint32_t key_length)
266
263
{
267
264
  uint32_t store_length;
268
 
  KeyPartInfo *key_part;
 
265
  KEY_PART_INFO *key_part;
269
266
  const unsigned char *key_end= key + key_length;;
270
267
 
271
268
  for (key_part=table->key_info[idx].key_part;
277
274
 
278
275
    if (key_part->null_bit)
279
276
    {
280
 
      if (*key != test(table->getInsertRecord()[key_part->null_offset] &
 
277
      if (*key != test(table->record[0][key_part->null_offset] &
281
278
                       key_part->null_bit))
282
279
        return 1;
283
280
      if (*key)
297
294
    {
298
295
      const CHARSET_INFO * const cs= key_part->field->charset();
299
296
      uint32_t char_length= key_part->length / cs->mbmaxlen;
300
 
      const unsigned char *pos= table->getInsertRecord() + key_part->offset;
 
297
      const unsigned char *pos= table->record[0] + key_part->offset;
301
298
      if (length > char_length)
302
299
      {
303
300
        char_length= my_charpos(cs, pos, pos + length, char_length);
309
306
        return 1;
310
307
      continue;
311
308
    }
312
 
    if (memcmp(key,table->getInsertRecord()+key_part->offset,length))
 
309
    if (memcmp(key,table->record[0]+key_part->offset,length))
313
310
      return 1;
314
311
  }
315
312
  return 0;
331
328
 
332
329
void key_unpack(String *to, Table *table, uint32_t idx)
333
330
{
334
 
  KeyPartInfo *key_part,*key_part_end;
 
331
  KEY_PART_INFO *key_part,*key_part_end;
335
332
  Field *field;
336
333
  String tmp;
337
334
 
345
342
      to->append('-');
346
343
    if (key_part->null_bit)
347
344
    {
348
 
      if (table->getInsertRecord()[key_part->null_offset] & key_part->null_bit)
 
345
      if (table->record[0][key_part->null_offset] & key_part->null_bit)
349
346
      {
350
347
        to->append(STRING_WITH_LEN("NULL"));
351
348
        continue;
355
352
    {
356
353
      const CHARSET_INFO * const cs= field->charset();
357
354
      field->setReadSet();
358
 
      field->val_str_internal(&tmp);
 
355
      field->val_str(&tmp);
359
356
      if (cs->mbmaxlen > 1 &&
360
 
          table->getField(key_part->fieldnr - 1)->field_length !=
 
357
          table->field[key_part->fieldnr - 1]->field_length !=
361
358
          key_part->length)
362
359
      {
363
360
        /*
375
372
      }
376
373
 
377
374
      if (key_part->length < field->pack_length())
378
 
        tmp.length(min(tmp.length(), static_cast<size_t>(key_part->length)));
 
375
        tmp.length(min(tmp.length(),(uint32_t)key_part->length));
379
376
      to->append(tmp);
380
377
    }
381
378
    else
402
399
    FALSE  Otherwise
403
400
*/
404
401
 
405
 
bool is_key_used(Table *table, uint32_t idx, const boost::dynamic_bitset<>& fields)
 
402
bool is_key_used(Table *table, uint32_t idx, const MyBitmap *fields)
406
403
{
407
 
  table->tmp_set.reset();
408
 
  table->mark_columns_used_by_index_no_reset(idx, table->tmp_set);
409
 
  if (table->tmp_set.is_subset_of(fields))
 
404
  table->tmp_set.clearAll();
 
405
  table->mark_columns_used_by_index_no_reset(idx, &table->tmp_set);
 
406
  if (bitmap_is_overlapping(&table->tmp_set, fields))
410
407
    return 1;
411
408
 
412
409
  /*
413
410
    If table handler has primary key as part of the index, check that primary
414
411
    key is not updated
415
412
  */
416
 
  if (idx != table->getShare()->getPrimaryKey() && table->getShare()->hasPrimaryKey() &&
 
413
  if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY &&
417
414
      (table->cursor->getEngine()->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX)))
418
 
  {
419
 
    return is_key_used(table, table->getShare()->getPrimaryKey(), fields);
420
 
  }
 
415
    return is_key_used(table, table->s->primary_key, fields);
421
416
  return 0;
422
417
}
423
418
 
426
421
  Compare key in row to a given key.
427
422
 
428
423
  @param key_part               Key part handler
429
 
  @param key                    Key to compare to value in table->getInsertRecord()
 
424
  @param key                    Key to compare to value in table->record[0]
430
425
  @param key_length             length of 'key'
431
426
 
432
427
  @return
436
431
    -   1               Key is larger than range
437
432
*/
438
433
 
439
 
int key_cmp(KeyPartInfo *key_part, const unsigned char *key, uint32_t key_length)
 
434
int key_cmp(KEY_PART_INFO *key_part, const unsigned char *key, uint32_t key_length)
440
435
{
441
436
  uint32_t store_length;
442
437
 
472
467
}
473
468
 
474
469
 
 
470
/*
 
471
  Compare two records in index order
 
472
  SYNOPSIS
 
473
    key_rec_cmp()
 
474
    key                         Index information
 
475
    rec0                        Pointer to table->record[0]
 
476
    first_rec                   Pointer to record compare with
 
477
    second_rec                  Pointer to record compare against first_rec
 
478
 
 
479
  DESCRIPTION
 
480
    This method is set-up such that it can be called directly from the
 
481
    priority queue and it is attempted to be optimised as much as possible
 
482
    since this will be called O(N * log N) times while performing a merge
 
483
    sort in various places in the code.
 
484
 
 
485
    We retrieve the pointer to table->record[0] using the fact that key_parts
 
486
    have an offset making it possible to calculate the start of the record.
 
487
    We need to get the diff to the compared record since none of the records
 
488
    being compared are stored in table->record[0].
 
489
 
 
490
    We first check for NULL values, if there are no NULL values we use
 
491
    a compare method that gets two field pointers and a max length
 
492
    and return the result of the comparison.
 
493
*/
 
494
 
 
495
int key_rec_cmp(void *key, unsigned char *first_rec, unsigned char *second_rec)
 
496
{
 
497
  KEY *key_info= (KEY*)key;
 
498
  uint32_t key_parts= key_info->key_parts, i= 0;
 
499
  KEY_PART_INFO *key_part= key_info->key_part;
 
500
  unsigned char *rec0= key_part->field->ptr - key_part->offset;
 
501
  ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0;
 
502
  int result= 0;
 
503
 
 
504
  do
 
505
  {
 
506
    Field *field= key_part->field;
 
507
 
 
508
    if (key_part->null_bit)
 
509
    {
 
510
      /* The key_part can contain NULL values */
 
511
      bool first_is_null= field->is_null_in_record_with_offset(first_diff);
 
512
      bool sec_is_null= field->is_null_in_record_with_offset(sec_diff);
 
513
      /*
 
514
        NULL is smaller then everything so if first is NULL and the other
 
515
        not then we know that we should return -1 and for the opposite
 
516
        we should return +1. If both are NULL then we call it equality
 
517
        although it is a strange form of equality, we have equally little
 
518
        information of the real value.
 
519
      */
 
520
      if (!first_is_null)
 
521
      {
 
522
        if (!sec_is_null)
 
523
          ; /* Fall through, no NULL fields */
 
524
        else
 
525
        {
 
526
          return(1);
 
527
        }
 
528
      }
 
529
      else if (!sec_is_null)
 
530
      {
 
531
        return(-1);
 
532
      }
 
533
      else
 
534
        goto next_loop; /* Both were NULL */
 
535
    }
 
536
    /*
 
537
      No null values in the fields
 
538
      We use the virtual method cmp_max with a max length parameter.
 
539
      For most field types this translates into a cmp without
 
540
      max length. The exceptions are the BLOB and VARCHAR field types
 
541
      that take the max length into account.
 
542
    */
 
543
    result= field->cmp_max(field->ptr+first_diff, field->ptr+sec_diff,
 
544
                           key_part->length);
 
545
next_loop:
 
546
    key_part++;
 
547
  } while (!result && ++i < key_parts);
 
548
  return(result);
 
549
}
 
550
 
475
551
} /* namespace drizzled */