~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
 *
4
 *  Copyright (C) 2008 Sun Microsystems
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
1241.9.1 by Monty Taylor
Removed global.h. Fixed all the headers.
20
#include "config.h"
212.5.39 by Monty Taylor
Phew. Moved my_base and my_global.
21
1241.9.61 by Monty Taylor
No more mystrings in drizzled/
22
#include "drizzled/charset_info.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>
1241.9.64 by Monty Taylor
Moved remaining non-public portions of mysys and mystrings to drizzled/internal.
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
482 by Brian Aker
Remove uint.
40
int ha_compare_text(const CHARSET_INFO * const charset_info, unsigned char *a, uint32_t a_length,
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_UINT24:
301
      l_1=mi_uint3korr(a);
302
      l_2=mi_uint3korr(b);
303
      if (piks && (flag = CMP_NUM(l_1,l_2)))
304
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
305
      a=  end;
306
      b+= 3;
307
      break;
308
    case HA_KEYTYPE_DOUBLE:
309
      mi_float8get(d_1,a);
310
      mi_float8get(d_2,b);
311
      /*
312
        The following may give a compiler warning about floating point
313
        comparison not being safe, but this is ok in this context as
314
        we are bascily doing sorting
315
      */
316
      if (piks && (flag = CMP_NUM(d_1,d_2)))
317
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
318
      a=  end;
319
      b+= 8;  /* sizeof(double); */
320
      break;
321
    case HA_KEYTYPE_LONGLONG:
322
    {
152 by Brian Aker
longlong replacement
323
      int64_t ll_a,ll_b;
1 by brian
clean slate
324
      ll_a= mi_sint8korr(a);
325
      ll_b= mi_sint8korr(b);
326
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
327
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
328
      a=  end;
329
      b+= 8;
330
      break;
331
    }
332
    case HA_KEYTYPE_ULONGLONG:
333
    {
151 by Brian Aker
Ulonglong to uint64_t
334
      uint64_t ll_a,ll_b;
1 by brian
clean slate
335
      ll_a= mi_uint8korr(a);
336
      ll_b= mi_uint8korr(b);
337
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
338
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
339
      a=  end;
340
      b+= 8;
341
      break;
342
    }
343
    case HA_KEYTYPE_END:                        /* Ready */
344
      goto end;                                 /* diff_pos is incremented */
345
    }
346
  }
347
  (*diff_pos)++;
348
end:
349
  if (!(nextflag & SEARCH_FIND))
350
  {
482 by Brian Aker
Remove uint.
351
    uint32_t i;
1 by brian
clean slate
352
    if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
353
      return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
354
    flag=0;
355
    for (i=keyseg->length ; i-- > 0 ; )
356
    {
357
      if (*a++ != *b++)
358
      {
359
        flag= FCMP(a[-1],b[-1]);
360
        break;
361
      }
362
    }
363
    if (nextflag & SEARCH_SAME)
364
      return (flag);                            /* read same */
365
    if (nextflag & SEARCH_BIGGER)
366
      return (flag <= 0 ? -1 : 1);              /* read next */
367
    return (flag < 0 ? -1 : 1);                 /* read previous */
368
  }
369
  return 0;
370
} /* ha_key_cmp */
371
372
373
/*
374
  Find the first NULL value in index-suffix values tuple
375
376
  SYNOPSIS
377
    ha_find_null()
378
      keyseg     Array of keyparts for key suffix
379
      a          Key suffix value tuple
380
381
  DESCRIPTION
382
    Find the first NULL value in index-suffix values tuple.
383
384
  TODO
385
    Consider optimizing this function or its use so we don't search for
386
    NULL values in completely NOT NULL index suffixes.
387
388
  RETURN
389
    First key part that has NULL as value in values tuple, or the last key
390
    part (with keyseg->type==HA_TYPE_END) if values tuple doesn't contain
391
    NULLs.
392
*/
393
481 by Brian Aker
Remove all of uchar.
394
HA_KEYSEG *ha_find_null(HA_KEYSEG *keyseg, unsigned char *a)
1 by brian
clean slate
395
{
396
  for (; (enum ha_base_keytype) keyseg->type != HA_KEYTYPE_END; keyseg++)
397
  {
481 by Brian Aker
Remove all of uchar.
398
    unsigned char *end;
1 by brian
clean slate
399
    if (keyseg->null_bit)
400
    {
401
      if (!*a++)
402
        return keyseg;
403
    }
404
    end= a+ keyseg->length;
405
406
    switch ((enum ha_base_keytype) keyseg->type) {
407
    case HA_KEYTYPE_TEXT:
408
    case HA_KEYTYPE_BINARY:
409
      if (keyseg->flag & HA_SPACE_PACK)
410
      {
411
        int a_length;
412
        get_key_length(a_length, a);
413
        a += a_length;
414
        break;
415
      }
416
      else
417
        a= end;
418
      break;
419
    case HA_KEYTYPE_VARTEXT1:
420
    case HA_KEYTYPE_VARTEXT2:
421
    case HA_KEYTYPE_VARBINARY1:
422
    case HA_KEYTYPE_VARBINARY2:
423
      {
424
        int a_length;
425
        get_key_length(a_length, a);
426
        a+= a_length;
427
        break;
428
      }
429
    case HA_KEYTYPE_LONG_INT:
430
    case HA_KEYTYPE_ULONG_INT:
431
    case HA_KEYTYPE_UINT24:
432
    case HA_KEYTYPE_LONGLONG:
433
    case HA_KEYTYPE_ULONGLONG:
434
    case HA_KEYTYPE_DOUBLE:
435
      a= end;
436
      break;
971.6.11 by Eric Day
Removed purecov messages.
437
    case HA_KEYTYPE_END:
1 by brian
clean slate
438
      /* keep compiler happy */
51.3.20 by Jay Pipes
Phase 6 - Remove DBUG from mysys
439
      assert(0);
1 by brian
clean slate
440
      break;
441
    }
442
  }
443
  return keyseg;
444
}
445
446
447