~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL AB
2
3
   This program is free software; you can redistribute it and/or modify
4
   it under the terms of the GNU General Public License as published by
5
   the Free Software Foundation; version 2 of the License.
6
7
   This program is distributed in the hope that it will be useful,
8
   but WITHOUT ANY WARRANTY; without even the implied warranty of
9
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10
   GNU General Public License for more details.
11
12
   You should have received a copy of the GNU General Public License
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 */
15
16
17
/* Functions to handle keys and fields in forms */
18
934.2.21 by Jay Pipes
Move Key stuff into key.cc and out of session.cc
19
#include "drizzled/server_includes.h"
20
#include "drizzled/table.h"
21
#include "drizzled/key.h"
22
#include "drizzled/field/blob.h"
1 by brian
clean slate
23
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
24
#include <string>
982.1.3 by Padraig O'Sullivan
Various small cleanups to numerous files to now have calls to the correct
25
#include <bitset>
656.1.1 by Monty Taylor
OOOh doggie. Got rid of my_alloca.
26
27
using namespace std;
28
1 by brian
clean slate
29
/*
30
  Search after a key that starts with 'field'
31
32
  SYNOPSIS
33
    find_ref_key()
34
    key			First key to check
35
    key_count		How many keys to check
36
    record		Start of record
37
    field		Field to search after
38
    key_length		On partial match, contains length of fields before
39
			field
40
    keypart             key part # of a field
41
42
  NOTES
43
   Used when calculating key for NEXT_NUMBER
44
45
  IMPLEMENTATION
46
    If no key starts with field test if field is part of some key. If we find
47
    one, then return first key and set key_length to the number of bytes
48
    preceding 'field'.
49
50
  RETURN
51
   -1  field is not part of the key
52
   #   Key part for key matching key.
53
       key_length is set to length of key before (not including) field
54
*/
55
482 by Brian Aker
Remove uint.
56
int find_ref_key(KEY *key, uint32_t key_count, unsigned char *record, Field *field,
57
                 uint32_t *key_length, uint32_t *keypart)
1 by brian
clean slate
58
{
59
  register int i;
60
  register KEY *key_info;
482 by Brian Aker
Remove uint.
61
  uint32_t fieldpos;
1 by brian
clean slate
62
63
  fieldpos= field->offset(record);
64
65
  /* Test if some key starts as fieldpos */
66
  for (i= 0, key_info= key ;
67
       i < (int) key_count ;
68
       i++, key_info++)
69
  {
70
    if (key_info->key_part[0].offset == fieldpos)
71
    {                                  		/* Found key. Calc keylength */
72
      *key_length= *keypart= 0;
73
      return i;                                 /* Use this key */
74
    }
75
  }
76
77
  /* Test if some key contains fieldpos */
78
  for (i= 0, key_info= key;
79
       i < (int) key_count ;
80
       i++, key_info++)
81
  {
482 by Brian Aker
Remove uint.
82
    uint32_t j;
1 by brian
clean slate
83
    KEY_PART_INFO *key_part;
84
    *key_length=0;
85
    for (j=0, key_part=key_info->key_part ;
86
	 j < key_info->key_parts ;
87
	 j++, key_part++)
88
    {
89
      if (key_part->offset == fieldpos)
90
      {
91
        *keypart= j;
92
        return i;                               /* Use this key */
93
      }
94
      *key_length+= key_part->store_length;
95
    }
96
  }
97
  return(-1);					/* No key is ok */
98
}
99
100
481 by Brian Aker
Remove all of uchar.
101
void key_copy(unsigned char *to_key, unsigned char *from_record, KEY *key_info,
287.3.8 by Monty Taylor
Oy. Replaced max and min macros with std::max and std::min so that we get
102
              unsigned int key_length)
1 by brian
clean slate
103
{
482 by Brian Aker
Remove uint.
104
  uint32_t length;
1 by brian
clean slate
105
  KEY_PART_INFO *key_part;
106
107
  if (key_length == 0)
108
    key_length= key_info->key_length;
109
  for (key_part= key_info->key_part; (int) key_length > 0; key_part++)
110
  {
111
    if (key_part->null_bit)
112
    {
113
      *to_key++= test(from_record[key_part->null_offset] &
114
		   key_part->null_bit);
115
      key_length--;
116
    }
117
    if (key_part->key_part_flag & HA_BLOB_PART ||
118
        key_part->key_part_flag & HA_VAR_LENGTH_PART)
119
    {
120
      key_length-= HA_KEY_BLOB_LENGTH;
398.1.4 by Monty Taylor
Renamed max/min.
121
      length= cmin((uint16_t)key_length, key_part->length);
1 by brian
clean slate
122
      key_part->field->get_key_image(to_key, length, Field::itRAW);
123
      to_key+= HA_KEY_BLOB_LENGTH;
124
    }
125
    else
126
    {
398.1.4 by Monty Taylor
Renamed max/min.
127
      length= cmin((uint16_t)key_length, key_part->length);
1 by brian
clean slate
128
      Field *field= key_part->field;
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
129
      const CHARSET_INFO * const cs= field->charset();
482 by Brian Aker
Remove uint.
130
      uint32_t bytes= field->get_key_image(to_key, length, Field::itRAW);
1 by brian
clean slate
131
      if (bytes < length)
132
        cs->cset->fill(cs, (char*) to_key + bytes, length - bytes, ' ');
133
    }
134
    to_key+= length;
135
    key_length-= length;
136
  }
137
}
138
139
140
/**
141
  Zero the null components of key tuple.
142
*/
143
481 by Brian Aker
Remove all of uchar.
144
void key_zero_nulls(unsigned char *tuple, KEY *key_info)
1 by brian
clean slate
145
{
146
  KEY_PART_INFO *key_part= key_info->key_part;
147
  KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
148
  for (; key_part != key_part_end; key_part++)
149
  {
150
    if (key_part->null_bit && *tuple)
212.6.1 by Mats Kindahl
Replacing all bzero() calls with memset() calls and removing the bzero.c file.
151
      memset(tuple+1, 0, key_part->store_length-1);
1 by brian
clean slate
152
    tuple+= key_part->store_length;
153
  }
154
}
155
156
157
/*
158
  Restore a key from some buffer to record.
159
160
    This function converts a key into record format. It can be used in cases
161
    when we want to return a key as a result row.
162
163
  @param to_record   record buffer where the key will be restored to
164
  @param from_key    buffer that contains a key
165
  @param key_info    descriptor of the index
166
  @param key_length  specifies length of all keyparts that will be restored
167
*/
168
481 by Brian Aker
Remove all of uchar.
169
void key_restore(unsigned char *to_record, unsigned char *from_key, KEY *key_info,
287.3.8 by Monty Taylor
Oy. Replaced max and min macros with std::max and std::min so that we get
170
                 uint16_t key_length)
1 by brian
clean slate
171
{
482 by Brian Aker
Remove uint.
172
  uint32_t length;
1 by brian
clean slate
173
  KEY_PART_INFO *key_part;
174
175
  if (key_length == 0)
176
  {
177
    key_length= key_info->key_length;
178
  }
179
  for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++)
180
  {
481 by Brian Aker
Remove all of uchar.
181
    unsigned char used_uneven_bits= 0;
1 by brian
clean slate
182
    if (key_part->null_bit)
183
    {
184
      if (*from_key++)
185
	to_record[key_part->null_offset]|= key_part->null_bit;
186
      else
187
	to_record[key_part->null_offset]&= ~key_part->null_bit;
188
      key_length--;
189
    }
190
    if (key_part->key_part_flag & HA_BLOB_PART)
191
    {
192
      /*
193
        This in fact never happens, as we have only partial BLOB
194
        keys yet anyway, so it's difficult to find any sence to
195
        restore the part of a record.
196
        Maybe this branch is to be removed, but now we
197
        have to ignore GCov compaining.
198
      */
482 by Brian Aker
Remove uint.
199
      uint32_t blob_length= uint2korr(from_key);
1 by brian
clean slate
200
      Field_blob *field= (Field_blob*) key_part->field;
201
      from_key+= HA_KEY_BLOB_LENGTH;
202
      key_length-= HA_KEY_BLOB_LENGTH;
203
      field->set_ptr_offset(to_record - field->table->record[0],
204
                            (ulong) blob_length, from_key);
205
      length= key_part->length;
206
    }
207
    else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
208
    {
209
      Field *field= key_part->field;
210
      my_ptrdiff_t ptrdiff= to_record - field->table->record[0];
211
      field->move_field_offset(ptrdiff);
212
      key_length-= HA_KEY_BLOB_LENGTH;
398.1.4 by Monty Taylor
Renamed max/min.
213
      length= cmin(key_length, key_part->length);
1 by brian
clean slate
214
      field->set_key_image(from_key, length);
215
      from_key+= HA_KEY_BLOB_LENGTH;
216
      field->move_field_offset(-ptrdiff);
217
    }
218
    else
219
    {
398.1.4 by Monty Taylor
Renamed max/min.
220
      length= cmin(key_length, key_part->length);
1 by brian
clean slate
221
      /* skip the byte with 'uneven' bits, if used */
222
      memcpy(to_record + key_part->offset, from_key + used_uneven_bits
223
             , (size_t) length - used_uneven_bits);
224
    }
225
    from_key+= length;
226
    key_length-= length;
227
  }
228
}
229
230
231
/**
232
  Compare if a key has changed.
233
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
234
  @param table		Table
1 by brian
clean slate
235
  @param key		key to compare to row
236
  @param idx		Index used
237
  @param key_length	Length of key
238
239
  @note
240
    In theory we could just call field->cmp() for all field types,
241
    but as we are only interested if a key has changed (not if the key is
242
    larger or smaller than the previous value) we can do things a bit
243
    faster by using memcmp() instead.
244
245
  @retval
246
    0	If key is equal
247
  @retval
248
    1	Key has changed
249
*/
250
482 by Brian Aker
Remove uint.
251
bool key_cmp_if_same(Table *table,const unsigned char *key,uint32_t idx,uint32_t key_length)
1 by brian
clean slate
252
{
482 by Brian Aker
Remove uint.
253
  uint32_t store_length;
1 by brian
clean slate
254
  KEY_PART_INFO *key_part;
481 by Brian Aker
Remove all of uchar.
255
  const unsigned char *key_end= key + key_length;;
1 by brian
clean slate
256
257
  for (key_part=table->key_info[idx].key_part;
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
258
       key < key_end ;
1 by brian
clean slate
259
       key_part++, key+= store_length)
260
  {
482 by Brian Aker
Remove uint.
261
    uint32_t length;
1 by brian
clean slate
262
    store_length= key_part->store_length;
263
264
    if (key_part->null_bit)
265
    {
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
266
      if (*key != test(table->record[0][key_part->null_offset] &
1 by brian
clean slate
267
		       key_part->null_bit))
268
	return 1;
269
      if (*key)
270
	continue;
271
      key++;
272
      store_length--;
273
    }
274
    if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART |
275
                                   HA_BIT_PART))
276
    {
277
      if (key_part->field->key_cmp(key, key_part->length))
278
	return 1;
279
      continue;
280
    }
895 by Brian Aker
Completion (?) of uint conversion.
281
    length= cmin((uint32_t) (key_end-key), store_length);
1 by brian
clean slate
282
    if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
283
                                FIELDFLAG_PACK)))
284
    {
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
285
      const CHARSET_INFO * const cs= key_part->field->charset();
482 by Brian Aker
Remove uint.
286
      uint32_t char_length= key_part->length / cs->mbmaxlen;
481 by Brian Aker
Remove all of uchar.
287
      const unsigned char *pos= table->record[0] + key_part->offset;
1 by brian
clean slate
288
      if (length > char_length)
289
      {
290
        char_length= my_charpos(cs, pos, pos + length, char_length);
291
        set_if_smaller(char_length, length);
292
      }
293
      if (cs->coll->strnncollsp(cs,
481 by Brian Aker
Remove all of uchar.
294
                                (const unsigned char*) key, length,
295
                                (const unsigned char*) pos, char_length, 0))
1 by brian
clean slate
296
        return 1;
297
      continue;
298
    }
299
    if (memcmp(key,table->record[0]+key_part->offset,length))
300
      return 1;
301
  }
302
  return 0;
303
}
304
305
/*
306
  unpack key-fields from record to some buffer.
307
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
308
  This is used mainly to get a good error message.  We temporary
1 by brian
clean slate
309
  change the column bitmap so that all columns are readable.
310
311
  @param
312
     to		Store value here in an easy to read form
313
  @param
314
     table	Table to use
315
  @param
316
     idx	Key number
317
*/
318
482 by Brian Aker
Remove uint.
319
void key_unpack(String *to,Table *table,uint32_t idx)
1 by brian
clean slate
320
{
321
  KEY_PART_INFO *key_part,*key_part_end;
322
  Field *field;
323
  String tmp;
324
325
  to->length(0);
326
  for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
327
	 table->key_info[idx].key_parts ;
328
       key_part < key_part_end;
329
       key_part++)
330
  {
331
    if (to->length())
332
      to->append('-');
333
    if (key_part->null_bit)
334
    {
335
      if (table->record[0][key_part->null_offset] & key_part->null_bit)
336
      {
337
	to->append(STRING_WITH_LEN("NULL"));
338
	continue;
339
      }
340
    }
341
    if ((field=key_part->field))
342
    {
264.2.6 by Andrey Hristov
Constify the usage of CHARSET_INFO almost to the last place in the code.
343
      const CHARSET_INFO * const cs= field->charset();
1 by brian
clean slate
344
      field->val_str(&tmp);
345
      if (cs->mbmaxlen > 1 &&
346
          table->field[key_part->fieldnr - 1]->field_length !=
347
          key_part->length)
348
      {
349
        /*
350
          Prefix key, multi-byte charset.
351
          For the columns of type CHAR(N), the above val_str()
352
          call will return exactly "key_part->length" bytes,
353
          which can break a multi-byte characters in the middle.
354
          Align, returning not more than "char_length" characters.
355
        */
482 by Brian Aker
Remove uint.
356
        uint32_t charpos, char_length= key_part->length / cs->mbmaxlen;
813.1.3 by Jay Pipes
Incorrectly passing str.ptr() instead of str.c_ptr() to my_charpos() in key.cc:key_unpack(). This resulted in duplicate key error messages containing random characters due to a bad offset, and would show up as random failure in the myisam.test case when running make test but not ./dtr myisam.
357
        if ((charpos= my_charpos(cs, tmp.c_ptr(),
358
                                 tmp.c_ptr() + tmp.length(),
1 by brian
clean slate
359
                                 char_length)) < key_part->length)
360
          tmp.length(charpos);
361
      }
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
362
1 by brian
clean slate
363
      if (key_part->length < field->pack_length())
398.1.4 by Monty Taylor
Renamed max/min.
364
	tmp.length(cmin(tmp.length(),(uint32_t)key_part->length));
1 by brian
clean slate
365
      to->append(tmp);
366
    }
367
    else
368
      to->append(STRING_WITH_LEN("???"));
369
  }
327.2.3 by Brian Aker
Refactoring of class Table
370
51.1.6 by Jay Pipes
Final removal of DBUG_ statements. Build/tests pass.
371
  return;
1 by brian
clean slate
372
}
373
374
375
/*
376
  Check if key uses field that is marked in passed field bitmap.
377
378
  SYNOPSIS
379
    is_key_used()
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
380
      table   Table object with which keys and fields are associated.
1 by brian
clean slate
381
      idx     Key to be checked.
382
      fields  Bitmap of fields to be checked.
383
384
  NOTE
327.1.5 by Brian Aker
Refactor around classes. TABLE_LIST has been factored out of table.h
385
    This function uses Table::tmp_set bitmap so the caller should care
1 by brian
clean slate
386
    about saving/restoring its state if it also uses this bitmap.
387
388
  RETURN VALUE
389
    TRUE   Key uses field from bitmap
390
    FALSE  Otherwise
391
*/
392
982.1.3 by Padraig O'Sullivan
Various small cleanups to numerous files to now have calls to the correct
393
bool is_key_used(Table *table, uint32_t idx, const bitset<MAX_FIELDS> *fields)
1 by brian
clean slate
394
{
982.1.1 by Padraig O'Sullivan
Initial work on removing MY_BITMAP from the Drizzle code base. For a start,
395
  table->tmp_set.reset();
1 by brian
clean slate
396
  table->mark_columns_used_by_index_no_reset(idx, &table->tmp_set);
982.1.8 by Padraig O'Sullivan
Added new functions for adding a bitset in a thread-safe way. I created a
397
  if (isBitmapOverlapping(fields, &table->tmp_set))
1 by brian
clean slate
398
    return 1;
399
400
  /*
401
    If table handler has primary key as part of the index, check that primary
402
    key is not updated
403
  */
404
  if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY &&
405
      (table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
406
    return is_key_used(table, table->s->primary_key, fields);
407
  return 0;
408
}
409
410
411
/**
412
  Compare key in row to a given key.
413
414
  @param key_part		Key part handler
415
  @param key			Key to compare to value in table->record[0]
416
  @param key_length		length of 'key'
417
418
  @return
419
    The return value is SIGN(key_in_row - range_key):
420
    -   0		Key is equal to range or 'range' == 0 (no range)
421
    -  -1		Key is less than range
422
    -   1		Key is larger than range
423
*/
424
482 by Brian Aker
Remove uint.
425
int key_cmp(KEY_PART_INFO *key_part, const unsigned char *key, uint32_t key_length)
1 by brian
clean slate
426
{
482 by Brian Aker
Remove uint.
427
  uint32_t store_length;
1 by brian
clean slate
428
481 by Brian Aker
Remove all of uchar.
429
  for (const unsigned char *end=key + key_length;
1 by brian
clean slate
430
       key < end;
431
       key+= store_length, key_part++)
432
  {
433
    int cmp;
434
    store_length= key_part->store_length;
435
    if (key_part->null_bit)
436
    {
437
      /* This key part allows null values; NULL is lower than everything */
438
      register bool field_is_null= key_part->field->is_null();
439
      if (*key)                                 // If range key is null
440
      {
441
	/* the range is expecting a null value */
442
	if (!field_is_null)
443
	  return 1;                             // Found key is > range
444
        /* null -- exact match, go to next key part */
445
	continue;
446
      }
447
      else if (field_is_null)
448
	return -1;                              // NULL is less than any value
449
      key++;					// Skip null byte
450
      store_length--;
451
    }
452
    if ((cmp=key_part->field->key_cmp(key, key_part->length)) < 0)
453
      return -1;
454
    if (cmp > 0)
455
      return 1;
456
  }
457
  return 0;                                     // Keys are equal
458
}
459
460
461
/*
462
  Compare two records in index order
463
  SYNOPSIS
464
    key_rec_cmp()
465
    key                         Index information
466
    rec0                        Pointer to table->record[0]
467
    first_rec                   Pointer to record compare with
468
    second_rec                  Pointer to record compare against first_rec
469
470
  DESCRIPTION
471
    This method is set-up such that it can be called directly from the
472
    priority queue and it is attempted to be optimised as much as possible
473
    since this will be called O(N * log N) times while performing a merge
474
    sort in various places in the code.
475
476
    We retrieve the pointer to table->record[0] using the fact that key_parts
477
    have an offset making it possible to calculate the start of the record.
478
    We need to get the diff to the compared record since none of the records
479
    being compared are stored in table->record[0].
480
481
    We first check for NULL values, if there are no NULL values we use
482
    a compare method that gets two field pointers and a max length
483
    and return the result of the comparison.
484
*/
485
481 by Brian Aker
Remove all of uchar.
486
int key_rec_cmp(void *key, unsigned char *first_rec, unsigned char *second_rec)
1 by brian
clean slate
487
{
488
  KEY *key_info= (KEY*)key;
482 by Brian Aker
Remove uint.
489
  uint32_t key_parts= key_info->key_parts, i= 0;
1 by brian
clean slate
490
  KEY_PART_INFO *key_part= key_info->key_part;
481 by Brian Aker
Remove all of uchar.
491
  unsigned char *rec0= key_part->field->ptr - key_part->offset;
1 by brian
clean slate
492
  my_ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0;
493
  int result= 0;
494
495
  do
496
  {
497
    Field *field= key_part->field;
498
499
    if (key_part->null_bit)
500
    {
501
      /* The key_part can contain NULL values */
502
      bool first_is_null= field->is_null_in_record_with_offset(first_diff);
503
      bool sec_is_null= field->is_null_in_record_with_offset(sec_diff);
504
      /*
505
        NULL is smaller then everything so if first is NULL and the other
506
        not then we know that we should return -1 and for the opposite
507
        we should return +1. If both are NULL then we call it equality
508
        although it is a strange form of equality, we have equally little
509
        information of the real value.
510
      */
511
      if (!first_is_null)
512
      {
513
        if (!sec_is_null)
514
          ; /* Fall through, no NULL fields */
515
        else
516
        {
51.1.6 by Jay Pipes
Final removal of DBUG_ statements. Build/tests pass.
517
          return(1);
1 by brian
clean slate
518
        }
519
      }
520
      else if (!sec_is_null)
521
      {
51.1.6 by Jay Pipes
Final removal of DBUG_ statements. Build/tests pass.
522
        return(-1);
1 by brian
clean slate
523
      }
524
      else
525
        goto next_loop; /* Both were NULL */
526
    }
527
    /*
528
      No null values in the fields
529
      We use the virtual method cmp_max with a max length parameter.
530
      For most field types this translates into a cmp without
531
      max length. The exceptions are the BLOB and VARCHAR field types
532
      that take the max length into account.
533
    */
534
    result= field->cmp_max(field->ptr+first_diff, field->ptr+sec_diff,
535
                           key_part->length);
536
next_loop:
537
    key_part++;
538
  } while (!result && ++i < key_parts);
51.1.6 by Jay Pipes
Final removal of DBUG_ statements. Build/tests pass.
539
  return(result);
1 by brian
clean slate
540
}
934.2.21 by Jay Pipes
Move Key stuff into key.cc and out of session.cc
541
542
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
543
  :type(rhs.type),
544
  key_create_info(rhs.key_create_info),
545
  columns(rhs.columns, mem_root),
546
  name(rhs.name),
547
  generated(rhs.generated)
548
{
549
  list_copy_and_replace_each_value(columns, mem_root);
550
}