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 | |
64 | namespace 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 | |