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
00021 using namespace drizzled;
00022
00023 bool mi_check_unique(MI_INFO *info,
00024 MI_UNIQUEDEF *def,
00025 unsigned char *record,
00026 internal::ha_checksum unique_hash,
00027 internal::my_off_t disk_pos)
00028 {
00029 internal::my_off_t lastpos=info->lastpos;
00030 MI_KEYDEF *key= &info->s->keyinfo[def->key];
00031 unsigned char *key_buff=info->lastkey2;
00032
00033 mi_unique_store(record+key->seg->start, unique_hash);
00034 _mi_make_key(info,def->key,key_buff,record,0);
00035
00036
00037 info->update&= ~HA_STATE_RNEXT_SAME;
00038
00039 if (_mi_search(info,info->s->keyinfo+def->key,key_buff,MI_UNIQUE_HASH_LENGTH,
00040 SEARCH_FIND,info->s->state.key_root[def->key]))
00041 {
00042 info->page_changed=1;
00043 info->lastpos= lastpos;
00044 return(0);
00045 }
00046
00047 for (;;)
00048 {
00049 if (info->lastpos != disk_pos &&
00050 !(*info->s->compare_unique)(info,def,record,info->lastpos))
00051 {
00052 errno=HA_ERR_FOUND_DUPP_UNIQUE;
00053 info->errkey= (int) def->key;
00054 info->dupp_key_pos= info->lastpos;
00055 info->page_changed=1;
00056 info->lastpos=lastpos;
00057 return(1);
00058 }
00059 if (_mi_search_next(info,info->s->keyinfo+def->key, info->lastkey,
00060 MI_UNIQUE_HASH_LENGTH, SEARCH_BIGGER,
00061 info->s->state.key_root[def->key]) ||
00062 memcmp(info->lastkey, key_buff, MI_UNIQUE_HASH_LENGTH))
00063 {
00064 info->page_changed=1;
00065 info->lastpos=lastpos;
00066 return(0);
00067 }
00068 }
00069 }
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 internal::ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const unsigned char *record)
00080 {
00081 const unsigned char *pos, *end;
00082 internal::ha_checksum crc= 0;
00083 uint32_t seed1=0, seed2= 4;
00084 HA_KEYSEG *keyseg;
00085
00086 for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
00087 {
00088 enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
00089 uint32_t length=keyseg->length;
00090
00091 if (keyseg->null_bit)
00092 {
00093 if (record[keyseg->null_pos] & keyseg->null_bit)
00094 {
00095
00096
00097
00098
00099
00100 crc=((crc << 8) + 511+
00101 (crc >> (8*sizeof(internal::ha_checksum)-8)));
00102 continue;
00103 }
00104 }
00105 pos= record+keyseg->start;
00106 if (keyseg->flag & HA_VAR_LENGTH_PART)
00107 {
00108 uint32_t pack_length= keyseg->bit_start;
00109 uint32_t tmp_length= (pack_length == 1 ? (uint) *(unsigned char*) pos :
00110 uint2korr(pos));
00111 pos+= pack_length;
00112 set_if_smaller(length,tmp_length);
00113 }
00114 else if (keyseg->flag & HA_BLOB_PART)
00115 {
00116 uint32_t tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
00117 memcpy(&pos,pos+keyseg->bit_start,sizeof(char*));
00118 if (!length || length > tmp_length)
00119 length=tmp_length;
00120 }
00121 end= pos+length;
00122 if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
00123 type == HA_KEYTYPE_VARTEXT2)
00124 {
00125 keyseg->charset->coll->hash_sort(keyseg->charset,
00126 (const unsigned char*) pos, length, &seed1,
00127 &seed2);
00128 crc^= seed1;
00129 }
00130 else
00131 while (pos != end)
00132 crc=((crc << 8) +
00133 (((unsigned char) *(unsigned char*) pos++))) +
00134 (crc >> (8*sizeof(internal::ha_checksum)-8));
00135 }
00136 return crc;
00137 }
00138
00139
00140
00141
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151 int mi_unique_comp(MI_UNIQUEDEF *def, const unsigned char *a, const unsigned char *b,
00152 bool null_are_equal)
00153 {
00154 const unsigned char *pos_a, *pos_b, *end;
00155 HA_KEYSEG *keyseg;
00156
00157 for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
00158 {
00159 enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
00160 uint16_t a_length, b_length;
00161 a_length= b_length= keyseg->length;
00162
00163
00164 if (keyseg->null_bit)
00165 {
00166 uint32_t tmp;
00167 if ((tmp=(a[keyseg->null_pos] & keyseg->null_bit)) !=
00168 (uint) (b[keyseg->null_pos] & keyseg->null_bit))
00169 return 1;
00170 if (tmp)
00171 {
00172 if (!null_are_equal)
00173 return 1;
00174 continue;
00175 }
00176 }
00177 pos_a= a+keyseg->start;
00178 pos_b= b+keyseg->start;
00179 if (keyseg->flag & HA_VAR_LENGTH_PART)
00180 {
00181 uint32_t pack_length= keyseg->bit_start;
00182 if (pack_length == 1)
00183 {
00184 a_length= (uint) *(unsigned char*) pos_a++;
00185 b_length= (uint) *(unsigned char*) pos_b++;
00186 }
00187 else
00188 {
00189 a_length= uint2korr(pos_a);
00190 b_length= uint2korr(pos_b);
00191 pos_a+= 2;
00192 pos_b+= 2;
00193 }
00194 set_if_smaller(a_length, keyseg->length);
00195 set_if_smaller(b_length, keyseg->length);
00196 }
00197 else if (keyseg->flag & HA_BLOB_PART)
00198 {
00199
00200 a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
00201 b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
00202
00203 if (keyseg->length)
00204 {
00205
00206
00207
00208
00209 set_if_smaller(a_length, keyseg->length);
00210 set_if_smaller(b_length, keyseg->length);
00211 }
00212 memcpy(&pos_a,pos_a+keyseg->bit_start,sizeof(char*));
00213 memcpy(&pos_b,pos_b+keyseg->bit_start,sizeof(char*));
00214 }
00215 if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
00216 type == HA_KEYTYPE_VARTEXT2)
00217 {
00218 if (ha_compare_text(keyseg->charset, (unsigned char *) pos_a, a_length,
00219 (unsigned char *) pos_b, b_length, 0, 1))
00220 return 1;
00221 }
00222 else
00223 {
00224 if (a_length != b_length)
00225 return 1;
00226 end= pos_a+a_length;
00227 while (pos_a != end)
00228 {
00229 if (*pos_a++ != *pos_b++)
00230 return 1;
00231 }
00232 }
00233 }
00234 return 0;
00235 }