mariadb/storage/maria/ma_unique.c
unknown 46922b5125 GPL license update (same change as was done for all files in 5.1).
storage/maria/Makefile.am:
  GPL license update
storage/maria/ft_maria.c:
  GPL license update
storage/maria/ha_maria.cc:
  GPL license update
storage/maria/ha_maria.h:
  GPL license update
storage/maria/lockman.c:
  GPL license update
storage/maria/lockman.h:
  GPL license update
storage/maria/ma_bitmap.c:
  GPL license update
storage/maria/ma_blockrec.c:
  GPL license update
storage/maria/ma_blockrec.h:
  GPL license update
storage/maria/ma_cache.c:
  GPL license update
storage/maria/ma_changed.c:
  GPL license update
storage/maria/ma_check.c:
  GPL license update
storage/maria/ma_checkpoint.c:
  GPL license update
storage/maria/ma_checkpoint.h:
  GPL license update
storage/maria/ma_checksum.c:
  GPL license update
storage/maria/ma_close.c:
  GPL license update
storage/maria/ma_control_file.c:
  GPL license update
storage/maria/ma_control_file.h:
  GPL license update
storage/maria/ma_create.c:
  GPL license update
storage/maria/ma_dbug.c:
  GPL license update
storage/maria/ma_delete.c:
  GPL license update
storage/maria/ma_delete_all.c:
  GPL license update
storage/maria/ma_delete_table.c:
  GPL license update
storage/maria/ma_dynrec.c:
  GPL license update
storage/maria/ma_extra.c:
  GPL license update
storage/maria/ma_ft_boolean_search.c:
  GPL license update
storage/maria/ma_ft_eval.c:
  GPL license update
storage/maria/ma_ft_eval.h:
  GPL license update
storage/maria/ma_ft_nlq_search.c:
  GPL license update
storage/maria/ma_ft_parser.c:
  GPL license update
storage/maria/ma_ft_stem.c:
  GPL license update
storage/maria/ma_ft_test1.c:
  GPL license update
storage/maria/ma_ft_test1.h:
  GPL license update
storage/maria/ma_ft_update.c:
  GPL license update
storage/maria/ma_ftdefs.h:
  GPL license update
storage/maria/ma_fulltext.h:
  GPL license update
storage/maria/ma_info.c:
  GPL license update
storage/maria/ma_init.c:
  GPL license update
storage/maria/ma_key.c:
  GPL license update
storage/maria/ma_keycache.c:
  GPL license update
storage/maria/ma_least_recently_dirtied.c:
  GPL license update
storage/maria/ma_least_recently_dirtied.h:
  GPL license update
storage/maria/ma_locking.c:
  GPL license update
storage/maria/ma_open.c:
  GPL license update
storage/maria/ma_packrec.c:
  GPL license update
storage/maria/ma_page.c:
  GPL license update
storage/maria/ma_panic.c:
  GPL license update
storage/maria/ma_preload.c:
  GPL license update
storage/maria/ma_range.c:
  GPL license update
storage/maria/ma_recovery.c:
  GPL license update
storage/maria/ma_recovery.h:
  GPL license update
storage/maria/ma_rename.c:
  GPL license update
storage/maria/ma_rfirst.c:
  GPL license update
storage/maria/ma_rkey.c:
  GPL license update
storage/maria/ma_rlast.c:
  GPL license update
storage/maria/ma_rnext.c:
  GPL license update
storage/maria/ma_rnext_same.c:
  GPL license update
storage/maria/ma_rprev.c:
  GPL license update
storage/maria/ma_rrnd.c:
  GPL license update
storage/maria/ma_rsame.c:
  GPL license update
storage/maria/ma_rsamepos.c:
  GPL license update
storage/maria/ma_rt_index.c:
  GPL license update
storage/maria/ma_rt_index.h:
  GPL license update
storage/maria/ma_rt_key.c:
  GPL license update
storage/maria/ma_rt_key.h:
  GPL license update
storage/maria/ma_rt_mbr.c:
  GPL license update
storage/maria/ma_rt_mbr.h:
  GPL license update
storage/maria/ma_rt_split.c:
  GPL license update
storage/maria/ma_rt_test.c:
  GPL license update
storage/maria/ma_scan.c:
  GPL license update
storage/maria/ma_search.c:
  GPL license update
storage/maria/ma_sort.c:
  GPL license update
storage/maria/ma_sp_defs.h:
  GPL license update
storage/maria/ma_sp_key.c:
  GPL license update
storage/maria/ma_sp_test.c:
  GPL license update
storage/maria/ma_static.c:
  GPL license update
storage/maria/ma_statrec.c:
  GPL license update
storage/maria/ma_test1.c:
  GPL license update
storage/maria/ma_test2.c:
  GPL license update
storage/maria/ma_test3.c:
  GPL license update
storage/maria/ma_unique.c:
  GPL license update
storage/maria/ma_update.c:
  GPL license update
storage/maria/ma_write.c:
  GPL license update
storage/maria/maria_chk.c:
  GPL license update
storage/maria/maria_def.h:
  GPL license update
storage/maria/maria_ftdump.c:
  GPL license update
storage/maria/maria_pack.c:
  GPL license update
storage/maria/tablockman.c:
  GPL license update
storage/maria/tablockman.h:
  GPL license update
storage/maria/trnman.c:
  GPL license update
storage/maria/trnman.h:
  GPL license update
2007-03-02 11:20:23 +01:00

235 lines
6.8 KiB
C

/* Copyright (C) 2006 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/* Functions to check if a row is unique */
#include "maria_def.h"
#include <m_ctype.h>
my_bool _ma_check_unique(MARIA_HA *info, MARIA_UNIQUEDEF *def, byte *record,
ha_checksum unique_hash, my_off_t disk_pos)
{
my_off_t lastpos=info->cur_row.lastpos;
MARIA_KEYDEF *key= &info->s->keyinfo[def->key];
byte *key_buff= info->lastkey2;
DBUG_ENTER("_ma_check_unique");
DBUG_PRINT("enter",("unique_hash: %lu", (ulong) unique_hash));
maria_unique_store(record+key->seg->start, unique_hash);
_ma_make_key(info,def->key,key_buff,record,0);
/* The above changed info->lastkey2. Inform maria_rnext_same(). */
info->update&= ~HA_STATE_RNEXT_SAME;
if (_ma_search(info,info->s->keyinfo+def->key,key_buff,
MARIA_UNIQUE_HASH_LENGTH,
SEARCH_FIND,info->s->state.key_root[def->key]))
{
info->page_changed=1; /* Can't optimize read next */
info->cur_row.lastpos= lastpos;
DBUG_RETURN(0); /* No matching rows */
}
for (;;)
{
if (info->cur_row.lastpos != disk_pos &&
!(*info->s->compare_unique)(info,def,record,info->cur_row.lastpos))
{
my_errno=HA_ERR_FOUND_DUPP_UNIQUE;
info->errkey= (int) def->key;
info->dup_key_pos= info->cur_row.lastpos;
info->page_changed= 1; /* Can't optimize read next */
info->cur_row.lastpos= lastpos;
DBUG_PRINT("info",("Found duplicate"));
DBUG_RETURN(1); /* Found identical */
}
if (_ma_search_next(info,info->s->keyinfo+def->key, info->lastkey,
MARIA_UNIQUE_HASH_LENGTH, SEARCH_BIGGER,
info->s->state.key_root[def->key]) ||
bcmp((char*) info->lastkey, (char*) key_buff,
MARIA_UNIQUE_HASH_LENGTH))
{
info->page_changed= 1; /* Can't optimize read next */
info->cur_row.lastpos= lastpos;
DBUG_RETURN(0); /* end of tree */
}
}
}
/*
Calculate a hash for a row
TODO
Add support for bit fields
*/
ha_checksum _ma_unique_hash(MARIA_UNIQUEDEF *def, const byte *record)
{
const byte *pos, *end;
ha_checksum crc= 0;
ulong seed1=0, seed2= 4;
HA_KEYSEG *keyseg;
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
{
enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
uint length=keyseg->length;
if (keyseg->null_bit)
{
if (record[keyseg->null_pos] & keyseg->null_bit)
{
/*
Change crc in a way different from an empty string or 0.
(This is an optimisation; The code will work even if this isn't
done)
*/
crc=((crc << 8) + 511+
(crc >> (8*sizeof(ha_checksum)-8)));
continue;
}
}
pos= record+keyseg->start;
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint pack_length= keyseg->bit_start;
uint tmp_length= (pack_length == 1 ? (uint) *(uchar*) pos :
uint2korr(pos));
pos+= pack_length; /* Skip VARCHAR length */
set_if_smaller(length,tmp_length);
}
else if (keyseg->flag & HA_BLOB_PART)
{
uint tmp_length= _ma_calc_blob_length(keyseg->bit_start,pos);
memcpy_fixed((byte*) &pos,pos+keyseg->bit_start,sizeof(char*));
if (!length || length > tmp_length)
length=tmp_length; /* The whole blob */
}
end= pos+length;
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
type == HA_KEYTYPE_VARTEXT2)
{
keyseg->charset->coll->hash_sort(keyseg->charset,
(const uchar*) pos, length, &seed1,
&seed2);
crc^= seed1;
}
else
while (pos != end)
crc=((crc << 8) +
(((uchar) *(uchar*) pos++))) +
(crc >> (8*sizeof(ha_checksum)-8));
}
return crc;
}
/*
compare unique key for two rows
TODO
Add support for bit fields
RETURN
0 if both rows have equal unique value
1 Rows are different
*/
my_bool _ma_unique_comp(MARIA_UNIQUEDEF *def, const byte *a, const byte *b,
my_bool null_are_equal)
{
const byte *pos_a, *pos_b, *end;
HA_KEYSEG *keyseg;
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
{
enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
uint a_length, b_length;
a_length= b_length= keyseg->length;
/* If part is NULL it's regarded as different */
if (keyseg->null_bit)
{
uint tmp;
if ((tmp=(a[keyseg->null_pos] & keyseg->null_bit)) !=
(uint) (b[keyseg->null_pos] & keyseg->null_bit))
return 1;
if (tmp)
{
if (!null_are_equal)
return 1;
continue;
}
}
pos_a= a+keyseg->start;
pos_b= b+keyseg->start;
if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint pack_length= keyseg->bit_start;
if (pack_length == 1)
{
a_length= (uint) *(uchar*) pos_a++;
b_length= (uint) *(uchar*) pos_b++;
}
else
{
a_length= uint2korr(pos_a);
b_length= uint2korr(pos_b);
pos_a+= 2; /* Skip VARCHAR length */
pos_b+= 2;
}
set_if_smaller(a_length, keyseg->length); /* Safety */
set_if_smaller(b_length, keyseg->length); /* safety */
}
else if (keyseg->flag & HA_BLOB_PART)
{
/* Only compare 'length' characters if length != 0 */
a_length= _ma_calc_blob_length(keyseg->bit_start,pos_a);
b_length= _ma_calc_blob_length(keyseg->bit_start,pos_b);
/* Check that a and b are of equal length */
if (keyseg->length)
{
/*
This is used in some cases when we are not interested in comparing
the whole length of the blob.
*/
set_if_smaller(a_length, keyseg->length);
set_if_smaller(b_length, keyseg->length);
}
memcpy_fixed((byte*) &pos_a,pos_a+keyseg->bit_start,sizeof(char*));
memcpy_fixed((byte*) &pos_b,pos_b+keyseg->bit_start,sizeof(char*));
}
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
type == HA_KEYTYPE_VARTEXT2)
{
if (ha_compare_text(keyseg->charset, (uchar *) pos_a, a_length,
(uchar *) pos_b, b_length, 0, 1))
return 1;
}
else
{
if (a_length != b_length)
return 1;
end= pos_a+a_length;
while (pos_a != end)
{
if (*pos_a++ != *pos_b++)
return 1;
}
}
}
return 0;
}