00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018 #include "myisam_priv.h"
00019 #include <drizzled/charset_info.h>
00020 #ifdef HAVE_IEEEFP_H
00021 #include <ieeefp.h>
00022 #endif
00023 #include <math.h>
00024 #include <cassert>
00025
00026 using namespace drizzled;
00027 using namespace std;
00028
00029 #define CHECK_KEYS
00030
00031 #define FIX_LENGTH(cs, pos, length, char_length) \
00032 do { \
00033 if (length > char_length) \
00034 char_length= my_charpos(cs, pos, pos+length, char_length); \
00035 drizzled::set_if_smaller(char_length,length); \
00036 } while(0)
00037
00038 static int _mi_put_key_in_record(MI_INFO *info,uint32_t keynr,unsigned char *record);
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055 uint32_t _mi_make_key(register MI_INFO *info, uint32_t keynr, unsigned char *key,
00056 const unsigned char *record, drizzled::internal::my_off_t filepos)
00057 {
00058 unsigned char *pos;
00059 unsigned char *start;
00060 register HA_KEYSEG *keyseg;
00061
00062 start=key;
00063 for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
00064 {
00065 enum drizzled::ha_base_keytype type=(enum drizzled::ha_base_keytype) keyseg->type;
00066 uint32_t length=keyseg->length;
00067 uint32_t char_length;
00068 const drizzled::CHARSET_INFO * const cs=keyseg->charset;
00069
00070 if (keyseg->null_bit)
00071 {
00072 if (record[keyseg->null_pos] & keyseg->null_bit)
00073 {
00074 *key++= 0;
00075 continue;
00076 }
00077 *key++=1;
00078 }
00079
00080 char_length= ((cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
00081 length);
00082
00083 pos= (unsigned char*) record+keyseg->start;
00084
00085 if (keyseg->flag & HA_SPACE_PACK)
00086 {
00087 length= cs->cset->lengthsp(cs, (char*) pos, length);
00088
00089 FIX_LENGTH(cs, pos, length, char_length);
00090 store_key_length_inc(key,char_length);
00091 memcpy(key, pos, char_length);
00092 key+=char_length;
00093 continue;
00094 }
00095 if (keyseg->flag & HA_VAR_LENGTH_PART)
00096 {
00097 uint32_t pack_length= (keyseg->bit_start == 1 ? 1 : 2);
00098 uint32_t tmp_length= (pack_length == 1 ? (uint) *(unsigned char*) pos :
00099 uint2korr(pos));
00100 pos+= pack_length;
00101 drizzled::set_if_smaller(length,tmp_length);
00102 FIX_LENGTH(cs, pos, length, char_length);
00103 store_key_length_inc(key,char_length);
00104 memcpy(key, pos, char_length);
00105 key+= char_length;
00106 continue;
00107 }
00108 else if (keyseg->flag & HA_BLOB_PART)
00109 {
00110 uint32_t tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
00111 memcpy(&pos, pos+keyseg->bit_start, sizeof(char*));
00112 drizzled::set_if_smaller(length,tmp_length);
00113 FIX_LENGTH(cs, pos, length, char_length);
00114 store_key_length_inc(key,char_length);
00115 memcpy(key, pos, char_length);
00116 key+= char_length;
00117 continue;
00118 }
00119 else if (keyseg->flag & HA_SWAP_KEY)
00120 {
00121 if (type == drizzled::HA_KEYTYPE_DOUBLE)
00122 {
00123 double nr;
00124 float8get(nr,pos);
00125 if (isnan(nr))
00126 {
00127 memset(key, 0, length);
00128 key+=length;
00129 continue;
00130 }
00131 }
00132 pos+=length;
00133 while (length--)
00134 {
00135 *key++ = *--pos;
00136 }
00137 continue;
00138 }
00139 FIX_LENGTH(cs, pos, length, char_length);
00140 memcpy(key, pos, char_length);
00141 if (length > char_length)
00142 cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
00143 key+= length;
00144 }
00145 _mi_dpointer(info,key,filepos);
00146 return((uint) (key-start));
00147 }
00148
00149
00150
00151
00152
00153
00154
00155
00156
00157
00158
00159
00160
00161
00162
00163
00164
00165
00166
00167
00168 uint32_t _mi_pack_key(register MI_INFO *info, uint32_t keynr, unsigned char *key, unsigned char *old,
00169 drizzled::key_part_map keypart_map, HA_KEYSEG **last_used_keyseg)
00170 {
00171 unsigned char *start_key=key;
00172 HA_KEYSEG *keyseg;
00173
00174
00175 assert(((keypart_map+1) & keypart_map) == 0);
00176
00177 for (keyseg= info->s->keyinfo[keynr].seg ; keyseg->type && keypart_map;
00178 old+= keyseg->length, keyseg++)
00179 {
00180 enum drizzled::ha_base_keytype type= (enum drizzled::ha_base_keytype) keyseg->type;
00181 uint32_t length= keyseg->length;
00182 uint32_t char_length;
00183 unsigned char *pos;
00184 const drizzled::CHARSET_INFO * const cs=keyseg->charset;
00185 keypart_map>>= 1;
00186 if (keyseg->null_bit)
00187 {
00188 if (!(*key++= (char) 1-*old++))
00189 {
00190 if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
00191 old+= 2;
00192 continue;
00193 }
00194 }
00195 char_length= (cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen : length;
00196 pos=old;
00197 if (keyseg->flag & HA_SPACE_PACK)
00198 {
00199 unsigned char *end=pos+length;
00200
00201 if (type != drizzled::HA_KEYTYPE_BINARY)
00202 {
00203 while (end > pos && end[-1] == ' ')
00204 end--;
00205 }
00206 length=(uint) (end-pos);
00207 FIX_LENGTH(cs, pos, length, char_length);
00208 store_key_length_inc(key,char_length);
00209 memcpy(key, pos, char_length);
00210 key+= char_length;
00211 continue;
00212 }
00213 else if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
00214 {
00215
00216 uint32_t tmp_length=uint2korr(pos);
00217 pos+=2;
00218 drizzled::set_if_smaller(length,tmp_length);
00219 FIX_LENGTH(cs, pos, length, char_length);
00220 store_key_length_inc(key,char_length);
00221 old+=2;
00222 memcpy(key, pos, char_length);
00223 key+= char_length;
00224 continue;
00225 }
00226 else if (keyseg->flag & HA_SWAP_KEY)
00227 {
00228 pos+=length;
00229 while (length--)
00230 *key++ = *--pos;
00231 continue;
00232 }
00233 FIX_LENGTH(cs, pos, length, char_length);
00234 memcpy(key, pos, char_length);
00235 if (length > char_length)
00236 cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
00237 key+= length;
00238 }
00239 if (last_used_keyseg)
00240 *last_used_keyseg= keyseg;
00241
00242 return((uint) (key-start_key));
00243 }
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254
00255
00256
00257
00258
00259
00260
00261
00262
00263
00264
00265
00266 static int _mi_put_key_in_record(register MI_INFO *info, uint32_t keynr,
00267 unsigned char *record)
00268 {
00269 register unsigned char *key;
00270 unsigned char *pos,*key_end;
00271 register HA_KEYSEG *keyseg;
00272 unsigned char *blob_ptr;
00273
00274 blob_ptr= (unsigned char*) info->lastkey2;
00275 key=(unsigned char*) info->lastkey;
00276 key_end=key+info->lastkey_length;
00277 for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
00278 {
00279 if (keyseg->null_bit)
00280 {
00281 if (!*key++)
00282 {
00283 record[keyseg->null_pos]|= keyseg->null_bit;
00284 continue;
00285 }
00286 record[keyseg->null_pos]&= ~keyseg->null_bit;
00287 }
00288
00289 if (keyseg->flag & HA_SPACE_PACK)
00290 {
00291 uint32_t length;
00292 get_key_length(length,key);
00293 #ifdef CHECK_KEYS
00294 if (length > keyseg->length || key+length > key_end)
00295 goto err;
00296 #endif
00297 pos= record+keyseg->start;
00298
00299 memcpy(pos, key, length);
00300 keyseg->charset->cset->fill(keyseg->charset,
00301 (char*) pos + length,
00302 keyseg->length - length,
00303 ' ');
00304 key+=length;
00305 continue;
00306 }
00307
00308 if (keyseg->flag & HA_VAR_LENGTH_PART)
00309 {
00310 uint32_t length;
00311 get_key_length(length,key);
00312 #ifdef CHECK_KEYS
00313 if (length > keyseg->length || key+length > key_end)
00314 goto err;
00315 #endif
00316
00317 if (keyseg->bit_start == 1)
00318 *(unsigned char*) (record+keyseg->start)= (unsigned char) length;
00319 else
00320 int2store(record+keyseg->start, length);
00321
00322 memcpy(record+keyseg->start + keyseg->bit_start, key, length);
00323 key+= length;
00324 }
00325 else if (keyseg->flag & HA_BLOB_PART)
00326 {
00327 uint32_t length;
00328 get_key_length(length,key);
00329 #ifdef CHECK_KEYS
00330 if (length > keyseg->length || key+length > key_end)
00331 goto err;
00332 #endif
00333 memcpy(record+keyseg->start+keyseg->bit_start,
00334 &blob_ptr,sizeof(char*));
00335 memcpy(blob_ptr,key,length);
00336 blob_ptr+=length;
00337
00338
00339 info->update&= ~HA_STATE_RNEXT_SAME;
00340
00341 _my_store_blob_length(record+keyseg->start,
00342 (uint) keyseg->bit_start,length);
00343 key+=length;
00344 }
00345 else if (keyseg->flag & HA_SWAP_KEY)
00346 {
00347 unsigned char *to= record+keyseg->start+keyseg->length;
00348 unsigned char *end= key+keyseg->length;
00349 #ifdef CHECK_KEYS
00350 if (end > key_end)
00351 goto err;
00352 #endif
00353 do
00354 {
00355 *--to= *key++;
00356 } while (key != end);
00357 continue;
00358 }
00359 else
00360 {
00361 #ifdef CHECK_KEYS
00362 if (key+keyseg->length > key_end)
00363 goto err;
00364 #endif
00365 memcpy(record+keyseg->start, key, keyseg->length);
00366 key+= keyseg->length;
00367 }
00368 }
00369 return(0);
00370
00371 err:
00372 return(1);
00373 }
00374
00375
00376
00377
00378 int _mi_read_key_record(MI_INFO *info, drizzled::internal::my_off_t filepos, unsigned char *buf)
00379 {
00380 fast_mi_writeinfo(info);
00381 if (filepos != HA_OFFSET_ERROR)
00382 {
00383 if (info->lastinx >= 0)
00384 {
00385 if (_mi_put_key_in_record(info,(uint) info->lastinx,buf))
00386 {
00387 mi_print_error(info->s, HA_ERR_CRASHED);
00388 errno=HA_ERR_CRASHED;
00389 return -1;
00390 }
00391 info->update|= HA_STATE_AKTIV;
00392 return 0;
00393 }
00394 errno=HA_ERR_WRONG_INDEX;
00395 }
00396 return(-1);
00397 }
00398
00399
00400
00401
00402
00403
00404
00405
00406
00407
00408
00409
00410
00411
00412
00413
00414
00415
00416
00417 int mi_check_index_cond(register MI_INFO *info, uint32_t keynr, unsigned char *record)
00418 {
00419 if (_mi_put_key_in_record(info, keynr, record))
00420 {
00421 mi_print_error(info->s, HA_ERR_CRASHED);
00422 errno=HA_ERR_CRASHED;
00423 return -1;
00424 }
00425 return info->index_cond_func(info->index_cond_func_arg);
00426 }
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442 uint64_t retrieve_auto_increment(MI_INFO *info,const unsigned char *record)
00443 {
00444 uint64_t value= 0;
00445 int64_t s_value= 0;
00446 HA_KEYSEG *keyseg= info->s->keyinfo[info->s->base.auto_key-1].seg;
00447 const unsigned char *key= (unsigned char*) record + keyseg->start;
00448
00449 switch (keyseg->type) {
00450 case drizzled::HA_KEYTYPE_BINARY:
00451 value=(uint64_t) *(unsigned char*) key;
00452 break;
00453 case drizzled::HA_KEYTYPE_LONG_INT:
00454 s_value= (int64_t) sint4korr(key);
00455 break;
00456 case drizzled::HA_KEYTYPE_ULONG_INT:
00457 value=(uint64_t) uint4korr(key);
00458 break;
00459 case drizzled::HA_KEYTYPE_DOUBLE:
00460 {
00461 double f_1;
00462 float8get(f_1,key);
00463
00464 value = (f_1 < 0.0) ? 0 : (uint64_t) f_1;
00465 break;
00466 }
00467 case drizzled::HA_KEYTYPE_LONGLONG:
00468 s_value= sint8korr(key);
00469 break;
00470 case drizzled::HA_KEYTYPE_ULONGLONG:
00471 value= uint8korr(key);
00472 break;
00473 default:
00474 assert(0);
00475 value=0;
00476 break;
00477 }
00478
00479
00480
00481
00482
00483
00484 return (s_value > 0) ? (uint64_t) s_value : value;
00485 }