~ubuntu-branches/ubuntu/precise/mysql-5.1/precise

« back to all changes in this revision

Viewing changes to storage/ndb/src/common/util/NdbSqlUtil.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Norbert Tretkowski
  • Date: 2010-03-17 14:56:02 UTC
  • Revision ID: james.westby@ubuntu.com-20100317145602-x7e30l1b2sb5s6w6
Tags: upstream-5.1.45
ImportĀ upstreamĀ versionĀ 5.1.45

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* Copyright (C) 2003 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
 
14
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 
15
 
 
16
#include <NdbSqlUtil.hpp>
 
17
#include <NdbOut.hpp>
 
18
#include <my_sys.h>
 
19
 
 
20
/*
 
21
 * Data types.  The entries must be in the numerical order.
 
22
 */
 
23
 
 
24
const NdbSqlUtil::Type
 
25
NdbSqlUtil::m_typeList[] = {
 
26
  { // 0
 
27
    Type::Undefined,
 
28
    NULL,
 
29
    NULL
 
30
  },
 
31
  { // 1
 
32
    Type::Tinyint,
 
33
    cmpTinyint,
 
34
    NULL
 
35
  },
 
36
  { // 2
 
37
    Type::Tinyunsigned,
 
38
    cmpTinyunsigned,
 
39
    NULL
 
40
  },
 
41
  { // 3
 
42
    Type::Smallint,
 
43
    cmpSmallint,
 
44
    NULL
 
45
  },
 
46
  { // 4
 
47
    Type::Smallunsigned,
 
48
    cmpSmallunsigned,
 
49
    NULL
 
50
  },
 
51
  { // 5
 
52
    Type::Mediumint,
 
53
    cmpMediumint,
 
54
    NULL
 
55
  },
 
56
  { // 6
 
57
    Type::Mediumunsigned,
 
58
    cmpMediumunsigned,
 
59
    NULL
 
60
  },
 
61
  { // 7
 
62
    Type::Int,
 
63
    cmpInt,
 
64
    NULL
 
65
  },
 
66
  { // 8
 
67
    Type::Unsigned,
 
68
    cmpUnsigned,
 
69
    NULL
 
70
  },
 
71
  { // 9
 
72
    Type::Bigint,
 
73
    cmpBigint,
 
74
    NULL
 
75
  },
 
76
  { // 10
 
77
    Type::Bigunsigned,
 
78
    cmpBigunsigned,
 
79
    NULL
 
80
  },
 
81
  { // 11
 
82
    Type::Float,
 
83
    cmpFloat,
 
84
    NULL
 
85
  },
 
86
  { // 12
 
87
    Type::Double,
 
88
    cmpDouble,
 
89
    NULL
 
90
  },
 
91
  { // 13
 
92
    Type::Olddecimal,
 
93
    cmpOlddecimal,
 
94
    NULL
 
95
  },
 
96
  { // 14
 
97
    Type::Char,
 
98
    cmpChar,
 
99
    likeChar
 
100
  },
 
101
  { // 15
 
102
    Type::Varchar,
 
103
    cmpVarchar,
 
104
    likeVarchar
 
105
  },
 
106
  { // 16
 
107
    Type::Binary,
 
108
    cmpBinary,
 
109
    likeBinary
 
110
  },
 
111
  { // 17
 
112
    Type::Varbinary,
 
113
    cmpVarbinary,
 
114
    likeVarbinary
 
115
  },
 
116
  { // 18
 
117
    Type::Datetime,
 
118
    cmpDatetime,
 
119
    NULL
 
120
  },
 
121
  { // 19
 
122
    Type::Date,
 
123
    cmpDate,
 
124
    NULL
 
125
  },
 
126
  { // 20
 
127
    Type::Blob,
 
128
    NULL,
 
129
    NULL
 
130
  },
 
131
  { // 21
 
132
    Type::Text,
 
133
    NULL,
 
134
    NULL
 
135
  },
 
136
  { // 22
 
137
    Type::Bit,
 
138
    cmpBit,
 
139
    NULL
 
140
  },
 
141
  { // 23
 
142
    Type::Longvarchar,
 
143
    cmpLongvarchar,
 
144
    likeLongvarchar
 
145
  },
 
146
  { // 24
 
147
    Type::Longvarbinary,
 
148
    cmpLongvarbinary,
 
149
    likeLongvarbinary
 
150
  },
 
151
  { // 25
 
152
    Type::Time,
 
153
    cmpTime,
 
154
    NULL
 
155
  },
 
156
  { // 26
 
157
    Type::Year,
 
158
    cmpYear,
 
159
    NULL
 
160
  },
 
161
  { // 27
 
162
    Type::Timestamp,
 
163
    cmpTimestamp,
 
164
    NULL
 
165
  },
 
166
  { // 28
 
167
    Type::Olddecimalunsigned,
 
168
    cmpOlddecimalunsigned,
 
169
    NULL
 
170
  },
 
171
  { // 29
 
172
    Type::Decimal,
 
173
    cmpDecimal,
 
174
    NULL
 
175
  },
 
176
  { // 30
 
177
    Type::Decimalunsigned,
 
178
    cmpDecimalunsigned,
 
179
    NULL
 
180
  }
 
181
};
 
182
 
 
183
const NdbSqlUtil::Type&
 
184
NdbSqlUtil::getType(Uint32 typeId)
 
185
{
 
186
  if (typeId < sizeof(m_typeList) / sizeof(m_typeList[0]) &&
 
187
      m_typeList[typeId].m_typeId != Type::Undefined) {
 
188
    return m_typeList[typeId];
 
189
  }
 
190
  return m_typeList[Type::Undefined];
 
191
}
 
192
 
 
193
const NdbSqlUtil::Type&
 
194
NdbSqlUtil::getTypeBinary(Uint32 typeId)
 
195
{
 
196
  switch (typeId) {
 
197
  case Type::Char:
 
198
  case Type::Varchar:
 
199
  case Type::Binary:
 
200
  case Type::Varbinary:
 
201
  case Type::Longvarchar:
 
202
  case Type::Longvarbinary:
 
203
    typeId = Type::Binary;
 
204
    break;
 
205
  case Type::Text:
 
206
    typeId = Type::Blob;
 
207
    break;
 
208
  default:
 
209
    break;
 
210
  }
 
211
  return getType(typeId);
 
212
}
 
213
 
 
214
/*
 
215
 * Comparison functions.
 
216
 */
 
217
 
 
218
int
 
219
NdbSqlUtil::cmpTinyint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
220
{
 
221
  if (n2 >= sizeof(Int8)) {
 
222
    Int8 v1, v2;
 
223
    memcpy(&v1, p1, sizeof(Int8));
 
224
    memcpy(&v2, p2, sizeof(Int8));
 
225
    if (v1 < v2)
 
226
      return -1;
 
227
    if (v1 > v2)
 
228
      return +1;
 
229
    return 0;
 
230
  }
 
231
  assert(! full);
 
232
  return CmpUnknown;
 
233
}
 
234
 
 
235
int
 
236
NdbSqlUtil::cmpTinyunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
237
{
 
238
  if (n2 >= sizeof(Uint8)) {
 
239
    Uint8 v1, v2;
 
240
    memcpy(&v1, p1, sizeof(Uint8));
 
241
    memcpy(&v2, p2, sizeof(Uint8));
 
242
    if (v1 < v2)
 
243
      return -1;
 
244
    if (v1 > v2)
 
245
      return +1;
 
246
    return 0;
 
247
  }
 
248
  assert(! full);
 
249
  return CmpUnknown;
 
250
}
 
251
 
 
252
int
 
253
NdbSqlUtil::cmpSmallint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
254
{
 
255
  if (n2 >= sizeof(Int16)) {
 
256
    Int16 v1, v2;
 
257
    memcpy(&v1, p1, sizeof(Int16));
 
258
    memcpy(&v2, p2, sizeof(Int16));
 
259
    if (v1 < v2)
 
260
      return -1;
 
261
    if (v1 > v2)
 
262
      return +1;
 
263
    return 0;
 
264
  }
 
265
  assert(! full);
 
266
  return CmpUnknown;
 
267
}
 
268
 
 
269
int
 
270
NdbSqlUtil::cmpSmallunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
271
{
 
272
  if (n2 >= sizeof(Uint16)) {
 
273
    Uint16 v1, v2;
 
274
    memcpy(&v1, p1, sizeof(Uint16));
 
275
    memcpy(&v2, p2, sizeof(Uint16));
 
276
    if (v1 < v2)
 
277
      return -1;
 
278
    if (v1 > v2)
 
279
      return +1;
 
280
    return 0;
 
281
  }
 
282
  assert(! full);
 
283
  return CmpUnknown;
 
284
}
 
285
 
 
286
int
 
287
NdbSqlUtil::cmpMediumint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
288
{
 
289
  if (n2 >= 3) {
 
290
    Int32 v1, v2;
 
291
    v1 = sint3korr((const uchar*)p1);
 
292
    v2 = sint3korr((const uchar*)p2);
 
293
    if (v1 < v2)
 
294
      return -1;
 
295
    if (v1 > v2)
 
296
      return +1;
 
297
    return 0;
 
298
  }
 
299
  assert(! full);
 
300
  return CmpUnknown;
 
301
}
 
302
 
 
303
int
 
304
NdbSqlUtil::cmpMediumunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
305
{
 
306
  if (n2 >= 3) {
 
307
    Uint32 v1, v2;
 
308
    v1 = uint3korr((const uchar*)p1);
 
309
    v2 = uint3korr((const uchar*)p2);
 
310
    if (v1 < v2)
 
311
      return -1;
 
312
    if (v1 > v2)
 
313
      return +1;
 
314
    return 0;
 
315
  }
 
316
  assert(! full);
 
317
  return CmpUnknown;
 
318
}
 
319
 
 
320
int
 
321
NdbSqlUtil::cmpInt(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
322
{
 
323
  if (n2 >= sizeof(Int32)) {
 
324
    Int32 v1, v2;
 
325
    memcpy(&v1, p1, sizeof(Int32));
 
326
    memcpy(&v2, p2, sizeof(Int32));
 
327
    if (v1 < v2)
 
328
      return -1;
 
329
    if (v1 > v2)
 
330
      return +1;
 
331
    return 0;
 
332
  }
 
333
  assert(! full);
 
334
  return CmpUnknown;
 
335
}
 
336
 
 
337
int
 
338
NdbSqlUtil::cmpUnsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
339
{
 
340
  if (n2 >= sizeof(Uint32)) {
 
341
    Uint32 v1, v2;
 
342
    memcpy(&v1, p1, sizeof(Uint32));
 
343
    memcpy(&v2, p2, sizeof(Uint32));
 
344
    if (v1 < v2)
 
345
      return -1;
 
346
    if (v1 > v2)
 
347
      return +1;
 
348
    return 0;
 
349
  }
 
350
  assert(! full);
 
351
  return CmpUnknown;
 
352
}
 
353
 
 
354
int
 
355
NdbSqlUtil::cmpBigint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
356
{
 
357
  if (n2 >= sizeof(Int64)) {
 
358
    Int64 v1, v2;
 
359
    memcpy(&v1, p1, sizeof(Int64));
 
360
    memcpy(&v2, p2, sizeof(Int64));
 
361
    if (v1 < v2)
 
362
      return -1;
 
363
    if (v1 > v2)
 
364
      return +1;
 
365
    return 0;
 
366
  }
 
367
  assert(! full);
 
368
  return CmpUnknown;
 
369
}
 
370
 
 
371
int
 
372
NdbSqlUtil::cmpBigunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
373
{
 
374
  if (n2 >= sizeof(Uint64)) {
 
375
    Uint64 v1, v2;
 
376
    memcpy(&v1, p1, sizeof(Uint64));
 
377
    memcpy(&v2, p2, sizeof(Uint64));
 
378
    if (v1 < v2)
 
379
      return -1;
 
380
    if (v1 > v2)
 
381
      return +1;
 
382
    return 0;
 
383
  }
 
384
  assert(! full);
 
385
  return CmpUnknown;
 
386
}
 
387
 
 
388
int
 
389
NdbSqlUtil::cmpFloat(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
390
{
 
391
  if (n2 >= sizeof(float)) {
 
392
    float v1, v2;
 
393
    memcpy(&v1, p1, sizeof(float));
 
394
    memcpy(&v2, p2, sizeof(float));
 
395
    if (v1 < v2)
 
396
      return -1;
 
397
    if (v1 > v2)
 
398
      return +1;
 
399
    return 0;
 
400
  }
 
401
  assert(! full);
 
402
  return CmpUnknown;
 
403
}
 
404
 
 
405
int
 
406
NdbSqlUtil::cmpDouble(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
407
{
 
408
  if (n2 >= sizeof(double)) {
 
409
    double v1, v2;
 
410
    memcpy(&v1, p1, sizeof(double));
 
411
    memcpy(&v2, p2, sizeof(double));
 
412
    if (v1 < v2)
 
413
      return -1;
 
414
    if (v1 > v2)
 
415
      return +1;
 
416
    return 0;
 
417
  }
 
418
  assert(! full);
 
419
  return CmpUnknown;
 
420
}
 
421
 
 
422
int
 
423
NdbSqlUtil::cmp_olddecimal(const uchar* s1, const uchar* s2, unsigned n)
 
424
{
 
425
  int sgn = +1;
 
426
  unsigned i = 0;
 
427
  while (i < n) {
 
428
    int c1 = s1[i];
 
429
    int c2 = s2[i];
 
430
    if (c1 == c2) {
 
431
      if (c1 == '-')
 
432
        sgn = -1;
 
433
    } else if (c1 == '-') {
 
434
      return -1;
 
435
    } else if (c2 == '-') {
 
436
      return +1;
 
437
    } else if (c1 < c2) {
 
438
      return -1 * sgn;
 
439
    } else {
 
440
      return +1 * sgn;
 
441
    }
 
442
    i++;
 
443
  }
 
444
  return 0;
 
445
}
 
446
 
 
447
int
 
448
NdbSqlUtil::cmpOlddecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
449
{
 
450
  if (full) {
 
451
    assert(n1 == n2);
 
452
    const uchar* v1 = (const uchar*)p1;
 
453
    const uchar* v2 = (const uchar*)p2;
 
454
    return cmp_olddecimal(v1, v2, n1);
 
455
  }
 
456
  return CmpUnknown;
 
457
}
 
458
 
 
459
int
 
460
NdbSqlUtil::cmpOlddecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
461
{
 
462
  if (full) {
 
463
    assert(n1 == n2);
 
464
    const uchar* v1 = (const uchar*)p1;
 
465
    const uchar* v2 = (const uchar*)p2;
 
466
    return cmp_olddecimal(v1, v2, n1);
 
467
  }
 
468
  return CmpUnknown;
 
469
}
 
470
 
 
471
int
 
472
NdbSqlUtil::cmpDecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
473
{
 
474
  const uchar* v1 = (const uchar*)p1;
 
475
  const uchar* v2 = (const uchar*)p2;
 
476
  // compare as binary strings
 
477
  unsigned n = (n1 <= n2 ? n1 : n2);
 
478
  int k = memcmp(v1, v2, n);
 
479
  if (k == 0) {
 
480
    k = (full ? n1 : n) - n2;
 
481
  }
 
482
  return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
 
483
}
 
484
 
 
485
int
 
486
NdbSqlUtil::cmpDecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
487
{
 
488
  const uchar* v1 = (const uchar*)p1;
 
489
  const uchar* v2 = (const uchar*)p2;
 
490
  // compare as binary strings
 
491
  unsigned n = (n1 <= n2 ? n1 : n2);
 
492
  int k = memcmp(v1, v2, n);
 
493
  if (k == 0) {
 
494
    k = (full ? n1 : n) - n2;
 
495
  }
 
496
  return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
 
497
}
 
498
 
 
499
int
 
500
NdbSqlUtil::cmpChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
501
{
 
502
  // collation does not work on prefix for some charsets
 
503
  assert(full);
 
504
  const uchar* v1 = (const uchar*)p1;
 
505
  const uchar* v2 = (const uchar*)p2;
 
506
  // not const in MySQL
 
507
  CHARSET_INFO* cs = (CHARSET_INFO*)(info);
 
508
  // compare with space padding
 
509
  int k = (*cs->coll->strnncollsp)(cs, v1, n1, v2, n2, false);
 
510
  return k < 0 ? -1 : k > 0 ? +1 : 0;
 
511
}
 
512
 
 
513
int
 
514
NdbSqlUtil::cmpVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
515
{
 
516
  const unsigned lb = 1;
 
517
  // collation does not work on prefix for some charsets
 
518
  assert(full && n1 >= lb && n2 >= lb);
 
519
  const uchar* v1 = (const uchar*)p1;
 
520
  const uchar* v2 = (const uchar*)p2;
 
521
  unsigned m1 = *v1;
 
522
  unsigned m2 = *v2;
 
523
  if (m1 <= n1 - lb && m2 <= n2 - lb) {
 
524
    CHARSET_INFO* cs = (CHARSET_INFO*)(info);
 
525
    // compare with space padding
 
526
    int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
 
527
    return k < 0 ? -1 : k > 0 ? +1 : 0;
 
528
  }
 
529
  // treat bad data as NULL
 
530
  if (m1 > n1 - lb && m2 <= n2 - lb)
 
531
    return -1;
 
532
  if (m1 <= n1 - lb && m2 > n2 - lb)
 
533
    return +1;
 
534
  return 0;
 
535
}
 
536
 
 
537
int
 
538
NdbSqlUtil::cmpBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
539
{
 
540
  const uchar* v1 = (const uchar*)p1;
 
541
  const uchar* v2 = (const uchar*)p2;
 
542
  // compare as binary strings
 
543
  unsigned n = (n1 <= n2 ? n1 : n2);
 
544
  int k = memcmp(v1, v2, n);
 
545
  if (k == 0) {
 
546
    k = (full ? n1 : n) - n2;
 
547
  }
 
548
  return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
 
549
}
 
550
 
 
551
int
 
552
NdbSqlUtil::cmpVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
553
{
 
554
  const unsigned lb = 1;
 
555
  if (n2 >= lb) {
 
556
    assert(n1 >= lb);
 
557
    const uchar* v1 = (const uchar*)p1;
 
558
    const uchar* v2 = (const uchar*)p2;
 
559
    unsigned m1 = *v1;
 
560
    unsigned m2 = *v2;
 
561
    if (m1 <= n1 - lb && m2 <= n2 - lb) {
 
562
      // compare as binary strings
 
563
      unsigned m = (m1 <= m2 ? m1 : m2);
 
564
      int k = memcmp(v1 + lb, v2 + lb, m);
 
565
      if (k == 0) {
 
566
        k = (full ? m1 : m) - m2;
 
567
      }
 
568
      return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
 
569
    }
 
570
    // treat bad data as NULL
 
571
    if (m1 > n1 - lb && m2 <= n2 - lb)
 
572
      return -1;
 
573
    if (m1 <= n1 - lb && m2 > n2 - lb)
 
574
      return +1;
 
575
    return 0;
 
576
  }
 
577
  assert(! full);
 
578
  return CmpUnknown;
 
579
}
 
580
 
 
581
int
 
582
NdbSqlUtil::cmpDatetime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
583
{
 
584
  if (n2 >= sizeof(Int64)) {
 
585
    Int64 v1, v2;
 
586
    memcpy(&v1, p1, sizeof(Int64));
 
587
    memcpy(&v2, p2, sizeof(Int64));
 
588
    if (v1 < v2)
 
589
      return -1;
 
590
    if (v1 > v2)
 
591
      return +1;
 
592
    return 0;
 
593
  }
 
594
  assert(! full);
 
595
  return CmpUnknown;
 
596
}
 
597
 
 
598
int
 
599
NdbSqlUtil::cmpDate(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
600
{
 
601
#ifdef ndb_date_is_4_byte_native_int
 
602
  if (n2 >= sizeof(Int32)) {
 
603
    Int32 v1, v2;
 
604
    memcpy(&v1, p1, sizeof(Int32));
 
605
    memcpy(&v2, p2, sizeof(Int32));
 
606
    if (v1 < v2)
 
607
      return -1;
 
608
    if (v1 > v2)
 
609
      return +1;
 
610
    return 0;
 
611
  }
 
612
#else
 
613
#ifdef ndb_date_sol9x86_cc_xO3_madness
 
614
  if (n2 >= 3) {
 
615
    const uchar* v1 = (const uchar*)p1;
 
616
    const uchar* v2 = (const uchar*)p2;
 
617
    // from Field_newdate::val_int
 
618
    Uint64 j1 = uint3korr(v1);
 
619
    Uint64 j2 = uint3korr(v2);
 
620
    j1 = (j1 % 32L)+(j1 / 32L % 16L)*100L + (j1/(16L*32L))*10000L;
 
621
    j2 = (j2 % 32L)+(j2 / 32L % 16L)*100L + (j2/(16L*32L))*10000L;
 
622
    if (j1 < j2)
 
623
      return -1;
 
624
    if (j1 > j2)
 
625
      return +1;
 
626
    return 0;
 
627
  }
 
628
#else
 
629
  if (n2 >= 3) {
 
630
    const uchar* v1 = (const uchar*)p1;
 
631
    const uchar* v2 = (const uchar*)p2;
 
632
    uint j1 = uint3korr(v1);
 
633
    uint j2 = uint3korr(v2);
 
634
    uint d1 = (j1 & 31);
 
635
    uint d2 = (j2 & 31);
 
636
    j1 = (j1 >> 5);
 
637
    j2 = (j2 >> 5);
 
638
    uint m1 = (j1 & 15);
 
639
    uint m2 = (j2 & 15);
 
640
    j1 = (j1 >> 4);
 
641
    j2 = (j2 >> 4);
 
642
    uint y1 = j1;
 
643
    uint y2 = j2;
 
644
    if (y1 < y2)
 
645
      return -1;
 
646
    if (y1 > y2)
 
647
      return +1;
 
648
    if (m1 < m2)
 
649
      return -1;
 
650
    if (m1 > m2)
 
651
      return +1;
 
652
    if (d1 < d2)
 
653
      return -1;
 
654
    if (d1 > d2)
 
655
      return +1;
 
656
    return 0;
 
657
  }
 
658
#endif
 
659
#endif
 
660
  assert(! full);
 
661
  return CmpUnknown;
 
662
}
 
663
 
 
664
// not supported
 
665
int
 
666
NdbSqlUtil::cmpBlob(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
667
{
 
668
  assert(false);
 
669
  return 0;
 
670
}
 
671
 
 
672
// not supported
 
673
int
 
674
NdbSqlUtil::cmpText(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
675
{
 
676
  assert(false);
 
677
  return 0;
 
678
}
 
679
 
 
680
int
 
681
NdbSqlUtil::cmpBit(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
682
 
683
  Uint32 n = (n1 < n2) ? n1 : n2;
 
684
  int ret = memcmp(p1, p2, n);
 
685
  return ret;
 
686
}
 
687
 
 
688
 
 
689
int
 
690
NdbSqlUtil::cmpTime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
691
{
 
692
  if (n2 >= 3) {
 
693
    const uchar* v1 = (const uchar*)p1;
 
694
    const uchar* v2 = (const uchar*)p2;
 
695
    // from Field_time::val_int
 
696
    Int32 j1 = sint3korr(v1);
 
697
    Int32 j2 = sint3korr(v2);
 
698
    if (j1 < j2)
 
699
      return -1;
 
700
    if (j1 > j2)
 
701
      return +1;
 
702
    return 0;
 
703
  }
 
704
  assert(! full);
 
705
  return CmpUnknown;
 
706
}
 
707
 
 
708
// not yet
 
709
 
 
710
int
 
711
NdbSqlUtil::cmpLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
712
{
 
713
  const unsigned lb = 2;
 
714
  // collation does not work on prefix for some charsets
 
715
  assert(full && n1 >= lb && n2 >= lb);
 
716
  const uchar* v1 = (const uchar*)p1;
 
717
  const uchar* v2 = (const uchar*)p2;
 
718
  unsigned m1 = uint2korr(v1);
 
719
  unsigned m2 = uint2korr(v2);
 
720
  if (m1 <= n1 - lb && m2 <= n2 - lb) {
 
721
    CHARSET_INFO* cs = (CHARSET_INFO*)(info);
 
722
    // compare with space padding
 
723
    int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
 
724
    return k < 0 ? -1 : k > 0 ? +1 : 0;
 
725
  }
 
726
  // treat bad data as NULL
 
727
  if (m1 > n1 - lb && m2 <= n2 - lb)
 
728
    return -1;
 
729
  if (m1 <= n1 - lb && m2 > n2 - lb)
 
730
    return +1;
 
731
  return 0;
 
732
}
 
733
 
 
734
int
 
735
NdbSqlUtil::cmpLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
736
{
 
737
  const unsigned lb = 2;
 
738
  if (n2 >= lb) {
 
739
    assert(n1 >= lb);
 
740
    const uchar* v1 = (const uchar*)p1;
 
741
    const uchar* v2 = (const uchar*)p2;
 
742
    unsigned m1 = uint2korr(v1);
 
743
    unsigned m2 = uint2korr(v2);
 
744
    if (m1 <= n1 - lb && m2 <= n2 - lb) {
 
745
      // compare as binary strings
 
746
      unsigned m = (m1 <= m2 ? m1 : m2);
 
747
      int k = memcmp(v1 + lb, v2 + lb, m);
 
748
      if (k == 0) {
 
749
        k = (full ? m1 : m) - m2;
 
750
      }
 
751
      return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
 
752
    }
 
753
    // treat bad data as NULL
 
754
    if (m1 > n1 - lb && m2 <= n2 - lb)
 
755
      return -1;
 
756
    if (m1 <= n1 - lb && m2 > n2 - lb)
 
757
      return +1;
 
758
    return 0;
 
759
  }
 
760
  assert(! full);
 
761
  return CmpUnknown;
 
762
}
 
763
 
 
764
int
 
765
NdbSqlUtil::cmpYear(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
766
{
 
767
  if (n2 >= sizeof(Uint8)) {
 
768
    Uint8 v1, v2;
 
769
    memcpy(&v1, p1, sizeof(Uint8));
 
770
    memcpy(&v2, p2, sizeof(Uint8));
 
771
    if (v1 < v2)
 
772
      return -1;
 
773
    if (v1 > v2)
 
774
      return +1;
 
775
    return 0;
 
776
  }
 
777
  assert(! full);
 
778
  return CmpUnknown;
 
779
}
 
780
 
 
781
int
 
782
NdbSqlUtil::cmpTimestamp(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
 
783
{
 
784
  if (n2 >= sizeof(Uint32)) {
 
785
    Uint32 v1, v2;
 
786
    memcpy(&v1, p1, sizeof(Uint32));
 
787
    memcpy(&v2, p2, sizeof(Uint32));
 
788
    if (v1 < v2)
 
789
      return -1;
 
790
    if (v1 > v2)
 
791
      return +1;
 
792
    return 0;
 
793
  }
 
794
  assert(! full);
 
795
  return CmpUnknown;
 
796
}
 
797
 
 
798
// like
 
799
 
 
800
static const int ndb_wild_prefix = '\\';
 
801
static const int ndb_wild_one = '_';
 
802
static const int ndb_wild_many = '%';
 
803
 
 
804
int
 
805
NdbSqlUtil::likeChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
806
{
 
807
  const char* v1 = (const char*)p1;
 
808
  const char* v2 = (const char*)p2;
 
809
  CHARSET_INFO* cs = (CHARSET_INFO*)(info);
 
810
  // strip end spaces to match (incorrect) MySQL behaviour
 
811
  n1 = (*cs->cset->lengthsp)(cs, v1, n1);
 
812
  int k = (*cs->coll->wildcmp)(cs, v1, v1 + n1, v2, v2 + n2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
 
813
  return k == 0 ? 0 : +1;
 
814
}
 
815
 
 
816
int
 
817
NdbSqlUtil::likeBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
818
{
 
819
  assert(info == 0);
 
820
  return likeChar(&my_charset_bin, p1, n1, p2, n2);
 
821
}
 
822
 
 
823
int
 
824
NdbSqlUtil::likeVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
825
{
 
826
  const unsigned lb = 1;
 
827
  if (n1 >= lb) {
 
828
    const uchar* v1 = (const uchar*)p1;
 
829
    const uchar* v2 = (const uchar*)p2;
 
830
    unsigned m1 = *v1;
 
831
    unsigned m2 = n2;
 
832
    if (lb + m1 <= n1) {
 
833
      const char* w1 = (const char*)v1 + lb;
 
834
      const char* w2 = (const char*)v2;
 
835
      CHARSET_INFO* cs = (CHARSET_INFO*)(info);
 
836
      int k = (*cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
 
837
      return k == 0 ? 0 : +1;
 
838
    }
 
839
  }
 
840
  return -1;
 
841
}
 
842
 
 
843
int
 
844
NdbSqlUtil::likeVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
845
{
 
846
  assert(info == 0);
 
847
  return likeVarchar(&my_charset_bin, p1, n1, p2, n2);
 
848
}
 
849
 
 
850
int
 
851
NdbSqlUtil::likeLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
852
{
 
853
  const unsigned lb = 2;
 
854
  if (n1 >= lb) {
 
855
    const uchar* v1 = (const uchar*)p1;
 
856
    const uchar* v2 = (const uchar*)p2;
 
857
    unsigned m1 = uint2korr(v1);
 
858
    unsigned m2 = n2;
 
859
    if (lb + m1 <= n1) {
 
860
      const char* w1 = (const char*)v1 + lb;
 
861
      const char* w2 = (const char*)v2;
 
862
      CHARSET_INFO* cs = (CHARSET_INFO*)(info);
 
863
      int k = (*cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
 
864
      return k == 0 ? 0 : +1;
 
865
    }
 
866
  }
 
867
  return -1;
 
868
}
 
869
 
 
870
int
 
871
NdbSqlUtil::likeLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
872
{
 
873
  assert(info == 0);
 
874
  return likeLongvarchar(&my_charset_bin, p1, n1, p2, n2);
 
875
}
 
876
 
 
877
// check charset
 
878
 
 
879
uint
 
880
NdbSqlUtil::check_column_for_pk(Uint32 typeId, const void* info)
 
881
{
 
882
  const Type& type = getType(typeId);
 
883
  switch (type.m_typeId) {
 
884
  case Type::Char:
 
885
  case Type::Varchar:
 
886
  case Type::Longvarchar:
 
887
    {
 
888
      const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
 
889
      if(cs != 0 &&
 
890
         cs->cset != 0 &&
 
891
         cs->coll != 0 &&
 
892
         cs->coll->strnxfrm != 0 &&
 
893
         cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY)
 
894
        return 0;
 
895
      else
 
896
        return 743;
 
897
    }
 
898
    break;
 
899
  case Type::Undefined:
 
900
  case Type::Blob:
 
901
  case Type::Text:
 
902
  case Type::Bit:
 
903
    break;
 
904
  default:
 
905
    return 0;
 
906
  }
 
907
  return 906;
 
908
}
 
909
 
 
910
uint
 
911
NdbSqlUtil::check_column_for_hash_index(Uint32 typeId, const void* info)
 
912
{
 
913
  return check_column_for_pk(typeId, info);
 
914
}
 
915
 
 
916
uint
 
917
NdbSqlUtil::check_column_for_ordered_index(Uint32 typeId, const void* info)
 
918
{
 
919
  const Type& type = getType(typeId);
 
920
  if (type.m_cmp == NULL)
 
921
    return false;
 
922
  switch (type.m_typeId) {
 
923
  case Type::Char:
 
924
  case Type::Varchar:
 
925
  case Type::Longvarchar:
 
926
    {
 
927
      const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
 
928
      if (cs != 0 &&
 
929
          cs->cset != 0 &&
 
930
          cs->coll != 0 &&
 
931
          cs->coll->strnxfrm != 0 &&
 
932
          cs->coll->strnncollsp != 0 &&
 
933
          cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY)
 
934
        return 0;
 
935
      else
 
936
        return 743;
 
937
    }
 
938
    break;
 
939
  case Type::Undefined:
 
940
  case Type::Blob:
 
941
  case Type::Text:
 
942
  case Type::Bit:       // can be fixed
 
943
    break;
 
944
  default:
 
945
    return 0;
 
946
  }
 
947
  return 906;
 
948
}
 
949
 
 
950
// utilities
 
951
 
 
952
bool
 
953
NdbSqlUtil::get_var_length(Uint32 typeId, const void* p, unsigned attrlen, Uint32& lb, Uint32& len)
 
954
{
 
955
  const unsigned char* const src = (const unsigned char*)p;
 
956
  switch (typeId) {
 
957
  case NdbSqlUtil::Type::Varchar:
 
958
  case NdbSqlUtil::Type::Varbinary:
 
959
    lb = 1;
 
960
    if (attrlen >= lb) {
 
961
      len = src[0];
 
962
      if (attrlen >= lb + len)
 
963
        return true;
 
964
    }
 
965
    break;
 
966
  case NdbSqlUtil::Type::Longvarchar:
 
967
  case NdbSqlUtil::Type::Longvarbinary:
 
968
    lb = 2;
 
969
    if (attrlen >= lb) {
 
970
      len = src[0] + (src[1] << 8);
 
971
      if (attrlen >= lb + len)
 
972
        return true;
 
973
    }
 
974
    break;
 
975
  default:
 
976
    lb = 0;
 
977
    len = attrlen;
 
978
    return true;
 
979
    break;
 
980
  }
 
981
  return false;
 
982
}
 
983
 
 
984
// workaround
 
985
 
 
986
int
 
987
NdbSqlUtil::strnxfrm_bug7284(CHARSET_INFO* cs, unsigned char* dst, unsigned dstLen, const unsigned char*src, unsigned srcLen)
 
988
{
 
989
  unsigned char nsp[20]; // native space char
 
990
  unsigned char xsp[20]; // strxfrm-ed space char
 
991
#ifdef VM_TRACE
 
992
  memset(nsp, 0x1f, sizeof(nsp));
 
993
  memset(xsp, 0x1f, sizeof(xsp));
 
994
#endif
 
995
  // convert from unicode codepoint for space
 
996
  int n1 = (*cs->cset->wc_mb)(cs, (my_wc_t)0x20, nsp, nsp + sizeof(nsp));
 
997
  if (n1 <= 0)
 
998
    return -1;
 
999
  // strxfrm to binary
 
1000
  int n2 = (*cs->coll->strnxfrm)(cs, xsp, sizeof(xsp), nsp, n1);
 
1001
  if (n2 <= 0)
 
1002
    return -1;
 
1003
  // XXX bug workaround - strnxfrm may not write full string
 
1004
  memset(dst, 0x0, dstLen);
 
1005
  // strxfrm argument string - returns no error indication
 
1006
  int n3 = (*cs->coll->strnxfrm)(cs, dst, dstLen, src, srcLen);
 
1007
  // pad with strxfrm-ed space chars
 
1008
  int n4 = n3;
 
1009
  while (n4 < (int)dstLen) {
 
1010
    dst[n4] = xsp[(n4 - n3) % n2];
 
1011
    n4++;
 
1012
  }
 
1013
  // no check for partial last
 
1014
  return dstLen;
 
1015
}