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