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
#include <drizzled/key.h>
22
21
#include <drizzled/field/blob.h>
23
#include <drizzled/util/test.h>
24
#include <drizzled/plugin/storage_engine.h>
26
#include <boost/dynamic_bitset.hpp>
32
25
using namespace std;
38
28
Search after a key that starts with 'field'
61
51
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,
54
int find_ref_key(KEY *key, uint32_t key_count, unsigned char *record, Field *field,
65
55
uint32_t *key_length, uint32_t *keypart)
58
register KEY *key_info;
71
61
fieldpos= field->offset(record);
126
116
key_part->key_part_flag & HA_VAR_LENGTH_PART)
128
118
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);
119
length= cmin((uint16_t)key_length, key_part->length);
120
key_part->field->get_key_image(to_key, length, Field::itRAW);
131
121
to_key+= HA_KEY_BLOB_LENGTH;
135
length= min((uint16_t)key_length, key_part->length);
125
length= cmin((uint16_t)key_length, key_part->length);
136
126
Field *field= key_part->field;
137
127
const CHARSET_INFO * const cs= field->charset();
138
uint32_t bytes= field->get_key_image(to_key, length);
128
uint32_t bytes= field->get_key_image(to_key, length, Field::itRAW);
139
129
if (bytes < length)
140
130
cs->cset->fill(cs, (char*) to_key + bytes, length - bytes, ' ');
138
void key_copy(basic_string<unsigned char> &to_key,
139
unsigned char *from_record, KEY *key_info,
140
unsigned int key_length)
143
KEY_PART_INFO *key_part;
146
key_length= key_info->key_length;
147
for (key_part= key_info->key_part; (int) key_length > 0; key_part++)
149
if (key_part->null_bit)
151
to_key.push_back(test(from_record[key_part->null_offset] &
152
key_part->null_bit) ? '1' : '0');
155
if (key_part->key_part_flag & HA_BLOB_PART ||
156
key_part->key_part_flag & HA_VAR_LENGTH_PART)
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');
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);
169
to_key.append(length-bytes, ' ');
149
177
Zero the null components of key tuple.
152
void key_zero_nulls(unsigned char *tuple, KeyInfo *key_info)
180
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;
182
KEY_PART_INFO *key_part= key_info->key_part;
183
KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
156
184
for (; key_part != key_part_end; key_part++)
158
186
if (key_part->null_bit && *tuple)
174
202
@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,
205
void key_restore(unsigned char *to_record, unsigned char *from_key, KEY *key_info,
178
206
uint16_t key_length)
181
KeyPartInfo *key_part;
209
KEY_PART_INFO *key_part;
183
211
if (key_length == 0)
203
231
restore the part of a record.
204
232
Maybe this branch is to be removed, but now we
205
233
have to ignore GCov compaining.
207
This may make more sense once we push down block lengths to the engine (aka partial retrieval).
209
235
uint32_t blob_length= uint2korr(from_key);
210
236
Field_blob *field= (Field_blob*) key_part->field;
213
237
from_key+= HA_KEY_BLOB_LENGTH;
214
238
key_length-= HA_KEY_BLOB_LENGTH;
215
field->set_ptr_offset(to_record - field->getTable()->getInsertRecord(),
239
field->set_ptr_offset(to_record - field->table->record[0],
216
240
(ulong) blob_length, from_key);
217
241
length= key_part->length;
219
243
else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
221
245
Field *field= key_part->field;
222
ptrdiff_t ptrdiff= to_record - field->getTable()->getInsertRecord();
225
field->setWriteSet();
246
my_ptrdiff_t ptrdiff= to_record - field->table->record[0];
226
247
field->move_field_offset(ptrdiff);
227
248
key_length-= HA_KEY_BLOB_LENGTH;
228
length= min(key_length, key_part->length);
249
length= cmin(key_length, key_part->length);
229
250
field->set_key_image(from_key, length);
230
251
from_key+= HA_KEY_BLOB_LENGTH;
231
252
field->move_field_offset(-ptrdiff);
235
length= min(key_length, key_part->length);
256
length= cmin(key_length, key_part->length);
236
257
/* skip the byte with 'uneven' bits, if used */
237
258
memcpy(to_record + key_part->offset, from_key + used_uneven_bits
238
259
, (size_t) length - used_uneven_bits);
296
length= min((uint32_t) (key_end-key), store_length);
297
if (key_part->field->type() == DRIZZLE_TYPE_VARCHAR)
317
length= cmin((uint32_t) (key_end-key), store_length);
318
if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
299
321
const CHARSET_INFO * const cs= key_part->field->charset();
300
322
uint32_t char_length= key_part->length / cs->mbmaxlen;
301
const unsigned char *pos= table->getInsertRecord() + key_part->offset;
323
const unsigned char *pos= table->record[0] + key_part->offset;
302
324
if (length > char_length)
304
326
char_length= my_charpos(cs, pos, pos + length, char_length);
333
void key_unpack(String *to, const Table *table, uint32_t idx)
355
void key_unpack(String *to,Table *table,uint32_t idx)
335
KeyPartInfo *key_part,*key_part_end;
357
KEY_PART_INFO *key_part,*key_part_end;
347
369
if (key_part->null_bit)
349
if (table->getInsertRecord()[key_part->null_offset] & key_part->null_bit)
371
if (table->record[0][key_part->null_offset] & key_part->null_bit)
351
373
to->append(STRING_WITH_LEN("NULL"));
355
if ((field= key_part->field))
377
if ((field=key_part->field))
357
379
const CHARSET_INFO * const cs= field->charset();
359
field->val_str_internal(&tmp);
380
field->val_str(&tmp);
360
381
if (cs->mbmaxlen > 1 &&
361
table->getField(key_part->fieldnr - 1)->field_length !=
382
table->field[key_part->fieldnr - 1]->field_length !=
362
383
key_part->length)
406
bool is_key_used(Table *table, uint32_t idx, const boost::dynamic_bitset<>& fields)
429
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))
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))
414
437
If table handler has primary key as part of the index, check that primary
415
438
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);
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);
476
} /* namespace drizzled */
498
Compare two records in index order
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
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.
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].
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.
522
int key_rec_cmp(void *key, unsigned char *first_rec, unsigned char *second_rec)
524
KEY *key_info= (KEY*)key;
525
uint32_t key_parts= key_info->key_parts, i= 0;
526
KEY_PART_INFO *key_part= key_info->key_part;
527
unsigned char *rec0= key_part->field->ptr - key_part->offset;
528
my_ptrdiff_t first_diff= first_rec - rec0, sec_diff= second_rec - rec0;
533
Field *field= key_part->field;
535
if (key_part->null_bit)
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);
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.
550
; /* Fall through, no NULL fields */
556
else if (!sec_is_null)
561
goto next_loop; /* Both were NULL */
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.
570
result= field->cmp_max(field->ptr+first_diff, field->ptr+sec_diff,
574
} while (!result && ++i < key_parts);