~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to drizzled/key.cc

  • Committer: Eric Day
  • Date: 2009-11-10 21:50:22 UTC
  • mto: This revision was merged to the branch mainline in revision 1218.
  • Revision ID: eday@oddments.org-20091110215022-0b2nqmurv7b2l6wo
Duplicated oldlibdrizzle module, one for Drizzle protocol and one for MySQL, per Brian's request from merge proposal. Port options are now --drizzle-protocol-port and --mysql-protocol-port.

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