1 : /* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
2 :
3 : This program is free software; you can redistribute it and/or modify
4 : it under the terms of the GNU General Public License as published by
5 : the Free Software Foundation; version 2 of the License.
6 :
7 : This program is distributed in the hope that it will be useful,
8 : but WITHOUT ANY WARRANTY; without even the implied warranty of
9 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 : GNU General Public License for more details.
11 :
12 : You should have received a copy of the GNU General Public License
13 : along with this program; if not, write to the Free Software
14 : Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
15 :
16 : /* Functions to handle keys */
17 :
18 : #include "maria_def.h"
19 : #include "m_ctype.h"
20 : #include "ma_sp_defs.h"
21 : #include "ma_blockrec.h" /* For ROW_FLAG_TRANSID */
22 : #include "trnman.h"
23 : #ifdef HAVE_IEEEFP_H
24 : #include <ieeefp.h>
25 : #endif
26 :
27 : #define CHECK_KEYS /* Enable safety checks */
28 :
29 : static int _ma_put_key_in_record(MARIA_HA *info,uint keynr,uchar *record);
30 :
31 : #define FIX_LENGTH(cs, pos, length, char_length) \
32 : do { \
33 : if (length > char_length) \
34 : char_length= (uint) my_charpos(cs, pos, pos+length, char_length); \
35 : set_if_smaller(char_length,length); \
36 : } while(0)
37 :
38 :
39 : /**
40 : Store trid in a packed format as part of a key
41 :
42 : @fn transid_store_packed
43 : @param info Maria handler
44 : @param to End of key to which we should store a packed transid
45 : @param trid Trid to be stored
46 :
47 : @notes
48 :
49 : Keys that have a transid has the lowest bit set for the last byte of the key
50 : This function sets this bit for the key.
51 :
52 : Trid is max 6 bytes long
53 :
54 : First Trid it's converted to a smaller number by using
55 : trid= trid - create_trid.
56 : Then trid is then shifted up one bit so that we can use the
57 : lowest bit as a marker if it's followed by another trid.
58 :
59 : Trid is then stored as follows:
60 :
61 : if trid < 256-12
62 : one byte
63 : else
64 : one byte prefix length_of_trid_in_bytes + 249 followed by data
65 : in high-byte-first order
66 :
67 : Prefix bytes 244 to 249 are reserved for negative transid, that can be used
68 : when we pack transid relative to each other on a key block.
69 :
70 : We have to store transid in high-byte-first order so that we can compare
71 : them unpacked byte per byte and as soon we find a difference we know
72 : which is smaller.
73 :
74 : For example, assuming we the following data:
75 :
76 : key_data: 1 (4 byte integer)
77 : pointer_to_row: 2 << 8 + 3 = 515 (page 2, row 3)
78 : table_create_transid 1000 Defined at create table time and
79 : stored in table definition
80 : transid 1010 Transaction that created row
81 : delete_transid 2011 Transaction that deleted row
82 :
83 : In addition we assume the table is created with a data pointer length
84 : of 4 bytes (this is automatically calculated based on the medium
85 : length of rows and the given max number of rows)
86 :
87 : The binary data for the key would then look like this in hex:
88 :
89 : 00 00 00 01 Key data (1 stored high byte first)
90 : 00 00 00 47 (515 << 1) + 1 ; The last 1 is marker that key cont.
91 : 15 ((1010-1000) << 1) + 1 ; The last 1 is marker that key cont.
92 : FB 07 E6 Length byte (FE = 249 + 2 means 2 bytes) and
93 : ((2011 - 1000) << 1) = 07 E6
94 : */
95 :
96 : uint transid_store_packed(MARIA_HA *info, uchar *to, ulonglong trid)
97 0 : {
98 : uchar *start;
99 : uint length;
100 : uchar buff[8];
101 0 : DBUG_ASSERT(trid < (LL(1) << (MARIA_MAX_PACK_TRANSID_SIZE*8)));
102 0 : DBUG_ASSERT(trid >= info->s->state.create_trid);
103 :
104 0 : trid= (trid - info->s->state.create_trid) << 1;
105 :
106 : /* Mark that key contains transid */
107 0 : to[-1]|= 1;
108 :
109 0 : if (trid < MARIA_MIN_TRANSID_PACK_OFFSET)
110 : {
111 0 : to[0]= (uchar) trid;
112 0 : return 1;
113 : }
114 0 : start= to;
115 :
116 : /* store things in low-byte-first-order in buff */
117 0 : to= buff;
118 : do
119 : {
120 0 : *to++= (uchar) trid;
121 0 : trid= trid>>8;
122 0 : } while (trid);
123 :
124 0 : length= (uint) (to - buff);
125 : /* Store length prefix */
126 0 : start[0]= (uchar) (length + MARIA_TRANSID_PACK_OFFSET);
127 0 : start++;
128 : /* Copy things in high-byte-first order to output buffer */
129 : do
130 : {
131 0 : *start++= *--to;
132 0 : } while (to != buff);
133 0 : return length+1;
134 : }
135 :
136 :
137 : /**
138 : Read packed transid
139 :
140 : @fn transid_get_packed
141 : @param info Maria handler
142 : @param from Transid is stored here
143 :
144 : See transid_store_packed() for how transid is packed
145 :
146 : */
147 :
148 : ulonglong transid_get_packed(MARIA_SHARE *share, const uchar *from)
149 0 : {
150 : ulonglong value;
151 : uint length;
152 :
153 0 : if (from[0] < MARIA_MIN_TRANSID_PACK_OFFSET)
154 0 : value= (ulonglong) from[0];
155 : else
156 : {
157 0 : value= 0;
158 : for (length= (uint) (from[0] - MARIA_TRANSID_PACK_OFFSET),
159 0 : value= (ulonglong) from[1], from+=2;
160 0 : --length ;
161 0 : from++)
162 0 : value= (value << 8) + ((ulonglong) *from);
163 : }
164 0 : return (value >> 1) + share->state.create_trid;
165 : }
166 :
167 :
168 : /*
169 : Make a normal (not spatial or fulltext) intern key from a record
170 :
171 : SYNOPSIS
172 : _ma_make_key()
173 : info MyiSAM handler
174 : int_key Store created key here
175 : keynr key number
176 : key Buffer used to store key data
177 : record Record
178 : filepos Position to record in the data file
179 :
180 : NOTES
181 : This is used to generate keys from the record on insert, update and delete
182 :
183 : RETURN
184 : key
185 : */
186 :
187 : MARIA_KEY *_ma_make_key(MARIA_HA *info, MARIA_KEY *int_key, uint keynr,
188 : uchar *key, const uchar *record,
189 : MARIA_RECORD_POS filepos, ulonglong trid)
190 0 : {
191 : const uchar *pos;
192 : reg1 HA_KEYSEG *keyseg;
193 : my_bool is_ft;
194 0 : DBUG_ENTER("_ma_make_key");
195 :
196 0 : int_key->data= key;
197 0 : int_key->flag= 0; /* Always return full key */
198 0 : int_key->keyinfo= info->s->keyinfo + keynr;
199 :
200 0 : is_ft= int_key->keyinfo->flag & HA_FULLTEXT;
201 0 : for (keyseg= int_key->keyinfo->seg ; keyseg->type ;keyseg++)
202 : {
203 0 : enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
204 0 : uint length=keyseg->length;
205 : uint char_length;
206 0 : CHARSET_INFO *cs=keyseg->charset;
207 :
208 0 : if (keyseg->null_bit)
209 : {
210 0 : if (record[keyseg->null_pos] & keyseg->null_bit)
211 : {
212 0 : *key++= 0; /* NULL in key */
213 0 : continue;
214 : }
215 0 : *key++=1; /* Not NULL */
216 : }
217 :
218 0 : char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
219 : length);
220 :
221 0 : pos= record+keyseg->start;
222 0 : if (type == HA_KEYTYPE_BIT)
223 : {
224 0 : if (keyseg->bit_length)
225 : {
226 0 : uchar bits= get_rec_bits(record + keyseg->bit_pos,
227 : keyseg->bit_start, keyseg->bit_length);
228 0 : *key++= (char) bits;
229 0 : length--;
230 : }
231 0 : memcpy(key, pos, length);
232 0 : key+= length;
233 0 : continue;
234 : }
235 0 : if (keyseg->flag & HA_SPACE_PACK)
236 : {
237 0 : if (type != HA_KEYTYPE_NUM)
238 : {
239 0 : length= (uint) cs->cset->lengthsp(cs, (const char*)pos, length);
240 : }
241 : else
242 : {
243 0 : const uchar *end= pos + length;
244 0 : while (pos < end && pos[0] == ' ')
245 0 : pos++;
246 0 : length= (uint) (end-pos);
247 : }
248 0 : FIX_LENGTH(cs, pos, length, char_length);
249 0 : store_key_length_inc(key,char_length);
250 0 : memcpy(key, pos, (size_t) char_length);
251 0 : key+=char_length;
252 0 : continue;
253 : }
254 0 : if (keyseg->flag & HA_VAR_LENGTH_PART)
255 : {
256 0 : uint pack_length= (keyseg->bit_start == 1 ? 1 : 2);
257 : uint tmp_length= (pack_length == 1 ? (uint) *pos :
258 0 : uint2korr(pos));
259 0 : pos+= pack_length; /* Skip VARCHAR length */
260 0 : set_if_smaller(length,tmp_length);
261 0 : FIX_LENGTH(cs, pos, length, char_length);
262 0 : store_key_length_inc(key,char_length);
263 0 : memcpy(key,pos,(size_t) char_length);
264 0 : key+= char_length;
265 0 : continue;
266 : }
267 0 : else if (keyseg->flag & HA_BLOB_PART)
268 : {
269 0 : uint tmp_length= _ma_calc_blob_length(keyseg->bit_start,pos);
270 : uchar *blob_pos;
271 0 : memcpy_fixed(&blob_pos, pos+keyseg->bit_start,sizeof(char*));
272 0 : set_if_smaller(length,tmp_length);
273 0 : FIX_LENGTH(cs, blob_pos, length, char_length);
274 0 : store_key_length_inc(key,char_length);
275 0 : memcpy(key, blob_pos, (size_t) char_length);
276 0 : key+= char_length;
277 0 : continue;
278 : }
279 0 : else if (keyseg->flag & HA_SWAP_KEY)
280 : { /* Numerical column */
281 : #ifdef HAVE_ISNAN
282 0 : if (type == HA_KEYTYPE_FLOAT)
283 : {
284 : float nr;
285 0 : float4get(nr,pos);
286 0 : if (isnan(nr))
287 : {
288 : /* Replace NAN with zero */
289 0 : bzero(key,length);
290 0 : key+=length;
291 0 : continue;
292 : }
293 : }
294 0 : else if (type == HA_KEYTYPE_DOUBLE)
295 : {
296 : double nr;
297 0 : float8get(nr,pos);
298 0 : if (isnan(nr))
299 : {
300 0 : bzero(key,length);
301 0 : key+=length;
302 0 : continue;
303 : }
304 : }
305 : #endif
306 0 : pos+=length;
307 0 : while (length--)
308 : {
309 0 : *key++ = *--pos;
310 : }
311 : continue;
312 : }
313 0 : FIX_LENGTH(cs, pos, length, char_length);
314 0 : memcpy(key, pos, char_length);
315 0 : if (length > char_length)
316 0 : cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
317 0 : key+= length;
318 : }
319 0 : _ma_dpointer(info->s, key, filepos);
320 0 : int_key->data_length= (key - int_key->data);
321 0 : int_key->ref_length= info->s->rec_reflength;
322 0 : int_key->flag= 0;
323 0 : if (_ma_have_versioning(info) && trid)
324 : {
325 0 : int_key->ref_length+= transid_store_packed(info,
326 : key + int_key->ref_length,
327 : (TrID) trid);
328 0 : int_key->flag|= SEARCH_USER_KEY_HAS_TRANSID;
329 : }
330 :
331 0 : DBUG_PRINT("exit",("keynr: %d",keynr));
332 0 : DBUG_DUMP_KEY("key", int_key);
333 0 : DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, int_key););
334 0 : DBUG_RETURN(int_key);
335 : } /* _ma_make_key */
336 :
337 :
338 : /*
339 : Pack a key to intern format from given format (c_rkey)
340 :
341 : SYNOPSIS
342 : _ma_pack_key()
343 : info MARIA handler
344 : int_key Store key here
345 : keynr key number
346 : key Buffer for key data
347 : old Original not packed key
348 : keypart_map bitmap of used keyparts
349 : last_used_keyseg out parameter. May be NULL
350 :
351 : RETURN
352 : int_key
353 :
354 : last_use_keyseg Store pointer to the keyseg after the last used one
355 : */
356 :
357 : MARIA_KEY *_ma_pack_key(register MARIA_HA *info, MARIA_KEY *int_key,
358 : uint keynr, uchar *key,
359 : const uchar *old, key_part_map keypart_map,
360 : HA_KEYSEG **last_used_keyseg)
361 0 : {
362 : HA_KEYSEG *keyseg;
363 : my_bool is_ft;
364 0 : DBUG_ENTER("_ma_pack_key");
365 :
366 0 : int_key->data= key;
367 0 : int_key->keyinfo= info->s->keyinfo + keynr;
368 :
369 : /* "one part" rtree key is 2*SPDIMS part key in Maria */
370 0 : if (int_key->keyinfo->key_alg == HA_KEY_ALG_RTREE)
371 0 : keypart_map= (((key_part_map)1) << (2*SPDIMS)) - 1;
372 :
373 : /* only key prefixes are supported */
374 0 : DBUG_ASSERT(((keypart_map+1) & keypart_map) == 0);
375 :
376 0 : is_ft= int_key->keyinfo->flag & HA_FULLTEXT;
377 0 : for (keyseg=int_key->keyinfo->seg ; keyseg->type && keypart_map;
378 0 : old+= keyseg->length, keyseg++)
379 : {
380 0 : enum ha_base_keytype type= (enum ha_base_keytype) keyseg->type;
381 0 : uint length= keyseg->length;
382 : uint char_length;
383 : const uchar *pos;
384 0 : CHARSET_INFO *cs=keyseg->charset;
385 :
386 0 : keypart_map>>= 1;
387 0 : if (keyseg->null_bit)
388 : {
389 0 : if (!(*key++= (char) 1-*old++)) /* Copy null marker */
390 : {
391 0 : if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
392 0 : old+= 2;
393 : continue; /* Found NULL */
394 : }
395 : }
396 0 : char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
397 : length);
398 0 : pos= old;
399 0 : if (keyseg->flag & HA_SPACE_PACK)
400 : {
401 0 : const uchar *end= pos + length;
402 0 : if (type == HA_KEYTYPE_NUM)
403 : {
404 0 : while (pos < end && pos[0] == ' ')
405 0 : pos++;
406 : }
407 0 : else if (type != HA_KEYTYPE_BINARY)
408 : {
409 0 : while (end > pos && end[-1] == ' ')
410 0 : end--;
411 : }
412 0 : length=(uint) (end-pos);
413 0 : FIX_LENGTH(cs, pos, length, char_length);
414 0 : store_key_length_inc(key,char_length);
415 0 : memcpy(key,pos,(size_t) char_length);
416 0 : key+= char_length;
417 0 : continue;
418 : }
419 0 : else if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
420 : {
421 : /* Length of key-part used with maria_rkey() always 2 */
422 0 : uint tmp_length=uint2korr(pos);
423 0 : pos+=2;
424 0 : set_if_smaller(length,tmp_length); /* Safety */
425 0 : FIX_LENGTH(cs, pos, length, char_length);
426 0 : store_key_length_inc(key,char_length);
427 0 : old+=2; /* Skip length */
428 0 : memcpy(key, pos,(size_t) char_length);
429 0 : key+= char_length;
430 0 : continue;
431 : }
432 0 : else if (keyseg->flag & HA_SWAP_KEY)
433 : { /* Numerical column */
434 0 : pos+=length;
435 0 : while (length--)
436 0 : *key++ = *--pos;
437 : continue;
438 : }
439 0 : FIX_LENGTH(cs, pos, length, char_length);
440 0 : memcpy(key, pos, char_length);
441 0 : if (length > char_length)
442 0 : cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
443 0 : key+= length;
444 : }
445 0 : if (last_used_keyseg)
446 0 : *last_used_keyseg= keyseg;
447 :
448 : /* set flag to SEARCH_PART_KEY if we are not using all key parts */
449 0 : int_key->flag= keyseg->type ? SEARCH_PART_KEY : 0;
450 0 : int_key->ref_length= 0;
451 0 : int_key->data_length= (key - int_key->data);
452 :
453 0 : DBUG_PRINT("exit", ("length: %u", int_key->data_length));
454 0 : DBUG_RETURN(int_key);
455 : } /* _ma_pack_key */
456 :
457 :
458 : /**
459 : Copy a key
460 : */
461 :
462 : void _ma_copy_key(MARIA_KEY *to, const MARIA_KEY *from)
463 0 : {
464 0 : memcpy(to->data, from->data, from->data_length + from->ref_length);
465 0 : to->keyinfo= from->keyinfo;
466 0 : to->data_length= from->data_length;
467 0 : to->ref_length= from->ref_length;
468 0 : to->flag= from->flag;
469 : }
470 :
471 :
472 : /*
473 : Store found key in record
474 :
475 : SYNOPSIS
476 : _ma_put_key_in_record()
477 : info MARIA handler
478 : keynr Key number that was used
479 : record Store key here
480 :
481 : Last read key is in info->lastkey
482 :
483 : NOTES
484 : Used when only-keyread is wanted
485 :
486 : RETURN
487 : 0 ok
488 : 1 error
489 : */
490 :
491 : static int _ma_put_key_in_record(register MARIA_HA *info, uint keynr,
492 : uchar *record)
493 0 : {
494 : reg2 uchar *key;
495 : uchar *pos,*key_end;
496 : reg1 HA_KEYSEG *keyseg;
497 : uchar *blob_ptr;
498 0 : DBUG_ENTER("_ma_put_key_in_record");
499 :
500 0 : blob_ptr= info->lastkey_buff2; /* Place to put blob parts */
501 0 : key= info->last_key.data; /* Key that was read */
502 0 : key_end= key + info->last_key.data_length;
503 0 : for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->type ;keyseg++)
504 : {
505 0 : if (keyseg->null_bit)
506 : {
507 0 : if (!*key++)
508 : {
509 0 : record[keyseg->null_pos]|= keyseg->null_bit;
510 0 : continue;
511 : }
512 0 : record[keyseg->null_pos]&= ~keyseg->null_bit;
513 : }
514 0 : if (keyseg->type == HA_KEYTYPE_BIT)
515 : {
516 0 : uint length= keyseg->length;
517 :
518 0 : if (keyseg->bit_length)
519 : {
520 0 : uchar bits= *key++;
521 0 : set_rec_bits(bits, record + keyseg->bit_pos, keyseg->bit_start,
522 : keyseg->bit_length);
523 0 : length--;
524 : }
525 : else
526 : {
527 0 : clr_rec_bits(record + keyseg->bit_pos, keyseg->bit_start,
528 : keyseg->bit_length);
529 : }
530 0 : memcpy(record + keyseg->start, key, length);
531 0 : key+= length;
532 0 : continue;
533 : }
534 0 : if (keyseg->flag & HA_SPACE_PACK)
535 : {
536 : uint length;
537 0 : get_key_length(length,key);
538 : #ifdef CHECK_KEYS
539 0 : if (length > keyseg->length || key+length > key_end)
540 : goto err;
541 : #endif
542 0 : pos= record+keyseg->start;
543 0 : if (keyseg->type != (int) HA_KEYTYPE_NUM)
544 : {
545 0 : memcpy(pos,key,(size_t) length);
546 0 : keyseg->charset->cset->fill(keyseg->charset,
547 : (char*) pos + length,
548 : keyseg->length - length,
549 : ' ');
550 : }
551 : else
552 : {
553 0 : bfill(pos,keyseg->length-length,' ');
554 0 : memcpy(pos+keyseg->length-length,key,(size_t) length);
555 : }
556 0 : key+=length;
557 0 : continue;
558 : }
559 :
560 0 : if (keyseg->flag & HA_VAR_LENGTH_PART)
561 : {
562 : uint length;
563 0 : get_key_length(length,key);
564 : #ifdef CHECK_KEYS
565 0 : if (length > keyseg->length || key+length > key_end)
566 : goto err;
567 : #endif
568 : /* Store key length */
569 0 : if (keyseg->bit_start == 1)
570 0 : *(uchar*) (record+keyseg->start)= (uchar) length;
571 : else
572 0 : int2store(record+keyseg->start, length);
573 : /* And key data */
574 0 : memcpy(record+keyseg->start + keyseg->bit_start, key, length);
575 0 : key+= length;
576 : }
577 0 : else if (keyseg->flag & HA_BLOB_PART)
578 : {
579 : uint length;
580 0 : get_key_length(length,key);
581 : #ifdef CHECK_KEYS
582 0 : if (length > keyseg->length || key+length > key_end)
583 : goto err;
584 : #endif
585 0 : memcpy(record+keyseg->start+keyseg->bit_start,
586 : (char*) &blob_ptr,sizeof(char*));
587 0 : memcpy(blob_ptr,key,length);
588 0 : blob_ptr+=length;
589 :
590 : /* The above changed info->lastkey2. Inform maria_rnext_same(). */
591 0 : info->update&= ~HA_STATE_RNEXT_SAME;
592 :
593 0 : _ma_store_blob_length(record+keyseg->start,
594 : (uint) keyseg->bit_start,length);
595 0 : key+=length;
596 : }
597 0 : else if (keyseg->flag & HA_SWAP_KEY)
598 : {
599 0 : uchar *to= record+keyseg->start+keyseg->length;
600 0 : uchar *end= key+keyseg->length;
601 : #ifdef CHECK_KEYS
602 0 : if (end > key_end)
603 0 : goto err;
604 : #endif
605 : do
606 : {
607 0 : *--to= *key++;
608 0 : } while (key != end);
609 : continue;
610 : }
611 : else
612 : {
613 : #ifdef CHECK_KEYS
614 0 : if (key+keyseg->length > key_end)
615 0 : goto err;
616 : #endif
617 0 : memcpy(record+keyseg->start, key, (size_t) keyseg->length);
618 0 : key+= keyseg->length;
619 : }
620 : }
621 0 : DBUG_RETURN(0);
622 :
623 0 : err:
624 0 : DBUG_RETURN(1); /* Crashed row */
625 : } /* _ma_put_key_in_record */
626 :
627 :
628 : /* Here when key reads are used */
629 :
630 : int _ma_read_key_record(MARIA_HA *info, uchar *buf, MARIA_RECORD_POS filepos)
631 0 : {
632 0 : fast_ma_writeinfo(info);
633 0 : if (filepos != HA_OFFSET_ERROR)
634 : {
635 0 : if (info->lastinx >= 0)
636 : { /* Read only key */
637 0 : if (_ma_put_key_in_record(info,(uint) info->lastinx,buf))
638 : {
639 0 : maria_print_error(info->s, HA_ERR_CRASHED);
640 0 : my_errno=HA_ERR_CRASHED;
641 0 : return -1;
642 : }
643 0 : info->update|= HA_STATE_AKTIV; /* We should find a record */
644 0 : return 0;
645 : }
646 0 : my_errno=HA_ERR_WRONG_INDEX;
647 : }
648 0 : return(-1); /* Wrong data to read */
649 : }
650 :
651 :
652 : /*
653 : Retrieve auto_increment info
654 :
655 : SYNOPSIS
656 : retrieve_auto_increment()
657 : key Auto-increment key
658 : key_type Key's type
659 :
660 : NOTE
661 : 'key' should in "record" format, that is, how it is packed in a record
662 : (this matters with HA_SWAP_KEY).
663 :
664 : IMPLEMENTATION
665 : For signed columns we don't retrieve the auto increment value if it's
666 : less than zero.
667 : */
668 :
669 : ulonglong ma_retrieve_auto_increment(const uchar *key, uint8 key_type)
670 0 : {
671 0 : ulonglong value= 0; /* Store unsigned values here */
672 0 : longlong s_value= 0; /* Store signed values here */
673 :
674 0 : switch (key_type) {
675 : case HA_KEYTYPE_INT8:
676 0 : s_value= (longlong) *(const char*)key;
677 0 : break;
678 : case HA_KEYTYPE_BINARY:
679 0 : value=(ulonglong) *key;
680 0 : break;
681 : case HA_KEYTYPE_SHORT_INT:
682 0 : s_value= (longlong) sint2korr(key);
683 0 : break;
684 : case HA_KEYTYPE_USHORT_INT:
685 0 : value=(ulonglong) uint2korr(key);
686 0 : break;
687 : case HA_KEYTYPE_LONG_INT:
688 0 : s_value= (longlong) sint4korr(key);
689 0 : break;
690 : case HA_KEYTYPE_ULONG_INT:
691 0 : value=(ulonglong) uint4korr(key);
692 0 : break;
693 : case HA_KEYTYPE_INT24:
694 0 : s_value= (longlong) sint3korr(key);
695 0 : break;
696 : case HA_KEYTYPE_UINT24:
697 0 : value=(ulonglong) uint3korr(key);
698 0 : break;
699 : case HA_KEYTYPE_FLOAT: /* This shouldn't be used */
700 : {
701 : float f_1;
702 0 : float4get(f_1,key);
703 : /* Ignore negative values */
704 0 : value = (f_1 < (float) 0.0) ? 0 : (ulonglong) f_1;
705 0 : break;
706 : }
707 : case HA_KEYTYPE_DOUBLE: /* This shouldn't be used */
708 : {
709 : double f_1;
710 0 : float8get(f_1,key);
711 : /* Ignore negative values */
712 0 : value = (f_1 < 0.0) ? 0 : (ulonglong) f_1;
713 0 : break;
714 : }
715 : case HA_KEYTYPE_LONGLONG:
716 0 : s_value= sint8korr(key);
717 0 : break;
718 : case HA_KEYTYPE_ULONGLONG:
719 0 : value= uint8korr(key);
720 0 : break;
721 : default:
722 0 : DBUG_ASSERT(0);
723 : value=0; /* Error */
724 : break;
725 : }
726 :
727 : /*
728 : The following code works becasue if s_value < 0 then value is 0
729 : and if s_value == 0 then value will contain either s_value or the
730 : correct value.
731 : */
732 0 : return (s_value > 0) ? (ulonglong) s_value : value;
733 : }
|