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 */
17
17
/* Functions to handle keys and fields in forms */
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"
25
#include <boost/dynamic_bitset.hpp>
31
26
using namespace std;
37
29
Search after a key that starts with 'field'
60
52
key_length is set to length of key before (not including) field
63
int find_ref_key(KeyInfo *key, uint32_t key_count, unsigned char *record, Field *field,
55
int find_ref_key(KEY *key, uint32_t key_count, unsigned char *record, Field *field,
64
56
uint32_t *key_length, uint32_t *keypart)
67
register KeyInfo *key_info;
59
register KEY *key_info;
70
62
fieldpos= field->offset(record);
125
117
key_part->key_part_flag & HA_VAR_LENGTH_PART)
127
119
key_length-= HA_KEY_BLOB_LENGTH;
128
length= min((uint16_t)key_length, key_part->length);
120
length= cmin((uint16_t)key_length, key_part->length);
129
121
key_part->field->get_key_image(to_key, length);
130
122
to_key+= HA_KEY_BLOB_LENGTH;
134
length= min((uint16_t)key_length, key_part->length);
126
length= cmin((uint16_t)key_length, key_part->length);
135
127
Field *field= key_part->field;
136
128
const CHARSET_INFO * const cs= field->charset();
137
129
uint32_t bytes= field->get_key_image(to_key, length);
148
140
Zero the null components of key tuple.
151
void key_zero_nulls(unsigned char *tuple, KeyInfo *key_info)
143
void key_zero_nulls(unsigned char *tuple, KEY *key_info)
153
KeyPartInfo *key_part= key_info->key_part;
154
KeyPartInfo *key_part_end= key_part + key_info->key_parts;
145
KEY_PART_INFO *key_part= key_info->key_part;
146
KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
155
147
for (; key_part != key_part_end; key_part++)
157
149
if (key_part->null_bit && *tuple)
202
194
restore the part of a record.
203
195
Maybe this branch is to be removed, but now we
204
196
have to ignore GCov compaining.
206
This may make more sense once we push down block lengths to the engine (aka partial retrieval).
208
198
uint32_t blob_length= uint2korr(from_key);
209
199
Field_blob *field= (Field_blob*) key_part->field;
212
200
from_key+= HA_KEY_BLOB_LENGTH;
213
201
key_length-= HA_KEY_BLOB_LENGTH;
214
field->set_ptr_offset(to_record - field->getTable()->getInsertRecord(),
202
field->set_ptr_offset(to_record - field->table->record[0],
215
203
(ulong) blob_length, from_key);
216
204
length= key_part->length;
218
206
else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
220
208
Field *field= key_part->field;
221
ptrdiff_t ptrdiff= to_record - field->getTable()->getInsertRecord();
224
field->setWriteSet();
209
my_ptrdiff_t ptrdiff= to_record - field->table->record[0];
225
210
field->move_field_offset(ptrdiff);
226
211
key_length-= HA_KEY_BLOB_LENGTH;
227
length= min(key_length, key_part->length);
212
length= cmin(key_length, key_part->length);
228
213
field->set_key_image(from_key, length);
229
214
from_key+= HA_KEY_BLOB_LENGTH;
230
215
field->move_field_offset(-ptrdiff);
234
length= min(key_length, key_part->length);
219
length= cmin(key_length, key_part->length);
235
220
/* skip the byte with 'uneven' bits, if used */
236
221
memcpy(to_record + key_part->offset, from_key + used_uneven_bits
237
222
, (size_t) length - used_uneven_bits);
295
length= min((uint32_t) (key_end-key), store_length);
296
if (key_part->field->type() == DRIZZLE_TYPE_VARCHAR)
280
length= cmin((uint32_t) (key_end-key), store_length);
281
if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
298
284
const CHARSET_INFO * const cs= key_part->field->charset();
299
285
uint32_t char_length= key_part->length / cs->mbmaxlen;
300
const unsigned char *pos= table->getInsertRecord() + key_part->offset;
286
const unsigned char *pos= table->record[0] + key_part->offset;
301
287
if (length > char_length)
303
289
char_length= my_charpos(cs, pos, pos + length, char_length);
346
332
if (key_part->null_bit)
348
if (table->getInsertRecord()[key_part->null_offset] & key_part->null_bit)
334
if (table->record[0][key_part->null_offset] & key_part->null_bit)
350
336
to->append(STRING_WITH_LEN("NULL"));
354
if ((field= key_part->field))
340
if ((field=key_part->field))
356
342
const CHARSET_INFO * const cs= field->charset();
358
field->val_str_internal(&tmp);
343
field->val_str(&tmp);
359
344
if (cs->mbmaxlen > 1 &&
360
table->getField(key_part->fieldnr - 1)->field_length !=
345
table->field[key_part->fieldnr - 1]->field_length !=
361
346
key_part->length)
405
bool is_key_used(Table *table, uint32_t idx, const boost::dynamic_bitset<>& fields)
392
bool is_key_used(Table *table, uint32_t idx, const MY_BITMAP *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))
394
bitmap_clear_all(&table->tmp_set);
395
table->mark_columns_used_by_index_no_reset(idx, &table->tmp_set);
396
if (bitmap_is_overlapping(&table->tmp_set, fields))
413
400
If table handler has primary key as part of the index, check that primary
414
401
key is not updated
416
if (idx != table->getShare()->getPrimaryKey() && table->getShare()->hasPrimaryKey() &&
417
(table->cursor->getEngine()->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX)))
419
return is_key_used(table, table->getShare()->getPrimaryKey(), fields);
403
if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY &&
404
(table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
405
return is_key_used(table, table->s->primary_key, fields);
475
} /* namespace drizzled */
461
Compare two records in index order
464
key Index information
465
rec0 Pointer to table->record[0]
466
first_rec Pointer to record compare with
467
second_rec Pointer to record compare against first_rec
470
This method is set-up such that it can be called directly from the
471
priority queue and it is attempted to be optimised as much as possible
472
since this will be called O(N * log N) times while performing a merge
473
sort in various places in the code.
475
We retrieve the pointer to table->record[0] using the fact that key_parts
476
have an offset making it possible to calculate the start of the record.
477
We need to get the diff to the compared record since none of the records
478
being compared are stored in table->record[0].
480
We first check for NULL values, if there are no NULL values we use
481
a compare method that gets two field pointers and a max length
482
and return the result of the comparison.
485
int key_rec_cmp(void *key, unsigned char *first_rec, unsigned char *second_rec)
487
KEY *key_info= (KEY*)key;
488
uint32_t key_parts= key_info->key_parts, i= 0;
489
KEY_PART_INFO *key_part= key_info->key_part;
490
unsigned char *rec0= key_part->field->ptr - key_part->offset;
491
my_ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0;
496
Field *field= key_part->field;
498
if (key_part->null_bit)
500
/* The key_part can contain NULL values */
501
bool first_is_null= field->is_null_in_record_with_offset(first_diff);
502
bool sec_is_null= field->is_null_in_record_with_offset(sec_diff);
504
NULL is smaller then everything so if first is NULL and the other
505
not then we know that we should return -1 and for the opposite
506
we should return +1. If both are NULL then we call it equality
507
although it is a strange form of equality, we have equally little
508
information of the real value.
513
; /* Fall through, no NULL fields */
519
else if (!sec_is_null)
524
goto next_loop; /* Both were NULL */
527
No null values in the fields
528
We use the virtual method cmp_max with a max length parameter.
529
For most field types this translates into a cmp without
530
max length. The exceptions are the BLOB and VARCHAR field types
531
that take the max length into account.
533
result= field->cmp_max(field->ptr+first_diff, field->ptr+sec_diff,
537
} while (!result && ++i < key_parts);
541
Key::Key(const Key &rhs, MEM_ROOT *mem_root)
543
key_create_info(rhs.key_create_info),
544
columns(rhs.columns, mem_root),
546
generated(rhs.generated)
548
list_copy_and_replace_each_value(columns, mem_root);