~drizzle-trunk/drizzle/development

547 by Monty Taylor
Moved handler_error_messages array out of header file. Moved associated
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
 *  vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
3
 *
1999.6.1 by kalebral at gmail
update Copyright strings to a more common format to help with creating the master debian copyright file
4
 *  Copyright (C) 2008 Sun Microsystems, Inc.
547 by Monty Taylor
Moved handler_error_messages array out of header file. Moved associated
5
 *
6
 *  This program is free software; you can redistribute it and/or modify
7
 *  it under the terms of the GNU General Public License as published by
8
 *  the Free Software Foundation; version 2 of the License.
9
 *
10
 *  This program is distributed in the hope that it will be useful,
11
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 *  GNU General Public License for more details.
14
 *
15
 *  You should have received a copy of the GNU General Public License
16
 *  along with this program; if not, write to the Free Software
17
 *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
18
 */
1 by brian
clean slate
19
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
20
#include <config.h>
212.5.39 by Monty Taylor
Phew. Moved my_base and my_global.
21
2281.5.1 by Muhammad Umair
Merged charset declarations of global_charset_info.h and charset_info.h into charset.h header file.
22
#include <drizzled/charset.h>
212.5.39 by Monty Taylor
Phew. Moved my_base and my_global.
23
#include <drizzled/base.h>
992.1.25 by Monty Taylor
Moved myisam to new plugin system.
24
#include <plugin/myisam/my_handler.h>
2173.2.1 by Monty Taylor
Fixes incorrect usage of include
25
#include <drizzled/internal/my_sys.h>
1 by brian
clean slate
26
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
27
#include <cassert>
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
28
#include <algorithm>
29
1280.1.10 by Monty Taylor
Put everything in drizzled into drizzled namespace.
30
using namespace drizzled;
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
31
using namespace std;
32
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
33
template<class T>
34
int CMP_NUM(const T& a, const T&b)
35
{
36
  return (a < b) ? -1 : (a == b) ? 0 : 1;
37
}
398.1.9 by Monty Taylor
Cleaned up stuff out of global.h.
38
39
2254 by Brian Aker
Shift CHARSET_INFO to charset_info_st
40
int ha_compare_text(const charset_info_st * const charset_info, unsigned char *a, uint32_t a_length,
482 by Brian Aker
Remove uint.
41
		    unsigned char *b, uint32_t b_length, bool part_key,
146 by Brian Aker
my_bool cleanup.
42
		    bool skip_end_space)
1 by brian
clean slate
43
{
44
  if (!part_key)
45
    return charset_info->coll->strnncollsp(charset_info, a, a_length,
146 by Brian Aker
my_bool cleanup.
46
                                           b, b_length, (bool)!skip_end_space);
1 by brian
clean slate
47
  return charset_info->coll->strnncoll(charset_info, a, a_length,
48
                                       b, b_length, part_key);
49
}
50
51
482 by Brian Aker
Remove uint.
52
static int compare_bin(unsigned char *a, uint32_t a_length, unsigned char *b, uint32_t b_length,
146 by Brian Aker
my_bool cleanup.
53
                       bool part_key, bool skip_end_space)
1 by brian
clean slate
54
{
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
55
  uint32_t length= min(a_length,b_length);
481 by Brian Aker
Remove all of uchar.
56
  unsigned char *end= a+ length;
1 by brian
clean slate
57
  int flag;
58
59
  while (a < end)
60
    if ((flag= (int) *a++ - (int) *b++))
61
      return flag;
62
  if (part_key && b_length < a_length)
63
    return 0;
64
  if (skip_end_space && a_length != b_length)
65
  {
66
    int swap= 1;
67
    /*
68
      We are using space compression. We have to check if longer key
69
      has next character < ' ', in which case it's less than the shorter
70
      key that has an implicite space afterwards.
71
72
      This code is identical to the one in
73
      strings/ctype-simple.c:my_strnncollsp_simple
74
    */
75
    if (a_length < b_length)
76
    {
77
      /* put shorter key in a */
78
      a_length= b_length;
79
      a= b;
80
      swap= -1;					/* swap sign of result */
81
    }
82
    for (end= a + a_length-length; a < end ; a++)
83
    {
84
      if (*a != ' ')
85
	return (*a < ' ') ? -swap : swap;
86
    }
87
    return 0;
88
  }
89
  return (int) (a_length-b_length);
90
}
91
92
93
/*
94
  Compare two keys
95
96
  SYNOPSIS
97
    ha_key_cmp()
98
    keyseg	Array of key segments of key to compare
99
    a		First key to compare, in format from _mi_pack_key()
100
		This is normally key specified by user
101
    b		Second key to compare.  This is always from a row
102
    key_length	Length of key to compare.  This can be shorter than
103
		a to just compare sub keys
104
    next_flag	How keys should be compared
105
		If bit SEARCH_FIND is not set the keys includes the row
106
		position and this should also be compared
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
107
    diff_pos    OUT Number of first keypart where values differ, counting
1 by brian
clean slate
108
                from one.
109
    diff_pos[1] OUT  (b + diff_pos[1]) points to first value in tuple b
110
                      that is different from corresponding value in tuple a.
660.1.3 by Eric Herman
removed trailing whitespace with simple script:
111
112
  EXAMPLES
1 by brian
clean slate
113
   Example1: if the function is called for tuples
114
     ('aaa','bbb') and ('eee','fff'), then
115
     diff_pos[0] = 1 (as 'aaa' != 'eee')
116
     diff_pos[1] = 0 (offset from beggining of tuple b to 'eee' keypart).
117
118
   Example2: if the index function is called for tuples
119
     ('aaa','bbb') and ('aaa','fff'),
120
     diff_pos[0] = 2 (as 'aaa' != 'eee')
121
     diff_pos[1] = 3 (offset from beggining of tuple b to 'fff' keypart,
122
                      here we assume that first key part is CHAR(3) NOT NULL)
123
124
  NOTES
125
    Number-keys can't be splited
126
127
  RETURN VALUES
128
    <0	If a < b
129
    0	If a == b
130
    >0	If a > b
131
*/
132
133
#define FCMP(A,B) ((int) (A) - (int) (B))
134
481 by Brian Aker
Remove all of uchar.
135
int ha_key_cmp(register HA_KEYSEG *keyseg, register unsigned char *a,
482 by Brian Aker
Remove uint.
136
	       register unsigned char *b, uint32_t key_length, uint32_t nextflag,
137
	       uint32_t *diff_pos)
1 by brian
clean slate
138
{
139
  int flag;
205 by Brian Aker
uint32 -> uin32_t
140
  int32_t l_1,l_2;
141
  uint32_t u_1,u_2;
1 by brian
clean slate
142
  double d_1,d_2;
482 by Brian Aker
Remove uint.
143
  uint32_t next_key_length;
481 by Brian Aker
Remove all of uchar.
144
  unsigned char *orig_b= b;
1 by brian
clean slate
145
146
  *diff_pos=0;
147
  for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
148
  {
481 by Brian Aker
Remove all of uchar.
149
    unsigned char *end;
482 by Brian Aker
Remove uint.
150
    uint32_t piks=! (keyseg->flag & HA_NO_SORT);
1 by brian
clean slate
151
    (*diff_pos)++;
152
    diff_pos[1]= (uint)(b - orig_b);
153
154
    /* Handle NULL part */
155
    if (keyseg->null_bit)
156
    {
157
      key_length--;
158
      if (*a != *b && piks)
159
      {
160
        flag = (int) *a - (int) *b;
161
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
162
      }
163
      b++;
164
      if (!*a++)                                /* If key was NULL */
165
      {
166
        if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
167
          nextflag=SEARCH_SAME;                 /* Allow duplicate keys */
168
  	else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
169
	{
170
	  /*
171
	    This is only used from mi_check() to calculate cardinality.
172
	    It can't be used when searching for a key as this would cause
173
	    compare of (a,b) and (b,a) to return the same value.
174
	  */
175
	  return -1;
176
	}
177
        next_key_length=key_length;
178
        continue;                               /* To next key part */
179
      }
180
    }
1067.4.8 by Nathan Williams
Converted all usages of cmin/cmax in plugin directory to std::min/max.
181
    end= a+ min((uint32_t)keyseg->length,key_length);
1 by brian
clean slate
182
    next_key_length=key_length-keyseg->length;
183
184
    switch ((enum ha_base_keytype) keyseg->type) {
185
    case HA_KEYTYPE_TEXT:                       /* Ascii; Key is converted */
186
      if (keyseg->flag & HA_SPACE_PACK)
187
      {
188
        int a_length,b_length,pack_length;
189
        get_key_length(a_length,a);
190
        get_key_pack_length(b_length,pack_length,b);
191
        next_key_length=key_length-b_length-pack_length;
192
193
        if (piks &&
194
            (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length,
146 by Brian Aker
my_bool cleanup.
195
				  (bool) ((nextflag & SEARCH_PREFIX) &&
1 by brian
clean slate
196
					     next_key_length <= 0),
146 by Brian Aker
my_bool cleanup.
197
				  (bool)!(nextflag & SEARCH_PREFIX))))
1 by brian
clean slate
198
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
199
        a+=a_length;
200
        b+=b_length;
201
        break;
202
      }
203
      else
204
      {
482 by Brian Aker
Remove uint.
205
	uint32_t length=(uint) (end-a), a_length=length, b_length=length;
1 by brian
clean slate
206
        if (piks &&
207
            (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length,
146 by Brian Aker
my_bool cleanup.
208
				   (bool) ((nextflag & SEARCH_PREFIX) &&
1 by brian
clean slate
209
					      next_key_length <= 0),
146 by Brian Aker
my_bool cleanup.
210
				   (bool)!(nextflag & SEARCH_PREFIX))))
1 by brian
clean slate
211
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
212
        a=end;
213
        b+=length;
214
      }
215
      break;
216
    case HA_KEYTYPE_BINARY:
217
      if (keyseg->flag & HA_SPACE_PACK)
218
      {
219
        int a_length,b_length,pack_length;
220
        get_key_length(a_length,a);
221
        get_key_pack_length(b_length,pack_length,b);
222
        next_key_length=key_length-b_length-pack_length;
223
224
        if (piks &&
225
	    (flag=compare_bin(a,a_length,b,b_length,
146 by Brian Aker
my_bool cleanup.
226
                              (bool) ((nextflag & SEARCH_PREFIX) &&
1 by brian
clean slate
227
                                         next_key_length <= 0),1)))
228
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
229
        a+=a_length;
230
        b+=b_length;
231
        break;
232
      }
233
      else
234
      {
482 by Brian Aker
Remove uint.
235
        uint32_t length=keyseg->length;
1 by brian
clean slate
236
        if (piks &&
237
	    (flag=compare_bin(a,length,b,length,
146 by Brian Aker
my_bool cleanup.
238
                              (bool) ((nextflag & SEARCH_PREFIX) &&
1 by brian
clean slate
239
                                         next_key_length <= 0),0)))
240
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
241
        a+=length;
242
        b+=length;
243
      }
244
      break;
245
    case HA_KEYTYPE_VARTEXT1:
246
    case HA_KEYTYPE_VARTEXT2:
247
      {
248
        int a_length,b_length,pack_length;
249
        get_key_length(a_length,a);
250
        get_key_pack_length(b_length,pack_length,b);
251
        next_key_length=key_length-b_length-pack_length;
252
253
        if (piks &&
254
	    (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length,
146 by Brian Aker
my_bool cleanup.
255
                                   (bool) ((nextflag & SEARCH_PREFIX) &&
1 by brian
clean slate
256
                                              next_key_length <= 0),
146 by Brian Aker
my_bool cleanup.
257
				   (bool) ((nextflag & (SEARCH_FIND |
1 by brian
clean slate
258
							   SEARCH_UPDATE)) ==
259
					      SEARCH_FIND &&
260
                                              ! (keyseg->flag &
261
                                                 HA_END_SPACE_ARE_EQUAL)))))
262
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
263
        a+= a_length;
264
        b+= b_length;
265
        break;
266
      }
267
    case HA_KEYTYPE_VARBINARY1:
268
    case HA_KEYTYPE_VARBINARY2:
269
      {
270
        int a_length,b_length,pack_length;
271
        get_key_length(a_length,a);
272
        get_key_pack_length(b_length,pack_length,b);
273
        next_key_length=key_length-b_length-pack_length;
274
275
        if (piks &&
276
	    (flag=compare_bin(a,a_length,b,b_length,
146 by Brian Aker
my_bool cleanup.
277
                              (bool) ((nextflag & SEARCH_PREFIX) &&
1 by brian
clean slate
278
                                         next_key_length <= 0), 0)))
279
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
280
        a+=a_length;
281
        b+=b_length;
282
        break;
283
      }
284
    case HA_KEYTYPE_LONG_INT:
285
      l_1= mi_sint4korr(a);
286
      l_2= mi_sint4korr(b);
287
      if (piks && (flag = CMP_NUM(l_1,l_2)))
288
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
289
      a=  end;
290
      b+= 4; /* sizeof(long int); */
291
      break;
292
    case HA_KEYTYPE_ULONG_INT:
293
      u_1= mi_sint4korr(a);
294
      u_2= mi_sint4korr(b);
295
      if (piks && (flag = CMP_NUM(u_1,u_2)))
296
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
297
      a=  end;
298
      b+= 4; /* sizeof(long int); */
299
      break;
300
    case HA_KEYTYPE_DOUBLE:
301
      mi_float8get(d_1,a);
302
      mi_float8get(d_2,b);
303
      /*
304
        The following may give a compiler warning about floating point
305
        comparison not being safe, but this is ok in this context as
306
        we are bascily doing sorting
307
      */
308
      if (piks && (flag = CMP_NUM(d_1,d_2)))
309
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
310
      a=  end;
311
      b+= 8;  /* sizeof(double); */
312
      break;
313
    case HA_KEYTYPE_LONGLONG:
314
    {
152 by Brian Aker
longlong replacement
315
      int64_t ll_a,ll_b;
1 by brian
clean slate
316
      ll_a= mi_sint8korr(a);
317
      ll_b= mi_sint8korr(b);
318
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
319
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
320
      a=  end;
321
      b+= 8;
322
      break;
323
    }
324
    case HA_KEYTYPE_ULONGLONG:
325
    {
151 by Brian Aker
Ulonglong to uint64_t
326
      uint64_t ll_a,ll_b;
1 by brian
clean slate
327
      ll_a= mi_uint8korr(a);
328
      ll_b= mi_uint8korr(b);
329
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
330
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
331
      a=  end;
332
      b+= 8;
333
      break;
334
    }
335
    case HA_KEYTYPE_END:                        /* Ready */
336
      goto end;                                 /* diff_pos is incremented */
337
    }
338
  }
339
  (*diff_pos)++;
340
end:
341
  if (!(nextflag & SEARCH_FIND))
342
  {
482 by Brian Aker
Remove uint.
343
    uint32_t i;
1 by brian
clean slate
344
    if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
345
      return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
346
    flag=0;
347
    for (i=keyseg->length ; i-- > 0 ; )
348
    {
349
      if (*a++ != *b++)
350
      {
351
        flag= FCMP(a[-1],b[-1]);
352
        break;
353
      }
354
    }
355
    if (nextflag & SEARCH_SAME)
356
      return (flag);                            /* read same */
357
    if (nextflag & SEARCH_BIGGER)
358
      return (flag <= 0 ? -1 : 1);              /* read next */
359
    return (flag < 0 ? -1 : 1);                 /* read previous */
360
  }
361
  return 0;
362
} /* ha_key_cmp */
363
364
365
/*
366
  Find the first NULL value in index-suffix values tuple
367
368
  SYNOPSIS
369
    ha_find_null()
370
      keyseg     Array of keyparts for key suffix
371
      a          Key suffix value tuple
372
373
  DESCRIPTION
374
    Find the first NULL value in index-suffix values tuple.
375
376
  TODO
377
    Consider optimizing this function or its use so we don't search for
378
    NULL values in completely NOT NULL index suffixes.
379
380
  RETURN
381
    First key part that has NULL as value in values tuple, or the last key
382
    part (with keyseg->type==HA_TYPE_END) if values tuple doesn't contain
383
    NULLs.
384
*/
385
481 by Brian Aker
Remove all of uchar.
386
HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, unsigned char *a)
1 by brian
clean slate
387
{
388
  for (; (enum ha_base_keytype) keyseg->type != HA_KEYTYPE_END; keyseg++)
389
  {
481 by Brian Aker
Remove all of uchar.
390
    unsigned char *end;
1 by brian
clean slate
391
    if (keyseg->null_bit)
392
    {
393
      if (!*a++)
394
        return keyseg;
395
    }
396
    end= a+ keyseg->length;
397
398
    switch ((enum ha_base_keytype) keyseg->type) {
399
    case HA_KEYTYPE_TEXT:
400
    case HA_KEYTYPE_BINARY:
401
      if (keyseg->flag & HA_SPACE_PACK)
402
      {
403
        int a_length;
404
        get_key_length(a_length, a);
405
        a += a_length;
406
        break;
407
      }
408
      else
409
        a= end;
410
      break;
411
    case HA_KEYTYPE_VARTEXT1:
412
    case HA_KEYTYPE_VARTEXT2:
413
    case HA_KEYTYPE_VARBINARY1:
414
    case HA_KEYTYPE_VARBINARY2:
415
      {
416
        int a_length;
417
        get_key_length(a_length, a);
418
        a+= a_length;
419
        break;
420
      }
421
    case HA_KEYTYPE_LONG_INT:
422
    case HA_KEYTYPE_ULONG_INT:
423
    case HA_KEYTYPE_LONGLONG:
424
    case HA_KEYTYPE_ULONGLONG:
425
    case HA_KEYTYPE_DOUBLE:
426
      a= end;
427
      break;
971.6.11 by Eric Day
Removed purecov messages.
428
    case HA_KEYTYPE_END:
1 by brian
clean slate
429
      /* keep compiler happy */
51.3.20 by Jay Pipes
Phase 6 - Remove DBUG from mysys
430
      assert(0);
1 by brian
clean slate
431
      break;
432
    }
433
  }
434
  return keyseg;
435
}
436
437
438