1 /* -*- c-basic-offset: 2 -*- */ 2 /* 3 Copyright(C) 2012-2015 Kouhei Sutou <kou@clear-code.com> 4 Copyright(C) 2013 Kentoku SHIBA 5 6 This library is free software; you can redistribute it and/or 7 modify it under the terms of the GNU Lesser General Public 8 License as published by the Free Software Foundation; either 9 version 2.1 of the License, or (at your option) any later version. 10 11 This library is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14 Lesser General Public License for more details. 15 16 You should have received a copy of the GNU Lesser General Public 17 License along with this library; if not, write to the Free Software 18 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA 19 */ 20 21 #include <mrn_mysql.h> 22 23 #include "mrn_multiple_column_key_codec.hpp" 24 #include "mrn_field_normalizer.hpp" 25 #include "mrn_smart_grn_obj.hpp" 26 #include "mrn_time_converter.hpp" 27 #include "mrn_value_decoder.hpp" 28 29 // for debug 30 #define MRN_CLASS_NAME "mrn::MultipleColumnKeyCodec" 31 32 #ifdef WORDS_BIGENDIAN 33 #define mrn_byte_order_host_to_network(buf, key, size) \ 34 { \ 35 uint32 size_ = (uint32)(size); \ 36 uint8 *buf_ = (uint8 *)(buf); \ 37 uint8 *key_ = (uint8 *)(key); \ 38 while (size_--) { *buf_++ = *key_++; } \ 39 } 40 #define mrn_byte_order_network_to_host(buf, key, size) \ 41 { \ 42 uint32 size_ = (uint32)(size); \ 43 uint8 *buf_ = (uint8 *)(buf); \ 44 uint8 *key_ = (uint8 *)(key); \ 45 while (size_) { *buf_++ = *key_++; size_--; } \ 46 } 47 #else /* WORDS_BIGENDIAN */ 48 #define mrn_byte_order_host_to_network(buf, key, size) \ 49 { \ 50 uint32 size_ = (uint32)(size); \ 51 uint8 *buf_ = (uint8 *)(buf); \ 52 uint8 *key_ = (uint8 *)(key) + size_; \ 53 while (size_--) { *buf_++ = *(--key_); } \ 54 } 55 #define mrn_byte_order_network_to_host(buf, key, size) \ 56 { \ 57 uint32 size_ = (uint32)(size); \ 58 uint8 *buf_ = (uint8 *)(buf); \ 59 uint8 *key_ = (uint8 *)(key) + size_; \ 60 while (size_) { *buf_++ = *(--key_); size_--; } \ 61 } 62 #endif /* WORDS_BIGENDIAN */ 63 64 namespace mrn { MultipleColumnKeyCodec(grn_ctx * ctx,THD * thread,KEY * key_info)65 MultipleColumnKeyCodec::MultipleColumnKeyCodec(grn_ctx *ctx, 66 THD *thread, 67 KEY *key_info) 68 : ctx_(ctx), 69 thread_(thread), 70 key_info_(key_info) { 71 } 72 ~MultipleColumnKeyCodec()73 MultipleColumnKeyCodec::~MultipleColumnKeyCodec() { 74 } 75 encode(const uchar * mysql_key,uint mysql_key_length,uchar * grn_key,uint * grn_key_length)76 int MultipleColumnKeyCodec::encode(const uchar *mysql_key, 77 uint mysql_key_length, 78 uchar *grn_key, 79 uint *grn_key_length) { 80 MRN_DBUG_ENTER_METHOD(); 81 int error = 0; 82 const uchar *current_mysql_key = mysql_key; 83 const uchar *mysql_key_end = mysql_key + mysql_key_length; 84 uchar *current_grn_key = grn_key; 85 86 int n_key_parts = KEY_N_KEY_PARTS(key_info_); 87 DBUG_PRINT("info", ("mroonga: n_key_parts=%d", n_key_parts)); 88 *grn_key_length = 0; 89 for (int i = 0; i < n_key_parts && current_mysql_key < mysql_key_end; i++) { 90 KEY_PART_INFO *key_part = &(key_info_->key_part[i]); 91 Field *field = key_part->field; 92 bool is_null = false; 93 DBUG_PRINT("info", ("mroonga: key_part->length=%u", key_part->length)); 94 95 if (field->null_bit) { 96 DBUG_PRINT("info", ("mroonga: field has null bit")); 97 *current_grn_key = 0; 98 is_null = *current_mysql_key; 99 current_mysql_key += 1; 100 current_grn_key += 1; 101 (*grn_key_length)++; 102 } 103 104 DataType data_type = TYPE_UNKNOWN; 105 uint data_size = 0; 106 get_key_info(key_part, &data_type, &data_size); 107 uint grn_key_data_size = data_size; 108 109 switch (data_type) { 110 case TYPE_UNKNOWN: 111 // TODO: This will not be happen. This is just for 112 // suppressing warnings by gcc -O2. :< 113 error = HA_ERR_UNSUPPORTED; 114 break; 115 case TYPE_LONG_LONG_NUMBER: 116 { 117 long long int long_long_value = 0; 118 long_long_value = sint8korr(current_mysql_key); 119 encode_long_long_int(long_long_value, current_grn_key); 120 } 121 break; 122 case TYPE_NUMBER: 123 { 124 Field_num *number_field = static_cast<Field_num *>(field); 125 encode_number(current_mysql_key, 126 data_size, 127 !number_field->unsigned_flag, 128 current_grn_key); 129 } 130 break; 131 case TYPE_FLOAT: 132 { 133 float value; 134 value_decoder::decode(&value, current_mysql_key); 135 encode_float(value, data_size, current_grn_key); 136 } 137 break; 138 case TYPE_DOUBLE: 139 { 140 double value; 141 value_decoder::decode(&value, current_mysql_key); 142 encode_double(value, data_size, current_grn_key); 143 } 144 break; 145 case TYPE_DATETIME: 146 { 147 long long int mysql_datetime; 148 #ifdef WORDS_BIGENDIAN 149 if (field->table && field->table->s->db_low_byte_first) { 150 mysql_datetime = sint8korr(current_mysql_key); 151 } else 152 #endif 153 { 154 value_decoder::decode(&mysql_datetime, current_mysql_key); 155 } 156 TimeConverter time_converter; 157 bool truncated; 158 long long int grn_time = 159 time_converter.mysql_datetime_to_grn_time(mysql_datetime, 160 &truncated); 161 encode_long_long_int(grn_time, current_grn_key); 162 } 163 break; 164 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 165 case TYPE_DATETIME2: 166 { 167 Field_datetimef *datetimef_field = 168 static_cast<Field_datetimef *>(field); 169 long long int mysql_datetime_packed = is_null ? 0 : 170 my_datetime_packed_from_binary(current_mysql_key, 171 datetimef_field->decimals()); 172 MYSQL_TIME mysql_time; 173 TIME_from_longlong_datetime_packed(&mysql_time, mysql_datetime_packed); 174 TimeConverter time_converter; 175 bool truncated; 176 long long int grn_time = 177 time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); 178 grn_key_data_size = 8; 179 encode_long_long_int(grn_time, current_grn_key); 180 } 181 break; 182 #endif 183 case TYPE_BYTE_SEQUENCE: 184 memcpy(current_grn_key, current_mysql_key, data_size); 185 break; 186 case TYPE_BYTE_REVERSE: 187 encode_reverse(current_mysql_key, data_size, current_grn_key); 188 break; 189 case TYPE_BYTE_BLOB: 190 encode_blob(current_mysql_key, &data_size, field, current_grn_key); 191 grn_key_data_size = data_size; 192 break; 193 } 194 195 if (error) { 196 break; 197 } 198 199 current_mysql_key += data_size; 200 current_grn_key += grn_key_data_size; 201 *grn_key_length += grn_key_data_size; 202 } 203 204 DBUG_RETURN(error); 205 } 206 decode(const uchar * grn_key,uint grn_key_length,uchar * mysql_key,uint * mysql_key_length)207 int MultipleColumnKeyCodec::decode(const uchar *grn_key, 208 uint grn_key_length, 209 uchar *mysql_key, 210 uint *mysql_key_length) { 211 MRN_DBUG_ENTER_METHOD(); 212 int error = 0; 213 const uchar *current_grn_key = grn_key; 214 const uchar *grn_key_end = grn_key + grn_key_length; 215 uchar *current_mysql_key = mysql_key; 216 217 int n_key_parts = KEY_N_KEY_PARTS(key_info_); 218 DBUG_PRINT("info", ("mroonga: n_key_parts=%d", n_key_parts)); 219 *mysql_key_length = 0; 220 for (int i = 0; i < n_key_parts && current_grn_key < grn_key_end; i++) { 221 KEY_PART_INFO *key_part = &(key_info_->key_part[i]); 222 Field *field = key_part->field; 223 DBUG_PRINT("info", ("mroonga: key_part->length=%u", key_part->length)); 224 225 if (field->null_bit) { 226 DBUG_PRINT("info", ("mroonga: field has null bit")); 227 *current_mysql_key = 0; 228 current_grn_key += 1; 229 current_mysql_key += 1; 230 (*mysql_key_length)++; 231 } 232 233 DataType data_type = TYPE_UNKNOWN; 234 uint data_size = 0; 235 get_key_info(key_part, &data_type, &data_size); 236 uint grn_key_data_size = data_size; 237 238 switch (data_type) { 239 case TYPE_UNKNOWN: 240 // TODO: This will not be happen. This is just for 241 // suppressing warnings by gcc -O2. :< 242 error = HA_ERR_UNSUPPORTED; 243 break; 244 case TYPE_LONG_LONG_NUMBER: 245 { 246 long long int value; 247 decode_long_long_int(current_grn_key, &value); 248 int8store(current_mysql_key, value); 249 } 250 break; 251 case TYPE_NUMBER: 252 { 253 Field_num *number_field = static_cast<Field_num *>(field); 254 decode_number(current_grn_key, 255 grn_key_data_size, 256 !number_field->unsigned_flag, 257 current_mysql_key); 258 } 259 break; 260 case TYPE_FLOAT: 261 decode_float(current_grn_key, grn_key_data_size, current_mysql_key); 262 break; 263 case TYPE_DOUBLE: 264 decode_double(current_grn_key, grn_key_data_size, current_mysql_key); 265 break; 266 case TYPE_DATETIME: 267 { 268 long long int grn_time; 269 decode_long_long_int(current_grn_key, &grn_time); 270 TimeConverter time_converter; 271 long long int mysql_datetime = 272 time_converter.grn_time_to_mysql_datetime(grn_time); 273 #ifdef WORDS_BIGENDIAN 274 if (field->table && field->table->s->db_low_byte_first) { 275 int8store(current_mysql_key, mysql_datetime); 276 } else 277 #endif 278 { 279 longlongstore(current_mysql_key, mysql_datetime); 280 } 281 } 282 break; 283 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 284 case TYPE_DATETIME2: 285 { 286 Field_datetimef *datetimef_field = 287 static_cast<Field_datetimef *>(field); 288 long long int grn_time; 289 grn_key_data_size = 8; 290 decode_long_long_int(current_grn_key, &grn_time); 291 TimeConverter time_converter; 292 MYSQL_TIME mysql_time; 293 mysql_time.neg = FALSE; 294 mysql_time.time_type = MYSQL_TIMESTAMP_DATETIME; 295 time_converter.grn_time_to_mysql_time(grn_time, &mysql_time); 296 long long int mysql_datetime_packed = 297 TIME_to_longlong_datetime_packed(&mysql_time); 298 my_datetime_packed_to_binary(mysql_datetime_packed, 299 current_mysql_key, 300 datetimef_field->decimals()); 301 } 302 break; 303 #endif 304 case TYPE_BYTE_SEQUENCE: 305 memcpy(current_mysql_key, current_grn_key, grn_key_data_size); 306 break; 307 case TYPE_BYTE_REVERSE: 308 decode_reverse(current_grn_key, grn_key_data_size, current_mysql_key); 309 break; 310 case TYPE_BYTE_BLOB: 311 memcpy(current_mysql_key, 312 current_grn_key + data_size, 313 HA_KEY_BLOB_LENGTH); 314 memcpy(current_mysql_key + HA_KEY_BLOB_LENGTH, 315 current_grn_key, 316 data_size); 317 data_size += HA_KEY_BLOB_LENGTH; 318 grn_key_data_size = data_size; 319 break; 320 } 321 322 if (error) { 323 break; 324 } 325 326 current_grn_key += grn_key_data_size; 327 current_mysql_key += data_size; 328 *mysql_key_length += data_size; 329 } 330 331 DBUG_RETURN(error); 332 } 333 size()334 uint MultipleColumnKeyCodec::size() { 335 MRN_DBUG_ENTER_METHOD(); 336 337 int n_key_parts = KEY_N_KEY_PARTS(key_info_); 338 DBUG_PRINT("info", ("mroonga: n_key_parts=%d", n_key_parts)); 339 340 uint total_size = 0; 341 for (int i = 0; i < n_key_parts; ++i) { 342 KEY_PART_INFO *key_part = &(key_info_->key_part[i]); 343 Field *field = key_part->field; 344 DBUG_PRINT("info", ("mroonga: key_part->length=%u", key_part->length)); 345 346 if (field->null_bit) { 347 DBUG_PRINT("info", ("mroonga: field has null bit")); 348 ++total_size; 349 } 350 351 DataType data_type = TYPE_UNKNOWN; 352 uint data_size = 0; 353 get_key_info(key_part, &data_type, &data_size); 354 switch (data_type) { 355 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 356 case TYPE_DATETIME2: 357 data_size = 8; 358 break; 359 #endif 360 case TYPE_BYTE_BLOB: 361 data_size += HA_KEY_BLOB_LENGTH; 362 break; 363 default: 364 break; 365 } 366 total_size += data_size; 367 } 368 369 DBUG_RETURN(total_size); 370 } 371 get_key_info(KEY_PART_INFO * key_part,DataType * data_type,uint * data_size)372 void MultipleColumnKeyCodec::get_key_info(KEY_PART_INFO *key_part, 373 DataType *data_type, 374 uint *data_size) { 375 MRN_DBUG_ENTER_METHOD(); 376 377 *data_type = TYPE_UNKNOWN; 378 *data_size = 0; 379 380 Field *field = key_part->field; 381 switch (field->real_type()) { 382 case MYSQL_TYPE_DECIMAL: 383 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_DECIMAL")); 384 *data_type = TYPE_BYTE_SEQUENCE; 385 *data_size = key_part->length; 386 break; 387 case MYSQL_TYPE_TINY: 388 case MYSQL_TYPE_YEAR: 389 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_TINY")); 390 *data_type = TYPE_NUMBER; 391 *data_size = 1; 392 break; 393 case MYSQL_TYPE_SHORT: 394 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_SHORT")); 395 *data_type = TYPE_NUMBER; 396 *data_size = 2; 397 break; 398 case MYSQL_TYPE_LONG: 399 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_LONG")); 400 *data_type = TYPE_NUMBER; 401 *data_size = 4; 402 break; 403 case MYSQL_TYPE_FLOAT: 404 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_FLOAT")); 405 *data_type = TYPE_FLOAT; 406 *data_size = 4; 407 break; 408 case MYSQL_TYPE_DOUBLE: 409 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_DOUBLE")); 410 *data_type = TYPE_DOUBLE; 411 *data_size = 8; 412 break; 413 case MYSQL_TYPE_NULL: 414 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_NULL")); 415 *data_type = TYPE_NUMBER; 416 *data_size = 1; 417 break; 418 case MYSQL_TYPE_TIMESTAMP: 419 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_TIMESTAMP")); 420 *data_type = TYPE_BYTE_REVERSE; 421 *data_size = key_part->length; 422 break; 423 case MYSQL_TYPE_DATE: 424 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_DATE")); 425 *data_type = TYPE_BYTE_REVERSE; 426 *data_size = key_part->length; 427 break; 428 case MYSQL_TYPE_DATETIME: 429 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_DATETIME")); 430 *data_type = TYPE_DATETIME; 431 *data_size = key_part->length; 432 break; 433 case MYSQL_TYPE_NEWDATE: 434 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_NEWDATE")); 435 *data_type = TYPE_BYTE_REVERSE; 436 *data_size = key_part->length; 437 break; 438 case MYSQL_TYPE_LONGLONG: 439 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_LONGLONG")); 440 *data_type = TYPE_NUMBER; 441 *data_size = 8; 442 break; 443 case MYSQL_TYPE_INT24: 444 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_INT24")); 445 *data_type = TYPE_NUMBER; 446 *data_size = 3; 447 break; 448 case MYSQL_TYPE_TIME: 449 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_TIME")); 450 *data_type = TYPE_NUMBER; 451 *data_size = 3; 452 break; 453 case MYSQL_TYPE_VARCHAR: 454 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_VARCHAR")); 455 *data_type = TYPE_BYTE_BLOB; 456 *data_size = key_part->length; 457 break; 458 case MYSQL_TYPE_BIT: 459 // TODO 460 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_BIT")); 461 *data_type = TYPE_NUMBER; 462 *data_size = 1; 463 break; 464 #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2 465 case MYSQL_TYPE_TIMESTAMP2: 466 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_TIMESTAMP2")); 467 *data_type = TYPE_BYTE_SEQUENCE; 468 *data_size = key_part->length; 469 break; 470 #endif 471 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 472 case MYSQL_TYPE_DATETIME2: 473 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_DATETIME2")); 474 *data_type = TYPE_DATETIME2; 475 *data_size = key_part->length; 476 break; 477 #endif 478 #ifdef MRN_HAVE_MYSQL_TYPE_TIME2 479 case MYSQL_TYPE_TIME2: 480 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_TIME2")); 481 *data_type = TYPE_BYTE_SEQUENCE; 482 *data_size = key_part->length; 483 break; 484 #endif 485 case MYSQL_TYPE_NEWDECIMAL: 486 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_NEWDECIMAL")); 487 *data_type = TYPE_BYTE_SEQUENCE; 488 *data_size = key_part->length; 489 break; 490 case MYSQL_TYPE_ENUM: 491 // TODO 492 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_ENUM")); 493 *data_type = TYPE_NUMBER; 494 *data_size = 1; 495 break; 496 case MYSQL_TYPE_SET: 497 // TODO 498 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_SET")); 499 *data_type = TYPE_NUMBER; 500 *data_size = 1; 501 break; 502 case MYSQL_TYPE_TINY_BLOB: 503 case MYSQL_TYPE_MEDIUM_BLOB: 504 case MYSQL_TYPE_LONG_BLOB: 505 case MYSQL_TYPE_BLOB: 506 // TODO 507 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_BLOB")); 508 *data_type = TYPE_BYTE_BLOB; 509 *data_size = key_part->length; 510 break; 511 case MYSQL_TYPE_VAR_STRING: 512 case MYSQL_TYPE_STRING: 513 // TODO 514 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_STRING")); 515 *data_type = TYPE_BYTE_SEQUENCE; 516 *data_size = key_part->length; 517 break; 518 case MYSQL_TYPE_GEOMETRY: 519 // TODO 520 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_GEOMETRY")); 521 *data_type = TYPE_BYTE_SEQUENCE; 522 *data_size = key_part->length; 523 break; 524 case MYSQL_TYPE_VARCHAR_COMPRESSED: 525 case MYSQL_TYPE_BLOB_COMPRESSED: 526 DBUG_ASSERT(0); 527 #ifdef MRN_HAVE_MYSQL_TYPE_JSON 528 case MYSQL_TYPE_JSON: 529 // TODO 530 DBUG_PRINT("info", ("mroonga: MYSQL_TYPE_JSON")); 531 *data_type = TYPE_BYTE_SEQUENCE; 532 *data_size = key_part->length; 533 break; 534 #endif 535 } 536 DBUG_VOID_RETURN; 537 } 538 encode_number(const uchar * mysql_key,uint mysql_key_size,bool is_signed,uchar * grn_key)539 void MultipleColumnKeyCodec::encode_number(const uchar *mysql_key, 540 uint mysql_key_size, 541 bool is_signed, 542 uchar *grn_key) { 543 MRN_DBUG_ENTER_METHOD(); 544 mrn_byte_order_host_to_network(grn_key, mysql_key, mysql_key_size); 545 if (is_signed) { 546 grn_key[0] ^= 0x80; 547 } 548 DBUG_VOID_RETURN; 549 } 550 decode_number(const uchar * grn_key,uint grn_key_size,bool is_signed,uchar * mysql_key)551 void MultipleColumnKeyCodec::decode_number(const uchar *grn_key, 552 uint grn_key_size, 553 bool is_signed, 554 uchar *mysql_key) { 555 MRN_DBUG_ENTER_METHOD(); 556 uchar buffer[8]; 557 memcpy(buffer, grn_key, grn_key_size); 558 if (is_signed) { 559 buffer[0] ^= 0x80; 560 } 561 mrn_byte_order_network_to_host(mysql_key, buffer, grn_key_size); 562 DBUG_VOID_RETURN; 563 } 564 encode_long_long_int(volatile long long int value,uchar * grn_key)565 void MultipleColumnKeyCodec::encode_long_long_int(volatile long long int value, 566 uchar *grn_key) { 567 MRN_DBUG_ENTER_METHOD(); 568 uint value_size = 8; 569 mrn_byte_order_host_to_network(grn_key, &value, value_size); 570 grn_key[0] ^= 0x80; 571 DBUG_VOID_RETURN; 572 } 573 decode_long_long_int(const uchar * grn_key,long long int * value)574 void MultipleColumnKeyCodec::decode_long_long_int(const uchar *grn_key, 575 long long int *value) { 576 MRN_DBUG_ENTER_METHOD(); 577 uint grn_key_size = 8; 578 uchar buffer[8]; 579 memcpy(buffer, grn_key, grn_key_size); 580 buffer[0] ^= 0x80; 581 mrn_byte_order_network_to_host(value, buffer, grn_key_size); 582 DBUG_VOID_RETURN; 583 } 584 encode_float(volatile float value,uint value_size,uchar * grn_key)585 void MultipleColumnKeyCodec::encode_float(volatile float value, 586 uint value_size, 587 uchar *grn_key) { 588 MRN_DBUG_ENTER_METHOD(); 589 int n_bits = (value_size * 8 - 1); 590 volatile int *int_value_pointer = (int *)(&value); 591 int int_value = *int_value_pointer; 592 int_value ^= ((int_value >> n_bits) | (1 << n_bits)); 593 mrn_byte_order_host_to_network(grn_key, &int_value, value_size); 594 DBUG_VOID_RETURN; 595 } 596 decode_float(const uchar * grn_key,uint grn_key_size,uchar * mysql_key)597 void MultipleColumnKeyCodec::decode_float(const uchar *grn_key, 598 uint grn_key_size, 599 uchar *mysql_key) { 600 MRN_DBUG_ENTER_METHOD(); 601 int int_value; 602 mrn_byte_order_network_to_host(&int_value, grn_key, grn_key_size); 603 int max_bit = (grn_key_size * 8 - 1); 604 *((int *)mysql_key) = 605 int_value ^ (((int_value ^ (1 << max_bit)) >> max_bit) | 606 (1 << max_bit)); 607 DBUG_VOID_RETURN; 608 } 609 encode_double(volatile double value,uint value_size,uchar * grn_key)610 void MultipleColumnKeyCodec::encode_double(volatile double value, 611 uint value_size, 612 uchar *grn_key) { 613 MRN_DBUG_ENTER_METHOD(); 614 int n_bits = (value_size * 8 - 1); 615 volatile long long int *long_long_value_pointer = (long long int *)(&value); 616 volatile long long int long_long_value = *long_long_value_pointer; 617 long_long_value ^= ((long_long_value >> n_bits) | (1LL << n_bits)); 618 mrn_byte_order_host_to_network(grn_key, &long_long_value, value_size); 619 DBUG_VOID_RETURN; 620 } 621 decode_double(const uchar * grn_key,uint grn_key_size,uchar * mysql_key)622 void MultipleColumnKeyCodec::decode_double(const uchar *grn_key, 623 uint grn_key_size, 624 uchar *mysql_key) { 625 MRN_DBUG_ENTER_METHOD(); 626 long long int long_long_value; 627 mrn_byte_order_network_to_host(&long_long_value, grn_key, grn_key_size); 628 int max_bit = (grn_key_size * 8 - 1); 629 long_long_value = 630 long_long_value ^ (((long_long_value ^ (1LL << max_bit)) >> max_bit) | 631 (1LL << max_bit)); 632 memcpy(mysql_key, &long_long_value, sizeof(long_long_value)); 633 DBUG_VOID_RETURN; 634 } 635 encode_reverse(const uchar * mysql_key,uint mysql_key_size,uchar * grn_key)636 void MultipleColumnKeyCodec::encode_reverse(const uchar *mysql_key, 637 uint mysql_key_size, 638 uchar *grn_key) { 639 MRN_DBUG_ENTER_METHOD(); 640 for (uint i = 0; i < mysql_key_size; i++) { 641 grn_key[i] = mysql_key[mysql_key_size - i - 1]; 642 } 643 DBUG_VOID_RETURN; 644 } 645 decode_reverse(const uchar * grn_key,uint grn_key_size,uchar * mysql_key)646 void MultipleColumnKeyCodec::decode_reverse(const uchar *grn_key, 647 uint grn_key_size, 648 uchar *mysql_key) { 649 MRN_DBUG_ENTER_METHOD(); 650 for (uint i = 0; i < grn_key_size; i++) { 651 mysql_key[i] = grn_key[grn_key_size - i - 1]; 652 } 653 DBUG_VOID_RETURN; 654 } 655 encode_blob(const uchar * mysql_key,uint * mysql_key_size,Field * field,uchar * grn_key)656 void MultipleColumnKeyCodec::encode_blob(const uchar *mysql_key, 657 uint *mysql_key_size, 658 Field *field, 659 uchar *grn_key) { 660 MRN_DBUG_ENTER_METHOD(); 661 FieldNormalizer normalizer(ctx_, thread_, field); 662 if (normalizer.should_normalize()) { 663 #if HA_KEY_BLOB_LENGTH != 2 664 # error "TODO: support HA_KEY_BLOB_LENGTH != 2 case if it is needed" 665 #endif 666 const char *blob_data = 667 reinterpret_cast<const char *>(mysql_key + HA_KEY_BLOB_LENGTH); 668 uint16 blob_data_length = *((uint16 *)(mysql_key)); 669 grn_obj *grn_string = normalizer.normalize(blob_data, 670 blob_data_length); 671 mrn::SmartGrnObj smart_grn_string(ctx_, grn_string); 672 const char *normalized; 673 unsigned int normalized_length = 0; 674 grn_string_get_normalized(ctx_, grn_string, 675 &normalized, &normalized_length, NULL); 676 uint16 new_blob_data_length; 677 if (normalized_length <= UINT_MAX16) { 678 if (normalized_length) 679 memcpy(grn_key, normalized, normalized_length); 680 if (normalized_length < *mysql_key_size) { 681 memset(grn_key + normalized_length, 682 '\0', *mysql_key_size - normalized_length); 683 } 684 new_blob_data_length = normalized_length; 685 } else { 686 push_warning_printf(thread_, 687 MRN_SEVERITY_WARNING, 688 MRN_ERROR_CODE_DATA_TRUNCATE(thread_), 689 "normalized data truncated " 690 "for multiple column index: " 691 "normalized-data-size: <%u> " 692 "max-data-size: <%u> " 693 "column-name: <%s> " 694 "data: <%.*s>", 695 normalized_length, 696 UINT_MAX16, 697 field->field_name, 698 blob_data_length, blob_data); 699 memcpy(grn_key, normalized, blob_data_length); 700 new_blob_data_length = blob_data_length; 701 } 702 memcpy(grn_key + *mysql_key_size, 703 &new_blob_data_length, 704 HA_KEY_BLOB_LENGTH); 705 } else { 706 memcpy(grn_key + *mysql_key_size, mysql_key, HA_KEY_BLOB_LENGTH); 707 memcpy(grn_key, mysql_key + HA_KEY_BLOB_LENGTH, *mysql_key_size); 708 } 709 *mysql_key_size += HA_KEY_BLOB_LENGTH; 710 DBUG_VOID_RETURN; 711 } 712 } 713