LTP GCOV extension - code coverage report
Current view: directory - storage/maria - ma_unique.c
Test: maria-mtr.html
Date: 2009-03-04 Instrumented lines: 96
Code covered: 0.0 % Executed lines: 0

       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 check if a row is unique */
      17                 : 
      18                 : #include "maria_def.h"
      19                 : #include <m_ctype.h>
      20                 : 
      21                 : /**
      22                 :   Check if there exist a row with the same hash
      23                 : 
      24                 :   @notes
      25                 :   This function is not versioning safe. For the moment this is not a problem
      26                 :   as it's only used for internal temporary tables in MySQL for which there
      27                 :   isn't any versioning information.
      28                 : */
      29                 : 
      30                 : my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, uchar *record,
      31                 :                         ha_checksum unique_hash, my_off_t disk_pos)
      32               0 : {
      33               0 :   my_off_t lastpos=info->cur_row.lastpos;
      34               0 :   MARIA_KEYDEF *keyinfo= &info->s->keyinfo[def->key];
      35               0 :   uchar *key_buff= info->lastkey_buff2;
      36                 :   MARIA_KEY key;
      37               0 :   DBUG_ENTER("_ma_check_unique");
      38               0 :   DBUG_PRINT("enter",("unique_hash: %lu", (ulong) unique_hash));
      39                 : 
      40               0 :   maria_unique_store(record+keyinfo->seg->start, unique_hash);
      41                 :   /* Can't be spatial so it's ok to call _ma_make_key directly here */
      42               0 :   _ma_make_key(info, &key, def->key, key_buff, record, 0, 0);
      43                 : 
      44                 :   /* The above changed info->lastkey_buff2. Inform maria_rnext_same(). */
      45               0 :   info->update&= ~HA_STATE_RNEXT_SAME;
      46                 : 
      47               0 :   DBUG_ASSERT(key.data_length == MARIA_UNIQUE_HASH_LENGTH);
      48               0 :   if (_ma_search(info, &key, SEARCH_FIND, info->s->state.key_root[def->key]))
      49                 :   {
      50               0 :     info->page_changed=1;                    /* Can't optimize read next */
      51               0 :     info->cur_row.lastpos= lastpos;
      52               0 :     DBUG_RETURN(0);                             /* No matching rows */
      53                 :   }
      54                 : 
      55                 :   for (;;)
      56                 :   {
      57               0 :     if (info->cur_row.lastpos != disk_pos &&
      58                 :         !(*info->s->compare_unique)(info,def,record,info->cur_row.lastpos))
      59                 :     {
      60               0 :       my_errno=HA_ERR_FOUND_DUPP_UNIQUE;
      61               0 :       info->errkey= (int) def->key;
      62               0 :       info->dup_key_pos= info->cur_row.lastpos;
      63               0 :       info->page_changed= 1;                 /* Can't optimize read next */
      64               0 :       info->cur_row.lastpos= lastpos;
      65               0 :       DBUG_PRINT("info",("Found duplicate"));
      66               0 :       DBUG_RETURN(1);                           /* Found identical  */
      67                 :     }
      68               0 :     DBUG_ASSERT(info->last_key.data_length == MARIA_UNIQUE_HASH_LENGTH);
      69               0 :     if (_ma_search_next(info, &info->last_key, SEARCH_BIGGER,
      70                 :                         info->s->state.key_root[def->key]) ||
      71                 :         bcmp((char*) info->last_key.data, (char*) key_buff,
      72                 :              MARIA_UNIQUE_HASH_LENGTH))
      73                 :     {
      74               0 :       info->page_changed= 1;                 /* Can't optimize read next */
      75               0 :       info->cur_row.lastpos= lastpos;
      76               0 :       DBUG_RETURN(0);                           /* end of tree */
      77                 :     }
      78                 :   }
      79                 : }
      80                 : 
      81                 : 
      82                 : /*
      83                 :   Calculate a hash for a row
      84                 : 
      85                 :   TODO
      86                 :     Add support for bit fields
      87                 : */
      88                 : 
      89                 : ha_checksum _ma_unique_hash(MARIA_UNIQUEDEF *def, const uchar *record)
      90               0 : {
      91                 :   const uchar *pos, *end;
      92               0 :   ha_checksum crc= 0;
      93               0 :   ulong seed1=0, seed2= 4;
      94                 :   HA_KEYSEG *keyseg;
      95                 : 
      96               0 :   for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
      97                 :   {
      98               0 :     enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
      99               0 :     uint length=keyseg->length;
     100                 : 
     101               0 :     if (keyseg->null_bit)
     102                 :     {
     103               0 :       if (record[keyseg->null_pos] & keyseg->null_bit)
     104                 :       {
     105                 :         /*
     106                 :           Change crc in a way different from an empty string or 0.
     107                 :           (This is an optimisation;  The code will work even if this isn't
     108                 :           done)
     109                 :         */
     110               0 :         crc=((crc << 8) + 511+
     111                 :              (crc >> (8*sizeof(ha_checksum)-8)));
     112               0 :         continue;
     113                 :       }
     114                 :     }
     115               0 :     pos= record+keyseg->start;
     116               0 :     if (keyseg->flag & HA_VAR_LENGTH_PART)
     117                 :     {
     118               0 :       uint pack_length=  keyseg->bit_start;
     119                 :       uint tmp_length= (pack_length == 1 ? (uint) *pos :
     120               0 :                         uint2korr(pos));
     121               0 :       pos+= pack_length;                        /* Skip VARCHAR length */
     122               0 :       set_if_smaller(length,tmp_length);
     123                 :     }
     124               0 :     else if (keyseg->flag & HA_BLOB_PART)
     125                 :     {
     126               0 :       uint tmp_length= _ma_calc_blob_length(keyseg->bit_start,pos);
     127               0 :       memcpy_fixed((uchar*) &pos,pos+keyseg->bit_start,sizeof(char*));
     128               0 :       if (!length || length > tmp_length)
     129               0 :         length=tmp_length;                      /* The whole blob */
     130                 :     }
     131               0 :     end= pos+length;
     132               0 :     if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
     133                 :         type == HA_KEYTYPE_VARTEXT2)
     134                 :     {
     135               0 :       keyseg->charset->coll->hash_sort(keyseg->charset,
     136                 :                                        (const uchar*) pos, length, &seed1,
     137                 :                                        &seed2);
     138               0 :       crc^= seed1;
     139                 :     }
     140                 :     else
     141               0 :       while (pos != end)
     142               0 :         crc=((crc << 8) +
     143                 :              (((uchar)  *pos++))) +
     144                 :           (crc >> (8*sizeof(ha_checksum)-8));
     145                 :   }
     146               0 :   return crc;
     147                 : }
     148                 : 
     149                 : 
     150                 : /*
     151                 :   compare unique key for two rows
     152                 : 
     153                 :   TODO
     154                 :     Add support for bit fields
     155                 : 
     156                 :   RETURN
     157                 :     0   if both rows have equal unique value
     158                 :     1   Rows are different
     159                 : */
     160                 : 
     161                 : my_bool _ma_unique_comp(MARIA_UNIQUEDEF *def, const uchar *a, const uchar *b,
     162                 :                         my_bool null_are_equal)
     163               0 : {
     164                 :   const uchar *pos_a, *pos_b, *end;
     165                 :   HA_KEYSEG *keyseg;
     166                 : 
     167               0 :   for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
     168                 :   {
     169               0 :     enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
     170                 :     uint a_length, b_length;
     171               0 :     a_length= b_length= keyseg->length;
     172                 : 
     173                 :     /* If part is NULL it's regarded as different */
     174               0 :     if (keyseg->null_bit)
     175                 :     {
     176                 :       uint tmp;
     177               0 :       if ((tmp=(a[keyseg->null_pos] & keyseg->null_bit)) !=
     178                 :           (uint) (b[keyseg->null_pos] & keyseg->null_bit))
     179               0 :         return 1;
     180               0 :       if (tmp)
     181                 :       {
     182               0 :         if (!null_are_equal)
     183               0 :           return 1;
     184                 :         continue;
     185                 :       }
     186                 :     }
     187               0 :     pos_a= a+keyseg->start;
     188               0 :     pos_b= b+keyseg->start;
     189               0 :     if (keyseg->flag & HA_VAR_LENGTH_PART)
     190                 :     {
     191               0 :       uint pack_length= keyseg->bit_start;
     192               0 :       if (pack_length == 1)
     193                 :       {
     194               0 :         a_length= (uint) *pos_a++;
     195               0 :         b_length= (uint) *pos_b++;
     196                 :       }
     197                 :       else
     198                 :       {
     199               0 :         a_length= uint2korr(pos_a);
     200               0 :         b_length= uint2korr(pos_b);
     201               0 :         pos_a+= 2;                              /* Skip VARCHAR length */
     202               0 :         pos_b+= 2;
     203                 :       }
     204               0 :       set_if_smaller(a_length, keyseg->length); /* Safety */
     205               0 :       set_if_smaller(b_length, keyseg->length); /* safety */
     206                 :     }
     207               0 :     else if (keyseg->flag & HA_BLOB_PART)
     208                 :     {
     209                 :       /* Only compare 'length' characters if length != 0 */
     210               0 :       a_length= _ma_calc_blob_length(keyseg->bit_start,pos_a);
     211               0 :       b_length= _ma_calc_blob_length(keyseg->bit_start,pos_b);
     212                 :       /* Check that a and b are of equal length */
     213               0 :       if (keyseg->length)
     214                 :       {
     215                 :         /*
     216                 :           This is used in some cases when we are not interested in comparing
     217                 :           the whole length of the blob.
     218                 :         */
     219               0 :         set_if_smaller(a_length, keyseg->length);
     220               0 :         set_if_smaller(b_length, keyseg->length);
     221                 :       }
     222               0 :       memcpy_fixed((uchar*) &pos_a,pos_a+keyseg->bit_start,sizeof(char*));
     223               0 :       memcpy_fixed((uchar*) &pos_b,pos_b+keyseg->bit_start,sizeof(char*));
     224                 :     }
     225               0 :     if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
     226                 :         type == HA_KEYTYPE_VARTEXT2)
     227                 :     {
     228               0 :       if (ha_compare_text(keyseg->charset, pos_a, a_length,
     229                 :                           pos_b, b_length, 0, 1))
     230               0 :         return 1;
     231                 :     }
     232                 :     else
     233                 :     {
     234               0 :       if (a_length != b_length)
     235               0 :         return 1;
     236               0 :       end= pos_a+a_length;
     237               0 :       while (pos_a != end)
     238                 :       {
     239               0 :         if (*pos_a++ != *pos_b++)
     240               0 :           return 1;
     241                 :       }
     242                 :     }
     243                 :   }
     244               0 :   return 0;
     245                 : }

Generated by: LTP GCOV extension version 1.4