~ubuntu-branches/ubuntu/natty/mysql-5.1/natty-proposed

« back to all changes in this revision

Viewing changes to mysys/my_compare.c

  • Committer: Package Import Robot
  • Author(s): Marc Deslauriers
  • Date: 2012-02-22 08:30:45 UTC
  • mfrom: (1.4.1)
  • Revision ID: package-import@ubuntu.com-20120222083045-2rd53r4bnyx7qus4
Tags: 5.1.61-0ubuntu0.11.04.1
* SECURITY UPDATE: Update to 5.1.61 to fix multiple security issues
  (LP: #937869)
  - http://www.oracle.com/technetwork/topics/security/cpujan2012-366304.html
  - CVE-2011-2262
  - CVE-2012-0075
  - CVE-2012-0112
  - CVE-2012-0113
  - CVE-2012-0114
  - CVE-2012-0115
  - CVE-2012-0116
  - CVE-2012-0117
  - CVE-2012-0118
  - CVE-2012-0119
  - CVE-2012-0120
  - CVE-2012-0484
  - CVE-2012-0485
  - CVE-2012-0486
  - CVE-2012-0487
  - CVE-2012-0488
  - CVE-2012-0489
  - CVE-2012-0490
  - CVE-2012-0491
  - CVE-2012-0492
  - CVE-2012-0493
  - CVE-2012-0494
  - CVE-2012-0495
  - CVE-2012-0496

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (c) 2011, Oracle and/or its affiliates. All rights reserved.
 
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
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include "my_compare.h"
 
17
 
 
18
int ha_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
 
19
                    uchar *b, uint b_length, my_bool part_key,
 
20
                    my_bool skip_end_space)
 
21
{
 
22
  if (!part_key)
 
23
    return charset_info->coll->strnncollsp(charset_info, a, a_length,
 
24
                                           b, b_length, (my_bool)!skip_end_space);
 
25
  return charset_info->coll->strnncoll(charset_info, a, a_length,
 
26
                                       b, b_length, part_key);
 
27
}
 
28
 
 
29
 
 
30
static int compare_bin(uchar *a, uint a_length, uchar *b, uint b_length,
 
31
                       my_bool part_key, my_bool skip_end_space)
 
32
{
 
33
  uint length= min(a_length,b_length);
 
34
  uchar *end= a+ length;
 
35
  int flag;
 
36
 
 
37
  while (a < end)
 
38
    if ((flag= (int) *a++ - (int) *b++))
 
39
      return flag;
 
40
  if (part_key && b_length < a_length)
 
41
    return 0;
 
42
  if (skip_end_space && a_length != b_length)
 
43
  {
 
44
    int swap= 1;
 
45
    /*
 
46
      We are using space compression. We have to check if longer key
 
47
      has next character < ' ', in which case it's less than the shorter
 
48
      key that has an implicite space afterwards.
 
49
 
 
50
      This code is identical to the one in
 
51
      strings/ctype-simple.c:my_strnncollsp_simple
 
52
    */
 
53
    if (a_length < b_length)
 
54
    {
 
55
      /* put shorter key in a */
 
56
      a_length= b_length;
 
57
      a= b;
 
58
      swap= -1;                                 /* swap sign of result */
 
59
    }
 
60
    for (end= a + a_length-length; a < end ; a++)
 
61
    {
 
62
      if (*a != ' ')
 
63
        return (*a < ' ') ? -swap : swap;
 
64
    }
 
65
    return 0;
 
66
  }
 
67
  return (int) (a_length-b_length);
 
68
}
 
69
 
 
70
 
 
71
/*
 
72
  Compare two keys
 
73
 
 
74
  SYNOPSIS
 
75
    ha_key_cmp()
 
76
    keyseg      Array of key segments of key to compare
 
77
    a           First key to compare, in format from _mi_pack_key()
 
78
                This is normally key specified by user
 
79
    b           Second key to compare.  This is always from a row
 
80
    key_length  Length of key to compare.  This can be shorter than
 
81
                a to just compare sub keys
 
82
    next_flag   How keys should be compared
 
83
                If bit SEARCH_FIND is not set the keys includes the row
 
84
                position and this should also be compared
 
85
    diff_pos    OUT Number of first keypart where values differ, counting 
 
86
                from one.
 
87
    diff_pos[1] OUT  (b + diff_pos[1]) points to first value in tuple b
 
88
                      that is different from corresponding value in tuple a.
 
89
  
 
90
  EXAMPLES 
 
91
   Example1: if the function is called for tuples
 
92
     ('aaa','bbb') and ('eee','fff'), then
 
93
     diff_pos[0] = 1 (as 'aaa' != 'eee')
 
94
     diff_pos[1] = 0 (offset from beggining of tuple b to 'eee' keypart).
 
95
 
 
96
   Example2: if the index function is called for tuples
 
97
     ('aaa','bbb') and ('aaa','fff'),
 
98
     diff_pos[0] = 2 (as 'aaa' != 'eee')
 
99
     diff_pos[1] = 3 (offset from beggining of tuple b to 'fff' keypart,
 
100
                      here we assume that first key part is CHAR(3) NOT NULL)
 
101
 
 
102
  NOTES
 
103
    Number-keys can't be splited
 
104
 
 
105
  RETURN VALUES
 
106
    <0  If a < b
 
107
    0   If a == b
 
108
    >0  If a > b
 
109
*/
 
110
 
 
111
#define FCMP(A,B) ((int) (A) - (int) (B))
 
112
 
 
113
int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
 
114
               register uchar *b, uint key_length, uint nextflag,
 
115
               uint *diff_pos)
 
116
{
 
117
  int flag;
 
118
  int16 s_1,s_2;
 
119
  int32 l_1,l_2;
 
120
  uint32 u_1,u_2;
 
121
  float f_1,f_2;
 
122
  double d_1,d_2;
 
123
  uint next_key_length;
 
124
  uchar *orig_b= b;
 
125
 
 
126
  *diff_pos=0;
 
127
  for ( ; (int) key_length >0 ; key_length=next_key_length, keyseg++)
 
128
  {
 
129
    uchar *end;
 
130
    uint piks=! (keyseg->flag & HA_NO_SORT);
 
131
    (*diff_pos)++;
 
132
    diff_pos[1]= (uint)(b - orig_b);
 
133
 
 
134
    /* Handle NULL part */
 
135
    if (keyseg->null_bit)
 
136
    {
 
137
      key_length--;
 
138
      if (*a != *b && piks)
 
139
      {
 
140
        flag = (int) *a - (int) *b;
 
141
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
142
      }
 
143
      b++;
 
144
      if (!*a++)                                /* If key was NULL */
 
145
      {
 
146
        if (nextflag == (SEARCH_FIND | SEARCH_UPDATE))
 
147
          nextflag=SEARCH_SAME;                 /* Allow duplicate keys */
 
148
        else if (nextflag & SEARCH_NULL_ARE_NOT_EQUAL)
 
149
        {
 
150
          /*
 
151
            This is only used from mi_check() to calculate cardinality.
 
152
            It can't be used when searching for a key as this would cause
 
153
            compare of (a,b) and (b,a) to return the same value.
 
154
          */
 
155
          return -1;
 
156
        }
 
157
        next_key_length=key_length;
 
158
        continue;                               /* To next key part */
 
159
      }
 
160
    }
 
161
    end= a+ min(keyseg->length,key_length);
 
162
    next_key_length=key_length-keyseg->length;
 
163
 
 
164
    switch ((enum ha_base_keytype) keyseg->type) {
 
165
    case HA_KEYTYPE_TEXT:                       /* Ascii; Key is converted */
 
166
      if (keyseg->flag & HA_SPACE_PACK)
 
167
      {
 
168
        int a_length,b_length,pack_length;
 
169
        get_key_length(a_length,a);
 
170
        get_key_pack_length(b_length,pack_length,b);
 
171
        next_key_length=key_length-b_length-pack_length;
 
172
 
 
173
        if (piks &&
 
174
            (flag=ha_compare_text(keyseg->charset,a,a_length,b,b_length,
 
175
                                  (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
176
                                             next_key_length <= 0),
 
177
                                  (my_bool)!(nextflag & SEARCH_PREFIX))))
 
178
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
179
        a+=a_length;
 
180
        b+=b_length;
 
181
        break;
 
182
      }
 
183
      else
 
184
      {
 
185
        uint length=(uint) (end-a), a_length=length, b_length=length;
 
186
        if (piks &&
 
187
            (flag= ha_compare_text(keyseg->charset, a, a_length, b, b_length,
 
188
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
189
                                              next_key_length <= 0),
 
190
                                   (my_bool)!(nextflag & SEARCH_PREFIX))))
 
191
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
192
        a=end;
 
193
        b+=length;
 
194
      }
 
195
      break;
 
196
    case HA_KEYTYPE_BINARY:
 
197
    case HA_KEYTYPE_BIT:
 
198
      if (keyseg->flag & HA_SPACE_PACK)
 
199
      {
 
200
        int a_length,b_length,pack_length;
 
201
        get_key_length(a_length,a);
 
202
        get_key_pack_length(b_length,pack_length,b);
 
203
        next_key_length=key_length-b_length-pack_length;
 
204
 
 
205
        if (piks &&
 
206
            (flag=compare_bin(a,a_length,b,b_length,
 
207
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
208
                                         next_key_length <= 0),1)))
 
209
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
210
        a+=a_length;
 
211
        b+=b_length;
 
212
        break;
 
213
      }
 
214
      else
 
215
      {
 
216
        uint length=keyseg->length;
 
217
        if (piks &&
 
218
            (flag=compare_bin(a,length,b,length,
 
219
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
220
                                         next_key_length <= 0),0)))
 
221
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
222
        a+=length;
 
223
        b+=length;
 
224
      }
 
225
      break;
 
226
    case HA_KEYTYPE_VARTEXT1:
 
227
    case HA_KEYTYPE_VARTEXT2:
 
228
      {
 
229
        int a_length,b_length,pack_length;
 
230
        get_key_length(a_length,a);
 
231
        get_key_pack_length(b_length,pack_length,b);
 
232
        next_key_length=key_length-b_length-pack_length;
 
233
 
 
234
        if (piks &&
 
235
            (flag= ha_compare_text(keyseg->charset,a,a_length,b,b_length,
 
236
                                   (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
237
                                              next_key_length <= 0),
 
238
                                   (my_bool) ((nextflag & (SEARCH_FIND |
 
239
                                                           SEARCH_UPDATE)) ==
 
240
                                              SEARCH_FIND &&
 
241
                                              ! (keyseg->flag &
 
242
                                                 HA_END_SPACE_ARE_EQUAL)))))
 
243
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
244
        a+= a_length;
 
245
        b+= b_length;
 
246
        break;
 
247
      }
 
248
      break;
 
249
    case HA_KEYTYPE_VARBINARY1:
 
250
    case HA_KEYTYPE_VARBINARY2:
 
251
      {
 
252
        int a_length,b_length,pack_length;
 
253
        get_key_length(a_length,a);
 
254
        get_key_pack_length(b_length,pack_length,b);
 
255
        next_key_length=key_length-b_length-pack_length;
 
256
 
 
257
        if (piks &&
 
258
            (flag=compare_bin(a,a_length,b,b_length,
 
259
                              (my_bool) ((nextflag & SEARCH_PREFIX) &&
 
260
                                         next_key_length <= 0), 0)))
 
261
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
262
        a+=a_length;
 
263
        b+=b_length;
 
264
        break;
 
265
      }
 
266
      break;
 
267
    case HA_KEYTYPE_INT8:
 
268
    {
 
269
      int i_1= (int) *((signed char*) a);
 
270
      int i_2= (int) *((signed char*) b);
 
271
      if (piks && (flag = CMP_NUM(i_1,i_2)))
 
272
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
273
      a= end;
 
274
      b++;
 
275
      break;
 
276
    }
 
277
    case HA_KEYTYPE_SHORT_INT:
 
278
      s_1= mi_sint2korr(a);
 
279
      s_2= mi_sint2korr(b);
 
280
      if (piks && (flag = CMP_NUM(s_1,s_2)))
 
281
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
282
      a=  end;
 
283
      b+= 2; /* sizeof(short int); */
 
284
      break;
 
285
    case HA_KEYTYPE_USHORT_INT:
 
286
      {
 
287
        uint16 us_1,us_2;
 
288
        us_1= mi_sint2korr(a);
 
289
        us_2= mi_sint2korr(b);
 
290
        if (piks && (flag = CMP_NUM(us_1,us_2)))
 
291
          return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
292
        a=  end;
 
293
        b+=2; /* sizeof(short int); */
 
294
        break;
 
295
      }
 
296
    case HA_KEYTYPE_LONG_INT:
 
297
      l_1= mi_sint4korr(a);
 
298
      l_2= mi_sint4korr(b);
 
299
      if (piks && (flag = CMP_NUM(l_1,l_2)))
 
300
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
301
      a=  end;
 
302
      b+= 4; /* sizeof(long int); */
 
303
      break;
 
304
    case HA_KEYTYPE_ULONG_INT:
 
305
      u_1= mi_sint4korr(a);
 
306
      u_2= mi_sint4korr(b);
 
307
      if (piks && (flag = CMP_NUM(u_1,u_2)))
 
308
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
309
      a=  end;
 
310
      b+= 4; /* sizeof(long int); */
 
311
      break;
 
312
    case HA_KEYTYPE_INT24:
 
313
      l_1=mi_sint3korr(a);
 
314
      l_2=mi_sint3korr(b);
 
315
      if (piks && (flag = CMP_NUM(l_1,l_2)))
 
316
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
317
      a=  end;
 
318
      b+= 3;
 
319
      break;
 
320
    case HA_KEYTYPE_UINT24:
 
321
      l_1=mi_uint3korr(a);
 
322
      l_2=mi_uint3korr(b);
 
323
      if (piks && (flag = CMP_NUM(l_1,l_2)))
 
324
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
325
      a=  end;
 
326
      b+= 3;
 
327
      break;
 
328
    case HA_KEYTYPE_FLOAT:
 
329
      mi_float4get(f_1,a);
 
330
      mi_float4get(f_2,b);
 
331
      /*
 
332
        The following may give a compiler warning about floating point
 
333
        comparison not being safe, but this is ok in this context as
 
334
        we are bascily doing sorting
 
335
      */
 
336
      if (piks && (flag = CMP_NUM(f_1,f_2)))
 
337
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
338
      a=  end;
 
339
      b+= 4; /* sizeof(float); */
 
340
      break;
 
341
    case HA_KEYTYPE_DOUBLE:
 
342
      mi_float8get(d_1,a);
 
343
      mi_float8get(d_2,b);
 
344
      /*
 
345
        The following may give a compiler warning about floating point
 
346
        comparison not being safe, but this is ok in this context as
 
347
        we are bascily doing sorting
 
348
      */
 
349
      if (piks && (flag = CMP_NUM(d_1,d_2)))
 
350
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
351
      a=  end;
 
352
      b+= 8;  /* sizeof(double); */
 
353
      break;
 
354
    case HA_KEYTYPE_NUM:                                /* Numeric key */
 
355
    {
 
356
      int swap_flag= 0;
 
357
      int alength,blength;
 
358
 
 
359
      if (keyseg->flag & HA_REVERSE_SORT)
 
360
      {
 
361
        swap_variables(uchar*, a, b);
 
362
        swap_flag=1;                            /* Remember swap of a & b */
 
363
        end= a+ (int) (end-b);
 
364
      }
 
365
      if (keyseg->flag & HA_SPACE_PACK)
 
366
      {
 
367
        alength= *a++; blength= *b++;
 
368
        end=a+alength;
 
369
        next_key_length=key_length-blength-1;
 
370
      }
 
371
      else
 
372
      {
 
373
        alength= (int) (end-a);
 
374
        blength=keyseg->length;
 
375
        /* remove pre space from keys */
 
376
        for ( ; alength && *a == ' ' ; a++, alength--) ;
 
377
        for ( ; blength && *b == ' ' ; b++, blength--) ;
 
378
      }
 
379
      if (piks)
 
380
      {
 
381
        if (*a == '-')
 
382
        {
 
383
          if (*b != '-')
 
384
            return -1;
 
385
          a++; b++;
 
386
          swap_variables(uchar*, a, b);
 
387
          swap_variables(int, alength, blength);
 
388
          swap_flag=1-swap_flag;
 
389
          alength--; blength--;
 
390
          end=a+alength;
 
391
        }
 
392
        else if (*b == '-')
 
393
          return 1;
 
394
        while (alength && (*a == '+' || *a == '0'))
 
395
        {
 
396
          a++; alength--;
 
397
        }
 
398
        while (blength && (*b == '+' || *b == '0'))
 
399
        {
 
400
          b++; blength--;
 
401
        }
 
402
        if (alength != blength)
 
403
          return (alength < blength) ? -1 : 1;
 
404
        while (a < end)
 
405
          if (*a++ !=  *b++)
 
406
            return ((int) a[-1] - (int) b[-1]);
 
407
      }
 
408
      else
 
409
      {
 
410
        b+=(end-a);
 
411
        a=end;
 
412
      }
 
413
 
 
414
      if (swap_flag)                            /* Restore pointers */
 
415
        swap_variables(uchar*, a, b);
 
416
      break;
 
417
    }
 
418
#ifdef HAVE_LONG_LONG
 
419
    case HA_KEYTYPE_LONGLONG:
 
420
    {
 
421
      longlong ll_a,ll_b;
 
422
      ll_a= mi_sint8korr(a);
 
423
      ll_b= mi_sint8korr(b);
 
424
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
 
425
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
426
      a=  end;
 
427
      b+= 8;
 
428
      break;
 
429
    }
 
430
    case HA_KEYTYPE_ULONGLONG:
 
431
    {
 
432
      ulonglong ll_a,ll_b;
 
433
      ll_a= mi_uint8korr(a);
 
434
      ll_b= mi_uint8korr(b);
 
435
      if (piks && (flag = CMP_NUM(ll_a,ll_b)))
 
436
        return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
 
437
      a=  end;
 
438
      b+= 8;
 
439
      break;
 
440
    }
 
441
#endif
 
442
    case HA_KEYTYPE_END:                        /* Ready */
 
443
      goto end;                                 /* diff_pos is incremented */
 
444
    }
 
445
  }
 
446
  (*diff_pos)++;
 
447
end:
 
448
  if (!(nextflag & SEARCH_FIND))
 
449
  {
 
450
    uint i;
 
451
    if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
 
452
      return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
 
453
    flag=0;
 
454
    for (i=keyseg->length ; i-- > 0 ; )
 
455
    {
 
456
      if (*a++ != *b++)
 
457
      {
 
458
        flag= FCMP(a[-1],b[-1]);
 
459
        break;
 
460
      }
 
461
    }
 
462
    if (nextflag & SEARCH_SAME)
 
463
      return (flag);                            /* read same */
 
464
    if (nextflag & SEARCH_BIGGER)
 
465
      return (flag <= 0 ? -1 : 1);              /* read next */
 
466
    return (flag < 0 ? -1 : 1);                 /* read previous */
 
467
  }
 
468
  return 0;
 
469
} /* ha_key_cmp */