~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2000-2006 MySQL 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
1802.10.2 by Monty Taylor
Update all of the copyright headers to include the correct address.
14
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA */
1 by brian
clean slate
15
16
/* Functions to check if a row is unique */
17
1130.3.28 by Monty Taylor
Moved heapdef.h and myisamdef.h to *_priv.h for easier filtering for include guard check.
18
#include "myisam_priv.h"
2281.5.1 by Muhammad Umair
Merged charset declarations of global_charset_info.h and charset_info.h into charset.h header file.
19
#include <drizzled/charset.h>
1 by brian
clean slate
20
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
21
using namespace drizzled;
22
23
bool mi_check_unique(MI_INFO *info,
24
                     MI_UNIQUEDEF *def,
25
                     unsigned char *record,
2241.4.37 by Stewart Smith
remove the drizzled::internal namespace prefix from teh typedef for ha_checksum - it's just for myisam now
26
                     ha_checksum unique_hash,
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
27
                     internal::my_off_t disk_pos)
1 by brian
clean slate
28
{
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
29
  internal::my_off_t lastpos=info->lastpos;
1 by brian
clean slate
30
  MI_KEYDEF *key= &info->s->keyinfo[def->key];
481 by Brian Aker
Remove all of uchar.
31
  unsigned char *key_buff=info->lastkey2;
1 by brian
clean slate
32
33
  mi_unique_store(record+key->seg->start, unique_hash);
34
  _mi_make_key(info,def->key,key_buff,record,0);
35
36
  /* The above changed info->lastkey2. Inform mi_rnext_same(). */
37
  info->update&= ~HA_STATE_RNEXT_SAME;
38
39
  if (_mi_search(info,info->s->keyinfo+def->key,key_buff,MI_UNIQUE_HASH_LENGTH,
40
		 SEARCH_FIND,info->s->state.key_root[def->key]))
41
  {
42
    info->page_changed=1;			/* Can't optimize read next */
43
    info->lastpos= lastpos;
51.1.114 by Jay Pipes
DBUG symbol removal
44
    return(0);				/* No matching rows */
1 by brian
clean slate
45
  }
46
47
  for (;;)
48
  {
49
    if (info->lastpos != disk_pos &&
50
	!(*info->s->compare_unique)(info,def,record,info->lastpos))
51
    {
1241.9.57 by Monty Taylor
Oy. Bigger change than I normally like - but this stuff is all intertwined.
52
      errno=HA_ERR_FOUND_DUPP_UNIQUE;
1 by brian
clean slate
53
      info->errkey= (int) def->key;
54
      info->dupp_key_pos= info->lastpos;
55
      info->page_changed=1;			/* Can't optimize read next */
56
      info->lastpos=lastpos;
51.1.114 by Jay Pipes
DBUG symbol removal
57
      return(1);				/* Found identical  */
1 by brian
clean slate
58
    }
59
    if (_mi_search_next(info,info->s->keyinfo+def->key, info->lastkey,
60
			MI_UNIQUE_HASH_LENGTH, SEARCH_BIGGER,
61
			info->s->state.key_root[def->key]) ||
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
62
	memcmp(info->lastkey, key_buff, MI_UNIQUE_HASH_LENGTH))
1 by brian
clean slate
63
    {
64
      info->page_changed=1;			/* Can't optimize read next */
65
      info->lastpos=lastpos;
51.1.114 by Jay Pipes
DBUG symbol removal
66
      return(0);				/* end of tree */
1 by brian
clean slate
67
    }
68
  }
69
}
70
71
72
/*
73
  Calculate a hash for a row
74
75
  TODO
76
    Add support for bit fields
77
*/
78
2241.4.37 by Stewart Smith
remove the drizzled::internal namespace prefix from teh typedef for ha_checksum - it's just for myisam now
79
ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const unsigned char *record)
1 by brian
clean slate
80
{
481 by Brian Aker
Remove all of uchar.
81
  const unsigned char *pos, *end;
2241.4.37 by Stewart Smith
remove the drizzled::internal namespace prefix from teh typedef for ha_checksum - it's just for myisam now
82
  ha_checksum crc= 0;
290 by Brian Aker
Update for ulong change over.
83
  uint32_t seed1=0, seed2= 4;
1 by brian
clean slate
84
  HA_KEYSEG *keyseg;
85
86
  for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
87
  {
88
    enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
482 by Brian Aker
Remove uint.
89
    uint32_t length=keyseg->length;
1 by brian
clean slate
90
91
    if (keyseg->null_bit)
92
    {
93
      if (record[keyseg->null_pos] & keyseg->null_bit)
94
      {
95
	/*
96
	  Change crc in a way different from an empty string or 0.
97
	  (This is an optimisation;  The code will work even if this isn't
98
	  done)
99
	*/
100
	crc=((crc << 8) + 511+
2241.4.37 by Stewart Smith
remove the drizzled::internal namespace prefix from teh typedef for ha_checksum - it's just for myisam now
101
	     (crc >> (8*sizeof(ha_checksum)-8)));
1 by brian
clean slate
102
	continue;
103
      }
104
    }
105
    pos= record+keyseg->start;
106
    if (keyseg->flag & HA_VAR_LENGTH_PART)
107
    {
482 by Brian Aker
Remove uint.
108
      uint32_t pack_length=  keyseg->bit_start;
109
      uint32_t tmp_length= (pack_length == 1 ? (uint) *(unsigned char*) pos :
1 by brian
clean slate
110
                        uint2korr(pos));
111
      pos+= pack_length;			/* Skip VARCHAR length */
112
      set_if_smaller(length,tmp_length);
113
    }
114
    else if (keyseg->flag & HA_BLOB_PART)
115
    {
482 by Brian Aker
Remove uint.
116
      uint32_t tmp_length=_mi_calc_blob_length(keyseg->bit_start,pos);
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
117
      memcpy(&pos,pos+keyseg->bit_start,sizeof(char*));
1 by brian
clean slate
118
      if (!length || length > tmp_length)
119
	length=tmp_length;			/* The whole blob */
120
    }
121
    end= pos+length;
122
    if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
123
        type == HA_KEYTYPE_VARTEXT2)
124
    {
125
      keyseg->charset->coll->hash_sort(keyseg->charset,
481 by Brian Aker
Remove all of uchar.
126
                                       (const unsigned char*) pos, length, &seed1,
1 by brian
clean slate
127
                                       &seed2);
128
      crc^= seed1;
129
    }
130
    else
131
      while (pos != end)
132
	crc=((crc << 8) +
481 by Brian Aker
Remove all of uchar.
133
	     (((unsigned char)  *(unsigned char*) pos++))) +
2241.4.37 by Stewart Smith
remove the drizzled::internal namespace prefix from teh typedef for ha_checksum - it's just for myisam now
134
	  (crc >> (8*sizeof(ha_checksum)-8));
1 by brian
clean slate
135
  }
136
  return crc;
137
}
138
139
140
/*
141
  compare unique key for two rows
142
143
  TODO
144
    Add support for bit fields
145
146
  RETURN
147
    0   if both rows have equal unique value
148
    #   Rows are different
149
*/
150
481 by Brian Aker
Remove all of uchar.
151
int mi_unique_comp(MI_UNIQUEDEF *def, const unsigned char *a, const unsigned char *b,
281 by Brian Aker
Converted myisam away from my_bool
152
		   bool null_are_equal)
1 by brian
clean slate
153
{
481 by Brian Aker
Remove all of uchar.
154
  const unsigned char *pos_a, *pos_b, *end;
1 by brian
clean slate
155
  HA_KEYSEG *keyseg;
156
157
  for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
158
  {
159
    enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
937.2.6 by Stewart Smith
make set_if_bigger typesafe for C and C++. Fix up everywhere.
160
    uint16_t a_length, b_length;
1 by brian
clean slate
161
    a_length= b_length= keyseg->length;
162
163
    /* If part is NULL it's regarded as different */
164
    if (keyseg->null_bit)
165
    {
482 by Brian Aker
Remove uint.
166
      uint32_t tmp;
1 by brian
clean slate
167
      if ((tmp=(a[keyseg->null_pos] & keyseg->null_bit)) !=
168
	  (uint) (b[keyseg->null_pos] & keyseg->null_bit))
169
	return 1;
170
      if (tmp)
171
      {
172
	if (!null_are_equal)
173
	  return 1;
174
	continue;
175
      }
176
    }
177
    pos_a= a+keyseg->start;
178
    pos_b= b+keyseg->start;
179
    if (keyseg->flag & HA_VAR_LENGTH_PART)
180
    {
482 by Brian Aker
Remove uint.
181
      uint32_t pack_length= keyseg->bit_start;
1 by brian
clean slate
182
      if (pack_length == 1)
183
      {
481 by Brian Aker
Remove all of uchar.
184
        a_length= (uint) *(unsigned char*) pos_a++;
185
        b_length= (uint) *(unsigned char*) pos_b++;
1 by brian
clean slate
186
      }
187
      else
188
      {
189
        a_length= uint2korr(pos_a);
190
        b_length= uint2korr(pos_b);
191
        pos_a+= 2;				/* Skip VARCHAR length */
192
        pos_b+= 2;
193
      }
194
      set_if_smaller(a_length, keyseg->length); /* Safety */
195
      set_if_smaller(b_length, keyseg->length); /* safety */
196
    }
197
    else if (keyseg->flag & HA_BLOB_PART)
198
    {
199
      /* Only compare 'length' characters if length != 0 */
200
      a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
201
      b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
202
      /* Check that a and b are of equal length */
203
      if (keyseg->length)
204
      {
205
        /*
206
          This is used in some cases when we are not interested in comparing
207
          the whole length of the blob.
208
        */
209
        set_if_smaller(a_length, keyseg->length);
210
        set_if_smaller(b_length, keyseg->length);
211
      }
212.6.12 by Mats Kindahl
Removing redundant use of casts in MyISAM storage for memcmp(), memcpy(), memset(), and memmove().
212
      memcpy(&pos_a,pos_a+keyseg->bit_start,sizeof(char*));
213
      memcpy(&pos_b,pos_b+keyseg->bit_start,sizeof(char*));
1 by brian
clean slate
214
    }
215
    if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT1 ||
216
        type == HA_KEYTYPE_VARTEXT2)
217
    {
481 by Brian Aker
Remove all of uchar.
218
      if (ha_compare_text(keyseg->charset, (unsigned char *) pos_a, a_length,
219
                                           (unsigned char *) pos_b, b_length, 0, 1))
1 by brian
clean slate
220
        return 1;
221
    }
222
    else
223
    {
224
      if (a_length != b_length)
225
        return 1;
226
      end= pos_a+a_length;
227
      while (pos_a != end)
228
      {
229
	if (*pos_a++ != *pos_b++)
230
	  return 1;
231
      }
232
    }
233
  }
234
  return 0;
235
}