~ubuntu-branches/ubuntu/trusty/mysql-5.6/trusty

« back to all changes in this revision

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

  • Committer: Package Import Robot
  • Author(s): James Page
  • Date: 2014-02-12 11:54:27 UTC
  • Revision ID: package-import@ubuntu.com-20140212115427-oq6tfsqxl1wuwehi
Tags: upstream-5.6.15
ImportĀ upstreamĀ versionĀ 5.6.15

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
   Copyright (c) 2003, 2010, Oracle and/or its affiliates. All rights reserved.
 
3
 
 
4
   This program is free software; you can redistribute it and/or modify
 
5
   it under the terms of the GNU General Public License as published by
 
6
   the Free Software Foundation; version 2 of the License.
 
7
 
 
8
   This program is distributed in the hope that it will be useful,
 
9
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
10
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
11
   GNU General Public License for more details.
 
12
 
 
13
   You should have received a copy of the GNU General Public License
 
14
   along with this program; if not, write to the Free Software
 
15
   Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301  USA
 
16
*/
 
17
 
 
18
#include <NdbSqlUtil.hpp>
 
19
#include <ndb_version.h>
 
20
#include <math.h>
 
21
 
 
22
/*
 
23
 * Data types.  The entries must be in the numerical order.
 
24
 */
 
25
 
 
26
const NdbSqlUtil::Type
 
27
NdbSqlUtil::m_typeList[] = {
 
28
  { // 0
 
29
    Type::Undefined,
 
30
    NULL,
 
31
    NULL,
 
32
    NULL
 
33
  },
 
34
  { // 1
 
35
    Type::Tinyint,
 
36
    cmpTinyint,
 
37
    NULL,
 
38
    NULL
 
39
  },
 
40
  { // 2
 
41
    Type::Tinyunsigned,
 
42
    cmpTinyunsigned,
 
43
    NULL,
 
44
    NULL
 
45
  },
 
46
  { // 3
 
47
    Type::Smallint,
 
48
    cmpSmallint,
 
49
    NULL,
 
50
    NULL
 
51
  },
 
52
  { // 4
 
53
    Type::Smallunsigned,
 
54
    cmpSmallunsigned,
 
55
    NULL,
 
56
    NULL
 
57
  },
 
58
  { // 5
 
59
    Type::Mediumint,
 
60
    cmpMediumint,
 
61
    NULL,
 
62
    NULL
 
63
  },
 
64
  { // 6
 
65
    Type::Mediumunsigned,
 
66
    cmpMediumunsigned,
 
67
    NULL,
 
68
    NULL
 
69
  },
 
70
  { // 7
 
71
    Type::Int,
 
72
    cmpInt,
 
73
    NULL,
 
74
    NULL
 
75
  },
 
76
  { // 8
 
77
    Type::Unsigned,
 
78
    cmpUnsigned,
 
79
    NULL,
 
80
    NULL
 
81
  },
 
82
  { // 9
 
83
    Type::Bigint,
 
84
    cmpBigint,
 
85
    NULL,
 
86
    NULL
 
87
  },
 
88
  { // 10
 
89
    Type::Bigunsigned,
 
90
    cmpBigunsigned,
 
91
    NULL,
 
92
    NULL
 
93
  },
 
94
  { // 11
 
95
    Type::Float,
 
96
    cmpFloat,
 
97
    NULL,
 
98
    NULL
 
99
  },
 
100
  { // 12
 
101
    Type::Double,
 
102
    cmpDouble,
 
103
    NULL,
 
104
    NULL
 
105
  },
 
106
  { // 13
 
107
    Type::Olddecimal,
 
108
    cmpOlddecimal,
 
109
    NULL,
 
110
    NULL
 
111
  },
 
112
  { // 14
 
113
    Type::Char,
 
114
    cmpChar,
 
115
    likeChar,
 
116
    NULL
 
117
  },
 
118
  { // 15
 
119
    Type::Varchar,
 
120
    cmpVarchar,
 
121
    likeVarchar,
 
122
    NULL
 
123
  },
 
124
  { // 16
 
125
    Type::Binary,
 
126
    cmpBinary,
 
127
    likeBinary,
 
128
    NULL
 
129
  },
 
130
  { // 17
 
131
    Type::Varbinary,
 
132
    cmpVarbinary,
 
133
    likeVarbinary,
 
134
    NULL
 
135
  },
 
136
  { // 18
 
137
    Type::Datetime,
 
138
    cmpDatetime,
 
139
    NULL,
 
140
    NULL
 
141
  },
 
142
  { // 19
 
143
    Type::Date,
 
144
    cmpDate,
 
145
    NULL,
 
146
    NULL
 
147
  },
 
148
  { // 20
 
149
    Type::Blob,
 
150
    NULL,
 
151
    NULL,
 
152
    NULL
 
153
  },
 
154
  { // 21
 
155
    Type::Text,
 
156
    NULL,
 
157
    NULL,
 
158
    NULL
 
159
  },
 
160
  { // 22
 
161
    Type::Bit,
 
162
    cmpBit,
 
163
    NULL,
 
164
    maskBit
 
165
  },
 
166
  { // 23
 
167
    Type::Longvarchar,
 
168
    cmpLongvarchar,
 
169
    likeLongvarchar,
 
170
    NULL
 
171
  },
 
172
  { // 24
 
173
    Type::Longvarbinary,
 
174
    cmpLongvarbinary,
 
175
    likeLongvarbinary,
 
176
    NULL
 
177
  },
 
178
  { // 25
 
179
    Type::Time,
 
180
    cmpTime,
 
181
    NULL,
 
182
    NULL
 
183
  },
 
184
  { // 26
 
185
    Type::Year,
 
186
    cmpYear,
 
187
    NULL,
 
188
    NULL
 
189
  },
 
190
  { // 27
 
191
    Type::Timestamp,
 
192
    cmpTimestamp,
 
193
    NULL,
 
194
    NULL
 
195
  },
 
196
  { // 28
 
197
    Type::Olddecimalunsigned,
 
198
    cmpOlddecimalunsigned,
 
199
    NULL,
 
200
    NULL
 
201
  },
 
202
  { // 29
 
203
    Type::Decimal,
 
204
    cmpDecimal,
 
205
    NULL,
 
206
    NULL
 
207
  },
 
208
  { // 30
 
209
    Type::Decimalunsigned,
 
210
    cmpDecimalunsigned,
 
211
    NULL,
 
212
    NULL
 
213
  }
 
214
};
 
215
 
 
216
const NdbSqlUtil::Type&
 
217
NdbSqlUtil::getType(Uint32 typeId)
 
218
{
 
219
  if (typeId < sizeof(m_typeList) / sizeof(m_typeList[0]) &&
 
220
      m_typeList[typeId].m_typeId != Type::Undefined) {
 
221
    return m_typeList[typeId];
 
222
  }
 
223
  return m_typeList[Type::Undefined];
 
224
}
 
225
 
 
226
/*
 
227
 * Comparison functions.
 
228
 */
 
229
 
 
230
int
 
231
NdbSqlUtil::cmpTinyint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
232
{
 
233
  assert(info == 0 && n1 == 1 && n2 == 1);
 
234
  Int8 v1, v2;
 
235
  memcpy(&v1, p1, 1);
 
236
  memcpy(&v2, p2, 1);
 
237
  int w1 = (int)v1;
 
238
  int w2 = (int)v2;
 
239
  return w1 - w2;
 
240
}
 
241
 
 
242
int
 
243
NdbSqlUtil::cmpTinyunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
244
{
 
245
  assert(info == 0 && n1 == 1 && n2 == 1);
 
246
  Uint8 v1, v2;
 
247
  memcpy(&v1, p1, 1);
 
248
  memcpy(&v2, p2, 1);
 
249
  int w1 = (int)v1;
 
250
  int w2 = (int)v2;
 
251
  return w1 - w2;
 
252
}
 
253
 
 
254
int
 
255
NdbSqlUtil::cmpSmallint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
256
{
 
257
  assert(info == 0 && n1 == 2 && n2 == 2);
 
258
  Int16 v1, v2;
 
259
  memcpy(&v1, p1, 2);
 
260
  memcpy(&v2, p2, 2);
 
261
  int w1 = (int)v1;
 
262
  int w2 = (int)v2;
 
263
  return w1 - w2;
 
264
}
 
265
 
 
266
int
 
267
NdbSqlUtil::cmpSmallunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
268
{
 
269
  assert(info == 0 && n1 == 2 && n2 == 2);
 
270
  Uint16 v1, v2;
 
271
  memcpy(&v1, p1, 2);
 
272
  memcpy(&v2, p2, 2);
 
273
  int w1 = (int)v1;
 
274
  int w2 = (int)v2;
 
275
  return w1 - w2;
 
276
}
 
277
 
 
278
int
 
279
NdbSqlUtil::cmpMediumint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
280
{
 
281
  assert(info == 0 && n1 == 3 && n2 == 3);
 
282
  uchar b1[4];
 
283
  uchar b2[4];
 
284
  memcpy(b1, p1, 3);
 
285
  b1[3] = 0;
 
286
  memcpy(b2, p2, 3);
 
287
  b2[3] = 0;
 
288
  int w1 = (int)sint3korr(b1);
 
289
  int w2 = (int)sint3korr(b2);
 
290
  return w1 - w2;
 
291
}
 
292
 
 
293
int
 
294
NdbSqlUtil::cmpMediumunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
295
{
 
296
  assert(info == 0 && n1 == 3 && n2 == 3);
 
297
  uchar b1[4];
 
298
  uchar b2[4];
 
299
  memcpy(b1, p1, 3);
 
300
  b1[3] = 0;
 
301
  memcpy(b2, p2, 3);
 
302
  b2[3] = 0;
 
303
  int w1 = (int)uint3korr(b1);
 
304
  int w2 = (int)uint3korr(b2);
 
305
  return w1 - w2;
 
306
}
 
307
 
 
308
int
 
309
NdbSqlUtil::cmpInt(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
310
{
 
311
  assert(info == 0 && n1 == 4 && n2 == 4);
 
312
  Int32 v1, v2;
 
313
  memcpy(&v1, p1, 4);
 
314
  memcpy(&v2, p2, 4);
 
315
  if (v1 < v2)
 
316
    return -1;
 
317
  if (v1 > v2)
 
318
    return +1;
 
319
  return 0;
 
320
}
 
321
 
 
322
int
 
323
NdbSqlUtil::cmpUnsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
324
{
 
325
  assert(info == 0 && n1 == 4 && n2 == 4);
 
326
  Uint32 v1, v2;
 
327
  memcpy(&v1, p1, 4);
 
328
  memcpy(&v2, p2, 4);
 
329
  if (v1 < v2)
 
330
    return -1;
 
331
  if (v1 > v2)
 
332
    return +1;
 
333
  return 0;
 
334
}
 
335
 
 
336
int
 
337
NdbSqlUtil::cmpBigint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
338
{
 
339
  assert(info == 0 && n1 == 8 && n2 == 8);
 
340
  Int64 v1, v2;
 
341
  memcpy(&v1, p1, 8);
 
342
  memcpy(&v2, p2, 8);
 
343
  if (v1 < v2)
 
344
    return -1;
 
345
  if (v1 > v2)
 
346
    return +1;
 
347
  return 0;
 
348
}
 
349
 
 
350
int
 
351
NdbSqlUtil::cmpBigunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
352
{
 
353
  assert(info == 0 && n1 == 8 && n2 == 8);
 
354
  Uint64 v1, v2;
 
355
  memcpy(&v1, p1, 8);
 
356
  memcpy(&v2, p2, 8);
 
357
  if (v1 < v2)
 
358
    return -1;
 
359
  if (v1 > v2)
 
360
    return +1;
 
361
  return 0;
 
362
}
 
363
 
 
364
int
 
365
NdbSqlUtil::cmpFloat(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
366
{
 
367
  assert(info == 0 && n1 == 4 && n2 == 4);
 
368
  float v1, v2;
 
369
  memcpy(&v1, p1, 4);
 
370
  memcpy(&v2, p2, 4);
 
371
  require(!isnan(v1) && !isnan(v2));
 
372
  if (v1 < v2)
 
373
    return -1;
 
374
  if (v1 > v2)
 
375
    return +1;
 
376
  return 0;
 
377
}
 
378
 
 
379
int
 
380
NdbSqlUtil::cmpDouble(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
381
{
 
382
  assert(info == 0 && n1 == 8 && n2 == 8);
 
383
  double v1, v2;
 
384
  memcpy(&v1, p1, 8);
 
385
  memcpy(&v2, p2, 8);
 
386
  require(!isnan(v1) && !isnan(v2));
 
387
  if (v1 < v2)
 
388
    return -1;
 
389
  if (v1 > v2)
 
390
    return +1;
 
391
  return 0;
 
392
}
 
393
 
 
394
int
 
395
NdbSqlUtil::cmpOlddecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
396
{
 
397
  assert(info == 0 && n1 == n2);
 
398
  const uchar* v1 = (const uchar*)p1;
 
399
  const uchar* v2 = (const uchar*)p2;
 
400
  int sgn = +1;
 
401
  unsigned i = 0;
 
402
  while (i < n1) {
 
403
    int c1 = v1[i];
 
404
    int c2 = v2[i];
 
405
    if (c1 == c2) {
 
406
      if (c1 == '-')
 
407
        sgn = -1;
 
408
    } else if (c1 == '-') {
 
409
      return -1;
 
410
    } else if (c2 == '-') {
 
411
      return +1;
 
412
    } else if (c1 < c2) {
 
413
      return -1 * sgn;
 
414
    } else {
 
415
      return +1 * sgn;
 
416
    }
 
417
    i++;
 
418
  }
 
419
  return 0;
 
420
}
 
421
 
 
422
int
 
423
NdbSqlUtil::cmpOlddecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
424
{
 
425
  return cmpOlddecimal(info, p1, n1, p2, n2);
 
426
}
 
427
 
 
428
int
 
429
NdbSqlUtil::cmpDecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
430
{
 
431
  return cmpBinary(info, p1, n1, p2, n2);
 
432
}
 
433
 
 
434
int
 
435
NdbSqlUtil::cmpDecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
436
{
 
437
  return cmpBinary(info, p1, n1, p2, n2);
 
438
}
 
439
 
 
440
int
 
441
NdbSqlUtil::cmpChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
442
{
 
443
  // allow different lengths
 
444
  assert(info != 0);
 
445
  const uchar* v1 = (const uchar*)p1;
 
446
  const uchar* v2 = (const uchar*)p2;
 
447
  CHARSET_INFO* cs = (CHARSET_INFO*)info;
 
448
  // compare with space padding
 
449
  int k = (*cs->coll->strnncollsp)(cs, v1, n1, v2, n2, false);
 
450
  return k;
 
451
}
 
452
 
 
453
int
 
454
NdbSqlUtil::cmpVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
455
{
 
456
  assert(info != 0);
 
457
  const uint lb = 1;
 
458
  const uchar* v1 = (const uchar*)p1;
 
459
  const uchar* v2 = (const uchar*)p2;
 
460
  uint m1 = v1[0];
 
461
  uint m2 = v2[0];
 
462
  require(lb + m1 <= n1 && lb + m2 <= n2);
 
463
  CHARSET_INFO* cs = (CHARSET_INFO*)info;
 
464
  // compare with space padding
 
465
  int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
 
466
  return k;
 
467
}
 
468
 
 
469
int
 
470
NdbSqlUtil::cmpBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
471
{
 
472
  // allow different lengths
 
473
  assert(info == 0);
 
474
  const uchar* v1 = (const uchar*)p1;
 
475
  const uchar* v2 = (const uchar*)p2;
 
476
  int k = 0;
 
477
  if (n1 < n2) {
 
478
    k = memcmp(v1, v2, n1);
 
479
    if (k == 0)
 
480
      k = -1;
 
481
  } else if (n1 > n2) {
 
482
    k = memcmp(v1, v2, n2);
 
483
    if (k == 0)
 
484
      k = +1;
 
485
  } else {
 
486
    k = memcmp(v1, v2, n1);
 
487
  }
 
488
  return k;
 
489
}
 
490
 
 
491
int
 
492
NdbSqlUtil::cmpVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
493
{
 
494
  assert(info == 0);
 
495
  const uint lb = 1;
 
496
  const uchar* v1 = (const uchar*)p1;
 
497
  const uchar* v2 = (const uchar*)p2;
 
498
  uint m1 = v1[0];
 
499
  uint m2 = v2[0];
 
500
  require(lb + m1 <= n1 && lb + m2 <= n2);
 
501
  int k = cmpBinary(info, v1 + lb, m1, v2 + lb, m2);
 
502
  return k;
 
503
}
 
504
 
 
505
int
 
506
NdbSqlUtil::cmpDatetime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
507
{
 
508
  assert(info == 0 && n1 == 8 && n2 == 8);
 
509
  Int64 v1, v2;
 
510
  memcpy(&v1, p1, sizeof(Int64));
 
511
  memcpy(&v2, p2, sizeof(Int64));
 
512
  if (v1 < v2)
 
513
    return -1;
 
514
  if (v1 > v2)
 
515
    return +1;
 
516
  return 0;
 
517
}
 
518
 
 
519
int
 
520
NdbSqlUtil::cmpDate(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
521
{
 
522
  assert(info == 0 && n1 == 3 && n2 == 3);
 
523
  uchar b1[4];
 
524
  uchar b2[4];
 
525
  memcpy(b1, p1, 3);
 
526
  b1[3] = 0;
 
527
  memcpy(b2, p2, 3);
 
528
  b2[3] = 0;
 
529
  // from Field_newdate::val_int
 
530
  int w1 = (int)uint3korr(b1);
 
531
  int w2 = (int)uint3korr(b2);
 
532
  return w1 - w2;
 
533
}
 
534
 
 
535
// not supported
 
536
int
 
537
NdbSqlUtil::cmpBlob(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
538
{
 
539
  assert(false);
 
540
  return 0;
 
541
}
 
542
 
 
543
// not supported
 
544
int
 
545
NdbSqlUtil::cmpText(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
546
{
 
547
  assert(false);
 
548
  return 0;
 
549
}
 
550
 
 
551
int
 
552
NdbSqlUtil::cmpBit(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
553
 
554
  /* Bitfields are stored as 32-bit words
 
555
   * This means that a byte-by-byte comparison will not work on all platforms
 
556
   * We do a word-wise comparison of the significant bytes.
 
557
   * It is assumed that insignificant bits (but not bytes) are zeroed in the
 
558
   * passed values.
 
559
   */
 
560
  const Uint32 bytes= MIN(n1, n2);
 
561
  Uint32 words= (bytes + 3) >> 2;
 
562
 
 
563
  /* Don't expect either value to be length zero */
 
564
  assert(words);
 
565
 
 
566
  /* Check ptr alignment */
 
567
  if (unlikely(((((UintPtr)p1) & 3) != 0) ||
 
568
               ((((UintPtr)p2) & 3) != 0)))
 
569
  {
 
570
    Uint32 copyP1[ MAX_TUPLE_SIZE_IN_WORDS ];
 
571
    Uint32 copyP2[ MAX_TUPLE_SIZE_IN_WORDS ];
 
572
    memcpy(copyP1, p1, words << 2);
 
573
    memcpy(copyP2, p2, words << 2);
 
574
 
 
575
    return cmpBit(info, copyP1, bytes, copyP2, bytes);
 
576
  }
 
577
 
 
578
  const Uint32* wp1= (const Uint32*) p1;
 
579
  const Uint32* wp2= (const Uint32*) p2;
 
580
  while (--words)
 
581
  {
 
582
    if (*wp1 < *wp2)
 
583
      return -1;
 
584
    if (*(wp1++) > *(wp2++))
 
585
      return 1;
 
586
  }
 
587
 
 
588
  /* For the last word, we mask out any insignificant bytes */
 
589
  const Uint32 sigBytes= bytes & 3; // 0..3; 0 == all bytes significant
 
590
  const Uint32 mask= sigBytes?
 
591
    (1 << (sigBytes *8)) -1 :
 
592
    ~0;
 
593
  const Uint32 lastWord1= *wp1 & mask;
 
594
  const Uint32 lastWord2= *wp2 & mask;
 
595
  
 
596
  if (lastWord1 < lastWord2)
 
597
    return -1;
 
598
  if (lastWord1 > lastWord2)
 
599
    return 1;
 
600
 
 
601
  return 0;
 
602
}
 
603
 
 
604
 
 
605
int
 
606
NdbSqlUtil::cmpTime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
607
{
 
608
  assert(info == 0 && n1 == 3 && n2 == 3);
 
609
  uchar b1[4];
 
610
  uchar b2[4];
 
611
  memcpy(b1, p1, 3);
 
612
  b1[3] = 0;
 
613
  memcpy(b2, p2, 3);
 
614
  b2[3] = 0;
 
615
  // from Field_time::val_int
 
616
  int j1 = (int)sint3korr(b1);
 
617
  int j2 = (int)sint3korr(b2);
 
618
  if (j1 < j2)
 
619
    return -1;
 
620
  if (j1 > j2)
 
621
    return +1;
 
622
  return 0;
 
623
}
 
624
 
 
625
// not yet
 
626
 
 
627
int
 
628
NdbSqlUtil::cmpLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
629
{
 
630
  assert(info != 0);
 
631
  const uint lb = 2;
 
632
  const uchar* v1 = (const uchar*)p1;
 
633
  const uchar* v2 = (const uchar*)p2;
 
634
  uint m1 = v1[0] | (v1[1] << 8);
 
635
  uint m2 = v2[0] | (v2[1] << 8);
 
636
  require(lb + m1 <= n1 && lb + m2 <= n2);
 
637
  CHARSET_INFO* cs = (CHARSET_INFO*)info;
 
638
  // compare with space padding
 
639
  int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
 
640
  return k;
 
641
}
 
642
 
 
643
int
 
644
NdbSqlUtil::cmpLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
645
{
 
646
  assert(info == 0);
 
647
  const uint lb = 2;
 
648
  const uchar* v1 = (const uchar*)p1;
 
649
  const uchar* v2 = (const uchar*)p2;
 
650
  uint m1 = v1[0] | (v1[1] << 8);
 
651
  uint m2 = v2[0] | (v2[1] << 8);
 
652
  require(lb + m1 <= n1 && lb + m2 <= n2);
 
653
  int k = cmpBinary(info, v1 + lb, m1, v2 + lb, m2);
 
654
  return k;
 
655
}
 
656
 
 
657
int
 
658
NdbSqlUtil::cmpYear(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
659
{
 
660
  assert(info == 0 && n1 == 1 && n2 == 1);
 
661
  Uint8 v1, v2;
 
662
  memcpy(&v1, p1, 1);
 
663
  memcpy(&v2, p2, 1);
 
664
  int w1 = (int)v1;
 
665
  int w2 = (int)v2;
 
666
  return w1 - w2;
 
667
}
 
668
 
 
669
int
 
670
NdbSqlUtil::cmpTimestamp(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
671
{
 
672
  assert(info == 0 && n1 == 4 && n2 == 4);
 
673
  Uint32 v1, v2;
 
674
  memcpy(&v1, p1, 4);
 
675
  memcpy(&v2, p2, 4);
 
676
  if (v1 < v2)
 
677
    return -1;
 
678
  if (v1 > v2)
 
679
    return +1;
 
680
  return 0;
 
681
}
 
682
 
 
683
// like
 
684
 
 
685
static const int ndb_wild_prefix = '\\';
 
686
static const int ndb_wild_one = '_';
 
687
static const int ndb_wild_many = '%';
 
688
 
 
689
int
 
690
NdbSqlUtil::likeChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
691
{
 
692
  const char* v1 = (const char*)p1;
 
693
  const char* v2 = (const char*)p2;
 
694
  CHARSET_INFO* cs = (CHARSET_INFO*)(info);
 
695
  // strip end spaces to match (incorrect) MySQL behaviour
 
696
  n1 = (*cs->cset->lengthsp)(cs, v1, n1);
 
697
  int k = (*cs->coll->wildcmp)(cs, v1, v1 + n1, v2, v2 + n2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
 
698
  return k == 0 ? 0 : +1;
 
699
}
 
700
 
 
701
int
 
702
NdbSqlUtil::likeBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
703
{
 
704
  assert(info == 0);
 
705
  return likeChar(&my_charset_bin, p1, n1, p2, n2);
 
706
}
 
707
 
 
708
int
 
709
NdbSqlUtil::likeVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
710
{
 
711
  const unsigned lb = 1;
 
712
  if (n1 >= lb) {
 
713
    const uchar* v1 = (const uchar*)p1;
 
714
    const uchar* v2 = (const uchar*)p2;
 
715
    unsigned m1 = *v1;
 
716
    unsigned m2 = n2;
 
717
    if (lb + m1 <= n1) {
 
718
      const char* w1 = (const char*)v1 + lb;
 
719
      const char* w2 = (const char*)v2;
 
720
      CHARSET_INFO* cs = (CHARSET_INFO*)(info);
 
721
      int k = (*cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
 
722
      return k == 0 ? 0 : +1;
 
723
    }
 
724
  }
 
725
  return -1;
 
726
}
 
727
 
 
728
int
 
729
NdbSqlUtil::likeVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
730
{
 
731
  assert(info == 0);
 
732
  return likeVarchar(&my_charset_bin, p1, n1, p2, n2);
 
733
}
 
734
 
 
735
int
 
736
NdbSqlUtil::likeLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
737
{
 
738
  const unsigned lb = 2;
 
739
  if (n1 >= lb) {
 
740
    const uchar* v1 = (const uchar*)p1;
 
741
    const uchar* v2 = (const uchar*)p2;
 
742
    unsigned m1 = uint2korr(v1);
 
743
    unsigned m2 = n2;
 
744
    if (lb + m1 <= n1) {
 
745
      const char* w1 = (const char*)v1 + lb;
 
746
      const char* w2 = (const char*)v2;
 
747
      CHARSET_INFO* cs = (CHARSET_INFO*)(info);
 
748
      int k = (*cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
 
749
      return k == 0 ? 0 : +1;
 
750
    }
 
751
  }
 
752
  return -1;
 
753
}
 
754
 
 
755
int
 
756
NdbSqlUtil::likeLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
 
757
{
 
758
  assert(info == 0);
 
759
  return likeLongvarchar(&my_charset_bin, p1, n1, p2, n2);
 
760
}
 
761
 
 
762
 
 
763
// mask Functions
 
764
 
 
765
int
 
766
NdbSqlUtil::maskBit(const void* data, unsigned dataLen, const void* mask, unsigned maskLen, bool cmpZero)
 
767
{
 
768
  /* Bitfields are stored in word oriented form, so we must compare them in that
 
769
   * style as well
 
770
   * It is assumed that insignificant bits (but not bytes) in the passed values
 
771
   * are zeroed
 
772
   */
 
773
  const Uint32 bytes = MIN(dataLen, maskLen);
 
774
  Uint32 words = (bytes + 3) >> 2;
 
775
 
 
776
  /* Don't expect either value to be length zero */
 
777
  assert(words);
 
778
 
 
779
  /* Check ptr alignment */
 
780
  if (unlikely(((((UintPtr)data) & 3) != 0) ||
 
781
               ((((UintPtr)mask) & 3) != 0)))
 
782
  {
 
783
    Uint32 copydata[ MAX_TUPLE_SIZE_IN_WORDS ];
 
784
    Uint32 copymask[ MAX_TUPLE_SIZE_IN_WORDS ];
 
785
    memcpy(copydata, data, words << 2);
 
786
    memcpy(copymask, mask, words << 2);
 
787
 
 
788
    return maskBit(data, bytes, mask, bytes, cmpZero);
 
789
  }
 
790
 
 
791
  const Uint32* wdata= (const Uint32*) data;
 
792
  const Uint32* wmask= (const Uint32*) mask;
 
793
 
 
794
  if (cmpZero)
 
795
  {
 
796
    while (--words)
 
797
    {
 
798
      if ((*(wdata++) & *(wmask++)) != 0)
 
799
        return 1;
 
800
    }
 
801
    
 
802
    /* For the last word, we mask out any insignificant bytes */
 
803
    const Uint32 sigBytes= bytes & 3; // 0..3; 0 == all bytes significant
 
804
    const Uint32 comparisonMask= sigBytes?
 
805
      (1 << (sigBytes *8)) -1 :
 
806
      ~0;
 
807
    const Uint32 lastDataWord= *wdata & comparisonMask;
 
808
    const Uint32 lastMaskWord= *wmask & comparisonMask;
 
809
    
 
810
    if ((lastDataWord & lastMaskWord) != 0)
 
811
      return 1;
 
812
 
 
813
    return 0;
 
814
  }
 
815
  else
 
816
  {
 
817
    while (--words)
 
818
    {
 
819
      if ((*(wdata++) & *wmask) != *wmask)
 
820
        return 1;
 
821
      
 
822
      wmask++;
 
823
    }
 
824
 
 
825
    /* For the last word, we mask out any insignificant bytes */
 
826
    const Uint32 sigBytes= bytes & 3; // 0..3; 0 == all bytes significant
 
827
    const Uint32 comparisonMask= sigBytes?
 
828
      (1 << (sigBytes *8)) -1 :
 
829
      ~0;
 
830
    const Uint32 lastDataWord= *wdata & comparisonMask;
 
831
    const Uint32 lastMaskWord= *wmask & comparisonMask;
 
832
    
 
833
    if ((lastDataWord & lastMaskWord) != lastMaskWord)
 
834
      return 1;
 
835
 
 
836
    return 0;
 
837
  }
 
838
}
 
839
 
 
840
 
 
841
// check charset
 
842
 
 
843
uint
 
844
NdbSqlUtil::check_column_for_pk(Uint32 typeId, const void* info)
 
845
{
 
846
  const Type& type = getType(typeId);
 
847
  switch (type.m_typeId) {
 
848
  case Type::Char:
 
849
  case Type::Varchar:
 
850
  case Type::Longvarchar:
 
851
    {
 
852
      const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
 
853
      if(cs != 0 &&
 
854
         cs->cset != 0 &&
 
855
         cs->coll != 0 &&
 
856
         cs->coll->strnxfrm != 0 &&
 
857
         cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY)
 
858
        return 0;
 
859
      else
 
860
        return 743;
 
861
    }
 
862
    break;
 
863
  case Type::Undefined:
 
864
  case Type::Blob:
 
865
  case Type::Text:
 
866
  case Type::Bit:
 
867
    break;
 
868
  default:
 
869
    return 0;
 
870
  }
 
871
  return 906;
 
872
}
 
873
 
 
874
uint
 
875
NdbSqlUtil::check_column_for_hash_index(Uint32 typeId, const void* info)
 
876
{
 
877
  return check_column_for_pk(typeId, info);
 
878
}
 
879
 
 
880
uint
 
881
NdbSqlUtil::check_column_for_ordered_index(Uint32 typeId, const void* info)
 
882
{
 
883
  const Type& type = getType(typeId);
 
884
  if (type.m_cmp == NULL)
 
885
    return false;
 
886
  switch (type.m_typeId) {
 
887
  case Type::Char:
 
888
  case Type::Varchar:
 
889
  case Type::Longvarchar:
 
890
    {
 
891
      const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
 
892
      if (cs != 0 &&
 
893
          cs->cset != 0 &&
 
894
          cs->coll != 0 &&
 
895
          cs->coll->strnxfrm != 0 &&
 
896
          cs->coll->strnncollsp != 0 &&
 
897
          cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY)
 
898
        return 0;
 
899
      else
 
900
        return 743;
 
901
    }
 
902
    break;
 
903
  case Type::Undefined:
 
904
  case Type::Blob:
 
905
  case Type::Text:
 
906
  case Type::Bit:       // can be fixed
 
907
    break;
 
908
  default:
 
909
    return 0;
 
910
  }
 
911
  return 906;
 
912
}
 
913
 
 
914
// utilities
 
915
 
 
916
bool
 
917
NdbSqlUtil::get_var_length(Uint32 typeId, const void* p, unsigned attrlen, Uint32& lb, Uint32& len)
 
918
{
 
919
  const unsigned char* const src = (const unsigned char*)p;
 
920
  switch (typeId) {
 
921
  case NdbSqlUtil::Type::Varchar:
 
922
  case NdbSqlUtil::Type::Varbinary:
 
923
    lb = 1;
 
924
    if (attrlen >= lb) {
 
925
      len = src[0];
 
926
      if (attrlen >= lb + len)
 
927
        return true;
 
928
    }
 
929
    break;
 
930
  case NdbSqlUtil::Type::Longvarchar:
 
931
  case NdbSqlUtil::Type::Longvarbinary:
 
932
    lb = 2;
 
933
    if (attrlen >= lb) {
 
934
      len = src[0] + (src[1] << 8);
 
935
      if (attrlen >= lb + len)
 
936
        return true;
 
937
    }
 
938
    break;
 
939
  default:
 
940
    lb = 0;
 
941
    len = attrlen;
 
942
    return true;
 
943
    break;
 
944
  }
 
945
  return false;
 
946
}
 
947
 
 
948
 
 
949
size_t
 
950
NdbSqlUtil::ndb_strnxfrm(struct charset_info_st * cs,
 
951
                         uchar *dst, size_t dstlen,
 
952
                         const uchar *src, size_t srclen)
 
953
{
 
954
#if NDB_MYSQL_VERSION_D < NDB_MAKE_VERSION(5,6,0)
 
955
  return (*cs->coll->strnxfrm)(cs, dst, dstlen, src, srclen);
 
956
#else
 
957
  /*
 
958
    strnxfrm has got two new parameters in 5.6, we are using the
 
959
    defaults for those and can thus easily calculate them from
 
960
    existing params
 
961
  */
 
962
  return  (*cs->coll->strnxfrm)(cs, dst, dstlen, dstlen,
 
963
                                src, srclen, MY_STRXFRM_PAD_WITH_SPACE);
 
964
#endif
 
965
}
 
966
 
 
967
// workaround
 
968
 
 
969
int
 
970
NdbSqlUtil::strnxfrm_bug7284(CHARSET_INFO* cs, unsigned char* dst, unsigned dstLen, const unsigned char*src, unsigned srcLen)
 
971
{
 
972
  unsigned char nsp[20]; // native space char
 
973
  unsigned char xsp[20]; // strxfrm-ed space char
 
974
#ifdef VM_TRACE
 
975
  memset(nsp, 0x1f, sizeof(nsp));
 
976
  memset(xsp, 0x1f, sizeof(xsp));
 
977
#endif
 
978
  // convert from unicode codepoint for space
 
979
  int n1 = (*cs->cset->wc_mb)(cs, (my_wc_t)0x20, nsp, nsp + sizeof(nsp));
 
980
  if (n1 <= 0)
 
981
    return -1;
 
982
  // strxfrm to binary
 
983
  int n2 = ndb_strnxfrm(cs, xsp, sizeof(xsp), nsp, n1);
 
984
  if (n2 <= 0)
 
985
    return -1;
 
986
  // XXX bug workaround - strnxfrm may not write full string
 
987
  memset(dst, 0x0, dstLen);
 
988
  // strxfrm argument string - returns no error indication
 
989
  int n3 = ndb_strnxfrm(cs, dst, dstLen, src, srcLen);
 
990
  // pad with strxfrm-ed space chars
 
991
  int n4 = n3;
 
992
  while (n4 < (int)dstLen) {
 
993
    dst[n4] = xsp[(n4 - n3) % n2];
 
994
    n4++;
 
995
  }
 
996
  // no check for partial last
 
997
  return dstLen;
 
998
}
 
999
 
 
1000
#if defined(WORDS_BIGENDIAN) || defined (VM_TRACE)
 
1001
 
 
1002
static
 
1003
void determineParams(Uint32 typeId,
 
1004
                     Uint32 typeLog2Size,
 
1005
                     Uint32 arrayType,
 
1006
                     Uint32 arraySize,
 
1007
                     Uint32 dataByteSize,
 
1008
                     Uint32& convSize,
 
1009
                     Uint32& convLen)
 
1010
{
 
1011
  /* Some types need 'normal behaviour' over-ridden in
 
1012
   * terms of endian-ness conversions
 
1013
   */
 
1014
  convSize = 0;
 
1015
  convLen = 0;
 
1016
  switch(typeId)
 
1017
  {
 
1018
  case NdbSqlUtil::Type::Datetime:
 
1019
  {
 
1020
    // Datetime is stored as 8x8, should be twiddled as 64 bit
 
1021
    assert(typeLog2Size == 3);
 
1022
    assert(arraySize == 8);
 
1023
    assert(dataByteSize == 8);
 
1024
    convSize = 64;
 
1025
    convLen = 1;
 
1026
    break;
 
1027
  }
 
1028
  case NdbSqlUtil::Type::Timestamp:
 
1029
  {
 
1030
    // Timestamp is stored as 4x8, should be twiddled as 32 bit
 
1031
    assert(typeLog2Size == 3);
 
1032
    assert(arraySize == 4);
 
1033
    assert(dataByteSize == 4);
 
1034
    convSize = 32;
 
1035
    convLen = 1;
 
1036
    break;
 
1037
  }
 
1038
  case NdbSqlUtil::Type::Bit:
 
1039
  {
 
1040
    // Bit is stored as bits, should be twiddled as 32 bit
 
1041
    assert(typeLog2Size == 0);
 
1042
    convSize = 32;
 
1043
    convLen = (arraySize + 31)/32;
 
1044
    break;
 
1045
  }
 
1046
  case NdbSqlUtil::Type::Blob:
 
1047
  case NdbSqlUtil::Type::Text:
 
1048
  {
 
1049
    if (arrayType == NDB_ARRAYTYPE_FIXED)
 
1050
    {
 
1051
      // Length of fixed size blob which is stored in first 64 bit's
 
1052
      // has to be twiddled, the remaining byte stream left as is
 
1053
      assert(typeLog2Size == 3);
 
1054
      assert(arraySize > 8);
 
1055
      assert(dataByteSize > 8);
 
1056
      convSize = 64;
 
1057
      convLen = 1;
 
1058
      break;
 
1059
    }
 
1060
    // Fall through for Blob v2
 
1061
  }
 
1062
  default:
 
1063
    /* Default determined by meta-info */
 
1064
    convSize = 1 << typeLog2Size;
 
1065
    convLen = arraySize;
 
1066
    break;
 
1067
  }
 
1068
 
 
1069
  const Uint32 unitBytes = (convSize >> 3);
 
1070
  
 
1071
  if (dataByteSize < (unitBytes * convLen))
 
1072
  {
 
1073
    /* Actual data is shorter than expected, could
 
1074
     * be VAR type or bad FIXED data (which some other
 
1075
     * code should detect + handle)
 
1076
     * We reduce convLen to avoid trampling
 
1077
     */
 
1078
    assert((dataByteSize % unitBytes) == 0);
 
1079
    convLen = dataByteSize / unitBytes;
 
1080
  }
 
1081
 
 
1082
  assert(convSize);
 
1083
  assert(convLen);
 
1084
  assert(dataByteSize >= (unitBytes * convLen));
 
1085
}
 
1086
 
 
1087
static
 
1088
void doConvert(Uint32 convSize,
 
1089
               Uint32 convLen,
 
1090
               uchar* data)
 
1091
{
 
1092
  switch(convSize)
 
1093
  {
 
1094
  case 8:
 
1095
    /* Nothing to swap */
 
1096
    break;
 
1097
  case 16:
 
1098
  {
 
1099
    Uint16* ptr = (Uint16*)data;
 
1100
    for (Uint32 i = 0; i < convLen; i++){
 
1101
      Uint16 val = 
 
1102
        ((*ptr & 0xFF00) >> 8) |
 
1103
        ((*ptr & 0x00FF) << 8);
 
1104
      *ptr = val;
 
1105
      ptr++;
 
1106
    }
 
1107
    break;
 
1108
  }
 
1109
  case 32:
 
1110
  {
 
1111
    Uint32* ptr = (Uint32*)data;
 
1112
    for (Uint32 i = 0; i < convLen; i++){
 
1113
      Uint32 val = 
 
1114
        ((*ptr & 0xFF000000) >> 24) |
 
1115
        ((*ptr & 0x00FF0000) >> 8)  |
 
1116
        ((*ptr & 0x0000FF00) << 8)  |
 
1117
        ((*ptr & 0x000000FF) << 24);
 
1118
      *ptr = val;
 
1119
      ptr++;
 
1120
    }
 
1121
    break;
 
1122
  }
 
1123
  case 64:
 
1124
  {
 
1125
    Uint64* ptr = (Uint64*)data;
 
1126
    for (Uint32 i = 0; i < convLen; i++){
 
1127
      Uint64 val = 
 
1128
        ((*ptr & (Uint64)0xFF00000000000000LL) >> 56) |
 
1129
        ((*ptr & (Uint64)0x00FF000000000000LL) >> 40) |
 
1130
        ((*ptr & (Uint64)0x0000FF0000000000LL) >> 24) |
 
1131
        ((*ptr & (Uint64)0x000000FF00000000LL) >> 8)  |
 
1132
        ((*ptr & (Uint64)0x00000000FF000000LL) << 8)  |
 
1133
        ((*ptr & (Uint64)0x0000000000FF0000LL) << 24) |
 
1134
        ((*ptr & (Uint64)0x000000000000FF00LL) << 40) |
 
1135
        ((*ptr & (Uint64)0x00000000000000FFLL) << 56);
 
1136
      *ptr = val;
 
1137
      ptr++;
 
1138
    }
 
1139
    break;
 
1140
  }
 
1141
  default:
 
1142
    abort();
 
1143
    break;
 
1144
  }
 
1145
}
 
1146
#endif
 
1147
 
 
1148
/**
 
1149
 * Convert attribute byte order if necessary
 
1150
 */
 
1151
void
 
1152
NdbSqlUtil::convertByteOrder(Uint32 typeId, 
 
1153
                             Uint32 typeLog2Size, 
 
1154
                             Uint32 arrayType, 
 
1155
                             Uint32 arraySize, 
 
1156
                             uchar* data,
 
1157
                             Uint32 dataByteSize)
 
1158
{
 
1159
#if defined(WORDS_BIGENDIAN) || defined (VM_TRACE)
 
1160
  Uint32 convSize;
 
1161
  Uint32 convLen;
 
1162
  determineParams(typeId,
 
1163
                  typeLog2Size,
 
1164
                  arrayType,
 
1165
                  arraySize,
 
1166
                  dataByteSize,
 
1167
                  convSize,
 
1168
                  convLen);
 
1169
 
 
1170
  size_t mask = (((size_t) convSize) >> 3) -1; // Bottom 0,1,2,3 bits set
 
1171
  bool aligned = (((size_t) data) & mask) == 0;
 
1172
  uchar* dataPtr = data;
 
1173
  const Uint32 bufSize = (MAX_TUPLE_SIZE_IN_WORDS + 1)/2;
 
1174
  Uint64 alignedBuf[bufSize];
 
1175
  
 
1176
  if (!aligned)
 
1177
  {
 
1178
    assert(dataByteSize <= 4 * MAX_TUPLE_SIZE_IN_WORDS);
 
1179
    memcpy(alignedBuf, data, dataByteSize);
 
1180
    dataPtr = (uchar*) alignedBuf;
 
1181
  }
 
1182
 
 
1183
  /* Now have convSize and convLen, do the conversion */
 
1184
  doConvert(convSize,
 
1185
            convLen,
 
1186
            dataPtr);
 
1187
 
 
1188
#ifdef VM_TRACE
 
1189
#ifndef WORDS_BIGENDIAN
 
1190
  // VM trace on little-endian performs double-convert
 
1191
  doConvert(convSize,
 
1192
            convLen,
 
1193
            dataPtr);
 
1194
#endif
 
1195
#endif
 
1196
 
 
1197
  if (!aligned)
 
1198
  {
 
1199
    memcpy(data, alignedBuf, dataByteSize);
 
1200
  }  
 
1201
#endif
 
1202
}
 
1203