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"
25
#include <boost/dynamic_bitset.hpp>
19
#include <drizzled/server_includes.h>
20
#include <drizzled/table.h>
21
#include <drizzled/field/blob.h>
31
25
using namespace std;
37
28
Search after a key that starts with 'field'
60
51
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,
54
int find_ref_key(KEY *key, uint32_t key_count, unsigned char *record, Field *field,
64
55
uint32_t *key_length, uint32_t *keypart)
67
register KeyInfo *key_info;
58
register KEY *key_info;
70
61
fieldpos= field->offset(record);
125
116
key_part->key_part_flag & HA_VAR_LENGTH_PART)
127
118
key_length-= HA_KEY_BLOB_LENGTH;
128
length= min((uint16_t)key_length, key_part->length);
129
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);
130
121
to_key+= HA_KEY_BLOB_LENGTH;
134
length= min((uint16_t)key_length, key_part->length);
125
length= cmin((uint16_t)key_length, key_part->length);
135
126
Field *field= key_part->field;
136
127
const CHARSET_INFO * const cs= field->charset();
137
uint32_t bytes= field->get_key_image(to_key, length);
128
uint32_t bytes= field->get_key_image(to_key, length, Field::itRAW);
138
129
if (bytes < length)
139
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, ' ');
148
177
Zero the null components of key tuple.
151
void key_zero_nulls(unsigned char *tuple, KeyInfo *key_info)
180
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;
182
KEY_PART_INFO *key_part= key_info->key_part;
183
KEY_PART_INFO *key_part_end= key_part + key_info->key_parts;
155
184
for (; key_part != key_part_end; key_part++)
157
186
if (key_part->null_bit && *tuple)
173
202
@param key_length specifies length of all keyparts that will be restored
176
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,
177
206
uint16_t key_length)
180
KeyPartInfo *key_part;
209
KEY_PART_INFO *key_part;
182
211
if (key_length == 0)
202
231
restore the part of a record.
203
232
Maybe this branch is to be removed, but now we
204
233
have to ignore GCov compaining.
206
This may make more sense once we push down block lengths to the engine (aka partial retrieval).
208
235
uint32_t blob_length= uint2korr(from_key);
209
236
Field_blob *field= (Field_blob*) key_part->field;
212
237
from_key+= HA_KEY_BLOB_LENGTH;
213
238
key_length-= HA_KEY_BLOB_LENGTH;
214
field->set_ptr_offset(to_record - field->getTable()->getInsertRecord(),
239
field->set_ptr_offset(to_record - field->table->record[0],
215
240
(ulong) blob_length, from_key);
216
241
length= key_part->length;
218
243
else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
220
245
Field *field= key_part->field;
221
ptrdiff_t ptrdiff= to_record - field->getTable()->getInsertRecord();
224
field->setWriteSet();
246
my_ptrdiff_t ptrdiff= to_record - field->table->record[0];
225
247
field->move_field_offset(ptrdiff);
226
248
key_length-= HA_KEY_BLOB_LENGTH;
227
length= min(key_length, key_part->length);
249
length= cmin(key_length, key_part->length);
228
250
field->set_key_image(from_key, length);
229
251
from_key+= HA_KEY_BLOB_LENGTH;
230
252
field->move_field_offset(-ptrdiff);
234
length= min(key_length, key_part->length);
256
length= cmin(key_length, key_part->length);
235
257
/* skip the byte with 'uneven' bits, if used */
236
258
memcpy(to_record + key_part->offset, from_key + used_uneven_bits
237
259
, (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)
317
length= cmin((uint32_t) (key_end-key), store_length);
318
if (!(key_part->key_type & (FIELDFLAG_NUMBER+FIELDFLAG_BINARY+
298
321
const CHARSET_INFO * const cs= key_part->field->charset();
299
322
uint32_t char_length= key_part->length / cs->mbmaxlen;
300
const unsigned char *pos= table->getInsertRecord() + key_part->offset;
323
const unsigned char *pos= table->record[0] + key_part->offset;
301
324
if (length > char_length)
303
326
char_length= my_charpos(cs, pos, pos + length, char_length);
332
void key_unpack(String *to, Table *table, uint32_t idx)
355
void key_unpack(String *to,Table *table,uint32_t idx)
334
KeyPartInfo *key_part,*key_part_end;
357
KEY_PART_INFO *key_part,*key_part_end;
346
369
if (key_part->null_bit)
348
if (table->getInsertRecord()[key_part->null_offset] & key_part->null_bit)
371
if (table->record[0][key_part->null_offset] & key_part->null_bit)
350
373
to->append(STRING_WITH_LEN("NULL"));
354
if ((field= key_part->field))
377
if ((field=key_part->field))
356
379
const CHARSET_INFO * const cs= field->charset();
358
field->val_str_internal(&tmp);
380
field->val_str(&tmp);
359
381
if (cs->mbmaxlen > 1 &&
360
table->getField(key_part->fieldnr - 1)->field_length !=
382
table->field[key_part->fieldnr - 1]->field_length !=
361
383
key_part->length)
405
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)
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))
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))
413
437
If table handler has primary key as part of the index, check that primary
414
438
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);
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);
475
} /* 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);