NdbSqlUtil.cpp 22.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/* Copyright (C) 2003 MySQL AB

   This program is free software; you can redistribute it and/or modify
   it under the terms of the GNU General Public License as published by
   the Free Software Foundation; either version 2 of the License, or
   (at your option) any later version.

   This program is distributed in the hope that it will be useful,
   but WITHOUT ANY WARRANTY; without even the implied warranty of
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
   GNU General Public License for more details.

   You should have received a copy of the GNU General Public License
   along with this program; if not, write to the Free Software
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */

#include <NdbSqlUtil.hpp>
18
#include <NdbOut.hpp>
19
#include <my_sys.h>
20

unknown's avatar
unknown committed
21
/*
unknown's avatar
unknown committed
22
 * Data types.  The entries must be in the numerical order.
23 24 25 26
 */

const NdbSqlUtil::Type
NdbSqlUtil::m_typeList[] = {
27
  { // 0
28
    Type::Undefined,
29
    NULL,
30 31
    NULL
  },
32
  { // 1
33
    Type::Tinyint,
34 35
    cmpTinyint,
    NULL
36
  },
37
  { // 2
38
    Type::Tinyunsigned,
39 40
    cmpTinyunsigned,
    NULL
41
  },
42
  { // 3
43
    Type::Smallint,
44 45
    cmpSmallint,
    NULL
46
  },
47
  { // 4
48
    Type::Smallunsigned,
49 50
    cmpSmallunsigned,
    NULL
51
  },
52
  { // 5
53
    Type::Mediumint,
54 55
    cmpMediumint,
    NULL
56
  },
57
  { // 6
58
    Type::Mediumunsigned,
59 60
    cmpMediumunsigned,
    NULL
61
  },
62
  { // 7
63
    Type::Int,
64 65
    cmpInt,
    NULL
66
  },
67
  { // 8
68
    Type::Unsigned,
69 70
    cmpUnsigned,
    NULL
71
  },
72
  { // 9
73
    Type::Bigint,
74 75
    cmpBigint,
    NULL
76
  },
77
  { // 10
78
    Type::Bigunsigned,
79 80
    cmpBigunsigned,
    NULL
81
  },
82
  { // 11
83
    Type::Float,
84 85
    cmpFloat,
    NULL
86
  },
87
  { // 12
88
    Type::Double,
89 90
    cmpDouble,
    NULL
91
  },
92 93
  { // 13
    Type::Olddecimal,
94 95
    cmpOlddecimal,
    NULL
96
  },
97
  { // 14
98
    Type::Char,
99 100
    cmpChar,
    likeChar
101
  },
102
  { // 15
103
    Type::Varchar,
104 105
    cmpVarchar,
    likeVarchar
106
  },
107
  { // 16
108
    Type::Binary,
109
    cmpBinary,
110
    likeBinary
111
  },
112
  { // 17
113
    Type::Varbinary,
114
    cmpVarbinary,
115
    likeVarbinary
116
  },
117
  { // 18
118
    Type::Datetime,
119 120
    cmpDatetime,
    NULL
121
  },
122
  { // 19
unknown's avatar
unknown committed
123
    Type::Date,
124 125
    cmpDate,
    NULL
unknown's avatar
unknown committed
126
  },
127
  { // 20
unknown's avatar
unknown committed
128
    Type::Blob,
129 130
    NULL,
    NULL
unknown's avatar
unknown committed
131
  },
132
  { // 21
unknown's avatar
unknown committed
133
    Type::Text,
134 135
    NULL,
    NULL
unknown's avatar
unknown committed
136
  },
137
  { // 22
unknown's avatar
unknown committed
138
    Type::Bit,
139 140
    NULL,
    NULL
unknown's avatar
unknown committed
141
  },
142
  { // 23
unknown's avatar
unknown committed
143
    Type::Longvarchar,
144 145
    cmpLongvarchar,
    likeLongvarchar
unknown's avatar
unknown committed
146
  },
147
  { // 24
unknown's avatar
unknown committed
148
    Type::Longvarbinary,
149
    cmpLongvarbinary,
150
    likeLongvarbinary
unknown's avatar
unknown committed
151
  },
152
  { // 25
unknown's avatar
unknown committed
153
    Type::Time,
154 155
    cmpTime,
    NULL
156
  },
157
  { // 26
158
    Type::Year,
159 160
    cmpYear,
    NULL
161
  },
162
  { // 27
163
    Type::Timestamp,
164 165
    cmpTimestamp,
    NULL
166 167 168
  },
  { // 28
    Type::Olddecimalunsigned,
169 170
    cmpOlddecimalunsigned,
    NULL
171 172 173
  },
  { // 29
    Type::Decimal,
174 175
    cmpDecimal,
    NULL
176 177 178
  },
  { // 30
    Type::Decimalunsigned,
179 180
    cmpDecimalunsigned,
    NULL
181 182 183 184
  }
};

const NdbSqlUtil::Type&
185
NdbSqlUtil::getType(Uint32 typeId)
186 187 188 189 190 191 192 193
{
  if (typeId < sizeof(m_typeList) / sizeof(m_typeList[0]) &&
      m_typeList[typeId].m_typeId != Type::Undefined) {
    return m_typeList[typeId];
  }
  return m_typeList[Type::Undefined];
}

unknown's avatar
unknown committed
194 195 196 197 198 199
const NdbSqlUtil::Type&
NdbSqlUtil::getTypeBinary(Uint32 typeId)
{
  switch (typeId) {
  case Type::Char:
  case Type::Varchar:
unknown's avatar
unknown committed
200 201 202 203 204
  case Type::Binary:
  case Type::Varbinary:
  case Type::Longvarchar:
  case Type::Longvarbinary:
    typeId = Type::Binary;
unknown's avatar
unknown committed
205 206 207 208 209 210 211 212 213 214
    break;
  case Type::Text:
    typeId = Type::Blob;
    break;
  default:
    break;
  }
  return getType(typeId);
}

unknown's avatar
unknown committed
215 216 217
/*
 * Comparison functions.
 */
218 219

int
unknown's avatar
unknown committed
220
NdbSqlUtil::cmpTinyint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
221
{
unknown's avatar
unknown committed
222 223 224 225 226 227 228 229 230 231 232 233
  if (n2 >= sizeof(Int8)) {
    Int8 v1, v2;
    memcpy(&v1, p1, sizeof(Int8));
    memcpy(&v2, p2, sizeof(Int8));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
234 235 236
}

int
unknown's avatar
unknown committed
237
NdbSqlUtil::cmpTinyunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
238
{
unknown's avatar
unknown committed
239 240 241 242 243 244 245 246 247 248 249 250
  if (n2 >= sizeof(Uint8)) {
    Uint8 v1, v2;
    memcpy(&v1, p1, sizeof(Uint8));
    memcpy(&v2, p2, sizeof(Uint8));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
251 252 253
}

int
unknown's avatar
unknown committed
254
NdbSqlUtil::cmpSmallint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
255
{
unknown's avatar
unknown committed
256 257 258 259 260 261 262 263 264 265 266 267
  if (n2 >= sizeof(Int16)) {
    Int16 v1, v2;
    memcpy(&v1, p1, sizeof(Int16));
    memcpy(&v2, p2, sizeof(Int16));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
268 269 270
}

int
unknown's avatar
unknown committed
271
NdbSqlUtil::cmpSmallunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
272
{
unknown's avatar
unknown committed
273 274 275 276 277 278 279 280 281 282 283 284
  if (n2 >= sizeof(Uint16)) {
    Uint16 v1, v2;
    memcpy(&v1, p1, sizeof(Uint16));
    memcpy(&v2, p2, sizeof(Uint16));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
285 286 287
}

int
unknown's avatar
unknown committed
288
NdbSqlUtil::cmpMediumint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
289
{
unknown's avatar
unknown committed
290 291 292 293 294 295 296 297 298 299 300 301
  if (n2 >= 3) {
    Int32 v1, v2;
    v1 = sint3korr((const uchar*)p1);
    v2 = sint3korr((const uchar*)p2);
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
302 303 304
}

int
unknown's avatar
unknown committed
305
NdbSqlUtil::cmpMediumunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
306
{
unknown's avatar
unknown committed
307 308 309 310 311 312 313 314 315 316 317 318
  if (n2 >= 3) {
    Uint32 v1, v2;
    v1 = uint3korr((const uchar*)p1);
    v2 = uint3korr((const uchar*)p2);
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
319 320 321
}

int
unknown's avatar
unknown committed
322
NdbSqlUtil::cmpInt(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
323
{
unknown's avatar
unknown committed
324 325 326 327 328 329 330 331 332 333 334 335
  if (n2 >= sizeof(Int32)) {
    Int32 v1, v2;
    memcpy(&v1, p1, sizeof(Int32));
    memcpy(&v2, p2, sizeof(Int32));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
336 337 338
}

int
unknown's avatar
unknown committed
339
NdbSqlUtil::cmpUnsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
340
{
unknown's avatar
unknown committed
341 342 343 344 345 346 347 348 349 350 351 352
  if (n2 >= sizeof(Uint32)) {
    Uint32 v1, v2;
    memcpy(&v1, p1, sizeof(Uint32));
    memcpy(&v2, p2, sizeof(Uint32));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
353 354 355
}

int
unknown's avatar
unknown committed
356
NdbSqlUtil::cmpBigint(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
357
{
unknown's avatar
unknown committed
358 359 360 361 362
  if (n2 >= sizeof(Int64)) {
    Int64 v1, v2;
    memcpy(&v1, p1, sizeof(Int64));
    memcpy(&v2, p2, sizeof(Int64));
    if (v1 < v2)
363
      return -1;
unknown's avatar
unknown committed
364
    if (v1 > v2)
365 366 367
      return +1;
    return 0;
  }
unknown's avatar
unknown committed
368
  assert(! full);
369
  return CmpUnknown;
370 371 372
}

int
unknown's avatar
unknown committed
373
NdbSqlUtil::cmpBigunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
374
{
unknown's avatar
unknown committed
375 376 377 378 379
  if (n2 >= sizeof(Uint64)) {
    Uint64 v1, v2;
    memcpy(&v1, p1, sizeof(Uint64));
    memcpy(&v2, p2, sizeof(Uint64));
    if (v1 < v2)
380
      return -1;
unknown's avatar
unknown committed
381
    if (v1 > v2)
382 383 384
      return +1;
    return 0;
  }
unknown's avatar
unknown committed
385
  assert(! full);
386
  return CmpUnknown;
387 388 389
}

int
unknown's avatar
unknown committed
390
NdbSqlUtil::cmpFloat(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
391
{
unknown's avatar
unknown committed
392 393 394 395 396 397 398 399 400 401 402 403
  if (n2 >= sizeof(float)) {
    float v1, v2;
    memcpy(&v1, p1, sizeof(float));
    memcpy(&v2, p2, sizeof(float));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
404 405 406
}

int
unknown's avatar
unknown committed
407
NdbSqlUtil::cmpDouble(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
408
{
unknown's avatar
unknown committed
409 410 411 412 413
  if (n2 >= sizeof(double)) {
    double v1, v2;
    memcpy(&v1, p1, sizeof(double));
    memcpy(&v2, p2, sizeof(double));
    if (v1 < v2)
414
      return -1;
unknown's avatar
unknown committed
415
    if (v1 > v2)
416 417 418
      return +1;
    return 0;
  }
unknown's avatar
unknown committed
419
  assert(! full);
420
  return CmpUnknown;
421 422
}

unknown's avatar
unknown committed
423
int
424
NdbSqlUtil::cmp_olddecimal(const uchar* s1, const uchar* s2, unsigned n)
425
{
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
  int sgn = +1;
  unsigned i = 0;
  while (i < n) {
    int c1 = s1[i];
    int c2 = s2[i];
    if (c1 == c2) {
      if (c1 == '-')
        sgn = -1;
    } else if (c1 == '-') {
      return -1;
    } else if (c2 == '-') {
      return +1;
    } else if (c1 < c2) {
      return -1 * sgn;
    } else {
      return +1 * sgn;
    }
    i++;
  }
445
  return 0;
446 447
}

448
int
unknown's avatar
Merge  
unknown committed
449
NdbSqlUtil::cmpOlddecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
450
{
unknown's avatar
Merge  
unknown committed
451 452 453 454 455
  if (full) {
    assert(n1 == n2);
    const uchar* v1 = (const uchar*)p1;
    const uchar* v2 = (const uchar*)p2;
    return cmp_olddecimal(v1, v2, n1);
456 457 458 459 460
  }
  return CmpUnknown;
}

int
unknown's avatar
Merge  
unknown committed
461
NdbSqlUtil::cmpOlddecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
462
{
unknown's avatar
Merge  
unknown committed
463 464 465 466 467
  if (full) {
    assert(n1 == n2);
    const uchar* v1 = (const uchar*)p1;
    const uchar* v2 = (const uchar*)p2;
    return cmp_olddecimal(v1, v2, n1);
468 469 470 471
  }
  return CmpUnknown;
}

472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499
int
NdbSqlUtil::cmpDecimal(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
  const uchar* v1 = (const uchar*)p1;
  const uchar* v2 = (const uchar*)p2;
  // compare as binary strings
  unsigned n = (n1 <= n2 ? n1 : n2);
  int k = memcmp(v1, v2, n);
  if (k == 0) {
    k = (full ? n1 : n) - n2;
  }
  return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
}

int
NdbSqlUtil::cmpDecimalunsigned(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
  const uchar* v1 = (const uchar*)p1;
  const uchar* v2 = (const uchar*)p2;
  // compare as binary strings
  unsigned n = (n1 <= n2 ? n1 : n2);
  int k = memcmp(v1, v2, n);
  if (k == 0) {
    k = (full ? n1 : n) - n2;
  }
  return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
}

500
int
unknown's avatar
unknown committed
501
NdbSqlUtil::cmpChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
502
{
503
  // collation does not work on prefix for some charsets
unknown's avatar
unknown committed
504 505 506
  assert(full);
  const uchar* v1 = (const uchar*)p1;
  const uchar* v2 = (const uchar*)p2;
507 508
  // not const in MySQL
  CHARSET_INFO* cs = (CHARSET_INFO*)(info);
unknown's avatar
unknown committed
509 510
  // compare with space padding
  int k = (*cs->coll->strnncollsp)(cs, v1, n1, v2, n2, false);
511
  return k < 0 ? -1 : k > 0 ? +1 : 0;
512 513 514
}

int
unknown's avatar
unknown committed
515
NdbSqlUtil::cmpVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
516
{
unknown's avatar
unknown committed
517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534
  const unsigned lb = 1;
  // collation does not work on prefix for some charsets
  assert(full && n1 >= lb && n2 >= lb);
  const uchar* v1 = (const uchar*)p1;
  const uchar* v2 = (const uchar*)p2;
  unsigned m1 = *v1;
  unsigned m2 = *v2;
  if (m1 <= n1 - lb && m2 <= n2 - lb) {
    CHARSET_INFO* cs = (CHARSET_INFO*)(info);
    // compare with space padding
    int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
    return k < 0 ? -1 : k > 0 ? +1 : 0;
  }
  // treat bad data as NULL
  if (m1 > n1 - lb && m2 <= n2 - lb)
    return -1;
  if (m1 <= n1 - lb && m2 > n2 - lb)
    return +1;
unknown's avatar
unknown committed
535
  return 0;
536 537 538
}

int
unknown's avatar
unknown committed
539
NdbSqlUtil::cmpBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
540
{
unknown's avatar
unknown committed
541 542 543 544 545 546
  const uchar* v1 = (const uchar*)p1;
  const uchar* v2 = (const uchar*)p2;
  // compare as binary strings
  unsigned n = (n1 <= n2 ? n1 : n2);
  int k = memcmp(v1, v2, n);
  if (k == 0) {
unknown's avatar
unknown committed
547
    k = (full ? n1 : n) - n2;
unknown's avatar
unknown committed
548 549
  }
  return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
550 551 552
}

int
unknown's avatar
unknown committed
553
NdbSqlUtil::cmpVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
554
{
unknown's avatar
unknown committed
555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579
  const unsigned lb = 1;
  if (n2 >= lb) {
    assert(n1 >= lb);
    const uchar* v1 = (const uchar*)p1;
    const uchar* v2 = (const uchar*)p2;
    unsigned m1 = *v1;
    unsigned m2 = *v2;
    if (m1 <= n1 - lb && m2 <= n2 - lb) {
      // compare as binary strings
      unsigned m = (m1 <= m2 ? m1 : m2);
      int k = memcmp(v1 + lb, v2 + lb, m);
      if (k == 0) {
        k = (full ? m1 : m) - m2;
      }
      return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
    }
    // treat bad data as NULL
    if (m1 > n1 - lb && m2 <= n2 - lb)
      return -1;
    if (m1 <= n1 - lb && m2 > n2 - lb)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
580 581 582
}

int
unknown's avatar
unknown committed
583
NdbSqlUtil::cmpDatetime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
584
{
unknown's avatar
Merge  
unknown committed
585 586 587 588 589
  if (n2 >= sizeof(Int64)) {
    Int64 v1, v2;
    memcpy(&v1, p1, sizeof(Int64));
    memcpy(&v2, p2, sizeof(Int64));
    if (v1 < v2)
590
      return -1;
unknown's avatar
Merge  
unknown committed
591
    if (v1 > v2)
592 593
      return +1;
    return 0;
594
  }
unknown's avatar
Merge  
unknown committed
595
  assert(! full);
596
  return CmpUnknown;
597 598 599
}

int
unknown's avatar
Merge  
unknown committed
600
NdbSqlUtil::cmpDate(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
601
{
unknown's avatar
unknown committed
602
#ifdef ndb_date_is_4_byte_native_int
unknown's avatar
Merge  
unknown committed
603 604 605 606 607 608 609 610 611 612
  if (n2 >= sizeof(Int32)) {
    Int32 v1, v2;
    memcpy(&v1, p1, sizeof(Int32));
    memcpy(&v2, p2, sizeof(Int32));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
unknown's avatar
unknown committed
613
#else
614
#ifdef ndb_date_sol9x86_cc_xO3_madness
unknown's avatar
unknown committed
615
  if (n2 >= 3) {
unknown's avatar
Merge  
unknown committed
616 617 618 619 620 621 622 623 624 625 626 627 628
    const uchar* v1 = (const uchar*)p1;
    const uchar* v2 = (const uchar*)p2;
    // from Field_newdate::val_int
    Uint64 j1 = uint3korr(v1);
    Uint64 j2 = uint3korr(v2);
    j1 = (j1 % 32L)+(j1 / 32L % 16L)*100L + (j1/(16L*32L))*10000L;
    j2 = (j2 % 32L)+(j2 / 32L % 16L)*100L + (j2/(16L*32L))*10000L;
    if (j1 < j2)
      return -1;
    if (j1 > j2)
      return +1;
    return 0;
  }
629
#else
unknown's avatar
unknown committed
630
  if (n2 >= 3) {
unknown's avatar
Merge  
unknown committed
631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
    const uchar* v1 = (const uchar*)p1;
    const uchar* v2 = (const uchar*)p2;
    uint j1 = uint3korr(v1);
    uint j2 = uint3korr(v2);
    uint d1 = (j1 & 31);
    uint d2 = (j2 & 31);
    j1 = (j1 >> 5);
    j2 = (j2 >> 5);
    uint m1 = (j1 & 15);
    uint m2 = (j2 & 15);
    j1 = (j1 >> 4);
    j2 = (j2 >> 4);
    uint y1 = j1;
    uint y2 = j2;
    if (y1 < y2)
      return -1;
    if (y1 > y2)
      return +1;
    if (m1 < m2)
      return -1;
    if (m1 > m2)
      return +1;
    if (d1 < d2)
      return -1;
    if (d1 > d2)
      return +1;
    return 0;
  }
659
#endif
unknown's avatar
unknown committed
660
#endif
unknown's avatar
Merge  
unknown committed
661
  assert(! full);
unknown's avatar
unknown committed
662
  return CmpUnknown;
663 664
}

unknown's avatar
unknown committed
665
// not supported
unknown's avatar
unknown committed
666
int
unknown's avatar
unknown committed
667
NdbSqlUtil::cmpBlob(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
unknown's avatar
unknown committed
668
{
unknown's avatar
unknown committed
669 670
  assert(false);
  return 0;
unknown's avatar
unknown committed
671 672
}

unknown's avatar
unknown committed
673
// not supported
unknown's avatar
unknown committed
674
int
unknown's avatar
unknown committed
675
NdbSqlUtil::cmpText(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
unknown's avatar
unknown committed
676
{
unknown's avatar
unknown committed
677 678
  assert(false);
  return 0;
unknown's avatar
unknown committed
679 680
}

unknown's avatar
unknown committed
681
int
unknown's avatar
unknown committed
682
NdbSqlUtil::cmpTime(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
unknown's avatar
unknown committed
683
{
unknown's avatar
unknown committed
684
  if (n2 >= 3) {
unknown's avatar
Merge  
unknown committed
685 686 687
    const uchar* v1 = (const uchar*)p1;
    const uchar* v2 = (const uchar*)p2;
    // from Field_time::val_int
unknown's avatar
unknown committed
688 689
    Int32 j1 = sint3korr(v1);
    Int32 j2 = sint3korr(v2);
unknown's avatar
Merge  
unknown committed
690 691 692 693 694 695 696 697
    if (j1 < j2)
      return -1;
    if (j1 > j2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
unknown's avatar
unknown committed
698 699
}

unknown's avatar
unknown committed
700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761
// not yet
int
NdbSqlUtil::cmpBit(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
  assert(false);
  return 0;
}

int
NdbSqlUtil::cmpLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
  const unsigned lb = 2;
  // collation does not work on prefix for some charsets
  assert(full && n1 >= lb && n2 >= lb);
  const uchar* v1 = (const uchar*)p1;
  const uchar* v2 = (const uchar*)p2;
  unsigned m1 = uint2korr(v1);
  unsigned m2 = uint2korr(v2);
  if (m1 <= n1 - lb && m2 <= n2 - lb) {
    CHARSET_INFO* cs = (CHARSET_INFO*)(info);
    // compare with space padding
    int k = (*cs->coll->strnncollsp)(cs, v1 + lb, m1, v2 + lb, m2, false);
    return k < 0 ? -1 : k > 0 ? +1 : 0;
  }
  // treat bad data as NULL
  if (m1 > n1 - lb && m2 <= n2 - lb)
    return -1;
  if (m1 <= n1 - lb && m2 > n2 - lb)
    return +1;
  return 0;
}

int
NdbSqlUtil::cmpLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
  const unsigned lb = 2;
  if (n2 >= lb) {
    assert(n1 >= lb);
    const uchar* v1 = (const uchar*)p1;
    const uchar* v2 = (const uchar*)p2;
    unsigned m1 = uint2korr(v1);
    unsigned m2 = uint2korr(v2);
    if (m1 <= n1 - lb && m2 <= n2 - lb) {
      // compare as binary strings
      unsigned m = (m1 <= m2 ? m1 : m2);
      int k = memcmp(v1 + lb, v2 + lb, m);
      if (k == 0) {
        k = (full ? m1 : m) - m2;
      }
      return k < 0 ? -1 : k > 0 ? +1 : full ? 0 : CmpUnknown;
    }
    // treat bad data as NULL
    if (m1 > n1 - lb && m2 <= n2 - lb)
      return -1;
    if (m1 <= n1 - lb && m2 > n2 - lb)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
}

unknown's avatar
Merge  
unknown committed
762 763
int
NdbSqlUtil::cmpYear(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
764
{
unknown's avatar
Merge  
unknown committed
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793
  if (n2 >= sizeof(Uint8)) {
    Uint8 v1, v2;
    memcpy(&v1, p1, sizeof(Uint8));
    memcpy(&v2, p2, sizeof(Uint8));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
}

int
NdbSqlUtil::cmpTimestamp(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2, bool full)
{
  if (n2 >= sizeof(Uint32)) {
    Uint32 v1, v2;
    memcpy(&v1, p1, sizeof(Uint32));
    memcpy(&v2, p2, sizeof(Uint32));
    if (v1 < v2)
      return -1;
    if (v1 > v2)
      return +1;
    return 0;
  }
  assert(! full);
  return CmpUnknown;
794 795
}

796 797
// like

798 799 800 801
static const int ndb_wild_prefix = '\\';
static const int ndb_wild_one = '_';
static const int ndb_wild_many = '%';

802 803 804 805 806 807
int
NdbSqlUtil::likeChar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
{
  const char* v1 = (const char*)p1;
  const char* v2 = (const char*)p2;
  CHARSET_INFO* cs = (CHARSET_INFO*)(info);
808 809
  int k = (cs->coll->wildcmp)(cs, v1, v1 + n1, v2, v2 + n2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
  return k == 0 ? 0 : +1;
810 811
}

812 813 814 815 816 817 818
int
NdbSqlUtil::likeBinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
{
  assert(info == 0);
  return likeChar(&my_charset_bin, p1, n1, p2, n2);
}

819 820 821 822 823 824 825 826 827 828 829 830 831
int
NdbSqlUtil::likeVarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
{
  const unsigned lb = 1;
  if (n1 >= lb && n2 >= lb) {
    const uchar* v1 = (const uchar*)p1;
    const uchar* v2 = (const uchar*)p2;
    unsigned m1 = *v1;
    unsigned m2 = *v2;
    if (lb + m1 <= n1 && lb + m2 <= n2) {
      const char* w1 = (const char*)v1 + lb;
      const char* w2 = (const char*)v2 + lb;
      CHARSET_INFO* cs = (CHARSET_INFO*)(info);
832 833
      int k = (cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
      return k == 0 ? 0 : +1;
834 835 836 837 838
    }
  }
  return -1;
}

839 840 841 842 843 844 845
int
NdbSqlUtil::likeVarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
{
  assert(info == 0);
  return likeVarchar(&my_charset_bin, p1, n1, p2, n2);
}

846 847 848 849 850 851 852 853 854 855 856 857 858
int
NdbSqlUtil::likeLongvarchar(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
{
  const unsigned lb = 2;
  if (n1 >= lb && n2 >= lb) {
    const uchar* v1 = (const uchar*)p1;
    const uchar* v2 = (const uchar*)p2;
    unsigned m1 = uint2korr(v1);
    unsigned m2 = uint2korr(v2);
    if (lb + m1 <= n1 && lb + m2 <= n2) {
      const char* w1 = (const char*)v1 + lb;
      const char* w2 = (const char*)v2 + lb;
      CHARSET_INFO* cs = (CHARSET_INFO*)(info);
859 860
      int k = (cs->coll->wildcmp)(cs, w1, w1 + m1, w2, w2 + m2, ndb_wild_prefix, ndb_wild_one, ndb_wild_many);
      return k == 0 ? 0 : +1;
861 862 863 864 865
    }
  }
  return -1;
}

866 867 868 869 870 871 872
int
NdbSqlUtil::likeLongvarbinary(const void* info, const void* p1, unsigned n1, const void* p2, unsigned n2)
{
  assert(info == 0);
  return likeLongvarchar(&my_charset_bin, p1, n1, p2, n2);
}

unknown's avatar
unknown committed
873 874 875 876 877 878 879 880
// check charset

bool
NdbSqlUtil::usable_in_pk(Uint32 typeId, const void* info)
{
  const Type& type = getType(typeId);
  switch (type.m_typeId) {
  case Type::Char:
unknown's avatar
unknown committed
881 882
  case Type::Varchar:
  case Type::Longvarchar:
unknown's avatar
unknown committed
883 884 885 886 887 888 889
    {
      const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
      return
        cs != 0 &&
        cs->cset != 0 &&
        cs->coll != 0 &&
        cs->coll->strnxfrm != 0 &&
unknown's avatar
unknown committed
890
        cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY;
unknown's avatar
unknown committed
891 892
    }
    break;
unknown's avatar
unknown committed
893
  case Type::Undefined:
unknown's avatar
unknown committed
894 895
  case Type::Blob:
  case Type::Text:
unknown's avatar
unknown committed
896
  case Type::Bit:
unknown's avatar
unknown committed
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913
    break;
  default:
    return true;
  }
  return false;
}

bool
NdbSqlUtil::usable_in_hash_index(Uint32 typeId, const void* info)
{
  return usable_in_pk(typeId, info);
}

bool
NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info)
{
  const Type& type = getType(typeId);
unknown's avatar
unknown committed
914 915
  if (type.m_cmp == NULL)
    return false;
unknown's avatar
unknown committed
916 917
  switch (type.m_typeId) {
  case Type::Char:
unknown's avatar
unknown committed
918 919
  case Type::Varchar:
  case Type::Longvarchar:
unknown's avatar
unknown committed
920 921 922 923 924 925 926 927
    {
      const CHARSET_INFO *cs = (const CHARSET_INFO*)info;
      return
        cs != 0 &&
        cs->cset != 0 &&
        cs->coll != 0 &&
        cs->coll->strnxfrm != 0 &&
        cs->coll->strnncollsp != 0 &&
unknown's avatar
unknown committed
928
        cs->strxfrm_multiply <= MAX_XFRM_MULTIPLY;
unknown's avatar
unknown committed
929 930
    }
    break;
unknown's avatar
unknown committed
931 932
  case Type::Undefined:
  case Type::Blob:
unknown's avatar
unknown committed
933
  case Type::Text:
unknown's avatar
unknown committed
934
  case Type::Bit:       // can be fixed
unknown's avatar
unknown committed
935 936 937 938 939 940
    break;
  default:
    return true;
  }
  return false;
}
unknown's avatar
unknown committed
941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994

// utilities

bool
NdbSqlUtil::get_var_length(Uint32 typeId, const void* p, unsigned attrlen, Uint32& lb, Uint32& len)
{
  const unsigned char* const src = (const unsigned char*)p;
  switch (typeId) {
  case NdbSqlUtil::Type::Varchar:
  case NdbSqlUtil::Type::Varbinary:
    lb = 1;
    if (attrlen >= lb) {
      len = src[0];
      if (attrlen >= lb + len)
        return true;
    }
    break;
  case NdbSqlUtil::Type::Longvarchar:
  case NdbSqlUtil::Type::Longvarbinary:
    lb = 2;
    if (attrlen >= lb) {
      len = src[0] + (src[1] << 8);
      if (attrlen >= lb + len)
        return true;
    }
    break;
  default:
    lb = 0;
    len = attrlen;
    return true;
    break;
  }
  return false;
}

// workaround

int
NdbSqlUtil::strnxfrm_bug7284(CHARSET_INFO* cs, unsigned char* dst, unsigned dstLen, const unsigned char*src, unsigned srcLen)
{
  unsigned char nsp[20]; // native space char
  unsigned char xsp[20]; // strxfrm-ed space char
#ifdef VM_TRACE
  memset(nsp, 0x1f, sizeof(nsp));
  memset(xsp, 0x1f, sizeof(xsp));
#endif
  // convert from unicode codepoint for space
  int n1 = (*cs->cset->wc_mb)(cs, (my_wc_t)0x20, nsp, nsp + sizeof(nsp));
  if (n1 <= 0)
    return -1;
  // strxfrm to binary
  int n2 = (*cs->coll->strnxfrm)(cs, xsp, sizeof(xsp), nsp, n1);
  if (n2 <= 0)
    return -1;
995 996
  // XXX bug workaround - strnxfrm may not write full string
  memset(dst, 0x0, dstLen);
unknown's avatar
unknown committed
997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
  // strxfrm argument string - returns no error indication
  int n3 = (*cs->coll->strnxfrm)(cs, dst, dstLen, src, srcLen);
  // pad with strxfrm-ed space chars
  int n4 = n3;
  while (n4 < (int)dstLen) {
    dst[n4] = xsp[(n4 - n3) % n2];
    n4++;
  }
  // no check for partial last
  return dstLen;
}