~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/key.cc

  • Committer: Patrick Crews
  • Date: 2011-01-29 14:17:35 UTC
  • mto: (2126.1.1 build)
  • mto: This revision was merged to the branch mainline in revision 2127.
  • Revision ID: gleebix@gmail.com-20110129141735-3y2658vt5ur0a33o
Fixes to make test-dbqp

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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  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>
23
26
 
24
27
#include <string>
25
28
 
57
60
       key_length is set to length of key before (not including) field
58
61
*/
59
62
 
60
 
int find_ref_key(KEY *key, uint32_t key_count, unsigned char *record, Field *field,
 
63
int find_ref_key(KeyInfo *key, uint32_t key_count, unsigned char *record, Field *field,
61
64
                 uint32_t *key_length, uint32_t *keypart)
62
65
{
63
66
  register int i;
64
 
  register KEY *key_info;
 
67
  register KeyInfo *key_info;
65
68
  uint32_t fieldpos;
66
69
 
67
70
  fieldpos= field->offset(record);
84
87
       i++, key_info++)
85
88
  {
86
89
    uint32_t j;
87
 
    KEY_PART_INFO *key_part;
 
90
    KeyPartInfo *key_part;
88
91
    *key_length=0;
89
92
    for (j=0, key_part=key_info->key_part ;
90
93
         j < key_info->key_parts ;
102
105
}
103
106
 
104
107
 
105
 
void key_copy(unsigned char *to_key, unsigned char *from_record, KEY *key_info,
 
108
void key_copy(unsigned char *to_key, unsigned char *from_record, KeyInfo *key_info,
106
109
              unsigned int key_length)
107
110
{
108
111
  uint32_t length;
109
 
  KEY_PART_INFO *key_part;
 
112
  KeyPartInfo *key_part;
110
113
 
111
114
  if (key_length == 0)
112
115
    key_length= key_info->key_length;
145
148
  Zero the null components of key tuple.
146
149
*/
147
150
 
148
 
void key_zero_nulls(unsigned char *tuple, KEY *key_info)
 
151
void key_zero_nulls(unsigned char *tuple, KeyInfo *key_info)
149
152
{
150
 
  KEY_PART_INFO *key_part= key_info->key_part;
151
 
  KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
 
153
  KeyPartInfo *key_part= key_info->key_part;
 
154
  KeyPartInfo *key_part_end= key_part + key_info->key_parts;
152
155
  for (; key_part != key_part_end; key_part++)
153
156
  {
154
157
    if (key_part->null_bit && *tuple)
170
173
  @param key_length  specifies length of all keyparts that will be restored
171
174
*/
172
175
 
173
 
void key_restore(unsigned char *to_record, unsigned char *from_key, KEY *key_info,
 
176
void key_restore(unsigned char *to_record, unsigned char *from_key, KeyInfo *key_info,
174
177
                 uint16_t key_length)
175
178
{
176
179
  uint32_t length;
177
 
  KEY_PART_INFO *key_part;
 
180
  KeyPartInfo *key_part;
178
181
 
179
182
  if (key_length == 0)
180
183
  {
208
211
      field->setReadSet();
209
212
      from_key+= HA_KEY_BLOB_LENGTH;
210
213
      key_length-= HA_KEY_BLOB_LENGTH;
211
 
      field->set_ptr_offset(to_record - field->table->record[0],
 
214
      field->set_ptr_offset(to_record - field->getTable()->getInsertRecord(),
212
215
                            (ulong) blob_length, from_key);
213
216
      length= key_part->length;
214
217
    }
215
218
    else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
216
219
    {
217
220
      Field *field= key_part->field;
218
 
      ptrdiff_t ptrdiff= to_record - field->table->record[0];
 
221
      ptrdiff_t ptrdiff= to_record - field->getTable()->getInsertRecord();
219
222
 
220
223
      field->setReadSet();
221
224
      field->setWriteSet();
262
265
bool key_cmp_if_same(Table *table,const unsigned char *key,uint32_t idx,uint32_t key_length)
263
266
{
264
267
  uint32_t store_length;
265
 
  KEY_PART_INFO *key_part;
 
268
  KeyPartInfo *key_part;
266
269
  const unsigned char *key_end= key + key_length;;
267
270
 
268
271
  for (key_part=table->key_info[idx].key_part;
274
277
 
275
278
    if (key_part->null_bit)
276
279
    {
277
 
      if (*key != test(table->record[0][key_part->null_offset] &
 
280
      if (*key != test(table->getInsertRecord()[key_part->null_offset] &
278
281
                       key_part->null_bit))
279
282
        return 1;
280
283
      if (*key)
294
297
    {
295
298
      const CHARSET_INFO * const cs= key_part->field->charset();
296
299
      uint32_t char_length= key_part->length / cs->mbmaxlen;
297
 
      const unsigned char *pos= table->record[0] + key_part->offset;
 
300
      const unsigned char *pos= table->getInsertRecord() + key_part->offset;
298
301
      if (length > char_length)
299
302
      {
300
303
        char_length= my_charpos(cs, pos, pos + length, char_length);
306
309
        return 1;
307
310
      continue;
308
311
    }
309
 
    if (memcmp(key,table->record[0]+key_part->offset,length))
 
312
    if (memcmp(key,table->getInsertRecord()+key_part->offset,length))
310
313
      return 1;
311
314
  }
312
315
  return 0;
328
331
 
329
332
void key_unpack(String *to, Table *table, uint32_t idx)
330
333
{
331
 
  KEY_PART_INFO *key_part,*key_part_end;
 
334
  KeyPartInfo *key_part,*key_part_end;
332
335
  Field *field;
333
336
  String tmp;
334
337
 
342
345
      to->append('-');
343
346
    if (key_part->null_bit)
344
347
    {
345
 
      if (table->record[0][key_part->null_offset] & key_part->null_bit)
 
348
      if (table->getInsertRecord()[key_part->null_offset] & key_part->null_bit)
346
349
      {
347
350
        to->append(STRING_WITH_LEN("NULL"));
348
351
        continue;
352
355
    {
353
356
      const CHARSET_INFO * const cs= field->charset();
354
357
      field->setReadSet();
355
 
      field->val_str(&tmp);
 
358
      field->val_str_internal(&tmp);
356
359
      if (cs->mbmaxlen > 1 &&
357
 
          table->field[key_part->fieldnr - 1]->field_length !=
 
360
          table->getField(key_part->fieldnr - 1)->field_length !=
358
361
          key_part->length)
359
362
      {
360
363
        /*
372
375
      }
373
376
 
374
377
      if (key_part->length < field->pack_length())
375
 
        tmp.length(min(tmp.length(),(uint32_t)key_part->length));
 
378
        tmp.length(min(tmp.length(), static_cast<size_t>(key_part->length)));
376
379
      to->append(tmp);
377
380
    }
378
381
    else
399
402
    FALSE  Otherwise
400
403
*/
401
404
 
402
 
bool is_key_used(Table *table, uint32_t idx, const MyBitmap *fields)
 
405
bool is_key_used(Table *table, uint32_t idx, const boost::dynamic_bitset<>& fields)
403
406
{
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))
 
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))
407
410
    return 1;
408
411
 
409
412
  /*
410
413
    If table handler has primary key as part of the index, check that primary
411
414
    key is not updated
412
415
  */
413
 
  if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY &&
 
416
  if (idx != table->getShare()->getPrimaryKey() && table->getShare()->hasPrimaryKey() &&
414
417
      (table->cursor->getEngine()->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX)))
415
 
    return is_key_used(table, table->s->primary_key, fields);
 
418
  {
 
419
    return is_key_used(table, table->getShare()->getPrimaryKey(), fields);
 
420
  }
416
421
  return 0;
417
422
}
418
423
 
421
426
  Compare key in row to a given key.
422
427
 
423
428
  @param key_part               Key part handler
424
 
  @param key                    Key to compare to value in table->record[0]
 
429
  @param key                    Key to compare to value in table->getInsertRecord()
425
430
  @param key_length             length of 'key'
426
431
 
427
432
  @return
431
436
    -   1               Key is larger than range
432
437
*/
433
438
 
434
 
int key_cmp(KEY_PART_INFO *key_part, const unsigned char *key, uint32_t key_length)
 
439
int key_cmp(KeyPartInfo *key_part, const unsigned char *key, uint32_t key_length)
435
440
{
436
441
  uint32_t store_length;
437
442
 
467
472
}
468
473
 
469
474
 
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
 
 
551
475
} /* namespace drizzled */