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