LTP GCOV extension - code coverage report
Current view: directory - storage/maria - ma_key.c
Test: maria-unit-test.html
Date: 2009-03-04 Instrumented lines: 289
Code covered: 45.7 % Executed lines: 132

       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          416896 : {
      98                 :   uchar *start;
      99                 :   uint length;
     100                 :   uchar buff[8];
     101          416896 :   DBUG_ASSERT(trid < (LL(1) << (MARIA_MAX_PACK_TRANSID_SIZE*8)));
     102          416896 :   DBUG_ASSERT(trid >= info->s->state.create_trid);
     103                 : 
     104          416896 :   trid= (trid - info->s->state.create_trid) << 1;
     105                 : 
     106                 :   /* Mark that key contains transid */
     107          416896 :   to[-1]|= 1;
     108                 : 
     109          416896 :   if (trid < MARIA_MIN_TRANSID_PACK_OFFSET)
     110                 :   {
     111          416896 :     to[0]= (uchar) trid;
     112          416896 :     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           75550 : {
     150                 :   ulonglong value;
     151                 :   uint length;
     152                 : 
     153           75550 :   if (from[0] < MARIA_MIN_TRANSID_PACK_OFFSET)
     154           75550 :     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           75550 :   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         2717267 : {
     191                 :   const uchar *pos;
     192                 :   reg1 HA_KEYSEG *keyseg;
     193                 :   my_bool is_ft;
     194         2717267 :   DBUG_ENTER("_ma_make_key");
     195                 : 
     196         2717335 :   int_key->data= key;
     197         2717335 :   int_key->flag= 0;                             /* Always return full key */
     198         2717335 :   int_key->keyinfo= info->s->keyinfo + keynr;
     199                 : 
     200         2717335 :   is_ft= int_key->keyinfo->flag & HA_FULLTEXT;
     201         6011921 :   for (keyseg= int_key->keyinfo->seg ; keyseg->type ;keyseg++)
     202                 :   {
     203         3294709 :     enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
     204         3294709 :     uint length=keyseg->length;
     205                 :     uint char_length;
     206         3294709 :     CHARSET_INFO *cs=keyseg->charset;
     207                 : 
     208         3294709 :     if (keyseg->null_bit)
     209                 :     {
     210           19249 :       if (record[keyseg->null_pos] & keyseg->null_bit)
     211                 :       {
     212            1429 :         *key++= 0;                              /* NULL in key */
     213            1429 :         continue;
     214                 :       }
     215           17820 :       *key++=1;                                 /* Not NULL */
     216                 :     }
     217                 : 
     218         3293280 :     char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
     219                 :                   length);
     220                 : 
     221         3293280 :     pos= record+keyseg->start;
     222         3293280 :     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         3293280 :     if (keyseg->flag & HA_SPACE_PACK)
     236                 :     {
     237          964449 :       if (type != HA_KEYTYPE_NUM)
     238                 :       {
     239          964449 :         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          964321 :       FIX_LENGTH(cs, pos, length, char_length);
     249          964321 :       store_key_length_inc(key,char_length);
     250          964321 :       memcpy(key, pos, (size_t) char_length);
     251          964321 :       key+=char_length;
     252          964321 :       continue;
     253                 :     }
     254         2328831 :     if (keyseg->flag & HA_VAR_LENGTH_PART)
     255                 :     {
     256            2030 :       uint pack_length= (keyseg->bit_start == 1 ? 1 : 2);
     257                 :       uint tmp_length= (pack_length == 1 ? (uint) *pos :
     258            2030 :                         uint2korr(pos));
     259            2030 :       pos+= pack_length;                        /* Skip VARCHAR length */
     260            2030 :       set_if_smaller(length,tmp_length);
     261            2030 :       FIX_LENGTH(cs, pos, length, char_length);
     262            2030 :       store_key_length_inc(key,char_length);
     263            2030 :       memcpy(key,pos,(size_t) char_length);
     264            2030 :       key+= char_length;
     265            2030 :       continue;
     266                 :     }
     267         2326801 :     else if (keyseg->flag & HA_BLOB_PART)
     268                 :     {
     269            7170 :       uint tmp_length= _ma_calc_blob_length(keyseg->bit_start,pos);
     270                 :       uchar *blob_pos;
     271            7170 :       memcpy_fixed(&blob_pos, pos+keyseg->bit_start,sizeof(char*));
     272            7170 :       set_if_smaller(length,tmp_length);
     273            7170 :       FIX_LENGTH(cs, blob_pos, length, char_length);
     274            7170 :       store_key_length_inc(key,char_length);
     275            7170 :       memcpy(key, blob_pos, (size_t) char_length);
     276            7170 :       key+= char_length;
     277            7170 :       continue;
     278                 :     }
     279         2319631 :     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         2319631 :     FIX_LENGTH(cs, pos, length, char_length);
     314         2319631 :     memcpy(key, pos, char_length);
     315         2319631 :     if (length > char_length)
     316               0 :       cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
     317         2319636 :     key+= length;
     318                 :   }
     319         2717212 :   _ma_dpointer(info->s, key, filepos);
     320         2717248 :   int_key->data_length= (key - int_key->data);
     321         2717248 :   int_key->ref_length= info->s->rec_reflength;
     322         2717248 :   int_key->flag= 0;
     323         2717248 :   if (_ma_have_versioning(info) && trid)
     324                 :   {
     325          416896 :     int_key->ref_length+= transid_store_packed(info,
     326                 :                                                key + int_key->ref_length,
     327                 :                                                (TrID) trid);
     328          416896 :     int_key->flag|= SEARCH_USER_KEY_HAS_TRANSID;
     329                 :   }
     330                 : 
     331         2717248 :   DBUG_PRINT("exit",("keynr: %d",keynr));
     332         2717267 :   DBUG_DUMP_KEY("key", int_key);
     333         2717263 :   DBUG_EXECUTE("key", _ma_print_key(DBUG_FILE, int_key););
     334         2717263 :   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           77728 : {
     362                 :   HA_KEYSEG *keyseg;
     363                 :   my_bool is_ft;
     364           77728 :   DBUG_ENTER("_ma_pack_key");
     365                 : 
     366           77728 :   int_key->data= key;
     367           77728 :   int_key->keyinfo= info->s->keyinfo + keynr;
     368                 : 
     369                 :   /* "one part" rtree key is 2*SPDIMS part key in Maria */
     370           77728 :   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           77728 :   DBUG_ASSERT(((keypart_map+1) & keypart_map) == 0);
     375                 : 
     376           77728 :   is_ft= int_key->keyinfo->flag & HA_FULLTEXT;
     377          233346 :   for (keyseg=int_key->keyinfo->seg ; keyseg->type && keypart_map;
     378           77890 :        old+= keyseg->length, keyseg++)
     379                 :   {
     380           77890 :     enum ha_base_keytype type= (enum ha_base_keytype) keyseg->type;
     381           77890 :     uint length= keyseg->length;
     382                 :     uint char_length;
     383                 :     const uchar *pos;
     384           77890 :     CHARSET_INFO *cs=keyseg->charset;
     385                 : 
     386           77890 :     keypart_map>>= 1;
     387           77890 :     if (keyseg->null_bit)
     388                 :     {
     389            2387 :       if (!(*key++= (char) 1-*old++))                   /* Copy null marker */
     390                 :       {
     391             142 :         if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
     392              36 :           old+= 2;
     393                 :         continue;                                       /* Found NULL */
     394                 :       }
     395                 :     }
     396           77748 :     char_length= ((!is_ft && cs && cs->mbmaxlen > 1) ? length/cs->mbmaxlen :
     397                 :                   length);
     398           77748 :     pos= old;
     399           77748 :     if (keyseg->flag & HA_SPACE_PACK)
     400                 :     {
     401           56372 :       const uchar *end= pos + length;
     402           56372 :       if (type == HA_KEYTYPE_NUM)
     403                 :       {
     404               0 :         while (pos < end && pos[0] == ' ')
     405               0 :           pos++;
     406                 :       }
     407           56372 :       else if (type != HA_KEYTYPE_BINARY)
     408                 :       {
     409          363973 :         while (end > pos && end[-1] == ' ')
     410          307601 :           end--;
     411                 :       }
     412           56372 :       length=(uint) (end-pos);
     413           56372 :       FIX_LENGTH(cs, pos, length, char_length);
     414           56372 :       store_key_length_inc(key,char_length);
     415           56372 :       memcpy(key,pos,(size_t) char_length);
     416           56372 :       key+= char_length;
     417           56372 :       continue;
     418                 :     }
     419           21376 :     else if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
     420                 :     {
     421                 :       /* Length of key-part used with maria_rkey() always 2 */
     422            1230 :       uint tmp_length=uint2korr(pos);
     423            1230 :       pos+=2;
     424            1230 :       set_if_smaller(length,tmp_length);        /* Safety */
     425            1230 :       FIX_LENGTH(cs, pos, length, char_length);
     426            1230 :       store_key_length_inc(key,char_length);
     427            1230 :       old+=2;                                   /* Skip length */
     428            1230 :       memcpy(key, pos,(size_t) char_length);
     429            1230 :       key+= char_length;
     430            1230 :       continue;
     431                 :     }
     432           20146 :     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           20146 :     FIX_LENGTH(cs, pos, length, char_length);
     440           20146 :     memcpy(key, pos, char_length);
     441           20146 :     if (length > char_length)
     442               0 :       cs->cset->fill(cs, (char*) key+char_length, length-char_length, ' ');
     443           20146 :     key+= length;
     444                 :   }
     445           77728 :   if (last_used_keyseg)
     446           75966 :     *last_used_keyseg= keyseg;
     447                 : 
     448                 :   /* set flag to SEARCH_PART_KEY if we are not using all key parts */
     449           77728 :   int_key->flag= keyseg->type ? SEARCH_PART_KEY : 0;
     450           77728 :   int_key->ref_length= 0;
     451           77728 :   int_key->data_length= (key - int_key->data);
     452                 : 
     453           77728 :   DBUG_PRINT("exit", ("length: %u", int_key->data_length));
     454           77728 :   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          317197 : {
     464          317197 :   memcpy(to->data, from->data, from->data_length + from->ref_length);
     465          317197 :   to->keyinfo=     from->keyinfo;
     466          317197 :   to->data_length= from->data_length;
     467          317197 :   to->ref_length=  from->ref_length;
     468          317197 :   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                 : }

Generated by: LTP GCOV extension version 1.4