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 */
20
#include <drizzled/table.h>
21
#include <drizzled/key.h>
22
#include <drizzled/field/blob.h>
23
#include <drizzled/util/test.h>
24
#include <drizzled/plugin/storage_engine.h>
26
#include <boost/dynamic_bitset.hpp>
19
#include <drizzled/server_includes.h>
38
22
Search after a key that starts with 'field'
61
45
key_length is set to length of key before (not including) field
64
int find_ref_key(KeyInfo *key, uint32_t key_count, unsigned char *record, Field *field,
48
int find_ref_key(KEY *key, uint32_t key_count, unsigned char *record, Field *field,
65
49
uint32_t *key_length, uint32_t *keypart)
52
register KEY *key_info;
71
55
fieldpos= field->offset(record);
109
void key_copy(unsigned char *to_key, unsigned char *from_record, KeyInfo *key_info,
94
Copy part of a record that forms a key or key prefix to a buffer.
96
The function takes a complete table record (as e.g. retrieved by
97
handler::index_read()), and a description of an index on the same table,
98
and extracts the first key_length bytes of the record which are part of a
99
key into to_key. If length == 0 then copy all bytes from the record that
102
@param to_key buffer that will be used as a key
103
@param from_record full record to be copied from
104
@param key_info descriptor of the index
105
@param key_length specifies length of all keyparts that will be copied
108
void key_copy(unsigned char *to_key, unsigned char *from_record, KEY *key_info,
110
109
unsigned int key_length)
113
KeyPartInfo *key_part;
112
KEY_PART_INFO *key_part;
115
114
if (key_length == 0)
116
115
key_length= key_info->key_length;
126
125
key_part->key_part_flag & HA_VAR_LENGTH_PART)
128
127
key_length-= HA_KEY_BLOB_LENGTH;
129
length= min((uint16_t)key_length, key_part->length);
130
key_part->field->get_key_image(to_key, length);
128
length= cmin((uint16_t)key_length, key_part->length);
129
key_part->field->get_key_image(to_key, length, Field::itRAW);
131
130
to_key+= HA_KEY_BLOB_LENGTH;
135
length= min((uint16_t)key_length, key_part->length);
134
length= cmin((uint16_t)key_length, key_part->length);
136
135
Field *field= key_part->field;
137
136
const CHARSET_INFO * const cs= field->charset();
138
uint32_t bytes= field->get_key_image(to_key, length);
137
uint32_t bytes= field->get_key_image(to_key, length, Field::itRAW);
139
138
if (bytes < length)
140
139
cs->cset->fill(cs, (char*) to_key + bytes, length - bytes, ' ');
149
148
Zero the null components of key tuple.
152
void key_zero_nulls(unsigned char *tuple, KeyInfo *key_info)
151
void key_zero_nulls(unsigned char *tuple, KEY *key_info)
154
KeyPartInfo *key_part= key_info->key_part;
155
KeyPartInfo *key_part_end= key_part + key_info->key_parts;
153
KEY_PART_INFO *key_part= key_info->key_part;
154
KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
156
155
for (; key_part != key_part_end; key_part++)
158
157
if (key_part->null_bit && *tuple)
174
173
@param key_length specifies length of all keyparts that will be restored
177
void key_restore(unsigned char *to_record, unsigned char *from_key, KeyInfo *key_info,
176
void key_restore(unsigned char *to_record, unsigned char *from_key, KEY *key_info,
178
177
uint16_t key_length)
181
KeyPartInfo *key_part;
180
KEY_PART_INFO *key_part;
183
182
if (key_length == 0)
203
202
restore the part of a record.
204
203
Maybe this branch is to be removed, but now we
205
204
have to ignore GCov compaining.
207
This may make more sense once we push down block lengths to the engine (aka partial retrieval).
209
206
uint32_t blob_length= uint2korr(from_key);
210
207
Field_blob *field= (Field_blob*) key_part->field;
213
208
from_key+= HA_KEY_BLOB_LENGTH;
214
209
key_length-= HA_KEY_BLOB_LENGTH;
215
field->set_ptr_offset(to_record - field->getTable()->getInsertRecord(),
210
field->set_ptr_offset(to_record - field->table->record[0],
216
211
(ulong) blob_length, from_key);
217
212
length= key_part->length;
219
214
else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
221
216
Field *field= key_part->field;
222
ptrdiff_t ptrdiff= to_record - field->getTable()->getInsertRecord();
225
field->setWriteSet();
217
my_ptrdiff_t ptrdiff= to_record - field->table->record[0];
226
218
field->move_field_offset(ptrdiff);
227
219
key_length-= HA_KEY_BLOB_LENGTH;
228
length= min(key_length, key_part->length);
220
length= cmin(key_length, key_part->length);
229
221
field->set_key_image(from_key, length);
230
222
from_key+= HA_KEY_BLOB_LENGTH;
231
223
field->move_field_offset(-ptrdiff);
235
length= min(key_length, key_part->length);
227
length= cmin(key_length, key_part->length);
236
228
/* skip the byte with 'uneven' bits, if used */
237
229
memcpy(to_record + key_part->offset, from_key + used_uneven_bits
238
230
, (size_t) length - used_uneven_bits);
266
258
bool key_cmp_if_same(Table *table,const unsigned char *key,uint32_t idx,uint32_t key_length)
268
260
uint32_t store_length;
269
KeyPartInfo *key_part;
261
KEY_PART_INFO *key_part;
270
262
const unsigned char *key_end= key + key_length;;
272
264
for (key_part=table->key_info[idx].key_part;
274
266
key_part++, key+= store_length)
296
length= min((uint32_t) (key_end-key), store_length);
297
if (key_part->field->type() == DRIZZLE_TYPE_VARCHAR)
288
length= cmin((uint) (key_end-key), store_length);
289
if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
299
292
const CHARSET_INFO * const cs= key_part->field->charset();
300
293
uint32_t char_length= key_part->length / cs->mbmaxlen;
301
const unsigned char *pos= table->getInsertRecord() + key_part->offset;
294
const unsigned char *pos= table->record[0] + key_part->offset;
302
295
if (length > char_length)
304
297
char_length= my_charpos(cs, pos, pos + length, char_length);
333
void key_unpack(String *to, const Table *table, uint32_t idx)
326
void key_unpack(String *to,Table *table,uint32_t idx)
335
KeyPartInfo *key_part,*key_part_end;
328
KEY_PART_INFO *key_part,*key_part_end;
347
340
if (key_part->null_bit)
349
if (table->getInsertRecord()[key_part->null_offset] & key_part->null_bit)
342
if (table->record[0][key_part->null_offset] & key_part->null_bit)
351
344
to->append(STRING_WITH_LEN("NULL"));
355
if ((field= key_part->field))
348
if ((field=key_part->field))
357
350
const CHARSET_INFO * const cs= field->charset();
359
field->val_str_internal(&tmp);
351
field->val_str(&tmp);
360
352
if (cs->mbmaxlen > 1 &&
361
table->getField(key_part->fieldnr - 1)->field_length !=
353
table->field[key_part->fieldnr - 1]->field_length !=
362
354
key_part->length)
369
361
Align, returning not more than "char_length" characters.
371
363
uint32_t charpos, char_length= key_part->length / cs->mbmaxlen;
372
if ((charpos= my_charpos(cs, tmp.c_ptr(),
373
tmp.c_ptr() + tmp.length(),
364
if ((charpos= my_charpos(cs, tmp.ptr(),
365
tmp.ptr() + tmp.length(),
374
366
char_length)) < key_part->length)
375
367
tmp.length(charpos);
378
370
if (key_part->length < field->pack_length())
379
tmp.length(min(tmp.length(), static_cast<size_t>(key_part->length)));
371
tmp.length(cmin(tmp.length(),(uint32_t)key_part->length));
383
375
to->append(STRING_WITH_LEN("???"));
406
bool is_key_used(Table *table, uint32_t idx, const boost::dynamic_bitset<>& fields)
400
bool is_key_used(Table *table, uint32_t idx, const MY_BITMAP *fields)
408
table->tmp_set.reset();
409
table->mark_columns_used_by_index_no_reset(idx, table->tmp_set);
410
if (table->tmp_set.is_subset_of(fields))
402
bitmap_clear_all(&table->tmp_set);
403
table->mark_columns_used_by_index_no_reset(idx, &table->tmp_set);
404
if (bitmap_is_overlapping(&table->tmp_set, fields))
414
408
If table handler has primary key as part of the index, check that primary
415
409
key is not updated
417
if (idx != table->getShare()->getPrimaryKey() && table->getShare()->hasPrimaryKey() &&
418
(table->cursor->getEngine()->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX)))
420
return is_key_used(table, table->getShare()->getPrimaryKey(), fields);
411
if (idx != table->s->primary_key && table->s->primary_key < MAX_KEY &&
412
(table->file->ha_table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX))
413
return is_key_used(table, table->s->primary_key, fields);
476
} /* namespace drizzled */
469
Compare two records in index order
472
key Index information
473
rec0 Pointer to table->record[0]
474
first_rec Pointer to record compare with
475
second_rec Pointer to record compare against first_rec
478
This method is set-up such that it can be called directly from the
479
priority queue and it is attempted to be optimised as much as possible
480
since this will be called O(N * log N) times while performing a merge
481
sort in various places in the code.
483
We retrieve the pointer to table->record[0] using the fact that key_parts
484
have an offset making it possible to calculate the start of the record.
485
We need to get the diff to the compared record since none of the records
486
being compared are stored in table->record[0].
488
We first check for NULL values, if there are no NULL values we use
489
a compare method that gets two field pointers and a max length
490
and return the result of the comparison.
493
int key_rec_cmp(void *key, unsigned char *first_rec, unsigned char *second_rec)
495
KEY *key_info= (KEY*)key;
496
uint32_t key_parts= key_info->key_parts, i= 0;
497
KEY_PART_INFO *key_part= key_info->key_part;
498
unsigned char *rec0= key_part->field->ptr - key_part->offset;
499
my_ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0;
504
Field *field= key_part->field;
506
if (key_part->null_bit)
508
/* The key_part can contain NULL values */
509
bool first_is_null= field->is_null_in_record_with_offset(first_diff);
510
bool sec_is_null= field->is_null_in_record_with_offset(sec_diff);
512
NULL is smaller then everything so if first is NULL and the other
513
not then we know that we should return -1 and for the opposite
514
we should return +1. If both are NULL then we call it equality
515
although it is a strange form of equality, we have equally little
516
information of the real value.
521
; /* Fall through, no NULL fields */
527
else if (!sec_is_null)
532
goto next_loop; /* Both were NULL */
535
No null values in the fields
536
We use the virtual method cmp_max with a max length parameter.
537
For most field types this translates into a cmp without
538
max length. The exceptions are the BLOB and VARCHAR field types
539
that take the max length into account.
541
result= field->cmp_max(field->ptr+first_diff, field->ptr+sec_diff,
545
} while (!result && ++i < key_parts);