00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019 #include <config.h>
00020 #include <drizzled/table.h>
00021 #include <drizzled/key.h>
00022 #include <drizzled/field/blob.h>
00023 #include <drizzled/util/test.h>
00024 #include <drizzled/plugin/storage_engine.h>
00025
00026 #include <boost/dynamic_bitset.hpp>
00027
00028 #include <string>
00029
00030 #include <algorithm>
00031
00032 using namespace std;
00033
00034 namespace drizzled
00035 {
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064 int find_ref_key(KeyInfo *key, uint32_t key_count, unsigned char *record, Field *field,
00065 uint32_t *key_length, uint32_t *keypart)
00066 {
00067 int i;
00068 KeyInfo *key_info;
00069 uint32_t fieldpos;
00070
00071 fieldpos= field->offset(record);
00072
00073
00074 for (i= 0, key_info= key ;
00075 i < (int) key_count ;
00076 i++, key_info++)
00077 {
00078 if (key_info->key_part[0].offset == fieldpos)
00079 {
00080 *key_length= *keypart= 0;
00081 return i;
00082 }
00083 }
00084
00085
00086 for (i= 0, key_info= key;
00087 i < (int) key_count ;
00088 i++, key_info++)
00089 {
00090 uint32_t j;
00091 KeyPartInfo *key_part;
00092 *key_length=0;
00093 for (j=0, key_part=key_info->key_part ;
00094 j < key_info->key_parts ;
00095 j++, key_part++)
00096 {
00097 if (key_part->offset == fieldpos)
00098 {
00099 *keypart= j;
00100 return i;
00101 }
00102 *key_length+= key_part->store_length;
00103 }
00104 }
00105 return(-1);
00106 }
00107
00108
00109 void key_copy(unsigned char *to_key, unsigned char *from_record, KeyInfo *key_info,
00110 unsigned int key_length)
00111 {
00112 uint32_t length;
00113 KeyPartInfo *key_part;
00114
00115 if (key_length == 0)
00116 key_length= key_info->key_length;
00117 for (key_part= key_info->key_part; (int) key_length > 0; key_part++)
00118 {
00119 if (key_part->null_bit)
00120 {
00121 *to_key++= test(from_record[key_part->null_offset] &
00122 key_part->null_bit);
00123 key_length--;
00124 }
00125 if (key_part->key_part_flag & HA_BLOB_PART ||
00126 key_part->key_part_flag & HA_VAR_LENGTH_PART)
00127 {
00128 key_length-= HA_KEY_BLOB_LENGTH;
00129 length= min((uint16_t)key_length, key_part->length);
00130 key_part->field->get_key_image(to_key, length);
00131 to_key+= HA_KEY_BLOB_LENGTH;
00132 }
00133 else
00134 {
00135 length= min((uint16_t)key_length, key_part->length);
00136 Field *field= key_part->field;
00137 const CHARSET_INFO * const cs= field->charset();
00138 uint32_t bytes= field->get_key_image(to_key, length);
00139 if (bytes < length)
00140 cs->cset->fill(cs, (char*) to_key + bytes, length - bytes, ' ');
00141 }
00142 to_key+= length;
00143 key_length-= length;
00144 }
00145 }
00146
00147
00152 void key_zero_nulls(unsigned char *tuple, KeyInfo *key_info)
00153 {
00154 KeyPartInfo *key_part= key_info->key_part;
00155 KeyPartInfo *key_part_end= key_part + key_info->key_parts;
00156 for (; key_part != key_part_end; key_part++)
00157 {
00158 if (key_part->null_bit && *tuple)
00159 memset(tuple+1, 0, key_part->store_length-1);
00160 tuple+= key_part->store_length;
00161 }
00162 }
00163
00164
00165
00166
00167
00168
00169
00170
00171
00172
00173
00174
00175
00176
00177 void key_restore(unsigned char *to_record, unsigned char *from_key, KeyInfo *key_info,
00178 uint16_t key_length)
00179 {
00180 uint32_t length;
00181 KeyPartInfo *key_part;
00182
00183 if (key_length == 0)
00184 {
00185 key_length= key_info->key_length;
00186 }
00187 for (key_part= key_info->key_part ; (int) key_length > 0 ; key_part++)
00188 {
00189 unsigned char used_uneven_bits= 0;
00190 if (key_part->null_bit)
00191 {
00192 if (*from_key++)
00193 to_record[key_part->null_offset]|= key_part->null_bit;
00194 else
00195 to_record[key_part->null_offset]&= ~key_part->null_bit;
00196 key_length--;
00197 }
00198 if (key_part->key_part_flag & HA_BLOB_PART)
00199 {
00200
00201
00202
00203
00204
00205
00206
00207
00208
00209 uint32_t blob_length= uint2korr(from_key);
00210 Field_blob *field= (Field_blob*) key_part->field;
00211
00212 field->setReadSet();
00213 from_key+= HA_KEY_BLOB_LENGTH;
00214 key_length-= HA_KEY_BLOB_LENGTH;
00215 field->set_ptr_offset(to_record - field->getTable()->getInsertRecord(),
00216 (ulong) blob_length, from_key);
00217 length= key_part->length;
00218 }
00219 else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
00220 {
00221 Field *field= key_part->field;
00222 ptrdiff_t ptrdiff= to_record - field->getTable()->getInsertRecord();
00223
00224 field->setReadSet();
00225 field->setWriteSet();
00226 field->move_field_offset(ptrdiff);
00227 key_length-= HA_KEY_BLOB_LENGTH;
00228 length= min(key_length, key_part->length);
00229 field->set_key_image(from_key, length);
00230 from_key+= HA_KEY_BLOB_LENGTH;
00231 field->move_field_offset(-ptrdiff);
00232 }
00233 else
00234 {
00235 length= min(key_length, key_part->length);
00236
00237 memcpy(to_record + key_part->offset, from_key + used_uneven_bits
00238 , (size_t) length - used_uneven_bits);
00239 }
00240 from_key+= length;
00241 key_length-= length;
00242 }
00243 }
00244
00245
00266 bool key_cmp_if_same(Table *table,const unsigned char *key,uint32_t idx,uint32_t key_length)
00267 {
00268 uint32_t store_length;
00269 KeyPartInfo *key_part;
00270 const unsigned char *key_end= key + key_length;;
00271
00272 for (key_part=table->key_info[idx].key_part;
00273 key < key_end ;
00274 key_part++, key+= store_length)
00275 {
00276 uint32_t length;
00277 store_length= key_part->store_length;
00278
00279 if (key_part->null_bit)
00280 {
00281 if (*key != test(table->getInsertRecord()[key_part->null_offset] &
00282 key_part->null_bit))
00283 return 1;
00284 if (*key)
00285 continue;
00286 key++;
00287 store_length--;
00288 }
00289 if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART |
00290 HA_BIT_PART))
00291 {
00292 if (key_part->field->key_cmp(key, key_part->length))
00293 return 1;
00294 continue;
00295 }
00296 length= min((uint32_t) (key_end-key), store_length);
00297 if (key_part->field->type() == DRIZZLE_TYPE_VARCHAR)
00298 {
00299 const CHARSET_INFO * const cs= key_part->field->charset();
00300 uint32_t char_length= key_part->length / cs->mbmaxlen;
00301 const unsigned char *pos= table->getInsertRecord() + key_part->offset;
00302 if (length > char_length)
00303 {
00304 char_length= my_charpos(cs, pos, pos + length, char_length);
00305 set_if_smaller(char_length, length);
00306 }
00307 if (cs->coll->strnncollsp(cs,
00308 (const unsigned char*) key, length,
00309 (const unsigned char*) pos, char_length, 0))
00310 return 1;
00311 continue;
00312 }
00313 if (memcmp(key,table->getInsertRecord()+key_part->offset,length))
00314 return 1;
00315 }
00316 return 0;
00317 }
00318
00319
00320
00321
00322
00323
00324
00325
00326
00327
00328
00329
00330
00331
00332
00333 void key_unpack(String *to, const Table *table, uint32_t idx)
00334 {
00335 KeyPartInfo *key_part,*key_part_end;
00336 Field *field;
00337 String tmp;
00338
00339 to->length(0);
00340 for (key_part=table->key_info[idx].key_part,key_part_end=key_part+
00341 table->key_info[idx].key_parts ;
00342 key_part < key_part_end;
00343 key_part++)
00344 {
00345 if (to->length())
00346 to->append('-');
00347 if (key_part->null_bit)
00348 {
00349 if (table->getInsertRecord()[key_part->null_offset] & key_part->null_bit)
00350 {
00351 to->append(STRING_WITH_LEN("NULL"));
00352 continue;
00353 }
00354 }
00355 if ((field= key_part->field))
00356 {
00357 const CHARSET_INFO * const cs= field->charset();
00358 field->setReadSet();
00359 field->val_str_internal(&tmp);
00360 if (cs->mbmaxlen > 1 &&
00361 table->getField(key_part->fieldnr - 1)->field_length !=
00362 key_part->length)
00363 {
00364
00365
00366
00367
00368
00369
00370
00371 uint32_t charpos, char_length= key_part->length / cs->mbmaxlen;
00372 if ((charpos= my_charpos(cs, tmp.c_ptr(),
00373 tmp.c_ptr() + tmp.length(),
00374 char_length)) < key_part->length)
00375 tmp.length(charpos);
00376 }
00377
00378 if (key_part->length < field->pack_length())
00379 tmp.length(min(tmp.length(), static_cast<size_t>(key_part->length)));
00380 to->append(tmp);
00381 }
00382 else
00383 to->append(STRING_WITH_LEN("???"));
00384 }
00385 }
00386
00387
00388
00389
00390
00391
00392
00393
00394
00395
00396
00397
00398
00399
00400
00401
00402
00403
00404
00405
00406 bool is_key_used(Table *table, uint32_t idx, const boost::dynamic_bitset<>& fields)
00407 {
00408 table->tmp_set.reset();
00409 table->mark_columns_used_by_index_no_reset(idx, table->tmp_set);
00410 if (table->tmp_set.is_subset_of(fields))
00411 return 1;
00412
00413
00414
00415
00416
00417 if (idx != table->getShare()->getPrimaryKey() && table->getShare()->hasPrimaryKey() &&
00418 (table->cursor->getEngine()->check_flag(HTON_BIT_PRIMARY_KEY_IN_READ_INDEX)))
00419 {
00420 return is_key_used(table, table->getShare()->getPrimaryKey(), fields);
00421 }
00422 return 0;
00423 }
00424
00425
00440 int key_cmp(KeyPartInfo *key_part, const unsigned char *key, uint32_t key_length)
00441 {
00442 uint32_t store_length;
00443
00444 for (const unsigned char *end=key + key_length;
00445 key < end;
00446 key+= store_length, key_part++)
00447 {
00448 int cmp;
00449 store_length= key_part->store_length;
00450 if (key_part->null_bit)
00451 {
00452
00453 bool field_is_null= key_part->field->is_null();
00454 if (*key)
00455 {
00456
00457 if (!field_is_null)
00458 return 1;
00459
00460 continue;
00461 }
00462 else if (field_is_null)
00463 return -1;
00464 key++;
00465 store_length--;
00466 }
00467 if ((cmp=key_part->field->key_cmp(key, key_part->length)) < 0)
00468 return -1;
00469 if (cmp > 0)
00470 return 1;
00471 }
00472 return 0;
00473 }
00474
00475
00476 }