1 /* -*- c-basic-offset: 2; indent-tabs-mode: nil -*- */
2 /*
3 Copyright(C) 2010 Tetsuro IKEDA
4 Copyright(C) 2010-2013 Kentoku SHIBA
5 Copyright(C) 2011-2017 Kouhei Sutou <kou@clear-code.com>
6 Copyright(C) 2013 Kenji Maruyama <mmmaru777@gmail.com>
7
8 This library is free software; you can redistribute it and/or
9 modify it under the terms of the GNU Lesser General Public
10 License as published by the Free Software Foundation; either
11 version 2.1 of the License, or (at your option) any later version.
12
13 This library is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 Lesser General Public License for more details.
17
18 You should have received a copy of the GNU Lesser General Public
19 License along with this library; if not, write to the Free Software
20 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335 USA
21 */
22
23 #include "mrn_mysql.h"
24 #include "mrn_mysql_compat.h"
25
26 #ifdef USE_PRAGMA_IMPLEMENTATION
27 #pragma implementation
28 #endif
29
30 #include <sql_plugin.h>
31 #include <sql_show.h>
32 #include <key.h>
33 #include <tztime.h>
34 #include <sql_base.h>
35 #include <sql_select.h>
36 #include <item_sum.h>
37
38 #ifdef MRN_HAVE_BINLOG_H
39 # include <binlog.h>
40 #endif
41
42 #ifdef MRN_HAVE_SQL_OPTIMIZER_H
43 # include <sql_optimizer.h>
44 #endif
45
46 #include <ft_global.h>
47 #include <spatial.h>
48 #include <mysql.h>
49 #include <sys/types.h>
50 #include <sys/stat.h>
51
52 #ifdef WIN32
53 # include <math.h>
54 # include <direct.h>
55 # define MRN_TABLE_SHARE_LOCK_SHARE_PROC "?key_TABLE_SHARE_LOCK_share@@3IA"
56 # define MRN_TABLE_SHARE_LOCK_HA_DATA_PROC "?key_TABLE_SHARE_LOCK_ha_data@@3IA"
57 # ifdef _WIN64
58 # define MRN_BINLOG_FILTER_PROC "?binlog_filter@@3PEAVRpl_filter@@EA"
59 # define MRN_MY_TZ_UTC_PROC "?my_tz_UTC@@3PEAVTime_zone@@EA"
60 # else
61 # define MRN_BINLOG_FILTER_PROC "?binlog_filter@@3PAVRpl_filter@@A"
62 # define MRN_MY_TZ_UTC_PROC "?my_tz_UTC@@3PAVTime_zone@@A"
63 # endif
64 #else
65 # include <dirent.h>
66 # include <unistd.h>
67 #endif
68
69 #include "mrn_err.h"
70 #include "mrn_table.hpp"
71 #include <groonga/plugin.h>
72 #include "ha_mroonga.hpp"
73 #include <mrn_path_mapper.hpp>
74 #include <mrn_index_table_name.hpp>
75 #include <mrn_index_column_name.hpp>
76 #include <mrn_debug_column_access.hpp>
77 #include <mrn_auto_increment_value_lock.hpp>
78 #include <mrn_external_lock.hpp>
79 #include <mrn_match_escalation_threshold_scope.hpp>
80 #include <mrn_multiple_column_key_codec.hpp>
81 #include <mrn_field_normalizer.hpp>
82 #include <mrn_encoding.hpp>
83 #include <mrn_parameters_parser.hpp>
84 #include <mrn_lock.hpp>
85 #include <mrn_condition_converter.hpp>
86 #include <mrn_time_converter.hpp>
87 #include <mrn_smart_grn_obj.hpp>
88 #include <mrn_database_manager.hpp>
89 #include <mrn_context_pool.hpp>
90 #include <mrn_grn.hpp>
91 #include <mrn_value_decoder.hpp>
92 #include <mrn_database_repairer.hpp>
93 #include <mrn_operation.hpp>
94 #include <mrn_column_name.hpp>
95 #include <mrn_count_skip_checker.hpp>
96 #include <mrn_variables.hpp>
97 #include <mrn_query_parser.hpp>
98 #include <mrn_smart_bitmap.hpp>
99 #include <mrn_table_fields_offset_mover.hpp>
100
101 #ifdef MRN_SUPPORT_FOREIGN_KEYS
102 # include <sql_table.h>
103 #endif
104
105 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
106 # include <create_options.h>
107 #endif
108
109 // for debug
110 #define MRN_CLASS_NAME "ha_mroonga"
111
112 #define MRN_SHORT_TEXT_SIZE (1 << 12) // 4Kbytes
113 #define MRN_TEXT_SIZE (1 << 16) // 64Kbytes
114 #define MRN_LONG_TEXT_SIZE (1 << 31) // 2Gbytes
115
116 #ifdef MRN_HAVE_TDC_LOCK_TABLE_SHARE
117 # ifdef MRN_TABLE_SHARE_TDC_IS_POINTER
118 # define mrn_open_mutex(share) &((share)->tdc->LOCK_table_share)
119 # else
120 # define mrn_open_mutex(share) &((share)->tdc.LOCK_table_share)
121 # endif
122 # define mrn_open_mutex_lock(share) do { \
123 TABLE_SHARE *share_ = share; \
124 if (share_ && share_->tmp_table == NO_TMP_TABLE) { \
125 mysql_mutex_lock(mrn_open_mutex(share_)); \
126 } \
127 } while (0)
128 # define mrn_open_mutex_unlock(share) do { \
129 TABLE_SHARE *share_ = share; \
130 if (share_ && share_->tmp_table == NO_TMP_TABLE) { \
131 mysql_mutex_unlock(mrn_open_mutex(share_)); \
132 } \
133 } while (0)
134 #else
135 # ifdef DBUG_OFF
136 # ifndef _WIN32
137 extern mysql_mutex_t LOCK_open;
138 # endif
139 # endif
140 static mysql_mutex_t *mrn_LOCK_open;
141 # define mrn_open_mutex_lock(share) mysql_mutex_lock(mrn_LOCK_open)
142 # define mrn_open_mutex_unlock(share) mysql_mutex_unlock(mrn_LOCK_open)
143 #endif
144
145 #if MYSQL_VERSION_ID >= 50600
146 # define MRN_NEED_M_LOCK_TYPE_CHECK_FOR_WRAPPER_EXTERNAL_LOCK
147 #endif
148
149 #ifdef MRN_MARIADB_P
150 # if MYSQL_VERSION_ID >= 100200
151 # define MRN_ORDER_IS_ASC(order) ((order)->direction == ORDER::ORDER_ASC)
152 # else
153 # define MRN_ORDER_IS_ASC(order) ((order)->asc)
154 # endif
155 #else
156 # if MYSQL_VERSION_ID >= 50603
157 # define MRN_ORDER_IS_ASC(order) ((order)->direction == ORDER::ORDER_ASC)
158 # else
159 # define MRN_ORDER_IS_ASC(order) ((order)->asc)
160 # endif
161 #endif
162
163 #define MRN_STRINGIFY(macro_or_string) MRN_STRINGIFY_ARG(macro_or_string)
164 #define MRN_STRINGIFY_ARG(contents) #contents
165
166 #define MRN_PLUGIN_NAME mroonga
167 #define MRN_PLUGIN_NAME_STRING "Mroonga"
168 #define MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "Mroonga"
169
170 #ifdef MRN_MARIADB_P
171 # define st_mysql_plugin st_maria_plugin
172 # define mrn_declare_plugin(NAME) maria_declare_plugin(NAME)
173 # define mrn_declare_plugin_end maria_declare_plugin_end
174 # define MRN_PLUGIN_LAST_VALUES MRN_VERSION, MariaDB_PLUGIN_MATURITY_STABLE
175 #else
176 # define mrn_declare_plugin(NAME) mysql_declare_plugin(NAME)
177 # define mrn_declare_plugin_end mysql_declare_plugin_end
178 # define MRN_PLUGIN_LAST_VALUES NULL, 0
179 #endif
180
181 #if MYSQL_VERSION_ID >= 100007 && defined(MRN_MARIADB_P)
182 # define MRN_THD_GET_AUTOINC(thd, off, inc) thd_get_autoinc(thd, off, inc)
183 # define MRN_GET_ERR_MSG(code) my_get_err_msg(code)
184 #else
185 # define MRN_THD_GET_AUTOINC(thd, off, inc) \
186 { \
187 *(off) = thd->variables.auto_increment_offset; \
188 *(inc) = thd->variables.auto_increment_increment; \
189 }
190 # define MRN_GET_ERR_MSG(code) ER(code)
191 #endif
192
193 #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
194 # define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex->table_list.first
195 #else
196 # define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex.table_list.first
197 #endif
198
199 #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
200 # define MRN_KEYTYPE_FOREIGN KEYTYPE_FOREIGN
201 #else
202 # define MRN_KEYTYPE_FOREIGN Key::FOREIGN_KEY
203 #endif
204
205 #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
206 # define mrn_calculate_key_len(table, key_index, buffer, keypart_map) \
207 calculate_key_len(table, key_index, keypart_map)
208 #else
209 # define mrn_calculate_key_len(table, key_index, buffer, keypart_map) \
210 calculate_key_len(table, key_index, buffer, keypart_map)
211 #endif
212
213 #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
214 # define MRN_TABLE_LIST_GET_DERIVED(table_list) NULL
215 #else
216 # define MRN_TABLE_LIST_GET_DERIVED(table_list) (table_list)->derived
217 #endif
218
219 #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
220 # define MRN_GEOMETRY_FREE(geometry)
221 #else
222 # define MRN_GEOMETRY_FREE(geometry) delete (geometry)
223 #endif
224
225 Rpl_filter *mrn_binlog_filter;
226 Time_zone *mrn_my_tz_UTC;
227 #ifdef MRN_HAVE_TABLE_DEF_CACHE
228 HASH *mrn_table_def_cache;
229 #endif
230
231 #ifdef MRN_HAVE_PSI_MEMORY_KEY
232 PSI_memory_key mrn_memory_key;
233
234 static PSI_memory_info mrn_all_memory_keys[]=
235 {
236 {&mrn_memory_key, "Mroonga", 0}
237 };
238 #endif
239
240 static const char *INDEX_COLUMN_NAME = "index";
241 static const char *MRN_PLUGIN_AUTHOR = "The Mroonga project";
242
243 #ifdef __cplusplus
244 extern "C" {
245 #endif
246
247 #ifdef HAVE_PSI_INTERFACE
248 # ifdef WIN32
249 # ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
250 PSI_mutex_key *mrn_table_share_lock_share;
251 # endif
252 PSI_mutex_key *mrn_table_share_lock_ha_data;
253 # endif
254 static PSI_mutex_key mrn_open_tables_mutex_key;
255 static PSI_mutex_key mrn_long_term_share_mutex_key;
256 static PSI_mutex_key mrn_allocated_thds_mutex_key;
257 PSI_mutex_key mrn_share_mutex_key;
258 PSI_mutex_key mrn_long_term_share_auto_inc_mutex_key;
259 static PSI_mutex_key mrn_log_mutex_key;
260 static PSI_mutex_key mrn_query_log_mutex_key;
261 static PSI_mutex_key mrn_db_manager_mutex_key;
262 static PSI_mutex_key mrn_context_pool_mutex_key;
263 static PSI_mutex_key mrn_operations_mutex_key;
264
265 # if (!defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 80002)
266 # define MRN_MUTEXT_INFO_ENTRY(key, name, flags, volatility) \
267 {key, name, flags, volatility}
268 # else
269 # define MRN_MUTEXT_INFO_ENTRY(key, name, flags, volatility) \
270 {key, name, flags}
271 # endif
272
273 static PSI_mutex_info mrn_mutexes[] =
274 {
275 MRN_MUTEXT_INFO_ENTRY(&mrn_open_tables_mutex_key,
276 "mrn::open_tables", PSI_FLAG_GLOBAL, 0),
277 MRN_MUTEXT_INFO_ENTRY(&mrn_long_term_share_mutex_key,
278 "mrn::long_term_share", PSI_FLAG_GLOBAL, 0),
279 MRN_MUTEXT_INFO_ENTRY(&mrn_allocated_thds_mutex_key,
280 "mrn::allocated_thds", PSI_FLAG_GLOBAL, 0),
281 MRN_MUTEXT_INFO_ENTRY(&mrn_share_mutex_key,
282 "mrn::share", 0, 0),
283 MRN_MUTEXT_INFO_ENTRY(&mrn_long_term_share_auto_inc_mutex_key,
284 "mrn::long_term_share::auto_inc", 0, 0),
285 MRN_MUTEXT_INFO_ENTRY(&mrn_log_mutex_key,
286 "mrn::log", PSI_FLAG_GLOBAL, 0),
287 MRN_MUTEXT_INFO_ENTRY(&mrn_query_log_mutex_key,
288 "mrn::query_log", PSI_FLAG_GLOBAL, 0),
289 MRN_MUTEXT_INFO_ENTRY(&mrn_db_manager_mutex_key,
290 "mrn::DatabaseManager", PSI_FLAG_GLOBAL, 0),
291 MRN_MUTEXT_INFO_ENTRY(&mrn_context_pool_mutex_key,
292 "mrn::ContextPool", PSI_FLAG_GLOBAL, 0),
293 MRN_MUTEXT_INFO_ENTRY(&mrn_operations_mutex_key,
294 "mrn::Operations", PSI_FLAG_GLOBAL, 0)
295 };
296 #endif
297
298 /* global variables */
299 handlerton *mrn_hton_ptr;
300 HASH mrn_open_tables;
301 mysql_mutex_t mrn_open_tables_mutex;
302 HASH mrn_long_term_share;
303 mysql_mutex_t mrn_long_term_share_mutex;
304
305 HASH mrn_allocated_thds;
306 mysql_mutex_t mrn_allocated_thds_mutex;
307
308 /* internal variables */
309 static grn_ctx mrn_ctx;
310 static mysql_mutex_t mrn_log_mutex;
311 static mysql_mutex_t mrn_query_log_mutex;
312 static grn_obj *mrn_db;
313 static grn_ctx mrn_db_manager_ctx;
314 static mysql_mutex_t mrn_db_manager_mutex;
315 mrn::DatabaseManager *mrn_db_manager = NULL;
316 static mysql_mutex_t mrn_context_pool_mutex;
317 mrn::ContextPool *mrn_context_pool = NULL;
318 static mysql_mutex_t mrn_operations_mutex;
319
320
321 #ifdef WIN32
round(double x)322 static inline double round(double x)
323 {
324 return (floor(x + 0.5));
325 }
326 #endif
327
mrn_init_encoding_map()328 static void mrn_init_encoding_map()
329 {
330 mrn::encoding::init();
331 }
332
mrn_change_encoding(grn_ctx * ctx,const CHARSET_INFO * charset)333 static int mrn_change_encoding(grn_ctx *ctx, const CHARSET_INFO *charset)
334 {
335 return mrn::encoding::set(ctx, charset);
336 }
337
338 #if !defined(DBUG_OFF) && !defined(_lint)
mrn_inspect_thr_lock_type(enum thr_lock_type lock_type)339 static const char *mrn_inspect_thr_lock_type(enum thr_lock_type lock_type)
340 {
341 const char *inspected = "<unknown>";
342 switch (lock_type) {
343 case TL_IGNORE:
344 inspected = "TL_IGNORE";
345 break;
346 case TL_UNLOCK:
347 inspected = "TL_UNLOCK";
348 break;
349 case TL_READ_DEFAULT:
350 inspected = "TL_READ_DEFAULT";
351 break;
352 case TL_READ:
353 inspected = "TL_READ";
354 break;
355 case TL_READ_WITH_SHARED_LOCKS:
356 inspected = "TL_READ_WITH_SHARED_LOCKS";
357 break;
358 case TL_READ_HIGH_PRIORITY:
359 inspected = "TL_READ_HIGH_PRIORITY";
360 break;
361 case TL_READ_NO_INSERT:
362 inspected = "TL_READ_NO_INSERT";
363 break;
364 case TL_WRITE_ALLOW_WRITE:
365 inspected = "TL_WRITE_ALLOW_WRITE";
366 break;
367 #ifdef MRN_HAVE_TL_WRITE_CONCURRENT_DEFAULT
368 case TL_WRITE_CONCURRENT_DEFAULT:
369 inspected = "TL_WRITE_CONCURRENT_DEFAULT";
370 break;
371 #endif
372 case TL_WRITE_CONCURRENT_INSERT:
373 inspected = "TL_WRITE_CONCURRENT_INSERT";
374 break;
375 #ifdef MRN_HAVE_TL_WRITE_DELAYED
376 case TL_WRITE_DELAYED:
377 inspected = "TL_WRITE_DELAYED";
378 break;
379 #endif
380 case TL_WRITE_DEFAULT:
381 inspected = "TL_WRITE_DEFAULT";
382 break;
383 case TL_WRITE_LOW_PRIORITY:
384 inspected = "TL_WRITE_LOW_PRIORITY";
385 break;
386 case TL_WRITE:
387 inspected = "TL_WRITE";
388 break;
389 case TL_WRITE_ONLY:
390 inspected = "TL_WRITE_ONLY";
391 break;
392 }
393 return inspected;
394 }
395
mrn_inspect_extra_function(enum ha_extra_function operation)396 static const char *mrn_inspect_extra_function(enum ha_extra_function operation)
397 {
398 const char *inspected = "<unknown>";
399 switch (operation) {
400 case HA_EXTRA_NORMAL:
401 inspected = "HA_EXTRA_NORMAL";
402 break;
403 case HA_EXTRA_QUICK:
404 inspected = "HA_EXTRA_QUICK";
405 break;
406 case HA_EXTRA_NOT_USED:
407 inspected = "HA_EXTRA_NOT_USED";
408 break;
409 case HA_EXTRA_CACHE:
410 inspected = "HA_EXTRA_CACHE";
411 break;
412 case HA_EXTRA_NO_CACHE:
413 inspected = "HA_EXTRA_NO_CACHE";
414 break;
415 case HA_EXTRA_NO_READCHECK:
416 inspected = "HA_EXTRA_NO_READCHECK";
417 break;
418 case HA_EXTRA_READCHECK:
419 inspected = "HA_EXTRA_READCHECK";
420 break;
421 case HA_EXTRA_KEYREAD:
422 inspected = "HA_EXTRA_KEYREAD";
423 break;
424 case HA_EXTRA_NO_KEYREAD:
425 inspected = "HA_EXTRA_NO_KEYREAD";
426 break;
427 case HA_EXTRA_NO_USER_CHANGE:
428 inspected = "HA_EXTRA_NO_USER_CHANGE";
429 break;
430 case HA_EXTRA_KEY_CACHE:
431 inspected = "HA_EXTRA_KEY_CACHE";
432 break;
433 case HA_EXTRA_NO_KEY_CACHE:
434 inspected = "HA_EXTRA_NO_KEY_CACHE";
435 break;
436 case HA_EXTRA_WAIT_LOCK:
437 inspected = "HA_EXTRA_WAIT_LOCK";
438 break;
439 case HA_EXTRA_NO_WAIT_LOCK:
440 inspected = "HA_EXTRA_NO_WAIT_LOCK";
441 break;
442 case HA_EXTRA_WRITE_CACHE:
443 inspected = "HA_EXTRA_WRITE_CACHE";
444 break;
445 case HA_EXTRA_FLUSH_CACHE:
446 inspected = "HA_EXTRA_FLUSH_CACHE";
447 break;
448 case HA_EXTRA_NO_KEYS:
449 inspected = "HA_EXTRA_NO_KEYS";
450 break;
451 case HA_EXTRA_KEYREAD_CHANGE_POS:
452 inspected = "HA_EXTRA_KEYREAD_CHANGE_POS";
453 break;
454 case HA_EXTRA_REMEMBER_POS:
455 inspected = "HA_EXTRA_REMEMBER_POS";
456 break;
457 case HA_EXTRA_RESTORE_POS:
458 inspected = "HA_EXTRA_RESTORE_POS";
459 break;
460 case HA_EXTRA_REINIT_CACHE:
461 inspected = "HA_EXTRA_REINIT_CACHE";
462 break;
463 case HA_EXTRA_FORCE_REOPEN:
464 inspected = "HA_EXTRA_FORCE_REOPEN";
465 break;
466 case HA_EXTRA_FLUSH:
467 inspected = "HA_EXTRA_FLUSH";
468 break;
469 case HA_EXTRA_NO_ROWS:
470 inspected = "HA_EXTRA_NO_ROWS";
471 break;
472 case HA_EXTRA_RESET_STATE:
473 inspected = "HA_EXTRA_RESET_STATE";
474 break;
475 case HA_EXTRA_IGNORE_DUP_KEY:
476 inspected = "HA_EXTRA_IGNORE_DUP_KEY";
477 break;
478 case HA_EXTRA_NO_IGNORE_DUP_KEY:
479 inspected = "HA_EXTRA_NO_IGNORE_DUP_KEY";
480 break;
481 case HA_EXTRA_PREPARE_FOR_DROP:
482 inspected = "HA_EXTRA_PREPARE_FOR_DROP";
483 break;
484 case HA_EXTRA_PREPARE_FOR_ALTER_TABLE:
485 inspected = "HA_EXTRA_PREPARE_FOR_ALTER_TABLE";
486 break;
487 case HA_EXTRA_PREPARE_FOR_UPDATE:
488 inspected = "HA_EXTRA_PREPARE_FOR_UPDATE";
489 break;
490 case HA_EXTRA_PRELOAD_BUFFER_SIZE:
491 inspected = "HA_EXTRA_PRELOAD_BUFFER_SIZE";
492 break;
493 case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
494 inspected = "HA_EXTRA_CHANGE_KEY_TO_UNIQUE";
495 break;
496 case HA_EXTRA_CHANGE_KEY_TO_DUP:
497 inspected = "HA_EXTRA_CHANGE_KEY_TO_DUP";
498 break;
499 case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
500 inspected = "HA_EXTRA_KEYREAD_PRESERVE_FIELDS";
501 break;
502 case HA_EXTRA_MMAP:
503 inspected = "HA_EXTRA_MMAP";
504 break;
505 case HA_EXTRA_IGNORE_NO_KEY:
506 inspected = "HA_EXTRA_IGNORE_NO_KEY";
507 break;
508 case HA_EXTRA_NO_IGNORE_NO_KEY:
509 inspected = "HA_EXTRA_NO_IGNORE_NO_KEY";
510 break;
511 case HA_EXTRA_MARK_AS_LOG_TABLE:
512 inspected = "HA_EXTRA_MARK_AS_LOG_TABLE";
513 break;
514 case HA_EXTRA_WRITE_CAN_REPLACE:
515 inspected = "HA_EXTRA_WRITE_CAN_REPLACE";
516 break;
517 case HA_EXTRA_WRITE_CANNOT_REPLACE:
518 inspected = "HA_EXTRA_WRITE_CANNOT_REPLACE";
519 break;
520 case HA_EXTRA_DELETE_CANNOT_BATCH:
521 inspected = "HA_EXTRA_DELETE_CANNOT_BATCH";
522 break;
523 case HA_EXTRA_UPDATE_CANNOT_BATCH:
524 inspected = "HA_EXTRA_UPDATE_CANNOT_BATCH";
525 break;
526 case HA_EXTRA_INSERT_WITH_UPDATE:
527 inspected = "HA_EXTRA_INSERT_WITH_UPDATE";
528 break;
529 case HA_EXTRA_PREPARE_FOR_RENAME:
530 inspected = "HA_EXTRA_PREPARE_FOR_RENAME";
531 break;
532 case HA_EXTRA_ADD_CHILDREN_LIST:
533 inspected = "HA_EXTRA_ADD_CHILDREN_LIST";
534 break;
535 case HA_EXTRA_ATTACH_CHILDREN:
536 inspected = "HA_EXTRA_ATTACH_CHILDREN";
537 break;
538 case HA_EXTRA_IS_ATTACHED_CHILDREN:
539 inspected = "HA_EXTRA_IS_ATTACHED_CHILDREN";
540 break;
541 case HA_EXTRA_DETACH_CHILDREN:
542 inspected = "HA_EXTRA_DETACH_CHILDREN";
543 break;
544 case HA_EXTRA_STARTING_ORDERED_INDEX_SCAN:
545 inspected = "HA_EXTRA_STARTING_ORDERED_INDEX_SCAN";
546 break;
547 case HA_EXTRA_BEGIN_ALTER_COPY:
548 inspected = "HA_EXTRA_BEGIN_ALTER_COPY";
549 break;
550 case HA_EXTRA_END_ALTER_COPY:
551 inspected = "HA_EXTRA_END_ALTER_COPY";
552 break;
553 case HA_EXTRA_FAKE_START_STMT:
554 inspected = "HA_EXTRA_FAKE_START_STMT";
555 break;
556 #ifdef MRN_HAVE_HA_EXTRA_EXPORT
557 case HA_EXTRA_EXPORT:
558 inspected = "HA_EXTRA_EXPORT";
559 break;
560 #endif
561 #ifdef MRN_HAVE_HA_EXTRA_SECONDARY_SORT_ROWID
562 case HA_EXTRA_SECONDARY_SORT_ROWID:
563 inspected = "HA_EXTRA_SECONDARY_SORT_ROWID";
564 break;
565 #endif
566 #ifdef MRN_HAVE_HA_EXTRA_DETACH_CHILD
567 case HA_EXTRA_DETACH_CHILD:
568 inspected = "HA_EXTRA_DETACH_CHILD";
569 break;
570 #endif
571 #ifdef MRN_HAVE_HA_EXTRA_PREPARE_FOR_FORCED_CLOSE
572 case HA_EXTRA_PREPARE_FOR_FORCED_CLOSE:
573 inspected = "HA_EXTRA_PREPARE_FOR_FORCED_CLOSE";
574 break;
575 #endif
576 #ifdef MRN_HAVE_HA_EXTRA_SKIP_SERIALIZABLE_DD_VIEW
577 case HA_EXTRA_SKIP_SERIALIZABLE_DD_VIEW:
578 inspected = "HA_EXTRA_SKIP_SERIALIZABLE_DD_VIEW";
579 break;
580 #endif
581 #ifdef MRN_HAVE_HA_EXTRA_BEGIN_ALTER_COPY
582 case HA_EXTRA_BEGIN_ALTER_COPY:
583 inspected = "HA_EXTRA_BEGIN_ALTER_COPY";
584 break;
585 #endif
586 #ifdef MRN_HAVE_HA_EXTRA_END_ALTER_COPY
587 case HA_EXTRA_END_ALTER_COPY:
588 inspected = "HA_EXTRA_END_ALTER_COPY";
589 break;
590 #endif
591 #ifdef MRN_HAVE_HA_EXTRA_NO_AUTOINC_LOCKING
592 case HA_EXTRA_NO_AUTOINC_LOCKING:
593 inspected = "HA_EXTRA_NO_AUTOINC_LOCKING";
594 break;
595 #endif
596 }
597 return inspected;
598 }
599 #endif
600
mrn_open_tables_get_key(const uchar * record,size_t * length,my_bool not_used)601 static uchar *mrn_open_tables_get_key(const uchar *record,
602 size_t *length,
603 my_bool not_used __attribute__ ((unused)))
604 {
605 MRN_DBUG_ENTER_FUNCTION();
606 MRN_SHARE *share = reinterpret_cast<MRN_SHARE *>(const_cast<uchar *>(record));
607 *length = share->table_name_length;
608 DBUG_RETURN(reinterpret_cast<uchar *>(share->table_name));
609 }
610
mrn_long_term_share_get_key(const uchar * record,size_t * length,my_bool not_used)611 static uchar *mrn_long_term_share_get_key(const uchar *record,
612 size_t *length,
613 my_bool not_used __attribute__ ((unused)))
614 {
615 MRN_DBUG_ENTER_FUNCTION();
616 MRN_LONG_TERM_SHARE *long_term_share =
617 reinterpret_cast<MRN_LONG_TERM_SHARE *>(const_cast<uchar *>(record));
618 *length = long_term_share->table_name_length;
619 DBUG_RETURN(reinterpret_cast<uchar *>(long_term_share->table_name));
620 }
621
622 /* status */
623 static long mrn_count_skip = 0;
624 static long mrn_fast_order_limit = 0;
625
626 /* logging */
627 static char *mrn_log_file_path = NULL;
628 static FILE *mrn_log_file = NULL;
629 static bool mrn_log_file_opened = false;
630 static grn_log_level mrn_log_level_default = GRN_LOG_DEFAULT_LEVEL;
631 static ulong mrn_log_level = mrn_log_level_default;
632 static char *mrn_query_log_file_path = NULL;
633
634 char *mrn_default_tokenizer = NULL;
635 char *mrn_default_wrapper_engine = NULL;
636 static int mrn_lock_timeout = grn_get_lock_timeout();
637 static char *mrn_libgroonga_version = const_cast<char *>(grn_get_version());
638 static char *mrn_version = const_cast<char *>(MRN_VERSION);
639 static char *mrn_vector_column_delimiter = NULL;
640 static mrn_bool mrn_libgroonga_support_zlib = false;
641 static mrn_bool mrn_libgroonga_support_lz4 = false;
642 static mrn_bool mrn_libgroonga_support_zstd = false;
643 static mrn_bool mrn_enable_operations_recording = true;
644 #ifdef MRN_SUPPORT_THDVAR_SET
645 static const char *mrn_boolean_mode_sytnax_flag_names[] = {
646 "DEFAULT",
647 "SYNTAX_QUERY",
648 "SYNTAX_SCRIPT",
649 "ALLOW_COLUMN",
650 "ALLOW_UPDATE",
651 "ALLOW_LEADING_NOT",
652 NullS
653 };
654 static TYPELIB mrn_boolean_mode_syntax_flags_typelib = {
655 array_elements(mrn_boolean_mode_sytnax_flag_names) - 1,
656 "",
657 mrn_boolean_mode_sytnax_flag_names,
658 NULL
659 };
660 #endif
661 #ifdef MRN_GROONGA_EMBEDDED
662 static mrn_bool mrn_libgroonga_embedded = true;
663 #else
664 static mrn_bool mrn_libgroonga_embedded = false;
665 #endif
666
667 static mrn::variables::ActionOnError mrn_action_on_fulltext_query_error_default =
668 mrn::variables::ACTION_ON_ERROR_ERROR_AND_LOG;
669
mrn_logger_log(grn_ctx * ctx,grn_log_level level,const char * timestamp,const char * title,const char * message,const char * location,void * user_data)670 static void mrn_logger_log(grn_ctx *ctx, grn_log_level level,
671 const char *timestamp, const char *title,
672 const char *message, const char *location,
673 void *user_data)
674 {
675 const char level_marks[] = " EACewnid-";
676 if (mrn_log_file_opened) {
677 mrn::Lock lock(&mrn_log_mutex);
678 fprintf(mrn_log_file,
679 "%s|%c|%08x|%s\n",
680 timestamp,
681 level_marks[level],
682 static_cast<uint>((ulong)(pthread_self())),
683 message);
684 fflush(mrn_log_file);
685 }
686 }
687
688 static grn_logger mrn_logger = {
689 mrn_log_level_default,
690 GRN_LOG_TIME|GRN_LOG_MESSAGE,
691 NULL,
692 mrn_logger_log,
693 NULL,
694 NULL
695 };
696
mrn_allocated_thds_get_key(const uchar * record,size_t * length,my_bool not_used)697 static uchar *mrn_allocated_thds_get_key(const uchar *record,
698 size_t *length,
699 my_bool not_used __attribute__ ((unused)))
700 {
701 MRN_DBUG_ENTER_FUNCTION();
702 *length = sizeof(THD *);
703 DBUG_RETURN(const_cast<uchar *>(record));
704 }
705
706 /* system functions */
707
708 static struct st_mysql_storage_engine storage_engine_structure =
709 { MYSQL_HANDLERTON_INTERFACE_VERSION };
710
711 #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P)
712 # define MRN_STATUS_VARIABLE_ENTRY(name, value, type, scope) \
713 {name, value, type, scope}
714 #else
715 # define MRN_STATUS_VARIABLE_ENTRY(name, value, type, scope) \
716 {name, value, type}
717 #endif
718
719 static struct st_mysql_show_var mrn_status_variables[] =
720 {
721 MRN_STATUS_VARIABLE_ENTRY(MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_count_skip",
722 (char *)&mrn_count_skip,
723 SHOW_LONG,
724 SHOW_SCOPE_GLOBAL),
725 MRN_STATUS_VARIABLE_ENTRY(MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_fast_order_limit",
726 (char *)&mrn_fast_order_limit,
727 SHOW_LONG,
728 SHOW_SCOPE_GLOBAL),
729 MRN_STATUS_VARIABLE_ENTRY(NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL)
730 };
731
732 static const char *mrn_log_level_type_names[] = {
733 "NONE",
734 "EMERG",
735 "ALERT",
736 "CRIT",
737 "ERROR",
738 "WARNING",
739 "NOTICE",
740 "INFO",
741 "DEBUG",
742 "DUMP",
743 NullS
744 };
745 static TYPELIB mrn_log_level_typelib = {
746 array_elements(mrn_log_level_type_names) - 1,
747 "mrn_log_level_typelib",
748 mrn_log_level_type_names,
749 NULL
750 };
751
mrn_log_level_update(THD * thd,struct st_mysql_sys_var * var,void * var_ptr,const void * save)752 static void mrn_log_level_update(THD *thd, struct st_mysql_sys_var *var,
753 void *var_ptr, const void *save)
754 {
755 MRN_DBUG_ENTER_FUNCTION();
756 ulong new_value = *static_cast<const ulong *>(save);
757 ulong old_value = mrn_log_level;
758 mrn_log_level = new_value;
759 mrn_logger.max_level = static_cast<grn_log_level>(mrn_log_level);
760 grn_logger_set(&mrn_ctx, &mrn_logger);
761 grn_ctx *ctx = grn_ctx_open(0);
762 mrn_change_encoding(ctx, system_charset_info);
763 GRN_LOG(ctx, GRN_LOG_NOTICE, "log level changed from '%s' to '%s'",
764 mrn_log_level_type_names[old_value],
765 mrn_log_level_type_names[new_value]);
766 grn_ctx_fin(ctx);
767 DBUG_VOID_RETURN;
768 }
769
770 static MYSQL_SYSVAR_ENUM(log_level, mrn_log_level,
771 PLUGIN_VAR_RQCMDARG,
772 "logging level",
773 NULL,
774 mrn_log_level_update,
775 static_cast<ulong>(mrn_log_level),
776 &mrn_log_level_typelib);
777
mrn_log_file_update(THD * thd,struct st_mysql_sys_var * var,void * var_ptr,const void * save)778 static void mrn_log_file_update(THD *thd, struct st_mysql_sys_var *var,
779 void *var_ptr, const void *save)
780 {
781 MRN_DBUG_ENTER_FUNCTION();
782 const char *new_value = *((const char **)save);
783 char **old_value_ptr = (char **)var_ptr;
784
785 grn_ctx *ctx = &mrn_ctx;
786 mrn_change_encoding(ctx, system_charset_info);
787
788 const char *new_log_file_name;
789 new_log_file_name = *old_value_ptr;
790
791 if (strcmp(*old_value_ptr, new_value) == 0) {
792 GRN_LOG(ctx, GRN_LOG_NOTICE,
793 "log file isn't changed "
794 "because the requested path isn't different: <%s>",
795 new_value);
796 } else {
797 GRN_LOG(ctx, GRN_LOG_NOTICE,
798 "log file is changed: <%s> -> <%s>",
799 *old_value_ptr, new_value);
800
801 int log_file_open_errno = 0;
802 {
803 mrn::Lock lock(&mrn_log_mutex);
804 FILE *new_log_file;
805 new_log_file = fopen(new_value, "a");
806 if (new_log_file) {
807 if (mrn_log_file_opened) {
808 fclose(mrn_log_file);
809 }
810 mrn_log_file = new_log_file;
811 mrn_log_file_opened = true;
812 } else {
813 log_file_open_errno = errno;
814 }
815 }
816
817 if (log_file_open_errno == 0) {
818 GRN_LOG(ctx, GRN_LOG_NOTICE,
819 "log file is changed: <%s> -> <%s>",
820 *old_value_ptr, new_value);
821 new_log_file_name = new_value;
822 } else {
823 if (mrn_log_file) {
824 GRN_LOG(ctx, GRN_LOG_ERROR,
825 "log file isn't changed "
826 "because the requested path can't be opened: <%s>: <%s>",
827 new_value, strerror(log_file_open_errno));
828 } else {
829 GRN_LOG(ctx, GRN_LOG_ERROR,
830 "log file can't be opened: <%s>: <%s>",
831 new_value, strerror(log_file_open_errno));
832 }
833 }
834 }
835
836 #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
837 char *old_log_file_name = *old_value_ptr;
838 *old_value_ptr = mrn_my_strdup(new_log_file_name, MYF(MY_WME));
839 my_free(old_log_file_name);
840 #else
841 *old_value_ptr = mrn_my_strdup(new_log_file_name, MYF(MY_WME));
842 #endif
843
844 DBUG_VOID_RETURN;
845 }
846
847 static MYSQL_SYSVAR_STR(log_file, mrn_log_file_path,
848 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
849 "log file for " MRN_PLUGIN_NAME_STRING,
850 NULL,
851 mrn_log_file_update,
852 MRN_LOG_FILE_PATH);
853
mrn_query_log_file_update(THD * thd,struct st_mysql_sys_var * var,void * var_ptr,const void * save)854 static void mrn_query_log_file_update(THD *thd, struct st_mysql_sys_var *var,
855 void *var_ptr, const void *save)
856 {
857 MRN_DBUG_ENTER_FUNCTION();
858 const char *new_value = *((const char **)save);
859 char **old_value_ptr = (char **)var_ptr;
860 const char *normalized_new_value = NULL;
861
862 grn_ctx *ctx = &mrn_ctx;
863 mrn_change_encoding(ctx, system_charset_info);
864
865 const char *new_query_log_file_name;
866 new_query_log_file_name = *old_value_ptr;
867
868 bool need_update = false;
869 if (!*old_value_ptr) {
870 if (new_value && new_value[0] != '\0') {
871 GRN_LOG(ctx, GRN_LOG_NOTICE,
872 "query log is enabled: <%s>",
873 new_value);
874 need_update = true;
875 normalized_new_value = new_value;
876 } else {
877 GRN_LOG(ctx, GRN_LOG_NOTICE,
878 "query log file is still disabled");
879 }
880 } else {
881 if (!new_value || new_value[0] == '\0') {
882 GRN_LOG(ctx, GRN_LOG_NOTICE,
883 "query log file is disabled: <%s>",
884 *old_value_ptr);
885 need_update = true;
886 normalized_new_value = NULL;
887 } else if (strcmp(*old_value_ptr, new_value) == 0) {
888 GRN_LOG(ctx, GRN_LOG_NOTICE,
889 "query log file isn't changed "
890 "because the requested path isn't different: <%s>",
891 new_value);
892 } else {
893 GRN_LOG(ctx, GRN_LOG_NOTICE,
894 "query log file is changed: <%s> -> <%s>",
895 *old_value_ptr, new_value);
896 need_update = true;
897 normalized_new_value = new_value;
898 }
899 }
900
901 if (need_update) {
902 { // TODO: Remove me when Groonga 7.0.5 is released.
903 mrn::Lock lock(&mrn_query_log_mutex);
904 grn_default_query_logger_set_path(normalized_new_value);
905 }
906 grn_query_logger_reopen(ctx);
907 new_query_log_file_name = normalized_new_value;
908 }
909
910 #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
911 char *old_query_log_file_name = *old_value_ptr;
912 #endif
913 if (new_query_log_file_name) {
914 *old_value_ptr = mrn_my_strdup(new_query_log_file_name, MYF(0));
915 } else {
916 *old_value_ptr = NULL;
917 }
918 #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
919 my_free(old_query_log_file_name);
920 #endif
921
922 DBUG_VOID_RETURN;
923 }
924
925 static MYSQL_SYSVAR_STR(query_log_file, mrn_query_log_file_path,
926 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
927 "query log file for " MRN_PLUGIN_NAME_STRING,
928 NULL,
929 mrn_query_log_file_update,
930 NULL);
931
mrn_default_tokenizer_update(THD * thd,struct st_mysql_sys_var * var,void * var_ptr,const void * save)932 static void mrn_default_tokenizer_update(THD *thd, struct st_mysql_sys_var *var,
933 void *var_ptr, const void *save)
934 {
935 MRN_DBUG_ENTER_FUNCTION();
936 const char *new_value = *((const char **)save);
937 char **old_value_ptr = (char **)var_ptr;
938 grn_ctx *ctx = &mrn_ctx;
939
940 mrn_change_encoding(ctx, system_charset_info);
941 if (strcmp(*old_value_ptr, new_value) == 0) {
942 GRN_LOG(ctx, GRN_LOG_NOTICE,
943 "default tokenizer for fulltext index isn't changed "
944 "because the requested default tokenizer isn't different: <%s>",
945 new_value);
946 } else {
947 GRN_LOG(ctx, GRN_LOG_NOTICE,
948 "default tokenizer for fulltext index is changed: <%s> -> <%s>",
949 *old_value_ptr, new_value);
950 }
951
952 #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
953 my_free(*old_value_ptr);
954 *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME));
955 #else
956 *old_value_ptr = (char *)new_value;
957 #endif
958
959 DBUG_VOID_RETURN;
960 }
961
962 static MYSQL_SYSVAR_STR(default_parser, mrn_default_tokenizer,
963 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
964 "default fulltext parser "
965 "(Deprecated. Use mroonga_default_tokenizer instead.)",
966 NULL,
967 mrn_default_tokenizer_update,
968 MRN_DEFAULT_TOKENIZER);
969
970 static MYSQL_SYSVAR_STR(default_tokenizer, mrn_default_tokenizer,
971 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
972 "default tokenizer for fulltext index",
973 NULL,
974 mrn_default_tokenizer_update,
975 MRN_DEFAULT_TOKENIZER);
976
977 static MYSQL_THDVAR_BOOL(
978 dry_write, /* name */
979 PLUGIN_VAR_OPCMDARG, /* options */
980 "If dry_write is true, any write operations are ignored.", /* comment */
981 NULL, /* check */
982 NULL, /* update */
983 false /* default */
984 );
985
986 static MYSQL_THDVAR_BOOL(
987 enable_optimization, /* name */
988 PLUGIN_VAR_OPCMDARG, /* options */
989 "If enable_optimization is true, some optimizations will be applied.", /* comment */
990 NULL, /* check */
991 NULL, /* update */
992 true /* default */
993 );
994
995 static MYSQL_THDVAR_LONGLONG(match_escalation_threshold,
996 PLUGIN_VAR_RQCMDARG,
997 "The threshold to determin whether search method is escalated",
998 NULL,
999 NULL,
1000 grn_get_default_match_escalation_threshold(),
1001 -1,
1002 INT_MAX64,
1003 0);
1004
mrn_vector_column_delimiter_update(THD * thd,struct st_mysql_sys_var * var,void * var_ptr,const void * save)1005 static void mrn_vector_column_delimiter_update(THD *thd, struct st_mysql_sys_var *var,
1006 void *var_ptr, const void *save)
1007 {
1008 MRN_DBUG_ENTER_FUNCTION();
1009 const char *new_value = *((const char **)save);
1010 char **old_value_ptr = (char **)var_ptr;
1011
1012 #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
1013 my_free(*old_value_ptr);
1014 *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME));
1015 #else
1016 *old_value_ptr = (char *)new_value;
1017 #endif
1018
1019 DBUG_VOID_RETURN;
1020 }
1021
1022 static MYSQL_SYSVAR_STR(vector_column_delimiter, mrn_vector_column_delimiter,
1023 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
1024 "The vector column delimiter",
1025 NULL,
1026 &mrn_vector_column_delimiter_update,
1027 " ");
1028
mrn_database_path_prefix_update(THD * thd,struct st_mysql_sys_var * var,void * var_ptr,const void * save)1029 static void mrn_database_path_prefix_update(THD *thd,
1030 struct st_mysql_sys_var *var,
1031 void *var_ptr, const void *save)
1032 {
1033 MRN_DBUG_ENTER_FUNCTION();
1034 const char *new_value = *((const char **)save);
1035 char **old_value_ptr = (char **)var_ptr;
1036 #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR
1037 if (*old_value_ptr)
1038 my_free(*old_value_ptr);
1039 if (new_value)
1040 *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME));
1041 else
1042 *old_value_ptr = NULL;
1043 #else
1044 *old_value_ptr = (char *)new_value;
1045 #endif
1046 DBUG_VOID_RETURN;
1047 }
1048
1049 static MYSQL_SYSVAR_STR(database_path_prefix,
1050 mrn::PathMapper::default_path_prefix,
1051 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC,
1052 "The database path prefix",
1053 NULL,
1054 &mrn_database_path_prefix_update,
1055 NULL);
1056
1057 static MYSQL_SYSVAR_STR(default_wrapper_engine, mrn_default_wrapper_engine,
1058 PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY,
1059 "The default engine for wrapper mode",
1060 NULL,
1061 NULL,
1062 NULL);
1063
1064 static const char *mrn_action_on_error_names[] = {
1065 "ERROR",
1066 "ERROR_AND_LOG",
1067 "IGNORE",
1068 "IGNORE_AND_LOG",
1069 NullS,
1070 };
1071
1072 static TYPELIB mrn_action_on_error_typelib =
1073 {
1074 array_elements(mrn_action_on_error_names) - 1,
1075 "mrn_action_on_error_typelib",
1076 mrn_action_on_error_names,
1077 NULL
1078 };
1079
1080 static MYSQL_THDVAR_ENUM(action_on_fulltext_query_error,
1081 PLUGIN_VAR_RQCMDARG,
1082 "action on fulltext query error",
1083 NULL,
1084 NULL,
1085 mrn_action_on_fulltext_query_error_default,
1086 &mrn_action_on_error_typelib);
1087
mrn_lock_timeout_update(THD * thd,struct st_mysql_sys_var * var,void * var_ptr,const void * save)1088 static void mrn_lock_timeout_update(THD *thd, struct st_mysql_sys_var *var,
1089 void *var_ptr, const void *save)
1090 {
1091 MRN_DBUG_ENTER_FUNCTION();
1092 const int new_value = *static_cast<const int *>(save);
1093 int *old_value_ptr = static_cast<int *>(var_ptr);
1094
1095 *old_value_ptr = new_value;
1096 grn_set_lock_timeout(new_value);
1097
1098 DBUG_VOID_RETURN;
1099 }
1100
1101 static MYSQL_SYSVAR_INT(lock_timeout,
1102 mrn_lock_timeout,
1103 PLUGIN_VAR_RQCMDARG,
1104 "lock timeout used in Groonga",
1105 NULL,
1106 mrn_lock_timeout_update,
1107 grn_get_lock_timeout(),
1108 -1,
1109 INT_MAX,
1110 1);
1111
1112 static MYSQL_SYSVAR_STR(libgroonga_version, mrn_libgroonga_version,
1113 PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
1114 "The version of libgroonga",
1115 NULL,
1116 NULL,
1117 grn_get_version());
1118
1119 static MYSQL_SYSVAR_STR(version, mrn_version,
1120 PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY,
1121 "The version of mroonga",
1122 NULL,
1123 NULL,
1124 MRN_VERSION);
1125
grn_check_zlib_support()1126 static mrn_bool grn_check_zlib_support()
1127 {
1128 bool is_zlib_support = false;
1129 grn_obj grn_support_p;
1130
1131 GRN_BOOL_INIT(&grn_support_p, 0);
1132 grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_ZLIB, &grn_support_p);
1133 is_zlib_support = (GRN_BOOL_VALUE(&grn_support_p));
1134 grn_obj_unlink(&mrn_ctx, &grn_support_p);
1135
1136 return is_zlib_support;
1137 }
1138
1139 static MYSQL_SYSVAR_BOOL(libgroonga_support_zlib, mrn_libgroonga_support_zlib,
1140 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
1141 "The status of libgroonga supports zlib",
1142 NULL,
1143 NULL,
1144 grn_check_zlib_support());
1145
grn_check_lz4_support()1146 static mrn_bool grn_check_lz4_support()
1147 {
1148 bool is_lz4_support = false;
1149 grn_obj grn_support_p;
1150
1151 GRN_BOOL_INIT(&grn_support_p, 0);
1152 grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_LZ4, &grn_support_p);
1153 is_lz4_support = (GRN_BOOL_VALUE(&grn_support_p));
1154 grn_obj_unlink(&mrn_ctx, &grn_support_p);
1155
1156 return is_lz4_support;
1157 }
1158
1159 static MYSQL_SYSVAR_BOOL(libgroonga_support_lz4, mrn_libgroonga_support_lz4,
1160 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
1161 "The status of libgroonga supports LZ4",
1162 NULL,
1163 NULL,
1164 grn_check_lz4_support());
1165
grn_check_zstd_support()1166 static mrn_bool grn_check_zstd_support()
1167 {
1168 bool is_zstd_support = false;
1169 grn_obj grn_support_p;
1170
1171 GRN_BOOL_INIT(&grn_support_p, 0);
1172 grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_ZSTD, &grn_support_p);
1173 is_zstd_support = (GRN_BOOL_VALUE(&grn_support_p));
1174 grn_obj_unlink(&mrn_ctx, &grn_support_p);
1175
1176 return is_zstd_support;
1177 }
1178
1179 static MYSQL_SYSVAR_BOOL(libgroonga_support_zstd, mrn_libgroonga_support_zstd,
1180 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
1181 "The status of libgroonga supports Zstandard",
1182 NULL,
1183 NULL,
1184 grn_check_zstd_support());
1185
mrn_enable_operations_recording_update(THD * thd,struct st_mysql_sys_var * var,void * var_ptr,const void * save)1186 static void mrn_enable_operations_recording_update(THD *thd, struct st_mysql_sys_var *var,
1187 void *var_ptr, const void *save)
1188 {
1189 MRN_DBUG_ENTER_FUNCTION();
1190 const bool new_value = *static_cast<const bool *>(save);
1191 bool *old_value_ptr = static_cast<bool *>(var_ptr);
1192
1193 *old_value_ptr = new_value;
1194
1195 DBUG_VOID_RETURN;
1196 }
1197
1198 static MYSQL_SYSVAR_BOOL(enable_operations_recording, mrn_enable_operations_recording,
1199 PLUGIN_VAR_RQCMDARG,
1200 "Whether recording operations for recovery is enabled or not",
1201 NULL,
1202 mrn_enable_operations_recording_update,
1203 true);
1204
1205 #ifdef MRN_SUPPORT_THDVAR_SET
1206 static MYSQL_THDVAR_SET(boolean_mode_syntax_flags,
1207 PLUGIN_VAR_RQCMDARG,
1208 "The flags to custom syntax in BOOLEAN MODE. "
1209 "Available flags: "
1210 "DEFAULT(=SYNTAX_QUERY,ALLOW_LEADING_NOT), "
1211 "SYNTAX_QUERY, SYNTAX_SCRIPT, "
1212 "ALLOW_COLUMN, ALLOW_UPDATE and ALLOW_LEADING_NOT",
1213 NULL,
1214 NULL,
1215 mrn::variables::BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT,
1216 &mrn_boolean_mode_syntax_flags_typelib);
1217 #endif
1218
1219 static const int MRN_MAX_N_RECORDS_FOR_ESTIMATE_DEFAULT = 1000;
1220
1221 static MYSQL_THDVAR_INT(max_n_records_for_estimate,
1222 PLUGIN_VAR_RQCMDARG,
1223 "The max number of records to "
1224 "estimate the number of matched records",
1225 NULL,
1226 NULL,
1227 MRN_MAX_N_RECORDS_FOR_ESTIMATE_DEFAULT,
1228 -1,
1229 INT_MAX,
1230 0);
1231
1232 static MYSQL_SYSVAR_BOOL(libgroonga_embedded, mrn_libgroonga_embedded,
1233 PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY,
1234 "Whether libgroonga is embedded or not",
1235 NULL,
1236 NULL,
1237 mrn_libgroonga_embedded);
1238
1239 static struct st_mysql_sys_var *mrn_system_variables[] =
1240 {
1241 MYSQL_SYSVAR(log_level),
1242 MYSQL_SYSVAR(log_file),
1243 MYSQL_SYSVAR(default_parser),
1244 MYSQL_SYSVAR(default_tokenizer),
1245 MYSQL_SYSVAR(dry_write),
1246 MYSQL_SYSVAR(enable_optimization),
1247 MYSQL_SYSVAR(match_escalation_threshold),
1248 MYSQL_SYSVAR(database_path_prefix),
1249 MYSQL_SYSVAR(default_wrapper_engine),
1250 MYSQL_SYSVAR(action_on_fulltext_query_error),
1251 MYSQL_SYSVAR(lock_timeout),
1252 MYSQL_SYSVAR(libgroonga_version),
1253 MYSQL_SYSVAR(version),
1254 MYSQL_SYSVAR(vector_column_delimiter),
1255 MYSQL_SYSVAR(libgroonga_support_zlib),
1256 MYSQL_SYSVAR(libgroonga_support_lz4),
1257 MYSQL_SYSVAR(libgroonga_support_zstd),
1258 #ifdef MRN_SUPPORT_THDVAR_SET
1259 MYSQL_SYSVAR(boolean_mode_syntax_flags),
1260 #endif
1261 MYSQL_SYSVAR(max_n_records_for_estimate),
1262 MYSQL_SYSVAR(libgroonga_embedded),
1263 MYSQL_SYSVAR(query_log_file),
1264 MYSQL_SYSVAR(enable_operations_recording),
1265 NULL
1266 };
1267
1268 /* mroonga information schema */
1269 static struct st_mysql_information_schema i_s_info =
1270 {
1271 MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
1272 };
1273
1274 static ST_FIELD_INFO i_s_mrn_stats_fields_info[] =
1275 {
1276 {
1277 "VERSION",
1278 40,
1279 MYSQL_TYPE_STRING,
1280 0,
1281 0,
1282 "",
1283 SKIP_OPEN_TABLE
1284 },
1285 {
1286 "rows_written",
1287 MY_INT32_NUM_DECIMAL_DIGITS,
1288 MYSQL_TYPE_LONG,
1289 0,
1290 0,
1291 "Rows written to Groonga",
1292 SKIP_OPEN_TABLE
1293 },
1294 {
1295 "rows_read",
1296 MY_INT32_NUM_DECIMAL_DIGITS,
1297 MYSQL_TYPE_LONG,
1298 0,
1299 0,
1300 "Rows read from Groonga",
1301 SKIP_OPEN_TABLE
1302 },
1303 { 0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0}
1304 };
1305
i_s_mrn_stats_deinit(void * p)1306 static int i_s_mrn_stats_deinit(void* p)
1307 {
1308 MRN_DBUG_ENTER_FUNCTION();
1309 DBUG_RETURN(0);
1310 }
1311
i_s_mrn_stats_fill(THD * thd,TABLE_LIST * tables,Item * cond)1312 static int i_s_mrn_stats_fill(
1313 THD* thd, TABLE_LIST* tables, Item* cond)
1314 {
1315 TABLE* table = (TABLE *) tables->table;
1316 int status = 0;
1317 MRN_DBUG_ENTER_FUNCTION();
1318 table->field[0]->store(grn_get_version(), strlen(grn_get_version()),
1319 system_charset_info);
1320 table->field[0]->set_notnull();
1321 table->field[1]->store(1); /* TODO */
1322 table->field[2]->store(2); /* TODO */
1323 if (schema_table_store_record(thd, table)) {
1324 status = 1;
1325 }
1326 DBUG_RETURN(status);
1327 }
1328
i_s_mrn_stats_init(void * p)1329 static int i_s_mrn_stats_init(void* p)
1330 {
1331 MRN_DBUG_ENTER_FUNCTION();
1332 ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p;
1333 schema->fields_info = i_s_mrn_stats_fields_info;
1334 schema->fill_table = i_s_mrn_stats_fill;
1335 DBUG_RETURN(0);
1336 }
1337
1338 struct st_mysql_plugin i_s_mrn_stats =
1339 {
1340 MYSQL_INFORMATION_SCHEMA_PLUGIN,
1341 &i_s_info,
1342 MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_stats",
1343 MRN_PLUGIN_AUTHOR,
1344 "Statistics for " MRN_PLUGIN_NAME_STRING,
1345 PLUGIN_LICENSE_GPL,
1346 i_s_mrn_stats_init,
1347 #ifdef MRN_ST_MYSQL_PLUGIN_HAVE_CHECK_UNINSTALL
1348 NULL,
1349 #endif
1350 i_s_mrn_stats_deinit,
1351 MRN_VERSION_IN_HEX,
1352 NULL,
1353 NULL,
1354 MRN_PLUGIN_LAST_VALUES
1355 };
1356 /* End of mroonga information schema implementations */
1357
mrn_handler_create(handlerton * hton,TABLE_SHARE * share,bool partitioned,MEM_ROOT * root)1358 static handler *mrn_handler_create(handlerton *hton,
1359 TABLE_SHARE *share,
1360 #ifdef MRN_HANDLERTON_CREATE_HAVE_PARTITIONED
1361 bool partitioned,
1362 #endif
1363 MEM_ROOT *root)
1364 {
1365 MRN_DBUG_ENTER_FUNCTION();
1366 handler *new_handler = new (root) ha_mroonga(hton, share);
1367 DBUG_RETURN(new_handler);
1368 }
1369
mrn_drop_database(handlerton * hton,char * path)1370 static void mrn_drop_database(handlerton *hton, char *path)
1371 {
1372 MRN_DBUG_ENTER_FUNCTION();
1373 mrn_db_manager->drop(path);
1374 DBUG_VOID_RETURN;
1375 }
1376
mrn_close_connection(handlerton * hton,THD * thd)1377 static int mrn_close_connection(handlerton *hton, THD *thd)
1378 {
1379 MRN_DBUG_ENTER_FUNCTION();
1380 void *p = *thd_ha_data(thd, mrn_hton_ptr);
1381 if (p) {
1382 mrn_clear_slot_data(thd);
1383 free(p);
1384 *thd_ha_data(thd, mrn_hton_ptr) = (void *) NULL;
1385 {
1386 mrn::Lock lock(&mrn_allocated_thds_mutex);
1387 my_hash_delete(&mrn_allocated_thds, (uchar*) thd);
1388 }
1389 }
1390 DBUG_RETURN(0);
1391 }
1392
1393 #ifdef MRN_FLUSH_LOGS_HAVE_BINLOG_GROUP_FLUSH
mrn_flush_logs(handlerton * hton,bool binlog_group_flush)1394 static bool mrn_flush_logs(handlerton *hton, bool binlog_group_flush)
1395 #else
1396 static bool mrn_flush_logs(handlerton *hton)
1397 #endif
1398 {
1399 MRN_DBUG_ENTER_FUNCTION();
1400 bool result = 0;
1401 if (mrn_log_file_opened) {
1402 mrn::Lock lock(&mrn_log_mutex);
1403 fclose(mrn_log_file);
1404 mrn_log_file = fopen(mrn_log_file_path, "a");
1405 }
1406 DBUG_RETURN(result);
1407 }
1408
mrn_grn_type_from_field(grn_ctx * ctx,Field * field,bool for_index_key)1409 static grn_builtin_type mrn_grn_type_from_field(grn_ctx *ctx, Field *field,
1410 bool for_index_key)
1411 {
1412 grn_builtin_type type = GRN_DB_VOID;
1413 enum_field_types mysql_field_type = field->real_type();
1414 switch (mysql_field_type) {
1415 case MYSQL_TYPE_DECIMAL: // DECIMAL; <= 65bytes
1416 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1417 break;
1418 case MYSQL_TYPE_TINY: // TINYINT; 1byte
1419 if (static_cast<Field_num *>(field)->unsigned_flag) {
1420 type = GRN_DB_UINT8; // 1byte
1421 } else {
1422 type = GRN_DB_INT8; // 1byte
1423 }
1424 break;
1425 case MYSQL_TYPE_SHORT: // SMALLINT; 2bytes
1426 if (static_cast<Field_num *>(field)->unsigned_flag) {
1427 type = GRN_DB_UINT16; // 2bytes
1428 } else {
1429 type = GRN_DB_INT16; // 2bytes
1430 }
1431 break;
1432 case MYSQL_TYPE_LONG: // INT; 4bytes
1433 if (static_cast<Field_num *>(field)->unsigned_flag) {
1434 type = GRN_DB_UINT32; // 4bytes
1435 } else {
1436 type = GRN_DB_INT32; // 4bytes
1437 }
1438 break;
1439 case MYSQL_TYPE_FLOAT: // FLOAT; 4 or 8bytes
1440 case MYSQL_TYPE_DOUBLE: // DOUBLE; 8bytes
1441 type = GRN_DB_FLOAT; // 8bytes
1442 break;
1443 case MYSQL_TYPE_NULL: // NULL; 1byte
1444 type = GRN_DB_INT8; // 1byte
1445 break;
1446 case MYSQL_TYPE_TIMESTAMP: // TIMESTAMP; 4bytes
1447 type = GRN_DB_TIME; // 8bytes
1448 break;
1449 case MYSQL_TYPE_LONGLONG: // BIGINT; 8bytes
1450 if (static_cast<Field_num *>(field)->unsigned_flag) {
1451 type = GRN_DB_UINT64; // 8bytes
1452 } else {
1453 type = GRN_DB_INT64; // 8bytes
1454 }
1455 break;
1456 case MYSQL_TYPE_INT24: // MEDIUMINT; 3bytes
1457 if (static_cast<Field_num *>(field)->unsigned_flag) {
1458 type = GRN_DB_UINT32; // 4bytes
1459 } else {
1460 type = GRN_DB_INT32; // 4bytes
1461 }
1462 break;
1463 case MYSQL_TYPE_DATE: // DATE; 4bytes
1464 case MYSQL_TYPE_TIME: // TIME; 3bytes
1465 case MYSQL_TYPE_DATETIME: // DATETIME; 8bytes
1466 case MYSQL_TYPE_YEAR: // YEAR; 1byte
1467 case MYSQL_TYPE_NEWDATE: // DATE; 3bytes
1468 type = GRN_DB_TIME; // 8bytes
1469 break;
1470 case MYSQL_TYPE_VARCHAR: // VARCHAR; <= 64KB * 4 + 2bytes
1471 if (for_index_key) {
1472 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1473 } else {
1474 if (field->field_length <= MRN_SHORT_TEXT_SIZE) {
1475 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1476 } else if (field->field_length <= MRN_TEXT_SIZE) {
1477 type = GRN_DB_TEXT; // 64Kbytes
1478 } else {
1479 type = GRN_DB_LONG_TEXT; // 2Gbytes
1480 }
1481 }
1482 break;
1483 case MYSQL_TYPE_BIT: // BIT; <= 8bytes
1484 type = GRN_DB_INT64; // 8bytes
1485 break;
1486 #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2
1487 case MYSQL_TYPE_TIMESTAMP2: // TIMESTAMP; 4bytes
1488 type = GRN_DB_TIME; // 8bytes
1489 break;
1490 #endif
1491 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2
1492 case MYSQL_TYPE_DATETIME2: // DATETIME; 8bytes
1493 type = GRN_DB_TIME; // 8bytes
1494 break;
1495 #endif
1496 #ifdef MRN_HAVE_MYSQL_TYPE_TIME2
1497 case MYSQL_TYPE_TIME2: // TIME(FSP); 3 + (FSP + 1) / 2 bytes
1498 // 0 <= FSP <= 6; 3-6bytes
1499 type = GRN_DB_TIME; // 8bytes
1500 break;
1501 #endif
1502 case MYSQL_TYPE_NEWDECIMAL: // DECIMAL; <= 9bytes
1503 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1504 break;
1505 case MYSQL_TYPE_ENUM: // ENUM; <= 2bytes
1506 if (field->pack_length() == 1) {
1507 type = GRN_DB_UINT8; // 1bytes
1508 } else {
1509 type = GRN_DB_UINT16; // 2bytes
1510 }
1511 break;
1512 case MYSQL_TYPE_SET: // SET; <= 8bytes
1513 switch (field->pack_length()) {
1514 case 1:
1515 type = GRN_DB_UINT8; // 1byte
1516 break;
1517 case 2:
1518 type = GRN_DB_UINT16; // 2bytes
1519 break;
1520 case 3:
1521 case 4:
1522 type = GRN_DB_UINT32; // 3bytes
1523 break;
1524 case 8:
1525 default:
1526 type = GRN_DB_UINT64; // 8bytes
1527 break;
1528 }
1529 break;
1530 case MYSQL_TYPE_TINY_BLOB: // TINYBLOB; <= 256bytes + 1byte
1531 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1532 break;
1533 case MYSQL_TYPE_MEDIUM_BLOB: // MEDIUMBLOB; <= 16Mbytes + 3bytes
1534 if (for_index_key) {
1535 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1536 } else {
1537 type = GRN_DB_LONG_TEXT; // 2Gbytes
1538 }
1539 break;
1540 case MYSQL_TYPE_LONG_BLOB: // LONGBLOB; <= 4Gbytes + 4bytes
1541 if (for_index_key) {
1542 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1543 } else {
1544 type = GRN_DB_LONG_TEXT; // 2Gbytes
1545 }
1546 break;
1547 case MYSQL_TYPE_BLOB: // BLOB; <= 64Kbytes + 2bytes
1548 if (for_index_key) {
1549 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1550 } else {
1551 type = GRN_DB_LONG_TEXT; // 2Gbytes
1552 }
1553 break;
1554 case MYSQL_TYPE_VAR_STRING: // VARCHAR; <= 255byte * 4 + 1bytes
1555 if (for_index_key) {
1556 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1557 } else {
1558 if (field->field_length <= MRN_SHORT_TEXT_SIZE) {
1559 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1560 } else if (field->field_length <= MRN_TEXT_SIZE) {
1561 type = GRN_DB_TEXT; // 64Kbytes
1562 } else {
1563 type = GRN_DB_LONG_TEXT; // 2Gbytes
1564 }
1565 }
1566 break;
1567 case MYSQL_TYPE_STRING: // CHAR; < 1Kbytes =~ (255 * 4)bytes
1568 // 4 is the maximum size of a character
1569 type = GRN_DB_SHORT_TEXT; // 4Kbytes
1570 break;
1571 case MYSQL_TYPE_GEOMETRY: // case-by-case
1572 type = GRN_DB_WGS84_GEO_POINT; // 8bytes
1573 break;
1574 case MYSQL_TYPE_VARCHAR_COMPRESSED:
1575 case MYSQL_TYPE_BLOB_COMPRESSED:
1576 DBUG_ASSERT(0);
1577 #ifdef MRN_HAVE_MYSQL_TYPE_JSON
1578 case MYSQL_TYPE_JSON:
1579 type = GRN_DB_TEXT;
1580 break;
1581 #endif
1582 }
1583 return type;
1584 }
1585
mrn_parse_grn_column_create_flags(THD * thd,grn_ctx * ctx,const char * flag_names,uint flag_names_length,grn_obj_flags * column_flags)1586 static bool mrn_parse_grn_column_create_flags(THD *thd,
1587 grn_ctx *ctx,
1588 const char *flag_names,
1589 uint flag_names_length,
1590 grn_obj_flags *column_flags)
1591 {
1592 const char *flag_names_end = flag_names + flag_names_length;
1593 bool found = false;
1594
1595 while (flag_names < flag_names_end) {
1596 uint rest_length = flag_names_end - flag_names;
1597
1598 if (*flag_names == '|' || *flag_names == ' ') {
1599 flag_names += 1;
1600 continue;
1601 }
1602 if (rest_length >= 13 && !memcmp(flag_names, "COLUMN_SCALAR", 13)) {
1603 *column_flags |= GRN_OBJ_COLUMN_SCALAR;
1604 flag_names += 13;
1605 found = true;
1606 } else if (rest_length >= 13 && !memcmp(flag_names, "COLUMN_VECTOR", 13)) {
1607 *column_flags |= GRN_OBJ_COLUMN_VECTOR;
1608 flag_names += 13;
1609 found = true;
1610 } else if (rest_length >= 13 && !memcmp(flag_names, "COMPRESS_ZLIB", 13)) {
1611 if (mrn_libgroonga_support_zlib) {
1612 *column_flags |= GRN_OBJ_COMPRESS_ZLIB;
1613 found = true;
1614 } else {
1615 push_warning_printf(thd, MRN_SEVERITY_WARNING,
1616 ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM,
1617 ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR,
1618 "COMPRESS_ZLIB");
1619 }
1620 flag_names += 13;
1621 } else if (rest_length >= 12 && !memcmp(flag_names, "COMPRESS_LZ4", 12)) {
1622 if (mrn_libgroonga_support_lz4) {
1623 *column_flags |= GRN_OBJ_COMPRESS_LZ4;
1624 found = true;
1625 } else {
1626 push_warning_printf(thd, MRN_SEVERITY_WARNING,
1627 ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM,
1628 ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR,
1629 "COMPRESS_LZ4");
1630 }
1631 flag_names += 12;
1632 } else if (rest_length >= 13 && !memcmp(flag_names, "COMPRESS_ZSTD", 13)) {
1633 if (mrn_libgroonga_support_zstd) {
1634 *column_flags |= GRN_OBJ_COMPRESS_ZSTD;
1635 found = true;
1636 } else {
1637 push_warning_printf(thd, MRN_SEVERITY_WARNING,
1638 ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM,
1639 ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR,
1640 "COMPRESS_ZSTD");
1641 }
1642 flag_names += 13;
1643 } else {
1644 char invalid_flag_name[MRN_MESSAGE_BUFFER_SIZE];
1645 snprintf(invalid_flag_name, MRN_MESSAGE_BUFFER_SIZE,
1646 "%.*s",
1647 static_cast<int>(rest_length),
1648 flag_names);
1649 push_warning_printf(thd, MRN_SEVERITY_WARNING,
1650 ER_MRN_INVALID_COLUMN_FLAG_NUM,
1651 ER_MRN_INVALID_COLUMN_FLAG_STR,
1652 invalid_flag_name);
1653 break;
1654 }
1655 }
1656 return found;
1657 }
1658
mrn_parse_grn_index_column_flags(THD * thd,grn_ctx * ctx,const char * flag_names,uint flag_names_length,grn_column_flags * index_column_flags)1659 static bool mrn_parse_grn_index_column_flags(THD *thd,
1660 grn_ctx *ctx,
1661 const char *flag_names,
1662 uint flag_names_length,
1663 grn_column_flags *index_column_flags)
1664 {
1665 const char *flag_names_end = flag_names + flag_names_length;
1666 bool found = false;
1667
1668 while (flag_names < flag_names_end) {
1669 uint rest_length = flag_names_end - flag_names;
1670
1671 if (*flag_names == '|' || *flag_names == ' ') {
1672 flag_names += 1;
1673 continue;
1674 }
1675 if (rest_length >= 4 && !memcmp(flag_names, "NONE", 4)) {
1676 flag_names += 4;
1677 found = true;
1678 } else if (rest_length >= 13 && !memcmp(flag_names, "WITH_POSITION", 13)) {
1679 *index_column_flags |= GRN_OBJ_WITH_POSITION;
1680 flag_names += 13;
1681 found = true;
1682 } else if (rest_length >= 12 && !memcmp(flag_names, "WITH_SECTION", 12)) {
1683 *index_column_flags |= GRN_OBJ_WITH_SECTION;
1684 flag_names += 12;
1685 found = true;
1686 } else if (rest_length >= 11 && !memcmp(flag_names, "WITH_WEIGHT", 11)) {
1687 *index_column_flags |= GRN_OBJ_WITH_WEIGHT;
1688 flag_names += 11;
1689 found = true;
1690 } else if (rest_length >= 11 && !memcmp(flag_names, "INDEX_SMALL", 11)) {
1691 *index_column_flags |= GRN_OBJ_INDEX_SMALL;
1692 flag_names += 11;
1693 found = true;
1694 } else if (rest_length >= 12 && !memcmp(flag_names, "INDEX_MEDIUM", 12)) {
1695 *index_column_flags |= GRN_OBJ_INDEX_MEDIUM;
1696 flag_names += 12;
1697 found = true;
1698 } else {
1699 char invalid_flag_name[MRN_MESSAGE_BUFFER_SIZE];
1700 snprintf(invalid_flag_name, MRN_MESSAGE_BUFFER_SIZE,
1701 "%.*s",
1702 static_cast<int>(rest_length),
1703 flag_names);
1704 push_warning_printf(thd, MRN_SEVERITY_WARNING,
1705 ER_MRN_INVALID_INDEX_FLAG_NUM,
1706 ER_MRN_INVALID_INDEX_FLAG_STR,
1707 invalid_flag_name);
1708 }
1709 }
1710 return found;
1711 }
1712
1713 #ifdef MRN_HAVE_SPATIAL
mrn_set_geometry(grn_ctx * ctx,grn_obj * buf,const char * wkb,uint wkb_size)1714 static int mrn_set_geometry(grn_ctx *ctx, grn_obj *buf,
1715 const char *wkb, uint wkb_size)
1716 {
1717 int error = 0;
1718 Geometry_buffer buffer;
1719 Geometry *geometry;
1720
1721 geometry = Geometry::construct(&buffer, wkb, wkb_size);
1722 if (!geometry) {
1723 return ER_CANT_CREATE_GEOMETRY_OBJECT;
1724 }
1725 switch (geometry->get_class_info()->m_type_id) {
1726 case Geometry::wkb_point:
1727 {
1728 Gis_point *point = (Gis_point *)geometry;
1729 double latitude = 0.0, longitude = 0.0;
1730 #ifdef MRN_HAVE_POINT_XY
1731 point_xy xy(0.0, 0.0);
1732 point->get_xy(&xy);
1733 longitude = xy.x;
1734 latitude = xy.y;
1735 #else
1736 point->get_xy(&longitude, &latitude);
1737 #endif
1738 grn_obj_reinit(ctx, buf, GRN_DB_WGS84_GEO_POINT, 0);
1739 GRN_GEO_POINT_SET(ctx, buf,
1740 GRN_GEO_DEGREE2MSEC(latitude),
1741 GRN_GEO_DEGREE2MSEC(longitude));
1742 break;
1743 }
1744 default:
1745 my_printf_error(ER_MRN_GEOMETRY_NOT_SUPPORT_NUM,
1746 ER_MRN_GEOMETRY_NOT_SUPPORT_STR, MYF(0));
1747 error = ER_MRN_GEOMETRY_NOT_SUPPORT_NUM;
1748 break;
1749 }
1750 MRN_GEOMETRY_FREE(geometry);
1751
1752 return error;
1753 }
1754 #endif
1755
1756 #ifdef MRN_HAVE_HTON_ALTER_TABLE_FLAGS
mrn_alter_table_flags(alter_table_operations flags)1757 static alter_table_operations mrn_alter_table_flags(alter_table_operations flags)
1758 {
1759 ulonglong alter_flags = 0;
1760 #ifdef HA_INPLACE_ADD_INDEX_NO_READ_WRITE
1761 bool is_inplace_index_change;
1762 # ifdef MRN_HAVE_ALTER_INFO
1763 is_inplace_index_change = (((flags & ALTER_ADD_INDEX) &&
1764 (flags & ALTER_DROP_INDEX)) ||
1765 (flags & ALTER_CHANGE_COLUMN));
1766 # else
1767 is_inplace_index_change = (((flags & ALTER_ADD_INDEX) &&
1768 (flags & ALTER_DROP_INDEX)) ||
1769 (flags & ALTER_CHANGE_COLUMN));
1770 # endif
1771 if (!is_inplace_index_change) {
1772 alter_flags |=
1773 HA_INPLACE_ADD_INDEX_NO_READ_WRITE |
1774 HA_INPLACE_DROP_INDEX_NO_READ_WRITE |
1775 HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE |
1776 HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE |
1777 HA_INPLACE_ADD_INDEX_NO_WRITE |
1778 HA_INPLACE_DROP_INDEX_NO_WRITE |
1779 HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE |
1780 HA_INPLACE_DROP_UNIQUE_INDEX_NO_WRITE;
1781 }
1782 #endif
1783 return alter_flags;
1784 }
1785 #endif
1786
1787 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
1788 static ha_create_table_option mrn_field_options[] =
1789 {
1790 HA_FOPTION_STRING("GROONGA_TYPE", groonga_type),
1791 HA_FOPTION_STRING("FLAGS", flags),
1792 HA_FOPTION_END
1793 };
1794
1795 static ha_create_table_option mrn_index_options[] =
1796 {
1797 HA_IOPTION_STRING("TOKENIZER", tokenizer),
1798 HA_IOPTION_STRING("NORMALIZER", normalizer),
1799 HA_IOPTION_STRING("TOKEN_FILTERS", token_filters),
1800 HA_IOPTION_STRING("FLAGS", flags),
1801 HA_IOPTION_END
1802 };
1803 #endif
1804
mrn_init(void * p)1805 static int mrn_init(void *p)
1806 {
1807 // init handlerton
1808 grn_ctx *ctx = NULL;
1809 handlerton *hton = static_cast<handlerton *>(p);
1810 hton->state = SHOW_OPTION_YES;
1811 hton->create = mrn_handler_create;
1812 hton->flags = HTON_NO_FLAGS;
1813 #ifndef MRN_SUPPORT_PARTITION
1814 hton->flags |= HTON_NO_PARTITION;
1815 #endif
1816 hton->drop_database = mrn_drop_database;
1817 hton->close_connection = mrn_close_connection;
1818 hton->flush_logs = mrn_flush_logs;
1819 #ifdef MRN_HAVE_HTON_ALTER_TABLE_FLAGS
1820 hton->alter_table_flags = mrn_alter_table_flags;
1821 #endif
1822 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
1823 hton->field_options = mrn_field_options;
1824 hton->index_options = mrn_index_options;
1825 #endif
1826 mrn_hton_ptr = hton;
1827
1828 #ifdef _WIN32
1829 HMODULE current_module = GetModuleHandle(NULL);
1830 mrn_binlog_filter =
1831 *((Rpl_filter **)GetProcAddress(current_module, MRN_BINLOG_FILTER_PROC));
1832 mrn_my_tz_UTC =
1833 *((Time_zone **)GetProcAddress(current_module, MRN_MY_TZ_UTC_PROC));
1834 # ifdef MRN_HAVE_TABLE_DEF_CACHE
1835 mrn_table_def_cache = (HASH *)GetProcAddress(current_module,
1836 "?table_def_cache@@3Ust_hash@@A");
1837 # endif
1838 # ifndef MRN_HAVE_TDC_LOCK_TABLE_SHARE
1839 mrn_LOCK_open =
1840 (mysql_mutex_t *)GetProcAddress(current_module,
1841 "?LOCK_open@@3Ust_mysql_mutex@@A");
1842 # endif
1843 # ifdef HAVE_PSI_INTERFACE
1844 # ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
1845 mrn_table_share_lock_share =
1846 (PSI_mutex_key *)GetProcAddress(current_module,
1847 MRN_TABLE_SHARE_LOCK_SHARE_PROC);
1848 # endif
1849 mrn_table_share_lock_ha_data =
1850 (PSI_mutex_key *)GetProcAddress(current_module,
1851 MRN_TABLE_SHARE_LOCK_HA_DATA_PROC);
1852 # endif
1853 #else
1854 mrn_binlog_filter = binlog_filter;
1855 mrn_my_tz_UTC = my_tz_UTC;
1856 # ifdef MRN_HAVE_TABLE_DEF_CACHE
1857 mrn_table_def_cache = &table_def_cache;
1858 # endif
1859 # ifndef MRN_HAVE_TDC_LOCK_TABLE_SHARE
1860 mrn_LOCK_open = &LOCK_open;
1861 # endif
1862 #endif
1863
1864 #ifdef MRN_HAVE_PSI_SERVER
1865 if (PSI_server) {
1866 const char *category = "mroonga";
1867 int n_mutexes = array_elements(mrn_mutexes);
1868 PSI_server->register_mutex(category, mrn_mutexes, n_mutexes);
1869 }
1870 #endif
1871
1872 grn_default_query_logger_set_path(mrn_query_log_file_path);
1873
1874 if (grn_init() != GRN_SUCCESS) {
1875 goto err_grn_init;
1876 }
1877
1878 grn_set_lock_timeout(mrn_lock_timeout);
1879
1880 mrn_init_encoding_map();
1881
1882 grn_ctx_init(&mrn_ctx, 0);
1883 ctx = &mrn_ctx;
1884 if (mrn_change_encoding(ctx, system_charset_info))
1885 goto err_mrn_change_encoding;
1886
1887 #ifdef MRN_HAVE_PSI_MEMORY_KEY
1888 {
1889 const char *category = "ha_mroonga";
1890 int n_keys = array_elements(mrn_all_memory_keys);
1891 mysql_memory_register(category, mrn_all_memory_keys, n_keys);
1892 }
1893 #endif
1894
1895 if (mysql_mutex_init(mrn_log_mutex_key,
1896 &mrn_log_mutex,
1897 MY_MUTEX_INIT_FAST) != 0) {
1898 goto err_log_mutex_init;
1899 }
1900 if (mysql_mutex_init(mrn_query_log_mutex_key,
1901 &mrn_query_log_mutex,
1902 MY_MUTEX_INIT_FAST) != 0) {
1903 goto err_query_log_mutex_init;
1904 }
1905
1906 mrn_logger.max_level = static_cast<grn_log_level>(mrn_log_level);
1907 grn_logger_set(ctx, &mrn_logger);
1908 if (!(mrn_log_file = fopen(mrn_log_file_path, "a"))) {
1909 goto err_log_file_open;
1910 }
1911 mrn_log_file_opened = true;
1912 GRN_LOG(ctx, GRN_LOG_NOTICE, "%s started.", MRN_PACKAGE_STRING);
1913 GRN_LOG(ctx, GRN_LOG_NOTICE, "log level is '%s'",
1914 mrn_log_level_type_names[mrn_log_level]);
1915
1916 // init meta-info database
1917 if (!(mrn_db = grn_db_create(ctx, NULL, NULL))) {
1918 GRN_LOG(ctx, GRN_LOG_ERROR, "cannot create system database, exiting");
1919 goto err_db_create;
1920 }
1921 grn_ctx_use(ctx, mrn_db);
1922
1923 grn_ctx_init(&mrn_db_manager_ctx, 0);
1924 grn_logger_set(&mrn_db_manager_ctx, &mrn_logger);
1925 if (mysql_mutex_init(mrn_db_manager_mutex_key,
1926 &mrn_db_manager_mutex,
1927 MY_MUTEX_INIT_FAST) != 0) {
1928 GRN_LOG(&mrn_db_manager_ctx, GRN_LOG_ERROR,
1929 "failed to initialize mutex for database manager");
1930 goto err_db_manager_mutex_init;
1931 }
1932 mrn_db_manager = new mrn::DatabaseManager(&mrn_db_manager_ctx,
1933 &mrn_db_manager_mutex);
1934 if (!mrn_db_manager->init()) {
1935 goto err_db_manager_init;
1936 }
1937
1938 if (mysql_mutex_init(mrn_context_pool_mutex_key,
1939 &mrn_context_pool_mutex,
1940 MY_MUTEX_INIT_FAST) != 0) {
1941 GRN_LOG(ctx, GRN_LOG_ERROR,
1942 "failed to initialize mutex for context pool");
1943 goto error_context_pool_mutex_init;
1944 }
1945 mrn_context_pool = new mrn::ContextPool(&mrn_context_pool_mutex);
1946
1947 if (mysql_mutex_init(mrn_operations_mutex_key,
1948 &mrn_operations_mutex,
1949 MY_MUTEX_INIT_FAST) != 0) {
1950 GRN_LOG(ctx, GRN_LOG_ERROR,
1951 "failed to initialize mutex for operations");
1952 goto error_operations_mutex_init;
1953 }
1954
1955 if ((mysql_mutex_init(mrn_allocated_thds_mutex_key,
1956 &mrn_allocated_thds_mutex,
1957 MY_MUTEX_INIT_FAST) != 0)) {
1958 goto err_allocated_thds_mutex_init;
1959 }
1960 if (mrn_my_hash_init(&mrn_allocated_thds, system_charset_info, 32, 0, 0,
1961 mrn_allocated_thds_get_key, 0, 0)) {
1962 goto error_allocated_thds_hash_init;
1963 }
1964 if ((mysql_mutex_init(mrn_open_tables_mutex_key,
1965 &mrn_open_tables_mutex,
1966 MY_MUTEX_INIT_FAST) != 0)) {
1967 goto err_allocated_open_tables_mutex_init;
1968 }
1969 if (mrn_my_hash_init(&mrn_open_tables, system_charset_info, 32, 0, 0,
1970 mrn_open_tables_get_key, 0, 0)) {
1971 goto error_allocated_open_tables_hash_init;
1972 }
1973 if ((mysql_mutex_init(mrn_long_term_share_mutex_key,
1974 &mrn_long_term_share_mutex,
1975 MY_MUTEX_INIT_FAST) != 0)) {
1976 goto error_allocated_long_term_share_mutex_init;
1977 }
1978 if (mrn_my_hash_init(&mrn_long_term_share, system_charset_info, 32, 0, 0,
1979 mrn_long_term_share_get_key, 0, 0)) {
1980 goto error_allocated_long_term_share_hash_init;
1981 }
1982
1983 #ifdef MRN_USE_MYSQL_DATA_HOME
1984 mrn::PathMapper::default_mysql_data_home_path = mysql_data_home;
1985 #endif
1986
1987 return 0;
1988
1989 error_allocated_long_term_share_hash_init:
1990 mysql_mutex_destroy(&mrn_long_term_share_mutex);
1991 error_allocated_long_term_share_mutex_init:
1992 my_hash_free(&mrn_open_tables);
1993 error_allocated_open_tables_hash_init:
1994 mysql_mutex_destroy(&mrn_open_tables_mutex);
1995 err_allocated_open_tables_mutex_init:
1996 my_hash_free(&mrn_allocated_thds);
1997 error_allocated_thds_hash_init:
1998 mysql_mutex_destroy(&mrn_allocated_thds_mutex);
1999 err_allocated_thds_mutex_init:
2000 mysql_mutex_destroy(&mrn_operations_mutex);
2001 error_operations_mutex_init:
2002 delete mrn_context_pool;
2003 mysql_mutex_destroy(&mrn_context_pool_mutex);
2004 error_context_pool_mutex_init:
2005 err_db_manager_init:
2006 delete mrn_db_manager;
2007 mysql_mutex_destroy(&mrn_db_manager_mutex);
2008 err_db_manager_mutex_init:
2009 grn_ctx_fin(&mrn_db_manager_ctx);
2010 grn_obj_unlink(ctx, mrn_db);
2011 err_db_create:
2012 if (mrn_log_file_opened) {
2013 fclose(mrn_log_file);
2014 mrn_log_file_opened = false;
2015 }
2016 err_log_file_open:
2017 mysql_mutex_destroy(&mrn_query_log_mutex);
2018 err_query_log_mutex_init:
2019 mysql_mutex_destroy(&mrn_log_mutex);
2020 err_log_mutex_init:
2021 err_mrn_change_encoding:
2022 grn_ctx_fin(ctx);
2023 grn_fin();
2024 err_grn_init:
2025 return -1;
2026 }
2027
mrn_deinit(void * p)2028 static int mrn_deinit(void *p)
2029 {
2030 THD *thd = current_thd, *tmp_thd;
2031 grn_ctx *ctx = &mrn_ctx;
2032 MRN_LONG_TERM_SHARE *long_term_share;
2033
2034 GRN_LOG(ctx, GRN_LOG_NOTICE, "%s deinit", MRN_PACKAGE_STRING);
2035
2036 if (thd && thd_sql_command(thd) == SQLCOM_UNINSTALL_PLUGIN) {
2037 mrn::Lock lock(&mrn_allocated_thds_mutex);
2038 while ((tmp_thd = (THD *) my_hash_element(&mrn_allocated_thds, 0)))
2039 {
2040 mrn_clear_slot_data(tmp_thd);
2041 void *slot_ptr = mrn_get_slot_data(tmp_thd, false);
2042 if (slot_ptr) free(slot_ptr);
2043 *thd_ha_data(tmp_thd, mrn_hton_ptr) = (void *) NULL;
2044 my_hash_delete(&mrn_allocated_thds, (uchar *) tmp_thd);
2045 }
2046 }
2047
2048 {
2049 mrn::Lock lock(&mrn_open_tables_mutex);
2050 while ((long_term_share = (MRN_LONG_TERM_SHARE *)
2051 my_hash_element(&mrn_long_term_share, 0)))
2052 {
2053 mrn_free_long_term_share(long_term_share);
2054 }
2055 }
2056
2057 my_hash_free(&mrn_long_term_share);
2058 mysql_mutex_destroy(&mrn_long_term_share_mutex);
2059 my_hash_free(&mrn_open_tables);
2060 mysql_mutex_destroy(&mrn_open_tables_mutex);
2061 my_hash_free(&mrn_allocated_thds);
2062 mysql_mutex_destroy(&mrn_allocated_thds_mutex);
2063 mysql_mutex_destroy(&mrn_operations_mutex);
2064 delete mrn_context_pool;
2065 mysql_mutex_destroy(&mrn_context_pool_mutex);
2066 delete mrn_db_manager;
2067 mysql_mutex_destroy(&mrn_db_manager_mutex);
2068 grn_ctx_fin(&mrn_db_manager_ctx);
2069
2070 grn_obj_unlink(ctx, mrn_db);
2071 grn_ctx_fin(ctx);
2072 grn_fin();
2073
2074 if (mrn_log_file_opened) {
2075 fclose(mrn_log_file);
2076 mrn_log_file_opened = false;
2077 }
2078 mysql_mutex_destroy(&mrn_query_log_mutex);
2079 mysql_mutex_destroy(&mrn_log_mutex);
2080
2081 return 0;
2082 }
2083
mrn_declare_plugin(MRN_PLUGIN_NAME)2084 mrn_declare_plugin(MRN_PLUGIN_NAME)
2085 {
2086 MYSQL_STORAGE_ENGINE_PLUGIN,
2087 &storage_engine_structure,
2088 MRN_PLUGIN_NAME_STRING,
2089 MRN_PLUGIN_AUTHOR,
2090 "CJK-ready fulltext search, column store",
2091 PLUGIN_LICENSE_GPL,
2092 mrn_init,
2093 mrn_deinit,
2094 MRN_VERSION_IN_HEX,
2095 mrn_status_variables,
2096 mrn_system_variables,
2097 MRN_PLUGIN_LAST_VALUES
2098 },
2099 i_s_mrn_stats
2100 mrn_declare_plugin_end;
2101
mrn_get_score_value(grn_obj * score)2102 static double mrn_get_score_value(grn_obj *score)
2103 {
2104 MRN_DBUG_ENTER_FUNCTION();
2105 double score_value;
2106 if (score->header.domain == GRN_DB_FLOAT) {
2107 score_value = GRN_FLOAT_VALUE(score);
2108 } else {
2109 score_value = (double)GRN_INT32_VALUE(score);
2110 }
2111 DBUG_RETURN(score_value);
2112 }
2113
mrn_generic_ft_clear(FT_INFO * handler)2114 static void mrn_generic_ft_clear(FT_INFO *handler)
2115 {
2116 MRN_DBUG_ENTER_FUNCTION();
2117 st_mrn_ft_info *info = (st_mrn_ft_info *)handler;
2118 if (!info->ctx) {
2119 DBUG_VOID_RETURN;
2120 }
2121
2122 if (info->cursor) {
2123 grn_obj_unlink(info->ctx, info->cursor);
2124 }
2125 if (info->id_accessor) {
2126 grn_obj_unlink(info->ctx, info->id_accessor);
2127 }
2128 if (info->key_accessor) {
2129 grn_obj_unlink(info->ctx, info->key_accessor);
2130 }
2131 grn_obj_unlink(info->ctx, info->result);
2132 grn_obj_unlink(info->ctx, info->score_column);
2133 grn_obj_unlink(info->ctx, &(info->key));
2134 grn_obj_unlink(info->ctx, &(info->score));
2135
2136 info->ctx = NULL;
2137
2138 DBUG_VOID_RETURN;
2139 }
2140
mrn_generic_ft_close_search(FT_INFO * handler)2141 static void mrn_generic_ft_close_search(FT_INFO *handler)
2142 {
2143 MRN_DBUG_ENTER_FUNCTION();
2144 st_mrn_ft_info *info = (st_mrn_ft_info *)handler;
2145 mrn_generic_ft_clear(handler);
2146 delete info;
2147 DBUG_VOID_RETURN;
2148 }
2149
mrn_wrapper_ft_read_next(FT_INFO * handler,char * record)2150 static int mrn_wrapper_ft_read_next(FT_INFO *handler, char *record)
2151 {
2152 MRN_DBUG_ENTER_FUNCTION();
2153 DBUG_RETURN(HA_ERR_END_OF_FILE);
2154 }
2155
mrn_wrapper_ft_find_relevance(FT_INFO * handler,uchar * record,uint length)2156 static float mrn_wrapper_ft_find_relevance(FT_INFO *handler, uchar *record,
2157 uint length)
2158 {
2159 MRN_DBUG_ENTER_FUNCTION();
2160 st_mrn_ft_info *info = (st_mrn_ft_info *)handler;
2161 float score = 0.0;
2162 grn_id record_id;
2163
2164 mrn_change_encoding(info->ctx, NULL);
2165 key_copy((uchar *)(GRN_TEXT_VALUE(&(info->key))), record,
2166 info->primary_key_info, info->primary_key_info->key_length);
2167 record_id = grn_table_get(info->ctx,
2168 info->table,
2169 GRN_TEXT_VALUE(&(info->key)),
2170 GRN_TEXT_LEN(&(info->key)));
2171
2172 if (record_id != GRN_ID_NIL) {
2173 grn_id result_record_id;
2174 result_record_id = grn_table_get(info->ctx, info->result,
2175 &record_id, sizeof(grn_id));
2176 if (result_record_id != GRN_ID_NIL) {
2177 GRN_BULK_REWIND(&(info->score));
2178 grn_obj_get_value(info->ctx, info->score_column,
2179 result_record_id, &(info->score));
2180 score = mrn_get_score_value(&(info->score));
2181 }
2182 }
2183
2184 DBUG_PRINT("info",
2185 ("mroonga: record_id=%d score=%g", record_id, score));
2186
2187 DBUG_RETURN(score);
2188 }
2189
mrn_wrapper_ft_close_search(FT_INFO * handler)2190 static void mrn_wrapper_ft_close_search(FT_INFO *handler)
2191 {
2192 MRN_DBUG_ENTER_FUNCTION();
2193 mrn_generic_ft_close_search(handler);
2194 DBUG_VOID_RETURN;
2195 }
2196
mrn_wrapper_ft_get_relevance(FT_INFO * handler)2197 static float mrn_wrapper_ft_get_relevance(FT_INFO *handler)
2198 {
2199 MRN_DBUG_ENTER_FUNCTION();
2200 st_mrn_ft_info *info = (st_mrn_ft_info *)handler;
2201 float score = 0.0;
2202 grn_id record_id;
2203 ha_mroonga *mroonga = info->mroonga;
2204 mrn_change_encoding(info->ctx, NULL);
2205 record_id = grn_table_get(info->ctx,
2206 info->table,
2207 GRN_TEXT_VALUE(&(mroonga->key_buffer)),
2208 GRN_TEXT_LEN(&(mroonga->key_buffer)));
2209
2210 if (record_id != GRN_ID_NIL) {
2211 grn_id result_record_id;
2212 result_record_id = grn_table_get(info->ctx, info->result,
2213 &record_id, sizeof(grn_id));
2214 if (result_record_id != GRN_ID_NIL) {
2215 GRN_BULK_REWIND(&(info->score));
2216 grn_obj_get_value(info->ctx, info->score_column,
2217 result_record_id, &(info->score));
2218 score = mrn_get_score_value(&(info->score));
2219 }
2220 }
2221
2222 DBUG_PRINT("info",
2223 ("mroonga: record_id=%d score=%g", record_id, score));
2224
2225 DBUG_RETURN(score);
2226 }
2227
mrn_wrapper_ft_reinit_search(FT_INFO * handler)2228 static void mrn_wrapper_ft_reinit_search(FT_INFO *handler)
2229 {
2230 MRN_DBUG_ENTER_FUNCTION();
2231 DBUG_VOID_RETURN;
2232 }
2233
2234 static _ft_vft mrn_wrapper_ft_vft = {
2235 mrn_wrapper_ft_read_next,
2236 mrn_wrapper_ft_find_relevance,
2237 mrn_wrapper_ft_close_search,
2238 mrn_wrapper_ft_get_relevance,
2239 mrn_wrapper_ft_reinit_search
2240 };
2241
mrn_storage_ft_read_next(FT_INFO * handler,char * record)2242 static int mrn_storage_ft_read_next(FT_INFO *handler, char *record)
2243 {
2244 MRN_DBUG_ENTER_FUNCTION();
2245 DBUG_RETURN(HA_ERR_END_OF_FILE);
2246 }
2247
mrn_storage_ft_find_relevance(FT_INFO * handler,uchar * record,uint length)2248 static float mrn_storage_ft_find_relevance(FT_INFO *handler, uchar *record,
2249 uint length)
2250 {
2251 MRN_DBUG_ENTER_FUNCTION();
2252 st_mrn_ft_info *info = (st_mrn_ft_info *)handler;
2253 ha_mroonga *mroonga = info->mroonga;
2254 mrn_change_encoding(info->ctx, NULL);
2255
2256 float score = 0.0;
2257 if (mroonga->record_id != GRN_ID_NIL) {
2258 grn_id result_record_id;
2259 result_record_id = grn_table_get(info->ctx, info->result,
2260 &(mroonga->record_id), sizeof(grn_id));
2261 if (result_record_id != GRN_ID_NIL) {
2262 GRN_BULK_REWIND(&(info->score));
2263 grn_obj_get_value(info->ctx, info->score_column,
2264 result_record_id, &(info->score));
2265 score = mrn_get_score_value(&(info->score));
2266 }
2267 }
2268 DBUG_PRINT("info", ("mroonga: record_id=%d score=%g",
2269 mroonga->record_id, score));
2270
2271 DBUG_RETURN(score);
2272 }
2273
mrn_storage_ft_close_search(FT_INFO * handler)2274 static void mrn_storage_ft_close_search(FT_INFO *handler)
2275 {
2276 MRN_DBUG_ENTER_FUNCTION();
2277 mrn_generic_ft_close_search(handler);
2278 DBUG_VOID_RETURN;
2279 }
2280
mrn_storage_ft_get_relevance(FT_INFO * handler)2281 static float mrn_storage_ft_get_relevance(FT_INFO *handler)
2282 {
2283 MRN_DBUG_ENTER_FUNCTION();
2284 st_mrn_ft_info *info = (st_mrn_ft_info *)handler;
2285 ha_mroonga *mroonga = info->mroonga;
2286 mrn_change_encoding(info->ctx, NULL);
2287
2288 float score = 0.0;
2289 if (mroonga->record_id != GRN_ID_NIL) {
2290 grn_id result_record_id;
2291 result_record_id = grn_table_get(info->ctx, info->result,
2292 &(mroonga->record_id), sizeof(grn_id));
2293 if (result_record_id != GRN_ID_NIL) {
2294 GRN_BULK_REWIND(&(info->score));
2295 grn_obj_get_value(info->ctx, info->score_column,
2296 result_record_id, &(info->score));
2297 score = mrn_get_score_value(&(info->score));
2298 }
2299 }
2300 DBUG_PRINT("info",
2301 ("mroonga: record_id=%d score=%g", mroonga->record_id, score));
2302
2303 DBUG_RETURN(score);
2304 }
2305
mrn_storage_ft_reinit_search(FT_INFO * handler)2306 static void mrn_storage_ft_reinit_search(FT_INFO *handler)
2307 {
2308 MRN_DBUG_ENTER_FUNCTION();
2309 DBUG_VOID_RETURN;
2310 }
2311
2312 static _ft_vft mrn_storage_ft_vft = {
2313 mrn_storage_ft_read_next,
2314 mrn_storage_ft_find_relevance,
2315 mrn_storage_ft_close_search,
2316 mrn_storage_ft_get_relevance,
2317 mrn_storage_ft_reinit_search
2318 };
2319
mrn_no_such_key_ft_read_next(FT_INFO * handler,char * record)2320 static int mrn_no_such_key_ft_read_next(FT_INFO *handler, char *record)
2321 {
2322 MRN_DBUG_ENTER_FUNCTION();
2323 DBUG_RETURN(HA_ERR_END_OF_FILE);
2324 }
2325
mrn_no_such_key_ft_find_relevance(FT_INFO * handler,uchar * record,uint length)2326 static float mrn_no_such_key_ft_find_relevance(FT_INFO *handler, uchar *record,
2327 uint length)
2328 {
2329 MRN_DBUG_ENTER_FUNCTION();
2330 DBUG_RETURN(0.0);
2331 }
2332
mrn_no_such_key_ft_close_search(FT_INFO * handler)2333 static void mrn_no_such_key_ft_close_search(FT_INFO *handler)
2334 {
2335 MRN_DBUG_ENTER_FUNCTION();
2336 st_mrn_ft_info *info = (st_mrn_ft_info *)handler;
2337 delete info;
2338 DBUG_VOID_RETURN;
2339 }
2340
mrn_no_such_key_ft_get_relevance(FT_INFO * handler)2341 static float mrn_no_such_key_ft_get_relevance(FT_INFO *handler)
2342 {
2343 MRN_DBUG_ENTER_FUNCTION();
2344 DBUG_RETURN(0.0);
2345 }
2346
mrn_no_such_key_ft_reinit_search(FT_INFO * handler)2347 static void mrn_no_such_key_ft_reinit_search(FT_INFO *handler)
2348 {
2349 MRN_DBUG_ENTER_FUNCTION();
2350 DBUG_VOID_RETURN;
2351 }
2352
2353 static _ft_vft mrn_no_such_key_ft_vft = {
2354 mrn_no_such_key_ft_read_next,
2355 mrn_no_such_key_ft_find_relevance,
2356 mrn_no_such_key_ft_close_search,
2357 mrn_no_such_key_ft_get_relevance,
2358 mrn_no_such_key_ft_reinit_search
2359 };
2360
2361 #ifdef HA_CAN_FULLTEXT_EXT
mrn_generic_ft_get_version()2362 static uint mrn_generic_ft_get_version()
2363 {
2364 MRN_DBUG_ENTER_FUNCTION();
2365 // This value is not used in MySQL 5.6.7-rc. So it is
2366 // meaningless. It may be used in the future...
2367 uint version = 1;
2368 DBUG_RETURN(version);
2369 }
2370
mrn_generic_ft_ext_get_flags()2371 static ulonglong mrn_generic_ft_ext_get_flags()
2372 {
2373 MRN_DBUG_ENTER_FUNCTION();
2374 // TODO: Should we support FTS_ORDERED_RESULT?
2375 // TODO: Shuold we support FTS_DOCID_IN_RESULT?
2376 ulonglong flags = 0;
2377 DBUG_RETURN(flags);
2378 }
2379
2380 // This function is used if we enable FTS_DOCID_IN_RESULT flag and the
2381 // table has "FTS_DOC_ID" (defined as FTS_DOC_ID_COL_NAME macro)
2382 // special name column. Should we support "FTS_DOC_ID" special name
2383 // column?
2384 // See also sql/sql_optimizer.cc:JOIN::optimize_fts_query().
mrn_generic_ft_ext_get_docid(FT_INFO_EXT * handler)2385 static ulonglong mrn_generic_ft_ext_get_docid(FT_INFO_EXT *handler)
2386 {
2387 MRN_DBUG_ENTER_FUNCTION();
2388 ulonglong id = GRN_ID_NIL;
2389 DBUG_RETURN(id);
2390 }
2391
mrn_generic_ft_ext_count_matches(FT_INFO_EXT * handler)2392 static ulonglong mrn_generic_ft_ext_count_matches(FT_INFO_EXT *handler)
2393 {
2394 MRN_DBUG_ENTER_FUNCTION();
2395 st_mrn_ft_info *info = reinterpret_cast<st_mrn_ft_info *>(handler);
2396 ulonglong n_records = grn_table_size(info->ctx, info->result);
2397 DBUG_RETURN(n_records);
2398 }
2399
mrn_wrapper_ft_ext_get_version()2400 static uint mrn_wrapper_ft_ext_get_version()
2401 {
2402 MRN_DBUG_ENTER_FUNCTION();
2403 uint version = mrn_generic_ft_get_version();
2404 DBUG_RETURN(version);
2405 }
2406
mrn_wrapper_ft_ext_get_flags()2407 static ulonglong mrn_wrapper_ft_ext_get_flags()
2408 {
2409 MRN_DBUG_ENTER_FUNCTION();
2410 ulonglong flags = mrn_generic_ft_ext_get_flags();
2411 DBUG_RETURN(flags);
2412 }
2413
mrn_wrapper_ft_ext_get_docid(FT_INFO_EXT * handler)2414 static ulonglong mrn_wrapper_ft_ext_get_docid(FT_INFO_EXT *handler)
2415 {
2416 MRN_DBUG_ENTER_FUNCTION();
2417 ulonglong id = mrn_generic_ft_ext_get_docid(handler);
2418 DBUG_RETURN(id);
2419 }
2420
mrn_wrapper_ft_ext_count_matches(FT_INFO_EXT * handler)2421 static ulonglong mrn_wrapper_ft_ext_count_matches(FT_INFO_EXT *handler)
2422 {
2423 MRN_DBUG_ENTER_FUNCTION();
2424 ulonglong n_records = mrn_generic_ft_ext_count_matches(handler);
2425 DBUG_RETURN(n_records);
2426 }
2427
2428 static _ft_vft_ext mrn_wrapper_ft_vft_ext = {
2429 mrn_wrapper_ft_ext_get_version,
2430 mrn_wrapper_ft_ext_get_flags,
2431 mrn_wrapper_ft_ext_get_docid,
2432 mrn_wrapper_ft_ext_count_matches
2433 };
2434
mrn_storage_ft_ext_get_version()2435 static uint mrn_storage_ft_ext_get_version()
2436 {
2437 MRN_DBUG_ENTER_FUNCTION();
2438 uint version = mrn_generic_ft_get_version();
2439 DBUG_RETURN(version);
2440 }
2441
mrn_storage_ft_ext_get_flags()2442 static ulonglong mrn_storage_ft_ext_get_flags()
2443 {
2444 MRN_DBUG_ENTER_FUNCTION();
2445 ulonglong flags = mrn_generic_ft_ext_get_flags();
2446 DBUG_RETURN(flags);
2447 }
2448
mrn_storage_ft_ext_get_docid(FT_INFO_EXT * handler)2449 static ulonglong mrn_storage_ft_ext_get_docid(FT_INFO_EXT *handler)
2450 {
2451 MRN_DBUG_ENTER_FUNCTION();
2452 ulonglong id = mrn_generic_ft_ext_get_docid(handler);
2453 DBUG_RETURN(id);
2454 }
2455
mrn_storage_ft_ext_count_matches(FT_INFO_EXT * handler)2456 static ulonglong mrn_storage_ft_ext_count_matches(FT_INFO_EXT *handler)
2457 {
2458 MRN_DBUG_ENTER_FUNCTION();
2459 ulonglong n_records = mrn_generic_ft_ext_count_matches(handler);
2460 DBUG_RETURN(n_records);
2461 }
2462
2463 static _ft_vft_ext mrn_storage_ft_vft_ext = {
2464 mrn_storage_ft_ext_get_version,
2465 mrn_storage_ft_ext_get_flags,
2466 mrn_storage_ft_ext_get_docid,
2467 mrn_storage_ft_ext_count_matches
2468 };
2469
mrn_no_such_key_ft_ext_get_version()2470 static uint mrn_no_such_key_ft_ext_get_version()
2471 {
2472 MRN_DBUG_ENTER_FUNCTION();
2473 uint version = mrn_generic_ft_get_version();
2474 DBUG_RETURN(version);
2475 }
2476
mrn_no_such_key_ft_ext_get_flags()2477 static ulonglong mrn_no_such_key_ft_ext_get_flags()
2478 {
2479 MRN_DBUG_ENTER_FUNCTION();
2480 ulonglong flags = mrn_generic_ft_ext_get_flags();
2481 DBUG_RETURN(flags);
2482 }
2483
mrn_no_such_key_ft_ext_get_docid(FT_INFO_EXT * handler)2484 static ulonglong mrn_no_such_key_ft_ext_get_docid(FT_INFO_EXT *handler)
2485 {
2486 MRN_DBUG_ENTER_FUNCTION();
2487 ulonglong id = GRN_ID_NIL;
2488 DBUG_RETURN(id);
2489 }
2490
mrn_no_such_key_ft_ext_count_matches(FT_INFO_EXT * handler)2491 static ulonglong mrn_no_such_key_ft_ext_count_matches(FT_INFO_EXT *handler)
2492 {
2493 MRN_DBUG_ENTER_FUNCTION();
2494 ulonglong n_records = 0;
2495 DBUG_RETURN(n_records);
2496 }
2497
2498 static _ft_vft_ext mrn_no_such_key_ft_vft_ext = {
2499 mrn_no_such_key_ft_ext_get_version,
2500 mrn_no_such_key_ft_ext_get_flags,
2501 mrn_no_such_key_ft_ext_get_docid,
2502 mrn_no_such_key_ft_ext_count_matches
2503 };
2504 #endif
2505
2506 /* handler implementation */
ha_mroonga(handlerton * hton,TABLE_SHARE * share_arg)2507 ha_mroonga::ha_mroonga(handlerton *hton, TABLE_SHARE *share_arg)
2508 :handler(hton, share_arg),
2509 wrap_handler(NULL),
2510 is_clone(false),
2511 parent_for_clone(NULL),
2512 mem_root_for_clone(NULL),
2513 record_id(GRN_ID_NIL),
2514 key_id(NULL),
2515 del_key_id(NULL),
2516
2517 wrap_ft_init_count(0),
2518 share(NULL),
2519 wrap_key_info(NULL),
2520 base_key_info(NULL),
2521
2522 analyzed_for_create(false),
2523 wrap_handler_for_create(NULL),
2524 #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
2525 hnd_add_index(NULL),
2526 #endif
2527 #ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER
2528 alter_key_info_buffer(NULL),
2529 #else
2530 wrap_alter_key_info(NULL),
2531 #endif
2532 mrn_lock_type(F_UNLCK),
2533
2534 ctx_entity_(),
2535 ctx(&ctx_entity_),
2536 grn_table(NULL),
2537 grn_columns(NULL),
2538 grn_column_ranges(NULL),
2539 grn_index_tables(NULL),
2540 grn_index_columns(NULL),
2541
2542 grn_source_column_geo(NULL),
2543 cursor_geo(NULL),
2544 cursor(NULL),
2545 index_table_cursor(NULL),
2546 empty_value_records(NULL),
2547 empty_value_records_cursor(NULL),
2548
2549 sorted_result(NULL),
2550 matched_record_keys(NULL),
2551 blob_buffers(NULL),
2552
2553 dup_key(0),
2554
2555 count_skip(false),
2556 fast_order_limit(false),
2557 fast_order_limit_with_index(false),
2558
2559 ignoring_duplicated_key(false),
2560 inserting_with_update(false),
2561 fulltext_searching(false),
2562 ignoring_no_key_columns(false),
2563 replacing_(false),
2564 written_by_row_based_binlog(0),
2565 current_ft_item(NULL),
2566 operations_(NULL)
2567 {
2568 MRN_DBUG_ENTER_METHOD();
2569 grn_ctx_init(ctx, 0);
2570 mrn_change_encoding(ctx, system_charset_info);
2571 grn_ctx_use(ctx, mrn_db);
2572 GRN_WGS84_GEO_POINT_INIT(&top_left_point, 0);
2573 GRN_WGS84_GEO_POINT_INIT(&bottom_right_point, 0);
2574 GRN_WGS84_GEO_POINT_INIT(&source_point, 0);
2575 GRN_TEXT_INIT(&key_buffer, 0);
2576 GRN_TEXT_INIT(&encoded_key_buffer, 0);
2577 GRN_VOID_INIT(&old_value_buffer);
2578 GRN_VOID_INIT(&new_value_buffer);
2579 DBUG_VOID_RETURN;
2580 }
2581
~ha_mroonga()2582 ha_mroonga::~ha_mroonga()
2583 {
2584 MRN_DBUG_ENTER_METHOD();
2585
2586 delete operations_;
2587
2588 if (analyzed_for_create) {
2589 if (wrap_handler_for_create) {
2590 delete wrap_handler_for_create;
2591 }
2592 if (share_for_create.wrapper_mode) {
2593 plugin_unlock(NULL, share_for_create.plugin);
2594 }
2595 if (share_for_create.table_name) {
2596 my_free(share_for_create.table_name);
2597 }
2598 mrn_free_share_alloc(&share_for_create);
2599 free_root(&mem_root_for_create, MYF(0));
2600 }
2601 if (blob_buffers)
2602 {
2603 delete [] blob_buffers;
2604 }
2605 grn_obj_unlink(ctx, &top_left_point);
2606 grn_obj_unlink(ctx, &bottom_right_point);
2607 grn_obj_unlink(ctx, &source_point);
2608 grn_obj_unlink(ctx, &key_buffer);
2609 grn_obj_unlink(ctx, &encoded_key_buffer);
2610 grn_obj_unlink(ctx, &old_value_buffer);
2611 grn_obj_unlink(ctx, &new_value_buffer);
2612 grn_ctx_fin(ctx);
2613 DBUG_VOID_RETURN;
2614 }
2615
table_type() const2616 const char *ha_mroonga::table_type() const
2617 {
2618 MRN_DBUG_ENTER_METHOD();
2619 DBUG_RETURN(MRN_PLUGIN_NAME_STRING);
2620 }
2621
index_type(uint key_nr)2622 const char *ha_mroonga::index_type(uint key_nr)
2623 {
2624 MRN_DBUG_ENTER_METHOD();
2625 KEY *key_info = &(table->s->key_info[key_nr]);
2626 if (key_info->algorithm == HA_KEY_ALG_FULLTEXT) {
2627 DBUG_RETURN("FULLTEXT");
2628 } else if (key_info->algorithm == HA_KEY_ALG_HASH) {
2629 DBUG_RETURN("HASH");
2630 } else {
2631 DBUG_RETURN("BTREE");
2632 }
2633 }
2634
2635 static const char *ha_mroonga_exts[] = {
2636 NullS
2637 };
bas_ext() const2638 const char **ha_mroonga::bas_ext() const
2639 {
2640 MRN_DBUG_ENTER_METHOD();
2641 DBUG_RETURN(ha_mroonga_exts);
2642 }
2643
wrapper_max_supported_record_length() const2644 uint ha_mroonga::wrapper_max_supported_record_length() const
2645 {
2646 uint res;
2647 MRN_DBUG_ENTER_METHOD();
2648 if (analyzed_for_create && share_for_create.wrapper_mode) {
2649 res = wrap_handler_for_create->max_supported_record_length();
2650 } else {
2651 MRN_SET_WRAP_SHARE_KEY(share, table->s);
2652 MRN_SET_WRAP_TABLE_KEY(this, table);
2653 res = wrap_handler->max_supported_record_length();
2654 MRN_SET_BASE_SHARE_KEY(share, table->s);
2655 MRN_SET_BASE_TABLE_KEY(this, table);
2656 }
2657 DBUG_RETURN(res);
2658 }
2659
storage_max_supported_record_length() const2660 uint ha_mroonga::storage_max_supported_record_length() const
2661 {
2662 MRN_DBUG_ENTER_METHOD();
2663 DBUG_RETURN(HA_MAX_REC_LENGTH);
2664 }
2665
max_supported_record_length() const2666 uint ha_mroonga::max_supported_record_length() const
2667 {
2668 MRN_DBUG_ENTER_METHOD();
2669
2670 uint res;
2671 if (!share && !analyzed_for_create &&
2672 (
2673 thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE ||
2674 thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX ||
2675 thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE
2676 )
2677 ) {
2678 create_share_for_create();
2679 }
2680 if (analyzed_for_create && share_for_create.wrapper_mode) {
2681 res = wrapper_max_supported_record_length();
2682 } else if (wrap_handler && share && share->wrapper_mode) {
2683 res = wrapper_max_supported_record_length();
2684 } else {
2685 res = storage_max_supported_record_length();
2686 }
2687
2688 DBUG_RETURN(res);
2689 }
2690
wrapper_max_supported_keys() const2691 uint ha_mroonga::wrapper_max_supported_keys() const
2692 {
2693 uint res;
2694 MRN_DBUG_ENTER_METHOD();
2695 if (analyzed_for_create && share_for_create.wrapper_mode) {
2696 res = wrap_handler_for_create->max_supported_keys();
2697 } else {
2698 MRN_SET_WRAP_SHARE_KEY(share, table->s);
2699 MRN_SET_WRAP_TABLE_KEY(this, table);
2700 res = wrap_handler->max_supported_keys();
2701 MRN_SET_BASE_SHARE_KEY(share, table->s);
2702 MRN_SET_BASE_TABLE_KEY(this, table);
2703 }
2704 DBUG_RETURN(res);
2705 }
2706
storage_max_supported_keys() const2707 uint ha_mroonga::storage_max_supported_keys() const
2708 {
2709 MRN_DBUG_ENTER_METHOD();
2710 DBUG_RETURN(HA_MAX_REC_LENGTH);
2711 }
2712
max_supported_keys() const2713 uint ha_mroonga::max_supported_keys() const
2714 {
2715 MRN_DBUG_ENTER_METHOD();
2716
2717 uint res;
2718 if (!share && !analyzed_for_create &&
2719 (
2720 thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE ||
2721 thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX ||
2722 thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE
2723 )
2724 ) {
2725 create_share_for_create();
2726 }
2727 if (analyzed_for_create && share_for_create.wrapper_mode) {
2728 res = wrapper_max_supported_keys();
2729 } else if (wrap_handler && share && share->wrapper_mode) {
2730 res = wrapper_max_supported_keys();
2731 } else {
2732 res = storage_max_supported_keys();
2733 }
2734
2735 DBUG_RETURN(res);
2736 }
2737
wrapper_max_supported_key_length() const2738 uint ha_mroonga::wrapper_max_supported_key_length() const
2739 {
2740 uint res;
2741 MRN_DBUG_ENTER_METHOD();
2742 if (analyzed_for_create && share_for_create.wrapper_mode) {
2743 res = wrap_handler_for_create->max_supported_key_length();
2744 } else {
2745 MRN_SET_WRAP_SHARE_KEY(share, table->s);
2746 MRN_SET_WRAP_TABLE_KEY(this, table);
2747 res = wrap_handler->max_supported_key_length();
2748 MRN_SET_BASE_SHARE_KEY(share, table->s);
2749 MRN_SET_BASE_TABLE_KEY(this, table);
2750 }
2751 DBUG_RETURN(res);
2752 }
2753
storage_max_supported_key_length() const2754 uint ha_mroonga::storage_max_supported_key_length() const
2755 {
2756 MRN_DBUG_ENTER_METHOD();
2757 DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE);
2758 }
2759
max_supported_key_length() const2760 uint ha_mroonga::max_supported_key_length() const
2761 {
2762 MRN_DBUG_ENTER_METHOD();
2763
2764 uint res;
2765 if (!share && !analyzed_for_create &&
2766 (
2767 thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE ||
2768 thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX ||
2769 thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE
2770 )
2771 ) {
2772 create_share_for_create();
2773 }
2774 if (analyzed_for_create && share_for_create.wrapper_mode) {
2775 res = wrapper_max_supported_key_length();
2776 } else if (wrap_handler && share && share->wrapper_mode) {
2777 res = wrapper_max_supported_key_length();
2778 } else {
2779 res = storage_max_supported_key_length();
2780 }
2781
2782 DBUG_RETURN(res);
2783 }
2784
wrapper_max_supported_key_part_length() const2785 uint ha_mroonga::wrapper_max_supported_key_part_length() const
2786 {
2787 uint res;
2788 MRN_DBUG_ENTER_METHOD();
2789 if (analyzed_for_create && share_for_create.wrapper_mode) {
2790 res = wrap_handler_for_create->max_supported_key_part_length();
2791 } else {
2792 MRN_SET_WRAP_SHARE_KEY(share, table->s);
2793 MRN_SET_WRAP_TABLE_KEY(this, table);
2794 res = wrap_handler->max_supported_key_part_length();
2795 MRN_SET_BASE_SHARE_KEY(share, table->s);
2796 MRN_SET_BASE_TABLE_KEY(this, table);
2797 }
2798 DBUG_RETURN(res);
2799 }
2800
storage_max_supported_key_part_length() const2801 uint ha_mroonga::storage_max_supported_key_part_length() const
2802 {
2803 MRN_DBUG_ENTER_METHOD();
2804 DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE);
2805 }
2806
max_supported_key_part_length() const2807 uint ha_mroonga::max_supported_key_part_length() const
2808 {
2809 MRN_DBUG_ENTER_METHOD();
2810
2811 uint res;
2812 if (!share && !analyzed_for_create &&
2813 (
2814 thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE ||
2815 thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX ||
2816 thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE
2817 )
2818 ) {
2819 create_share_for_create();
2820 }
2821 if (analyzed_for_create && share_for_create.wrapper_mode) {
2822 res = wrapper_max_supported_key_part_length();
2823 } else if (wrap_handler && share && share->wrapper_mode) {
2824 res = wrapper_max_supported_key_part_length();
2825 } else {
2826 res = storage_max_supported_key_part_length();
2827 }
2828
2829 DBUG_RETURN(res);
2830 }
2831
wrapper_table_flags() const2832 ulonglong ha_mroonga::wrapper_table_flags() const
2833 {
2834 ulonglong table_flags;
2835 MRN_DBUG_ENTER_METHOD();
2836 if (analyzed_for_create && share_for_create.wrapper_mode) {
2837 table_flags = wrap_handler_for_create->ha_table_flags();
2838 } else {
2839 MRN_SET_WRAP_SHARE_KEY(share, table->s);
2840 MRN_SET_WRAP_TABLE_KEY(this, table);
2841 table_flags = wrap_handler->ha_table_flags();
2842 MRN_SET_BASE_SHARE_KEY(share, table->s);
2843 MRN_SET_BASE_TABLE_KEY(this, table);
2844 }
2845 table_flags |= HA_CAN_FULLTEXT | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE |
2846 HA_CAN_RTREEKEYS | HA_REC_NOT_IN_SEQ;
2847 #ifdef HA_CAN_REPAIR
2848 table_flags |= HA_CAN_REPAIR;
2849 #endif
2850 #ifdef HA_CAN_FULLTEXT_EXT
2851 table_flags |= HA_CAN_FULLTEXT_EXT;
2852 #endif
2853 #ifdef HA_GENERATED_COLUMNS
2854 table_flags |= HA_GENERATED_COLUMNS;
2855 #endif
2856 #ifdef HA_CAN_VIRTUAL_COLUMNS
2857 table_flags |= HA_CAN_VIRTUAL_COLUMNS;
2858 #endif
2859 DBUG_RETURN(table_flags);
2860 }
2861
storage_table_flags() const2862 ulonglong ha_mroonga::storage_table_flags() const
2863 {
2864 MRN_DBUG_ENTER_METHOD();
2865 ulonglong flags =
2866 HA_NO_TRANSACTIONS |
2867 HA_PARTIAL_COLUMN_READ |
2868 HA_REC_NOT_IN_SEQ |
2869 HA_NULL_IN_KEY |
2870 HA_CAN_INDEX_BLOBS |
2871 HA_STATS_RECORDS_IS_EXACT |
2872 HA_CAN_FULLTEXT |
2873 HA_BINLOG_FLAGS |
2874 HA_CAN_BIT_FIELD |
2875 HA_DUPLICATE_POS |
2876 HA_CAN_GEOMETRY |
2877 HA_CAN_RTREEKEYS;
2878 //HA_HAS_RECORDS;
2879 #ifdef HA_MUST_USE_TABLE_CONDITION_PUSHDOWN
2880 flags |= HA_MUST_USE_TABLE_CONDITION_PUSHDOWN;
2881 #endif
2882 #ifdef HA_CAN_REPAIR
2883 flags |= HA_CAN_REPAIR;
2884 #endif
2885 #ifdef HA_CAN_FULLTEXT_EXT
2886 flags |= HA_CAN_FULLTEXT_EXT;
2887 #endif
2888 #ifdef HA_GENERATED_COLUMNS
2889 flags |= HA_GENERATED_COLUMNS;
2890 #endif
2891 #ifdef HA_CAN_VIRTUAL_COLUMNS
2892 flags |= HA_CAN_VIRTUAL_COLUMNS;
2893 #endif
2894 DBUG_RETURN(flags);
2895 }
2896
table_flags() const2897 ulonglong ha_mroonga::table_flags() const
2898 {
2899 MRN_DBUG_ENTER_METHOD();
2900
2901 ulonglong flags;
2902 if (!share && !analyzed_for_create &&
2903 (
2904 thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE ||
2905 thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX ||
2906 thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE
2907 )
2908 ) {
2909 create_share_for_create();
2910 }
2911 if (analyzed_for_create && share_for_create.wrapper_mode) {
2912 flags = wrapper_table_flags();
2913 } else if (wrap_handler && share && share->wrapper_mode) {
2914 flags = wrapper_table_flags();
2915 } else {
2916 flags = storage_table_flags();
2917 }
2918
2919 DBUG_RETURN(flags);
2920 }
2921
wrapper_index_flags(uint idx,uint part,bool all_parts) const2922 ulong ha_mroonga::wrapper_index_flags(uint idx, uint part, bool all_parts) const
2923 {
2924 ulong index_flags;
2925 KEY *key = &(table_share->key_info[idx]);
2926 MRN_DBUG_ENTER_METHOD();
2927 if (key->algorithm == HA_KEY_ALG_BTREE ||
2928 key->algorithm == HA_KEY_ALG_UNDEF) {
2929 MRN_SET_WRAP_SHARE_KEY(share, table->s);
2930 MRN_SET_WRAP_TABLE_KEY(this, table);
2931 index_flags = wrap_handler->index_flags(idx, part, all_parts);
2932 MRN_SET_BASE_SHARE_KEY(share, table->s);
2933 MRN_SET_BASE_TABLE_KEY(this, table);
2934 } else {
2935 index_flags = HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR;
2936 }
2937 DBUG_RETURN(index_flags);
2938 }
2939
storage_index_flags(uint idx,uint part,bool all_parts) const2940 ulong ha_mroonga::storage_index_flags(uint idx, uint part, bool all_parts) const
2941 {
2942 MRN_DBUG_ENTER_METHOD();
2943 ulong flags;
2944 KEY *key = &(table_share->key_info[idx]);
2945 if (key->algorithm == HA_KEY_ALG_BTREE ||
2946 key->algorithm == HA_KEY_ALG_UNDEF) {
2947 flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE;
2948 bool need_normalize_p = false;
2949 // TODO: MariaDB 10.1 passes key->user_defined_key_parts as part
2950 // for ORDER BY DESC. We just it fallback to part = 0. We may use
2951 // it for optimization in the future.
2952 //
2953 // See also: test_if_order_by_key() in sql/sql_select.cc.
2954 if (KEY_N_KEY_PARTS(key) == part) {
2955 part = 0;
2956 }
2957 Field *field = &(key->key_part[part].field[0]);
2958 if (field && (have_custom_normalizer(key) || should_normalize(field))) {
2959 need_normalize_p = true;
2960 }
2961 if (!need_normalize_p) {
2962 flags |= HA_KEYREAD_ONLY;
2963 }
2964 if (KEY_N_KEY_PARTS(key) > 1 || !need_normalize_p) {
2965 flags |= HA_READ_ORDER;
2966 }
2967 } else {
2968 flags = HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR;
2969 }
2970 DBUG_RETURN(flags);
2971 }
2972
index_flags(uint idx,uint part,bool all_parts) const2973 ulong ha_mroonga::index_flags(uint idx, uint part, bool all_parts) const
2974 {
2975 MRN_DBUG_ENTER_METHOD();
2976
2977 KEY *key = &(table_share->key_info[idx]);
2978 if (key->algorithm == HA_KEY_ALG_FULLTEXT) {
2979 DBUG_RETURN(HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR);
2980 }
2981 if (mrn_is_geo_key(key)) {
2982 DBUG_RETURN(HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR | HA_READ_RANGE);
2983 }
2984
2985 int error = 0;
2986 if (wrap_handler && share && share->wrapper_mode)
2987 {
2988 error = wrapper_index_flags(idx, part, all_parts);
2989 } else {
2990 error = storage_index_flags(idx, part, all_parts);
2991 }
2992 DBUG_RETURN(error);
2993 }
2994
create_share_for_create() const2995 int ha_mroonga::create_share_for_create() const
2996 {
2997 int error;
2998 THD *thd = ha_thd();
2999 LEX *lex = thd->lex;
3000 HA_CREATE_INFO *create_info = &lex->create_info;
3001 TABLE_LIST *table_list = MRN_LEX_GET_TABLE_LIST(lex);
3002 MRN_DBUG_ENTER_METHOD();
3003 wrap_handler_for_create = NULL;
3004 table_for_create.reset();
3005 table_share_for_create.reset();
3006 memset(&share_for_create, 0, sizeof(MRN_SHARE));
3007 if (table_share) {
3008 table_share_for_create.comment = table_share->comment;
3009 table_share_for_create.connect_string = table_share->connect_string;
3010 } else {
3011 #ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER
3012 if (thd_sql_command(ha_thd()) != SQLCOM_CREATE_INDEX) {
3013 #endif
3014 table_share_for_create.comment = create_info->comment;
3015 table_share_for_create.connect_string = create_info->connect_string;
3016 #ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER
3017 }
3018 #endif
3019 if (thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE ||
3020 thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX) {
3021 st_mrn_slot_data *slot_data = mrn_get_slot_data(thd, false);
3022 if (slot_data && slot_data->alter_create_info) {
3023 create_info = slot_data->alter_create_info;
3024 if (slot_data->alter_connect_string) {
3025 table_share_for_create.connect_string.str =
3026 slot_data->alter_connect_string;
3027 table_share_for_create.connect_string.length =
3028 strlen(slot_data->alter_connect_string);
3029 } else {
3030 table_share_for_create.connect_string.str = NULL;
3031 table_share_for_create.connect_string.length = 0;
3032 }
3033 if (slot_data->alter_comment) {
3034 table_share_for_create.comment.str =
3035 slot_data->alter_comment;
3036 table_share_for_create.comment.length =
3037 strlen(slot_data->alter_comment);
3038 } else {
3039 table_share_for_create.comment.str = NULL;
3040 table_share_for_create.comment.length = 0;
3041 }
3042 }
3043 }
3044 }
3045 mrn_init_alloc_root(&mem_root_for_create, 1024, 0, MYF(0));
3046 analyzed_for_create = true;
3047 if (table_list) {
3048 share_for_create.table_name = mrn_my_strndup(table_list->table_name.str,
3049 table_list->table_name.length,
3050 MYF(MY_WME));
3051 share_for_create.table_name_length = table_list->table_name.length;
3052 }
3053 share_for_create.table_share = &table_share_for_create;
3054 table_for_create.s = &table_share_for_create;
3055 #ifdef WITH_PARTITION_STORAGE_ENGINE
3056 table_for_create.part_info = NULL;
3057 #endif
3058 if ((error = mrn_parse_table_param(&share_for_create, &table_for_create)))
3059 goto error;
3060
3061 if (share_for_create.wrapper_mode)
3062 {
3063 wrap_handler_for_create =
3064 share_for_create.hton->create(share_for_create.hton, NULL,
3065 &mem_root_for_create);
3066 if (!wrap_handler_for_create) {
3067 error = HA_ERR_OUT_OF_MEM;
3068 goto error;
3069 }
3070 wrap_handler_for_create->init();
3071 }
3072 DBUG_RETURN(0);
3073
3074 error:
3075 if (share_for_create.wrapper_mode) {
3076 plugin_unlock(NULL, share_for_create.plugin);
3077 }
3078 mrn_free_share_alloc(&share_for_create);
3079 free_root(&mem_root_for_create, MYF(0));
3080 analyzed_for_create = false;
3081 thd->clear_error();
3082 DBUG_RETURN(error);
3083 }
3084
wrapper_create(const char * name,TABLE * table,HA_CREATE_INFO * info,MRN_SHARE * tmp_share)3085 int ha_mroonga::wrapper_create(const char *name, TABLE *table,
3086 HA_CREATE_INFO *info, MRN_SHARE *tmp_share)
3087 {
3088 int error = 0;
3089 handler *hnd;
3090 MRN_DBUG_ENTER_METHOD();
3091
3092 if (table_share->primary_key == MAX_KEY)
3093 {
3094 my_message(ER_REQUIRES_PRIMARY_KEY,
3095 MRN_GET_ERR_MSG(ER_REQUIRES_PRIMARY_KEY), MYF(0));
3096 DBUG_RETURN(ER_REQUIRES_PRIMARY_KEY);
3097 }
3098
3099 error = ensure_database_open(name);
3100 if (error)
3101 DBUG_RETURN(error);
3102
3103 error = wrapper_create_index(name, table, tmp_share);
3104 if (error)
3105 DBUG_RETURN(error);
3106
3107 wrap_key_info = mrn_create_key_info_for_table(tmp_share, table, &error);
3108 if (error)
3109 DBUG_RETURN(error);
3110 base_key_info = table->key_info;
3111
3112 share = tmp_share;
3113 MRN_SET_WRAP_SHARE_KEY(tmp_share, table->s);
3114 MRN_SET_WRAP_TABLE_KEY(this, table);
3115 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
3116 if (parse_engine_table_options(ha_thd(), tmp_share->hton, table->s)) {
3117 MRN_SET_BASE_SHARE_KEY(tmp_share, table->s);
3118 MRN_SET_BASE_TABLE_KEY(this, table);
3119 share = NULL;
3120 if (wrap_key_info)
3121 {
3122 my_free(wrap_key_info);
3123 wrap_key_info = NULL;
3124 }
3125 base_key_info = NULL;
3126 error = MRN_GET_ERROR_NUMBER;
3127 DBUG_RETURN(error);
3128 }
3129 #endif
3130 hnd = get_new_handler(table->s, current_thd->mem_root, tmp_share->hton);
3131 if (!hnd)
3132 {
3133 MRN_SET_BASE_SHARE_KEY(tmp_share, table->s);
3134 MRN_SET_BASE_TABLE_KEY(this, table);
3135 share = NULL;
3136 if (wrap_key_info)
3137 {
3138 my_free(wrap_key_info);
3139 wrap_key_info = NULL;
3140 }
3141 base_key_info = NULL;
3142 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
3143 }
3144 error = hnd->ha_create(name, table, info);
3145 MRN_SET_BASE_SHARE_KEY(tmp_share, table->s);
3146 MRN_SET_BASE_TABLE_KEY(this, table);
3147 share = NULL;
3148 delete hnd;
3149
3150 if (error) {
3151 mrn::PathMapper mapper(name);
3152 generic_delete_table(name, mapper.table_name());
3153 }
3154
3155 if (wrap_key_info)
3156 {
3157 my_free(wrap_key_info);
3158 wrap_key_info = NULL;
3159 }
3160 base_key_info = NULL;
3161 DBUG_RETURN(error);
3162 }
3163
wrapper_create_index_fulltext_validate(KEY * key_info)3164 int ha_mroonga::wrapper_create_index_fulltext_validate(KEY *key_info)
3165 {
3166 MRN_DBUG_ENTER_METHOD();
3167
3168 int error = 0;
3169 uint i;
3170 for (i = 0; i < KEY_N_KEY_PARTS(key_info); i++) {
3171 Field *field = key_info->key_part[i].field;
3172
3173 grn_builtin_type gtype = mrn_grn_type_from_field(ctx, field, true);
3174 if (gtype != GRN_DB_SHORT_TEXT)
3175 {
3176 error = ER_CANT_CREATE_TABLE;
3177 GRN_LOG(ctx, GRN_LOG_ERROR,
3178 "key type must be text: <%d> "
3179 "(TODO: We should show type name not type ID.)",
3180 field->type());
3181 my_message(ER_CANT_CREATE_TABLE,
3182 "key type must be text. (TODO: We should show type name.)",
3183 MYF(0));
3184 DBUG_RETURN(error);
3185 }
3186 }
3187
3188 DBUG_RETURN(error);
3189 }
3190
wrapper_create_index_fulltext(const char * grn_table_name,int i,KEY * key_info,grn_obj ** index_tables,grn_obj ** index_columns,MRN_SHARE * tmp_share)3191 int ha_mroonga::wrapper_create_index_fulltext(const char *grn_table_name,
3192 int i,
3193 KEY *key_info,
3194 grn_obj **index_tables,
3195 grn_obj **index_columns,
3196 MRN_SHARE *tmp_share)
3197 {
3198 MRN_DBUG_ENTER_METHOD();
3199 int error = 0;
3200
3201 error = wrapper_create_index_fulltext_validate(key_info);
3202 if (error) {
3203 DBUG_RETURN(error);
3204 }
3205
3206 error = mrn_change_encoding(ctx, system_charset_info);
3207 if (error)
3208 DBUG_RETURN(error);
3209
3210 grn_obj_flags index_table_flags =
3211 GRN_OBJ_TABLE_PAT_KEY |
3212 GRN_OBJ_PERSISTENT;
3213 grn_obj *index_table;
3214
3215 grn_column_flags index_column_flags = GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT;
3216
3217 if (!find_index_column_flags(key_info, &index_column_flags)) {
3218 index_column_flags |= GRN_OBJ_WITH_POSITION;
3219 if (KEY_N_KEY_PARTS(key_info) > 1) {
3220 index_column_flags |= GRN_OBJ_WITH_SECTION;
3221 }
3222 }
3223
3224 mrn::SmartGrnObj lexicon_key_type(ctx, GRN_DB_SHORT_TEXT);
3225 error = mrn_change_encoding(ctx, key_info->key_part->field->charset());
3226 if (error) {
3227 DBUG_RETURN(error);
3228 }
3229 mrn::IndexTableName index_table_name(grn_table_name, key_info->name.str);
3230 index_table = grn_table_create(ctx,
3231 index_table_name.c_str(),
3232 index_table_name.length(),
3233 NULL,
3234 index_table_flags,
3235 lexicon_key_type.get(),
3236 0);
3237 if (ctx->rc) {
3238 error = ER_CANT_CREATE_TABLE;
3239 my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0));
3240 DBUG_RETURN(error);
3241 }
3242 mrn_change_encoding(ctx, system_charset_info);
3243 index_tables[i] = index_table;
3244
3245 grn_obj *tokenizer = find_tokenizer(key_info, tmp_share, i);
3246 if (tokenizer) {
3247 grn_info_type info_type = GRN_INFO_DEFAULT_TOKENIZER;
3248 grn_obj_set_info(ctx, index_table, info_type, tokenizer);
3249 grn_obj_unlink(ctx, tokenizer);
3250 }
3251
3252 {
3253 grn_obj token_filters;
3254 GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, 0);
3255 if (find_token_filters(key_info, &token_filters)) {
3256 grn_obj_set_info(ctx, index_table,
3257 GRN_INFO_TOKEN_FILTERS, &token_filters);
3258 }
3259 grn_obj_unlink(ctx, &token_filters);
3260 }
3261
3262 if (have_custom_normalizer(key_info) ||
3263 should_normalize(&key_info->key_part->field[0])) {
3264 grn_info_type info_type = GRN_INFO_NORMALIZER;
3265 grn_obj *normalizer = find_normalizer(key_info);
3266 if (normalizer) {
3267 grn_obj_set_info(ctx, index_table, info_type, normalizer);
3268 grn_obj_unlink(ctx, normalizer);
3269 }
3270 }
3271
3272 grn_obj *index_column = grn_column_create(ctx, index_table,
3273 INDEX_COLUMN_NAME,
3274 strlen(INDEX_COLUMN_NAME),
3275 NULL,
3276 index_column_flags,
3277 grn_table);
3278 if (ctx->rc) {
3279 error = ER_CANT_CREATE_TABLE;
3280 my_message(error, ctx->errbuf, MYF(0));
3281 DBUG_RETURN(error);
3282 }
3283 if (index_columns) {
3284 index_columns[i] = index_column;
3285 } else {
3286 grn_obj_unlink(ctx, index_column);
3287 }
3288
3289 DBUG_RETURN(error);
3290 }
3291
wrapper_create_index_geo(const char * grn_table_name,int i,KEY * key_info,grn_obj ** index_tables,grn_obj ** index_columns,MRN_SHARE * tmp_share)3292 int ha_mroonga::wrapper_create_index_geo(const char *grn_table_name,
3293 int i,
3294 KEY *key_info,
3295 grn_obj **index_tables,
3296 grn_obj **index_columns,
3297 MRN_SHARE *tmp_share)
3298 {
3299 MRN_DBUG_ENTER_METHOD();
3300 int error;
3301
3302 error = mrn_change_encoding(ctx, system_charset_info);
3303 if (error)
3304 DBUG_RETURN(error);
3305
3306 mrn::IndexTableName index_table_name(grn_table_name, key_info->name.str);
3307
3308 grn_obj_flags index_table_flags =
3309 GRN_OBJ_TABLE_PAT_KEY |
3310 GRN_OBJ_PERSISTENT;
3311 grn_obj *index_table;
3312
3313 grn_obj_flags index_column_flags =
3314 GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT;
3315
3316 grn_obj *lexicon_key_type = grn_ctx_at(ctx, GRN_DB_WGS84_GEO_POINT);
3317 index_table = grn_table_create(ctx,
3318 index_table_name.c_str(),
3319 index_table_name.length(),
3320 NULL,
3321 index_table_flags, lexicon_key_type, 0);
3322 if (ctx->rc) {
3323 error = ER_CANT_CREATE_TABLE;
3324 my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0));
3325 grn_obj_unlink(ctx, lexicon_key_type);
3326 DBUG_RETURN(error);
3327 }
3328 grn_obj_unlink(ctx, lexicon_key_type);
3329 index_tables[i] = index_table;
3330
3331 grn_obj *index_column = grn_column_create(ctx, index_table,
3332 INDEX_COLUMN_NAME,
3333 strlen(INDEX_COLUMN_NAME),
3334 NULL,
3335 index_column_flags,
3336 grn_table);
3337 if (ctx->rc) {
3338 error = ER_CANT_CREATE_TABLE;
3339 my_message(error, ctx->errbuf, MYF(0));
3340 DBUG_RETURN(error);
3341 }
3342 if (index_columns) {
3343 index_columns[i] = index_column;
3344 } else {
3345 grn_obj_unlink(ctx, index_column);
3346 }
3347
3348 DBUG_RETURN(error);
3349 }
3350
wrapper_create_index(const char * name,TABLE * table,MRN_SHARE * tmp_share)3351 int ha_mroonga::wrapper_create_index(const char *name, TABLE *table,
3352 MRN_SHARE *tmp_share)
3353 {
3354 MRN_DBUG_ENTER_METHOD();
3355
3356 int error = 0;
3357 error = mrn_change_encoding(ctx, system_charset_info);
3358 if (error)
3359 DBUG_RETURN(error);
3360
3361 grn_obj *grn_index_table;
3362 mrn::PathMapper mapper(name);
3363 const char *grn_table_name = mapper.table_name();
3364 char *grn_table_path = NULL; // we don't specify path
3365 grn_obj *pkey_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT);
3366 grn_obj *pkey_value_type = NULL; // we don't use this
3367 grn_obj_flags grn_table_flags = GRN_OBJ_PERSISTENT | GRN_OBJ_TABLE_HASH_KEY;
3368
3369 grn_index_table = grn_table_create(ctx, grn_table_name, strlen(grn_table_name),
3370 grn_table_path, grn_table_flags,
3371 pkey_type, pkey_value_type);
3372 if (ctx->rc) {
3373 error = ER_CANT_CREATE_TABLE;
3374 my_message(error, ctx->errbuf, MYF(0));
3375 DBUG_RETURN(error);
3376 }
3377 if (grn_table) {
3378 grn_obj_unlink(ctx, grn_table);
3379 }
3380 grn_table = grn_index_table;
3381
3382 uint i;
3383 uint n_keys = table->s->keys;
3384 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys);
3385 if (!tmp_share->disable_keys) {
3386 for (i = 0; i < n_keys; i++) {
3387 index_tables[i] = NULL;
3388
3389 KEY *key_info = &(table->s->key_info[i]);
3390 if (key_info->algorithm == HA_KEY_ALG_FULLTEXT) {
3391 error = wrapper_create_index_fulltext(grn_table_name,
3392 i, key_info,
3393 index_tables, NULL, tmp_share);
3394 } else if (mrn_is_geo_key(key_info)) {
3395 error = wrapper_create_index_geo(grn_table_name,
3396 i, key_info,
3397 index_tables, NULL, tmp_share);
3398 }
3399 }
3400 }
3401
3402 if (error) {
3403 for (uint j = 0; j < i; j++) {
3404 if (index_tables[j]) {
3405 grn_obj_remove(ctx, index_tables[j]);
3406 }
3407 }
3408 grn_obj_remove(ctx, grn_table);
3409 grn_table = NULL;
3410 }
3411 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
3412 DBUG_RETURN(error);
3413 }
3414
storage_create(const char * name,TABLE * table,HA_CREATE_INFO * info,MRN_SHARE * tmp_share)3415 int ha_mroonga::storage_create(const char *name, TABLE *table,
3416 HA_CREATE_INFO *info, MRN_SHARE *tmp_share)
3417 {
3418 int error;
3419 MRN_LONG_TERM_SHARE *long_term_share = tmp_share->long_term_share;
3420 MRN_DBUG_ENTER_METHOD();
3421
3422 if (info->auto_increment_value) {
3423 mrn::Lock lock(&long_term_share->auto_inc_mutex);
3424 long_term_share->auto_inc_value = info->auto_increment_value;
3425 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
3426 long_term_share->auto_inc_value));
3427 long_term_share->auto_inc_inited = true;
3428 }
3429
3430 error = storage_create_validate_pseudo_column(table);
3431 if (error)
3432 DBUG_RETURN(error);
3433
3434 error = storage_create_validate_index(table);
3435 if (error)
3436 DBUG_RETURN(error);
3437
3438 error = ensure_database_open(name);
3439 if (error)
3440 DBUG_RETURN(error);
3441
3442 error = mrn_change_encoding(ctx, system_charset_info);
3443 if (error)
3444 DBUG_RETURN(error);
3445
3446 grn_obj_flags table_flags = GRN_OBJ_PERSISTENT;
3447
3448 /* primary key must be handled before creating table */
3449 grn_obj *pkey_type;
3450 uint pkey_nr = table->s->primary_key;
3451 if (pkey_nr != MAX_INDEXES) {
3452 KEY *key_info = &(table->s->key_info[pkey_nr]);
3453 bool is_id;
3454
3455 int key_parts = KEY_N_KEY_PARTS(key_info);
3456 if (key_parts == 1) {
3457 Field *pkey_field = key_info->key_part[0].field;
3458 const char *column_name = pkey_field->field_name.str;
3459 is_id = (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0);
3460
3461 grn_builtin_type gtype = mrn_grn_type_from_field(ctx, pkey_field, false);
3462 pkey_type = grn_ctx_at(ctx, gtype);
3463 } else {
3464 is_id = false;
3465 pkey_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT);
3466 }
3467
3468 // default algorithm is BTREE ==> PAT
3469 if (!is_id && key_info->algorithm == HA_KEY_ALG_HASH) {
3470 table_flags |= GRN_OBJ_TABLE_HASH_KEY;
3471 } else if (!is_id) {
3472 table_flags |= GRN_OBJ_TABLE_PAT_KEY;
3473 } else {
3474 // for _id
3475 table_flags |= GRN_OBJ_TABLE_NO_KEY;
3476 pkey_type = NULL;
3477 }
3478
3479 } else {
3480 // primary key doesn't exists
3481 table_flags |= GRN_OBJ_TABLE_NO_KEY;
3482 pkey_type = NULL;
3483 }
3484
3485 /* create table */
3486 grn_obj *table_obj;
3487 mrn::PathMapper mapper(name);
3488
3489 char *table_path = NULL; // we don't specify path
3490 grn_obj *pkey_value_type = NULL; // we don't use this
3491
3492 table_obj = grn_table_create(ctx,
3493 mapper.table_name(), strlen(mapper.table_name()),
3494 table_path,
3495 table_flags, pkey_type, pkey_value_type);
3496 if (ctx->rc) {
3497 error = ER_CANT_CREATE_TABLE;
3498 my_message(error, ctx->errbuf, MYF(0));
3499 DBUG_RETURN(error);
3500 }
3501
3502 if (table_flags == (GRN_OBJ_PERSISTENT | GRN_OBJ_TABLE_PAT_KEY) ||
3503 table_flags == (GRN_OBJ_PERSISTENT | GRN_OBJ_TABLE_HASH_KEY)) {
3504 KEY *key_info = &(table->s->key_info[pkey_nr]);
3505 int key_parts = KEY_N_KEY_PARTS(key_info);
3506 if (key_parts == 1) {
3507 grn_obj *normalizer = NULL;
3508 if (tmp_share->normalizer) {
3509 normalizer = grn_ctx_get(ctx,
3510 tmp_share->normalizer,
3511 tmp_share->normalizer_length);
3512 } else {
3513 Field *field = &(key_info->key_part->field[0]);
3514 if (should_normalize(field)) {
3515 normalizer = find_normalizer(key_info);
3516 }
3517 }
3518 if (normalizer) {
3519 grn_info_type info_type = GRN_INFO_NORMALIZER;
3520 grn_obj_set_info(ctx, table_obj, info_type, normalizer);
3521 grn_obj_unlink(ctx, normalizer);
3522 }
3523 if (tmp_share->default_tokenizer) {
3524 grn_obj *default_tokenizer =
3525 grn_ctx_get(ctx,
3526 tmp_share->default_tokenizer,
3527 tmp_share->default_tokenizer_length);
3528 if (default_tokenizer) {
3529 grn_info_type info_type = GRN_INFO_DEFAULT_TOKENIZER;
3530 grn_obj_set_info(ctx, table_obj, info_type, default_tokenizer);
3531 grn_obj_unlink(ctx, default_tokenizer);
3532 }
3533 }
3534 if (tmp_share->token_filters) {
3535 grn_obj token_filters;
3536 GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, 0);
3537 if (find_token_filters_fill(&token_filters,
3538 tmp_share->token_filters,
3539 tmp_share->token_filters_length)) {
3540 grn_obj_set_info(ctx, table_obj,
3541 GRN_INFO_TOKEN_FILTERS, &token_filters);
3542 }
3543 grn_obj_unlink(ctx, &token_filters);
3544 }
3545 }
3546 }
3547
3548 /* create columns */
3549 uint n_columns = table->s->fields;
3550 for (uint i = 0; i < n_columns; i++) {
3551 Field *field = table->s->field[i];
3552 mrn::ColumnName column_name(field->field_name);
3553
3554 if (strcmp(MRN_COLUMN_NAME_ID, column_name.mysql_name()) == 0) {
3555 continue;
3556 }
3557
3558 #ifdef MRN_SUPPORT_FOREIGN_KEYS
3559 if (storage_create_foreign_key(table, mapper.table_name(), field, table_obj,
3560 error)) {
3561 continue;
3562 }
3563 if (error) {
3564 grn_obj_remove(ctx, table_obj);
3565 DBUG_RETURN(error);
3566 }
3567 #endif
3568
3569 #ifdef MRN_SUPPORT_GENERATED_COLUMNS
3570 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
3571 continue;
3572 }
3573 #endif
3574
3575 grn_obj_flags col_flags = GRN_OBJ_PERSISTENT;
3576 if (!find_column_flags(field, tmp_share, i, &col_flags)) {
3577 col_flags |= GRN_OBJ_COLUMN_SCALAR;
3578 }
3579
3580 grn_obj *col_type;
3581 {
3582 int column_type_error_code = ER_CANT_CREATE_TABLE;
3583 col_type = find_column_type(field, tmp_share, i, column_type_error_code);
3584 if (!col_type) {
3585 grn_obj_remove(ctx, table_obj);
3586 DBUG_RETURN(column_type_error_code);
3587 }
3588 }
3589 char *col_path = NULL; // we don't specify path
3590
3591 grn_column_create(ctx, table_obj,
3592 column_name.c_str(), column_name.length(),
3593 col_path, col_flags, col_type);
3594 if (ctx->rc) {
3595 error = ER_CANT_CREATE_TABLE;
3596 my_message(error, ctx->errbuf, MYF(0));
3597 grn_obj_remove(ctx, table_obj);
3598 DBUG_RETURN(error);
3599 }
3600 }
3601
3602 error = storage_create_indexes(table, mapper.table_name(), table_obj,
3603 tmp_share);
3604 if (error) {
3605 grn_obj_remove(ctx, table_obj);
3606 table_obj = NULL;
3607 }
3608
3609 if (table_obj) {
3610 grn_obj_unlink(ctx, table_obj);
3611 }
3612
3613 DBUG_RETURN(error);
3614 }
3615
storage_create_validate_pseudo_column(TABLE * table)3616 int ha_mroonga::storage_create_validate_pseudo_column(TABLE *table)
3617 {
3618 int error = 0;
3619 uint i, n_columns;
3620
3621 MRN_DBUG_ENTER_METHOD();
3622 n_columns = table->s->fields;
3623 for (i = 0; i < n_columns; i++) {
3624 Field *field = table->s->field[i];
3625 const char *column_name = field->field_name.str;
3626 if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
3627 switch (field->type()) {
3628 case MYSQL_TYPE_TINY :
3629 case MYSQL_TYPE_SHORT :
3630 case MYSQL_TYPE_INT24 :
3631 case MYSQL_TYPE_LONG :
3632 case MYSQL_TYPE_LONGLONG :
3633 break;
3634 default:
3635 GRN_LOG(ctx, GRN_LOG_ERROR, "_id must be numeric data type");
3636 error = ER_CANT_CREATE_TABLE;
3637 my_message(error, "_id must be numeric data type", MYF(0));
3638 DBUG_RETURN(error);
3639 }
3640 }
3641 }
3642
3643 DBUG_RETURN(error);
3644 }
3645
3646 #ifdef MRN_SUPPORT_FOREIGN_KEYS
storage_create_foreign_key(TABLE * table,const char * grn_table_name,Field * field,grn_obj * table_obj,int & error)3647 bool ha_mroonga::storage_create_foreign_key(TABLE *table,
3648 const char *grn_table_name,
3649 Field *field,
3650 grn_obj *table_obj, int &error)
3651 {
3652 MRN_DBUG_ENTER_METHOD();
3653 LEX *lex = ha_thd()->lex;
3654 Alter_info *alter_info = &lex->alter_info;
3655 List_iterator<Key> key_iterator(alter_info->key_list);
3656 Key *key;
3657 char ref_db_buff[NAME_LEN + 1], ref_table_buff[NAME_LEN + 1];
3658 while ((key = key_iterator++))
3659 {
3660 if (key->type != MRN_KEYTYPE_FOREIGN)
3661 {
3662 continue;
3663 }
3664 if (key->columns.elements > 1)
3665 {
3666 error = ER_CANT_CREATE_TABLE;
3667 my_message(error, "mroonga can't use FOREIGN_KEY with multiple columns",
3668 MYF(0));
3669 DBUG_RETURN(false);
3670 }
3671 List_iterator<Key_part_spec> key_part_col_iterator(key->columns);
3672 Key_part_spec *key_part_col = key_part_col_iterator++;
3673 LEX_CSTRING field_name = key_part_col->field_name;
3674 DBUG_PRINT("info", ("mroonga: field_name=%s", field_name.str));
3675 DBUG_PRINT("info", ("mroonga: field->field_name=%s", field->field_name.str));
3676 if (strcmp(field->field_name.str, field_name.str))
3677 {
3678 continue;
3679 }
3680 Foreign_key *fk = (Foreign_key *) key;
3681 List_iterator<Key_part_spec> key_part_ref_col_iterator(fk->ref_columns);
3682 Key_part_spec *key_part_ref_col = key_part_ref_col_iterator++;
3683 LEX_CSTRING ref_field_name = key_part_ref_col->field_name;
3684 DBUG_PRINT("info", ("mroonga: ref_field_name=%s", ref_field_name.str));
3685 #ifdef MRN_FOREIGN_KEY_USE_CONST_STRING
3686 LEX_CSTRING ref_db_name = fk->ref_db;
3687 #else
3688 LEX_STRING ref_db_name = fk->ref_db;
3689 #endif
3690 DBUG_PRINT("info", ("mroonga: ref_db_name=%s", ref_db_name.str));
3691 if (ref_db_name.str && lower_case_table_names) {
3692 strmake(ref_db_buff, ref_db_name.str, sizeof(ref_db_buff) - 1);
3693 my_casedn_str(system_charset_info, ref_db_buff);
3694 ref_db_name.str = ref_db_buff;
3695 DBUG_PRINT("info", ("mroonga: casedn ref_db_name=%s", ref_db_name.str));
3696 }
3697 #ifdef MRN_FOREIGN_KEY_USE_CONST_STRING
3698 LEX_CSTRING ref_table_name = fk->ref_table;
3699 #else
3700 LEX_STRING ref_table_name = fk->ref_table;
3701 #endif
3702 DBUG_PRINT("info", ("mroonga: ref_table_name=%s", ref_table_name.str));
3703 if (ref_table_name.str && lower_case_table_names) {
3704 strmake(ref_table_buff, ref_table_name.str, sizeof(ref_table_buff) - 1);
3705 my_casedn_str(system_charset_info, ref_table_buff);
3706 ref_table_name.str = ref_table_buff;
3707 DBUG_PRINT("info", ("mroonga: casedn ref_table_name=%s", ref_table_name.str));
3708 }
3709 if (ref_db_name.str && strcmp(table->s->db.str, ref_db_name.str))
3710 {
3711 error = ER_CANT_CREATE_TABLE;
3712 my_message(error,
3713 "mroonga can't use FOREIGN_KEY during different database tables",
3714 MYF(0));
3715 DBUG_RETURN(false);
3716 }
3717
3718 grn_obj *column, *column_ref = NULL, *grn_table_ref = NULL;
3719 char ref_path[FN_REFLEN + 1];
3720 TABLE_LIST table_list;
3721 TABLE_SHARE *tmp_ref_table_share;
3722 build_table_filename(ref_path, sizeof(ref_path) - 1,
3723 table->s->db.str, ref_table_name.str, "", 0);
3724
3725 DBUG_PRINT("info", ("mroonga: ref_path=%s", ref_path));
3726 error = mrn_change_encoding(ctx, system_charset_info);
3727 if (error)
3728 DBUG_RETURN(false);
3729 mrn::PathMapper mapper(ref_path);
3730 grn_table_ref = grn_ctx_get(ctx, mapper.table_name(),
3731 strlen(mapper.table_name()));
3732 if (!grn_table_ref) {
3733 error = ER_CANT_CREATE_TABLE;
3734 char err_msg[MRN_BUFFER_SIZE];
3735 sprintf(err_msg, "reference table [%s.%s] is not mroonga table",
3736 table->s->db.str, ref_table_name.str);
3737 my_message(error, err_msg, MYF(0));
3738 DBUG_RETURN(false);
3739 }
3740
3741 LEX_CSTRING tmp_db_name= { mapper.db_name(), strlen(mapper.db_name()) };
3742 LEX_CSTRING tmp_table_name= { mapper.mysql_table_name(), strlen(mapper.mysql_table_name()) };
3743 table_list.init_one_table(&tmp_db_name, &tmp_table_name, 0, TL_WRITE);
3744 mrn_open_mutex_lock(table->s);
3745 tmp_ref_table_share =
3746 mrn_create_tmp_table_share(&table_list, ref_path, &error);
3747 mrn_open_mutex_unlock(table->s);
3748 if (!tmp_ref_table_share) {
3749 grn_obj_unlink(ctx, grn_table_ref);
3750 error = ER_CANT_CREATE_TABLE;
3751 char err_msg[MRN_BUFFER_SIZE];
3752 sprintf(err_msg, "reference table [%s.%s] is not found",
3753 table->s->db.str, ref_table_name.str);
3754 my_message(error, err_msg, MYF(0));
3755 DBUG_RETURN(false);
3756 }
3757 uint ref_pkey_nr = tmp_ref_table_share->primary_key;
3758 if (ref_pkey_nr == MAX_KEY) {
3759 mrn_open_mutex_lock(table->s);
3760 mrn_free_tmp_table_share(tmp_ref_table_share);
3761 mrn_open_mutex_unlock(table->s);
3762 grn_obj_unlink(ctx, grn_table_ref);
3763 error = ER_CANT_CREATE_TABLE;
3764 char err_msg[MRN_BUFFER_SIZE];
3765 sprintf(err_msg, "reference table [%s.%s] has no primary key",
3766 table->s->db.str, ref_table_name.str);
3767 my_message(error, err_msg, MYF(0));
3768 DBUG_RETURN(false);
3769 }
3770 KEY *ref_key_info = &tmp_ref_table_share->key_info[ref_pkey_nr];
3771 uint ref_key_parts = KEY_N_KEY_PARTS(ref_key_info);
3772 if (ref_key_parts > 1) {
3773 mrn_open_mutex_lock(table->s);
3774 mrn_free_tmp_table_share(tmp_ref_table_share);
3775 mrn_open_mutex_unlock(table->s);
3776 grn_obj_unlink(ctx, grn_table_ref);
3777 error = ER_CANT_CREATE_TABLE;
3778 char err_msg[MRN_BUFFER_SIZE];
3779 sprintf(err_msg,
3780 "reference table [%s.%s] primary key is multiple column",
3781 table->s->db.str, ref_table_name.str);
3782 my_message(error, err_msg, MYF(0));
3783 DBUG_RETURN(false);
3784 }
3785 Field *ref_field = &ref_key_info->key_part->field[0];
3786 if (strcmp(ref_field->field_name.str, ref_field_name.str)) {
3787 mrn_open_mutex_lock(table->s);
3788 mrn_free_tmp_table_share(tmp_ref_table_share);
3789 mrn_open_mutex_unlock(table->s);
3790 grn_obj_unlink(ctx, grn_table_ref);
3791 error = ER_CANT_CREATE_TABLE;
3792 char err_msg[MRN_BUFFER_SIZE];
3793 sprintf(err_msg,
3794 "reference column [%s.%s.%s] is not used for primary key",
3795 table->s->db.str, ref_table_name.str, ref_field_name.str);
3796 my_message(error, err_msg, MYF(0));
3797 DBUG_RETURN(false);
3798 }
3799 mrn_open_mutex_lock(table->s);
3800 mrn_free_tmp_table_share(tmp_ref_table_share);
3801 mrn_open_mutex_unlock(table->s);
3802 grn_obj_flags col_flags = GRN_OBJ_PERSISTENT;
3803 column = grn_column_create(ctx, table_obj, field->field_name.str,
3804 field->field_name.length,
3805 NULL, col_flags, grn_table_ref);
3806 if (ctx->rc) {
3807 grn_obj_unlink(ctx, grn_table_ref);
3808 error = ER_CANT_CREATE_TABLE;
3809 my_message(error, ctx->errbuf, MYF(0));
3810 DBUG_RETURN(false);
3811 }
3812
3813 mrn::IndexColumnName index_column_name(grn_table_name, field->field_name.str);
3814 grn_obj_flags ref_col_flags = GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT;
3815 column_ref = grn_column_create(ctx, grn_table_ref,
3816 index_column_name.c_str(),
3817 index_column_name.length(),
3818 NULL, ref_col_flags, table_obj);
3819 if (ctx->rc) {
3820 grn_obj_unlink(ctx, column);
3821 grn_obj_unlink(ctx, grn_table_ref);
3822 error = ER_CANT_CREATE_TABLE;
3823 my_message(error, ctx->errbuf, MYF(0));
3824 DBUG_RETURN(false);
3825 }
3826
3827 grn_obj source_ids;
3828 grn_id source_id = grn_obj_id(ctx, column);
3829 GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR);
3830 GRN_UINT32_PUT(ctx, &source_ids, source_id);
3831 if (error) {
3832 grn_obj_unlink(ctx, &source_ids);
3833 grn_obj_unlink(ctx, column_ref);
3834 grn_obj_unlink(ctx, column);
3835 grn_obj_unlink(ctx, grn_table_ref);
3836 DBUG_RETURN(false);
3837 }
3838 grn_obj_set_info(ctx, column_ref, GRN_INFO_SOURCE, &source_ids);
3839 grn_obj_unlink(ctx, &source_ids);
3840 grn_obj_unlink(ctx, column_ref);
3841 grn_obj_unlink(ctx, column);
3842 grn_obj_unlink(ctx, grn_table_ref);
3843 error = 0;
3844 DBUG_RETURN(true);
3845 }
3846 error = 0;
3847 DBUG_RETURN(false);
3848 }
3849 #endif
3850
storage_create_validate_index(TABLE * table)3851 int ha_mroonga::storage_create_validate_index(TABLE *table)
3852 {
3853 int error = 0;
3854 uint i;
3855
3856 MRN_DBUG_ENTER_METHOD();
3857 /* checking if index is used for virtual columns */
3858 uint n_keys = table->s->keys;
3859 for (i = 0; i < n_keys; i++) {
3860 KEY *key_info = &(table->s->key_info[i]);
3861 // must be single column key
3862 int key_parts = KEY_N_KEY_PARTS(key_info);
3863 if (key_parts != 1) {
3864 continue;
3865 }
3866 Field *field = key_info->key_part[0].field;
3867 const char *column_name = field->field_name.str;
3868 if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
3869 if (key_info->algorithm == HA_KEY_ALG_HASH) {
3870 continue; // hash index is ok
3871 }
3872 GRN_LOG(ctx, GRN_LOG_ERROR, "only hash index can be defined for _id");
3873 error = ER_CANT_CREATE_TABLE;
3874 my_message(error, "only hash index can be defined for _id", MYF(0));
3875 DBUG_RETURN(error);
3876 }
3877 }
3878
3879 DBUG_RETURN(error);
3880 }
3881
storage_create_index_table(TABLE * table,const char * grn_table_name,grn_obj * grn_table,MRN_SHARE * tmp_share,KEY * key_info,grn_obj ** index_tables,uint i)3882 int ha_mroonga::storage_create_index_table(TABLE *table,
3883 const char *grn_table_name,
3884 grn_obj *grn_table,
3885 MRN_SHARE *tmp_share,
3886 KEY *key_info,
3887 grn_obj **index_tables,
3888 uint i)
3889 {
3890 MRN_DBUG_ENTER_METHOD();
3891 int error = 0;
3892 grn_obj *index_type;
3893 grn_obj *index_table;
3894 grn_obj_flags index_table_flags = GRN_OBJ_PERSISTENT;
3895 bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1;
3896
3897 if (tmp_share->index_table && tmp_share->index_table[i]) {
3898 index_table = grn_ctx_get(ctx,
3899 tmp_share->index_table[i],
3900 tmp_share->index_table_length[i]);
3901 // TODO: add error check
3902 index_tables[i] = index_table;
3903 DBUG_RETURN(error);
3904 }
3905
3906 if (is_multiple_column_index) {
3907 index_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT);
3908 } else {
3909 Field *field = key_info->key_part[0].field;
3910 grn_builtin_type groonga_type = mrn_grn_type_from_field(ctx, field, true);
3911 index_type = grn_ctx_at(ctx, groonga_type);
3912 }
3913 // TODO: Add NULL check for index_type
3914
3915 int key_alg = key_info->algorithm;
3916 if (key_info->flags & HA_FULLTEXT) {
3917 index_table_flags |= GRN_OBJ_TABLE_PAT_KEY;
3918 error = mrn_change_encoding(ctx, key_info->key_part->field->charset());
3919 if (error) {
3920 grn_obj_remove(ctx, grn_table);
3921 DBUG_RETURN(error);
3922 }
3923 } else if (key_alg == HA_KEY_ALG_HASH) {
3924 index_table_flags |= GRN_OBJ_TABLE_HASH_KEY;
3925 } else {
3926 index_table_flags |= GRN_OBJ_TABLE_PAT_KEY;
3927 }
3928
3929 {
3930 mrn::IndexTableName index_table_name(grn_table_name, key_info->name.str);
3931 index_table = grn_table_create(ctx,
3932 index_table_name.c_str(),
3933 index_table_name.length(),
3934 NULL,
3935 index_table_flags,
3936 index_type,
3937 NULL);
3938 }
3939 if (ctx->rc) {
3940 grn_obj_unlink(ctx, index_type);
3941 grn_obj_remove(ctx, grn_table);
3942 error = ER_CANT_CREATE_TABLE;
3943 my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0));
3944 DBUG_RETURN(error);
3945 }
3946
3947 if (key_info->flags & HA_FULLTEXT) {
3948 grn_obj *tokenizer = find_tokenizer(key_info, tmp_share, i);
3949 if (tokenizer) {
3950 grn_info_type info_type = GRN_INFO_DEFAULT_TOKENIZER;
3951 grn_obj_set_info(ctx, index_table, info_type, tokenizer);
3952 grn_obj_unlink(ctx, tokenizer);
3953 }
3954
3955 {
3956 grn_obj token_filters;
3957 GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, 0);
3958 if (find_token_filters(key_info, &token_filters)) {
3959 grn_obj_set_info(ctx, index_table,
3960 GRN_INFO_TOKEN_FILTERS, &token_filters);
3961 }
3962 grn_obj_unlink(ctx, &token_filters);
3963 }
3964 }
3965
3966 {
3967 grn_obj *normalizer = NULL;
3968 Field *field = &(key_info->key_part->field[0]);
3969 if (key_info->flags & HA_FULLTEXT) {
3970 if (have_custom_normalizer(key_info) ||
3971 should_normalize(field)) {
3972 normalizer = find_normalizer(key_info);
3973 }
3974 } else if (key_alg != HA_KEY_ALG_HASH) {
3975 if (!is_multiple_column_index &&
3976 (have_custom_normalizer(key_info) ||
3977 should_normalize(field))) {
3978 normalizer = find_normalizer(key_info);
3979 }
3980 }
3981 if (normalizer) {
3982 grn_info_type info_type = GRN_INFO_NORMALIZER;
3983 grn_obj_set_info(ctx, index_table, info_type, normalizer);
3984 grn_obj_unlink(ctx, normalizer);
3985 }
3986 }
3987
3988 index_tables[i] = index_table;
3989
3990 DBUG_RETURN(error);
3991 }
3992
storage_create_index(TABLE * table,const char * grn_table_name,grn_obj * grn_table,MRN_SHARE * tmp_share,KEY * key_info,grn_obj ** index_tables,grn_obj ** index_columns,uint i)3993 int ha_mroonga::storage_create_index(TABLE *table, const char *grn_table_name,
3994 grn_obj *grn_table, MRN_SHARE *tmp_share,
3995 KEY *key_info, grn_obj **index_tables,
3996 grn_obj **index_columns, uint i)
3997 {
3998 MRN_DBUG_ENTER_METHOD();
3999 int error = 0;
4000 grn_obj *index_column;
4001
4002 bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1;
4003 if (!is_multiple_column_index) {
4004 Field *field = key_info->key_part[0].field;
4005 if (strcmp(MRN_COLUMN_NAME_ID, field->field_name.str) == 0) {
4006 // skipping _id virtual column
4007 DBUG_RETURN(0);
4008 }
4009
4010 if (is_foreign_key_field(table->s->table_name.str,
4011 field->field_name.str)) {
4012 DBUG_RETURN(0);
4013 }
4014
4015 #ifdef HA_CAN_VIRTUAL_COLUMNS
4016 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
4017 char error_message[MRN_MESSAGE_BUFFER_SIZE];
4018 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
4019 "mroonga: storage: failed to create index: "
4020 ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_STR,
4021 field->field_name.str);
4022 error = ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_NUM;
4023 my_message(error, error_message, MYF(0));
4024 DBUG_RETURN(error);
4025 }
4026 } else {
4027 int j, n_key_parts = KEY_N_KEY_PARTS(key_info);
4028 for (j = 0; j < n_key_parts; j++) {
4029 Field *field = key_info->key_part[j].field;
4030 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
4031 char error_message[MRN_MESSAGE_BUFFER_SIZE];
4032 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
4033 "mroonga: storage: failed to create index: "
4034 ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_STR,
4035 field->field_name.str);
4036 error = ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_NUM;
4037 my_message(error, error_message, MYF(0));
4038 DBUG_RETURN(error);
4039 }
4040 }
4041 #endif
4042 }
4043
4044 error = mrn_change_encoding(ctx, system_charset_info);
4045 if (error)
4046 DBUG_RETURN(error);
4047
4048 error = storage_create_index_table(table, grn_table_name,
4049 grn_table, tmp_share,
4050 key_info, index_tables, i);
4051 if (error)
4052 DBUG_RETURN(error);
4053
4054 grn_obj *index_table = index_tables[i];
4055
4056 grn_column_flags index_column_flags = GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT;
4057
4058 if (!find_index_column_flags(key_info, &index_column_flags)) {
4059 grn_obj *tokenizer = grn_obj_get_info(ctx, index_table,
4060 GRN_INFO_DEFAULT_TOKENIZER, NULL);
4061 if (tokenizer) {
4062 index_column_flags |= GRN_OBJ_WITH_POSITION;
4063 }
4064 if (is_multiple_column_index && (key_info->flags & HA_FULLTEXT)) {
4065 index_column_flags |= GRN_OBJ_WITH_SECTION;
4066 }
4067 }
4068
4069 const char *index_column_name;
4070 if (tmp_share->index_table && tmp_share->index_table[i]) {
4071 index_column_name = key_info->name.str;
4072 } else {
4073 index_column_name = INDEX_COLUMN_NAME;
4074 }
4075 index_column = grn_column_create(ctx,
4076 index_table,
4077 index_column_name,
4078 strlen(index_column_name),
4079 NULL,
4080 index_column_flags,
4081 grn_table);
4082
4083 if (ctx->rc) {
4084 grn_obj_remove(ctx, index_table);
4085 error = ER_CANT_CREATE_TABLE;
4086 my_message(error, ctx->errbuf, MYF(0));
4087 DBUG_RETURN(error);
4088 }
4089
4090 mrn_change_encoding(ctx, system_charset_info);
4091 if (is_multiple_column_index) {
4092 if (key_info->flags & HA_FULLTEXT) {
4093 grn_obj source_ids;
4094 GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR);
4095
4096 int j, n_key_parts = KEY_N_KEY_PARTS(key_info);
4097 for (j = 0; j < n_key_parts; j++) {
4098 Field *field = key_info->key_part[j].field;
4099 mrn::ColumnName column_name(field->field_name);
4100 grn_obj *source_column = grn_obj_column(ctx,
4101 grn_table,
4102 column_name.c_str(),
4103 column_name.length());
4104 grn_id source_id = grn_obj_id(ctx, source_column);
4105 GRN_UINT32_PUT(ctx, &source_ids, source_id);
4106 grn_obj_unlink(ctx, source_column);
4107 }
4108 mrn_change_encoding(ctx, key_info->key_part->field->charset());
4109 grn_obj_set_info(ctx, index_column, GRN_INFO_SOURCE, &source_ids);
4110 grn_obj_unlink(ctx, &source_ids);
4111 }
4112 } else {
4113 Field *field = key_info->key_part[0].field;
4114 mrn::ColumnName column_name(field->field_name);
4115 grn_obj *column;
4116 column = grn_obj_column(ctx,
4117 grn_table,
4118 column_name.c_str(),
4119 column_name.length());
4120 if (column) {
4121 grn_obj source_ids;
4122 grn_id source_id = grn_obj_id(ctx, column);
4123 GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR);
4124 GRN_UINT32_PUT(ctx, &source_ids, source_id);
4125 mrn_change_encoding(ctx, key_info->key_part->field->charset());
4126 grn_obj_set_info(ctx, index_column, GRN_INFO_SOURCE, &source_ids);
4127 grn_obj_unlink(ctx, &source_ids);
4128 grn_obj_unlink(ctx, column);
4129 }
4130 }
4131 mrn_change_encoding(ctx, system_charset_info);
4132
4133 if (index_columns) {
4134 index_columns[i] = index_column;
4135 }
4136
4137 DBUG_RETURN(error);
4138 }
4139
storage_create_indexes(TABLE * table,const char * grn_table_name,grn_obj * grn_table,MRN_SHARE * tmp_share)4140 int ha_mroonga::storage_create_indexes(TABLE *table, const char *grn_table_name,
4141 grn_obj *grn_table, MRN_SHARE *tmp_share)
4142 {
4143 MRN_DBUG_ENTER_METHOD();
4144 int error = 0;
4145
4146 uint n_keys = table->s->keys;
4147 uint i;
4148 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys);
4149 for (i = 0; i < n_keys; i++) {
4150 index_tables[i] = NULL;
4151 if (i == table->s->primary_key) {
4152 continue; // pkey is already handled
4153 }
4154 KEY *key_info = &table->s->key_info[i];
4155 if (tmp_share->disable_keys && !(key_info->flags & HA_NOSAME)) {
4156 continue; // key is disabled
4157 }
4158 if ((error = storage_create_index(table, grn_table_name, grn_table,
4159 tmp_share, key_info,
4160 index_tables, NULL, i))) {
4161 break;
4162 }
4163 }
4164 if (error) {
4165 while (true) {
4166 if (index_tables[i] &&
4167 !(tmp_share->index_table && tmp_share->index_table[i])) {
4168 grn_obj_remove(ctx, index_tables[i]);
4169 }
4170 if (!i)
4171 break;
4172 i--;
4173 }
4174 }
4175 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
4176 DBUG_RETURN(error);
4177 }
4178
ensure_database_open(const char * name,mrn::Database ** db)4179 int ha_mroonga::ensure_database_open(const char *name, mrn::Database **db)
4180 {
4181 int error;
4182
4183 MRN_DBUG_ENTER_METHOD();
4184
4185 if (db)
4186 *db = NULL;
4187
4188 mrn::Database *local_db;
4189 error = mrn_db_manager->open(name, &local_db);
4190 if (error)
4191 DBUG_RETURN(error);
4192
4193 if (db)
4194 *db = local_db;
4195 grn_ctx_use(ctx, local_db->get());
4196
4197 delete operations_;
4198 operations_ = new mrn::Operations(ctx);
4199 if (mrn_enable_operations_recording) {
4200 operations_->enable_recording();
4201 } else {
4202 operations_->disable_recording();
4203 }
4204
4205 DBUG_RETURN(error);
4206 }
4207
ensure_database_remove(const char * name)4208 int ha_mroonga::ensure_database_remove(const char *name)
4209 {
4210 int error;
4211
4212 MRN_DBUG_ENTER_METHOD();
4213
4214 error = mrn_change_encoding(ctx, system_charset_info);
4215 if (error)
4216 DBUG_RETURN(error);
4217
4218 delete operations_;
4219 operations_ = NULL;
4220
4221 mrn_db_manager->close(name);
4222
4223 mrn::PathMapper mapper(name);
4224 remove_related_files(mapper.db_path());
4225
4226 DBUG_RETURN(error);
4227 }
4228
4229
create(const char * name,TABLE * table,HA_CREATE_INFO * info,dd::Table * table_def)4230 int ha_mroonga::create(const char *name,
4231 TABLE *table,
4232 HA_CREATE_INFO *info
4233 #ifdef MRN_HANDLER_CREATE_HAVE_TABLE_DEFINITION
4234 ,
4235 dd::Table *table_def
4236 #endif
4237 )
4238 {
4239 int error = 0;
4240 MRN_SHARE *tmp_share;
4241 MRN_DBUG_ENTER_METHOD();
4242 /* checking data type of virtual columns */
4243
4244 if (!(tmp_share = mrn_get_share(name, table, &error)))
4245 DBUG_RETURN(error);
4246
4247 st_mrn_slot_data *slot_data = mrn_get_slot_data(ha_thd(), false);
4248 if (slot_data && slot_data->disable_keys_create_info == info) {
4249 tmp_share->disable_keys = true;
4250 }
4251
4252 if (tmp_share->wrapper_mode)
4253 {
4254 error = wrapper_create(name, table, info, tmp_share);
4255 } else {
4256 error = storage_create(name, table, info, tmp_share);
4257 }
4258
4259 if (error) {
4260 mrn_free_long_term_share(tmp_share->long_term_share);
4261 tmp_share->long_term_share = NULL;
4262 } else {
4263 error = add_wrap_hton(tmp_share->table_name, tmp_share->hton);
4264 }
4265 mrn_free_share(tmp_share);
4266 DBUG_RETURN(error);
4267 }
4268
wrapper_open(const char * name,int mode,uint open_options)4269 int ha_mroonga::wrapper_open(const char *name, int mode, uint open_options)
4270 {
4271 int error = 0;
4272 MRN_DBUG_ENTER_METHOD();
4273
4274 mrn::Database *db = NULL;
4275 error = ensure_database_open(name, &db);
4276 if (error)
4277 DBUG_RETURN(error);
4278
4279 if (!(open_options & HA_OPEN_FOR_REPAIR)) {
4280 error = open_table(name);
4281 if (error)
4282 DBUG_RETURN(error);
4283
4284 error = wrapper_open_indexes(name);
4285 if (error) {
4286 grn_obj_unlink(ctx, grn_table);
4287 grn_table = NULL;
4288 DBUG_RETURN(error);
4289 }
4290 }
4291
4292 mrn_init_alloc_root(&mem_root, 1024, 0, MYF(0));
4293 wrap_key_info = mrn_create_key_info_for_table(share, table, &error);
4294 if (error)
4295 DBUG_RETURN(error);
4296 base_key_info = table->key_info;
4297
4298 MRN_SET_WRAP_SHARE_KEY(share, table->s);
4299 MRN_SET_WRAP_TABLE_KEY(this, table);
4300 if (!is_clone)
4301 {
4302 wrap_handler = get_new_handler(table->s, &mem_root, share->hton);
4303 if (!wrap_handler)
4304 {
4305 MRN_SET_BASE_SHARE_KEY(share, table->s);
4306 MRN_SET_BASE_TABLE_KEY(this, table);
4307 if (wrap_key_info)
4308 {
4309 my_free(wrap_key_info);
4310 wrap_key_info = NULL;
4311 }
4312 base_key_info = NULL;
4313 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
4314 }
4315 #ifdef MRN_HANDLER_HAVE_SET_HA_SHARE_REF
4316 wrap_handler->set_ha_share_ref(&table->s->ha_share);
4317 #endif
4318 error = wrap_handler->ha_open(table, name, mode, open_options);
4319 } else {
4320 if (!(wrap_handler = parent_for_clone->wrap_handler->clone(name,
4321 mem_root_for_clone)))
4322 {
4323 MRN_SET_BASE_SHARE_KEY(share, table->s);
4324 MRN_SET_BASE_TABLE_KEY(this, table);
4325 if (wrap_key_info)
4326 {
4327 my_free(wrap_key_info);
4328 wrap_key_info = NULL;
4329 }
4330 base_key_info = NULL;
4331 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
4332 }
4333 }
4334 ref_length = wrap_handler->ref_length;
4335 key_used_on_scan = wrap_handler->key_used_on_scan;
4336 MRN_SET_BASE_SHARE_KEY(share, table->s);
4337 MRN_SET_BASE_TABLE_KEY(this, table);
4338 init();
4339 wrapper_overwrite_index_bits();
4340 wrapper_set_keys_in_use();
4341
4342 pk_keypart_map = make_prev_keypart_map(
4343 KEY_N_KEY_PARTS(&(table->key_info[table_share->primary_key])));
4344
4345 if (!error) {
4346 if (open_options & HA_OPEN_FOR_REPAIR) {
4347 // TODO: How to check whether is DISABLE KEYS used or not?
4348 error = wrapper_recreate_indexes(ha_thd());
4349 } else if (db) {
4350 mrn::Lock lock(&mrn_operations_mutex);
4351 mrn::PathMapper mapper(name);
4352 const char *table_name = mapper.table_name();
4353 size_t table_name_size = strlen(table_name);
4354 if (db->is_broken_table(table_name, table_name_size)) {
4355 GRN_LOG(ctx, GRN_LOG_NOTICE,
4356 "Auto repair is started: <%s>",
4357 name);
4358 error = operations_->clear(table_name, table_name_size);
4359 if (!error) {
4360 db->mark_table_repaired(table_name, table_name_size);
4361 if (!share->disable_keys) {
4362 // TODO: implemented by "reindex" instead of "remove and recreate".
4363 // Because "remove and recreate" invalidates opened indexes by
4364 // other threads.
4365 error = wrapper_disable_indexes_mroonga(HA_KEY_SWITCH_ALL);
4366 if (!error) {
4367 error = wrapper_enable_indexes_mroonga(HA_KEY_SWITCH_ALL);
4368 }
4369 }
4370 }
4371 GRN_LOG(ctx, GRN_LOG_NOTICE,
4372 "Auto repair is done: <%s>: %s",
4373 name, error == 0 ? "success" : "failure");
4374 }
4375 }
4376 }
4377
4378 if (error)
4379 {
4380 grn_obj_unlink(ctx, grn_table);
4381 grn_table = NULL;
4382 // TODO: free indexes.
4383
4384 delete wrap_handler;
4385 wrap_handler = NULL;
4386 if (wrap_key_info)
4387 {
4388 my_free(wrap_key_info);
4389 wrap_key_info = NULL;
4390 }
4391 base_key_info = NULL;
4392 }
4393 DBUG_RETURN(error);
4394 }
4395
wrapper_open_indexes(const char * name)4396 int ha_mroonga::wrapper_open_indexes(const char *name)
4397 {
4398 int error;
4399
4400 MRN_DBUG_ENTER_METHOD();
4401
4402 error = mrn_change_encoding(ctx, system_charset_info);
4403 if (error)
4404 DBUG_RETURN(error);
4405
4406 uint n_keys = table->s->keys;
4407 uint n_primary_keys = table->s->primary_key;
4408 if (n_keys > 0) {
4409 // TODO: reduce allocate memories. We only need just
4410 // for HA_KEY_ALG_FULLTEXT keys.
4411 grn_index_tables = (grn_obj **)malloc(sizeof(grn_obj *) * n_keys);
4412 grn_index_columns = (grn_obj **)malloc(sizeof(grn_obj *) * n_keys);
4413 } else {
4414 grn_index_tables = grn_index_columns = NULL;
4415 }
4416
4417 mrn::PathMapper mapper(name);
4418 uint i = 0;
4419 for (i = 0; i < n_keys; i++) {
4420 KEY *key_info = &(table->s->key_info[i]);
4421
4422 grn_index_tables[i] = NULL;
4423 grn_index_columns[i] = NULL;
4424
4425 if (!(wrapper_is_target_index(key_info))) {
4426 continue;
4427 }
4428
4429 if (i == n_primary_keys) {
4430 continue;
4431 }
4432
4433 mrn::IndexTableName index_table_name(mapper.table_name(), key_info->name.str);
4434 grn_index_tables[i] = grn_ctx_get(ctx,
4435 index_table_name.c_str(),
4436 index_table_name.length());
4437 if (ctx->rc == GRN_SUCCESS && !grn_index_tables[i]) {
4438 grn_index_tables[i] = grn_ctx_get(ctx,
4439 index_table_name.old_c_str(),
4440 index_table_name.old_length());
4441 }
4442 if (ctx->rc) {
4443 DBUG_PRINT("info",
4444 ("mroonga: sql_command=%u", thd_sql_command(ha_thd())));
4445 error = ER_CANT_OPEN_FILE;
4446 my_message(error, ctx->errbuf, MYF(0));
4447 goto error;
4448 }
4449
4450 grn_index_columns[i] = grn_obj_column(ctx, grn_index_tables[i],
4451 INDEX_COLUMN_NAME,
4452 strlen(INDEX_COLUMN_NAME));
4453 if (!grn_index_columns[i]) {
4454 /* just for backward compatibility before 1.0. */
4455 Field *field = key_info->key_part[0].field;
4456 grn_index_columns[i] = grn_obj_column(ctx, grn_index_tables[i],
4457 field->field_name.str,
4458 field->field_name.length);
4459 }
4460
4461 if (ctx->rc) {
4462 DBUG_PRINT("info",
4463 ("mroonga: sql_command=%u", thd_sql_command(ha_thd())));
4464 error = ER_CANT_OPEN_FILE;
4465 my_message(error, ctx->errbuf, MYF(0));
4466 grn_obj_unlink(ctx, grn_index_tables[i]);
4467 goto error;
4468 }
4469 }
4470
4471 grn_bulk_space(ctx, &key_buffer, table->key_info->key_length);
4472
4473 error:
4474 if (error) {
4475 while (i-- > 0) {
4476 grn_obj *index_column = grn_index_columns[i];
4477 if (index_column) {
4478 grn_obj_unlink(ctx, index_column);
4479 }
4480 grn_obj *index_table = grn_index_tables[i];
4481 if (index_table) {
4482 grn_obj_unlink(ctx, index_table);
4483 }
4484 }
4485 free(grn_index_columns);
4486 free(grn_index_tables);
4487 grn_index_columns = NULL;
4488 grn_index_tables = NULL;
4489 }
4490
4491 DBUG_RETURN(error);
4492 }
4493
wrapper_overwrite_index_bits()4494 void ha_mroonga::wrapper_overwrite_index_bits()
4495 {
4496 uint i, j;
4497 longlong table_option = table_flags();
4498 MRN_DBUG_ENTER_METHOD();
4499 table_share->keys_for_keyread.clear_all();
4500 for (i = 0; i < table_share->fields; i++)
4501 {
4502 Field *field = table_share->field[i];
4503 field->part_of_key.clear_all();
4504 #ifdef MRN_HAVE_MYSQL_FIELD_PART_OF_KEY_NOT_CLUSTERED
4505 field->part_of_key_not_clustered.clear_all();
4506 #endif
4507 field->part_of_sortkey.clear_all();
4508 /*
4509 TODO: We may need to update field->part_of_key_not_extended for
4510 MySQL >= 5.7.18. If users report "raw InnoDB can use index for
4511 this case but Mroonga wrapper mode for InnoDB can't use index
4512 for the same case", we'll reconsider it again.
4513 */
4514 }
4515 for (i = 0; i < table_share->keys; i++) {
4516 KEY *key_info = &table->s->key_info[i];
4517 KEY_PART_INFO *key_part = key_info->key_part;
4518 for (j = 0 ; j < KEY_N_KEY_PARTS(key_info); key_part++, j++)
4519 {
4520 Field *field = key_part->field;
4521 if (field->key_length() == key_part->length &&
4522 !(field->flags & BLOB_FLAG))
4523 {
4524 if (index_flags(i, j, 0) & HA_KEYREAD_ONLY)
4525 {
4526 table_share->keys_for_keyread.set_bit(i);
4527 field->part_of_key.set_bit(i);
4528 #ifdef MRN_HAVE_MYSQL_FIELD_PART_OF_KEY_NOT_CLUSTERED
4529 field->part_of_key_not_clustered.set_bit(i);
4530 #endif
4531 }
4532 if (index_flags(i, j, 1) & HA_READ_ORDER)
4533 field->part_of_sortkey.set_bit(i);
4534 }
4535 if (i == table_share->primary_key &&
4536 (table_option & HA_PRIMARY_KEY_IN_READ_INDEX))
4537 {
4538 if (field->key_length() == key_part->length &&
4539 !(field->flags & BLOB_FLAG))
4540 field->part_of_key = table_share->keys_in_use;
4541 if (field->part_of_sortkey.is_set(i))
4542 field->part_of_sortkey = table_share->keys_in_use;
4543 }
4544 }
4545 }
4546 DBUG_VOID_RETURN;
4547 }
4548
storage_reindex()4549 int ha_mroonga::storage_reindex()
4550 {
4551 int error = 0;
4552 MRN_DBUG_ENTER_METHOD();
4553
4554 uint n_keys = table_share->keys;
4555 KEY *key_info = table->key_info;
4556
4557 bool have_multiple_column_index = false;
4558 bitmap_clear_all(table->read_set);
4559 for (uint i = 0; i < n_keys; ++i) {
4560 if (!grn_index_columns[i])
4561 continue;
4562
4563 grn_hash *columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
4564 GRN_OBJ_TABLE_HASH_KEY);
4565 grn_table_columns(ctx, grn_index_tables[i], NULL, 0,
4566 reinterpret_cast<grn_obj *>(columns));
4567 unsigned int n_columns =
4568 grn_table_size(ctx, reinterpret_cast<grn_obj *>(columns));
4569 grn_hash_close(ctx, columns);
4570
4571 bool is_multiple_column_index =
4572 (KEY_N_KEY_PARTS(&(key_info[i])) != 1 &&
4573 !(key_info[i].flags & HA_FULLTEXT));
4574
4575 if (n_columns == 1 || is_multiple_column_index) {
4576 grn_table_truncate(ctx, grn_index_tables[i]);
4577 if (ctx->rc != GRN_SUCCESS) {
4578 error = ER_ERROR_ON_WRITE;
4579 char error_message[MRN_MESSAGE_BUFFER_SIZE];
4580 char index_table_name[GRN_TABLE_MAX_KEY_SIZE];
4581 int index_table_name_size;
4582 index_table_name_size =
4583 grn_obj_name(ctx, grn_index_tables[i],
4584 index_table_name, GRN_TABLE_MAX_KEY_SIZE);
4585 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
4586 "mroonga: reindex: failed to truncate index table: "
4587 "<%.*s>: <%s>(%d)",
4588 index_table_name_size, index_table_name,
4589 ctx->errbuf, ctx->rc);
4590 my_message(error, error_message, MYF(0));
4591 break;
4592 }
4593 }
4594
4595 if (is_multiple_column_index) {
4596 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
4597 have_multiple_column_index = true;
4598 } else {
4599 grn_obj_reindex(ctx, grn_index_columns[i]);
4600 if (ctx->rc != GRN_SUCCESS) {
4601 error = ER_ERROR_ON_WRITE;
4602 char error_message[MRN_MESSAGE_BUFFER_SIZE];
4603 char index_column_name[GRN_TABLE_MAX_KEY_SIZE];
4604 int index_column_name_size;
4605 index_column_name_size =
4606 grn_obj_name(ctx, grn_index_columns[i],
4607 index_column_name, GRN_TABLE_MAX_KEY_SIZE);
4608 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
4609 "mroonga: reindex: failed to reindex: "
4610 "<%.*s>: <%s>(%d)",
4611 index_column_name_size, index_column_name,
4612 ctx->errbuf, ctx->rc);
4613 my_message(error, error_message, MYF(0));
4614 break;
4615 }
4616 }
4617 }
4618
4619 if (!error && have_multiple_column_index)
4620 error = storage_add_index_multiple_columns(key_info, n_keys,
4621 grn_index_tables,
4622 grn_index_columns,
4623 false);
4624 bitmap_set_all(table->read_set);
4625
4626 DBUG_RETURN(error);
4627 }
4628
storage_open(const char * name,int mode,uint open_options)4629 int ha_mroonga::storage_open(const char *name, int mode, uint open_options)
4630 {
4631 int error = 0;
4632 MRN_DBUG_ENTER_METHOD();
4633
4634 mrn::Database *db;
4635 error = ensure_database_open(name, &db);
4636 if (error)
4637 DBUG_RETURN(error);
4638
4639 error = open_table(name);
4640 if (error)
4641 DBUG_RETURN(error);
4642
4643 error = storage_open_columns();
4644 if (error) {
4645 grn_obj_unlink(ctx, grn_table);
4646 grn_table = NULL;
4647 DBUG_RETURN(error);
4648 }
4649
4650 if (!(open_options & HA_OPEN_FOR_REPAIR)) {
4651 error = storage_open_indexes(name);
4652 if (error) {
4653 storage_close_columns();
4654 grn_obj_unlink(ctx, grn_table);
4655 grn_table = NULL;
4656 DBUG_RETURN(error);
4657 }
4658
4659 storage_set_keys_in_use();
4660
4661 {
4662 mrn::Lock lock(&mrn_operations_mutex);
4663 mrn::PathMapper mapper(name);
4664 const char *table_name = mapper.table_name();
4665 size_t table_name_size = strlen(table_name);
4666 if (db->is_broken_table(table_name, table_name_size)) {
4667 GRN_LOG(ctx, GRN_LOG_NOTICE,
4668 "Auto repair is started: <%s>",
4669 name);
4670 error = operations_->repair(table_name, table_name_size);
4671 if (!error)
4672 db->mark_table_repaired(table_name, table_name_size);
4673 if (!share->disable_keys) {
4674 if (!error)
4675 error = storage_reindex();
4676 }
4677 GRN_LOG(ctx, GRN_LOG_NOTICE,
4678 "Auto repair is done: <%s>: %s",
4679 name, error == 0 ? "success" : "failure");
4680 }
4681 }
4682 }
4683
4684 ref_length = sizeof(grn_id);
4685 DBUG_RETURN(0);
4686 }
4687
open_table(const char * name)4688 int ha_mroonga::open_table(const char *name)
4689 {
4690 int error;
4691 MRN_DBUG_ENTER_METHOD();
4692
4693 error = mrn_change_encoding(ctx, system_charset_info);
4694 if (error)
4695 DBUG_RETURN(error);
4696
4697 mrn::PathMapper mapper(name);
4698 grn_table = grn_ctx_get(ctx, mapper.table_name(), strlen(mapper.table_name()));
4699 if (ctx->rc) {
4700 error = ER_CANT_OPEN_FILE;
4701 my_message(error, ctx->errbuf, MYF(0));
4702 DBUG_RETURN(error);
4703 }
4704 if (!grn_table) {
4705 error = ER_CANT_OPEN_FILE;
4706 char error_message[MRN_MESSAGE_BUFFER_SIZE];
4707 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
4708 "mroonga: failed to open table: <%s>",
4709 mapper.table_name());
4710 my_message(error, error_message, MYF(0));
4711 DBUG_RETURN(error);
4712 }
4713
4714 DBUG_RETURN(0);
4715 }
4716
storage_open_columns(void)4717 int ha_mroonga::storage_open_columns(void)
4718 {
4719 int error;
4720 MRN_DBUG_ENTER_METHOD();
4721
4722 error = mrn_change_encoding(ctx, system_charset_info);
4723 if (error)
4724 DBUG_RETURN(error);
4725
4726 int n_columns = table->s->fields;
4727 grn_columns = (grn_obj **)malloc(sizeof(grn_obj *) * n_columns);
4728 grn_column_ranges = (grn_obj **)malloc(sizeof(grn_obj *) * n_columns);
4729 for (int i = 0; i < n_columns; i++) {
4730 grn_columns[i] = NULL;
4731 grn_column_ranges[i] = NULL;
4732 }
4733
4734 if (table_share->blob_fields)
4735 {
4736 DBUG_ASSERT(!blob_buffers);
4737 if (!(blob_buffers = new (&table->mem_root) String[n_columns]))
4738 {
4739 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
4740 }
4741 }
4742
4743 for (int i = 0; i < n_columns; i++) {
4744 Field *field = table->field[i];
4745 mrn::ColumnName column_name(field->field_name);
4746 if (table_share->blob_fields)
4747 {
4748 blob_buffers[i].set_charset(field->charset());
4749 }
4750 if (strcmp(MRN_COLUMN_NAME_ID, column_name.mysql_name()) == 0) {
4751 continue;
4752 }
4753 #ifdef MRN_SUPPORT_GENERATED_COLUMNS
4754 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
4755 grn_columns[i] = NULL;
4756 grn_column_ranges[i] = NULL;
4757 continue;
4758 }
4759 #endif
4760
4761 grn_columns[i] = grn_obj_column(ctx,
4762 grn_table,
4763 column_name.c_str(),
4764 column_name.length());
4765 if (!grn_columns[i]) {
4766 error = ER_CANT_OPEN_FILE;
4767 my_message(error, ctx->errbuf, MYF(0));
4768 break;
4769 }
4770
4771 grn_id range_id = grn_obj_get_range(ctx, grn_columns[i]);
4772 grn_column_ranges[i] = grn_ctx_at(ctx, range_id);
4773 if (!grn_column_ranges[i]) {
4774 error = ER_CANT_OPEN_FILE;
4775 my_message(error, ctx->errbuf, MYF(0));
4776 break;
4777 }
4778 }
4779
4780 if (error != 0) {
4781 storage_close_columns();
4782 }
4783
4784 DBUG_RETURN(error);
4785 }
4786
storage_close_columns(void)4787 void ha_mroonga::storage_close_columns(void)
4788 {
4789 int n_columns = table->s->fields;
4790 for (int i = 0; i < n_columns; i++) {
4791 grn_obj *column = grn_columns[i];
4792 if (column) {
4793 grn_obj_unlink(ctx, column);
4794 }
4795
4796 grn_obj *range = grn_column_ranges[i];
4797 if (range) {
4798 grn_obj_unlink(ctx, range);
4799 }
4800 }
4801
4802 free(grn_columns);
4803 grn_columns = NULL;
4804 free(grn_column_ranges);
4805 grn_column_ranges = NULL;
4806 }
4807
storage_open_indexes(const char * name)4808 int ha_mroonga::storage_open_indexes(const char *name)
4809 {
4810 int error;
4811
4812 MRN_DBUG_ENTER_METHOD();
4813
4814 error = mrn_change_encoding(ctx, system_charset_info);
4815 if (error)
4816 DBUG_RETURN(error);
4817
4818 uint n_keys = table->s->keys;
4819 uint pkey_nr = table->s->primary_key;
4820 if (n_keys > 0) {
4821 grn_index_tables = (grn_obj **)malloc(sizeof(grn_obj *) * n_keys);
4822 grn_index_columns = (grn_obj **)malloc(sizeof(grn_obj *) * n_keys);
4823 key_id = (grn_id *)malloc(sizeof(grn_id) * n_keys);
4824 del_key_id = (grn_id *)malloc(sizeof(grn_id) * n_keys);
4825 } else {
4826 grn_index_tables = grn_index_columns = NULL;
4827 key_id = NULL;
4828 del_key_id = NULL;
4829 }
4830
4831 mrn::PathMapper mapper(name);
4832 uint i, j;
4833 for (i = 0; i < n_keys; i++) {
4834 if (i == pkey_nr) {
4835 grn_index_tables[i] = grn_index_columns[i] = NULL;
4836 continue;
4837 }
4838
4839 KEY *key_info = &(table->s->key_info[i]);
4840 if (KEY_N_KEY_PARTS(key_info) > 1) {
4841 KEY_PART_INFO *key_part = key_info->key_part;
4842 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
4843 bitmap_set_bit(&multiple_column_key_bitmap,
4844 key_part[j].field->field_index);
4845 }
4846 }
4847
4848 MRN_SHARE *tmp_share;
4849 tmp_share = mrn_get_share(name, table, &error);
4850 if (tmp_share->index_table[i]) {
4851 grn_index_tables[i] = grn_ctx_get(ctx,
4852 tmp_share->index_table[i],
4853 tmp_share->index_table_length[i]);
4854 if (ctx->rc == GRN_SUCCESS) {
4855 grn_index_columns[i] = grn_obj_column(ctx,
4856 grn_index_tables[i],
4857 key_info->name.str,
4858 key_info->name.length);
4859 }
4860 } else {
4861 mrn::IndexTableName index_table_name(mapper.table_name(),
4862 key_info->name.str);
4863 grn_index_tables[i] = grn_ctx_get(ctx,
4864 index_table_name.c_str(),
4865 index_table_name.length());
4866 if (ctx->rc == GRN_SUCCESS && !grn_index_tables[i]) {
4867 grn_index_tables[i] = grn_ctx_get(ctx,
4868 index_table_name.old_c_str(),
4869 index_table_name.old_length());
4870 }
4871 if (ctx->rc == GRN_SUCCESS) {
4872 grn_index_columns[i] = grn_obj_column(ctx,
4873 grn_index_tables[i],
4874 INDEX_COLUMN_NAME,
4875 strlen(INDEX_COLUMN_NAME));
4876 if (!grn_index_columns[i] && ctx->rc == GRN_SUCCESS) {
4877 /* just for backward compatibility before 1.0. */
4878 Field *field = key_info->key_part[0].field;
4879 grn_index_columns[i] = grn_obj_column(ctx, grn_index_tables[i],
4880 field->field_name.str,
4881 field->field_name.length);
4882 }
4883 }
4884 }
4885 mrn_free_share(tmp_share);
4886 if (ctx->rc) {
4887 error = ER_CANT_OPEN_FILE;
4888 my_message(error, ctx->errbuf, MYF(0));
4889 goto error;
4890 }
4891
4892 if (ctx->rc) {
4893 error = ER_CANT_OPEN_FILE;
4894 my_message(error, ctx->errbuf, MYF(0));
4895 goto error;
4896 }
4897 }
4898
4899 error:
4900 if (error) {
4901 if (i) {
4902 while (true) {
4903 grn_obj *index_column = grn_index_columns[i];
4904 if (index_column) {
4905 grn_obj_unlink(ctx, index_column);
4906 }
4907 grn_obj *index_table = grn_index_tables[i];
4908 if (index_table) {
4909 grn_obj_unlink(ctx, index_table);
4910 }
4911 if (!i)
4912 break;
4913 i--;
4914 }
4915 }
4916 free(key_id);
4917 free(del_key_id);
4918 free(grn_index_columns);
4919 free(grn_index_tables);
4920 key_id = NULL;
4921 del_key_id = NULL;
4922 grn_index_columns = NULL;
4923 grn_index_tables = NULL;
4924 }
4925
4926 DBUG_RETURN(error);
4927 }
4928
open(const char * name,int mode,uint open_options,const dd::Table * table_def)4929 int ha_mroonga::open(const char *name,
4930 int mode,
4931 uint open_options
4932 #ifdef MRN_HANDLER_OPEN_HAVE_TABLE_DEFINITION
4933 ,
4934 const dd::Table *table_def
4935 #endif
4936 )
4937 {
4938 int error = 0;
4939 MRN_DBUG_ENTER_METHOD();
4940
4941 if (!(share = mrn_get_share(name, table, &error)))
4942 DBUG_RETURN(error);
4943 thr_lock_data_init(&share->lock,&thr_lock_data,NULL);
4944
4945 if (bitmap_init(&multiple_column_key_bitmap, NULL, table->s->fields, false))
4946 {
4947 mrn_free_share(share);
4948 share = NULL;
4949 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
4950 }
4951
4952 if (share->wrapper_mode)
4953 {
4954 error = wrapper_open(name, mode, open_options);
4955 } else {
4956 error = storage_open(name, mode, open_options);
4957 }
4958
4959 if (error)
4960 {
4961 bitmap_free(&multiple_column_key_bitmap);
4962 mrn_free_share(share);
4963 share = NULL;
4964 }
4965 DBUG_RETURN(error);
4966 }
4967
wrapper_close()4968 int ha_mroonga::wrapper_close()
4969 {
4970 int error = 0;
4971 MRN_DBUG_ENTER_METHOD();
4972 MRN_SET_WRAP_SHARE_KEY(share, table->s);
4973 MRN_SET_WRAP_TABLE_KEY(this, table);
4974 #ifdef MRN_HANDLER_HAVE_HA_CLOSE
4975 error = wrap_handler->ha_close();
4976 #else
4977 error = wrap_handler->close();
4978 #endif
4979 MRN_SET_BASE_SHARE_KEY(share, table->s);
4980 MRN_SET_BASE_TABLE_KEY(this, table);
4981 delete wrap_handler;
4982 wrap_handler = NULL;
4983 if (wrap_key_info)
4984 {
4985 my_free(wrap_key_info);
4986 wrap_key_info = NULL;
4987 }
4988 base_key_info = NULL;
4989 free_root(&mem_root, MYF(0));
4990 DBUG_RETURN(error);
4991 }
4992
storage_close()4993 int ha_mroonga::storage_close()
4994 {
4995 MRN_DBUG_ENTER_METHOD();
4996 grn_obj_unlink(ctx, grn_table);
4997 // TODO: unlink elements
4998 free(grn_columns);
4999 // TODO: unlink elements
5000 free(grn_column_ranges);
5001 DBUG_RETURN(0);
5002 }
5003
close()5004 int ha_mroonga::close()
5005 {
5006 int error = 0;
5007 THD *thd = ha_thd();
5008 MRN_DBUG_ENTER_METHOD();
5009
5010 clear_indexes();
5011
5012 if (share->wrapper_mode)
5013 {
5014 error = wrapper_close();
5015 } else {
5016 error = storage_close();
5017 }
5018
5019 if (error != 0)
5020 {
5021 DBUG_RETURN(error);
5022 }
5023
5024 if (thd)
5025 {
5026 error = add_wrap_hton(share->table_name, share->hton);
5027 }
5028 bitmap_free(&multiple_column_key_bitmap);
5029 if (share->use_count == 1) {
5030 mrn_free_long_term_share(share->long_term_share);
5031 }
5032 mrn_free_share(share);
5033 share = NULL;
5034 is_clone = false;
5035
5036 if (
5037 thd &&
5038 thd_sql_command(thd) == SQLCOM_FLUSH
5039 ) {
5040 /* flush tables */
5041 mrn::Lock lock(&mrn_open_tables_mutex);
5042 if (!mrn_open_tables.records)
5043 {
5044 int tmp_error = mrn_db_manager->clear();
5045 if (tmp_error)
5046 error = tmp_error;
5047 }
5048 }
5049 DBUG_RETURN(error);
5050 }
5051
wrapper_delete_table(const char * name,handlerton * wrap_handlerton,const char * table_name)5052 int ha_mroonga::wrapper_delete_table(const char *name,
5053 handlerton *wrap_handlerton,
5054 const char *table_name)
5055 {
5056 int error = 0;
5057 MRN_DBUG_ENTER_METHOD();
5058
5059 handler *hnd = get_new_handler(NULL, current_thd->mem_root, wrap_handlerton);
5060 if (!hnd)
5061 {
5062 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
5063 }
5064
5065 error = hnd->ha_delete_table(name);
5066 delete hnd;
5067
5068 DBUG_RETURN(error);
5069 }
5070
generic_delete_table(const char * name,const char * table_name)5071 int ha_mroonga::generic_delete_table(const char *name, const char *table_name)
5072 {
5073 int error = 0;
5074 MRN_DBUG_ENTER_METHOD();
5075
5076 error = ensure_database_open(name);
5077 if (error)
5078 DBUG_RETURN(error);
5079
5080 error = mrn_change_encoding(ctx, system_charset_info);
5081 if (error)
5082 DBUG_RETURN(error);
5083
5084 error = drop_indexes(table_name);
5085 grn_obj *table_obj = grn_ctx_get(ctx, table_name, strlen(table_name));
5086 if (table_obj) {
5087 grn_obj_remove(ctx, table_obj);
5088 }
5089 if (ctx->rc) {
5090 error = ER_CANT_OPEN_FILE;
5091 my_message(error, ctx->errbuf, MYF(0));
5092 DBUG_RETURN(error);
5093 }
5094 DBUG_RETURN(error);
5095 }
5096
delete_table(const char * name)5097 int ha_mroonga::delete_table(const char *name)
5098 {
5099 MRN_DBUG_ENTER_METHOD();
5100
5101 int error = 0;
5102 THD *thd = ha_thd();
5103 handlerton *wrap_handlerton = NULL;
5104 mrn::PathMapper mapper(name);
5105 st_mrn_slot_data *slot_data = mrn_get_slot_data(thd, false);
5106 if (slot_data && slot_data->first_wrap_hton)
5107 {
5108 st_mrn_wrap_hton *wrap_hton, *tmp_wrap_hton;
5109 tmp_wrap_hton = NULL;
5110 wrap_hton = slot_data->first_wrap_hton;
5111 while (wrap_hton)
5112 {
5113 if (!strcmp(wrap_hton->path, name))
5114 {
5115 /* found */
5116 wrap_handlerton = wrap_hton->hton;
5117 if (tmp_wrap_hton)
5118 tmp_wrap_hton->next = wrap_hton->next;
5119 else
5120 slot_data->first_wrap_hton = wrap_hton->next;
5121 free(wrap_hton);
5122 break;
5123 }
5124 tmp_wrap_hton = wrap_hton;
5125 wrap_hton = wrap_hton->next;
5126 }
5127 }
5128
5129 if (!wrap_handlerton) {
5130 bool open_table_to_get_wrap_handlerton = true;
5131 if (mapper.is_internal_table_name()) {
5132 open_table_to_get_wrap_handlerton = false;
5133 }
5134 if (open_table_to_get_wrap_handlerton) {
5135 TABLE_LIST table_list;
5136 LEX_CSTRING db_name= { mapper.db_name(), strlen(mapper.db_name()) };
5137 LEX_CSTRING table_name= { mapper.mysql_table_name(), strlen(mapper.mysql_table_name()) };
5138
5139 table_list.init_one_table(&db_name, &table_name, 0, TL_WRITE);
5140 mrn_open_mutex_lock(NULL);
5141 TABLE_SHARE *tmp_table_share =
5142 mrn_create_tmp_table_share(&table_list, name, &error);
5143 error = 0;
5144 mrn_open_mutex_unlock(NULL);
5145 if (tmp_table_share) {
5146 TABLE tmp_table;
5147 tmp_table.s = tmp_table_share;
5148 #ifdef WITH_PARTITION_STORAGE_ENGINE
5149 tmp_table.part_info = NULL;
5150 #endif
5151 MRN_SHARE *tmp_share = mrn_get_share(name, &tmp_table, &error);
5152 if (tmp_share) {
5153 wrap_handlerton = tmp_share->hton;
5154 mrn_free_long_term_share(tmp_share->long_term_share);
5155 tmp_share->long_term_share = NULL;
5156 mrn_free_share(tmp_share);
5157 }
5158 mrn_open_mutex_lock(NULL);
5159 mrn_free_tmp_table_share(tmp_table_share);
5160 mrn_open_mutex_unlock(NULL);
5161 if (error) {
5162 DBUG_RETURN(error);
5163 }
5164 }
5165 }
5166 }
5167
5168 if (wrap_handlerton)
5169 {
5170 error = wrapper_delete_table(name, wrap_handlerton, mapper.table_name());
5171 }
5172
5173 if (!error)
5174 {
5175 error = generic_delete_table(name, mapper.table_name());
5176 }
5177
5178 if (!error) {
5179 error = operations_->clear(name, strlen(name));
5180 }
5181
5182 DBUG_RETURN(error);
5183 }
5184
wrapper_set_keys_in_use()5185 void ha_mroonga::wrapper_set_keys_in_use()
5186 {
5187 uint i, j;
5188 MRN_DBUG_ENTER_METHOD();
5189 mrn::AutoIncrementValueLock lock_(table_share);
5190 table_share->keys_in_use.set_prefix(table_share->keys);
5191 share->disable_keys = false;
5192 for (i = 0; i < table_share->keys; i++) {
5193 j = share->wrap_key_nr[i];
5194 if (j < MAX_KEY) {
5195 if (!share->wrap_table_share->keys_in_use.is_set(j)) {
5196 /* copy bitmap */
5197 table_share->keys_in_use.clear_bit(i);
5198 share->disable_keys = true;
5199 }
5200 } else {
5201 if (!grn_index_tables || !grn_index_tables[i]) {
5202 /* disabled */
5203 table_share->keys_in_use.clear_bit(i);
5204 share->disable_keys = true;
5205 }
5206 }
5207 }
5208 table_share->keys_for_keyread.set_prefix(table_share->keys);
5209 table_share->keys_for_keyread.intersect(table_share->keys_in_use);
5210 DBUG_VOID_RETURN;
5211 }
5212
storage_set_keys_in_use()5213 void ha_mroonga::storage_set_keys_in_use()
5214 {
5215 uint i;
5216 MRN_DBUG_ENTER_METHOD();
5217 mrn::AutoIncrementValueLock lock_(table_share);
5218 table_share->keys_in_use.set_prefix(table_share->keys);
5219 share->disable_keys = false;
5220 for (i = 0; i < table_share->keys; i++) {
5221 if (i == table_share->primary_key) {
5222 continue;
5223 }
5224 if (!grn_index_tables[i]) {
5225 /* disabled */
5226 table_share->keys_in_use.clear_bit(i);
5227 DBUG_PRINT("info", ("mroonga: key %u disabled", i));
5228 share->disable_keys = true;
5229 }
5230 }
5231 table_share->keys_for_keyread.set_prefix(table_share->keys);
5232 table_share->keys_for_keyread.intersect(table_share->keys_in_use);
5233 DBUG_VOID_RETURN;
5234 }
5235
wrapper_info(uint flag)5236 int ha_mroonga::wrapper_info(uint flag)
5237 {
5238 int error = 0;
5239 MRN_DBUG_ENTER_METHOD();
5240
5241 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5242 MRN_SET_WRAP_TABLE_KEY(this, table);
5243 error = wrap_handler->info(flag);
5244 MRN_SET_BASE_SHARE_KEY(share, table->s);
5245 MRN_SET_BASE_TABLE_KEY(this, table);
5246 if (flag & HA_STATUS_ERRKEY) {
5247 errkey = wrap_handler->errkey;
5248 memcpy(dup_ref, wrap_handler->dup_ref, wrap_handler->ref_length);
5249 }
5250 if (flag & HA_STATUS_TIME) {
5251 stats.update_time = wrap_handler->stats.update_time;
5252 }
5253 if (flag & HA_STATUS_CONST) {
5254 stats.max_data_file_length = wrap_handler->stats.max_data_file_length;
5255 stats.create_time = wrap_handler->stats.create_time;
5256 stats.block_size = wrap_handler->stats.block_size;
5257 wrapper_set_keys_in_use();
5258 }
5259 if (flag & HA_STATUS_VARIABLE) {
5260 stats.data_file_length = wrap_handler->stats.data_file_length;
5261 stats.index_file_length = wrap_handler->stats.index_file_length;
5262 stats.records = wrap_handler->stats.records;
5263 stats.mean_rec_length = wrap_handler->stats.mean_rec_length;
5264 stats.check_time = wrap_handler->stats.check_time;
5265 }
5266 if (flag & HA_STATUS_AUTO) {
5267 stats.auto_increment_value = wrap_handler->stats.auto_increment_value;
5268 }
5269 DBUG_RETURN(error);
5270 }
5271
storage_info(uint flag)5272 int ha_mroonga::storage_info(uint flag)
5273 {
5274 MRN_DBUG_ENTER_METHOD();
5275 mrn_change_encoding(ctx, NULL);
5276
5277 if (flag & (HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK)) {
5278 errkey = dup_key;
5279 }
5280
5281 if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
5282 THD *thd = ha_thd();
5283 ulonglong nb_reserved_values;
5284 bool next_number_field_is_null = !table->next_number_field;
5285 mrn::ExternalLock mrn_external_lock(ha_thd(), this,
5286 mrn_lock_type == F_UNLCK ?
5287 F_RDLCK : F_UNLCK);
5288 if (mrn_external_lock.error()) {
5289 DBUG_RETURN(mrn_external_lock.error());
5290 }
5291 if (next_number_field_is_null) {
5292 table->next_number_field = table->found_next_number_field;
5293 }
5294 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
5295 {
5296 mrn::Lock lock(&long_term_share->auto_inc_mutex);
5297 unsigned long auto_increment_offset, auto_increment_increment;
5298 MRN_THD_GET_AUTOINC(thd, &auto_increment_offset,
5299 &auto_increment_increment);
5300 storage_get_auto_increment(auto_increment_offset,
5301 auto_increment_increment, 1,
5302 &stats.auto_increment_value,
5303 &nb_reserved_values);
5304 }
5305 if (next_number_field_is_null) {
5306 table->next_number_field = NULL;
5307 }
5308 }
5309
5310 if (flag & HA_STATUS_CONST) {
5311 storage_set_keys_in_use();
5312 }
5313
5314 if (flag & HA_STATUS_VARIABLE) {
5315 storage_info_variable();
5316 }
5317
5318 DBUG_RETURN(0);
5319 }
5320
storage_info_variable()5321 void ha_mroonga::storage_info_variable()
5322 {
5323 MRN_DBUG_ENTER_METHOD();
5324
5325 storage_info_variable_records();
5326 storage_info_variable_data_file_length();
5327
5328 DBUG_VOID_RETURN;
5329 }
5330
storage_info_variable_records()5331 void ha_mroonga::storage_info_variable_records()
5332 {
5333 MRN_DBUG_ENTER_METHOD();
5334
5335 stats.records = grn_table_size(ctx, grn_table);
5336
5337 DBUG_VOID_RETURN;
5338 }
5339
storage_info_variable_data_file_length()5340 void ha_mroonga::storage_info_variable_data_file_length()
5341 {
5342 MRN_DBUG_ENTER_METHOD();
5343
5344 stats.data_file_length = 0;
5345 stats.data_file_length += file_size(grn_obj_path(ctx, grn_table));
5346 grn_hash *columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
5347 GRN_OBJ_TABLE_HASH_KEY);
5348 grn_table_columns(ctx, grn_table, NULL, 0, (grn_obj *)columns);
5349 /* grn_id id __attribute__((unused)); */
5350 grn_id *column_id;
5351 GRN_HASH_EACH(ctx, columns, id, &column_id, NULL, NULL, {
5352 grn_obj *column = grn_ctx_at(ctx, *column_id);
5353 stats.data_file_length += file_size(grn_obj_path(ctx, column));
5354 grn_obj_unlink(ctx, column);
5355 });
5356 grn_hash_close(ctx, columns);
5357
5358 DBUG_VOID_RETURN;
5359 }
5360
info(uint flag)5361 int ha_mroonga::info(uint flag)
5362 {
5363 MRN_DBUG_ENTER_METHOD();
5364
5365 int error = 0;
5366 if (share->wrapper_mode)
5367 {
5368 error = wrapper_info(flag);
5369 } else {
5370 error = storage_info(flag);
5371 }
5372 DBUG_RETURN(error);
5373 }
5374
wrapper_lock_count() const5375 uint ha_mroonga::wrapper_lock_count() const
5376 {
5377 uint lock_count;
5378 MRN_DBUG_ENTER_METHOD();
5379 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5380 MRN_SET_WRAP_TABLE_KEY(this, table);
5381 lock_count = wrap_handler->lock_count();
5382 MRN_SET_BASE_SHARE_KEY(share, table->s);
5383 MRN_SET_BASE_TABLE_KEY(this, table);
5384 DBUG_RETURN(lock_count);
5385 }
5386
storage_lock_count() const5387 uint ha_mroonga::storage_lock_count() const
5388 {
5389 MRN_DBUG_ENTER_METHOD();
5390 DBUG_RETURN(1);
5391 }
5392
lock_count() const5393 uint ha_mroonga::lock_count() const
5394 {
5395 MRN_DBUG_ENTER_METHOD();
5396 int error = 0;
5397 if (share->wrapper_mode)
5398 {
5399 error = wrapper_lock_count();
5400 } else {
5401 error = storage_lock_count();
5402 }
5403 DBUG_RETURN(error);
5404 }
5405
wrapper_store_lock(THD * thd,THR_LOCK_DATA ** to,enum thr_lock_type lock_type)5406 THR_LOCK_DATA **ha_mroonga::wrapper_store_lock(THD *thd, THR_LOCK_DATA **to,
5407 enum thr_lock_type lock_type)
5408 {
5409 MRN_DBUG_ENTER_METHOD();
5410 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5411 MRN_SET_WRAP_TABLE_KEY(this, table);
5412 to = wrap_handler->store_lock(thd, to, lock_type);
5413 MRN_SET_BASE_SHARE_KEY(share, table->s);
5414 MRN_SET_BASE_TABLE_KEY(this, table);
5415 DBUG_RETURN(to);
5416 }
5417
storage_store_lock(THD * thd,THR_LOCK_DATA ** to,enum thr_lock_type lock_type)5418 THR_LOCK_DATA **ha_mroonga::storage_store_lock(THD *thd, THR_LOCK_DATA **to,
5419 enum thr_lock_type lock_type)
5420 {
5421 MRN_DBUG_ENTER_METHOD();
5422 if (lock_type != TL_IGNORE && thr_lock_data.type == TL_UNLOCK) {
5423 if (!thd_in_lock_tables(thd)) {
5424 if (lock_type == TL_READ_NO_INSERT) {
5425 lock_type = TL_READ;
5426 } else if (lock_type >= TL_WRITE_CONCURRENT_INSERT &&
5427 lock_type <= TL_WRITE && !thd_tablespace_op(thd)) {
5428 lock_type = TL_WRITE_ALLOW_WRITE;
5429 }
5430 }
5431
5432 thr_lock_data.type = lock_type;
5433 }
5434 *to++ = &thr_lock_data;
5435 DBUG_RETURN(to);
5436 }
5437
store_lock(THD * thd,THR_LOCK_DATA ** to,enum thr_lock_type lock_type)5438 THR_LOCK_DATA **ha_mroonga::store_lock(THD *thd, THR_LOCK_DATA **to,
5439 enum thr_lock_type lock_type)
5440 {
5441 MRN_DBUG_ENTER_METHOD();
5442 DBUG_PRINT("info", ("mroonga: lock_type=%s",
5443 mrn_inspect_thr_lock_type(lock_type)));
5444 if (share->wrapper_mode)
5445 to = wrapper_store_lock(thd, to, lock_type);
5446 else
5447 to = storage_store_lock(thd, to, lock_type);
5448 DBUG_RETURN(to);
5449 }
5450
wrapper_external_lock(THD * thd,int lock_type)5451 int ha_mroonga::wrapper_external_lock(THD *thd, int lock_type)
5452 {
5453 int error = 0;
5454 MRN_DBUG_ENTER_METHOD();
5455 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5456 MRN_SET_WRAP_TABLE_KEY(this, table);
5457 error = wrap_handler->ha_external_lock(thd, lock_type);
5458 MRN_SET_BASE_SHARE_KEY(share, table->s);
5459 MRN_SET_BASE_TABLE_KEY(this, table);
5460 DBUG_RETURN(error);
5461 }
5462
storage_external_lock(THD * thd,int lock_type)5463 int ha_mroonga::storage_external_lock(THD *thd, int lock_type)
5464 {
5465 MRN_DBUG_ENTER_METHOD();
5466 DBUG_RETURN(0);
5467 }
5468
external_lock(THD * thd,int lock_type)5469 int ha_mroonga::external_lock(THD *thd, int lock_type)
5470 {
5471 MRN_DBUG_ENTER_METHOD();
5472 int error = 0;
5473 mrn_lock_type = lock_type;
5474 if (share->wrapper_mode)
5475 {
5476 error = wrapper_external_lock(thd, lock_type);
5477 } else {
5478 error = storage_external_lock(thd, lock_type);
5479 }
5480 DBUG_RETURN(error);
5481 }
5482
wrapper_rnd_init(bool scan)5483 int ha_mroonga::wrapper_rnd_init(bool scan)
5484 {
5485 int error = 0;
5486 MRN_DBUG_ENTER_METHOD();
5487 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5488 MRN_SET_WRAP_TABLE_KEY(this, table);
5489 error = wrap_handler->ha_rnd_init(scan);
5490 MRN_SET_BASE_SHARE_KEY(share, table->s);
5491 MRN_SET_BASE_TABLE_KEY(this, table);
5492 DBUG_RETURN(error);
5493 }
5494
storage_rnd_init(bool scan)5495 int ha_mroonga::storage_rnd_init(bool scan)
5496 {
5497 MRN_DBUG_ENTER_METHOD();
5498 mrn_change_encoding(ctx, NULL);
5499 cursor = grn_table_cursor_open(ctx, grn_table, NULL, 0, NULL, 0, 0, -1, 0);
5500 if (ctx->rc) {
5501 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
5502 DBUG_RETURN(ER_ERROR_ON_READ);
5503 }
5504 DBUG_RETURN(0);
5505 }
5506
rnd_init(bool scan)5507 int ha_mroonga::rnd_init(bool scan)
5508 {
5509 MRN_DBUG_ENTER_METHOD();
5510 int error = 0;
5511 if (share->wrapper_mode)
5512 {
5513 error = wrapper_rnd_init(scan);
5514 } else {
5515 error = storage_rnd_init(scan);
5516 }
5517 DBUG_RETURN(error);
5518 }
5519
wrapper_rnd_end()5520 int ha_mroonga::wrapper_rnd_end()
5521 {
5522 int error = 0;
5523 MRN_DBUG_ENTER_METHOD();
5524 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5525 MRN_SET_WRAP_TABLE_KEY(this, table);
5526 error = wrap_handler->ha_rnd_end();
5527 MRN_SET_BASE_SHARE_KEY(share, table->s);
5528 MRN_SET_BASE_TABLE_KEY(this, table);
5529 DBUG_RETURN(error);
5530 }
5531
storage_rnd_end()5532 int ha_mroonga::storage_rnd_end()
5533 {
5534 MRN_DBUG_ENTER_METHOD();
5535 clear_cursor();
5536 DBUG_RETURN(0);
5537 }
5538
rnd_end()5539 int ha_mroonga::rnd_end()
5540 {
5541 MRN_DBUG_ENTER_METHOD();
5542 int error = 0;
5543 if (share->wrapper_mode)
5544 {
5545 error = wrapper_rnd_end();
5546 } else {
5547 error = storage_rnd_end();
5548 }
5549 DBUG_RETURN(error);
5550 }
5551
5552 #ifdef MRN_HANDLER_RECORDS_RETURN_ERROR
wrapper_records(ha_rows * num_rows)5553 int ha_mroonga::wrapper_records(ha_rows *num_rows)
5554 {
5555 int error = 0;
5556 MRN_DBUG_ENTER_METHOD();
5557 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5558 MRN_SET_WRAP_TABLE_KEY(this, table);
5559 error = wrap_handler->ha_records(num_rows);
5560 MRN_SET_BASE_SHARE_KEY(share, table->s);
5561 MRN_SET_BASE_TABLE_KEY(this, table);
5562 DBUG_RETURN(error);
5563 }
5564
storage_records(ha_rows * num_rows)5565 int ha_mroonga::storage_records(ha_rows *num_rows)
5566 {
5567 MRN_DBUG_ENTER_METHOD();
5568 int error = handler::records(num_rows);
5569 DBUG_RETURN(error);
5570 }
5571
records(ha_rows * num_rows)5572 int ha_mroonga::records(ha_rows *num_rows)
5573 {
5574 MRN_DBUG_ENTER_METHOD();
5575 int error = 0;
5576 if (share->wrapper_mode) {
5577 error = wrapper_records(num_rows);
5578 } else {
5579 error = storage_records(num_rows);
5580 }
5581 DBUG_RETURN(error);
5582 }
5583 #else
wrapper_records()5584 ha_rows ha_mroonga::wrapper_records()
5585 {
5586 ha_rows num_rows;
5587 MRN_DBUG_ENTER_METHOD();
5588 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5589 MRN_SET_WRAP_TABLE_KEY(this, table);
5590 num_rows = wrap_handler->records();
5591 MRN_SET_BASE_SHARE_KEY(share, table->s);
5592 MRN_SET_BASE_TABLE_KEY(this, table);
5593 DBUG_RETURN(num_rows);
5594 }
5595
storage_records()5596 ha_rows ha_mroonga::storage_records()
5597 {
5598 MRN_DBUG_ENTER_METHOD();
5599 ha_rows num_rows = handler::records();
5600 DBUG_RETURN(num_rows);
5601 }
5602
records()5603 ha_rows ha_mroonga::records()
5604 {
5605 MRN_DBUG_ENTER_METHOD();
5606 ha_rows num_rows;
5607 if (share->wrapper_mode) {
5608 num_rows = wrapper_records();
5609 } else {
5610 num_rows = storage_records();
5611 }
5612 DBUG_RETURN(num_rows);
5613 }
5614 #endif
5615
wrapper_rnd_next(uchar * buf)5616 int ha_mroonga::wrapper_rnd_next(uchar *buf)
5617 {
5618 int error = 0;
5619 MRN_DBUG_ENTER_METHOD();
5620 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5621 MRN_SET_WRAP_TABLE_KEY(this, table);
5622 if (fulltext_searching)
5623 set_pk_bitmap();
5624 #ifdef MRN_HANDLER_HAVE_HA_RND_NEXT
5625 error = wrap_handler->ha_rnd_next(buf);
5626 #else
5627 error = wrap_handler->rnd_next(buf);
5628 #endif
5629 MRN_SET_BASE_SHARE_KEY(share, table->s);
5630 MRN_SET_BASE_TABLE_KEY(this, table);
5631 DBUG_RETURN(error);
5632 }
5633
storage_rnd_next(uchar * buf)5634 int ha_mroonga::storage_rnd_next(uchar *buf)
5635 {
5636 MRN_DBUG_ENTER_METHOD();
5637 int error = storage_get_next_record(buf);
5638 DBUG_RETURN(error);
5639 }
5640
rnd_next(uchar * buf)5641 int ha_mroonga::rnd_next(uchar *buf)
5642 {
5643 MRN_DBUG_ENTER_METHOD();
5644 int error = 0;
5645 if (share->wrapper_mode)
5646 {
5647 error = wrapper_rnd_next(buf);
5648 } else {
5649 error = storage_rnd_next(buf);
5650 }
5651 DBUG_RETURN(error);
5652 }
5653
wrapper_rnd_pos(uchar * buf,uchar * pos)5654 int ha_mroonga::wrapper_rnd_pos(uchar *buf, uchar *pos)
5655 {
5656 int error = 0;
5657 MRN_DBUG_ENTER_METHOD();
5658 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5659 MRN_SET_WRAP_TABLE_KEY(this, table);
5660 #ifdef MRN_HANDLER_HAVE_HA_RND_POS
5661 error = wrap_handler->ha_rnd_pos(buf, pos);
5662 #else
5663 error = wrap_handler->rnd_pos(buf, pos);
5664 #endif
5665 MRN_SET_BASE_SHARE_KEY(share, table->s);
5666 MRN_SET_BASE_TABLE_KEY(this, table);
5667 DBUG_RETURN(error);
5668 }
5669
storage_rnd_pos(uchar * buf,uchar * pos)5670 int ha_mroonga::storage_rnd_pos(uchar *buf, uchar *pos)
5671 {
5672 MRN_DBUG_ENTER_METHOD();
5673 record_id = *((grn_id*) pos);
5674 storage_store_fields(buf, record_id);
5675 DBUG_RETURN(0);
5676 }
5677
rnd_pos(uchar * buf,uchar * pos)5678 int ha_mroonga::rnd_pos(uchar *buf, uchar *pos)
5679 {
5680 MRN_DBUG_ENTER_METHOD();
5681 int error = 0;
5682 if (share->wrapper_mode)
5683 {
5684 error = wrapper_rnd_pos(buf, pos);
5685 } else {
5686 error = storage_rnd_pos(buf, pos);
5687 }
5688 DBUG_RETURN(error);
5689 }
5690
wrapper_position(const uchar * record)5691 void ha_mroonga::wrapper_position(const uchar *record)
5692 {
5693 MRN_DBUG_ENTER_METHOD();
5694 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5695 MRN_SET_WRAP_TABLE_KEY(this, table);
5696 wrap_handler->ref = ref;
5697 wrap_handler->position(record);
5698 MRN_SET_BASE_SHARE_KEY(share, table->s);
5699 MRN_SET_BASE_TABLE_KEY(this, table);
5700 DBUG_VOID_RETURN;
5701 }
5702
storage_position(const uchar * record)5703 void ha_mroonga::storage_position(const uchar *record)
5704 {
5705 MRN_DBUG_ENTER_METHOD();
5706 memcpy(ref, &record_id, sizeof(grn_id));
5707 DBUG_VOID_RETURN;
5708 }
5709
position(const uchar * record)5710 void ha_mroonga::position(const uchar *record)
5711 {
5712 MRN_DBUG_ENTER_METHOD();
5713 if (share->wrapper_mode)
5714 wrapper_position(record);
5715 else
5716 storage_position(record);
5717 DBUG_VOID_RETURN;
5718 }
5719
generic_extra(enum ha_extra_function operation)5720 int ha_mroonga::generic_extra(enum ha_extra_function operation)
5721 {
5722 MRN_DBUG_ENTER_METHOD();
5723 switch (operation) {
5724 case HA_EXTRA_IGNORE_DUP_KEY:
5725 ignoring_duplicated_key = true;
5726 break;
5727 case HA_EXTRA_NO_IGNORE_DUP_KEY:
5728 ignoring_duplicated_key = false;
5729 break;
5730 case HA_EXTRA_WRITE_CAN_REPLACE:
5731 replacing_ = true;
5732 break;
5733 case HA_EXTRA_WRITE_CANNOT_REPLACE:
5734 replacing_ = false;
5735 break;
5736 case HA_EXTRA_INSERT_WITH_UPDATE:
5737 inserting_with_update = true;
5738 break;
5739 case HA_EXTRA_KEYREAD:
5740 ignoring_no_key_columns = true;
5741 break;
5742 case HA_EXTRA_NO_KEYREAD:
5743 ignoring_no_key_columns = false;
5744 break;
5745 default:
5746 break;
5747 }
5748 DBUG_RETURN(0);
5749 }
5750
wrapper_extra(enum ha_extra_function operation)5751 int ha_mroonga::wrapper_extra(enum ha_extra_function operation)
5752 {
5753 int error = 0;
5754 MRN_DBUG_ENTER_METHOD();
5755 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5756 MRN_SET_WRAP_TABLE_KEY(this, table);
5757 error = wrap_handler->extra(operation);
5758 MRN_SET_BASE_SHARE_KEY(share, table->s);
5759 MRN_SET_BASE_TABLE_KEY(this, table);
5760 DBUG_RETURN(error);
5761 }
5762
storage_extra(enum ha_extra_function operation)5763 int ha_mroonga::storage_extra(enum ha_extra_function operation)
5764 {
5765 MRN_DBUG_ENTER_METHOD();
5766 DBUG_RETURN(0);
5767 }
5768
extra(enum ha_extra_function operation)5769 int ha_mroonga::extra(enum ha_extra_function operation)
5770 {
5771 int error = 0;
5772 MRN_DBUG_ENTER_METHOD();
5773 DBUG_PRINT("info",
5774 ("mroonga: this=%p; extra-operation=%s",
5775 this, mrn_inspect_extra_function(operation)));
5776 if (share->wrapper_mode) {
5777 if ((error = wrapper_extra(operation)))
5778 DBUG_RETURN(error);
5779 } else {
5780 if ((error = storage_extra(operation)))
5781 DBUG_RETURN(error);
5782 }
5783 error = generic_extra(operation);
5784 DBUG_RETURN(error);
5785 }
5786
wrapper_extra_opt(enum ha_extra_function operation,ulong cache_size)5787 int ha_mroonga::wrapper_extra_opt(enum ha_extra_function operation,
5788 ulong cache_size)
5789 {
5790 int error = 0;
5791 MRN_DBUG_ENTER_METHOD();
5792 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5793 MRN_SET_WRAP_TABLE_KEY(this, table);
5794 error = wrap_handler->extra_opt(operation, cache_size);
5795 MRN_SET_BASE_SHARE_KEY(share, table->s);
5796 MRN_SET_BASE_TABLE_KEY(this, table);
5797 DBUG_RETURN(error);
5798 }
5799
storage_extra_opt(enum ha_extra_function operation,ulong cache_size)5800 int ha_mroonga::storage_extra_opt(enum ha_extra_function operation,
5801 ulong cache_size)
5802 {
5803 MRN_DBUG_ENTER_METHOD();
5804 DBUG_RETURN(0);
5805 }
5806
extra_opt(enum ha_extra_function operation,ulong cache_size)5807 int ha_mroonga::extra_opt(enum ha_extra_function operation, ulong cache_size)
5808 {
5809 int error = 0;
5810 MRN_DBUG_ENTER_METHOD();
5811 if (share->wrapper_mode)
5812 {
5813 if ((error = wrapper_extra_opt(operation, cache_size)))
5814 DBUG_RETURN(error);
5815 } else {
5816 if ((error = storage_extra_opt(operation, cache_size)))
5817 DBUG_RETURN(error);
5818 }
5819 error = generic_extra(operation);
5820 DBUG_RETURN(error);
5821 }
5822
wrapper_is_target_index(KEY * key_info)5823 bool ha_mroonga::wrapper_is_target_index(KEY *key_info)
5824 {
5825 MRN_DBUG_ENTER_METHOD();
5826 bool target_index =
5827 (key_info->algorithm == HA_KEY_ALG_FULLTEXT) || mrn_is_geo_key(key_info);
5828 DBUG_PRINT("info", ("mroonga: %s", target_index ? "true" : "false"));
5829 DBUG_RETURN(target_index);
5830 }
5831
wrapper_have_target_index()5832 bool ha_mroonga::wrapper_have_target_index()
5833 {
5834 MRN_DBUG_ENTER_METHOD();
5835
5836 bool have_target_index = false;
5837
5838 uint i;
5839 uint n_keys = table->s->keys;
5840 for (i = 0; i < n_keys; i++) {
5841 KEY *key_info = &(table->key_info[i]);
5842
5843 if (wrapper_is_target_index(key_info)) {
5844 have_target_index = true;
5845 break;
5846 }
5847 }
5848
5849 DBUG_PRINT("info", ("mroonga: %s", have_target_index ? "true" : "false"));
5850 DBUG_RETURN(have_target_index);
5851 }
5852
wrapper_write_row(uchar * buf)5853 int ha_mroonga::wrapper_write_row(uchar *buf)
5854 {
5855 int error = 0;
5856 THD *thd = ha_thd();
5857
5858 MRN_DBUG_ENTER_METHOD();
5859
5860 mrn::Operation operation(operations_,
5861 "write",
5862 table->s->table_name.str,
5863 table->s->table_name.length);
5864
5865 operation.record_target(record_id);
5866 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5867 MRN_SET_WRAP_TABLE_KEY(this, table);
5868 tmp_disable_binlog(thd);
5869 error = wrap_handler->ha_write_row(buf);
5870 insert_id_for_cur_row = wrap_handler->insert_id_for_cur_row;
5871 reenable_binlog(thd);
5872 MRN_SET_BASE_SHARE_KEY(share, table->s);
5873 MRN_SET_BASE_TABLE_KEY(this, table);
5874
5875 if (!error && wrapper_have_target_index()) {
5876 error = wrapper_write_row_index(buf);
5877 }
5878
5879 DBUG_RETURN(error);
5880 }
5881
wrapper_write_row_index(uchar * buf)5882 int ha_mroonga::wrapper_write_row_index(uchar *buf)
5883 {
5884 MRN_DBUG_ENTER_METHOD();
5885
5886 int error = 0;
5887
5888 if (is_dry_write()) {
5889 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
5890 DBUG_RETURN(error);
5891 }
5892
5893 mrn_change_encoding(ctx, NULL);
5894 GRN_BULK_REWIND(&key_buffer);
5895 grn_bulk_space(ctx, &key_buffer, table->key_info->key_length);
5896 key_copy((uchar *)(GRN_TEXT_VALUE(&key_buffer)),
5897 buf,
5898 &(table->key_info[table_share->primary_key]),
5899 table->key_info[table_share->primary_key].key_length);
5900
5901 int added;
5902 grn_id record_id;
5903 record_id = grn_table_add(ctx, grn_table,
5904 GRN_TEXT_VALUE(&key_buffer),
5905 GRN_TEXT_LEN(&key_buffer),
5906 &added);
5907 if (record_id == GRN_ID_NIL) {
5908 DBUG_PRINT("info", ("mroonga: failed to add a new record into groonga"));
5909 char error_message[MRN_MESSAGE_BUFFER_SIZE];
5910 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
5911 "failed to add a new record into groonga: key=<%.*s>",
5912 (int)GRN_TEXT_LEN(&key_buffer),
5913 GRN_TEXT_VALUE(&key_buffer));
5914 error = ER_ERROR_ON_WRITE;
5915 push_warning(ha_thd(), MRN_SEVERITY_WARNING, error,
5916 error_message);
5917 DBUG_RETURN(0);
5918 }
5919
5920 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
5921 uint i;
5922 uint n_keys = table->s->keys;
5923 for (i = 0; i < n_keys; i++) {
5924 KEY *key_info = &(table->key_info[i]);
5925
5926 if (!(wrapper_is_target_index(key_info))) {
5927 continue;
5928 }
5929
5930 grn_obj *index_column = grn_index_columns[i];
5931 if (!index_column) {
5932 continue;
5933 }
5934
5935 uint j;
5936 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
5937 Field *field = key_info->key_part[j].field;
5938
5939 if (field->is_null())
5940 continue;
5941
5942 error = mrn_change_encoding(ctx, field->charset());
5943 if (error)
5944 goto err;
5945 error = generic_store_bulk(field, &new_value_buffer);
5946 if (error) {
5947 my_message(error,
5948 "mroonga: wrapper: "
5949 "failed to get new value for updating index.",
5950 MYF(0));
5951 goto err;
5952 }
5953
5954 grn_rc rc;
5955 rc = grn_column_index_update(ctx, index_column, record_id, j + 1,
5956 NULL, &new_value_buffer);
5957 if (rc) {
5958 error = ER_ERROR_ON_WRITE;
5959 my_message(error, ctx->errbuf, MYF(0));
5960 goto err;
5961 }
5962 }
5963 }
5964 err:
5965
5966 DBUG_RETURN(error);
5967 }
5968
storage_write_row(uchar * buf)5969 int ha_mroonga::storage_write_row(uchar *buf)
5970 {
5971 MRN_DBUG_ENTER_METHOD();
5972 int error = 0;
5973 bool unique_indexes_are_processed = false;
5974
5975 if (is_dry_write()) {
5976 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
5977 DBUG_RETURN(error);
5978 }
5979
5980 mrn::Operation operation(operations_,
5981 "write",
5982 table->s->table_name.str,
5983 table->s->table_name.length);
5984
5985 THD *thd = ha_thd();
5986 int i;
5987 int n_columns = table->s->fields;
5988
5989 if (table->next_number_field && buf == table->record[0])
5990 {
5991 if ((error = update_auto_increment()))
5992 DBUG_RETURN(error);
5993 }
5994
5995 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
5996 for (i = 0; i < n_columns; i++) {
5997 Field *field = table->field[i];
5998
5999 #ifdef MRN_SUPPORT_GENERATED_COLUMNS
6000 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
6001 continue;
6002 }
6003 #endif
6004
6005 if (field->is_null()) continue;
6006
6007 mrn::ColumnName column_name(field->field_name);
6008 if (strcmp(MRN_COLUMN_NAME_ID, column_name.c_str()) == 0) {
6009 push_warning_printf(thd, MRN_SEVERITY_WARNING,
6010 WARN_DATA_TRUNCATED,
6011 MRN_GET_ERR_MSG(WARN_DATA_TRUNCATED),
6012 MRN_COLUMN_NAME_ID,
6013 MRN_GET_CURRENT_ROW_FOR_WARNING(thd));
6014 if (MRN_ABORT_ON_WARNING(thd)) {
6015 DBUG_RETURN(ER_DATA_TOO_LONG);
6016 }
6017 }
6018 }
6019
6020 uint pkey_nr = table->s->primary_key;
6021
6022 int added = 0;
6023 {
6024 mrn::Lock lock(&(share->record_mutex), have_unique_index());
6025 if ((error = storage_write_row_unique_indexes(buf)))
6026 {
6027 DBUG_RETURN(error);
6028 }
6029 unique_indexes_are_processed = true;
6030
6031 char *pkey;
6032 int pkey_size;
6033 GRN_BULK_REWIND(&key_buffer);
6034 if (pkey_nr == MAX_INDEXES) {
6035 pkey = NULL;
6036 pkey_size = 0;
6037 } else {
6038 KEY *key_info = &(table->key_info[pkey_nr]);
6039 if (KEY_N_KEY_PARTS(key_info) == 1) {
6040 Field *pkey_field = key_info->key_part[0].field;
6041 error = mrn_change_encoding(ctx, pkey_field->charset());
6042 if (error) {
6043 DBUG_RETURN(error);
6044 }
6045 generic_store_bulk(pkey_field, &key_buffer);
6046 pkey = GRN_TEXT_VALUE(&key_buffer);
6047 pkey_size = GRN_TEXT_LEN(&key_buffer);
6048 } else {
6049 mrn_change_encoding(ctx, NULL);
6050 uchar key[MRN_MAX_KEY_SIZE];
6051 key_copy(key, buf, key_info, key_info->key_length);
6052 grn_bulk_reserve(ctx, &key_buffer, MRN_MAX_KEY_SIZE);
6053 pkey = GRN_TEXT_VALUE(&key_buffer);
6054 storage_encode_multiple_column_key(key_info,
6055 key, key_info->key_length,
6056 (uchar *)pkey, (uint *)&pkey_size);
6057 }
6058 }
6059
6060 if (grn_table->header.type != GRN_TABLE_NO_KEY && pkey_size == 0) {
6061 my_message(ER_ERROR_ON_WRITE, "primary key is empty", MYF(0));
6062 DBUG_RETURN(ER_ERROR_ON_WRITE);
6063 }
6064
6065 record_id = grn_table_add(ctx, grn_table, pkey, pkey_size, &added);
6066 if (ctx->rc) {
6067 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
6068 DBUG_RETURN(ER_ERROR_ON_WRITE);
6069 }
6070 if (!added) {
6071 // duplicated error
6072 error = HA_ERR_FOUND_DUPP_KEY;
6073 memcpy(dup_ref, &record_id, sizeof(grn_id));
6074 dup_key = pkey_nr;
6075 if (!ignoring_duplicated_key) {
6076 GRN_LOG(ctx, GRN_LOG_ERROR,
6077 "duplicated id on insert: update primary key: <%.*s>",
6078 pkey_size, pkey);
6079 }
6080 uint j;
6081 for (j = 0; j < table->s->keys; j++) {
6082 if (j == pkey_nr) {
6083 continue;
6084 }
6085 KEY *key_info = &table->key_info[j];
6086 if (key_info->flags & HA_NOSAME) {
6087 grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]);
6088 }
6089 }
6090 DBUG_RETURN(error);
6091 }
6092 operation.record_target(record_id);
6093 }
6094
6095 grn_obj colbuf;
6096 GRN_VOID_INIT(&colbuf);
6097 for (i = 0; i < n_columns; i++) {
6098 Field *field = table->field[i];
6099
6100 if (field->is_null())
6101 continue;
6102
6103 #ifdef MRN_SUPPORT_GENERATED_COLUMNS
6104 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
6105 continue;
6106 }
6107 #endif
6108
6109 mrn::ColumnName column_name(field->field_name);
6110
6111 #ifdef MRN_HAVE_SPATIAL
6112 bool is_null_geometry_value =
6113 field->real_type() == MYSQL_TYPE_GEOMETRY &&
6114 static_cast<Field_geom *>(field)->get_length() == 0;
6115 if (is_null_geometry_value) {
6116 continue;
6117 }
6118 #endif
6119
6120 if (strcmp(MRN_COLUMN_NAME_ID, column_name.c_str()) == 0) {
6121 continue;
6122 }
6123
6124 error = mrn_change_encoding(ctx, field->charset());
6125 if (error) {
6126 GRN_OBJ_FIN(ctx, &colbuf);
6127 goto err;
6128 }
6129 error = generic_store_bulk(field, &colbuf);
6130 if (error) {
6131 GRN_OBJ_FIN(ctx, &colbuf);
6132 goto err;
6133 }
6134
6135 grn_obj *column = grn_columns[i];
6136 if (is_foreign_key_field(table->s->table_name.str, field->field_name.str)) {
6137 grn_obj value;
6138 GRN_RECORD_INIT(&value, 0, grn_obj_get_range(ctx, column));
6139 grn_rc cast_rc = grn_obj_cast(ctx, &colbuf, &value, GRN_FALSE);
6140 if (cast_rc != GRN_SUCCESS) {
6141 grn_obj inspected;
6142 GRN_TEXT_INIT(&inspected, 0);
6143 grn_inspect(ctx, &inspected, &colbuf);
6144 error = HA_ERR_NO_REFERENCED_ROW;
6145 GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
6146 "foreign record doesn't exist: <%s>:<%.*s>",
6147 field->field_name.str,
6148 static_cast<int>(GRN_TEXT_LEN(&inspected)),
6149 GRN_TEXT_VALUE(&inspected));
6150 GRN_OBJ_FIN(ctx, &value);
6151 GRN_OBJ_FIN(ctx, &colbuf);
6152 GRN_OBJ_FIN(ctx, &inspected);
6153 goto err;
6154 }
6155 grn_obj_set_value(ctx, column, record_id, &value, GRN_OBJ_SET);
6156 } else {
6157 if (added && is_grn_zero_column_value(column, &colbuf)) {
6158 // WORKAROUND: groonga can't index newly added '0' value for
6159 // fix size column. So we add non-'0' value first then add
6160 // real '0' value again. It will be removed when groonga
6161 // supports 'null' value.
6162 char *bytes = GRN_BULK_HEAD(&colbuf);
6163 bytes[0] = '\1';
6164 grn_obj_set_value(ctx, column, record_id, &colbuf, GRN_OBJ_SET);
6165 bytes[0] = '\0';
6166 }
6167 grn_obj_set_value(ctx, column, record_id, &colbuf, GRN_OBJ_SET);
6168 }
6169 if (ctx->rc) {
6170 GRN_OBJ_FIN(ctx, &colbuf);
6171 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
6172 error = ER_ERROR_ON_WRITE;
6173 goto err;
6174 }
6175 }
6176 GRN_OBJ_FIN(ctx, &colbuf);
6177
6178 error = storage_write_row_multiple_column_indexes(buf, record_id);
6179 if (error) {
6180 goto err;
6181 }
6182
6183 // for UDF last_insert_grn_id()
6184 st_mrn_slot_data *slot_data;
6185 slot_data = mrn_get_slot_data(thd, true);
6186 if (slot_data == NULL) {
6187 error = HA_ERR_OUT_OF_MEM;
6188 goto err;
6189 }
6190 slot_data->last_insert_record_id = record_id;
6191
6192 grn_db_touch(ctx, grn_ctx_db(ctx));
6193
6194 if (table->found_next_number_field &&
6195 !table->s->next_number_keypart) {
6196 Field_num *field = (Field_num *) table->found_next_number_field;
6197 if (field->unsigned_flag || field->val_int() > 0) {
6198 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
6199 ulonglong nr = (ulonglong) field->val_int();
6200 if (!long_term_share->auto_inc_inited) {
6201 storage_info(HA_STATUS_AUTO);
6202 }
6203 {
6204 mrn::Lock lock(&long_term_share->auto_inc_mutex);
6205 if (long_term_share->auto_inc_value <= nr) {
6206 long_term_share->auto_inc_value = nr + 1;
6207 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
6208 long_term_share->auto_inc_value));
6209 }
6210 }
6211 }
6212 }
6213 DBUG_RETURN(0);
6214
6215 err:
6216 if (unique_indexes_are_processed) {
6217 uint j;
6218 for (j = 0; j < table->s->keys; j++) {
6219 if (j == pkey_nr) {
6220 continue;
6221 }
6222 KEY *key_info = &table->key_info[j];
6223 if (key_info->flags & HA_NOSAME) {
6224 grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]);
6225 }
6226 }
6227 }
6228 grn_table_delete_by_id(ctx, grn_table, record_id);
6229 DBUG_RETURN(error);
6230 }
6231
storage_write_row_multiple_column_index(uchar * buf,grn_id record_id,KEY * key_info,grn_obj * index_column)6232 int ha_mroonga::storage_write_row_multiple_column_index(uchar *buf,
6233 grn_id record_id,
6234 KEY *key_info,
6235 grn_obj *index_column)
6236 {
6237 MRN_DBUG_ENTER_METHOD();
6238 int error = 0;
6239
6240 mrn_change_encoding(ctx, NULL);
6241 GRN_BULK_REWIND(&key_buffer);
6242 grn_bulk_space(ctx, &key_buffer, key_info->key_length);
6243 key_copy((uchar *)(GRN_TEXT_VALUE(&key_buffer)),
6244 buf,
6245 key_info,
6246 key_info->key_length);
6247 GRN_BULK_REWIND(&encoded_key_buffer);
6248 grn_bulk_reserve(ctx, &encoded_key_buffer, MRN_MAX_KEY_SIZE);
6249 uint encoded_key_length;
6250 storage_encode_multiple_column_key(key_info,
6251 (uchar *)(GRN_TEXT_VALUE(&key_buffer)),
6252 key_info->key_length,
6253 (uchar *)(GRN_TEXT_VALUE(&encoded_key_buffer)),
6254 &encoded_key_length);
6255 grn_bulk_space(ctx, &encoded_key_buffer, encoded_key_length);
6256 DBUG_PRINT("info", ("mroonga: key_length=%u", key_info->key_length));
6257 DBUG_PRINT("info", ("mroonga: encoded_key_length=%u", encoded_key_length));
6258
6259 grn_rc rc;
6260 rc = grn_column_index_update(ctx, index_column, record_id, 1, NULL,
6261 &encoded_key_buffer);
6262 if (rc) {
6263 error = ER_ERROR_ON_WRITE;
6264 my_message(error, ctx->errbuf, MYF(0));
6265 }
6266 DBUG_RETURN(error);
6267 }
6268
storage_write_row_multiple_column_indexes(uchar * buf,grn_id record_id)6269 int ha_mroonga::storage_write_row_multiple_column_indexes(uchar *buf,
6270 grn_id record_id)
6271 {
6272 MRN_DBUG_ENTER_METHOD();
6273
6274 int error = 0;
6275
6276 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
6277 uint i;
6278 uint n_keys = table->s->keys;
6279 for (i = 0; i < n_keys; i++) {
6280 if (i == table->s->primary_key) {
6281 continue;
6282 }
6283
6284 KEY *key_info = &(table->key_info[i]);
6285
6286 if (KEY_N_KEY_PARTS(key_info) == 1 || (key_info->flags & HA_FULLTEXT)) {
6287 continue;
6288 }
6289
6290 grn_obj *index_column = grn_index_columns[i];
6291 if (!index_column) {
6292 continue;
6293 }
6294
6295 if ((error = storage_write_row_multiple_column_index(buf,
6296 record_id,
6297 key_info,
6298 index_column)))
6299 {
6300 goto err;
6301 }
6302 }
6303
6304 err:
6305
6306 DBUG_RETURN(error);
6307 }
6308
storage_write_row_unique_index(const uchar * buf,KEY * key_info,grn_obj * index_table,grn_obj * index_column,grn_id * key_id)6309 int ha_mroonga::storage_write_row_unique_index(const uchar *buf,
6310 KEY *key_info,
6311 grn_obj *index_table,
6312 grn_obj *index_column,
6313 grn_id *key_id)
6314 {
6315 char *ukey = NULL;
6316 int error, ukey_size = 0;
6317 MRN_DBUG_ENTER_METHOD();
6318 GRN_BULK_REWIND(&key_buffer);
6319 if (KEY_N_KEY_PARTS(key_info) == 1) {
6320 Field *ukey_field = key_info->key_part[0].field;
6321 error = mrn_change_encoding(ctx, ukey_field->charset());
6322 if (error) {
6323 DBUG_RETURN(error);
6324 }
6325 generic_store_bulk(ukey_field, &key_buffer);
6326 ukey = GRN_TEXT_VALUE(&key_buffer);
6327 ukey_size = GRN_TEXT_LEN(&key_buffer);
6328 } else {
6329 mrn_change_encoding(ctx, NULL);
6330 uchar key[MRN_MAX_KEY_SIZE];
6331 key_copy(key, buf, key_info, key_info->key_length);
6332 grn_bulk_reserve(ctx, &key_buffer, MRN_MAX_KEY_SIZE);
6333 ukey = GRN_TEXT_VALUE(&key_buffer);
6334 storage_encode_multiple_column_key(key_info,
6335 key, key_info->key_length,
6336 (uchar *)(ukey), (uint *)&ukey_size);
6337 }
6338
6339 int added;
6340 *key_id = grn_table_add(ctx, index_table, ukey, ukey_size, &added);
6341 if (ctx->rc) {
6342 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
6343 DBUG_RETURN(ER_ERROR_ON_WRITE);
6344 }
6345 if (!added) {
6346 // duplicated error
6347 error = HA_ERR_FOUND_DUPP_KEY;
6348 grn_id duplicated_record_id = GRN_ID_NIL;
6349 {
6350 grn_table_cursor *table_cursor;
6351 table_cursor = grn_table_cursor_open(ctx, index_table,
6352 ukey, ukey_size,
6353 ukey, ukey_size,
6354 0, -1, 0);
6355 if (table_cursor) {
6356 grn_obj *index_cursor;
6357 index_cursor = grn_index_cursor_open(ctx, table_cursor, index_column,
6358 GRN_ID_NIL, GRN_ID_MAX, 0);
6359 if (index_cursor) {
6360 grn_posting *posting;
6361 posting = grn_index_cursor_next(ctx, index_cursor, NULL);
6362 if (posting) {
6363 duplicated_record_id = posting->rid;
6364 }
6365 }
6366 grn_obj_unlink(ctx, index_cursor);
6367 }
6368 grn_table_cursor_close(ctx, table_cursor);
6369 }
6370 memcpy(dup_ref, &duplicated_record_id, sizeof(grn_id));
6371 if (!ignoring_duplicated_key) {
6372 GRN_LOG(ctx, GRN_LOG_ERROR,
6373 "duplicated id on insert: update unique index: <%.*s>",
6374 ukey_size, ukey);
6375 }
6376 DBUG_RETURN(error);
6377 }
6378 DBUG_RETURN(0);
6379 }
6380
storage_write_row_unique_indexes(uchar * buf)6381 int ha_mroonga::storage_write_row_unique_indexes(uchar *buf)
6382 {
6383 int error = 0;
6384 uint i;
6385 uint n_keys = table->s->keys;
6386 MRN_DBUG_ENTER_METHOD();
6387
6388 for (i = 0; i < n_keys; i++) {
6389 if (i == table->s->primary_key) {
6390 continue;
6391 }
6392
6393 KEY *key_info = &table->key_info[i];
6394
6395 if (!(key_info->flags & HA_NOSAME)) {
6396 continue;
6397 }
6398
6399 grn_obj *index_table = grn_index_tables[i];
6400 if (!index_table) {
6401 continue;
6402 }
6403 grn_obj *index_column = grn_index_columns[i];
6404 if (!index_column) {
6405 continue;
6406 }
6407
6408 if ((error = storage_write_row_unique_index(buf, key_info,
6409 index_table, index_column,
6410 &key_id[i])))
6411 {
6412 if (error == HA_ERR_FOUND_DUPP_KEY)
6413 {
6414 dup_key = i;
6415 }
6416 goto err;
6417 }
6418 }
6419 DBUG_RETURN(0);
6420
6421 err:
6422 if (i) {
6423 mrn_change_encoding(ctx, NULL);
6424 do {
6425 i--;
6426
6427 if (i == table->s->primary_key) {
6428 continue;
6429 }
6430
6431 KEY *key_info = &table->key_info[i];
6432 if (!(key_info->flags & HA_NOSAME)) {
6433 continue;
6434 }
6435
6436 if (key_info->flags & HA_NOSAME) {
6437 grn_table_delete_by_id(ctx, grn_index_tables[i], key_id[i]);
6438 }
6439 } while (i);
6440 }
6441 DBUG_RETURN(error);
6442 }
6443
write_row(uchar * buf)6444 int ha_mroonga::write_row(uchar *buf)
6445 {
6446 MRN_DBUG_ENTER_METHOD();
6447 int error = 0;
6448 if (share->wrapper_mode)
6449 {
6450 error = wrapper_write_row(buf);
6451 } else {
6452 error = storage_write_row(buf);
6453 }
6454 DBUG_RETURN(error);
6455 }
6456
wrapper_get_record_id(uchar * data,grn_id * record_id,const char * context)6457 int ha_mroonga::wrapper_get_record_id(uchar *data, grn_id *record_id,
6458 const char *context)
6459 {
6460 MRN_DBUG_ENTER_METHOD();
6461
6462 int error = 0;
6463
6464 grn_obj key;
6465 GRN_TEXT_INIT(&key, 0);
6466
6467 mrn_change_encoding(ctx, NULL);
6468 grn_bulk_space(ctx, &key, table->key_info->key_length);
6469 key_copy((uchar *)(GRN_TEXT_VALUE(&key)),
6470 data,
6471 &(table->key_info[table_share->primary_key]),
6472 table->key_info[table_share->primary_key].key_length);
6473
6474 *record_id = grn_table_get(ctx, grn_table,
6475 GRN_TEXT_VALUE(&key), GRN_TEXT_LEN(&key));
6476 if (*record_id == GRN_ID_NIL) {
6477 DBUG_PRINT("info", ("mroonga: %s", context));
6478 char error_message[MRN_MESSAGE_BUFFER_SIZE];
6479 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
6480 "%s: key=<%.*s>",
6481 context, (int)GRN_TEXT_LEN(&key), GRN_TEXT_VALUE(&key));
6482 error = ER_ERROR_ON_WRITE;
6483 push_warning(ha_thd(), MRN_SEVERITY_WARNING, error,
6484 error_message);
6485 }
6486 grn_obj_unlink(ctx, &key);
6487
6488 DBUG_RETURN(error);
6489 }
6490
wrapper_update_row(const uchar * old_data,const uchar * new_data)6491 int ha_mroonga::wrapper_update_row(const uchar *old_data,
6492 const uchar *new_data)
6493 {
6494 MRN_DBUG_ENTER_METHOD();
6495
6496 int error = 0;
6497 THD *thd = ha_thd();
6498
6499 mrn::Operation operation(operations_,
6500 "update",
6501 table->s->table_name.str,
6502 table->s->table_name.length);
6503
6504 MRN_SET_WRAP_SHARE_KEY(share, table->s);
6505 MRN_SET_WRAP_TABLE_KEY(this, table);
6506 tmp_disable_binlog(thd);
6507 error = wrap_handler->ha_update_row(old_data, new_data);
6508 reenable_binlog(thd);
6509 MRN_SET_BASE_SHARE_KEY(share, table->s);
6510 MRN_SET_BASE_TABLE_KEY(this, table);
6511
6512 if (!error && wrapper_have_target_index()) {
6513 error = wrapper_update_row_index(old_data, new_data);
6514 }
6515
6516 DBUG_RETURN(error);
6517 }
6518
wrapper_update_row_index(const uchar * old_data,const uchar * new_data)6519 int ha_mroonga::wrapper_update_row_index(const uchar *old_data,
6520 const uchar *new_data)
6521 {
6522 MRN_DBUG_ENTER_METHOD();
6523
6524 int error = 0;
6525
6526 if (is_dry_write()) {
6527 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
6528 DBUG_RETURN(error);
6529 }
6530
6531 mrn_change_encoding(ctx, NULL);
6532 KEY *key_info = &(table->key_info[table_share->primary_key]);
6533 GRN_BULK_REWIND(&key_buffer);
6534 key_copy((uchar *)(GRN_TEXT_VALUE(&key_buffer)),
6535 new_data,
6536 key_info, key_info->key_length);
6537 int added;
6538 grn_id new_record_id;
6539 new_record_id = grn_table_add(ctx, grn_table,
6540 GRN_TEXT_VALUE(&key_buffer),
6541 table->key_info->key_length,
6542 &added);
6543 if (new_record_id == GRN_ID_NIL) {
6544 char error_message[MRN_MESSAGE_BUFFER_SIZE];
6545 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
6546 "failed to get new record ID for updating from groonga: key=<%.*s>",
6547 (int)GRN_TEXT_LEN(&key_buffer), GRN_TEXT_VALUE(&key_buffer));
6548 error = ER_ERROR_ON_WRITE;
6549 my_message(error, error_message, MYF(0));
6550 DBUG_RETURN(error);
6551 }
6552
6553 grn_id old_record_id;
6554 my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(old_data, table->record[0]);
6555 for (uint j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6556 Field *field = key_info->key_part[j].field;
6557 field->move_field_offset(ptr_diff);
6558 }
6559 error = wrapper_get_record_id((uchar *)old_data, &old_record_id,
6560 "failed to get old record ID "
6561 "for updating from groonga");
6562 for (uint j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6563 Field *field = key_info->key_part[j].field;
6564 field->move_field_offset(-ptr_diff);
6565 }
6566 if (error) {
6567 DBUG_RETURN(0);
6568 }
6569
6570 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
6571 uint i;
6572 uint n_keys = table->s->keys;
6573 for (i = 0; i < n_keys; i++) {
6574 KEY *key_info = &(table->key_info[i]);
6575
6576 if (!(wrapper_is_target_index(key_info))) {
6577 continue;
6578 }
6579
6580 grn_obj *index_column = grn_index_columns[i];
6581 if (!index_column) {
6582 /* disable keys */
6583 continue;
6584 }
6585
6586 uint j;
6587 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6588 Field *field = key_info->key_part[j].field;
6589
6590 generic_store_bulk(field, &new_value_buffer);
6591
6592 field->move_field_offset(ptr_diff);
6593 generic_store_bulk(field, &old_value_buffer);
6594 field->move_field_offset(-ptr_diff);
6595
6596 grn_rc rc;
6597 if (old_record_id == new_record_id) {
6598 if (added) {
6599 rc = grn_column_index_update(ctx, index_column, old_record_id, j + 1,
6600 &old_value_buffer, NULL);
6601 if (!rc) {
6602 rc = grn_column_index_update(ctx, index_column, new_record_id, j + 1,
6603 NULL, &new_value_buffer);
6604 }
6605 } else {
6606 rc = grn_column_index_update(ctx, index_column, old_record_id, j + 1,
6607 &old_value_buffer, &new_value_buffer);
6608 }
6609 } else {
6610 rc = grn_column_index_update(ctx, index_column, old_record_id, j + 1,
6611 &old_value_buffer, NULL);
6612 if (!rc) {
6613 rc = grn_column_index_update(ctx, index_column, new_record_id, j + 1,
6614 NULL, &new_value_buffer);
6615 }
6616 if (!rc) {
6617 rc = grn_table_delete_by_id(ctx, grn_table, old_record_id);
6618 }
6619 }
6620 if (rc) {
6621 error = ER_ERROR_ON_WRITE;
6622 my_message(error, ctx->errbuf, MYF(0));
6623 goto err;
6624 }
6625 }
6626 }
6627 err:
6628
6629 DBUG_RETURN(error);
6630 }
6631
storage_update_row(const uchar * old_data,const uchar * new_data)6632 int ha_mroonga::storage_update_row(const uchar *old_data,
6633 const uchar *new_data)
6634 {
6635 MRN_DBUG_ENTER_METHOD();
6636 int error = 0;
6637
6638 if (is_dry_write()) {
6639 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
6640 DBUG_RETURN(error);
6641 }
6642
6643 mrn::Operation operation(operations_,
6644 "update",
6645 table->s->table_name.str,
6646 table->s->table_name.length);
6647 operation.record_target(record_id);
6648
6649 grn_obj colbuf;
6650 int i;
6651 uint j;
6652 int n_columns = table->s->fields;
6653 THD *thd = ha_thd();
6654
6655 for (i = 0; i < n_columns; i++) {
6656 Field *field = table->field[i];
6657
6658 #ifdef MRN_SUPPORT_GENERATED_COLUMNS
6659 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
6660 continue;
6661 }
6662 #endif
6663
6664 if (!bitmap_is_set(table->write_set, field->field_index))
6665 continue;
6666
6667 if (field->is_null())
6668 continue;
6669
6670 {
6671 mrn::ColumnName column_name(field->field_name);
6672 if (strcmp(MRN_COLUMN_NAME_ID, column_name.c_str()) == 0) {
6673 push_warning_printf(thd, MRN_SEVERITY_WARNING,
6674 WARN_DATA_TRUNCATED, MRN_GET_ERR_MSG(WARN_DATA_TRUNCATED),
6675 MRN_COLUMN_NAME_ID,
6676 MRN_GET_CURRENT_ROW_FOR_WARNING(thd));
6677 if (MRN_ABORT_ON_WARNING(thd)) {
6678 DBUG_RETURN(ER_DATA_TOO_LONG);
6679 }
6680 }
6681 }
6682
6683 if (!is_foreign_key_field(table->s->table_name.str, field->field_name.str))
6684 continue;
6685
6686 {
6687 grn_obj *column = grn_columns[i];
6688 grn_obj new_value;
6689 GRN_VOID_INIT(&new_value);
6690 {
6691 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
6692 generic_store_bulk(field, &new_value);
6693 }
6694 grn_obj casted_value;
6695 GRN_RECORD_INIT(&casted_value, 0, grn_obj_get_range(ctx, column));
6696 grn_rc cast_rc = grn_obj_cast(ctx, &new_value, &casted_value, GRN_FALSE);
6697 GRN_OBJ_FIN(ctx, &casted_value);
6698 if (cast_rc != GRN_SUCCESS) {
6699 grn_obj inspected;
6700 GRN_TEXT_INIT(&inspected, 0);
6701 grn_inspect(ctx, &inspected, &new_value);
6702 GRN_OBJ_FIN(ctx, &new_value);
6703 error = HA_ERR_NO_REFERENCED_ROW;
6704 GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
6705 "foreign record doesn't exist: <%s>:<%.*s>",
6706 field->field_name.str,
6707 static_cast<int>(GRN_TEXT_LEN(&inspected)),
6708 GRN_TEXT_VALUE(&inspected));
6709 GRN_OBJ_FIN(ctx, &inspected);
6710 DBUG_RETURN(error);
6711 }
6712 GRN_OBJ_FIN(ctx, &new_value);
6713 }
6714 }
6715
6716 KEY *pkey_info = NULL;
6717 storage_store_fields_for_prep_update(old_data, new_data, record_id);
6718 {
6719 mrn::Lock lock(&(share->record_mutex), have_unique_index());
6720 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
6721 if ((error = storage_prepare_delete_row_unique_indexes(old_data,
6722 record_id))) {
6723 DBUG_RETURN(error);
6724 }
6725 if ((error = storage_update_row_unique_indexes(new_data)))
6726 {
6727 DBUG_RETURN(error);
6728 }
6729 }
6730
6731 if (table->s->primary_key != MAX_INDEXES) {
6732 pkey_info = &(table->key_info[table->s->primary_key]);
6733 }
6734 GRN_VOID_INIT(&colbuf);
6735 for (i = 0; i < n_columns; i++) {
6736 Field *field = table->field[i];
6737
6738 #ifdef MRN_SUPPORT_GENERATED_COLUMNS
6739 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
6740 continue;
6741 }
6742 #endif
6743
6744 if (bitmap_is_set(table->write_set, field->field_index)) {
6745 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
6746 DBUG_PRINT("info", ("mroonga: update column %d(%d)",i,field->field_index));
6747
6748 if (field->is_null()) continue;
6749
6750 mrn::ColumnName column_name(field->field_name);
6751 if (strcmp(MRN_COLUMN_NAME_ID, column_name.c_str()) == 0) {
6752 continue;
6753 }
6754
6755 error = mrn_change_encoding(ctx, field->charset());
6756 if (error)
6757 goto err;
6758
6759 bool is_pkey = false;
6760 bool on_duplicate_key_update =
6761 (inserting_with_update && ignoring_duplicated_key);
6762 if (pkey_info && !on_duplicate_key_update) {
6763 for (j = 0; j < KEY_N_KEY_PARTS(pkey_info); j++) {
6764 Field *pkey_field = pkey_info->key_part[j].field;
6765 if (strcmp(pkey_field->field_name.str, column_name.c_str()) == 0) {
6766 is_pkey = true;
6767 break;
6768 }
6769 }
6770 }
6771
6772 generic_store_bulk(field, &colbuf);
6773 if (is_pkey) {
6774 bool is_multiple_column_index = KEY_N_KEY_PARTS(pkey_info) > 1;
6775 bool is_same_value;
6776 if (is_multiple_column_index) {
6777 is_same_value = false;
6778 } else {
6779 grn_id found_record_id = grn_table_get(ctx,
6780 grn_table,
6781 GRN_BULK_HEAD(&colbuf),
6782 GRN_BULK_VSIZE(&colbuf));
6783 is_same_value = (record_id == found_record_id);
6784 }
6785 if (!is_same_value && !replacing_) {
6786 char message[MRN_BUFFER_SIZE];
6787 snprintf(message, MRN_BUFFER_SIZE,
6788 "data truncated for primary key column: <%s>",
6789 column_name.c_str());
6790 push_warning(thd, MRN_SEVERITY_WARNING,
6791 WARN_DATA_TRUNCATED, message);
6792 }
6793 continue;
6794 }
6795
6796 grn_obj_set_value(ctx, grn_columns[i], record_id, &colbuf, GRN_OBJ_SET);
6797 if (ctx->rc) {
6798 grn_obj_unlink(ctx, &colbuf);
6799 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
6800 error = ER_ERROR_ON_WRITE;
6801 goto err;
6802 }
6803 }
6804 }
6805 grn_obj_unlink(ctx, &colbuf);
6806
6807 if ((error = storage_update_row_index(old_data, new_data)))
6808 {
6809 goto err;
6810 }
6811
6812 if ((error = storage_delete_row_unique_indexes()))
6813 {
6814 DBUG_RETURN(error);
6815 }
6816
6817 grn_db_touch(ctx, grn_ctx_db(ctx));
6818
6819 if (table->found_next_number_field &&
6820 !table->s->next_number_keypart &&
6821 new_data == table->record[0]) {
6822 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
6823 Field_num *field = (Field_num *) table->found_next_number_field;
6824 if (field->unsigned_flag || field->val_int() > 0) {
6825 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
6826 ulonglong nr = (ulonglong) field->val_int();
6827 if (!long_term_share->auto_inc_inited) {
6828 storage_info(HA_STATUS_AUTO);
6829 }
6830 {
6831 mrn::Lock lock(&long_term_share->auto_inc_mutex);
6832 if (long_term_share->auto_inc_value <= nr) {
6833 long_term_share->auto_inc_value = nr + 1;
6834 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
6835 long_term_share->auto_inc_value));
6836 }
6837 }
6838 }
6839 }
6840 DBUG_RETURN(0);
6841
6842 err:
6843 for (j = 0; j < table->s->keys; j++) {
6844 if (j == table->s->primary_key) {
6845 continue;
6846 }
6847 KEY *key_info = &table->key_info[j];
6848 if ((key_info->flags & HA_NOSAME) && key_id[j] != GRN_ID_NIL) {
6849 grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]);
6850 }
6851 }
6852
6853 if (!error && thd_sql_command(ha_thd()) == SQLCOM_TRUNCATE) {
6854 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
6855 mrn::Lock lock(&long_term_share->auto_inc_mutex);
6856 long_term_share->auto_inc_value = 0;
6857 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
6858 long_term_share->auto_inc_value));
6859 long_term_share->auto_inc_inited = false;
6860 }
6861
6862 DBUG_RETURN(error);
6863 }
6864
storage_update_row_index(const uchar * old_data,const uchar * new_data)6865 int ha_mroonga::storage_update_row_index(const uchar *old_data,
6866 const uchar *new_data)
6867 {
6868 MRN_DBUG_ENTER_METHOD();
6869 int error = 0;
6870
6871 grn_obj old_key, old_encoded_key, new_key, new_encoded_key;
6872 GRN_TEXT_INIT(&old_key, 0);
6873 GRN_TEXT_INIT(&old_encoded_key, 0);
6874 GRN_TEXT_INIT(&new_key, 0);
6875 GRN_TEXT_INIT(&new_encoded_key, 0);
6876
6877 my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(old_data, table->record[0]);
6878
6879 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
6880 uint i;
6881 uint n_keys = table->s->keys;
6882 mrn_change_encoding(ctx, NULL);
6883 for (i = 0; i < n_keys; i++) {
6884 if (i == table->s->primary_key) {
6885 continue;
6886 }
6887
6888 KEY *key_info = &(table->key_info[i]);
6889
6890 if (KEY_N_KEY_PARTS(key_info) == 1 || (key_info->flags & HA_FULLTEXT)) {
6891 continue;
6892 }
6893
6894 grn_obj *index_column = grn_index_columns[i];
6895 if (!index_column) {
6896 /* disable keys */
6897 continue;
6898 }
6899
6900 GRN_BULK_REWIND(&old_key);
6901 grn_bulk_space(ctx, &old_key, key_info->key_length);
6902 for (uint j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6903 Field *field = key_info->key_part[j].field;
6904 field->move_field_offset(ptr_diff);
6905 }
6906 key_copy((uchar *)(GRN_TEXT_VALUE(&old_key)),
6907 (uchar *)old_data,
6908 key_info,
6909 key_info->key_length);
6910 for (uint j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6911 Field *field = key_info->key_part[j].field;
6912 field->move_field_offset(-ptr_diff);
6913 }
6914 GRN_BULK_REWIND(&old_encoded_key);
6915 grn_bulk_reserve(ctx, &old_encoded_key, MRN_MAX_KEY_SIZE);
6916 uint old_encoded_key_length;
6917 storage_encode_multiple_column_key(key_info,
6918 (uchar *)(GRN_TEXT_VALUE(&old_key)),
6919 key_info->key_length,
6920 (uchar *)(GRN_TEXT_VALUE(&old_encoded_key)),
6921 &old_encoded_key_length);
6922 grn_bulk_space(ctx, &old_encoded_key, old_encoded_key_length);
6923
6924 GRN_BULK_REWIND(&new_key);
6925 grn_bulk_space(ctx, &new_key, key_info->key_length);
6926 key_copy((uchar *)(GRN_TEXT_VALUE(&new_key)),
6927 (uchar *)new_data,
6928 key_info,
6929 key_info->key_length);
6930 GRN_BULK_REWIND(&new_encoded_key);
6931 grn_bulk_reserve(ctx, &new_encoded_key, MRN_MAX_KEY_SIZE);
6932 uint new_encoded_key_length;
6933 storage_encode_multiple_column_key(key_info,
6934 (uchar *)(GRN_TEXT_VALUE(&new_key)),
6935 key_info->key_length,
6936 (uchar *)(GRN_TEXT_VALUE(&new_encoded_key)),
6937 &new_encoded_key_length);
6938 grn_bulk_space(ctx, &new_encoded_key, new_encoded_key_length);
6939
6940 grn_rc rc;
6941 rc = grn_column_index_update(ctx, index_column, record_id, 1,
6942 &old_encoded_key, &new_encoded_key);
6943 if (rc) {
6944 error = ER_ERROR_ON_WRITE;
6945 my_message(error, ctx->errbuf, MYF(0));
6946 goto err;
6947 }
6948 }
6949 err:
6950 grn_obj_unlink(ctx, &old_key);
6951 grn_obj_unlink(ctx, &old_encoded_key);
6952 grn_obj_unlink(ctx, &new_key);
6953 grn_obj_unlink(ctx, &new_encoded_key);
6954
6955 DBUG_RETURN(error);
6956 }
6957
storage_update_row_unique_indexes(const uchar * new_data)6958 int ha_mroonga::storage_update_row_unique_indexes(const uchar *new_data)
6959 {
6960 int error;
6961 uint i;
6962 uint n_keys = table->s->keys;
6963 MRN_DBUG_ENTER_METHOD();
6964
6965 for (i = 0; i < n_keys; i++) {
6966 if (i == table->s->primary_key) {
6967 continue;
6968 }
6969
6970 KEY *key_info = &table->key_info[i];
6971 if (!(key_info->flags & HA_NOSAME)) {
6972 continue;
6973 }
6974
6975 grn_obj *index_table = grn_index_tables[i];
6976 if (!index_table) {
6977 key_id[i] = GRN_ID_NIL;
6978 del_key_id[i] = GRN_ID_NIL;
6979 continue;
6980 }
6981
6982 grn_obj *index_column = grn_index_columns[i];
6983 if (!index_column) {
6984 key_id[i] = GRN_ID_NIL;
6985 del_key_id[i] = GRN_ID_NIL;
6986 continue;
6987 }
6988
6989 if (
6990 KEY_N_KEY_PARTS(key_info) == 1 &&
6991 !bitmap_is_set(table->write_set,
6992 key_info->key_part[0].field->field_index)
6993 ) {
6994 /* no change */
6995 key_id[i] = GRN_ID_NIL;
6996 del_key_id[i] = GRN_ID_NIL;
6997 continue;
6998 }
6999
7000 if ((error = storage_write_row_unique_index(new_data, key_info,
7001 index_table, index_column,
7002 &key_id[i])))
7003 {
7004 if (error == HA_ERR_FOUND_DUPP_KEY)
7005 {
7006 if (key_id[i] == del_key_id[i]) {
7007 /* no change */
7008 key_id[i] = GRN_ID_NIL;
7009 del_key_id[i] = GRN_ID_NIL;
7010 continue;
7011 }
7012 dup_key = i;
7013 DBUG_PRINT("info", ("mroonga: different key ID: %d record ID: %d,%d",
7014 i, key_id[i], del_key_id[i]));
7015 }
7016 goto err;
7017 }
7018 }
7019 DBUG_RETURN(0);
7020
7021 err:
7022 if (i) {
7023 mrn_change_encoding(ctx, NULL);
7024 do {
7025 i--;
7026 KEY *key_info = &table->key_info[i];
7027 if ((key_info->flags & HA_NOSAME) && key_id[i] != GRN_ID_NIL) {
7028 grn_table_delete_by_id(ctx, grn_index_tables[i], key_id[i]);
7029 }
7030 } while (i);
7031 }
7032 DBUG_RETURN(error);
7033 }
7034
update_row(const uchar * old_data,const uchar * new_data)7035 int ha_mroonga::update_row(const uchar *old_data, const uchar *new_data)
7036 {
7037 MRN_DBUG_ENTER_METHOD();
7038 int error = 0;
7039 if (share->wrapper_mode)
7040 {
7041 error = wrapper_update_row(old_data, new_data);
7042 } else {
7043 error = storage_update_row(old_data, new_data);
7044 }
7045 DBUG_RETURN(error);
7046 }
7047
wrapper_delete_row(const uchar * buf)7048 int ha_mroonga::wrapper_delete_row(const uchar *buf)
7049 {
7050 MRN_DBUG_ENTER_METHOD();
7051
7052 int error = 0;
7053 THD *thd= ha_thd();
7054
7055 mrn::Operation operation(operations_,
7056 "delete",
7057 table->s->table_name.str,
7058 table->s->table_name.length);
7059
7060 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7061 MRN_SET_WRAP_TABLE_KEY(this, table);
7062 tmp_disable_binlog(thd);
7063 error = wrap_handler->ha_delete_row(buf);
7064 reenable_binlog(thd);
7065 MRN_SET_BASE_SHARE_KEY(share, table->s);
7066 MRN_SET_BASE_TABLE_KEY(this, table);
7067
7068 if (!error && wrapper_have_target_index()) {
7069 error = wrapper_delete_row_index(buf);
7070 }
7071
7072 DBUG_RETURN(error);
7073 }
7074
wrapper_delete_row_index(const uchar * buf)7075 int ha_mroonga::wrapper_delete_row_index(const uchar *buf)
7076 {
7077 MRN_DBUG_ENTER_METHOD();
7078
7079 int error = 0;
7080
7081 if (is_dry_write()) {
7082 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
7083 DBUG_RETURN(error);
7084 }
7085
7086 mrn_change_encoding(ctx, NULL);
7087 grn_id record_id;
7088 error = wrapper_get_record_id((uchar *)buf, &record_id,
7089 "failed to get record ID "
7090 "for deleting from groonga");
7091 if (error) {
7092 DBUG_RETURN(0);
7093 }
7094
7095 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
7096 uint i;
7097 uint n_keys = table->s->keys;
7098 for (i = 0; i < n_keys; i++) {
7099 KEY *key_info = &(table->key_info[i]);
7100
7101 if (!(wrapper_is_target_index(key_info))) {
7102 continue;
7103 }
7104
7105 grn_obj *index_column = grn_index_columns[i];
7106 if (!index_column) {
7107 /* disable keys */
7108 continue;
7109 }
7110
7111 uint j;
7112 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
7113 Field *field = key_info->key_part[j].field;
7114
7115 if (field->is_null())
7116 continue;
7117
7118 generic_store_bulk(field, &old_value_buffer);
7119 grn_rc rc;
7120 rc = grn_column_index_update(ctx, index_column, record_id, j + 1,
7121 &old_value_buffer, NULL);
7122 if (rc) {
7123 error = ER_ERROR_ON_WRITE;
7124 my_message(error, ctx->errbuf, MYF(0));
7125 goto err;
7126 }
7127 }
7128 }
7129 err:
7130 grn_table_delete_by_id(ctx, grn_table, record_id);
7131 if (ctx->rc) {
7132 error = ER_ERROR_ON_WRITE;
7133 my_message(error, ctx->errbuf, MYF(0));
7134 }
7135
7136 DBUG_RETURN(error);
7137 }
7138
storage_delete_row(const uchar * buf)7139 int ha_mroonga::storage_delete_row(const uchar *buf)
7140 {
7141 MRN_DBUG_ENTER_METHOD();
7142 int error;
7143
7144 if (is_dry_write()) {
7145 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
7146 DBUG_RETURN(0);
7147 }
7148
7149 mrn::Operation operation(operations_,
7150 "delete",
7151 table->s->table_name.str,
7152 table->s->table_name.length);
7153 operation.record_target(record_id);
7154
7155 {
7156 grn_id referencing_child_table_id = GRN_ID_NIL;
7157 grn_hash *columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
7158 GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY);
7159 grn_table_columns(ctx, grn_table, "", 0,
7160 reinterpret_cast<grn_obj *>(columns));
7161 GRN_HASH_EACH_BEGIN(ctx, columns, cursor, id) {
7162 void *key;
7163 grn_hash_cursor_get_key(ctx, cursor, &key);
7164 grn_id column_id = *static_cast<grn_id *>(key);
7165 grn_obj *column = grn_ctx_at(ctx, column_id);
7166 if (!column)
7167 continue;
7168
7169 if (column->header.type != GRN_COLUMN_INDEX)
7170 continue;
7171
7172 grn_ii_cursor *ii_cursor =
7173 grn_ii_cursor_open(ctx,
7174 reinterpret_cast<grn_ii *>(column),
7175 record_id,
7176 GRN_ID_NIL,
7177 GRN_ID_MAX,
7178 0,
7179 0);
7180 if (!ii_cursor)
7181 continue;
7182
7183 if (grn_ii_cursor_next(ctx, ii_cursor)) {
7184 referencing_child_table_id = grn_obj_get_range(ctx, column);
7185 }
7186
7187 grn_ii_cursor_close(ctx, ii_cursor);
7188
7189 if (referencing_child_table_id != GRN_ID_NIL)
7190 break;
7191 } GRN_HASH_EACH_END(ctx, cursor);
7192 grn_hash_close(ctx, columns);
7193
7194 if (referencing_child_table_id != GRN_ID_NIL) {
7195 grn_obj *referencing_child_table =
7196 grn_ctx_at(ctx, referencing_child_table_id);
7197 char name[GRN_TABLE_MAX_KEY_SIZE];
7198 int name_size;
7199 name_size = grn_obj_name(ctx,
7200 referencing_child_table,
7201 name,
7202 GRN_TABLE_MAX_KEY_SIZE);
7203 error = HA_ERR_ROW_IS_REFERENCED;
7204 GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
7205 "one or more child rows exist in <%.*s>",
7206 name_size,
7207 name);
7208 DBUG_RETURN(error);
7209 }
7210 }
7211
7212 storage_store_fields_for_prep_update(buf, NULL, record_id);
7213 {
7214 mrn::Lock lock(&(share->record_mutex), have_unique_index());
7215 if ((error = storage_prepare_delete_row_unique_indexes(buf, record_id))) {
7216 DBUG_RETURN(error);
7217 }
7218 mrn_change_encoding(ctx, NULL);
7219 grn_table_delete_by_id(ctx, grn_table, record_id);
7220 if (ctx->rc) {
7221 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
7222 DBUG_RETURN(ER_ERROR_ON_WRITE);
7223 }
7224 if (
7225 (error = storage_delete_row_index(buf)) ||
7226 (error = storage_delete_row_unique_indexes())
7227 ) {
7228 DBUG_RETURN(error);
7229 }
7230 }
7231
7232 grn_db_touch(ctx, grn_ctx_db(ctx));
7233
7234 DBUG_RETURN(0);
7235 }
7236
storage_delete_row_index(const uchar * buf)7237 int ha_mroonga::storage_delete_row_index(const uchar *buf)
7238 {
7239 MRN_DBUG_ENTER_METHOD();
7240 int error = 0;
7241
7242 grn_obj key, encoded_key;
7243 GRN_TEXT_INIT(&key, 0);
7244 GRN_TEXT_INIT(&encoded_key, 0);
7245
7246 mrn::DebugColumnAccess debug_column_access(table, &table->read_set);
7247 uint i;
7248 uint n_keys = table->s->keys;
7249 mrn_change_encoding(ctx, NULL);
7250 for (i = 0; i < n_keys; i++) {
7251 if (i == table->s->primary_key) {
7252 continue;
7253 }
7254
7255 KEY *key_info = &(table->key_info[i]);
7256
7257 if (KEY_N_KEY_PARTS(key_info) == 1 || (key_info->flags & HA_FULLTEXT)) {
7258 continue;
7259 }
7260
7261 grn_obj *index_column = grn_index_columns[i];
7262 if (!index_column) {
7263 /* disable keys */
7264 continue;
7265 }
7266
7267 GRN_BULK_REWIND(&key);
7268 grn_bulk_space(ctx, &key, key_info->key_length);
7269 key_copy((uchar *)(GRN_TEXT_VALUE(&key)),
7270 (uchar *)buf,
7271 key_info,
7272 key_info->key_length);
7273 GRN_BULK_REWIND(&encoded_key);
7274 grn_bulk_reserve(ctx, &encoded_key, MRN_MAX_KEY_SIZE);
7275 uint encoded_key_length;
7276 storage_encode_multiple_column_key(key_info,
7277 (uchar *)(GRN_TEXT_VALUE(&key)),
7278 key_info->key_length,
7279 (uchar *)(GRN_TEXT_VALUE(&encoded_key)),
7280 &encoded_key_length);
7281 grn_bulk_space(ctx, &encoded_key, encoded_key_length);
7282
7283 grn_rc rc;
7284 rc = grn_column_index_update(ctx, index_column, record_id, 1,
7285 &encoded_key, NULL);
7286 if (rc) {
7287 error = ER_ERROR_ON_WRITE;
7288 my_message(error, ctx->errbuf, MYF(0));
7289 goto err;
7290 }
7291 }
7292 err:
7293 grn_obj_unlink(ctx, &encoded_key);
7294 grn_obj_unlink(ctx, &key);
7295
7296 DBUG_RETURN(error);
7297 }
7298
storage_delete_row_unique_index(grn_obj * index_table,grn_id del_key_id)7299 int ha_mroonga::storage_delete_row_unique_index(grn_obj *index_table,
7300 grn_id del_key_id)
7301 {
7302 MRN_DBUG_ENTER_METHOD();
7303 grn_rc rc = grn_table_delete_by_id(ctx, index_table, del_key_id);
7304 if (rc) {
7305 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
7306 DBUG_RETURN(ER_ERROR_ON_WRITE);
7307 }
7308 DBUG_RETURN(0);
7309 }
7310
storage_delete_row_unique_indexes()7311 int ha_mroonga::storage_delete_row_unique_indexes()
7312 {
7313 int error = 0, tmp_error;
7314 uint i;
7315 uint n_keys = table->s->keys;
7316 MRN_DBUG_ENTER_METHOD();
7317
7318 for (i = 0; i < n_keys; i++) {
7319 if (i == table->s->primary_key) {
7320 continue;
7321 }
7322
7323 KEY *key_info = &table->key_info[i];
7324 if ((!(key_info->flags & HA_NOSAME)) || del_key_id[i] == GRN_ID_NIL) {
7325 continue;
7326 }
7327
7328 grn_obj *index_table = grn_index_tables[i];
7329 if ((tmp_error = storage_delete_row_unique_index(index_table,
7330 del_key_id[i])))
7331 {
7332 error = tmp_error;
7333 }
7334 }
7335 DBUG_RETURN(error);
7336 }
7337
storage_prepare_delete_row_unique_index(const uchar * buf,grn_id record_id,KEY * key_info,grn_obj * index_table,grn_obj * index_column,grn_id * del_key_id)7338 int ha_mroonga::storage_prepare_delete_row_unique_index(const uchar *buf,
7339 grn_id record_id,
7340 KEY *key_info,
7341 grn_obj *index_table,
7342 grn_obj *index_column,
7343 grn_id *del_key_id)
7344 {
7345 const void *ukey = NULL;
7346 uint32 ukey_size = 0;
7347 MRN_DBUG_ENTER_METHOD();
7348 if (KEY_N_KEY_PARTS(key_info) == 1) {
7349 GRN_BULK_REWIND(&key_buffer);
7350 grn_obj_get_value(ctx, index_column, record_id, &key_buffer);
7351 ukey = GRN_TEXT_VALUE(&key_buffer);
7352 ukey_size = GRN_TEXT_LEN(&key_buffer);
7353 } else {
7354 mrn_change_encoding(ctx, NULL);
7355 uchar key[MRN_MAX_KEY_SIZE];
7356 key_copy(key, (uchar *) buf, key_info, key_info->key_length);
7357 grn_bulk_reserve(ctx, &key_buffer, MRN_MAX_KEY_SIZE);
7358 ukey = GRN_TEXT_VALUE(&key_buffer);
7359 storage_encode_multiple_column_key(key_info,
7360 key, key_info->key_length,
7361 (uchar *)ukey, (uint *)&ukey_size);
7362 }
7363 *del_key_id = grn_table_get(ctx, index_table, ukey, ukey_size);
7364 DBUG_RETURN(0);
7365 }
7366
storage_prepare_delete_row_unique_indexes(const uchar * buf,grn_id record_id)7367 int ha_mroonga::storage_prepare_delete_row_unique_indexes(const uchar *buf,
7368 grn_id record_id)
7369 {
7370 int error = 0, tmp_error;
7371 uint i;
7372 uint n_keys = table->s->keys;
7373 MRN_DBUG_ENTER_METHOD();
7374
7375 for (i = 0; i < n_keys; i++) {
7376 if (i == table->s->primary_key) {
7377 continue;
7378 }
7379
7380 KEY *key_info = &table->key_info[i];
7381 if (!(key_info->flags & HA_NOSAME)) {
7382 continue;
7383 }
7384
7385 grn_obj *index_table = grn_index_tables[i];
7386 if (!index_table) {
7387 del_key_id[i] = GRN_ID_NIL;
7388 continue;
7389 }
7390
7391 grn_obj *index_column;
7392 if (KEY_N_KEY_PARTS(key_info) == 1) {
7393 Field *field = key_info->key_part[0].field;
7394 mrn_change_encoding(ctx, field->charset());
7395 index_column = grn_columns[field->field_index];
7396 } else {
7397 mrn_change_encoding(ctx, NULL);
7398 index_column = grn_index_columns[i];
7399 }
7400 if ((tmp_error = storage_prepare_delete_row_unique_index(buf, record_id,
7401 key_info,
7402 index_table,
7403 index_column,
7404 &del_key_id[i])))
7405 {
7406 error = tmp_error;
7407 }
7408 }
7409 DBUG_RETURN(error);
7410 }
7411
delete_row(const uchar * buf)7412 int ha_mroonga::delete_row(const uchar *buf)
7413 {
7414 MRN_DBUG_ENTER_METHOD();
7415 int error = 0;
7416 if (share->wrapper_mode)
7417 {
7418 error = wrapper_delete_row(buf);
7419 } else {
7420 error = storage_delete_row(buf);
7421 }
7422 DBUG_RETURN(error);
7423 }
7424
wrapper_max_supported_key_parts() const7425 uint ha_mroonga::wrapper_max_supported_key_parts() const
7426 {
7427 MRN_DBUG_ENTER_METHOD();
7428 DBUG_RETURN(MAX_REF_PARTS);
7429 }
7430
storage_max_supported_key_parts() const7431 uint ha_mroonga::storage_max_supported_key_parts() const
7432 {
7433 MRN_DBUG_ENTER_METHOD();
7434 DBUG_RETURN(MAX_REF_PARTS);
7435 }
7436
max_supported_key_parts() const7437 uint ha_mroonga::max_supported_key_parts() const
7438 {
7439 MRN_DBUG_ENTER_METHOD();
7440
7441 uint parts;
7442 if (!share && !analyzed_for_create &&
7443 (
7444 thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE ||
7445 thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX ||
7446 thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE
7447 )
7448 ) {
7449 create_share_for_create();
7450 }
7451 if (analyzed_for_create && share_for_create.wrapper_mode) {
7452 parts = wrapper_max_supported_key_parts();
7453 } else if (wrap_handler && share && share->wrapper_mode) {
7454 parts = wrapper_max_supported_key_parts();
7455 } else {
7456 parts = storage_max_supported_key_parts();
7457 }
7458
7459 DBUG_RETURN(parts);
7460 }
7461
wrapper_records_in_range(uint key_nr,key_range * range_min,key_range * range_max)7462 ha_rows ha_mroonga::wrapper_records_in_range(uint key_nr, key_range *range_min,
7463 key_range *range_max)
7464 {
7465 ha_rows row_count;
7466 MRN_DBUG_ENTER_METHOD();
7467 KEY *key_info = &(table->s->key_info[key_nr]);
7468 if (mrn_is_geo_key(key_info)) {
7469 row_count = generic_records_in_range_geo(key_nr, range_min, range_max);
7470 } else {
7471 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7472 MRN_SET_WRAP_TABLE_KEY(this, table);
7473 row_count = wrap_handler->records_in_range(key_nr, range_min, range_max);
7474 MRN_SET_BASE_SHARE_KEY(share, table->s);
7475 MRN_SET_BASE_TABLE_KEY(this, table);
7476 }
7477 DBUG_RETURN(row_count);
7478 }
7479
storage_records_in_range(uint key_nr,key_range * range_min,key_range * range_max)7480 ha_rows ha_mroonga::storage_records_in_range(uint key_nr, key_range *range_min,
7481 key_range *range_max)
7482 {
7483 MRN_DBUG_ENTER_METHOD();
7484 int flags = 0;
7485 uint size_min = 0, size_max = 0;
7486 ha_rows row_count = 0;
7487 uchar *key_min = NULL, *key_max = NULL;
7488 uchar key_min_entity[MRN_MAX_KEY_SIZE];
7489 uchar key_max_entity[MRN_MAX_KEY_SIZE];
7490 KEY *key_info = &(table->s->key_info[key_nr]);
7491 bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1;
7492
7493 if (is_multiple_column_index) {
7494 mrn_change_encoding(ctx, NULL);
7495 if (range_min && range_max &&
7496 range_min->length == range_max->length &&
7497 memcmp(range_min->key, range_max->key, range_min->length) == 0) {
7498 flags |= GRN_CURSOR_PREFIX;
7499 key_min = key_min_entity;
7500 storage_encode_multiple_column_key(key_info,
7501 range_min->key, range_min->length,
7502 key_min, &size_min);
7503 } else {
7504 key_min = key_min_entity;
7505 key_max = key_max_entity;
7506 storage_encode_multiple_column_key_range(key_info,
7507 range_min, range_max,
7508 key_min, &size_min,
7509 key_max, &size_max);
7510 }
7511 } else if (mrn_is_geo_key(key_info)) {
7512 mrn_change_encoding(ctx, key_info->key_part->field->charset());
7513 row_count = generic_records_in_range_geo(key_nr, range_min, range_max);
7514 DBUG_RETURN(row_count);
7515 } else {
7516 Field *field = key_info->key_part[0].field;
7517 const char *column_name = field->field_name.str;
7518 mrn_change_encoding(ctx, field->charset());
7519
7520 if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
7521 DBUG_RETURN((ha_rows)1);
7522 }
7523
7524 if (range_min) {
7525 key_min = key_min_entity;
7526 storage_encode_key(field, range_min->key, key_min, &size_min);
7527 if (size_min == 0) {
7528 DBUG_RETURN(HA_POS_ERROR);
7529 }
7530 }
7531 if (range_max) {
7532 key_max = key_max_entity;
7533 storage_encode_key(field, range_max->key, key_max, &size_max);
7534 if (size_max == 0) {
7535 DBUG_RETURN(HA_POS_ERROR);
7536 }
7537 }
7538 }
7539
7540 if (range_min) {
7541 DBUG_PRINT("info", ("mroonga: range_min->flag=%u", range_min->flag));
7542 if (range_min->flag == HA_READ_AFTER_KEY) {
7543 flags |= GRN_CURSOR_GT;
7544 }
7545 }
7546 if (range_max) {
7547 DBUG_PRINT("info", ("mroonga: range_min->flag=%u", range_max->flag));
7548 if (range_max->flag == HA_READ_BEFORE_KEY) {
7549 flags |= GRN_CURSOR_LT;
7550 }
7551 }
7552
7553 int cursor_limit = THDVAR(ha_thd(), max_n_records_for_estimate);
7554 uint pkey_nr = table->s->primary_key;
7555 if (key_nr == pkey_nr) {
7556 DBUG_PRINT("info", ("mroonga: use primary key"));
7557 grn_table_cursor *cursor;
7558 cursor = grn_table_cursor_open(ctx, grn_table,
7559 key_min, size_min,
7560 key_max, size_max,
7561 0, cursor_limit, flags);
7562 while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) {
7563 row_count++;
7564 }
7565 grn_table_cursor_close(ctx, cursor);
7566 } else {
7567 if (is_multiple_column_index) {
7568 DBUG_PRINT("info", ("mroonga: use multiple column key%u", key_nr));
7569 } else {
7570 DBUG_PRINT("info", ("mroonga: use key%u", key_nr));
7571 }
7572
7573 grn_table_cursor *cursor;
7574 cursor = grn_table_cursor_open(ctx, grn_index_tables[key_nr],
7575 key_min, size_min,
7576 key_max, size_max,
7577 0, cursor_limit, flags);
7578 grn_obj *index_column = grn_index_columns[key_nr];
7579 grn_ii *ii = reinterpret_cast<grn_ii *>(index_column);
7580 row_count = grn_ii_estimate_size_for_lexicon_cursor(ctx, ii, cursor);
7581 grn_table_cursor_close(ctx, cursor);
7582
7583 unsigned int max_n_lexicon_records =
7584 grn_table_size(ctx, grn_index_tables[key_nr]);
7585 if (cursor_limit >= 0 &&
7586 static_cast<unsigned int>(cursor_limit) < max_n_lexicon_records) {
7587 row_count++;
7588 }
7589 }
7590 DBUG_RETURN(row_count);
7591 }
7592
generic_records_in_range_geo(uint key_nr,key_range * range_min,key_range * range_max)7593 ha_rows ha_mroonga::generic_records_in_range_geo(uint key_nr,
7594 key_range *range_min,
7595 key_range *range_max)
7596 {
7597 MRN_DBUG_ENTER_METHOD();
7598 ha_rows row_count;
7599 int error;
7600
7601 if (!range_min) {
7602 DBUG_PRINT("info",
7603 ("mroonga: range min is missing for geometry range search"));
7604 DBUG_RETURN(HA_POS_ERROR);
7605 }
7606 if (range_max) {
7607 DBUG_PRINT("info",
7608 ("mroonga: range max is specified for geometry range search"));
7609 DBUG_RETURN(HA_POS_ERROR);
7610 }
7611 error = mrn_change_encoding(ctx,
7612 table->key_info[key_nr].key_part->field->charset());
7613 if (error)
7614 DBUG_RETURN(error);
7615 if (!(range_min->flag & HA_READ_MBR_CONTAIN)) {
7616 push_warning_unsupported_spatial_index_search(range_min->flag);
7617 row_count = grn_table_size(ctx, grn_table);
7618 DBUG_RETURN(row_count);
7619 }
7620
7621 geo_store_rectangle(range_min->key);
7622 row_count = grn_geo_estimate_in_rectangle(ctx,
7623 grn_index_columns[key_nr],
7624 &top_left_point,
7625 &bottom_right_point);
7626 DBUG_RETURN(row_count);
7627 }
7628
records_in_range(uint key_nr,key_range * range_min,key_range * range_max)7629 ha_rows ha_mroonga::records_in_range(uint key_nr, key_range *range_min, key_range *range_max)
7630 {
7631 MRN_DBUG_ENTER_METHOD();
7632 ha_rows row_count = 0;
7633 if (share->wrapper_mode)
7634 {
7635 row_count = wrapper_records_in_range(key_nr, range_min, range_max);
7636 } else {
7637 row_count = storage_records_in_range(key_nr, range_min, range_max);
7638 }
7639 DBUG_PRINT("info", ("mroonga: row_count=%" MRN_HA_ROWS_FORMAT, row_count));
7640 DBUG_RETURN(row_count);
7641 }
7642
wrapper_index_init(uint idx,bool sorted)7643 int ha_mroonga::wrapper_index_init(uint idx, bool sorted)
7644 {
7645 MRN_DBUG_ENTER_METHOD();
7646 int error = 0;
7647 KEY *key_info = &(table->s->key_info[idx]);
7648 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7649 MRN_SET_WRAP_TABLE_KEY(this, table);
7650 if (!mrn_is_geo_key(key_info) && key_info->algorithm != HA_KEY_ALG_FULLTEXT)
7651 {
7652 error = wrap_handler->ha_index_init(share->wrap_key_nr[idx], sorted);
7653 } else {
7654 error = wrap_handler->ha_index_init(share->wrap_primary_key, sorted);
7655 }
7656 MRN_SET_BASE_SHARE_KEY(share, table->s);
7657 MRN_SET_BASE_TABLE_KEY(this, table);
7658 DBUG_RETURN(error);
7659 }
7660
storage_index_init(uint idx,bool sorted)7661 int ha_mroonga::storage_index_init(uint idx, bool sorted)
7662 {
7663 MRN_DBUG_ENTER_METHOD();
7664 DBUG_RETURN(0);
7665 }
7666
index_init(uint idx,bool sorted)7667 int ha_mroonga::index_init(uint idx, bool sorted)
7668 {
7669 MRN_DBUG_ENTER_METHOD();
7670 DBUG_PRINT("info", ("mroonga: idx=%u", idx));
7671 active_index = idx;
7672 int error = 0;
7673 if (share->wrapper_mode)
7674 {
7675 error = wrapper_index_init(idx, sorted);
7676 } else {
7677 error = storage_index_init(idx, sorted);
7678 }
7679 DBUG_RETURN(error);
7680 }
7681
wrapper_index_end()7682 int ha_mroonga::wrapper_index_end()
7683 {
7684 int error = 0;
7685 MRN_DBUG_ENTER_METHOD();
7686 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7687 MRN_SET_WRAP_TABLE_KEY(this, table);
7688 error = wrap_handler->ha_index_or_rnd_end();
7689 MRN_SET_BASE_SHARE_KEY(share, table->s);
7690 MRN_SET_BASE_TABLE_KEY(this, table);
7691 DBUG_RETURN(error);
7692 }
7693
storage_index_end()7694 int ha_mroonga::storage_index_end()
7695 {
7696 MRN_DBUG_ENTER_METHOD();
7697 clear_cursor();
7698 clear_cursor_geo();
7699 DBUG_RETURN(0);
7700 }
7701
index_end()7702 int ha_mroonga::index_end()
7703 {
7704 MRN_DBUG_ENTER_METHOD();
7705 int error = 0;
7706 if (share->wrapper_mode)
7707 {
7708 error = wrapper_index_end();
7709 } else {
7710 error = storage_index_end();
7711 }
7712 DBUG_RETURN(error);
7713 }
7714
wrapper_index_read_map(uchar * buf,const uchar * key,key_part_map keypart_map,enum ha_rkey_function find_flag)7715 int ha_mroonga::wrapper_index_read_map(uchar *buf, const uchar *key,
7716 key_part_map keypart_map,
7717 enum ha_rkey_function find_flag)
7718 {
7719 int error = 0;
7720 MRN_DBUG_ENTER_METHOD();
7721 KEY *key_info = &(table->key_info[active_index]);
7722 if (mrn_is_geo_key(key_info)) {
7723 clear_cursor_geo();
7724 error = generic_geo_open_cursor(key, find_flag);
7725 if (!error) {
7726 error = wrapper_get_next_geo_record(buf);
7727 }
7728 DBUG_RETURN(error);
7729 } else {
7730 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7731 MRN_SET_WRAP_TABLE_KEY(this, table);
7732 if (fulltext_searching)
7733 set_pk_bitmap();
7734 #ifdef MRN_HANDLER_HAVE_HA_INDEX_READ_MAP
7735 error = wrap_handler->ha_index_read_map(buf, key, keypart_map, find_flag);
7736 #else
7737 error = wrap_handler->index_read_map(buf, key, keypart_map, find_flag);
7738 #endif
7739 MRN_SET_BASE_SHARE_KEY(share, table->s);
7740 MRN_SET_BASE_TABLE_KEY(this, table);
7741 }
7742 DBUG_RETURN(error);
7743 }
7744
storage_index_read_map(uchar * buf,const uchar * key,key_part_map keypart_map,enum ha_rkey_function find_flag)7745 int ha_mroonga::storage_index_read_map(uchar *buf, const uchar *key,
7746 key_part_map keypart_map,
7747 enum ha_rkey_function find_flag)
7748 {
7749 MRN_DBUG_ENTER_METHOD();
7750 check_count_skip(keypart_map);
7751
7752 int error = 0;
7753
7754 uint key_nr = active_index;
7755 KEY *key_info = &(table->key_info[key_nr]);
7756 int flags = 0;
7757 uint size_min = 0, size_max = 0;
7758 uchar *key_min = NULL, *key_max = NULL;
7759 uchar key_min_entity[MRN_MAX_KEY_SIZE];
7760 uchar key_max_entity[MRN_MAX_KEY_SIZE];
7761
7762 clear_cursor();
7763 clear_cursor_geo();
7764 clear_empty_value_records();
7765
7766 switch (find_flag) {
7767 case HA_READ_BEFORE_KEY:
7768 flags |= GRN_CURSOR_LT | GRN_CURSOR_DESCENDING;
7769 break;
7770 case HA_READ_PREFIX_LAST:
7771 flags |= GRN_CURSOR_PREFIX | GRN_CURSOR_DESCENDING;
7772 break;
7773 case HA_READ_PREFIX_LAST_OR_PREV:
7774 flags |= GRN_CURSOR_LE | GRN_CURSOR_DESCENDING;
7775 break;
7776 case HA_READ_AFTER_KEY:
7777 flags |= GRN_CURSOR_GT | GRN_CURSOR_ASCENDING;
7778 break;
7779 case HA_READ_KEY_OR_NEXT:
7780 flags |= GRN_CURSOR_GE | GRN_CURSOR_ASCENDING;
7781 break;
7782 case HA_READ_KEY_EXACT:
7783 flags |= GRN_CURSOR_LE | GRN_CURSOR_GE;
7784 break;
7785 default:
7786 break;
7787 }
7788
7789 bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1;
7790 if (is_multiple_column_index) {
7791 mrn_change_encoding(ctx, NULL);
7792 uint key_length =
7793 mrn_calculate_key_len(table, active_index, key, keypart_map);
7794 DBUG_PRINT("info",
7795 ("mroonga: multiple column index: "
7796 "search key length=<%u>, "
7797 "multiple column index key length=<%u>",
7798 key_length, key_info->key_length));
7799 if (key_length == key_info->key_length) {
7800 switch (find_flag) {
7801 case HA_READ_BEFORE_KEY:
7802 case HA_READ_PREFIX_LAST_OR_PREV:
7803 key_max = key_max_entity;
7804 storage_encode_multiple_column_key(key_info,
7805 key, key_length,
7806 key_max, &size_max);
7807 break;
7808 case HA_READ_PREFIX_LAST:
7809 key_min = key_min_entity;
7810 storage_encode_multiple_column_key(key_info,
7811 key, key_length,
7812 key_min, &size_min);
7813 break;
7814 default:
7815 key_min = key_min_entity;
7816 storage_encode_multiple_column_key(key_info,
7817 key, key_length,
7818 key_min, &size_min);
7819 if (find_flag == HA_READ_KEY_EXACT) {
7820 key_max = key_min;
7821 size_max = size_min;
7822 }
7823 break;
7824 }
7825 } else {
7826 const uchar *prev_key = NULL;
7827 uint prev_key_length = 0;
7828 if ((keypart_map >> 1) > 0) {
7829 prev_key = key;
7830 prev_key_length =
7831 mrn_calculate_key_len(table, active_index, key, keypart_map >> 1);
7832 }
7833 switch (find_flag) {
7834 case HA_READ_BEFORE_KEY:
7835 if (prev_key) {
7836 flags |= GRN_CURSOR_GE;
7837 key_min = key_min_entity;
7838 storage_encode_multiple_column_key_range(key_info,
7839 prev_key, prev_key_length,
7840 NULL, 0,
7841 key_min, &size_min,
7842 NULL, NULL);
7843 }
7844 key_max = key_max_entity;
7845 storage_encode_multiple_column_key_range(key_info,
7846 key, key_length,
7847 NULL, 0,
7848 key_max, &size_max,
7849 NULL, NULL);
7850 break;
7851 case HA_READ_PREFIX_LAST:
7852 key_min = key_min_entity;
7853 storage_encode_multiple_column_key(key_info,
7854 key, key_length,
7855 key_min, &size_min);
7856 break;
7857 case HA_READ_PREFIX_LAST_OR_PREV:
7858 if (prev_key) {
7859 flags |= GRN_CURSOR_GE;
7860 key_min = key_min_entity;
7861 storage_encode_multiple_column_key_range(key_info,
7862 prev_key, prev_key_length,
7863 NULL, 0,
7864 key_min, &size_min,
7865 NULL, NULL);
7866 }
7867 key_max = key_max_entity;
7868 storage_encode_multiple_column_key_range(key_info,
7869 NULL, 0,
7870 key, key_length,
7871 NULL, NULL,
7872 key_max, &size_max);
7873 break;
7874 case HA_READ_AFTER_KEY:
7875 key_min = key_min_entity;
7876 storage_encode_multiple_column_key_range(key_info,
7877 NULL, 0,
7878 key, key_length,
7879 NULL, NULL,
7880 key_min, &size_min);
7881 if (prev_key) {
7882 flags |= GRN_CURSOR_LE;
7883 key_max = key_max_entity;
7884 storage_encode_multiple_column_key_range(key_info,
7885 NULL, 0,
7886 prev_key, prev_key_length,
7887 NULL, NULL,
7888 key_max, &size_max);
7889 }
7890 break;
7891 case HA_READ_KEY_OR_NEXT:
7892 key_min = key_min_entity;
7893 storage_encode_multiple_column_key_range(key_info,
7894 key, key_length,
7895 NULL, 0,
7896 key_min, &size_min,
7897 NULL, NULL);
7898 if (prev_key) {
7899 flags |= GRN_CURSOR_LE;
7900 key_max = key_max_entity;
7901 storage_encode_multiple_column_key_range(key_info,
7902 NULL, 0,
7903 prev_key, prev_key_length,
7904 NULL, NULL,
7905 key_max, &size_max);
7906 }
7907 break;
7908 case HA_READ_KEY_EXACT:
7909 key_min = key_min_entity;
7910 key_max = key_max_entity;
7911 storage_encode_multiple_column_key_range(key_info,
7912 key, key_length,
7913 key, key_length,
7914 key_min, &size_min,
7915 key_max, &size_max);
7916 default:
7917 break;
7918 }
7919 }
7920 } else if (mrn_is_geo_key(key_info)) {
7921 error = mrn_change_encoding(ctx, key_info->key_part->field->charset());
7922 if (error)
7923 DBUG_RETURN(error);
7924 error = generic_geo_open_cursor(key, find_flag);
7925 if (!error) {
7926 error = storage_get_next_record(buf);
7927 }
7928 DBUG_RETURN(error);
7929 } else {
7930 Field *field = key_info->key_part[0].field;
7931 error = mrn_change_encoding(ctx, field->charset());
7932 if (error)
7933 DBUG_RETURN(error);
7934
7935 if (find_flag == HA_READ_KEY_EXACT) {
7936 const char *column_name = field->field_name.str;
7937
7938 key_min = key_min_entity;
7939 key_max = key_min_entity;
7940 storage_encode_key(field, key, key_min, &size_min);
7941 size_max = size_min;
7942 // for _id
7943 if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
7944 grn_id found_record_id = *((grn_id *)key_min);
7945 if (grn_table_at(ctx, grn_table, found_record_id) != GRN_ID_NIL) { // found
7946 storage_store_fields(buf, found_record_id);
7947 table->status = 0;
7948 record_id = found_record_id;
7949 DBUG_RETURN(0);
7950 } else {
7951 table->status = STATUS_NOT_FOUND;
7952 DBUG_RETURN(HA_ERR_END_OF_FILE);
7953 }
7954 }
7955 } else if (find_flag == HA_READ_BEFORE_KEY ||
7956 find_flag == HA_READ_PREFIX_LAST_OR_PREV) {
7957 key_max = key_max_entity;
7958 storage_encode_key(field, key, key_max_entity, &size_max);
7959 } else {
7960 key_min = key_min_entity;
7961 storage_encode_key(field, key, key_min_entity, &size_min);
7962 }
7963 }
7964
7965 uint pkey_nr = table->s->primary_key;
7966 if (key_nr == pkey_nr) {
7967 DBUG_PRINT("info", ("mroonga: use primary key"));
7968 cursor = grn_table_cursor_open(ctx, grn_table,
7969 key_min, size_min,
7970 key_max, size_max,
7971 0, -1, flags);
7972 } else {
7973 bool is_empty_value_records_search = false;
7974 if (is_multiple_column_index) {
7975 DBUG_PRINT("info", ("mroonga: use multiple column key%u", key_nr));
7976 } else if (flags == 0 && size_min == 0 && size_max == 0) {
7977 is_empty_value_records_search = true;
7978 DBUG_PRINT("info",
7979 ("mroonga: use table scan for searching empty value records"));
7980 } else {
7981 DBUG_PRINT("info", ("mroonga: use key%u", key_nr));
7982 }
7983 if (is_empty_value_records_search) {
7984 grn_obj *expression, *expression_variable;
7985 GRN_EXPR_CREATE_FOR_QUERY(ctx, grn_table,
7986 expression, expression_variable);
7987 grn_obj *target_column =
7988 grn_columns[key_info->key_part->field->field_index];
7989 grn_expr_append_const(ctx, expression, target_column, GRN_OP_GET_VALUE, 1);
7990 grn_obj empty_value;
7991 GRN_TEXT_INIT(&empty_value, 0);
7992 grn_expr_append_obj(ctx, expression, &empty_value, GRN_OP_PUSH, 1);
7993 grn_expr_append_op(ctx, expression, GRN_OP_EQUAL, 2);
7994
7995 empty_value_records =
7996 grn_table_create(ctx, NULL, 0, NULL,
7997 GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
7998 grn_table, 0);
7999 grn_table_select(ctx, grn_table, expression, empty_value_records,
8000 GRN_OP_OR);
8001 grn_obj_unlink(ctx, expression);
8002 grn_obj_unlink(ctx, &empty_value);
8003
8004 empty_value_records_cursor =
8005 grn_table_cursor_open(ctx, empty_value_records,
8006 NULL, 0, NULL, 0,
8007 0, -1, flags);
8008 } else {
8009 index_table_cursor = grn_table_cursor_open(ctx, grn_index_tables[key_nr],
8010 key_min, size_min,
8011 key_max, size_max,
8012 0, -1, flags);
8013 cursor = grn_index_cursor_open(ctx, index_table_cursor,
8014 grn_index_columns[key_nr],
8015 0, GRN_ID_MAX, 0);
8016 }
8017 }
8018 if (ctx->rc) {
8019 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8020 DBUG_RETURN(ER_ERROR_ON_READ);
8021 }
8022 error = storage_get_next_record(buf);
8023 DBUG_RETURN(error);
8024 }
8025
index_read_map(uchar * buf,const uchar * key,key_part_map keypart_map,enum ha_rkey_function find_flag)8026 int ha_mroonga::index_read_map(uchar *buf, const uchar *key,
8027 key_part_map keypart_map,
8028 enum ha_rkey_function find_flag)
8029 {
8030 MRN_DBUG_ENTER_METHOD();
8031 int error = 0;
8032 if (share->wrapper_mode)
8033 {
8034 error = wrapper_index_read_map(buf, key, keypart_map, find_flag);
8035 } else {
8036 error = storage_index_read_map(buf, key, keypart_map, find_flag);
8037 }
8038 DBUG_PRINT("info", ("mroonga: error=%d", error));
8039 DBUG_RETURN(error);
8040 }
8041
8042 #ifdef MRN_HANDLER_HAVE_INDEX_READ_LAST_MAP
wrapper_index_read_last_map(uchar * buf,const uchar * key,key_part_map keypart_map)8043 int ha_mroonga::wrapper_index_read_last_map(uchar *buf, const uchar *key,
8044 key_part_map keypart_map)
8045 {
8046 int error = 0;
8047 MRN_DBUG_ENTER_METHOD();
8048 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8049 MRN_SET_WRAP_TABLE_KEY(this, table);
8050 if (fulltext_searching)
8051 set_pk_bitmap();
8052 # ifdef MRN_HANDLER_HAVE_HA_INDEX_READ_LAST_MAP
8053 error = wrap_handler->ha_index_read_last_map(buf, key, keypart_map);
8054 # else
8055 error = wrap_handler->index_read_last_map(buf, key, keypart_map);
8056 # endif
8057 MRN_SET_BASE_SHARE_KEY(share, table->s);
8058 MRN_SET_BASE_TABLE_KEY(this, table);
8059 DBUG_RETURN(error);
8060 }
8061
storage_index_read_last_map(uchar * buf,const uchar * key,key_part_map keypart_map)8062 int ha_mroonga::storage_index_read_last_map(uchar *buf, const uchar *key,
8063 key_part_map keypart_map)
8064 {
8065 MRN_DBUG_ENTER_METHOD();
8066 uint key_nr = active_index;
8067 KEY *key_info = &(table->key_info[key_nr]);
8068
8069 int flags = GRN_CURSOR_DESCENDING, error;
8070 uint size_min = 0, size_max = 0;
8071 uchar *key_min = NULL, *key_max = NULL;
8072 uchar key_min_entity[MRN_MAX_KEY_SIZE];
8073
8074 clear_cursor();
8075
8076 bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1;
8077 if (is_multiple_column_index) {
8078 mrn_change_encoding(ctx, NULL);
8079 flags |= GRN_CURSOR_PREFIX;
8080 uint key_length =
8081 mrn_calculate_key_len(table, active_index, key, keypart_map);
8082 key_min = key_min_entity;
8083 storage_encode_multiple_column_key(key_info,
8084 key, key_length,
8085 key_min, &size_min);
8086 } else {
8087 Field *field = key_info->key_part[0].field;
8088 error = mrn_change_encoding(ctx, field->charset());
8089 if (error)
8090 DBUG_RETURN(error);
8091
8092 key_min = key_min_entity;
8093 key_max = key_min_entity;
8094 storage_encode_key(field, key, key_min, &size_min);
8095 size_max = size_min;
8096 }
8097
8098 uint pkey_nr = table->s->primary_key;
8099 if (key_nr == pkey_nr) {
8100 DBUG_PRINT("info", ("mroonga: use primary key"));
8101 cursor = grn_table_cursor_open(ctx, grn_table,
8102 key_min, size_min, key_max, size_max,
8103 0, -1, flags);
8104 } else {
8105 if (is_multiple_column_index) {
8106 DBUG_PRINT("info", ("mroonga: use multiple column key%u", key_nr));
8107 } else {
8108 DBUG_PRINT("info", ("mroonga: use key%u", key_nr));
8109 }
8110 index_table_cursor = grn_table_cursor_open(ctx, grn_index_tables[key_nr],
8111 key_min, size_min,
8112 key_max, size_max,
8113 0, -1, flags);
8114 cursor = grn_index_cursor_open(ctx, index_table_cursor,
8115 grn_index_columns[key_nr],
8116 0, GRN_ID_MAX, 0);
8117 }
8118 if (ctx->rc) {
8119 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8120 DBUG_RETURN(ER_ERROR_ON_READ);
8121 }
8122 error = storage_get_next_record(buf);
8123 DBUG_RETURN(error);
8124 }
8125
index_read_last_map(uchar * buf,const uchar * key,key_part_map keypart_map)8126 int ha_mroonga::index_read_last_map(uchar *buf, const uchar *key,
8127 key_part_map keypart_map)
8128 {
8129 MRN_DBUG_ENTER_METHOD();
8130 int error = 0;
8131 if (share->wrapper_mode)
8132 {
8133 error = wrapper_index_read_last_map(buf, key, keypart_map);
8134 } else {
8135 error = storage_index_read_last_map(buf, key, keypart_map);
8136 }
8137 DBUG_RETURN(error);
8138 }
8139 #endif
8140
wrapper_index_next(uchar * buf)8141 int ha_mroonga::wrapper_index_next(uchar *buf)
8142 {
8143 int error = 0;
8144 MRN_DBUG_ENTER_METHOD();
8145 KEY *key_info = &(table->key_info[active_index]);
8146 if (mrn_is_geo_key(key_info)) {
8147 error = wrapper_get_next_geo_record(buf);
8148 } else {
8149 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8150 MRN_SET_WRAP_TABLE_KEY(this, table);
8151 if (fulltext_searching)
8152 set_pk_bitmap();
8153 #ifdef MRN_HANDLER_HAVE_HA_INDEX_NEXT
8154 error = wrap_handler->ha_index_next(buf);
8155 #else
8156 error = wrap_handler->index_next(buf);
8157 #endif
8158 MRN_SET_BASE_SHARE_KEY(share, table->s);
8159 MRN_SET_BASE_TABLE_KEY(this, table);
8160 }
8161 DBUG_RETURN(error);
8162 }
8163
storage_index_next(uchar * buf)8164 int ha_mroonga::storage_index_next(uchar *buf)
8165 {
8166 MRN_DBUG_ENTER_METHOD();
8167 int error = storage_get_next_record(buf);
8168 DBUG_RETURN(error);
8169 }
8170
index_next(uchar * buf)8171 int ha_mroonga::index_next(uchar *buf)
8172 {
8173 MRN_DBUG_ENTER_METHOD();
8174 int error = 0;
8175 if (share->wrapper_mode)
8176 {
8177 error = wrapper_index_next(buf);
8178 } else {
8179 error = storage_index_next(buf);
8180 }
8181 DBUG_RETURN(error);
8182 }
8183
wrapper_index_prev(uchar * buf)8184 int ha_mroonga::wrapper_index_prev(uchar *buf)
8185 {
8186 int error = 0;
8187 MRN_DBUG_ENTER_METHOD();
8188 KEY *key_info = &(table->key_info[active_index]);
8189 if (mrn_is_geo_key(key_info)) {
8190 error = wrapper_get_next_geo_record(buf);
8191 } else {
8192 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8193 MRN_SET_WRAP_TABLE_KEY(this, table);
8194 if (fulltext_searching)
8195 set_pk_bitmap();
8196 #ifdef MRN_HANDLER_HAVE_HA_INDEX_NEXT
8197 error = wrap_handler->ha_index_prev(buf);
8198 #else
8199 error = wrap_handler->index_prev(buf);
8200 #endif
8201 MRN_SET_BASE_SHARE_KEY(share, table->s);
8202 MRN_SET_BASE_TABLE_KEY(this, table);
8203 }
8204 DBUG_RETURN(error);
8205 }
8206
storage_index_prev(uchar * buf)8207 int ha_mroonga::storage_index_prev(uchar *buf)
8208 {
8209 MRN_DBUG_ENTER_METHOD();
8210 int error = storage_get_next_record(buf);
8211 DBUG_RETURN(error);
8212 }
8213
index_prev(uchar * buf)8214 int ha_mroonga::index_prev(uchar *buf)
8215 {
8216 MRN_DBUG_ENTER_METHOD();
8217 int error = 0;
8218 if (share->wrapper_mode)
8219 {
8220 error = wrapper_index_prev(buf);
8221 } else {
8222 error = storage_index_prev(buf);
8223 }
8224 DBUG_RETURN(error);
8225 }
8226
wrapper_index_first(uchar * buf)8227 int ha_mroonga::wrapper_index_first(uchar *buf)
8228 {
8229 int error = 0;
8230 MRN_DBUG_ENTER_METHOD();
8231 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8232 MRN_SET_WRAP_TABLE_KEY(this, table);
8233 if (fulltext_searching)
8234 set_pk_bitmap();
8235 #ifdef MRN_HANDLER_HAVE_HA_INDEX_FIRST
8236 error = wrap_handler->ha_index_first(buf);
8237 #else
8238 error = wrap_handler->index_first(buf);
8239 #endif
8240 MRN_SET_BASE_SHARE_KEY(share, table->s);
8241 MRN_SET_BASE_TABLE_KEY(this, table);
8242 DBUG_RETURN(error);
8243 }
8244
storage_index_first(uchar * buf)8245 int ha_mroonga::storage_index_first(uchar *buf)
8246 {
8247 MRN_DBUG_ENTER_METHOD();
8248 clear_cursor();
8249 int flags = GRN_CURSOR_ASCENDING;
8250 uint pkey_nr = table->s->primary_key;
8251 mrn_change_encoding(ctx, NULL);
8252 if (active_index == pkey_nr) {
8253 DBUG_PRINT("info", ("mroonga: use primary key"));
8254 cursor = grn_table_cursor_open(ctx, grn_table, NULL, 0, NULL, 0,
8255 0, -1, flags);
8256 } else {
8257 if (KEY_N_KEY_PARTS(&(table->key_info[active_index])) > 1) {
8258 DBUG_PRINT("info", ("mroonga: use multiple column key%u", active_index));
8259 } else {
8260 DBUG_PRINT("info", ("mroonga: use key%u", active_index));
8261 }
8262 index_table_cursor = grn_table_cursor_open(ctx,
8263 grn_index_tables[active_index],
8264 NULL, 0,
8265 NULL, 0,
8266 0, -1, flags);
8267 cursor = grn_index_cursor_open(ctx, index_table_cursor,
8268 grn_index_columns[active_index],
8269 0, GRN_ID_MAX, 0);
8270 }
8271 if (ctx->rc) {
8272 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8273 DBUG_RETURN(ER_ERROR_ON_READ);
8274 }
8275 int error = storage_get_next_record(buf);
8276 DBUG_RETURN(error);
8277 }
8278
index_first(uchar * buf)8279 int ha_mroonga::index_first(uchar *buf)
8280 {
8281 MRN_DBUG_ENTER_METHOD();
8282 int error = 0;
8283 if (share->wrapper_mode)
8284 {
8285 error = wrapper_index_first(buf);
8286 } else {
8287 error = storage_index_first(buf);
8288 }
8289 DBUG_RETURN(error);
8290 }
8291
wrapper_index_last(uchar * buf)8292 int ha_mroonga::wrapper_index_last(uchar *buf)
8293 {
8294 int error = 0;
8295 MRN_DBUG_ENTER_METHOD();
8296 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8297 MRN_SET_WRAP_TABLE_KEY(this, table);
8298 if (fulltext_searching)
8299 set_pk_bitmap();
8300 #ifdef MRN_HANDLER_HAVE_HA_INDEX_LAST
8301 error = wrap_handler->ha_index_last(buf);
8302 #else
8303 error = wrap_handler->index_last(buf);
8304 #endif
8305 MRN_SET_BASE_SHARE_KEY(share, table->s);
8306 MRN_SET_BASE_TABLE_KEY(this, table);
8307 DBUG_RETURN(error);
8308 }
8309
storage_index_last(uchar * buf)8310 int ha_mroonga::storage_index_last(uchar *buf)
8311 {
8312 MRN_DBUG_ENTER_METHOD();
8313 clear_cursor();
8314 int flags = GRN_CURSOR_DESCENDING;
8315 uint pkey_nr = table->s->primary_key;
8316 mrn_change_encoding(ctx, NULL);
8317 if (active_index == pkey_nr) {
8318 DBUG_PRINT("info", ("mroonga: use primary key"));
8319 cursor = grn_table_cursor_open(ctx, grn_table, NULL, 0, NULL, 0,
8320 0, -1, flags);
8321 } else {
8322 if (KEY_N_KEY_PARTS(&(table->key_info[active_index])) > 1) {
8323 DBUG_PRINT("info", ("mroonga: use multiple column key%u", active_index));
8324 } else {
8325 DBUG_PRINT("info", ("mroonga: use key%u", active_index));
8326 }
8327 index_table_cursor = grn_table_cursor_open(ctx,
8328 grn_index_tables[active_index],
8329 NULL, 0,
8330 NULL, 0,
8331 0, -1, flags);
8332 cursor = grn_index_cursor_open(ctx, index_table_cursor,
8333 grn_index_columns[active_index],
8334 0, GRN_ID_MAX, 0);
8335 }
8336 if (ctx->rc) {
8337 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8338 DBUG_RETURN(ER_ERROR_ON_READ);
8339 }
8340 int error = storage_get_next_record(buf);
8341 DBUG_RETURN(error);
8342 }
8343
index_last(uchar * buf)8344 int ha_mroonga::index_last(uchar *buf)
8345 {
8346 MRN_DBUG_ENTER_METHOD();
8347 int error = 0;
8348 if (share->wrapper_mode)
8349 {
8350 error = wrapper_index_last(buf);
8351 } else {
8352 error = storage_index_last(buf);
8353 }
8354 DBUG_RETURN(error);
8355 }
8356
wrapper_index_next_same(uchar * buf,const uchar * key,uint keylen)8357 int ha_mroonga::wrapper_index_next_same(uchar *buf, const uchar *key,
8358 uint keylen)
8359 {
8360 MRN_DBUG_ENTER_METHOD();
8361 int error = 0;
8362 KEY *key_info = &(table->s->key_info[active_index]);
8363 if (mrn_is_geo_key(key_info)) {
8364 error = wrapper_get_next_geo_record(buf);
8365 } else {
8366 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8367 MRN_SET_WRAP_TABLE_KEY(this, table);
8368 if (fulltext_searching)
8369 set_pk_bitmap();
8370 #ifdef MRN_HANDLER_HAVE_HA_INDEX_NEXT_SAME
8371 error = wrap_handler->ha_index_next_same(buf, key, keylen);
8372 #else
8373 error = wrap_handler->index_next_same(buf, key, keylen);
8374 #endif
8375 MRN_SET_BASE_SHARE_KEY(share, table->s);
8376 MRN_SET_BASE_TABLE_KEY(this, table);
8377 }
8378 DBUG_RETURN(error);
8379 }
8380
storage_index_next_same(uchar * buf,const uchar * key,uint keylen)8381 int ha_mroonga::storage_index_next_same(uchar *buf, const uchar *key,
8382 uint keylen)
8383 {
8384 MRN_DBUG_ENTER_METHOD();
8385 int error = storage_get_next_record(count_skip ? NULL : buf);
8386 DBUG_RETURN(error);
8387 }
8388
index_next_same(uchar * buf,const uchar * key,uint keylen)8389 int ha_mroonga::index_next_same(uchar *buf, const uchar *key, uint keylen)
8390 {
8391 MRN_DBUG_ENTER_METHOD();
8392 int error = 0;
8393 if (share->wrapper_mode)
8394 {
8395 error = wrapper_index_next_same(buf, key, keylen);
8396 } else {
8397 error = storage_index_next_same(buf, key, keylen);
8398 }
8399 DBUG_RETURN(error);
8400 }
8401
generic_ft_init()8402 int ha_mroonga::generic_ft_init()
8403 {
8404 MRN_DBUG_ENTER_METHOD();
8405 struct st_mrn_ft_info *mrn_ft_info =
8406 reinterpret_cast<struct st_mrn_ft_info *>(ft_handler);
8407 GRN_CTX_SET_ENCODING(ctx, mrn_ft_info->encoding);
8408
8409 int error = 0;
8410 if (sorted_result) {
8411 mrn_ft_info->cursor = grn_table_cursor_open(ctx, sorted_result,
8412 NULL, 0, NULL, 0,
8413 0, -1, 0);
8414 } else {
8415 mrn_ft_info->cursor = grn_table_cursor_open(ctx, mrn_ft_info->result,
8416 NULL, 0, NULL, 0,
8417 0, -1, 0);
8418 }
8419 if (ctx->rc) {
8420 error = ER_ERROR_ON_READ;
8421 my_message(error, ctx->errbuf, MYF(0));
8422 } else {
8423 if (sorted_result) {
8424 if (grn_table->header.type == GRN_TABLE_NO_KEY) {
8425 mrn_ft_info->id_accessor = grn_obj_column(ctx, sorted_result,
8426 MRN_COLUMN_NAME_ID,
8427 strlen(MRN_COLUMN_NAME_ID));
8428 } else {
8429 mrn_ft_info->key_accessor = grn_obj_column(ctx, sorted_result,
8430 MRN_COLUMN_NAME_KEY,
8431 strlen(MRN_COLUMN_NAME_KEY));
8432 }
8433 } else {
8434 mrn_ft_info->key_accessor = grn_obj_column(ctx, mrn_ft_info->result,
8435 MRN_COLUMN_NAME_KEY,
8436 strlen(MRN_COLUMN_NAME_KEY));
8437 }
8438 }
8439 DBUG_RETURN(error);
8440 }
8441
wrapper_ft_init()8442 int ha_mroonga::wrapper_ft_init()
8443 {
8444 MRN_DBUG_ENTER_METHOD();
8445 int error = generic_ft_init();
8446 DBUG_RETURN(error);
8447 }
8448
storage_ft_init()8449 int ha_mroonga::storage_ft_init()
8450 {
8451 MRN_DBUG_ENTER_METHOD();
8452 int error = generic_ft_init();
8453 record_id = GRN_ID_NIL;
8454 DBUG_RETURN(error);
8455 }
8456
ft_init()8457 int ha_mroonga::ft_init()
8458 {
8459 MRN_DBUG_ENTER_METHOD();
8460 int error = 0;
8461 if (share->wrapper_mode)
8462 {
8463 error = wrapper_ft_init();
8464 } else {
8465 error = storage_ft_init();
8466 }
8467 DBUG_RETURN(error);
8468 }
8469
generic_ft_init_ext_add_conditions_fast_order_limit(struct st_mrn_ft_info * info,grn_obj * expression)8470 void ha_mroonga::generic_ft_init_ext_add_conditions_fast_order_limit(
8471 struct st_mrn_ft_info *info, grn_obj *expression)
8472 {
8473 MRN_DBUG_ENTER_METHOD();
8474
8475 Item *where =
8476 MRN_SELECT_LEX_GET_WHERE_COND(table->pos_in_table_list->select_lex);
8477
8478 bool is_storage_mode = !(share->wrapper_mode);
8479 mrn::ConditionConverter converter(info->ctx, grn_table, is_storage_mode);
8480 converter.convert(where, expression);
8481
8482 DBUG_VOID_RETURN;
8483 }
8484
generic_ft_init_ext_prepare_expression_in_boolean_mode(struct st_mrn_ft_info * info,String * key,grn_obj * index_column,grn_obj * match_columns,grn_obj * expression)8485 grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_boolean_mode(
8486 struct st_mrn_ft_info *info,
8487 String *key,
8488 grn_obj *index_column,
8489 grn_obj *match_columns,
8490 grn_obj *expression)
8491 {
8492 MRN_DBUG_ENTER_METHOD();
8493
8494 mrn::QueryParser query_parser(info->ctx,
8495 ha_thd(),
8496 expression,
8497 index_column,
8498 KEY_N_KEY_PARTS(info->key_info),
8499 match_columns);
8500 grn_rc rc = query_parser.parse(key->ptr(), key->length());
8501
8502 DBUG_RETURN(rc);
8503 }
8504
generic_ft_init_ext_prepare_expression_in_normal_mode(struct st_mrn_ft_info * info,String * key,grn_obj * index_column,grn_obj * match_columns,grn_obj * expression)8505 grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_normal_mode(
8506 struct st_mrn_ft_info *info,
8507 String *key,
8508 grn_obj *index_column,
8509 grn_obj *match_columns,
8510 grn_obj *expression)
8511 {
8512 MRN_DBUG_ENTER_METHOD();
8513
8514 grn_rc rc = GRN_SUCCESS;
8515
8516 grn_obj query;
8517 GRN_TEXT_INIT(&query, GRN_OBJ_DO_SHALLOW_COPY);
8518 GRN_TEXT_SET(info->ctx, &query, key->ptr(), key->length());
8519 grn_expr_append_obj(info->ctx, match_columns, index_column, GRN_OP_PUSH, 1);
8520 grn_expr_append_obj(info->ctx, expression, match_columns, GRN_OP_PUSH, 1);
8521 grn_expr_append_const(info->ctx, expression, &query, GRN_OP_PUSH, 1);
8522 grn_expr_append_op(info->ctx, expression, GRN_OP_SIMILAR, 2);
8523 grn_obj_unlink(info->ctx, &query);
8524
8525 DBUG_RETURN(rc);
8526 }
8527
generic_ft_init_ext_select(uint flags,uint key_nr,String * key)8528 struct st_mrn_ft_info *ha_mroonga::generic_ft_init_ext_select(uint flags,
8529 uint key_nr,
8530 String *key)
8531 {
8532 MRN_DBUG_ENTER_METHOD();
8533
8534 struct st_mrn_ft_info *info = new st_mrn_ft_info();
8535 info->mroonga = this;
8536 info->ctx = ctx;
8537 mrn_change_encoding(info->ctx,
8538 table->key_info[key_nr].key_part->field->charset());
8539 info->encoding = GRN_CTX_GET_ENCODING(info->ctx);
8540 info->table = grn_table;
8541 info->result = grn_table_create(info->ctx, NULL, 0, NULL,
8542 GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
8543 grn_table, 0);
8544 if (!info->result) {
8545 char error_message[MRN_MESSAGE_BUFFER_SIZE];
8546 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
8547 "[mroonga][ft-init] failed to create a table "
8548 "to store matched records for one search: <%s>",
8549 ctx->errbuf);
8550 my_message(ER_ERROR_ON_READ, error_message, MYF(0));
8551 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
8552 delete info;
8553 DBUG_RETURN(NULL);
8554 }
8555
8556 info->score_column = grn_obj_column(info->ctx, info->result,
8557 MRN_COLUMN_NAME_SCORE,
8558 strlen(MRN_COLUMN_NAME_SCORE));
8559 GRN_TEXT_INIT(&(info->key), 0);
8560 grn_bulk_space(info->ctx, &(info->key), table->key_info->key_length);
8561 GRN_INT32_INIT(&(info->score), 0);
8562 info->active_index = key_nr;
8563 info->key_info = &(table->key_info[key_nr]);
8564 info->primary_key_info = &(table->key_info[table_share->primary_key]);
8565 info->cursor = NULL;
8566 info->id_accessor = NULL;
8567 info->key_accessor = NULL;
8568
8569 if (key->length() == 0) {
8570 DBUG_RETURN(info);
8571 }
8572
8573 grn_obj *index_column = grn_index_columns[key_nr];
8574 grn_obj *match_columns, *match_columns_variable;
8575 GRN_EXPR_CREATE_FOR_QUERY(info->ctx, info->table, match_columns,
8576 match_columns_variable);
8577
8578 grn_obj *expression, *expression_variable;
8579 GRN_EXPR_CREATE_FOR_QUERY(info->ctx, info->table,
8580 expression, expression_variable);
8581
8582 grn_rc rc = GRN_SUCCESS;
8583 if (flags & FT_BOOL) {
8584 rc = generic_ft_init_ext_prepare_expression_in_boolean_mode(info,
8585 key,
8586 index_column,
8587 match_columns,
8588 expression);
8589 } else {
8590 rc = generic_ft_init_ext_prepare_expression_in_normal_mode(info,
8591 key,
8592 index_column,
8593 match_columns,
8594 expression);
8595 }
8596
8597 if (rc == GRN_SUCCESS) {
8598 if (fast_order_limit) {
8599 generic_ft_init_ext_add_conditions_fast_order_limit(info, expression);
8600 }
8601 longlong escalation_threshold = THDVAR(ha_thd(), match_escalation_threshold);
8602 mrn::MatchEscalationThresholdScope scope(info->ctx, escalation_threshold);
8603 grn_table_select(info->ctx, info->table, expression,
8604 info->result, GRN_OP_OR);
8605 }
8606
8607 grn_obj_unlink(info->ctx, expression);
8608 grn_obj_unlink(info->ctx, match_columns);
8609
8610 DBUG_RETURN(info);
8611 }
8612
generic_ft_init_ext(uint flags,uint key_nr,String * key)8613 FT_INFO *ha_mroonga::generic_ft_init_ext(uint flags, uint key_nr, String *key)
8614 {
8615 MRN_DBUG_ENTER_METHOD();
8616
8617 check_count_skip(0);
8618
8619 mrn_change_encoding(ctx, system_charset_info);
8620 grn_operator operation = GRN_OP_OR;
8621 if (!matched_record_keys) {
8622 matched_record_keys = grn_table_create(ctx, NULL, 0, NULL,
8623 GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
8624 grn_table, 0);
8625 if (!matched_record_keys) {
8626 char error_message[MRN_MESSAGE_BUFFER_SIZE];
8627 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
8628 "[mroonga][ft-init] "
8629 "failed to create a table to store all matched records: <%s>",
8630 ctx->errbuf);
8631 my_message(ER_ERROR_ON_READ, error_message, MYF(0));
8632 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
8633 DBUG_RETURN(NULL);
8634 }
8635 }
8636
8637 grn_table_sort_key *sort_keys = NULL;
8638 int n_sort_keys = 0;
8639 longlong limit = -1;
8640 check_fast_order_limit(&sort_keys, &n_sort_keys, &limit);
8641
8642 struct st_mrn_ft_info *info = generic_ft_init_ext_select(flags, key_nr, key);
8643 if (!info) {
8644 DBUG_RETURN(NULL);
8645 }
8646
8647 grn_rc rc;
8648 rc = grn_table_setoperation(ctx, matched_record_keys, info->result,
8649 matched_record_keys, operation);
8650 if (rc) {
8651 char error_message[MRN_MESSAGE_BUFFER_SIZE];
8652 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
8653 "failed to merge matched record keys: <%s>",
8654 ctx->errbuf);
8655 my_message(ER_ERROR_ON_READ, error_message, MYF(0));
8656 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
8657 }
8658 if (fast_order_limit) {
8659 if (sorted_result) {
8660 grn_obj_close(ctx, sorted_result);
8661 }
8662 sorted_result = grn_table_create(ctx, NULL,
8663 0, NULL,
8664 GRN_OBJ_TABLE_NO_KEY, NULL,
8665 matched_record_keys);
8666 grn_table_sort(ctx, matched_record_keys, 0, static_cast<int>(limit),
8667 sorted_result, sort_keys, n_sort_keys);
8668 } else if (flags & FT_SORTED) {
8669 grn_table_sort_key score_sort_key;
8670 score_sort_key.key = grn_obj_column(ctx,
8671 matched_record_keys,
8672 MRN_COLUMN_NAME_SCORE,
8673 strlen(MRN_COLUMN_NAME_SCORE));
8674 score_sort_key.offset = 0;
8675 score_sort_key.flags = GRN_TABLE_SORT_DESC;
8676 if (sorted_result) {
8677 grn_obj_unlink(ctx, sorted_result);
8678 }
8679 sorted_result = grn_table_create(ctx, NULL,
8680 0, NULL,
8681 GRN_OBJ_TABLE_NO_KEY, NULL,
8682 matched_record_keys);
8683 grn_table_sort(ctx, matched_record_keys, 0, -1,
8684 sorted_result, &score_sort_key, 1);
8685 grn_obj_unlink(ctx, score_sort_key.key);
8686 }
8687 if (sort_keys) {
8688 for (int i = 0; i < n_sort_keys; i++) {
8689 grn_obj_unlink(info->ctx, sort_keys[i].key);
8690 }
8691 my_free(sort_keys);
8692 }
8693
8694 DBUG_RETURN((FT_INFO *)info);
8695 }
8696
wrapper_ft_init_ext(uint flags,uint key_nr,String * key)8697 FT_INFO *ha_mroonga::wrapper_ft_init_ext(uint flags, uint key_nr, String *key)
8698 {
8699 MRN_DBUG_ENTER_METHOD();
8700
8701 FT_INFO *info = generic_ft_init_ext(flags, key_nr, key);
8702 if (!info) {
8703 DBUG_RETURN(NULL);
8704 }
8705
8706 struct st_mrn_ft_info *mrn_ft_info = (struct st_mrn_ft_info *)info;
8707 mrn_ft_info->please = &mrn_wrapper_ft_vft;
8708 #ifdef HA_CAN_FULLTEXT_EXT
8709 mrn_ft_info->could_you = &mrn_wrapper_ft_vft_ext;
8710 #endif
8711 ++wrap_ft_init_count;
8712
8713 DBUG_RETURN(info);
8714 }
8715
storage_ft_init_ext(uint flags,uint key_nr,String * key)8716 FT_INFO *ha_mroonga::storage_ft_init_ext(uint flags, uint key_nr, String *key)
8717 {
8718 MRN_DBUG_ENTER_METHOD();
8719
8720 FT_INFO *info = generic_ft_init_ext(flags, key_nr, key);
8721 if (!info) {
8722 DBUG_RETURN(NULL);
8723 }
8724
8725 struct st_mrn_ft_info *mrn_ft_info = (struct st_mrn_ft_info *)info;
8726 mrn_ft_info->please = &mrn_storage_ft_vft;
8727 #ifdef HA_CAN_FULLTEXT_EXT
8728 mrn_ft_info->could_you = &mrn_storage_ft_vft_ext;
8729 #endif
8730 DBUG_RETURN(info);
8731 }
8732
ft_init_ext(uint flags,uint key_nr,String * key)8733 FT_INFO *ha_mroonga::ft_init_ext(uint flags, uint key_nr, String *key)
8734 {
8735 MRN_DBUG_ENTER_METHOD();
8736 fulltext_searching = true;
8737 FT_INFO *info;
8738 if (key_nr == NO_SUCH_KEY) {
8739 struct st_mrn_ft_info *mrn_ft_info = new st_mrn_ft_info();
8740 mrn_ft_info->please = &mrn_no_such_key_ft_vft;
8741 #ifdef HA_CAN_FULLTEXT_EXT
8742 mrn_ft_info->could_you = &mrn_no_such_key_ft_vft_ext;
8743 #endif
8744 info = (FT_INFO *)mrn_ft_info;
8745 } else {
8746 if (share->wrapper_mode)
8747 {
8748 info = wrapper_ft_init_ext(flags, key_nr, key);
8749 } else {
8750 info = storage_ft_init_ext(flags, key_nr, key);
8751 }
8752 }
8753 DBUG_RETURN(info);
8754 }
8755
wrapper_ft_read(uchar * buf)8756 int ha_mroonga::wrapper_ft_read(uchar *buf)
8757 {
8758 MRN_DBUG_ENTER_METHOD();
8759 if (wrap_ft_init_count)
8760 set_pk_bitmap();
8761
8762 struct st_mrn_ft_info *mrn_ft_info =
8763 reinterpret_cast<struct st_mrn_ft_info *>(ft_handler);
8764 GRN_CTX_SET_ENCODING(ctx, mrn_ft_info->encoding);
8765
8766 int error = 0;
8767 do {
8768 grn_id found_record_id;
8769 found_record_id = grn_table_cursor_next(ctx, mrn_ft_info->cursor);
8770 if (found_record_id == GRN_ID_NIL) {
8771 error = HA_ERR_END_OF_FILE;
8772 break;
8773 }
8774
8775 GRN_BULK_REWIND(&key_buffer);
8776 if (mrn_ft_info->key_accessor) {
8777 grn_obj_get_value(ctx, mrn_ft_info->key_accessor,
8778 found_record_id, &key_buffer);
8779 } else {
8780 void *key;
8781 int key_length;
8782 key_length = grn_table_cursor_get_key(ctx, mrn_ft_info->cursor, &key);
8783 GRN_TEXT_SET(ctx, &key_buffer, key, key_length);
8784 }
8785 error = wrapper_get_record(buf, (const uchar *)GRN_TEXT_VALUE(&key_buffer));
8786 } while (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND);
8787 DBUG_RETURN(error);
8788 }
8789
storage_ft_read(uchar * buf)8790 int ha_mroonga::storage_ft_read(uchar *buf)
8791 {
8792 MRN_DBUG_ENTER_METHOD();
8793 struct st_mrn_ft_info *mrn_ft_info =
8794 reinterpret_cast<struct st_mrn_ft_info *>(ft_handler);
8795 GRN_CTX_SET_ENCODING(ctx, mrn_ft_info->encoding);
8796
8797 grn_id found_record_id;
8798 found_record_id = grn_table_cursor_next(ctx, mrn_ft_info->cursor);
8799 if (ctx->rc) {
8800 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8801 DBUG_RETURN(ER_ERROR_ON_READ);
8802 }
8803
8804 if (found_record_id == GRN_ID_NIL) {
8805 table->status = STATUS_NOT_FOUND;
8806 DBUG_RETURN(HA_ERR_END_OF_FILE);
8807 }
8808 table->status = 0;
8809
8810 if (count_skip && record_id != GRN_ID_NIL) {
8811 DBUG_RETURN(0);
8812 }
8813
8814 GRN_BULK_REWIND(&key_buffer);
8815 if (mrn_ft_info->id_accessor) {
8816 grn_obj id_buffer;
8817 GRN_RECORD_INIT(&id_buffer, 0, grn_obj_id(ctx, grn_table));
8818 grn_obj_get_value(ctx, mrn_ft_info->id_accessor,
8819 found_record_id, &id_buffer);
8820 record_id = GRN_RECORD_VALUE(&id_buffer);
8821 } else if (mrn_ft_info->key_accessor) {
8822 grn_obj_get_value(ctx, mrn_ft_info->key_accessor,
8823 found_record_id, &key_buffer);
8824 record_id = grn_table_get(ctx, grn_table,
8825 GRN_TEXT_VALUE(&key_buffer),
8826 GRN_TEXT_LEN(&key_buffer));
8827 } else {
8828 void *key;
8829 grn_table_cursor_get_key(ctx, mrn_ft_info->cursor, &key);
8830 if (ctx->rc) {
8831 record_id = GRN_ID_NIL;
8832 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8833 DBUG_RETURN(ER_ERROR_ON_READ);
8834 } else {
8835 record_id = *((grn_id *)key);
8836 }
8837 }
8838 storage_store_fields(buf, record_id);
8839 DBUG_RETURN(0);
8840 }
8841
ft_read(uchar * buf)8842 int ha_mroonga::ft_read(uchar *buf)
8843 {
8844 MRN_DBUG_ENTER_METHOD();
8845 int error = 0;
8846 if (share->wrapper_mode)
8847 {
8848 error = wrapper_ft_read(buf);
8849 } else {
8850 error = storage_ft_read(buf);
8851 }
8852 DBUG_RETURN(error);
8853 }
8854
wrapper_cond_push(const Item * cond)8855 const Item *ha_mroonga::wrapper_cond_push(const Item *cond)
8856 {
8857 const Item *reminder_cond;
8858 MRN_DBUG_ENTER_METHOD();
8859 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8860 MRN_SET_WRAP_TABLE_KEY(this, table);
8861 reminder_cond = wrap_handler->cond_push(cond);
8862 MRN_SET_BASE_SHARE_KEY(share, table->s);
8863 MRN_SET_BASE_TABLE_KEY(this, table);
8864 DBUG_RETURN(reminder_cond);
8865 }
8866
storage_cond_push(const Item * cond)8867 const Item *ha_mroonga::storage_cond_push(const Item *cond)
8868 {
8869 MRN_DBUG_ENTER_METHOD();
8870 const Item *reminder_cond = cond;
8871 if (!pushed_cond) {
8872 mrn::ConditionConverter converter(ctx, grn_table, true);
8873 if (converter.count_match_against(cond) == 1 &&
8874 converter.is_convertable(cond)) {
8875 reminder_cond = NULL;
8876 }
8877 }
8878 DBUG_RETURN(reminder_cond);
8879 }
8880
cond_push(const Item * cond)8881 const Item *ha_mroonga::cond_push(const Item *cond)
8882 {
8883 MRN_DBUG_ENTER_METHOD();
8884 const Item *reminder_cond;
8885 if (share->wrapper_mode)
8886 {
8887 reminder_cond = wrapper_cond_push(cond);
8888 } else {
8889 reminder_cond = storage_cond_push(cond);
8890 }
8891 DBUG_RETURN(reminder_cond);
8892 }
8893
wrapper_cond_pop()8894 void ha_mroonga::wrapper_cond_pop()
8895 {
8896 MRN_DBUG_ENTER_METHOD();
8897 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8898 MRN_SET_WRAP_TABLE_KEY(this, table);
8899 wrap_handler->cond_pop();
8900 MRN_SET_BASE_SHARE_KEY(share, table->s);
8901 MRN_SET_BASE_TABLE_KEY(this, table);
8902 DBUG_VOID_RETURN;
8903 }
8904
storage_cond_pop()8905 void ha_mroonga::storage_cond_pop()
8906 {
8907 MRN_DBUG_ENTER_METHOD();
8908 DBUG_VOID_RETURN;
8909 }
8910
cond_pop()8911 void ha_mroonga::cond_pop()
8912 {
8913 MRN_DBUG_ENTER_METHOD();
8914 if (share->wrapper_mode)
8915 wrapper_cond_pop();
8916 else
8917 storage_cond_pop();
8918 DBUG_VOID_RETURN;
8919 }
8920
wrapper_get_error_message(int error,String * buf)8921 bool ha_mroonga::wrapper_get_error_message(int error, String *buf)
8922 {
8923 bool temporary_error;
8924 MRN_DBUG_ENTER_METHOD();
8925 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8926 MRN_SET_WRAP_TABLE_KEY(this, table);
8927 temporary_error = wrap_handler->get_error_message(error, buf);
8928 MRN_SET_BASE_SHARE_KEY(share, table->s);
8929 MRN_SET_BASE_TABLE_KEY(this, table);
8930 DBUG_RETURN(temporary_error);
8931 }
8932
storage_get_error_message(int error,String * buf)8933 bool ha_mroonga::storage_get_error_message(int error, String *buf)
8934 {
8935 MRN_DBUG_ENTER_METHOD();
8936 bool temporary_error = false;
8937 // latest error message
8938 buf->copy(ctx->errbuf, (uint) strlen(ctx->errbuf), system_charset_info);
8939 DBUG_RETURN(temporary_error);
8940 }
8941
get_error_message(int error,String * buf)8942 bool ha_mroonga::get_error_message(int error, String *buf)
8943 {
8944 MRN_DBUG_ENTER_METHOD();
8945 bool temporary_error;
8946 if (share && share->wrapper_mode)
8947 {
8948 temporary_error = wrapper_get_error_message(error, buf);
8949 } else {
8950 temporary_error = storage_get_error_message(error, buf);
8951 }
8952 DBUG_RETURN(temporary_error);
8953 }
8954
file_size(const char * path)8955 ulonglong ha_mroonga::file_size(const char *path)
8956 {
8957 MRN_DBUG_ENTER_METHOD();
8958
8959 struct stat file_status;
8960 if (stat(path, &file_status) == 0) {
8961 DBUG_RETURN(file_status.st_size);
8962 } else {
8963 DBUG_RETURN(0);
8964 }
8965 }
8966
have_unique_index()8967 bool ha_mroonga::have_unique_index()
8968 {
8969 MRN_DBUG_ENTER_METHOD();
8970
8971 uint n_keys = table->s->keys;
8972
8973 for (uint i = 0; i < n_keys; i++) {
8974 if (i == table->s->primary_key) {
8975 continue;
8976 }
8977
8978 KEY *key_info = &(table->key_info[i]);
8979 if (key_info->flags & HA_NOSAME) {
8980 DBUG_RETURN(true);
8981 }
8982 }
8983
8984 DBUG_RETURN(false);
8985 }
8986
is_foreign_key_field(const char * table_name,const char * field_name)8987 bool ha_mroonga::is_foreign_key_field(const char *table_name,
8988 const char *field_name)
8989 {
8990 MRN_DBUG_ENTER_METHOD();
8991
8992 grn_obj *table = grn_ctx_get(ctx, table_name, -1);
8993 if (!table) {
8994 DBUG_RETURN(false);
8995 }
8996
8997 mrn::ColumnName column_name(field_name);
8998 grn_obj *column = grn_obj_column(ctx,
8999 table,
9000 column_name.c_str(),
9001 column_name.length());
9002 if (!column) {
9003 DBUG_RETURN(false);
9004 }
9005
9006 grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, column));
9007 if (!range) {
9008 grn_obj_unlink(ctx, column);
9009 DBUG_RETURN(false);
9010 }
9011
9012 if (!mrn::grn::is_table(range)) {
9013 grn_obj_unlink(ctx, column);
9014 DBUG_RETURN(false);
9015 }
9016
9017 grn_obj *foreign_index_column;
9018 mrn::IndexColumnName index_column_name(table_name, field_name);
9019 foreign_index_column = grn_obj_column(ctx, range,
9020 index_column_name.c_str(),
9021 index_column_name.length());
9022 if (foreign_index_column) {
9023 grn_obj_unlink(ctx, foreign_index_column);
9024 DBUG_RETURN(true);
9025 }
9026
9027 grn_obj_unlink(ctx, column);
9028 DBUG_RETURN(false);
9029 }
9030
push_warning_unsupported_spatial_index_search(enum ha_rkey_function flag)9031 void ha_mroonga::push_warning_unsupported_spatial_index_search(enum ha_rkey_function flag)
9032 {
9033 char search_name[MRN_BUFFER_SIZE];
9034 if (flag == HA_READ_MBR_INTERSECT) {
9035 strcpy(search_name, "intersect");
9036 } else if (flag == HA_READ_MBR_WITHIN) {
9037 strcpy(search_name, "within");
9038 } else if (flag & HA_READ_MBR_DISJOINT) {
9039 strcpy(search_name, "disjoint");
9040 } else if (flag & HA_READ_MBR_EQUAL) {
9041 strcpy(search_name, "equal");
9042 } else {
9043 sprintf(search_name, "unknown: %d", flag);
9044 }
9045 push_warning_printf(ha_thd(),
9046 MRN_SEVERITY_WARNING,
9047 ER_UNSUPPORTED_EXTENSION,
9048 "spatial index search "
9049 "except MBRContains aren't supported: <%s>",
9050 search_name);
9051 }
9052
clear_cursor()9053 void ha_mroonga::clear_cursor()
9054 {
9055 MRN_DBUG_ENTER_METHOD();
9056 if (cursor) {
9057 grn_obj_unlink(ctx, cursor);
9058 cursor = NULL;
9059 }
9060 if (index_table_cursor) {
9061 grn_table_cursor_close(ctx, index_table_cursor);
9062 index_table_cursor = NULL;
9063 }
9064 DBUG_VOID_RETURN;
9065 }
9066
clear_cursor_geo()9067 void ha_mroonga::clear_cursor_geo()
9068 {
9069 MRN_DBUG_ENTER_METHOD();
9070 if (cursor_geo) {
9071 grn_obj_unlink(ctx, cursor_geo);
9072 cursor_geo = NULL;
9073 }
9074 DBUG_VOID_RETURN;
9075 }
9076
clear_empty_value_records()9077 void ha_mroonga::clear_empty_value_records()
9078 {
9079 MRN_DBUG_ENTER_METHOD();
9080 if (empty_value_records_cursor) {
9081 grn_table_cursor_close(ctx, empty_value_records_cursor);
9082 empty_value_records_cursor = NULL;
9083 }
9084 if (empty_value_records) {
9085 grn_obj_unlink(ctx, empty_value_records);
9086 empty_value_records = NULL;
9087 }
9088 DBUG_VOID_RETURN;
9089 }
9090
clear_search_result()9091 void ha_mroonga::clear_search_result()
9092 {
9093 MRN_DBUG_ENTER_METHOD();
9094 clear_cursor();
9095 if (sorted_result) {
9096 grn_obj_unlink(ctx, sorted_result);
9097 sorted_result = NULL;
9098 }
9099 if (matched_record_keys) {
9100 grn_obj_unlink(ctx, matched_record_keys);
9101 matched_record_keys = NULL;
9102 }
9103 DBUG_VOID_RETURN;
9104 }
9105
clear_search_result_geo()9106 void ha_mroonga::clear_search_result_geo()
9107 {
9108 MRN_DBUG_ENTER_METHOD();
9109 clear_cursor_geo();
9110 if (grn_source_column_geo) {
9111 grn_obj_unlink(ctx, grn_source_column_geo);
9112 grn_source_column_geo = NULL;
9113 }
9114 DBUG_VOID_RETURN;
9115 }
9116
clear_indexes()9117 void ha_mroonga::clear_indexes()
9118 {
9119 MRN_DBUG_ENTER_METHOD();
9120 uint n_keys = table->s->keys;
9121 uint pkey_nr = table->s->primary_key;
9122
9123 for (uint i = 0; i < n_keys; i++) {
9124 if (i != pkey_nr) {
9125 if (grn_index_tables) {
9126 grn_obj_unlink(ctx, grn_index_tables[i]);
9127 }
9128 if (grn_index_columns) {
9129 grn_obj_unlink(ctx, grn_index_columns[i]);
9130 }
9131 }
9132 }
9133
9134 if (grn_index_tables) {
9135 free(grn_index_tables);
9136 grn_index_tables = NULL;
9137 }
9138
9139 if (grn_index_columns) {
9140 free(grn_index_columns);
9141 grn_index_columns = NULL;
9142 }
9143
9144 if (key_id) {
9145 free(key_id);
9146 key_id = NULL;
9147 }
9148
9149 if (del_key_id) {
9150 free(del_key_id);
9151 del_key_id = NULL;
9152 }
9153
9154 DBUG_VOID_RETURN;
9155 }
9156
add_wrap_hton(const char * path,handlerton * wrap_handlerton)9157 int ha_mroonga::add_wrap_hton(const char *path, handlerton *wrap_handlerton)
9158 {
9159 MRN_DBUG_ENTER_METHOD();
9160 st_mrn_slot_data *slot_data = mrn_get_slot_data(ha_thd(), true);
9161 if (!slot_data)
9162 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
9163 st_mrn_wrap_hton *wrap_hton =
9164 (st_mrn_wrap_hton *)malloc(sizeof(st_mrn_wrap_hton));
9165 if (!wrap_hton)
9166 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
9167 wrap_hton->next = NULL;
9168 strcpy(wrap_hton->path, path);
9169 wrap_hton->hton = wrap_handlerton;
9170 if (slot_data->first_wrap_hton)
9171 {
9172 st_mrn_wrap_hton *tmp_wrap_hton = slot_data->first_wrap_hton;
9173 while (tmp_wrap_hton->next)
9174 tmp_wrap_hton = tmp_wrap_hton->next;
9175 tmp_wrap_hton->next = wrap_hton;
9176 } else {
9177 slot_data->first_wrap_hton = wrap_hton;
9178 }
9179 DBUG_RETURN(0);
9180 }
9181
remove_related_files(const char * base_path)9182 void ha_mroonga::remove_related_files(const char *base_path)
9183 {
9184 MRN_DBUG_ENTER_METHOD();
9185
9186 const char *base_directory_name = ".";
9187 size_t base_path_length = strlen(base_path);
9188 #ifdef WIN32
9189 WIN32_FIND_DATA data;
9190 HANDLE finder = FindFirstFile(base_directory_name, &data);
9191 if (finder != INVALID_HANDLE_VALUE) {
9192 do {
9193 if (!(data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)) {
9194 continue;
9195 }
9196 if (strncmp(data.cFileName, base_path, base_path_length) == 0) {
9197 unlink(data.cFileName);
9198 }
9199 } while (FindNextFile(finder, &data) != 0);
9200 FindClose(finder);
9201 }
9202 #else
9203 DIR *dir = opendir(base_directory_name);
9204 if (dir) {
9205 while (struct dirent *entry = readdir(dir)) {
9206 struct stat file_status;
9207 if (stat(entry->d_name, &file_status) != 0) {
9208 continue;
9209 }
9210 if (!((file_status.st_mode & S_IFMT) == S_IFREG)) {
9211 continue;
9212 }
9213 if (strncmp(entry->d_name, base_path, base_path_length) == 0) {
9214 unlink(entry->d_name);
9215 }
9216 }
9217 closedir(dir);
9218 }
9219 #endif
9220
9221 DBUG_VOID_RETURN;
9222 }
9223
remove_grn_obj_force(const char * name)9224 void ha_mroonga::remove_grn_obj_force(const char *name)
9225 {
9226 MRN_DBUG_ENTER_METHOD();
9227
9228 grn_obj *obj = grn_ctx_get(ctx, name, strlen(name));
9229 if (obj) {
9230 grn_obj_remove(ctx, obj);
9231 } else {
9232 grn_obj *db = grn_ctx_db(ctx);
9233 grn_id id = grn_table_get(ctx, db, name, strlen(name));
9234 if (id) {
9235 char path[MRN_MAX_PATH_SIZE];
9236 grn_obj_delete_by_id(ctx, db, id, GRN_TRUE);
9237 if (grn_obj_path_by_id(ctx, db, id, path) == GRN_SUCCESS) {
9238 remove_related_files(path);
9239 }
9240 }
9241 }
9242
9243 DBUG_VOID_RETURN;
9244 }
9245
drop_index(MRN_SHARE * target_share,uint key_index)9246 int ha_mroonga::drop_index(MRN_SHARE *target_share, uint key_index)
9247 {
9248 MRN_DBUG_ENTER_METHOD();
9249 int error = 0;
9250 grn_rc rc = GRN_SUCCESS;
9251 char target_name[GRN_TABLE_MAX_KEY_SIZE];
9252 int target_name_length;
9253
9254 KEY *key_info = target_share->table_share->key_info;
9255 if (!target_share->wrapper_mode && target_share->index_table[key_index]) {
9256 const char *table_name = target_share->index_table[key_index];
9257 snprintf(target_name, GRN_TABLE_MAX_KEY_SIZE,
9258 "%s.%s", table_name, key_info[key_index].name.str);
9259 target_name_length = strlen(target_name);
9260 grn_obj *index_column = grn_ctx_get(ctx, target_name, target_name_length);
9261 if (index_column) {
9262 rc = grn_obj_remove(ctx, index_column);
9263 }
9264 } else {
9265 mrn::PathMapper mapper(target_share->table_name);
9266 mrn::IndexTableName index_table_name(mapper.table_name(),
9267 key_info[key_index].name.str);
9268 grn_obj *index_table = grn_ctx_get(ctx,
9269 index_table_name.c_str(),
9270 index_table_name.length());
9271 if (!index_table) {
9272 index_table = grn_ctx_get(ctx,
9273 index_table_name.old_c_str(),
9274 index_table_name.old_length());
9275 }
9276 if (index_table) {
9277 target_name_length = grn_obj_name(ctx, index_table,
9278 target_name, GRN_TABLE_MAX_KEY_SIZE);
9279 rc = grn_obj_remove(ctx, index_table);
9280 } else {
9281 target_name_length = 0;
9282 }
9283 }
9284
9285 if (rc != GRN_SUCCESS) {
9286 char error_message[MRN_MESSAGE_BUFFER_SIZE];
9287 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
9288 "failed to drop index: <%.*s>: <%s>",
9289 target_name_length, target_name,
9290 ctx->errbuf);
9291 my_message(ER_ERROR_ON_WRITE, error_message, MYF(0));
9292 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
9293 }
9294
9295 DBUG_RETURN(error);
9296 }
9297
drop_indexes_normal(const char * table_name,grn_obj * table)9298 int ha_mroonga::drop_indexes_normal(const char *table_name, grn_obj *table)
9299 {
9300 MRN_DBUG_ENTER_METHOD();
9301
9302 int error = 0;
9303
9304 grn_hash *columns_raw = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
9305 GRN_OBJ_TABLE_HASH_KEY);
9306 mrn::SmartGrnObj columns(ctx, reinterpret_cast<grn_obj *>(columns_raw));
9307 if (!columns.get()) {
9308 char error_message[MRN_MESSAGE_BUFFER_SIZE];
9309 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
9310 "failed to allocate columns buffer: <%s>: <%s>",
9311 table_name, ctx->errbuf);
9312 error = HA_ERR_OUT_OF_MEM;
9313 my_message(ER_ERROR_ON_WRITE, error_message, MYF(0));
9314 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
9315 DBUG_RETURN(error);
9316 }
9317
9318 grn_table_columns(ctx, table, "", 0, columns.get());
9319 grn_table_cursor *cursor = grn_table_cursor_open(ctx,
9320 columns.get(),
9321 NULL, 0,
9322 NULL, 0,
9323 0, -1,
9324 0);
9325 if (!cursor) {
9326 char error_message[MRN_MESSAGE_BUFFER_SIZE];
9327 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
9328 "failed to allocate columns cursor: <%s>: <%s>",
9329 table_name, ctx->errbuf);
9330 error = HA_ERR_OUT_OF_MEM;
9331 my_message(ER_ERROR_ON_WRITE, error_message, MYF(0));
9332 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
9333 DBUG_RETURN(error);
9334 }
9335
9336 while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) {
9337 void *key;
9338 grn_table_cursor_get_key(ctx, cursor, &key);
9339 grn_id *id = reinterpret_cast<grn_id *>(key);
9340 mrn::SmartGrnObj column(ctx, grn_ctx_at(ctx, *id));
9341 if (!column.get()) {
9342 continue;
9343 }
9344
9345 grn_operator index_operators[] = {
9346 GRN_OP_EQUAL,
9347 GRN_OP_MATCH,
9348 GRN_OP_LESS,
9349 GRN_OP_REGEXP
9350 };
9351 size_t n_index_operators = sizeof(index_operators) / sizeof(grn_operator);
9352 for (size_t i = 0; i < n_index_operators; i++) {
9353 grn_index_datum index_datum;
9354 while (grn_column_find_index_data(ctx,
9355 column.get(),
9356 index_operators[i],
9357 &index_datum,
9358 1) > 0) {
9359 grn_id index_table_id = index_datum.index->header.domain;
9360 mrn::SmartGrnObj index_table(ctx, grn_ctx_at(ctx, index_table_id));
9361 char index_table_name[GRN_TABLE_MAX_KEY_SIZE];
9362 int index_table_name_length;
9363 index_table_name_length = grn_obj_name(ctx, index_table.get(),
9364 index_table_name,
9365 GRN_TABLE_MAX_KEY_SIZE);
9366 if (mrn::IndexTableName::is_custom_name(table_name,
9367 strlen(table_name),
9368 index_table_name,
9369 index_table_name_length)) {
9370 char index_column_name[GRN_TABLE_MAX_KEY_SIZE];
9371 int index_column_name_length;
9372 index_column_name_length = grn_obj_name(ctx,
9373 index_datum.index,
9374 index_column_name,
9375 GRN_TABLE_MAX_KEY_SIZE);
9376 grn_rc rc = grn_obj_remove(ctx, index_datum.index);
9377 if (rc != GRN_SUCCESS) {
9378 char error_message[MRN_MESSAGE_BUFFER_SIZE];
9379 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
9380 "failed to drop index column: <%.*s>: <%s>",
9381 index_column_name_length, index_column_name,
9382 ctx->errbuf);
9383 error = ER_ERROR_ON_WRITE;
9384 my_message(error, error_message, MYF(0));
9385 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
9386 }
9387 } else {
9388 grn_rc rc = grn_obj_remove(ctx, index_table.get());
9389 if (rc == GRN_SUCCESS) {
9390 index_table.release();
9391 } else {
9392 char error_message[MRN_MESSAGE_BUFFER_SIZE];
9393 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
9394 "failed to drop index table: <%.*s>: <%s>",
9395 index_table_name_length, index_table_name,
9396 ctx->errbuf);
9397 error = ER_ERROR_ON_WRITE;
9398 my_message(error, error_message, MYF(0));
9399 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
9400 }
9401 }
9402
9403 if (error != 0) {
9404 break;
9405 }
9406 }
9407
9408 if (error != 0) {
9409 break;
9410 }
9411 }
9412
9413 if (error != 0) {
9414 break;
9415 }
9416 }
9417
9418 grn_table_cursor_close(ctx, cursor);
9419
9420 DBUG_RETURN(error);
9421 }
9422
drop_indexes_multiple(const char * table_name,grn_obj * table,const char * index_table_name_separator)9423 int ha_mroonga::drop_indexes_multiple(const char *table_name,
9424 grn_obj *table,
9425 const char *index_table_name_separator)
9426 {
9427 MRN_DBUG_ENTER_METHOD();
9428
9429 int error = 0;
9430
9431 char index_table_name_prefix[GRN_TABLE_MAX_KEY_SIZE];
9432 snprintf(index_table_name_prefix, GRN_TABLE_MAX_KEY_SIZE,
9433 "%s%s", table_name, index_table_name_separator);
9434 grn_table_cursor *cursor =
9435 grn_table_cursor_open(ctx,
9436 grn_ctx_db(ctx),
9437 index_table_name_prefix,
9438 strlen(index_table_name_prefix),
9439 NULL, 0,
9440 0, -1,
9441 GRN_CURSOR_PREFIX);
9442 if (!cursor) {
9443 char error_message[MRN_MESSAGE_BUFFER_SIZE];
9444 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
9445 "failed to allocate index tables cursor: <%s>: <%s>",
9446 table_name, ctx->errbuf);
9447 error = HA_ERR_OUT_OF_MEM;
9448 my_message(ER_ERROR_ON_WRITE, error_message, MYF(0));
9449 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
9450 DBUG_RETURN(error);
9451 }
9452
9453 grn_id table_id = grn_obj_id(ctx, table);
9454 grn_id id;
9455 while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) {
9456 mrn::SmartGrnObj object(ctx, grn_ctx_at(ctx, id));
9457 if (!object.get()) {
9458 continue;
9459 }
9460 if (!grn_obj_is_table(ctx, object.get())) {
9461 continue;
9462 }
9463
9464 char multiple_column_index_table_name[GRN_TABLE_MAX_KEY_SIZE];
9465 int multiple_column_index_table_name_length;
9466 multiple_column_index_table_name_length =
9467 grn_obj_name(ctx,
9468 object.get(),
9469 multiple_column_index_table_name,
9470 GRN_TABLE_MAX_KEY_SIZE);
9471
9472 char multiple_column_index_name[GRN_TABLE_MAX_KEY_SIZE];
9473 snprintf(multiple_column_index_name, GRN_TABLE_MAX_KEY_SIZE,
9474 "%.*s.%s",
9475 multiple_column_index_table_name_length,
9476 multiple_column_index_table_name,
9477 INDEX_COLUMN_NAME);
9478 mrn::SmartGrnObj index_column(ctx, multiple_column_index_name);
9479 if (!index_column.get()) {
9480 continue;
9481 }
9482
9483 if (grn_obj_get_range(ctx, index_column.get()) != table_id) {
9484 continue;
9485 }
9486
9487 grn_rc rc = grn_obj_remove(ctx, object.get());
9488 if (rc == GRN_SUCCESS) {
9489 object.release();
9490 index_column.release();
9491 } else {
9492 char error_message[MRN_MESSAGE_BUFFER_SIZE];
9493 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
9494 "failed to drop multiple column index table: <%.*s>: <%s>",
9495 multiple_column_index_table_name_length,
9496 multiple_column_index_table_name,
9497 ctx->errbuf);
9498 error = ER_ERROR_ON_WRITE;
9499 my_message(error, error_message, MYF(0));
9500 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
9501 break;
9502 }
9503 }
9504
9505 grn_table_cursor_close(ctx, cursor);
9506
9507 DBUG_RETURN(error);
9508 }
9509
drop_indexes(const char * table_name)9510 int ha_mroonga::drop_indexes(const char *table_name)
9511 {
9512 MRN_DBUG_ENTER_METHOD();
9513 int error = 0;
9514
9515 mrn::SmartGrnObj table(ctx, table_name);
9516 if (!table.get()) {
9517 DBUG_RETURN(0);
9518 }
9519
9520 error = drop_indexes_normal(table_name, table.get());
9521 if (error == 0) {
9522 error = drop_indexes_multiple(table_name, table.get(),
9523 mrn::IndexTableName::SEPARATOR);
9524 }
9525 if (error == 0) {
9526 error = drop_indexes_multiple(table_name, table.get(),
9527 mrn::IndexTableName::OLD_SEPARATOR);
9528 }
9529
9530 DBUG_RETURN(error);
9531 }
9532
find_column_flags(Field * field,MRN_SHARE * mrn_share,int i,grn_obj_flags * column_flags)9533 bool ha_mroonga::find_column_flags(Field *field, MRN_SHARE *mrn_share, int i,
9534 grn_obj_flags *column_flags)
9535 {
9536 MRN_DBUG_ENTER_METHOD();
9537 bool found = false;
9538
9539 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
9540 {
9541 const char *names = field->option_struct->flags;
9542 if (names) {
9543 found = mrn_parse_grn_column_create_flags(ha_thd(),
9544 ctx,
9545 names,
9546 strlen(names),
9547 column_flags);
9548 DBUG_RETURN(found);
9549 }
9550 }
9551 #endif
9552
9553 if (mrn_share->col_flags[i]) {
9554 found = mrn_parse_grn_column_create_flags(ha_thd(),
9555 ctx,
9556 mrn_share->col_flags[i],
9557 mrn_share->col_flags_length[i],
9558 column_flags);
9559 DBUG_RETURN(found);
9560 }
9561
9562 DBUG_RETURN(found);
9563 }
9564
find_column_type(Field * field,MRN_SHARE * mrn_share,int i,int error_code)9565 grn_obj *ha_mroonga::find_column_type(Field *field, MRN_SHARE *mrn_share, int i,
9566 int error_code)
9567 {
9568 MRN_DBUG_ENTER_METHOD();
9569
9570 const char *grn_type_name = NULL;
9571 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
9572 grn_type_name = field->option_struct->groonga_type;
9573 #endif
9574 if (!grn_type_name) {
9575 grn_type_name = mrn_share->col_type[i];
9576 }
9577
9578 grn_obj *type = NULL;
9579 if (grn_type_name) {
9580 type = grn_ctx_get(ctx, grn_type_name, -1);
9581 if (!type) {
9582 char error_message[MRN_BUFFER_SIZE];
9583 snprintf(error_message, MRN_BUFFER_SIZE,
9584 "unknown custom Groonga type name for <%s> column: <%s>",
9585 field->field_name.str, grn_type_name);
9586 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
9587 my_message(error_code, error_message, MYF(0));
9588
9589 DBUG_RETURN(NULL);
9590 }
9591 } else {
9592 grn_builtin_type grn_type_id = mrn_grn_type_from_field(ctx, field, false);
9593 type = grn_ctx_at(ctx, grn_type_id);
9594 }
9595
9596 DBUG_RETURN(type);
9597 }
9598
find_tokenizer(KEY * key,MRN_SHARE * mrn_share,int i)9599 grn_obj *ha_mroonga::find_tokenizer(KEY *key, MRN_SHARE *mrn_share, int i)
9600 {
9601 MRN_DBUG_ENTER_METHOD();
9602 grn_obj *tokenizer;
9603 const char *tokenizer_name = NULL;
9604 uint tokenizer_name_length = 0;
9605 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
9606 if (key->option_struct->tokenizer) {
9607 tokenizer_name = key->option_struct->tokenizer;
9608 tokenizer_name_length = strlen(tokenizer_name);
9609 }
9610 #endif
9611 if (!tokenizer_name) {
9612 tokenizer_name = mrn_share->key_tokenizer[i];
9613 tokenizer_name_length = mrn_share->key_tokenizer_length[i];
9614 }
9615 tokenizer = find_tokenizer(tokenizer_name, tokenizer_name_length);
9616 DBUG_RETURN(tokenizer);
9617 }
9618
find_tokenizer(const char * name,int name_length)9619 grn_obj *ha_mroonga::find_tokenizer(const char *name, int name_length)
9620 {
9621 MRN_DBUG_ENTER_METHOD();
9622
9623 if (strncasecmp("off", name, name_length) == 0) {
9624 DBUG_RETURN(NULL);
9625 }
9626
9627 grn_obj *tokenizer;
9628 mrn_change_encoding(ctx, system_charset_info);
9629 tokenizer = grn_ctx_get(ctx, name, name_length);
9630 if (!tokenizer) {
9631 char message[MRN_BUFFER_SIZE];
9632 sprintf(message,
9633 "specified tokenizer for fulltext index <%.*s> doesn't exist. "
9634 "The default tokenizer for fulltext index <%s> is used instead.",
9635 name_length, name,
9636 MRN_DEFAULT_TOKENIZER);
9637 push_warning(ha_thd(),
9638 MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION,
9639 message);
9640 tokenizer = grn_ctx_get(ctx,
9641 MRN_DEFAULT_TOKENIZER,
9642 strlen(MRN_DEFAULT_TOKENIZER));
9643 }
9644 if (!tokenizer) {
9645 push_warning(ha_thd(),
9646 MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION,
9647 "couldn't find tokenizer for fulltext index. "
9648 "Bigram tokenizer is used instead.");
9649 tokenizer = grn_ctx_at(ctx, GRN_DB_BIGRAM);
9650 }
9651 DBUG_RETURN(tokenizer);
9652 }
9653
have_custom_normalizer(KEY * key) const9654 bool ha_mroonga::have_custom_normalizer(KEY *key) const
9655 {
9656 MRN_DBUG_ENTER_METHOD();
9657
9658 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
9659 if (key->option_struct && key->option_struct->normalizer) {
9660 DBUG_RETURN(true);
9661 }
9662 #endif
9663
9664 if (key->comment.length > 0) {
9665 mrn::ParametersParser parser(key->comment.str,
9666 key->comment.length);
9667 parser.parse();
9668 DBUG_RETURN(parser["normalizer"] != NULL);
9669 }
9670
9671 DBUG_RETURN(false);
9672 }
9673
find_normalizer(KEY * key)9674 grn_obj *ha_mroonga::find_normalizer(KEY *key)
9675 {
9676 MRN_DBUG_ENTER_METHOD();
9677
9678 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
9679 if (key->option_struct->normalizer) {
9680 grn_obj *normalizer = find_normalizer(key,
9681 key->option_struct->normalizer);
9682 DBUG_RETURN(normalizer);
9683 }
9684 #endif
9685
9686 if (key->comment.length > 0) {
9687 mrn::ParametersParser parser(key->comment.str,
9688 key->comment.length);
9689 parser.parse();
9690 grn_obj *normalizer = find_normalizer(key, parser["normalizer"]);
9691 DBUG_RETURN(normalizer);
9692 }
9693
9694 grn_obj *normalizer = find_normalizer(key, NULL);
9695 DBUG_RETURN(normalizer);
9696 }
9697
find_normalizer(KEY * key,const char * name)9698 grn_obj *ha_mroonga::find_normalizer(KEY *key, const char *name)
9699 {
9700 MRN_DBUG_ENTER_METHOD();
9701
9702 grn_obj *normalizer = NULL;
9703 bool use_normalizer = true;
9704 if (name) {
9705 if (strcmp(name, "none") == 0) {
9706 use_normalizer = false;
9707 } else {
9708 normalizer = grn_ctx_get(ctx, name, -1);
9709 }
9710 }
9711 if (use_normalizer && !normalizer) {
9712 Field *field = key->key_part[0].field;
9713 mrn::FieldNormalizer field_normalizer(ctx, ha_thd(), field);
9714 normalizer = field_normalizer.find_grn_normalizer();
9715 }
9716
9717 DBUG_RETURN(normalizer);
9718 }
9719
find_index_column_flags(KEY * key,grn_column_flags * index_column_flags)9720 bool ha_mroonga::find_index_column_flags(KEY *key, grn_column_flags *index_column_flags)
9721 {
9722 MRN_DBUG_ENTER_METHOD();
9723 bool found = false;
9724
9725 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
9726 {
9727 const char *names = key->option_struct->flags;
9728 if (names) {
9729 found = mrn_parse_grn_index_column_flags(ha_thd(),
9730 ctx,
9731 names,
9732 strlen(names),
9733 index_column_flags);
9734 DBUG_RETURN(found);
9735 }
9736 }
9737 #endif
9738
9739 if (key->comment.length > 0) {
9740 mrn::ParametersParser parser(key->comment.str,
9741 key->comment.length);
9742 parser.parse();
9743 const char *names = parser["flags"];
9744 if (!names) {
9745 // Deprecated. It's for backward compatibility.
9746 names = parser["index_flags"];
9747 }
9748 if (names) {
9749 found = mrn_parse_grn_index_column_flags(ha_thd(),
9750 ctx,
9751 names,
9752 strlen(names),
9753 index_column_flags);
9754 }
9755 }
9756
9757 DBUG_RETURN(found);
9758 }
9759
find_token_filters(KEY * key,grn_obj * token_filters)9760 bool ha_mroonga::find_token_filters(KEY *key, grn_obj *token_filters)
9761 {
9762 MRN_DBUG_ENTER_METHOD();
9763 bool found = false;
9764
9765 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
9766 if (key->option_struct->token_filters) {
9767 found = find_token_filters_fill(token_filters,
9768 key->option_struct->token_filters,
9769 strlen(key->option_struct->token_filters));
9770 DBUG_RETURN(found);
9771 }
9772 #endif
9773
9774 if (key->comment.length > 0) {
9775 mrn::ParametersParser parser(key->comment.str,
9776 key->comment.length);
9777 parser.parse();
9778 const char *names = parser["token_filters"];
9779 if (names) {
9780 found = find_token_filters_fill(token_filters, names, strlen(names));
9781 }
9782 }
9783
9784 DBUG_RETURN(found);
9785 }
9786
find_token_filters_put(grn_obj * token_filters,const char * token_filter_name,int token_filter_name_length)9787 bool ha_mroonga::find_token_filters_put(grn_obj *token_filters,
9788 const char *token_filter_name,
9789 int token_filter_name_length)
9790 {
9791 grn_obj *token_filter;
9792
9793 token_filter = grn_ctx_get(ctx,
9794 token_filter_name,
9795 token_filter_name_length);
9796 if (token_filter) {
9797 GRN_PTR_PUT(ctx, token_filters, token_filter);
9798 return true;
9799 } else {
9800 char message[MRN_BUFFER_SIZE];
9801 sprintf(message,
9802 "nonexistent token filter: <%.*s>",
9803 token_filter_name_length, token_filter_name);
9804 push_warning(ha_thd(),
9805 MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION,
9806 message);
9807 return false;
9808 }
9809 }
9810
find_token_filters_fill(grn_obj * token_filters,const char * token_filter_names,int token_filter_names_length)9811 bool ha_mroonga::find_token_filters_fill(grn_obj *token_filters,
9812 const char *token_filter_names,
9813 int token_filter_names_length)
9814 {
9815 const char *start, *current, *end;
9816 const char *name_start, *name_end;
9817 const char *last_name_end;
9818
9819 start = token_filter_names;
9820 end = start + token_filter_names_length;
9821 current = start;
9822 name_start = NULL;
9823 name_end = NULL;
9824 last_name_end = start;
9825 while (current < end) {
9826 switch (current[0]) {
9827 case ' ' :
9828 if (name_start && !name_end) {
9829 name_end = current;
9830 }
9831 break;
9832 case ',' :
9833 if (!name_start) {
9834 goto break_loop;
9835 }
9836 if (!name_end) {
9837 name_end = current;
9838 }
9839 find_token_filters_put(token_filters,
9840 name_start,
9841 name_end - name_start);
9842 last_name_end = name_end + 1;
9843 name_start = NULL;
9844 name_end = NULL;
9845 break;
9846 default :
9847 if (!name_start) {
9848 name_start = current;
9849 }
9850 break;
9851 }
9852 current++;
9853 }
9854
9855 break_loop:
9856 if (!name_start) {
9857 char message[MRN_BUFFER_SIZE];
9858 sprintf(message,
9859 "empty token filter name: "
9860 "<%.*s|%.*s|%.*s>",
9861 (int)(last_name_end - start), start,
9862 (int)(current - last_name_end), last_name_end,
9863 (int)(end - current), current);
9864 push_warning(ha_thd(),
9865 MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION,
9866 message);
9867 return false;
9868 }
9869
9870 if (!name_end) {
9871 name_end = current;
9872 }
9873 find_token_filters_put(token_filters,
9874 name_start,
9875 name_end - name_start);
9876
9877 return true;
9878 }
9879
wrapper_get_record(uchar * buf,const uchar * key)9880 int ha_mroonga::wrapper_get_record(uchar *buf, const uchar *key)
9881 {
9882 MRN_DBUG_ENTER_METHOD();
9883
9884 int error = 0;
9885 MRN_SET_WRAP_SHARE_KEY(share, table->s);
9886 MRN_SET_WRAP_TABLE_KEY(this, table);
9887 if (wrap_handler->inited == NONE) {
9888 #ifdef MRN_HANDLER_HAVE_HA_INDEX_READ_IDX_MAP
9889 error = wrap_handler->ha_index_read_idx_map(buf,
9890 share->wrap_primary_key,
9891 key,
9892 pk_keypart_map,
9893 HA_READ_KEY_EXACT);
9894 #else
9895 error = wrap_handler->index_read_idx_map(buf,
9896 share->wrap_primary_key,
9897 key,
9898 pk_keypart_map,
9899 HA_READ_KEY_EXACT);
9900 #endif
9901 } else {
9902 #ifdef MRN_HANDLER_HAVE_HA_INDEX_READ_MAP
9903 error = wrap_handler->ha_index_read_map(buf,
9904 key,
9905 pk_keypart_map,
9906 HA_READ_KEY_EXACT);
9907 #else
9908 error = wrap_handler->index_read_map(buf,
9909 key,
9910 pk_keypart_map,
9911 HA_READ_KEY_EXACT);
9912 #endif
9913 }
9914 MRN_SET_BASE_SHARE_KEY(share, table->s);
9915 MRN_SET_BASE_TABLE_KEY(this, table);
9916
9917 DBUG_RETURN(error);
9918 }
9919
wrapper_get_next_geo_record(uchar * buf)9920 int ha_mroonga::wrapper_get_next_geo_record(uchar *buf)
9921 {
9922 MRN_DBUG_ENTER_METHOD();
9923 int error = 0;
9924 mrn_change_encoding(ctx, NULL);
9925 do {
9926 GRN_BULK_REWIND(&key_buffer);
9927 grn_id found_record_id;
9928 grn_posting *posting;
9929 posting = grn_geo_cursor_next(ctx, cursor_geo);
9930 if (!posting) {
9931 error = HA_ERR_END_OF_FILE;
9932 clear_cursor_geo();
9933 break;
9934 }
9935 found_record_id = posting->rid;
9936 grn_table_get_key(ctx, grn_table, found_record_id,
9937 GRN_TEXT_VALUE(&key_buffer),
9938 table->key_info->key_length);
9939 error = wrapper_get_record(buf, (const uchar *)GRN_TEXT_VALUE(&key_buffer));
9940 } while (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND);
9941 DBUG_RETURN(error);
9942 }
9943
storage_get_next_record(uchar * buf)9944 int ha_mroonga::storage_get_next_record(uchar *buf)
9945 {
9946 MRN_DBUG_ENTER_METHOD();
9947 if (cursor_geo) {
9948 grn_posting *posting;
9949 posting = grn_geo_cursor_next(ctx, cursor_geo);
9950 if (posting) {
9951 record_id = posting->rid;
9952 } else {
9953 record_id = GRN_ID_NIL;
9954 }
9955 } else if (cursor) {
9956 record_id = grn_table_cursor_next(ctx, cursor);
9957 } else if (empty_value_records_cursor) {
9958 grn_id empty_value_record_id;
9959 empty_value_record_id =
9960 grn_table_cursor_next(ctx, empty_value_records_cursor);
9961 if (empty_value_record_id == GRN_ID_NIL) {
9962 record_id = GRN_ID_NIL;
9963 } else {
9964 grn_table_get_key(ctx, empty_value_records, empty_value_record_id,
9965 &record_id, sizeof(grn_id));
9966 }
9967 } else {
9968 record_id = GRN_ID_NIL;
9969 }
9970 if (ctx->rc) {
9971 int error = ER_ERROR_ON_READ;
9972 my_message(error, ctx->errbuf, MYF(0));
9973 DBUG_RETURN(error);
9974 }
9975 if (record_id == GRN_ID_NIL) {
9976 DBUG_PRINT("info", ("mroonga: storage_get_next_record: end-of-file"));
9977 table->status = STATUS_NOT_FOUND;
9978 DBUG_RETURN(HA_ERR_END_OF_FILE);
9979 }
9980 if (buf) {
9981 if (ignoring_no_key_columns)
9982 storage_store_fields_by_index(buf);
9983 else
9984 storage_store_fields(buf, record_id);
9985 if (cursor_geo && grn_source_column_geo) {
9986 int latitude, longitude;
9987 GRN_GEO_POINT_VALUE(&source_point, latitude, longitude);
9988 double latitude_in_degree = GRN_GEO_MSEC2DEGREE(latitude);
9989 double longitude_in_degree = GRN_GEO_MSEC2DEGREE(longitude);
9990 if (!((bottom_right_latitude_in_degree <= latitude_in_degree &&
9991 latitude_in_degree <= top_left_latitude_in_degree) &&
9992 (top_left_longitude_in_degree <= longitude_in_degree &&
9993 longitude_in_degree <= bottom_right_longitude_in_degree))) {
9994 DBUG_PRINT("info",
9995 ("mroonga: remove not contained geo point: "
9996 "<%g,%g>(<%d,%d>); key: <%g,%g>(<%d,%d>), <%g,%g>(<%d,%d>)",
9997 latitude_in_degree, longitude_in_degree,
9998 latitude, longitude,
9999 top_left_latitude_in_degree, top_left_longitude_in_degree,
10000 GRN_GEO_DEGREE2MSEC(top_left_latitude_in_degree),
10001 GRN_GEO_DEGREE2MSEC(top_left_longitude_in_degree),
10002 bottom_right_latitude_in_degree,
10003 bottom_right_longitude_in_degree,
10004 GRN_GEO_DEGREE2MSEC(bottom_right_latitude_in_degree),
10005 GRN_GEO_DEGREE2MSEC(bottom_right_longitude_in_degree)));
10006 int error = storage_get_next_record(buf);
10007 DBUG_RETURN(error);
10008 }
10009 }
10010 }
10011 table->status = 0;
10012 DBUG_RETURN(0);
10013 }
10014
geo_store_rectangle(const uchar * rectangle)10015 void ha_mroonga::geo_store_rectangle(const uchar *rectangle)
10016 {
10017 MRN_DBUG_ENTER_METHOD();
10018
10019 double locations[4];
10020 for (int i = 0; i < 4; i++) {
10021 uchar reversed_value[8];
10022 for (int j = 0; j < 8; j++) {
10023 reversed_value[j] = (rectangle + (8 * i))[7 - j];
10024 }
10025 mi_float8get(locations[i], reversed_value);
10026 }
10027 top_left_longitude_in_degree = locations[0];
10028 bottom_right_longitude_in_degree = locations[1];
10029 bottom_right_latitude_in_degree = locations[2];
10030 top_left_latitude_in_degree = locations[3];
10031 int top_left_latitude = GRN_GEO_DEGREE2MSEC(top_left_latitude_in_degree);
10032 int top_left_longitude = GRN_GEO_DEGREE2MSEC(top_left_longitude_in_degree);
10033 int bottom_right_latitude = GRN_GEO_DEGREE2MSEC(bottom_right_latitude_in_degree);
10034 int bottom_right_longitude = GRN_GEO_DEGREE2MSEC(bottom_right_longitude_in_degree);
10035 GRN_GEO_POINT_SET(ctx, &top_left_point,
10036 top_left_latitude, top_left_longitude);
10037 GRN_GEO_POINT_SET(ctx, &bottom_right_point,
10038 bottom_right_latitude, bottom_right_longitude);
10039
10040 DBUG_VOID_RETURN;
10041 }
10042
generic_geo_open_cursor(const uchar * key,enum ha_rkey_function find_flag)10043 int ha_mroonga::generic_geo_open_cursor(const uchar *key,
10044 enum ha_rkey_function find_flag)
10045 {
10046 MRN_DBUG_ENTER_METHOD();
10047 int error = 0;
10048 int flags = 0;
10049 if (find_flag & HA_READ_MBR_CONTAIN) {
10050 grn_obj *index = grn_index_columns[active_index];
10051 geo_store_rectangle(key);
10052 cursor_geo = grn_geo_cursor_open_in_rectangle(ctx,
10053 index,
10054 &top_left_point,
10055 &bottom_right_point,
10056 0, -1);
10057 if (cursor_geo) {
10058 if (grn_source_column_geo) {
10059 grn_obj_unlink(ctx, grn_source_column_geo);
10060 }
10061 grn_obj sources;
10062 GRN_OBJ_INIT(&sources, GRN_BULK, 0, GRN_ID_NIL);
10063 grn_obj_get_info(ctx, index, GRN_INFO_SOURCE, &sources);
10064 grn_source_column_geo = grn_ctx_at(ctx, GRN_RECORD_VALUE(&sources));
10065 grn_obj_unlink(ctx, &sources);
10066 }
10067 } else {
10068 push_warning_unsupported_spatial_index_search(find_flag);
10069 cursor = grn_table_cursor_open(ctx, grn_table, NULL, 0, NULL, 0,
10070 0, -1, flags);
10071 }
10072 if (ctx->rc) {
10073 error = ER_ERROR_ON_READ;
10074 my_message(error, ctx->errbuf, MYF(0));
10075 }
10076 DBUG_RETURN(error);
10077 }
10078
is_dry_write()10079 bool ha_mroonga::is_dry_write()
10080 {
10081 MRN_DBUG_ENTER_METHOD();
10082 bool dry_write_p = THDVAR(ha_thd(), dry_write);
10083 DBUG_RETURN(dry_write_p);
10084 }
10085
is_enable_optimization()10086 bool ha_mroonga::is_enable_optimization()
10087 {
10088 MRN_DBUG_ENTER_METHOD();
10089 bool enable_optimization_p = THDVAR(ha_thd(), enable_optimization);
10090 DBUG_RETURN(enable_optimization_p);
10091 }
10092
should_normalize(Field * field) const10093 bool ha_mroonga::should_normalize(Field *field) const
10094 {
10095 MRN_DBUG_ENTER_METHOD();
10096 mrn::FieldNormalizer field_normalizer(ctx, ha_thd(), field);
10097 bool need_normalize_p = field_normalizer.should_normalize();
10098 DBUG_RETURN(need_normalize_p);
10099 }
10100
check_count_skip(key_part_map target_key_part_map)10101 void ha_mroonga::check_count_skip(key_part_map target_key_part_map)
10102 {
10103 MRN_DBUG_ENTER_METHOD();
10104
10105 if (!is_enable_optimization()) {
10106 GRN_LOG(ctx, GRN_LOG_DEBUG,
10107 "[mroonga][count-skip][false] optimization is disabled");
10108 count_skip = false;
10109 DBUG_VOID_RETURN;
10110 }
10111
10112 if (thd_sql_command(ha_thd()) != SQLCOM_SELECT) {
10113 GRN_LOG(ctx, GRN_LOG_DEBUG,
10114 "[mroonga][count-skip][false] not SELECT");
10115 count_skip = false;
10116 DBUG_VOID_RETURN;
10117 }
10118
10119 if (share->wrapper_mode &&
10120 !(wrap_handler->ha_table_flags() & HA_NO_TRANSACTIONS)) {
10121 GRN_LOG(ctx, GRN_LOG_DEBUG,
10122 "[mroonga][count-skip][false] wrapped engine is transactional");
10123 count_skip = false;
10124 DBUG_VOID_RETURN;
10125 }
10126
10127 st_select_lex *select_lex = table->pos_in_table_list->select_lex;
10128 KEY *key_info = NULL;
10129 if (active_index != MAX_KEY) {
10130 key_info = &(table->key_info[active_index]);
10131 }
10132 mrn::CountSkipChecker checker(ctx,
10133 table,
10134 select_lex,
10135 key_info,
10136 target_key_part_map,
10137 !share->wrapper_mode);
10138 if (checker.check()) {
10139 count_skip = true;
10140 mrn_count_skip++;
10141 DBUG_VOID_RETURN;
10142 } else {
10143 count_skip = false;
10144 DBUG_VOID_RETURN;
10145 }
10146 }
10147
is_grn_zero_column_value(grn_obj * column,grn_obj * value)10148 bool ha_mroonga::is_grn_zero_column_value(grn_obj *column, grn_obj *value)
10149 {
10150 MRN_DBUG_ENTER_METHOD();
10151
10152 if (column->header.type != GRN_COLUMN_FIX_SIZE) {
10153 DBUG_RETURN(false);
10154 }
10155
10156 char *bytes = GRN_BULK_HEAD(value);
10157 unsigned int size = GRN_BULK_VSIZE(value);
10158 for (unsigned int i = 0; i < size; ++i) {
10159 if (bytes[i] != '\0') {
10160 DBUG_RETURN(false);
10161 }
10162 }
10163
10164 DBUG_RETURN(true);
10165 }
10166
is_primary_key_field(Field * field) const10167 bool ha_mroonga::is_primary_key_field(Field *field) const
10168 {
10169 MRN_DBUG_ENTER_METHOD();
10170
10171 if (table->s->primary_key == MAX_INDEXES) {
10172 DBUG_RETURN(false);
10173 }
10174
10175 KEY *key_info = &(table->s->key_info[table->s->primary_key]);
10176 if (KEY_N_KEY_PARTS(key_info) != 1) {
10177 DBUG_RETURN(false);
10178 }
10179
10180 if (strcmp(field->field_name.str,
10181 key_info->key_part[0].field->field_name.str) == 0) {
10182 DBUG_RETURN(true);
10183 } else {
10184 DBUG_RETURN(false);
10185 }
10186 }
10187
check_fast_order_limit(grn_table_sort_key ** sort_keys,int * n_sort_keys,longlong * limit)10188 void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys,
10189 int *n_sort_keys,
10190 longlong *limit)
10191 {
10192 MRN_DBUG_ENTER_METHOD();
10193
10194 if (!is_enable_optimization()) {
10195 DBUG_PRINT("info", ("mroonga: fast order limit: optimization is disabled"));
10196 fast_order_limit = false;
10197 DBUG_VOID_RETURN;
10198 }
10199
10200 TABLE_LIST *table_list = table->pos_in_table_list;
10201 st_select_lex *select_lex = table_list->select_lex;
10202 SELECT_LEX_UNIT *unit = MRN_TABLE_LIST_GET_DERIVED(table_list);
10203 st_select_lex *first_select_lex;
10204 if (unit)
10205 {
10206 first_select_lex = unit->first_select();
10207 } else {
10208 first_select_lex = select_lex;
10209 }
10210 DBUG_PRINT("info",
10211 ("mroonga: first_select_lex->options=%llu",
10212 first_select_lex ? MRN_SELECT_LEX_GET_ACTIVE_OPTIONS(first_select_lex) : 0));
10213
10214 if (
10215 thd_sql_command(ha_thd()) == SQLCOM_SELECT &&
10216 !select_lex->with_sum_func &&
10217 !select_lex->group_list.elements &&
10218 !MRN_SELECT_LEX_GET_HAVING_COND(select_lex) &&
10219 select_lex->table_list.elements == 1 &&
10220 select_lex->order_list.elements &&
10221 select_lex->explicit_limit &&
10222 select_lex->select_limit &&
10223 select_lex->select_limit->val_int() > 0
10224 ) {
10225 if (select_lex->offset_limit) {
10226 *limit = select_lex->offset_limit->val_int();
10227 } else {
10228 *limit = 0;
10229 }
10230 *limit += select_lex->select_limit->val_int();
10231 if (*limit > (longlong)INT_MAX) {
10232 DBUG_PRINT("info",
10233 ("mroonga: fast_order_limit = false: "
10234 "too long limit: %lld <= %d is required",
10235 *limit, INT_MAX));
10236 fast_order_limit = false;
10237 DBUG_VOID_RETURN;
10238 }
10239 if (first_select_lex &&
10240 (MRN_SELECT_LEX_GET_ACTIVE_OPTIONS(first_select_lex) & OPTION_FOUND_ROWS)) {
10241 DBUG_PRINT("info",
10242 ("mroonga: fast_order_limit = false: "
10243 "SQL_CALC_FOUND_ROWS is specified"));
10244 fast_order_limit = false;
10245 DBUG_VOID_RETURN;
10246 }
10247 bool is_storage_mode = !(share->wrapper_mode);
10248 Item *where = MRN_SELECT_LEX_GET_WHERE_COND(select_lex);
10249 const Item_func *match_against = NULL;
10250 if (where) {
10251 mrn::ConditionConverter converter(ctx, grn_table, is_storage_mode);
10252 if (!converter.is_convertable(where)) {
10253 DBUG_PRINT("info",
10254 ("mroonga: fast_order_limit = false: "
10255 "not Groonga layer condition search"));
10256 fast_order_limit = false;
10257 DBUG_VOID_RETURN;
10258 }
10259 unsigned int n_match_againsts = converter.count_match_against(where);
10260 if (n_match_againsts == 0) {
10261 DBUG_PRINT("info",
10262 ("mroonga: fast_order_limit = false: "
10263 "Groonga layer condition but not fulltext search"));
10264 fast_order_limit = false;
10265 DBUG_VOID_RETURN;
10266 }
10267 if (n_match_againsts > 1) {
10268 DBUG_PRINT("info",
10269 ("mroonga: fast_order_limit = false: "
10270 "MATCH AGAINST must be only one"));
10271 fast_order_limit = false;
10272 DBUG_VOID_RETURN;
10273 }
10274 }
10275 int n_max_sort_keys = select_lex->order_list.elements;
10276 *n_sort_keys = 0;
10277 size_t sort_keys_size = sizeof(grn_table_sort_key) * n_max_sort_keys;
10278 *sort_keys = (grn_table_sort_key *)mrn_my_malloc(sort_keys_size,
10279 MYF(MY_WME));
10280 memset(*sort_keys, 0, sort_keys_size);
10281 ORDER *order;
10282 int i;
10283 mrn_change_encoding(ctx, system_charset_info);
10284 for (order = (ORDER *) select_lex->order_list.first, i = 0;
10285 order;
10286 order = order->next, i++) {
10287 Item *item = *order->item;
10288 if (item->type() == Item::FIELD_ITEM)
10289 {
10290 Field *field = static_cast<Item_field *>(item)->field;
10291 mrn::ColumnName column_name(field->field_name);
10292
10293 if (should_normalize(field))
10294 {
10295 DBUG_PRINT("info", ("mroonga: fast_order_limit = false: "
10296 "sort by collated value isn't supported yet."));
10297 fast_order_limit = false;
10298 my_free(*sort_keys);
10299 *sort_keys = NULL;
10300 *n_sort_keys = 0;
10301 DBUG_VOID_RETURN;
10302 }
10303
10304 if (is_storage_mode) {
10305 (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys,
10306 column_name.c_str(),
10307 column_name.length());
10308 } else {
10309 if (is_primary_key_field(field)) {
10310 (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys,
10311 MRN_COLUMN_NAME_KEY,
10312 strlen(MRN_COLUMN_NAME_KEY));
10313 } else {
10314 DBUG_PRINT("info", ("mroonga: fast_order_limit = false: "
10315 "sort by not primary key value "
10316 "isn't supported in wrapper mode."));
10317 fast_order_limit = false;
10318 my_free(*sort_keys);
10319 *sort_keys = NULL;
10320 *n_sort_keys = 0;
10321 DBUG_VOID_RETURN;
10322 }
10323 }
10324 } else if (!match_against || match_against->eq(item, true)) {
10325 (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys,
10326 MRN_COLUMN_NAME_SCORE,
10327 strlen(MRN_COLUMN_NAME_SCORE));
10328 } else {
10329 DBUG_PRINT("info", ("mroonga: fast_order_limit = false: "
10330 "sort by computed value isn't supported."));
10331 fast_order_limit = false;
10332 my_free(*sort_keys);
10333 *sort_keys = NULL;
10334 *n_sort_keys = 0;
10335 DBUG_VOID_RETURN;
10336 }
10337 (*sort_keys)[i].offset = 0;
10338 if (MRN_ORDER_IS_ASC(order))
10339 {
10340 (*sort_keys)[i].flags = GRN_TABLE_SORT_ASC;
10341 } else {
10342 (*sort_keys)[i].flags = GRN_TABLE_SORT_DESC;
10343 }
10344 (*n_sort_keys)++;
10345 }
10346 DBUG_PRINT("info", ("mroonga: fast_order_limit = true"));
10347 fast_order_limit = true;
10348 mrn_fast_order_limit++;
10349 DBUG_VOID_RETURN;
10350 }
10351 DBUG_PRINT("info", ("mroonga: fast_order_limit = false"));
10352 fast_order_limit = false;
10353 DBUG_VOID_RETURN;
10354 }
10355
generic_store_bulk_fixed_size_string(Field * field,grn_obj * buf)10356 int ha_mroonga::generic_store_bulk_fixed_size_string(Field *field, grn_obj *buf)
10357 {
10358 MRN_DBUG_ENTER_METHOD();
10359 int error = 0;
10360 grn_obj_reinit(ctx, buf, GRN_DB_SHORT_TEXT, 0);
10361 GRN_TEXT_SET(ctx, buf, field->ptr, field->field_length);
10362 DBUG_RETURN(error);
10363 }
10364
generic_store_bulk_variable_size_string(Field * field,grn_obj * buf)10365 int ha_mroonga::generic_store_bulk_variable_size_string(Field *field,
10366 grn_obj *buf)
10367 {
10368 MRN_DBUG_ENTER_METHOD();
10369 int error = 0;
10370 String value;
10371 field->val_str(NULL, &value);
10372 grn_obj_reinit(ctx, buf, GRN_DB_SHORT_TEXT, 0);
10373 DBUG_PRINT("info", ("mroonga: length=%" MRN_FORMAT_STRING_LENGTH,
10374 value.length()));
10375 DBUG_PRINT("info", ("mroonga: value=%s", value.c_ptr_safe()));
10376 GRN_TEXT_SET(ctx, buf, value.ptr(), value.length());
10377 DBUG_RETURN(error);
10378 }
10379
generic_store_bulk_integer(Field * field,grn_obj * buf)10380 int ha_mroonga::generic_store_bulk_integer(Field *field, grn_obj *buf)
10381 {
10382 MRN_DBUG_ENTER_METHOD();
10383 int error = 0;
10384 long long value = field->val_int();
10385 DBUG_PRINT("info", ("mroonga: value=%lld", value));
10386 uint32 size = field->pack_length();
10387 DBUG_PRINT("info", ("mroonga: size=%u", size));
10388 Field_num *field_num = static_cast<Field_num *>(field);
10389 bool is_unsigned = field_num->unsigned_flag;
10390 DBUG_PRINT("info", ("mroonga: is_unsigned=%s", is_unsigned ? "true" : "false"));
10391 switch (size) {
10392 case 1:
10393 if (is_unsigned) {
10394 grn_obj_reinit(ctx, buf, GRN_DB_UINT8, 0);
10395 GRN_UINT8_SET(ctx, buf, value);
10396 } else {
10397 grn_obj_reinit(ctx, buf, GRN_DB_INT8, 0);
10398 GRN_INT8_SET(ctx, buf, value);
10399 }
10400 break;
10401 case 2:
10402 if (is_unsigned) {
10403 grn_obj_reinit(ctx, buf, GRN_DB_UINT16, 0);
10404 GRN_UINT16_SET(ctx, buf, value);
10405 } else {
10406 grn_obj_reinit(ctx, buf, GRN_DB_INT16, 0);
10407 GRN_INT16_SET(ctx, buf, value);
10408 }
10409 break;
10410 case 3:
10411 case 4:
10412 if (is_unsigned) {
10413 grn_obj_reinit(ctx, buf, GRN_DB_UINT32, 0);
10414 GRN_UINT32_SET(ctx, buf, value);
10415 } else {
10416 grn_obj_reinit(ctx, buf, GRN_DB_INT32, 0);
10417 GRN_INT32_SET(ctx, buf, value);
10418 }
10419 break;
10420 case 8:
10421 if (is_unsigned) {
10422 grn_obj_reinit(ctx, buf, GRN_DB_UINT64, 0);
10423 GRN_UINT64_SET(ctx, buf, value);
10424 } else {
10425 grn_obj_reinit(ctx, buf, GRN_DB_INT64, 0);
10426 GRN_INT64_SET(ctx, buf, value);
10427 }
10428 break;
10429 default:
10430 // Why!?
10431 error = HA_ERR_UNSUPPORTED;
10432 char error_message[MRN_MESSAGE_BUFFER_SIZE];
10433 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
10434 "unknown integer value size: <%u>: "
10435 "available sizes: [1, 2, 3, 4, 8]",
10436 size);
10437 push_warning(ha_thd(), MRN_SEVERITY_WARNING,
10438 error, error_message);
10439 break;
10440 }
10441 DBUG_RETURN(error);
10442 }
10443
generic_store_bulk_unsigned_integer(Field * field,grn_obj * buf)10444 int ha_mroonga::generic_store_bulk_unsigned_integer(Field *field, grn_obj *buf)
10445 {
10446 MRN_DBUG_ENTER_METHOD();
10447 int error = 0;
10448 long long signed_value = field->val_int();
10449 unsigned long long unsigned_value = *((unsigned long long *)(&signed_value));
10450 uint32 size = field->pack_length();
10451 switch (size) {
10452 case 1:
10453 grn_obj_reinit(ctx, buf, GRN_DB_UINT8, 0);
10454 GRN_UINT8_SET(ctx, buf, unsigned_value);
10455 break;
10456 case 2:
10457 grn_obj_reinit(ctx, buf, GRN_DB_UINT16, 0);
10458 GRN_UINT16_SET(ctx, buf, unsigned_value);
10459 break;
10460 case 3:
10461 case 4:
10462 grn_obj_reinit(ctx, buf, GRN_DB_UINT32, 0);
10463 GRN_UINT32_SET(ctx, buf, unsigned_value);
10464 break;
10465 case 8:
10466 grn_obj_reinit(ctx, buf, GRN_DB_UINT64, 0);
10467 GRN_UINT64_SET(ctx, buf, unsigned_value);
10468 break;
10469 default:
10470 // Why!?
10471 error = HA_ERR_UNSUPPORTED;
10472 char error_message[MRN_MESSAGE_BUFFER_SIZE];
10473 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
10474 "unknown unsigned integer value size: <%u>: "
10475 "available sizes: [1, 2, 3, 4, 8]",
10476 size);
10477 push_warning(ha_thd(), MRN_SEVERITY_WARNING,
10478 error, error_message);
10479 break;
10480 }
10481 DBUG_RETURN(error);
10482 }
10483
generic_store_bulk_float(Field * field,grn_obj * buf)10484 int ha_mroonga::generic_store_bulk_float(Field *field, grn_obj *buf)
10485 {
10486 MRN_DBUG_ENTER_METHOD();
10487 int error = 0;
10488 double value = field->val_real();
10489 uint32 size = field->pack_length();
10490 switch (size) {
10491 case 4:
10492 case 8:
10493 grn_obj_reinit(ctx, buf, GRN_DB_FLOAT, 0);
10494 GRN_FLOAT_SET(ctx, buf, value);
10495 break;
10496 default:
10497 // Why!?
10498 error = HA_ERR_UNSUPPORTED;
10499 char error_message[MRN_MESSAGE_BUFFER_SIZE];
10500 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
10501 "unknown float value size: <%u>: "
10502 "available sizes: [4, 8]",
10503 size);
10504 push_warning(ha_thd(), MRN_SEVERITY_WARNING,
10505 error, error_message);
10506 break;
10507 }
10508 DBUG_RETURN(error);
10509 }
10510
get_grn_time_from_timestamp_field(Field_timestamp * field)10511 long long int ha_mroonga::get_grn_time_from_timestamp_field(Field_timestamp *field)
10512 {
10513 MRN_DBUG_ENTER_METHOD();
10514 long long int grn_time = 0;
10515 #ifdef MRN_TIMESTAMP_USE_TIMEVAL
10516 int warnings = 0;
10517 struct timeval time_value;
10518 if (field->get_timestamp(&time_value, &warnings)) {
10519 // XXX: Should we report warnings or MySQL does?
10520 } else {
10521 DBUG_PRINT("info", ("mroonga: timeval tv_sec=%ld", time_value.tv_sec));
10522 grn_time = GRN_TIME_PACK(time_value.tv_sec, time_value.tv_usec);
10523 }
10524 #elif defined(MRN_TIMESTAMP_USE_MY_TIME_T)
10525 unsigned long int micro_seconds;
10526 my_time_t seconds = field->get_timestamp(µ_seconds);
10527 DBUG_PRINT("info", ("mroonga: my_time_t seconds=%ld", seconds));
10528 grn_time = GRN_TIME_PACK(seconds, micro_seconds);
10529 #else
10530 my_bool is_null_value;
10531 long seconds = field->get_timestamp(&is_null_value);
10532 DBUG_PRINT("info", ("mroonga: long seconds=%ld", seconds));
10533 grn_time = GRN_TIME_PACK(seconds, 0);
10534 #endif
10535 DBUG_RETURN(grn_time);
10536 }
10537
generic_store_bulk_timestamp(Field * field,grn_obj * buf)10538 int ha_mroonga::generic_store_bulk_timestamp(Field *field, grn_obj *buf)
10539 {
10540 MRN_DBUG_ENTER_METHOD();
10541 int error = 0;
10542 Field_timestamp *timestamp_field = (Field_timestamp *)field;
10543 long long int time = get_grn_time_from_timestamp_field(timestamp_field);
10544 grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0);
10545 GRN_TIME_SET(ctx, buf, time);
10546 DBUG_RETURN(error);
10547 }
10548
generic_store_bulk_date(Field * field,grn_obj * buf)10549 int ha_mroonga::generic_store_bulk_date(Field *field, grn_obj *buf)
10550 {
10551 MRN_DBUG_ENTER_METHOD();
10552 int error = 0;
10553 bool truncated = false;
10554 long long int date_value = field->val_int();
10555 struct tm date;
10556 memset(&date, 0, sizeof(struct tm));
10557 date.tm_year = date_value / 10000 % 10000 - mrn::TimeConverter::TM_YEAR_BASE;
10558 date.tm_mon = date_value / 100 % 100 - 1;
10559 date.tm_mday = date_value % 100;
10560 int usec = 0;
10561 mrn::TimeConverter time_converter;
10562 long long int time = time_converter.tm_to_grn_time(&date, usec, &truncated);
10563 if (truncated) {
10564 field->set_warning(MRN_SEVERITY_WARNING,
10565 WARN_DATA_TRUNCATED, 1);
10566 }
10567 grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0);
10568 GRN_TIME_SET(ctx, buf, time);
10569 DBUG_RETURN(error);
10570 }
10571
generic_store_bulk_time(Field * field,grn_obj * buf)10572 int ha_mroonga::generic_store_bulk_time(Field *field, grn_obj *buf)
10573 {
10574 MRN_DBUG_ENTER_METHOD();
10575 int error = 0;
10576 bool truncated = false;
10577 Field_time *time_field = (Field_time *)field;
10578 MYSQL_TIME mysql_time;
10579 time_field->get_time(&mysql_time);
10580 mrn::TimeConverter time_converter;
10581 long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
10582 &truncated);
10583 if (truncated) {
10584 field->set_warning(MRN_SEVERITY_WARNING,
10585 WARN_DATA_TRUNCATED, 1);
10586 }
10587 grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0);
10588 GRN_TIME_SET(ctx, buf, time);
10589 DBUG_RETURN(error);
10590 }
10591
generic_store_bulk_datetime(Field * field,grn_obj * buf)10592 int ha_mroonga::generic_store_bulk_datetime(Field *field, grn_obj *buf)
10593 {
10594 MRN_DBUG_ENTER_METHOD();
10595 int error = 0;
10596 bool truncated = false;
10597 Field_datetime *datetime_field = (Field_datetime *)field;
10598 MYSQL_TIME mysql_time;
10599 datetime_field->get_time(&mysql_time);
10600 mrn::TimeConverter time_converter;
10601 long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
10602 &truncated);
10603 if (truncated) {
10604 if (MRN_ABORT_ON_WARNING(ha_thd())) {
10605 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
10606 }
10607 field->set_warning(MRN_SEVERITY_WARNING,
10608 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
10609 1);
10610 }
10611 grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0);
10612 GRN_TIME_SET(ctx, buf, time);
10613 DBUG_RETURN(error);
10614 }
10615
generic_store_bulk_year(Field * field,grn_obj * buf)10616 int ha_mroonga::generic_store_bulk_year(Field *field, grn_obj *buf)
10617 {
10618 MRN_DBUG_ENTER_METHOD();
10619 int error = 0;
10620 bool truncated = false;
10621
10622 int year;
10623 if (field->field_length == 2) {
10624 year = static_cast<int>(field->val_int() + 2000);
10625 } else {
10626 year = static_cast<int>(field->val_int());
10627 }
10628
10629 DBUG_PRINT("info", ("mroonga: year=%d", year));
10630 struct tm date;
10631 memset(&date, 0, sizeof(struct tm));
10632 date.tm_year = year - mrn::TimeConverter::TM_YEAR_BASE;
10633 date.tm_mon = 0;
10634 date.tm_mday = 1;
10635
10636 int usec = 0;
10637 mrn::TimeConverter time_converter;
10638 long long int time = time_converter.tm_to_grn_time(&date, usec, &truncated);
10639 if (truncated) {
10640 if (MRN_ABORT_ON_WARNING(ha_thd())) {
10641 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
10642 }
10643 field->set_warning(MRN_SEVERITY_WARNING,
10644 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
10645 1);
10646 }
10647 grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0);
10648 GRN_TIME_SET(ctx, buf, time);
10649 DBUG_RETURN(error);
10650 }
10651
10652 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2
generic_store_bulk_datetime2(Field * field,grn_obj * buf)10653 int ha_mroonga::generic_store_bulk_datetime2(Field *field, grn_obj *buf)
10654 {
10655 MRN_DBUG_ENTER_METHOD();
10656 int error = 0;
10657 bool truncated = false;
10658 Field_datetimef *datetimef_field = (Field_datetimef *)field;
10659 MYSQL_TIME mysql_time;
10660 datetimef_field->get_time(&mysql_time);
10661 mrn::TimeConverter time_converter;
10662 long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
10663 &truncated);
10664 if (truncated) {
10665 if (MRN_ABORT_ON_WARNING(ha_thd())) {
10666 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
10667 }
10668 field->set_warning(MRN_SEVERITY_WARNING,
10669 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
10670 1);
10671 }
10672 grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0);
10673 GRN_TIME_SET(ctx, buf, time);
10674 DBUG_RETURN(error);
10675 }
10676 #endif
10677
10678 #ifdef MRN_HAVE_MYSQL_TYPE_TIME2
generic_store_bulk_time2(Field * field,grn_obj * buf)10679 int ha_mroonga::generic_store_bulk_time2(Field *field, grn_obj *buf)
10680 {
10681 MRN_DBUG_ENTER_METHOD();
10682 int error = 0;
10683 bool truncated = false;
10684 MYSQL_TIME mysql_time;
10685 field->get_time(&mysql_time);
10686 mrn::TimeConverter time_converter;
10687 long long int time = time_converter.mysql_time_to_grn_time(&mysql_time,
10688 &truncated);
10689 if (truncated) {
10690 if (MRN_ABORT_ON_WARNING(ha_thd())) {
10691 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
10692 }
10693 field->set_warning(MRN_SEVERITY_WARNING,
10694 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
10695 1);
10696 }
10697 grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0);
10698 GRN_TIME_SET(ctx, buf, time);
10699 DBUG_RETURN(error);
10700 }
10701 #endif
10702
generic_store_bulk_new_date(Field * field,grn_obj * buf)10703 int ha_mroonga::generic_store_bulk_new_date(Field *field, grn_obj *buf)
10704 {
10705 MRN_DBUG_ENTER_METHOD();
10706 int error = 0;
10707 bool truncated = false;
10708 Field_newdate *newdate_field = (Field_newdate *)field;
10709 MYSQL_TIME mysql_date;
10710 newdate_field->get_time(&mysql_date);
10711 mrn::TimeConverter time_converter;
10712 long long int time = time_converter.mysql_time_to_grn_time(&mysql_date,
10713 &truncated);
10714 if (truncated) {
10715 if (MRN_ABORT_ON_WARNING(ha_thd())) {
10716 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
10717 }
10718 field->set_warning(MRN_SEVERITY_WARNING,
10719 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
10720 1);
10721 }
10722 grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0);
10723 GRN_TIME_SET(ctx, buf, time);
10724 DBUG_RETURN(error);
10725 }
10726
generic_store_bulk_new_decimal(Field * field,grn_obj * buf)10727 int ha_mroonga::generic_store_bulk_new_decimal(Field *field, grn_obj *buf)
10728 {
10729 MRN_DBUG_ENTER_METHOD();
10730 int error = 0;
10731 String value;
10732 Field_new_decimal *new_decimal_field = (Field_new_decimal *)field;
10733 new_decimal_field->val_str(&value, NULL);
10734 grn_obj_reinit(ctx, buf, GRN_DB_SHORT_TEXT, 0);
10735 GRN_TEXT_SET(ctx, buf, value.ptr(), value.length());
10736 DBUG_RETURN(error);
10737 }
10738
generic_store_bulk_blob(Field * field,grn_obj * buf)10739 int ha_mroonga::generic_store_bulk_blob(Field *field, grn_obj *buf)
10740 {
10741 MRN_DBUG_ENTER_METHOD();
10742 int error = 0;
10743 String buffer;
10744 Field_blob *blob = (Field_blob *)field;
10745 String *value = blob->val_str(0, &buffer);
10746 grn_obj_reinit(ctx, buf, GRN_DB_TEXT, 0);
10747 GRN_TEXT_SET(ctx, buf, value->ptr(), value->length());
10748 DBUG_RETURN(error);
10749 }
10750
generic_store_bulk_geometry(Field * field,grn_obj * buf)10751 int ha_mroonga::generic_store_bulk_geometry(Field *field, grn_obj *buf)
10752 {
10753 MRN_DBUG_ENTER_METHOD();
10754 int error = 0;
10755 #ifdef MRN_HAVE_SPATIAL
10756 String buffer;
10757 Field_geom *geometry = (Field_geom *)field;
10758 String *value = geometry->val_str(0, &buffer);
10759 const char *wkb = value->ptr();
10760 int len = value->length();
10761 error = mrn_set_geometry(ctx, buf, wkb, len);
10762 #endif
10763 DBUG_RETURN(error);
10764 }
10765
10766 #ifdef MRN_HAVE_MYSQL_TYPE_JSON
generic_store_bulk_json(Field * field,grn_obj * buf)10767 int ha_mroonga::generic_store_bulk_json(Field *field, grn_obj *buf)
10768 {
10769 MRN_DBUG_ENTER_METHOD();
10770 int error = 0;
10771 String buffer;
10772 Field_json *json = static_cast<Field_json *>(field);
10773 String *value = json->val_str(&buffer, NULL);
10774 grn_obj_reinit(ctx, buf, GRN_DB_TEXT, 0);
10775 GRN_TEXT_SET(ctx, buf, value->ptr(), value->length());
10776 DBUG_RETURN(error);
10777 }
10778 #endif
10779
generic_store_bulk(Field * field,grn_obj * buf)10780 int ha_mroonga::generic_store_bulk(Field *field, grn_obj *buf)
10781 {
10782 MRN_DBUG_ENTER_METHOD();
10783 int error;
10784 error = mrn_change_encoding(ctx, field->charset());
10785 if (error)
10786 return error;
10787 switch (field->real_type()) {
10788 case MYSQL_TYPE_DECIMAL:
10789 error = generic_store_bulk_variable_size_string(field, buf);
10790 break;
10791 case MYSQL_TYPE_TINY:
10792 case MYSQL_TYPE_SHORT:
10793 case MYSQL_TYPE_LONG:
10794 error = generic_store_bulk_integer(field, buf);
10795 break;
10796 case MYSQL_TYPE_FLOAT:
10797 case MYSQL_TYPE_DOUBLE:
10798 error = generic_store_bulk_float(field, buf);
10799 break;
10800 case MYSQL_TYPE_NULL:
10801 error = generic_store_bulk_unsigned_integer(field, buf);
10802 break;
10803 case MYSQL_TYPE_TIMESTAMP:
10804 error = generic_store_bulk_timestamp(field, buf);
10805 break;
10806 case MYSQL_TYPE_LONGLONG:
10807 case MYSQL_TYPE_INT24:
10808 error = generic_store_bulk_integer(field, buf);
10809 break;
10810 case MYSQL_TYPE_DATE:
10811 error = generic_store_bulk_date(field, buf);
10812 break;
10813 case MYSQL_TYPE_TIME:
10814 error = generic_store_bulk_time(field, buf);
10815 break;
10816 case MYSQL_TYPE_DATETIME:
10817 error = generic_store_bulk_datetime(field, buf);
10818 break;
10819 case MYSQL_TYPE_YEAR:
10820 error = generic_store_bulk_year(field, buf);
10821 break;
10822 case MYSQL_TYPE_NEWDATE:
10823 error = generic_store_bulk_new_date(field, buf);
10824 break;
10825 case MYSQL_TYPE_VARCHAR:
10826 error = generic_store_bulk_variable_size_string(field, buf);
10827 break;
10828 case MYSQL_TYPE_BIT:
10829 error = generic_store_bulk_unsigned_integer(field, buf);
10830 break;
10831 #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2
10832 case MYSQL_TYPE_TIMESTAMP2:
10833 error = generic_store_bulk_timestamp(field, buf);
10834 break;
10835 #endif
10836 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2
10837 case MYSQL_TYPE_DATETIME2:
10838 error = generic_store_bulk_datetime2(field, buf);
10839 break;
10840 #endif
10841 #ifdef MRN_HAVE_MYSQL_TYPE_TIME2
10842 case MYSQL_TYPE_TIME2:
10843 error = generic_store_bulk_time2(field, buf);
10844 break;
10845 #endif
10846 case MYSQL_TYPE_NEWDECIMAL:
10847 error = generic_store_bulk_new_decimal(field, buf);
10848 break;
10849 case MYSQL_TYPE_ENUM:
10850 error = generic_store_bulk_unsigned_integer(field, buf);
10851 break;
10852 case MYSQL_TYPE_SET:
10853 error = generic_store_bulk_unsigned_integer(field, buf);
10854 break;
10855 case MYSQL_TYPE_TINY_BLOB:
10856 case MYSQL_TYPE_MEDIUM_BLOB:
10857 case MYSQL_TYPE_LONG_BLOB:
10858 case MYSQL_TYPE_BLOB:
10859 error = generic_store_bulk_blob(field, buf);
10860 break;
10861 case MYSQL_TYPE_VAR_STRING:
10862 error = generic_store_bulk_variable_size_string(field, buf);
10863 break;
10864 case MYSQL_TYPE_STRING:
10865 error = generic_store_bulk_fixed_size_string(field, buf);
10866 break;
10867 case MYSQL_TYPE_GEOMETRY:
10868 error = generic_store_bulk_geometry(field, buf);
10869 break;
10870 #ifdef MRN_HAVE_MYSQL_TYPE_JSON
10871 case MYSQL_TYPE_JSON:
10872 error = generic_store_bulk_json(field, buf);
10873 break;
10874 #endif
10875 default:
10876 error = HA_ERR_UNSUPPORTED;
10877 break;
10878 }
10879 DBUG_RETURN(error);
10880 }
10881
storage_store_field_string(Field * field,const char * value,uint value_length)10882 void ha_mroonga::storage_store_field_string(Field *field,
10883 const char *value,
10884 uint value_length)
10885 {
10886 MRN_DBUG_ENTER_METHOD();
10887 field->store(value, value_length, field->charset());
10888 DBUG_VOID_RETURN;
10889 }
10890
storage_store_field_integer(Field * field,const char * value,uint value_length)10891 void ha_mroonga::storage_store_field_integer(Field *field,
10892 const char *value,
10893 uint value_length)
10894 {
10895 MRN_DBUG_ENTER_METHOD();
10896 Field_num *field_num = static_cast<Field_num *>(field);
10897 bool is_unsigned = field_num->unsigned_flag;
10898 switch (value_length) {
10899 case 1:
10900 {
10901 if (is_unsigned) {
10902 unsigned char field_value;
10903 field_value = *((unsigned char *)value);
10904 field->store(field_value, is_unsigned);
10905 } else {
10906 signed char field_value;
10907 field_value = *((signed char *)value);
10908 field->store(field_value, is_unsigned);
10909 }
10910 break;
10911 }
10912 case 2:
10913 {
10914 if (is_unsigned) {
10915 unsigned short field_value;
10916 field_value = *((unsigned short *)value);
10917 field->store(field_value, is_unsigned);
10918 } else {
10919 short field_value;
10920 field_value = *((short *)value);
10921 field->store(field_value, is_unsigned);
10922 }
10923 break;
10924 }
10925 case 4:
10926 {
10927 if (is_unsigned) {
10928 unsigned int field_value;
10929 field_value = *((unsigned int *)value);
10930 field->store(field_value, is_unsigned);
10931 } else {
10932 int field_value;
10933 field_value = *((int *)value);
10934 field->store(field_value, is_unsigned);
10935 }
10936 break;
10937 }
10938 case 8:
10939 {
10940 if (is_unsigned) {
10941 unsigned long long int field_value;
10942 field_value = *((unsigned long long int *)value);
10943 DBUG_PRINT("info", ("mroonga: field_value=%llu", field_value));
10944 field->store(field_value, is_unsigned);
10945 } else {
10946 long long int field_value;
10947 field_value = *((long long int *)value);
10948 field->store(field_value, is_unsigned);
10949 }
10950 break;
10951 }
10952 default:
10953 {
10954 // Why!?
10955 char error_message[MRN_MESSAGE_BUFFER_SIZE];
10956 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
10957 "unknown integer value size: <%d>: "
10958 "available sizes: [1, 2, 4, 8]",
10959 value_length);
10960 push_warning(ha_thd(), MRN_SEVERITY_WARNING,
10961 HA_ERR_UNSUPPORTED, error_message);
10962 storage_store_field_string(field, value, value_length);
10963 break;
10964 }
10965 }
10966 DBUG_VOID_RETURN;
10967 }
10968
storage_store_field_unsigned_integer(Field * field,const char * value,uint value_length)10969 void ha_mroonga::storage_store_field_unsigned_integer(Field *field,
10970 const char *value,
10971 uint value_length)
10972 {
10973 MRN_DBUG_ENTER_METHOD();
10974 switch (value_length) {
10975 case 1:
10976 {
10977 unsigned char field_value;
10978 field_value = *((unsigned char *)value);
10979 field->store(field_value, true);
10980 break;
10981 }
10982 case 2:
10983 {
10984 unsigned short field_value;
10985 field_value = *((unsigned short *)value);
10986 field->store(field_value, true);
10987 break;
10988 }
10989 case 4:
10990 {
10991 unsigned int field_value;
10992 field_value = *((unsigned int *)value);
10993 field->store(field_value, true);
10994 break;
10995 }
10996 case 8:
10997 {
10998 unsigned long long int field_value;
10999 field_value = *((unsigned long long int *)value);
11000 DBUG_PRINT("info", ("mroonga: field_value=%llu", field_value));
11001 field->store(field_value, true);
11002 break;
11003 }
11004 default:
11005 {
11006 // Why!?
11007 char error_message[MRN_MESSAGE_BUFFER_SIZE];
11008 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
11009 "unknown integer value size: <%d>: "
11010 "available sizes: [1, 2, 4, 8]",
11011 value_length);
11012 push_warning(ha_thd(), MRN_SEVERITY_WARNING,
11013 HA_ERR_UNSUPPORTED, error_message);
11014 storage_store_field_string(field, value, value_length);
11015 break;
11016 }
11017 }
11018 DBUG_VOID_RETURN;
11019 }
11020
storage_store_field_float(Field * field,const char * value,uint value_length)11021 void ha_mroonga::storage_store_field_float(Field *field,
11022 const char *value,
11023 uint value_length)
11024 {
11025 MRN_DBUG_ENTER_METHOD();
11026 double field_value;
11027 field_value = *((double *)value);
11028 field->store(field_value);
11029 DBUG_VOID_RETURN;
11030 }
11031
storage_store_field_timestamp(Field * field,const char * value,uint value_length)11032 void ha_mroonga::storage_store_field_timestamp(Field *field,
11033 const char *value,
11034 uint value_length)
11035 {
11036 MRN_DBUG_ENTER_METHOD();
11037 long long int time = *((long long int *)value);
11038 Field_timestamp *timestamp_field = (Field_timestamp *)field;
11039 #ifdef MRN_TIMESTAMP_USE_TIMEVAL
11040 struct timeval time_value;
11041 GRN_TIME_UNPACK(time, time_value.tv_sec, time_value.tv_usec);
11042 timestamp_field->store_timestamp(&time_value);
11043 #elif defined(MRN_TIMESTAMP_USE_MY_TIME_T)
11044 long long int sec, usec;
11045 GRN_TIME_UNPACK(time, sec, usec);
11046 timestamp_field->store_TIME(static_cast<int32>(sec),
11047 static_cast<int32>(usec));
11048 #else
11049 int32 sec, usec __attribute__((unused));
11050 GRN_TIME_UNPACK(time, sec, usec);
11051 timestamp_field->store_timestamp(sec);
11052 #endif
11053 DBUG_VOID_RETURN;
11054 }
11055
storage_store_field_date(Field * field,const char * value,uint value_length)11056 void ha_mroonga::storage_store_field_date(Field *field,
11057 const char *value,
11058 uint value_length)
11059 {
11060 MRN_DBUG_ENTER_METHOD();
11061 long long int time = *((long long int *)value);
11062 long long int sec, usec __attribute__((unused));
11063 GRN_TIME_UNPACK(time, sec, usec);
11064 struct tm date;
11065 time_t sec_t = static_cast<int32>(sec);
11066 gmtime_r(&sec_t, &date);
11067 long long int date_in_mysql =
11068 (date.tm_year + mrn::TimeConverter::TM_YEAR_BASE) * 10000 +
11069 (date.tm_mon + 1) * 100 +
11070 date.tm_mday;
11071 field->store(date_in_mysql, false);
11072 DBUG_VOID_RETURN;
11073 }
11074
storage_store_field_time(Field * field,const char * value,uint value_length)11075 void ha_mroonga::storage_store_field_time(Field *field,
11076 const char *value,
11077 uint value_length)
11078 {
11079 MRN_DBUG_ENTER_METHOD();
11080 long long int time = *((long long int *)value);
11081 MYSQL_TIME mysql_time;
11082 memset(&mysql_time, 0, sizeof(MYSQL_TIME));
11083 mysql_time.time_type = MYSQL_TIMESTAMP_TIME;
11084 mrn::TimeConverter time_converter;
11085 time_converter.grn_time_to_mysql_time(time, &mysql_time);
11086 #ifdef MRN_FIELD_STORE_TIME_NEED_TYPE
11087 Field_time *time_field = (Field_time *)field;
11088 time_field->store_time(&mysql_time, mysql_time.time_type);
11089 #else
11090 field->store_time(&mysql_time);
11091 #endif
11092 DBUG_VOID_RETURN;
11093 }
11094
storage_store_field_datetime(Field * field,const char * value,uint value_length)11095 void ha_mroonga::storage_store_field_datetime(Field *field,
11096 const char *value,
11097 uint value_length)
11098 {
11099 MRN_DBUG_ENTER_METHOD();
11100 long long int time = *((long long int *)value);
11101 MYSQL_TIME mysql_datetime;
11102 memset(&mysql_datetime, 0, sizeof(MYSQL_TIME));
11103 mysql_datetime.time_type = MYSQL_TIMESTAMP_DATETIME;
11104 mrn::TimeConverter time_converter;
11105 time_converter.grn_time_to_mysql_time(time, &mysql_datetime);
11106 #ifdef MRN_FIELD_STORE_TIME_NEED_TYPE
11107 Field_datetime *datetime_field = (Field_datetime *)field;
11108 datetime_field->store_time(&mysql_datetime, mysql_datetime.time_type);
11109 #else
11110 field->store_time(&mysql_datetime);
11111 #endif
11112 DBUG_VOID_RETURN;
11113 }
11114
storage_store_field_year(Field * field,const char * value,uint value_length)11115 void ha_mroonga::storage_store_field_year(Field *field,
11116 const char *value,
11117 uint value_length)
11118 {
11119 MRN_DBUG_ENTER_METHOD();
11120 long long int time = *((long long int *)value);
11121 MYSQL_TIME mysql_time;
11122 memset(&mysql_time, 0, sizeof(MYSQL_TIME));
11123 mysql_time.time_type = MYSQL_TIMESTAMP_DATE;
11124 mrn::TimeConverter time_converter;
11125 time_converter.grn_time_to_mysql_time(time, &mysql_time);
11126 DBUG_PRINT("info", ("mroonga: stored %d", mysql_time.year));
11127 field->store(mysql_time.year, false);
11128 DBUG_VOID_RETURN;
11129 }
11130
storage_store_field_new_date(Field * field,const char * value,uint value_length)11131 void ha_mroonga::storage_store_field_new_date(Field *field,
11132 const char *value,
11133 uint value_length)
11134 {
11135 MRN_DBUG_ENTER_METHOD();
11136 long long int time = *((long long int *)value);
11137 MYSQL_TIME mysql_date;
11138 memset(&mysql_date, 0, sizeof(MYSQL_TIME));
11139 mysql_date.time_type = MYSQL_TIMESTAMP_DATE;
11140 mrn::TimeConverter time_converter;
11141 time_converter.grn_time_to_mysql_time(time, &mysql_date);
11142 #ifdef MRN_FIELD_STORE_TIME_NEED_TYPE
11143 Field_newdate *newdate_field = (Field_newdate *)field;
11144 newdate_field->store_time(&mysql_date, MYSQL_TIMESTAMP_DATE);
11145 #else
11146 field->store_time(&mysql_date);
11147 #endif
11148 DBUG_VOID_RETURN;
11149 }
11150
11151 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2
storage_store_field_datetime2(Field * field,const char * value,uint value_length)11152 void ha_mroonga::storage_store_field_datetime2(Field *field,
11153 const char *value,
11154 uint value_length)
11155 {
11156 MRN_DBUG_ENTER_METHOD();
11157 long long int time = *((long long int *)value);
11158 MYSQL_TIME mysql_datetime;
11159 memset(&mysql_datetime, 0, sizeof(MYSQL_TIME));
11160 mysql_datetime.time_type = MYSQL_TIMESTAMP_DATETIME;
11161 mrn::TimeConverter time_converter;
11162 time_converter.grn_time_to_mysql_time(time, &mysql_datetime);
11163 field->store_time(&mysql_datetime);
11164 DBUG_VOID_RETURN;
11165 }
11166 #endif
11167
11168 #ifdef MRN_HAVE_MYSQL_TYPE_TIME2
storage_store_field_time2(Field * field,const char * value,uint value_length)11169 void ha_mroonga::storage_store_field_time2(Field *field,
11170 const char *value,
11171 uint value_length)
11172 {
11173 MRN_DBUG_ENTER_METHOD();
11174 long long int time = *((long long int *)value);
11175
11176 MYSQL_TIME mysql_time;
11177 memset(&mysql_time, 0, sizeof(MYSQL_TIME));
11178 mysql_time.time_type = MYSQL_TIMESTAMP_TIME;
11179 mrn::TimeConverter time_converter;
11180 time_converter.grn_time_to_mysql_time(time, &mysql_time);
11181 field->store_time(&mysql_time);
11182 DBUG_VOID_RETURN;
11183 }
11184 #endif
11185
storage_store_field_blob(Field * field,const char * value,uint value_length)11186 void ha_mroonga::storage_store_field_blob(Field *field,
11187 const char *value,
11188 uint value_length)
11189 {
11190 MRN_DBUG_ENTER_METHOD();
11191 Field_blob *blob = (Field_blob *)field;
11192 String *blob_buffer = &blob_buffers[field->field_index];
11193 blob_buffer->length(0);
11194 blob_buffer->reserve(value_length);
11195 blob_buffer->q_append(value, value_length);
11196 blob->set_ptr((uint32) value_length, (uchar *) blob_buffer->ptr());
11197 DBUG_VOID_RETURN;
11198 }
11199
storage_store_field_geometry(Field * field,const char * value,uint value_length)11200 void ha_mroonga::storage_store_field_geometry(Field *field,
11201 const char *value,
11202 uint value_length)
11203 {
11204 MRN_DBUG_ENTER_METHOD();
11205 #ifdef MRN_HAVE_SPATIAL
11206 uchar wkb[SRID_SIZE + WKB_HEADER_SIZE + POINT_DATA_SIZE];
11207 grn_geo_point *field_value = (grn_geo_point *)value;
11208 int latitude, longitude;
11209 latitude = field_value->latitude;
11210 longitude = field_value->longitude;
11211 if (grn_source_column_geo) {
11212 GRN_GEO_POINT_SET(ctx, &source_point, latitude, longitude);
11213 }
11214 memset(wkb, 0, SRID_SIZE);
11215 memset(wkb + SRID_SIZE, Geometry::wkb_ndr, 1); // wkb_ndr is meaningless.
11216 int4store(wkb + SRID_SIZE + 1, Geometry::wkb_point);
11217 double latitude_in_degree, longitude_in_degree;
11218 latitude_in_degree = GRN_GEO_MSEC2DEGREE(latitude);
11219 longitude_in_degree = GRN_GEO_MSEC2DEGREE(longitude);
11220 float8store(wkb + SRID_SIZE + WKB_HEADER_SIZE,
11221 longitude_in_degree);
11222 float8store(wkb + SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE,
11223 latitude_in_degree);
11224 String *geometry_buffer = &blob_buffers[field->field_index];
11225 geometry_buffer->length(0);
11226 uint wkb_length = sizeof(wkb) / sizeof(*wkb);
11227 Field_geom *geometry = (Field_geom *)field;
11228 geometry_buffer->reserve(wkb_length);
11229 geometry_buffer->q_append((const char *) wkb, wkb_length);
11230 geometry->set_ptr((uint32) wkb_length, (uchar *) geometry_buffer->ptr());
11231 #endif
11232 DBUG_VOID_RETURN;
11233 }
11234
11235 #ifdef MRN_HAVE_MYSQL_TYPE_JSON
storage_store_field_json(Field * field,const char * value,uint value_length)11236 void ha_mroonga::storage_store_field_json(Field *field,
11237 const char *value,
11238 uint value_length)
11239 {
11240 MRN_DBUG_ENTER_METHOD();
11241 Field_json *json = static_cast<Field_json *>(field);
11242 json->store(value, value_length, field->charset());
11243 DBUG_VOID_RETURN;
11244 }
11245 #endif
11246
storage_store_field(Field * field,const char * value,uint value_length)11247 void ha_mroonga::storage_store_field(Field *field,
11248 const char *value, uint value_length)
11249 {
11250 field->set_notnull();
11251 switch (field->real_type()) {
11252 case MYSQL_TYPE_DECIMAL:
11253 storage_store_field_string(field, value, value_length);
11254 break;
11255 case MYSQL_TYPE_TINY:
11256 case MYSQL_TYPE_SHORT:
11257 case MYSQL_TYPE_LONG:
11258 storage_store_field_integer(field, value, value_length);
11259 break;
11260 case MYSQL_TYPE_FLOAT:
11261 case MYSQL_TYPE_DOUBLE:
11262 storage_store_field_float(field, value, value_length);
11263 break;
11264 case MYSQL_TYPE_NULL:
11265 storage_store_field_unsigned_integer(field, value, value_length);
11266 break;
11267 case MYSQL_TYPE_TIMESTAMP:
11268 storage_store_field_timestamp(field, value, value_length);
11269 break;
11270 case MYSQL_TYPE_LONGLONG:
11271 case MYSQL_TYPE_INT24:
11272 storage_store_field_integer(field, value, value_length);
11273 break;
11274 case MYSQL_TYPE_DATE:
11275 storage_store_field_date(field, value, value_length);
11276 break;
11277 case MYSQL_TYPE_TIME:
11278 storage_store_field_time(field, value, value_length);
11279 break;
11280 case MYSQL_TYPE_DATETIME:
11281 storage_store_field_datetime(field, value, value_length);
11282 break;
11283 case MYSQL_TYPE_YEAR:
11284 storage_store_field_year(field, value, value_length);
11285 break;
11286 case MYSQL_TYPE_NEWDATE:
11287 storage_store_field_new_date(field, value, value_length);
11288 break;
11289 case MYSQL_TYPE_VARCHAR:
11290 storage_store_field_string(field, value, value_length);
11291 break;
11292 case MYSQL_TYPE_BIT:
11293 storage_store_field_unsigned_integer(field, value, value_length);
11294 break;
11295 #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2
11296 case MYSQL_TYPE_TIMESTAMP2:
11297 storage_store_field_timestamp(field, value, value_length);
11298 break;
11299 #endif
11300 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2
11301 case MYSQL_TYPE_DATETIME2:
11302 storage_store_field_datetime2(field, value, value_length);
11303 break;
11304 #endif
11305 #ifdef MRN_HAVE_MYSQL_TYPE_TIME2
11306 case MYSQL_TYPE_TIME2:
11307 storage_store_field_time2(field, value, value_length);
11308 break;
11309 #endif
11310 case MYSQL_TYPE_NEWDECIMAL:
11311 storage_store_field_string(field, value, value_length);
11312 break;
11313 case MYSQL_TYPE_ENUM:
11314 case MYSQL_TYPE_SET:
11315 storage_store_field_unsigned_integer(field, value, value_length);
11316 break;
11317 case MYSQL_TYPE_TINY_BLOB:
11318 case MYSQL_TYPE_MEDIUM_BLOB:
11319 case MYSQL_TYPE_LONG_BLOB:
11320 case MYSQL_TYPE_BLOB:
11321 storage_store_field_blob(field, value, value_length);
11322 break;
11323 case MYSQL_TYPE_VAR_STRING:
11324 case MYSQL_TYPE_STRING:
11325 storage_store_field_string(field, value, value_length);
11326 break;
11327 case MYSQL_TYPE_GEOMETRY:
11328 storage_store_field_geometry(field, value, value_length);
11329 break;
11330 case MYSQL_TYPE_VARCHAR_COMPRESSED:
11331 case MYSQL_TYPE_BLOB_COMPRESSED:
11332 DBUG_ASSERT(0);
11333 #ifdef MRN_HAVE_MYSQL_TYPE_JSON
11334 case MYSQL_TYPE_JSON:
11335 storage_store_field_json(field, value, value_length);
11336 break;
11337 #endif
11338 }
11339 }
11340
storage_store_field_column(Field * field,bool is_primary_key,int nth_column,grn_id record_id)11341 void ha_mroonga::storage_store_field_column(Field *field, bool is_primary_key,
11342 int nth_column, grn_id record_id)
11343 {
11344 MRN_DBUG_ENTER_METHOD();
11345
11346 if (!grn_columns[nth_column]) {
11347 DBUG_VOID_RETURN;
11348 }
11349
11350 grn_obj *column = grn_columns[nth_column];
11351 grn_id range_id = grn_obj_get_range(ctx, column);
11352 grn_obj *range = grn_column_ranges[nth_column];
11353 grn_obj *value = &new_value_buffer;
11354
11355 if (mrn::grn::is_table(range)) {
11356 if (mrn::grn::is_vector_column(column)) {
11357 grn_obj_reinit(ctx, value, range_id, GRN_OBJ_VECTOR);
11358 grn_obj_get_value(ctx, column, record_id, value);
11359
11360 grn_obj unvectored_value;
11361 GRN_TEXT_INIT(&unvectored_value, 0);
11362 int n_ids = GRN_BULK_VSIZE(value) / sizeof(grn_id);
11363 for (int i = 0; i < n_ids; i++) {
11364 grn_id id = GRN_RECORD_VALUE_AT(value, i);
11365 if (i > 0) {
11366 GRN_TEXT_PUTS(ctx, &unvectored_value, mrn_vector_column_delimiter);
11367 }
11368 char key[GRN_TABLE_MAX_KEY_SIZE];
11369 int key_length;
11370 key_length = grn_table_get_key(ctx, range, id,
11371 &key, GRN_TABLE_MAX_KEY_SIZE);
11372 GRN_TEXT_PUT(ctx, &unvectored_value, key, key_length);
11373 }
11374 storage_store_field(field,
11375 GRN_TEXT_VALUE(&unvectored_value),
11376 GRN_TEXT_LEN(&unvectored_value));
11377 GRN_OBJ_FIN(ctx, &unvectored_value);
11378 } else {
11379 grn_obj_reinit(ctx, value, range_id, 0);
11380 grn_obj_get_value(ctx, column, record_id, value);
11381
11382 grn_id id = GRN_RECORD_VALUE(value);
11383 char key[GRN_TABLE_MAX_KEY_SIZE];
11384 int key_length;
11385 key_length = grn_table_get_key(ctx, range, id,
11386 &key, GRN_TABLE_MAX_KEY_SIZE);
11387 storage_store_field(field, key, key_length);
11388 }
11389 } else {
11390 grn_obj_reinit(ctx, value, range_id, 0);
11391 grn_obj_get_value(ctx, column, record_id, value);
11392 if (is_primary_key && GRN_BULK_VSIZE(value) == 0) {
11393 char key[GRN_TABLE_MAX_KEY_SIZE];
11394 int key_length;
11395 key_length = grn_table_get_key(ctx, grn_table, record_id,
11396 &key, GRN_TABLE_MAX_KEY_SIZE);
11397 storage_store_field(field, key, key_length);
11398 } else {
11399 storage_store_field(field, GRN_BULK_HEAD(value), GRN_BULK_VSIZE(value));
11400 }
11401 }
11402
11403 DBUG_VOID_RETURN;
11404 }
11405
storage_store_fields(uchar * buf,grn_id record_id)11406 void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id)
11407 {
11408 MRN_DBUG_ENTER_METHOD();
11409 DBUG_PRINT("info", ("mroonga: stored record ID: %d", record_id));
11410
11411 my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(buf, table->record[0]);
11412
11413 Field *primary_key_field = NULL;
11414 if (table->s->primary_key != MAX_INDEXES) {
11415 KEY *key_info = &(table->s->key_info[table->s->primary_key]);
11416 if (KEY_N_KEY_PARTS(key_info) == 1) {
11417 primary_key_field = key_info->key_part[0].field;
11418 }
11419 }
11420
11421 int i;
11422 int n_columns = table->s->fields;
11423 for (i = 0; i < n_columns; i++) {
11424 Field *field = table->field[i];
11425
11426 if (bitmap_is_set(table->read_set, field->field_index) ||
11427 bitmap_is_set(table->write_set, field->field_index)) {
11428 const char *column_name = field->field_name.str;
11429
11430 if (ignoring_no_key_columns) {
11431 KEY *key_info = &(table->s->key_info[active_index]);
11432 if (strcmp(key_info->key_part[0].field->field_name.str, column_name)) {
11433 continue;
11434 }
11435 }
11436
11437 mrn::DebugColumnAccess debug_column_access(table, &table->write_set);
11438 DBUG_PRINT("info", ("mroonga: store column %d(%d)",i,field->field_index));
11439 field->move_field_offset(ptr_diff);
11440 if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
11441 // for _id column
11442 field->set_notnull();
11443 field->store((int)record_id);
11444 } else if (primary_key_field &&
11445 strcmp(primary_key_field->field_name.str, column_name) == 0) {
11446 // for primary key column
11447 storage_store_field_column(field, true, i, record_id);
11448 } else {
11449 storage_store_field_column(field, false, i, record_id);
11450 }
11451 field->move_field_offset(-ptr_diff);
11452 }
11453 }
11454
11455 DBUG_VOID_RETURN;
11456 }
11457
storage_store_fields_for_prep_update(const uchar * old_data,const uchar * new_data,grn_id record_id)11458 void ha_mroonga::storage_store_fields_for_prep_update(const uchar *old_data,
11459 const uchar *new_data,
11460 grn_id record_id)
11461 {
11462 MRN_DBUG_ENTER_METHOD();
11463 DBUG_PRINT("info", ("mroonga: stored record ID: %d", record_id));
11464 my_ptrdiff_t ptr_diff_old = PTR_BYTE_DIFF(old_data, table->record[0]);
11465 my_ptrdiff_t ptr_diff_new = 0;
11466 #ifdef MRN_RBR_UPDATE_NEED_ALL_COLUMNS
11467 if (!written_by_row_based_binlog) {
11468 if (check_written_by_row_based_binlog()) {
11469 written_by_row_based_binlog = 2;
11470 } else {
11471 written_by_row_based_binlog = 1;
11472 }
11473 }
11474 bool need_all_columns =
11475 (new_data && written_by_row_based_binlog == 2);
11476 #endif
11477 if (new_data) {
11478 ptr_diff_new = PTR_BYTE_DIFF(new_data, table->record[0]);
11479 }
11480 int i;
11481 int n_columns = table->s->fields;
11482 for (i = 0; i < n_columns; i++) {
11483 Field *field = table->field[i];
11484
11485 #ifdef MRN_SUPPORT_GENERATED_COLUMNS
11486 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
11487 continue;
11488 }
11489 #endif
11490 if (
11491 !bitmap_is_set(table->read_set, field->field_index) &&
11492 !bitmap_is_set(table->write_set, field->field_index) &&
11493 #ifdef MRN_RBR_UPDATE_NEED_ALL_COLUMNS
11494 (
11495 need_all_columns ||
11496 #endif
11497 bitmap_is_set(&multiple_column_key_bitmap, field->field_index)
11498 #ifdef MRN_RBR_UPDATE_NEED_ALL_COLUMNS
11499 )
11500 #endif
11501 ) {
11502 mrn::DebugColumnAccess debug_column_access(table, &table->write_set);
11503 DBUG_PRINT("info", ("mroonga: store column %d(%d)",i,field->field_index));
11504 grn_obj value;
11505 GRN_OBJ_INIT(&value, GRN_BULK, 0, grn_obj_get_range(ctx, grn_columns[i]));
11506 grn_obj_get_value(ctx, grn_columns[i], record_id, &value);
11507 // old column
11508 field->move_field_offset(ptr_diff_old);
11509 storage_store_field(field, GRN_BULK_HEAD(&value), GRN_BULK_VSIZE(&value));
11510 field->move_field_offset(-ptr_diff_old);
11511 if (new_data) {
11512 // new column
11513 field->move_field_offset(ptr_diff_new);
11514 storage_store_field(field, GRN_BULK_HEAD(&value), GRN_BULK_VSIZE(&value));
11515 field->move_field_offset(-ptr_diff_new);
11516 }
11517 GRN_OBJ_FIN(ctx, &value);
11518 }
11519 }
11520
11521 DBUG_VOID_RETURN;
11522 }
11523
storage_store_fields_by_index(uchar * buf)11524 void ha_mroonga::storage_store_fields_by_index(uchar *buf)
11525 {
11526 MRN_DBUG_ENTER_METHOD();
11527 uint key_length;
11528 void *key;
11529 KEY *key_info = &table->key_info[active_index];
11530 if (table->s->primary_key == active_index)
11531 key_length = grn_table_cursor_get_key(ctx, cursor, &key);
11532 else
11533 key_length = grn_table_cursor_get_key(ctx, index_table_cursor, &key);
11534
11535 if (KEY_N_KEY_PARTS(key_info) == 1) {
11536 my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(buf, table->record[0]);
11537 Field *field = key_info->key_part->field;
11538 mrn::DebugColumnAccess debug_column_access(table, &table->write_set);
11539 field->move_field_offset(ptr_diff);
11540 storage_store_field(field, (const char *)key, key_length);
11541 field->move_field_offset(-ptr_diff);
11542 } else {
11543 uchar enc_buf[MAX_KEY_LENGTH];
11544 uint enc_len;
11545 mrn::MultipleColumnKeyCodec codec(ctx, ha_thd(), key_info);
11546 codec.decode(static_cast<uchar *>(key), key_length, enc_buf, &enc_len);
11547 key_restore(buf, enc_buf, key_info, enc_len);
11548 }
11549 DBUG_VOID_RETURN;
11550 }
11551
storage_encode_key_normalize_min_sort_chars(Field * field,uchar * buf,uint size)11552 int ha_mroonga::storage_encode_key_normalize_min_sort_chars(Field *field,
11553 uchar *buf,
11554 uint size)
11555 {
11556 MRN_DBUG_ENTER_METHOD();
11557 int error = 0;
11558
11559 if (size == 0) {
11560 DBUG_RETURN(0);
11561 }
11562 if (!field->has_charset()) {
11563 DBUG_RETURN(0);
11564 }
11565
11566 uint16 raw_min_sort_char =
11567 static_cast<uint16>(field->sort_charset()->min_sort_char);
11568 if (raw_min_sort_char <= UINT_MAX8) {
11569 uchar min_sort_char = static_cast<uchar>(raw_min_sort_char);
11570 for (uint i = size - 1; i > 0; --i) {
11571 if (buf[i] != min_sort_char) {
11572 break;
11573 }
11574 buf[i] = '\0';
11575 }
11576 }
11577
11578 DBUG_RETURN(error);
11579 }
11580
storage_encode_key_fixed_size_string(Field * field,const uchar * key,uchar * buf,uint * size)11581 int ha_mroonga::storage_encode_key_fixed_size_string(Field *field,
11582 const uchar *key,
11583 uchar *buf, uint *size)
11584 {
11585 MRN_DBUG_ENTER_METHOD();
11586 int error = 0;
11587 memcpy(buf, key, field->field_length);
11588 *size = field->field_length;
11589 DBUG_RETURN(error);
11590 }
11591
storage_encode_key_variable_size_string(Field * field,const uchar * key,uchar * buf,uint * size)11592 int ha_mroonga::storage_encode_key_variable_size_string(Field *field,
11593 const uchar *key,
11594 uchar *buf, uint *size)
11595 {
11596 MRN_DBUG_ENTER_METHOD();
11597 int error = 0;
11598 *size = uint2korr(key);
11599 memcpy(buf, key + HA_KEY_BLOB_LENGTH, *size);
11600 storage_encode_key_normalize_min_sort_chars(field, buf, *size);
11601 DBUG_RETURN(error);
11602 }
11603
storage_encode_key_timestamp(Field * field,const uchar * key,uchar * buf,uint * size)11604 int ha_mroonga::storage_encode_key_timestamp(Field *field, const uchar *key,
11605 uchar *buf, uint *size)
11606 {
11607 MRN_DBUG_ENTER_METHOD();
11608 int error = 0;
11609 bool truncated = false;
11610 long long int time;
11611 MYSQL_TIME mysql_time;
11612 #ifdef MRN_MARIADB_P
11613 if (field->decimals() == 0) {
11614 my_time_t my_time = sint4korr(key);
11615 mrn_my_tz_UTC->gmt_sec_to_TIME(&mysql_time, my_time);
11616 mysql_time.second_part = 0;
11617 } else {
11618 Field_timestamp_hires *timestamp_hires_field =
11619 (Field_timestamp_hires *)field;
11620 uint fuzzy_date = 0;
11621 uchar *ptr_backup = field->ptr;
11622 uchar *null_ptr_backup = field->null_ptr;
11623 TABLE *table_backup = field->table;
11624 field->ptr = (uchar *)key;
11625 field->null_ptr = (uchar *)(key - 1);
11626 field->table = table;
11627 timestamp_hires_field->get_date(&mysql_time, fuzzy_date);
11628 field->ptr = ptr_backup;
11629 field->null_ptr = null_ptr_backup;
11630 field->table = table_backup;
11631 }
11632 #else
11633 my_time_t my_time = uint4korr(key);
11634 mrn_my_tz_UTC->gmt_sec_to_TIME(&mysql_time, my_time);
11635 #endif
11636 mrn::TimeConverter time_converter;
11637 time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated);
11638 if (truncated) {
11639 if (MRN_ABORT_ON_WARNING(ha_thd())) {
11640 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
11641 }
11642 field->set_warning(MRN_SEVERITY_WARNING,
11643 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
11644 1);
11645 }
11646 memcpy(buf, &time, 8);
11647 *size = 8;
11648 DBUG_RETURN(error);
11649 }
11650
storage_encode_key_time(Field * field,const uchar * key,uchar * buf,uint * size)11651 int ha_mroonga::storage_encode_key_time(Field *field, const uchar *key,
11652 uchar *buf, uint *size)
11653 {
11654 MRN_DBUG_ENTER_METHOD();
11655 int error = 0;
11656 long long int time;
11657 #ifdef MRN_MARIADB_P
11658 MYSQL_TIME mysql_time;
11659 bool truncated = false;
11660 if (field->decimals() == 0) {
11661 long long int packed_time = sint3korr(key);
11662 mysql_time.neg = false;
11663 if (packed_time < 0) {
11664 mysql_time.neg = true;
11665 packed_time = -packed_time;
11666 }
11667 mysql_time.year = 0;
11668 mysql_time.month = 0;
11669 mysql_time.day = 0;
11670 mysql_time.hour = (int)(packed_time / 10000);
11671 long long int minute_part = packed_time - mysql_time.hour * 10000;
11672 mysql_time.minute = (int)(minute_part / 100);
11673 mysql_time.second = (int)(minute_part % 100);
11674 mysql_time.second_part = 0;
11675 mysql_time.time_type = MYSQL_TIMESTAMP_TIME;
11676 } else {
11677 Field_time_hires *time_hires_field = (Field_time_hires *)field;
11678 uint fuzzy_date = 0;
11679 uchar *ptr_backup = field->ptr;
11680 uchar *null_ptr_backup = field->null_ptr;
11681 field->ptr = (uchar *)key;
11682 field->null_ptr = (uchar *)(key - 1);
11683 time_hires_field->get_date(&mysql_time, fuzzy_date);
11684 field->ptr = ptr_backup;
11685 field->null_ptr = null_ptr_backup;
11686 }
11687 mrn::TimeConverter time_converter;
11688 time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated);
11689 if (truncated) {
11690 if (MRN_ABORT_ON_WARNING(ha_thd())) {
11691 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
11692 }
11693 field->set_warning(MRN_SEVERITY_WARNING,
11694 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
11695 1);
11696 }
11697 #else
11698 int mysql_time = (int)sint3korr(key);
11699 int sec =
11700 mysql_time / 10000 * 60 * 60 +
11701 mysql_time / 100 % 100 * 60 +
11702 mysql_time % 60;
11703 int usec = 0;
11704 time = GRN_TIME_PACK(sec, usec);
11705 #endif
11706 memcpy(buf, &time, 8);
11707 *size = 8;
11708 DBUG_RETURN(error);
11709 }
11710
storage_encode_key_year(Field * field,const uchar * key,uchar * buf,uint * size)11711 int ha_mroonga::storage_encode_key_year(Field *field, const uchar *key,
11712 uchar *buf, uint *size)
11713 {
11714 MRN_DBUG_ENTER_METHOD();
11715 int error = 0;
11716 bool truncated = false;
11717 int year = (int)key[0];
11718
11719 struct tm datetime;
11720 memset(&datetime, 0, sizeof(struct tm));
11721 datetime.tm_year = year;
11722 datetime.tm_mon = 0;
11723 datetime.tm_mday = 1;
11724 int usec = 0;
11725 mrn::TimeConverter time_converter;
11726 long long int time = time_converter.tm_to_grn_time(&datetime, usec,
11727 &truncated);
11728 if (truncated) {
11729 if (MRN_ABORT_ON_WARNING(ha_thd())) {
11730 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
11731 }
11732 field->set_warning(MRN_SEVERITY_WARNING,
11733 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
11734 1);
11735 }
11736 memcpy(buf, &time, 8);
11737 *size = 8;
11738 DBUG_RETURN(error);
11739 }
11740
storage_encode_key_datetime(Field * field,const uchar * key,uchar * buf,uint * size)11741 int ha_mroonga::storage_encode_key_datetime(Field *field, const uchar *key,
11742 uchar *buf, uint *size)
11743 {
11744 MRN_DBUG_ENTER_METHOD();
11745 int error = 0;
11746 bool truncated = false;
11747 long long int time;
11748 #ifdef MRN_MARIADB_P
11749 if (field->decimals() > 0) {
11750 Field_datetime_hires *datetime_hires_field = (Field_datetime_hires *)field;
11751 MYSQL_TIME mysql_time;
11752 uint fuzzy_date = 0;
11753 uchar *ptr_backup = field->ptr;
11754 uchar *null_ptr_backup = field->null_ptr;
11755 field->ptr = (uchar *)key;
11756 field->null_ptr = (uchar *)(key - 1);
11757 datetime_hires_field->get_date(&mysql_time, fuzzy_date);
11758 field->ptr = ptr_backup;
11759 field->null_ptr = null_ptr_backup;
11760 mrn::TimeConverter time_converter;
11761 time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated);
11762 } else
11763 #endif
11764 {
11765 long long int encoded_datetime = sint8korr(key);
11766 uint32 part1 = (uint32)(encoded_datetime / 1000000LL);
11767 uint32 part2 = (uint32)(encoded_datetime -
11768 (unsigned long long int)part1 * 1000000LL);
11769 struct tm date;
11770 memset(&date, 0, sizeof(struct tm));
11771 date.tm_year = part1 / 10000 - mrn::TimeConverter::TM_YEAR_BASE;
11772 date.tm_mon = part1 / 100 % 100 - 1;
11773 date.tm_mday = part1 % 100;
11774 date.tm_hour = part2 / 10000;
11775 date.tm_min = part2 / 100 % 100;
11776 date.tm_sec = part2 % 100;
11777 int usec = 0;
11778 mrn::TimeConverter time_converter;
11779 time = time_converter.tm_to_grn_time(&date, usec, &truncated);
11780 }
11781 if (truncated) {
11782 if (MRN_ABORT_ON_WARNING(ha_thd())) {
11783 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
11784 }
11785 field->set_warning(MRN_SEVERITY_WARNING,
11786 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
11787 1);
11788 }
11789 memcpy(buf, &time, 8);
11790 *size = 8;
11791 DBUG_RETURN(error);
11792 }
11793
11794 #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2
storage_encode_key_timestamp2(Field * field,const uchar * key,uchar * buf,uint * size)11795 int ha_mroonga::storage_encode_key_timestamp2(Field *field, const uchar *key,
11796 uchar *buf, uint *size)
11797 {
11798 MRN_DBUG_ENTER_METHOD();
11799 int error = 0;
11800 bool truncated = false;
11801
11802 Field_timestampf *timestamp2_field = (Field_timestampf *)field;
11803 struct timeval tm;
11804 my_timestamp_from_binary(&tm, key, timestamp2_field->decimals());
11805 MYSQL_TIME mysql_time;
11806 mrn_my_tz_UTC->gmt_sec_to_TIME(&mysql_time, (my_time_t)tm.tv_sec);
11807 mysql_time.second_part = tm.tv_usec;
11808 mrn::TimeConverter time_converter;
11809 long long int grn_time = time_converter.mysql_time_to_grn_time(&mysql_time,
11810 &truncated);
11811 if (truncated) {
11812 if (MRN_ABORT_ON_WARNING(ha_thd())) {
11813 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
11814 }
11815 field->set_warning(MRN_SEVERITY_WARNING,
11816 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
11817 1);
11818 }
11819 memcpy(buf, &grn_time, 8);
11820 *size = 8;
11821
11822 DBUG_RETURN(error);
11823 }
11824 #endif
11825
11826 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2
storage_encode_key_datetime2(Field * field,bool is_null,const uchar * key,uchar * buf,uint * size)11827 int ha_mroonga::storage_encode_key_datetime2(Field *field, bool is_null,
11828 const uchar *key,
11829 uchar *buf, uint *size)
11830 {
11831 MRN_DBUG_ENTER_METHOD();
11832 int error = 0;
11833 bool truncated = false;
11834
11835 Field_datetimef *datetime2_field = (Field_datetimef *)field;
11836 longlong packed_time = is_null ? 0 :
11837 my_datetime_packed_from_binary(key, datetime2_field->decimals());
11838 MYSQL_TIME mysql_time;
11839 TIME_from_longlong_datetime_packed(&mysql_time, packed_time);
11840 mrn::TimeConverter time_converter;
11841 long long int grn_time = time_converter.mysql_time_to_grn_time(&mysql_time,
11842 &truncated);
11843 if (truncated) {
11844 if (MRN_ABORT_ON_WARNING(ha_thd())) {
11845 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
11846 }
11847 field->set_warning(MRN_SEVERITY_WARNING,
11848 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
11849 1);
11850 }
11851 memcpy(buf, &grn_time, 8);
11852 *size = 8;
11853
11854 DBUG_RETURN(error);
11855 }
11856 #endif
11857
11858 #ifdef MRN_HAVE_MYSQL_TYPE_TIME2
storage_encode_key_time2(Field * field,const uchar * key,uchar * buf,uint * size)11859 int ha_mroonga::storage_encode_key_time2(Field *field, const uchar *key,
11860 uchar *buf, uint *size)
11861 {
11862 MRN_DBUG_ENTER_METHOD();
11863 int error = 0;
11864 bool truncated = false;
11865
11866 Field_timef *time2_field = (Field_timef *)field;
11867 longlong packed_time =
11868 my_time_packed_from_binary(key, time2_field->decimals());
11869 MYSQL_TIME mysql_time;
11870 TIME_from_longlong_time_packed(&mysql_time, packed_time);
11871 mrn::TimeConverter time_converter;
11872 long long int grn_time = time_converter.mysql_time_to_grn_time(&mysql_time,
11873 &truncated);
11874 if (truncated) {
11875 if (MRN_ABORT_ON_WARNING(ha_thd())) {
11876 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
11877 }
11878 field->set_warning(MRN_SEVERITY_WARNING,
11879 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
11880 1);
11881 }
11882 memcpy(buf, &grn_time, 8);
11883 *size = 8;
11884
11885 DBUG_RETURN(error);
11886 }
11887 #endif
11888
storage_encode_key_enum(Field * field,const uchar * key,uchar * buf,uint * size)11889 int ha_mroonga::storage_encode_key_enum(Field *field, const uchar *key,
11890 uchar *buf, uint *size)
11891 {
11892 MRN_DBUG_ENTER_METHOD();
11893 int error = 0;
11894 if (field->pack_length() == 1) {
11895 uchar value;
11896 value = key[0];
11897 *size = 1;
11898 memcpy(buf, &value, *size);
11899 } else {
11900 uint16 value;
11901 mrn::value_decoder::decode(&value, key);
11902 *size = 2;
11903 memcpy(buf, &value, *size);
11904 }
11905 DBUG_RETURN(error);
11906 }
11907
storage_encode_key_set(Field * field,const uchar * key,uchar * buf,uint * size)11908 int ha_mroonga::storage_encode_key_set(Field *field, const uchar *key,
11909 uchar *buf, uint *size)
11910 {
11911 MRN_DBUG_ENTER_METHOD();
11912 int error = 0;
11913 Field_set unpacker((uchar *)key, field->field_length, (uchar *)(key - 1),
11914 field->null_bit, field->unireg_check,
11915 &field->field_name,
11916 field->pack_length(),
11917 static_cast<Field_set*>(field)->typelib,
11918 static_cast<Field_set*>(field)->charset());
11919 switch (field->pack_length()) {
11920 case 1:
11921 {
11922 int8 signed_value = (int8)(unpacker.val_int());
11923 uint8 unsigned_value = *((uint8 *)&signed_value);
11924 *size = 1;
11925 memcpy(buf, &unsigned_value, *size);
11926 }
11927 break;
11928 case 2:
11929 {
11930 int16 signed_value = (int16)(unpacker.val_int());
11931 uint16 unsigned_value = *((uint16 *)&signed_value);
11932 *size = 2;
11933 memcpy(buf, &unsigned_value, *size);
11934 }
11935 break;
11936 case 3:
11937 case 4:
11938 {
11939 int32 signed_value = (int32)(unpacker.val_int());
11940 uint32 unsigned_value = *((uint32 *)&signed_value);
11941 *size = 4;
11942 memcpy(buf, &unsigned_value, *size);
11943 }
11944 break;
11945 case 8:
11946 default:
11947 {
11948 int64 signed_value = (int64)(unpacker.val_int());
11949 uint64 unsigned_value = *((uint64 *)&signed_value);
11950 *size = 8;
11951 memcpy(buf, &unsigned_value, *size);
11952 }
11953 break;
11954 }
11955 DBUG_RETURN(error);
11956 }
11957
storage_encode_key(Field * field,const uchar * key,uchar * buf,uint * size)11958 int ha_mroonga::storage_encode_key(Field *field, const uchar *key,
11959 uchar *buf, uint *size)
11960 {
11961 MRN_DBUG_ENTER_METHOD();
11962 int error;
11963 bool truncated = false;
11964 bool is_null = false;
11965 const uchar *ptr = key;
11966
11967 error = mrn_change_encoding(ctx, field->charset());
11968 if (error)
11969 DBUG_RETURN(error);
11970
11971 if (field->null_bit) {
11972 is_null = *ptr;
11973 ptr += 1;
11974 }
11975
11976 switch (field->real_type()) {
11977 case MYSQL_TYPE_BIT:
11978 case MYSQL_TYPE_TINY:
11979 {
11980 memcpy(buf, ptr, 1);
11981 *size = 1;
11982 break;
11983 }
11984 case MYSQL_TYPE_SHORT:
11985 {
11986 memcpy(buf, ptr, 2);
11987 *size = 2;
11988 break;
11989 }
11990 case MYSQL_TYPE_INT24:
11991 {
11992 memcpy(buf, ptr, 3);
11993 buf[3] = 0;
11994 *size = 4;
11995 break;
11996 }
11997 case MYSQL_TYPE_LONG:
11998 {
11999 memcpy(buf, ptr, 4);
12000 *size = 4;
12001 break;
12002 }
12003 case MYSQL_TYPE_TIMESTAMP:
12004 error = storage_encode_key_timestamp(field, ptr, buf, size);
12005 break;
12006 case MYSQL_TYPE_LONGLONG:
12007 {
12008 memcpy(buf, ptr, 8);
12009 *size = 8;
12010 break;
12011 }
12012 case MYSQL_TYPE_FLOAT:
12013 {
12014 float float_value;
12015 double double_value;
12016 mrn::value_decoder::decode(&float_value, ptr);
12017 double_value = float_value;
12018 memcpy(buf, &double_value, 8);
12019 *size = 8;
12020 break;
12021 }
12022 case MYSQL_TYPE_DOUBLE:
12023 {
12024 double val;
12025 mrn::value_decoder::decode(&val, ptr);
12026 memcpy(buf, &val, 8);
12027 *size = 8;
12028 break;
12029 }
12030 case MYSQL_TYPE_TIME:
12031 error = storage_encode_key_time(field, ptr, buf, size);
12032 break;
12033 case MYSQL_TYPE_YEAR:
12034 error = storage_encode_key_year(field, ptr, buf, size);
12035 break;
12036 case MYSQL_TYPE_DATETIME:
12037 error = storage_encode_key_datetime(field, ptr, buf, size);
12038 break;
12039 case MYSQL_TYPE_NEWDATE:
12040 {
12041 uint32 encoded_date = uint3korr(ptr);
12042 struct tm date;
12043 memset(&date, 0, sizeof(struct tm));
12044 date.tm_year = encoded_date / (16 * 32) - mrn::TimeConverter::TM_YEAR_BASE;
12045 date.tm_mon = encoded_date / 32 % 16 - 1;
12046 date.tm_mday = encoded_date % 32;
12047 int usec = 0;
12048 mrn::TimeConverter time_converter;
12049 long long int time = time_converter.tm_to_grn_time(&date, usec,
12050 &truncated);
12051 if (truncated) {
12052 if (MRN_ABORT_ON_WARNING(ha_thd())) {
12053 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
12054 }
12055 field->set_warning(MRN_SEVERITY_WARNING,
12056 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
12057 1);
12058 }
12059 memcpy(buf, &time, 8);
12060 *size = 8;
12061 break;
12062 }
12063 #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2
12064 case MYSQL_TYPE_TIMESTAMP2:
12065 error = storage_encode_key_timestamp2(field, ptr, buf, size);
12066 break;
12067 #endif
12068 #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2
12069 case MYSQL_TYPE_DATETIME2:
12070 error = storage_encode_key_datetime2(field, is_null, ptr, buf, size);
12071 break;
12072 #endif
12073 #ifdef MRN_HAVE_MYSQL_TYPE_TIME2
12074 case MYSQL_TYPE_TIME2:
12075 error = storage_encode_key_time2(field, ptr, buf, size);
12076 break;
12077 #endif
12078 case MYSQL_TYPE_STRING:
12079 error = storage_encode_key_fixed_size_string(field, ptr, buf, size);
12080 break;
12081 case MYSQL_TYPE_VARCHAR:
12082 case MYSQL_TYPE_BLOB:
12083 error = storage_encode_key_variable_size_string(field, ptr, buf, size);
12084 break;
12085 case MYSQL_TYPE_ENUM:
12086 error = storage_encode_key_enum(field, ptr, buf, size);
12087 break;
12088 case MYSQL_TYPE_SET:
12089 error = storage_encode_key_set(field, ptr, buf, size);
12090 break;
12091 default:
12092 error = HA_ERR_UNSUPPORTED;
12093 break;
12094 }
12095 DBUG_RETURN(error);
12096 }
12097
storage_encode_multiple_column_key(KEY * key_info,const uchar * key,uint key_length,uchar * buffer,uint * encoded_length)12098 int ha_mroonga::storage_encode_multiple_column_key(KEY *key_info,
12099 const uchar *key,
12100 uint key_length,
12101 uchar *buffer,
12102 uint *encoded_length)
12103 {
12104 MRN_DBUG_ENTER_METHOD();
12105 mrn::MultipleColumnKeyCodec codec(ctx, ha_thd(), key_info);
12106 int error = codec.encode(key, key_length, buffer, encoded_length);
12107 DBUG_RETURN(error);
12108 }
12109
storage_encode_multiple_column_key_range(KEY * key_info,const uchar * start,uint start_size,const uchar * end,uint end_size,uchar * min_buffer,uint * min_encoded_size,uchar * max_buffer,uint * max_encoded_size)12110 int ha_mroonga::storage_encode_multiple_column_key_range(KEY *key_info,
12111 const uchar *start,
12112 uint start_size,
12113 const uchar *end,
12114 uint end_size,
12115 uchar *min_buffer,
12116 uint *min_encoded_size,
12117 uchar *max_buffer,
12118 uint *max_encoded_size)
12119 {
12120 MRN_DBUG_ENTER_METHOD();
12121 int error = 0;
12122 mrn::MultipleColumnKeyCodec codec(ctx, ha_thd(), key_info);
12123 uint encoded_key_size = codec.size();
12124 if (start) {
12125 memset(min_buffer, 0, encoded_key_size);
12126 error = codec.encode(start, start_size,
12127 min_buffer, min_encoded_size);
12128 // TODO: handle error?
12129 *min_encoded_size = encoded_key_size;
12130 }
12131 if (end) {
12132 memset(max_buffer, 0xff, encoded_key_size);
12133 error = codec.encode(end, end_size,
12134 max_buffer, max_encoded_size);
12135 // TODO: handle error?
12136 *max_encoded_size = encoded_key_size;
12137 }
12138 DBUG_RETURN(error);
12139 }
12140
storage_encode_multiple_column_key_range(KEY * key_info,const key_range * start,const key_range * end,uchar * min_buffer,uint * min_encoded_size,uchar * max_buffer,uint * max_encoded_size)12141 int ha_mroonga::storage_encode_multiple_column_key_range(KEY *key_info,
12142 const key_range *start,
12143 const key_range *end,
12144 uchar *min_buffer,
12145 uint *min_encoded_size,
12146 uchar *max_buffer,
12147 uint *max_encoded_size)
12148 {
12149 MRN_DBUG_ENTER_METHOD();
12150
12151 const uchar *start_data = NULL;
12152 uint start_size = 0;
12153 const uchar *end_data = NULL;
12154 uint end_size = 0;
12155 if (start) {
12156 start_data = start->key;
12157 start_size = start->length;
12158 }
12159 if (end) {
12160 end_data = end->key;
12161 end_size = end->length;
12162 }
12163
12164 int error = storage_encode_multiple_column_key_range(key_info,
12165 start_data, start_size,
12166 end_data, end_size,
12167 min_buffer,
12168 min_encoded_size,
12169 max_buffer,
12170 max_encoded_size);
12171
12172 DBUG_RETURN(error);
12173 }
12174
generic_reset()12175 int ha_mroonga::generic_reset()
12176 {
12177 MRN_DBUG_ENTER_METHOD();
12178 int error = 0;
12179
12180 if (thd_sql_command(ha_thd()) != SQLCOM_SELECT) {
12181 DBUG_RETURN(error);
12182 }
12183
12184 TABLE_LIST *table_list = table->pos_in_table_list;
12185 if (!table_list) {
12186 DBUG_RETURN(error);
12187 }
12188
12189 st_select_lex *select_lex = table_list->select_lex;
12190 if (!select_lex) {
12191 DBUG_RETURN(error);
12192 }
12193
12194 List_iterator<Item_func_match> iterator(*(select_lex->ftfunc_list));
12195 Item_func_match *item;
12196 while ((item = iterator++)) {
12197 if (item->ft_handler) {
12198 mrn_generic_ft_clear(item->ft_handler);
12199 }
12200 }
12201
12202 DBUG_RETURN(error);
12203 }
12204
wrapper_reset()12205 int ha_mroonga::wrapper_reset()
12206 {
12207 MRN_DBUG_ENTER_METHOD();
12208 int error = 0;
12209 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12210 MRN_SET_WRAP_TABLE_KEY(this, table);
12211 error = wrap_handler->ha_reset();
12212 MRN_SET_BASE_SHARE_KEY(share, table->s);
12213 MRN_SET_BASE_TABLE_KEY(this, table);
12214 #ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER
12215 if (alter_key_info_buffer) {
12216 my_free(alter_key_info_buffer);
12217 alter_key_info_buffer = NULL;
12218 }
12219 #else
12220 if (wrap_alter_key_info) {
12221 my_free(wrap_alter_key_info);
12222 wrap_alter_key_info = NULL;
12223 }
12224 #endif
12225 wrap_ft_init_count = 0;
12226 int generic_error = generic_reset();
12227 if (error == 0) {
12228 error = generic_error;
12229 }
12230 DBUG_RETURN(error);
12231 }
12232
storage_reset()12233 int ha_mroonga::storage_reset()
12234 {
12235 MRN_DBUG_ENTER_METHOD();
12236 int error;
12237 error = generic_reset();
12238 DBUG_RETURN(error);
12239 }
12240
reset()12241 int ha_mroonga::reset()
12242 {
12243 int error = 0;
12244 THD *thd = ha_thd();
12245 MRN_DBUG_ENTER_METHOD();
12246 DBUG_PRINT("info", ("mroonga: this=%p", this));
12247 clear_empty_value_records();
12248 clear_search_result();
12249 clear_search_result_geo();
12250 if (share->wrapper_mode)
12251 error = wrapper_reset();
12252 else
12253 error = storage_reset();
12254 ignoring_no_key_columns = false;
12255 inserting_with_update = false;
12256 ignoring_duplicated_key = false;
12257 fulltext_searching = false;
12258 replacing_ = false;
12259 written_by_row_based_binlog = 0;
12260 mrn_lock_type = F_UNLCK;
12261 mrn_clear_slot_data(thd);
12262 current_ft_item = NULL;
12263 DBUG_RETURN(error);
12264 }
12265
wrapper_clone(const char * name,MEM_ROOT * mem_root)12266 handler *ha_mroonga::wrapper_clone(const char *name, MEM_ROOT *mem_root)
12267 {
12268 handler *cloned_handler;
12269 MRN_DBUG_ENTER_METHOD();
12270 if (!(cloned_handler = get_new_handler(table->s, mem_root,
12271 table->s->db_type())))
12272 DBUG_RETURN(NULL);
12273 ((ha_mroonga *) cloned_handler)->is_clone = true;
12274 ((ha_mroonga *) cloned_handler)->parent_for_clone = this;
12275 ((ha_mroonga *) cloned_handler)->mem_root_for_clone = mem_root;
12276 if (cloned_handler->ha_open(table, table->s->normalized_path.str,
12277 table->db_stat, HA_OPEN_IGNORE_IF_LOCKED))
12278 {
12279 delete cloned_handler;
12280 DBUG_RETURN(NULL);
12281 }
12282 DBUG_RETURN(cloned_handler);
12283 }
12284
storage_clone(const char * name,MEM_ROOT * mem_root)12285 handler *ha_mroonga::storage_clone(const char *name, MEM_ROOT *mem_root)
12286 {
12287 MRN_DBUG_ENTER_METHOD();
12288 handler *cloned_handler;
12289 cloned_handler = handler::clone(name, mem_root);
12290 DBUG_RETURN(cloned_handler);
12291 }
12292
clone(const char * name,MEM_ROOT * mem_root)12293 handler *ha_mroonga::clone(const char *name, MEM_ROOT *mem_root)
12294 {
12295 MRN_DBUG_ENTER_METHOD();
12296 handler *cloned_handler;
12297 if (share->wrapper_mode)
12298 {
12299 cloned_handler = wrapper_clone(name, mem_root);
12300 } else {
12301 cloned_handler = storage_clone(name, mem_root);
12302 }
12303 DBUG_RETURN(cloned_handler);
12304 }
12305
wrapper_table_cache_type()12306 uint8 ha_mroonga::wrapper_table_cache_type()
12307 {
12308 uint8 res;
12309 MRN_DBUG_ENTER_METHOD();
12310 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12311 MRN_SET_WRAP_TABLE_KEY(this, table);
12312 res = wrap_handler->table_cache_type();
12313 MRN_SET_BASE_SHARE_KEY(share, table->s);
12314 MRN_SET_BASE_TABLE_KEY(this, table);
12315 DBUG_RETURN(res);
12316 }
12317
storage_table_cache_type()12318 uint8 ha_mroonga::storage_table_cache_type()
12319 {
12320 MRN_DBUG_ENTER_METHOD();
12321 uint8 type = handler::table_cache_type();
12322 DBUG_RETURN(type);
12323 }
12324
table_cache_type()12325 uint8 ha_mroonga::table_cache_type()
12326 {
12327 MRN_DBUG_ENTER_METHOD();
12328 uint8 type;
12329 if (share->wrapper_mode)
12330 {
12331 type = wrapper_table_cache_type();
12332 } else {
12333 type = storage_table_cache_type();
12334 }
12335 DBUG_RETURN(type);
12336 }
12337
12338 #ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ
wrapper_multi_range_read_info_const(uint keyno,RANGE_SEQ_IF * seq,void * seq_init_param,uint n_ranges,uint * bufsz,uint * flags,Cost_estimate * cost)12339 ha_rows ha_mroonga::wrapper_multi_range_read_info_const(uint keyno,
12340 RANGE_SEQ_IF *seq,
12341 void *seq_init_param,
12342 uint n_ranges,
12343 uint *bufsz,
12344 uint *flags,
12345 Cost_estimate *cost)
12346 {
12347 MRN_DBUG_ENTER_METHOD();
12348 ha_rows rows;
12349 KEY *key_info = &(table->key_info[keyno]);
12350 if (mrn_is_geo_key(key_info)) {
12351 rows = handler::multi_range_read_info_const(keyno, seq, seq_init_param,
12352 n_ranges, bufsz, flags, cost);
12353 DBUG_RETURN(rows);
12354 }
12355 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12356 MRN_SET_WRAP_TABLE_KEY(this, table);
12357 if (fulltext_searching)
12358 set_pk_bitmap();
12359 rows = wrap_handler->multi_range_read_info_const(keyno, seq, seq_init_param,
12360 n_ranges, bufsz, flags,
12361 cost);
12362 MRN_SET_BASE_SHARE_KEY(share, table->s);
12363 MRN_SET_BASE_TABLE_KEY(this, table);
12364 DBUG_RETURN(rows);
12365 }
12366
storage_multi_range_read_info_const(uint keyno,RANGE_SEQ_IF * seq,void * seq_init_param,uint n_ranges,uint * bufsz,uint * flags,Cost_estimate * cost)12367 ha_rows ha_mroonga::storage_multi_range_read_info_const(uint keyno,
12368 RANGE_SEQ_IF *seq,
12369 void *seq_init_param,
12370 uint n_ranges,
12371 uint *bufsz,
12372 uint *flags,
12373 Cost_estimate *cost)
12374 {
12375 MRN_DBUG_ENTER_METHOD();
12376 ha_rows rows = handler::multi_range_read_info_const(keyno, seq,
12377 seq_init_param,
12378 n_ranges, bufsz, flags,
12379 cost);
12380 DBUG_RETURN(rows);
12381 }
12382
multi_range_read_info_const(uint keyno,RANGE_SEQ_IF * seq,void * seq_init_param,uint n_ranges,uint * bufsz,uint * flags,Cost_estimate * cost)12383 ha_rows ha_mroonga::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
12384 void *seq_init_param,
12385 uint n_ranges, uint *bufsz,
12386 uint *flags,
12387 Cost_estimate *cost)
12388 {
12389 MRN_DBUG_ENTER_METHOD();
12390 ha_rows rows;
12391 if (share->wrapper_mode)
12392 {
12393 rows = wrapper_multi_range_read_info_const(keyno, seq, seq_init_param,
12394 n_ranges, bufsz,
12395 flags, cost);
12396 } else {
12397 rows = storage_multi_range_read_info_const(keyno, seq, seq_init_param,
12398 n_ranges, bufsz,
12399 flags, cost);
12400 }
12401 DBUG_RETURN(rows);
12402 }
12403
wrapper_multi_range_read_info(uint keyno,uint n_ranges,uint keys,uint key_parts,uint * bufsz,uint * flags,Cost_estimate * cost)12404 ha_rows ha_mroonga::wrapper_multi_range_read_info(uint keyno, uint n_ranges,
12405 uint keys,
12406 #ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12407 uint key_parts,
12408 #endif
12409 uint *bufsz,
12410 uint *flags,
12411 Cost_estimate *cost)
12412 {
12413 MRN_DBUG_ENTER_METHOD();
12414 ha_rows rows;
12415 KEY *key_info = &(table->key_info[keyno]);
12416 if (mrn_is_geo_key(key_info)) {
12417 rows = handler::multi_range_read_info(keyno, n_ranges, keys,
12418 #ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12419 key_parts,
12420 #endif
12421 bufsz, flags, cost);
12422 DBUG_RETURN(rows);
12423 }
12424 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12425 MRN_SET_WRAP_TABLE_KEY(this, table);
12426 if (fulltext_searching)
12427 set_pk_bitmap();
12428 rows = wrap_handler->multi_range_read_info(keyno, n_ranges, keys,
12429 #ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12430 key_parts,
12431 #endif
12432 bufsz, flags, cost);
12433 MRN_SET_BASE_SHARE_KEY(share, table->s);
12434 MRN_SET_BASE_TABLE_KEY(this, table);
12435 DBUG_RETURN(rows);
12436 }
12437
storage_multi_range_read_info(uint keyno,uint n_ranges,uint keys,uint key_parts,uint * bufsz,uint * flags,Cost_estimate * cost)12438 ha_rows ha_mroonga::storage_multi_range_read_info(uint keyno, uint n_ranges,
12439 uint keys,
12440 #ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12441 uint key_parts,
12442 #endif
12443 uint *bufsz,
12444 uint *flags,
12445 Cost_estimate *cost)
12446 {
12447 MRN_DBUG_ENTER_METHOD();
12448 ha_rows rows = handler::multi_range_read_info(keyno, n_ranges, keys,
12449 #ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12450 key_parts,
12451 #endif
12452 bufsz, flags, cost);
12453 DBUG_RETURN(rows);
12454 }
12455
multi_range_read_info(uint keyno,uint n_ranges,uint keys,uint key_parts,uint * bufsz,uint * flags,Cost_estimate * cost)12456 ha_rows ha_mroonga::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
12457 #ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12458 uint key_parts,
12459 #endif
12460 uint *bufsz, uint *flags,
12461 Cost_estimate *cost)
12462 {
12463 MRN_DBUG_ENTER_METHOD();
12464 ha_rows rows;
12465 if (share->wrapper_mode)
12466 {
12467 rows = wrapper_multi_range_read_info(keyno, n_ranges, keys,
12468 #ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12469 key_parts,
12470 #endif
12471 bufsz, flags, cost);
12472 } else {
12473 rows = storage_multi_range_read_info(keyno, n_ranges, keys,
12474 #ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12475 key_parts,
12476 #endif
12477 bufsz, flags, cost);
12478 }
12479 DBUG_RETURN(rows);
12480 }
12481
wrapper_multi_range_read_init(RANGE_SEQ_IF * seq,void * seq_init_param,uint n_ranges,uint mode,HANDLER_BUFFER * buf)12482 int ha_mroonga::wrapper_multi_range_read_init(RANGE_SEQ_IF *seq,
12483 void *seq_init_param,
12484 uint n_ranges, uint mode,
12485 HANDLER_BUFFER *buf)
12486 {
12487 MRN_DBUG_ENTER_METHOD();
12488 int error = 0;
12489 KEY *key_info = &(table->key_info[active_index]);
12490 if (mrn_is_geo_key(key_info)) {
12491 error = handler::multi_range_read_init(seq, seq_init_param,
12492 n_ranges, mode, buf);
12493 DBUG_RETURN(error);
12494 }
12495 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12496 MRN_SET_WRAP_TABLE_KEY(this, table);
12497 if (fulltext_searching)
12498 set_pk_bitmap();
12499 error = wrap_handler->multi_range_read_init(seq, seq_init_param,
12500 n_ranges, mode, buf);
12501 MRN_SET_BASE_SHARE_KEY(share, table->s);
12502 MRN_SET_BASE_TABLE_KEY(this, table);
12503 DBUG_RETURN(error);
12504 }
12505
storage_multi_range_read_init(RANGE_SEQ_IF * seq,void * seq_init_param,uint n_ranges,uint mode,HANDLER_BUFFER * buf)12506 int ha_mroonga::storage_multi_range_read_init(RANGE_SEQ_IF *seq,
12507 void *seq_init_param,
12508 uint n_ranges, uint mode,
12509 HANDLER_BUFFER *buf)
12510 {
12511 MRN_DBUG_ENTER_METHOD();
12512 int error = handler::multi_range_read_init(seq, seq_init_param,
12513 n_ranges, mode, buf);
12514 DBUG_RETURN(error);
12515 }
12516
multi_range_read_init(RANGE_SEQ_IF * seq,void * seq_init_param,uint n_ranges,uint mode,HANDLER_BUFFER * buf)12517 int ha_mroonga::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
12518 uint n_ranges, uint mode,
12519 HANDLER_BUFFER *buf)
12520 {
12521 MRN_DBUG_ENTER_METHOD();
12522 int error = 0;
12523 if (share->wrapper_mode)
12524 {
12525 error = wrapper_multi_range_read_init(seq, seq_init_param,
12526 n_ranges, mode, buf);
12527 } else {
12528 error = storage_multi_range_read_init(seq, seq_init_param,
12529 n_ranges, mode, buf);
12530 }
12531 DBUG_RETURN(error);
12532 }
12533
wrapper_multi_range_read_next(range_id_t * range_info)12534 int ha_mroonga::wrapper_multi_range_read_next(range_id_t *range_info)
12535 {
12536 MRN_DBUG_ENTER_METHOD();
12537 int error = 0;
12538 KEY *key_info = &(table->key_info[active_index]);
12539 if (mrn_is_geo_key(key_info)) {
12540 error = handler::multi_range_read_next(range_info);
12541 DBUG_RETURN(error);
12542 }
12543 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12544 MRN_SET_WRAP_TABLE_KEY(this, table);
12545 if (fulltext_searching)
12546 set_pk_bitmap();
12547 error = wrap_handler->multi_range_read_next(range_info);
12548 MRN_SET_BASE_SHARE_KEY(share, table->s);
12549 MRN_SET_BASE_TABLE_KEY(this, table);
12550 DBUG_RETURN(error);
12551 }
12552
storage_multi_range_read_next(range_id_t * range_info)12553 int ha_mroonga::storage_multi_range_read_next(range_id_t *range_info)
12554 {
12555 MRN_DBUG_ENTER_METHOD();
12556 int error = handler::multi_range_read_next(range_info);
12557 DBUG_RETURN(error);
12558 }
12559
multi_range_read_next(range_id_t * range_info)12560 int ha_mroonga::multi_range_read_next(range_id_t *range_info)
12561 {
12562 MRN_DBUG_ENTER_METHOD();
12563 int error = 0;
12564 if (share->wrapper_mode)
12565 {
12566 error = wrapper_multi_range_read_next(range_info);
12567 } else {
12568 error = storage_multi_range_read_next(range_info);
12569 }
12570 DBUG_RETURN(error);
12571 }
12572 #else // MRN_HANDLER_HAVE_MULTI_RANGE_READ
wrapper_read_multi_range_first(KEY_MULTI_RANGE ** found_range_p,KEY_MULTI_RANGE * ranges,uint range_count,bool sorted,HANDLER_BUFFER * buffer)12573 int ha_mroonga::wrapper_read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
12574 KEY_MULTI_RANGE *ranges,
12575 uint range_count,
12576 bool sorted,
12577 HANDLER_BUFFER *buffer)
12578 {
12579 int error = 0;
12580 MRN_DBUG_ENTER_METHOD();
12581 KEY *key_info = &(table->key_info[active_index]);
12582 if (mrn_is_geo_key(key_info)) {
12583 error = handler::read_multi_range_first(found_range_p, ranges,
12584 range_count, sorted, buffer);
12585 DBUG_RETURN(error);
12586 }
12587 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12588 MRN_SET_WRAP_TABLE_KEY(this, table);
12589 if (fulltext_searching)
12590 set_pk_bitmap();
12591 error = wrap_handler->read_multi_range_first(found_range_p, ranges,
12592 range_count, sorted, buffer);
12593 MRN_SET_BASE_SHARE_KEY(share, table->s);
12594 MRN_SET_BASE_TABLE_KEY(this, table);
12595 DBUG_RETURN(error);
12596 }
12597
storage_read_multi_range_first(KEY_MULTI_RANGE ** found_range_p,KEY_MULTI_RANGE * ranges,uint range_count,bool sorted,HANDLER_BUFFER * buffer)12598 int ha_mroonga::storage_read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
12599 KEY_MULTI_RANGE *ranges,
12600 uint range_count,
12601 bool sorted,
12602 HANDLER_BUFFER *buffer)
12603 {
12604 MRN_DBUG_ENTER_METHOD();
12605 int error = handler::read_multi_range_first(found_range_p, ranges,
12606 range_count, sorted, buffer);
12607 DBUG_RETURN(error);
12608 }
12609
read_multi_range_first(KEY_MULTI_RANGE ** found_range_p,KEY_MULTI_RANGE * ranges,uint range_count,bool sorted,HANDLER_BUFFER * buffer)12610 int ha_mroonga::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
12611 KEY_MULTI_RANGE *ranges,
12612 uint range_count,
12613 bool sorted,
12614 HANDLER_BUFFER *buffer)
12615 {
12616 MRN_DBUG_ENTER_METHOD();
12617 int error = 0;
12618 if (share->wrapper_mode)
12619 {
12620 error = wrapper_read_multi_range_first(found_range_p, ranges,
12621 range_count, sorted, buffer);
12622 } else {
12623 error = storage_read_multi_range_first(found_range_p, ranges,
12624 range_count, sorted, buffer);
12625 }
12626 DBUG_RETURN(error);
12627 }
12628
wrapper_read_multi_range_next(KEY_MULTI_RANGE ** found_range_p)12629 int ha_mroonga::wrapper_read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
12630 {
12631 int error = 0;
12632 MRN_DBUG_ENTER_METHOD();
12633 KEY *key_info = &(table->key_info[active_index]);
12634 if (mrn_is_geo_key(key_info)) {
12635 error = handler::read_multi_range_next(found_range_p);
12636 DBUG_RETURN(error);
12637 }
12638 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12639 MRN_SET_WRAP_TABLE_KEY(this, table);
12640 if (fulltext_searching)
12641 set_pk_bitmap();
12642 error = wrap_handler->read_multi_range_next(found_range_p);
12643 MRN_SET_BASE_SHARE_KEY(share, table->s);
12644 MRN_SET_BASE_TABLE_KEY(this, table);
12645 DBUG_RETURN(error);
12646 }
12647
storage_read_multi_range_next(KEY_MULTI_RANGE ** found_range_p)12648 int ha_mroonga::storage_read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
12649 {
12650 MRN_DBUG_ENTER_METHOD();
12651 int error = handler::read_multi_range_next(found_range_p);
12652 DBUG_RETURN(error);
12653 }
12654
read_multi_range_next(KEY_MULTI_RANGE ** found_range_p)12655 int ha_mroonga::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
12656 {
12657 MRN_DBUG_ENTER_METHOD();
12658 int error = 0;
12659 if (share->wrapper_mode)
12660 {
12661 error = wrapper_read_multi_range_next(found_range_p);
12662 } else {
12663 error = storage_read_multi_range_next(found_range_p);
12664 }
12665 DBUG_RETURN(error);
12666 }
12667 #endif // MRN_HANDLER_HAVE_MULTI_RANGE_READ
12668
12669 #ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
wrapper_start_bulk_insert(ha_rows rows,uint flags)12670 void ha_mroonga::wrapper_start_bulk_insert(ha_rows rows, uint flags)
12671 #else
12672 void ha_mroonga::wrapper_start_bulk_insert(ha_rows rows)
12673 #endif
12674 {
12675 MRN_DBUG_ENTER_METHOD();
12676 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12677 MRN_SET_WRAP_TABLE_KEY(this, table);
12678 #ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
12679 wrap_handler->ha_start_bulk_insert(rows, flags);
12680 #else
12681 wrap_handler->ha_start_bulk_insert(rows);
12682 #endif
12683 MRN_SET_BASE_SHARE_KEY(share, table->s);
12684 MRN_SET_BASE_TABLE_KEY(this, table);
12685 DBUG_VOID_RETURN;
12686 }
12687
12688 #ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
storage_start_bulk_insert(ha_rows rows,uint flags)12689 void ha_mroonga::storage_start_bulk_insert(ha_rows rows, uint flags)
12690 #else
12691 void ha_mroonga::storage_start_bulk_insert(ha_rows rows)
12692 #endif
12693 {
12694 MRN_DBUG_ENTER_METHOD();
12695 DBUG_VOID_RETURN;
12696 }
12697
12698 #ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
start_bulk_insert(ha_rows rows,uint flags)12699 void ha_mroonga::start_bulk_insert(ha_rows rows, uint flags)
12700 #else
12701 void ha_mroonga::start_bulk_insert(ha_rows rows)
12702 #endif
12703 {
12704 MRN_DBUG_ENTER_METHOD();
12705 if (share->wrapper_mode) {
12706 #ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
12707 wrapper_start_bulk_insert(rows, flags);
12708 #else
12709 wrapper_start_bulk_insert(rows);
12710 #endif
12711 } else {
12712 #ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
12713 storage_start_bulk_insert(rows, flags);
12714 #else
12715 storage_start_bulk_insert(rows);
12716 #endif
12717 }
12718 DBUG_VOID_RETURN;
12719 }
12720
wrapper_end_bulk_insert()12721 int ha_mroonga::wrapper_end_bulk_insert()
12722 {
12723 int error = 0;
12724 MRN_DBUG_ENTER_METHOD();
12725 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12726 MRN_SET_WRAP_TABLE_KEY(this, table);
12727 error = wrap_handler->ha_end_bulk_insert();
12728 MRN_SET_BASE_SHARE_KEY(share, table->s);
12729 MRN_SET_BASE_TABLE_KEY(this, table);
12730 DBUG_RETURN(error);
12731 }
12732
storage_end_bulk_insert()12733 int ha_mroonga::storage_end_bulk_insert()
12734 {
12735 MRN_DBUG_ENTER_METHOD();
12736 DBUG_RETURN(0);
12737 }
12738
end_bulk_insert()12739 int ha_mroonga::end_bulk_insert()
12740 {
12741 MRN_DBUG_ENTER_METHOD();
12742 int error = 0;
12743 if (share->wrapper_mode)
12744 {
12745 error = wrapper_end_bulk_insert();
12746 } else {
12747 error = storage_end_bulk_insert();
12748 }
12749 DBUG_RETURN(error);
12750 }
12751
generic_delete_all_rows(grn_obj * target_grn_table,const char * function_name)12752 int ha_mroonga::generic_delete_all_rows(grn_obj *target_grn_table,
12753 const char *function_name)
12754 {
12755 MRN_DBUG_ENTER_METHOD();
12756
12757 int error = 0;
12758
12759 error = mrn_change_encoding(ctx, system_charset_info);
12760 if (error)
12761 DBUG_RETURN(error);
12762
12763 if (is_dry_write()) {
12764 DBUG_PRINT("info",
12765 ("mroonga: dry write: %s::%s", MRN_CLASS_NAME, function_name));
12766 DBUG_RETURN(error);
12767 }
12768
12769 grn_table_cursor *cursor;
12770 cursor = grn_table_cursor_open(ctx, target_grn_table,
12771 NULL, 0,
12772 NULL, 0,
12773 0, -1,
12774 0);
12775 if (cursor) {
12776 while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) {
12777 grn_table_cursor_delete(ctx, cursor);
12778 }
12779 grn_table_cursor_close(ctx, cursor);
12780 } else {
12781 error = ER_ERROR_ON_WRITE;
12782 my_message(error, ctx->errbuf, MYF(0));
12783 }
12784 DBUG_RETURN(error);
12785 }
12786
wrapper_delete_all_rows()12787 int ha_mroonga::wrapper_delete_all_rows()
12788 {
12789 int error = 0;
12790 MRN_DBUG_ENTER_METHOD();
12791 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12792 MRN_SET_WRAP_TABLE_KEY(this, table);
12793 error = wrap_handler->ha_delete_all_rows();
12794 MRN_SET_BASE_SHARE_KEY(share, table->s);
12795 MRN_SET_BASE_TABLE_KEY(this, table);
12796
12797 if (error) {
12798 DBUG_RETURN(error);
12799 }
12800
12801 if (!wrapper_have_target_index()) {
12802 DBUG_RETURN(error);
12803 }
12804
12805 uint i;
12806 uint n_keys = table->s->keys;
12807 for (i = 0; i < n_keys; i++) {
12808 KEY *key_info = &(table->key_info[i]);
12809
12810 if (!(wrapper_is_target_index(key_info))) {
12811 continue;
12812 }
12813
12814 if (!grn_index_tables[i]) {
12815 /* disable keys */
12816 continue;
12817 }
12818
12819 error = generic_delete_all_rows(grn_index_tables[i], __FUNCTION__);
12820 if (error) {
12821 break;
12822 }
12823 }
12824
12825 int grn_table_error;
12826 grn_table_error = generic_delete_all_rows(grn_table, __FUNCTION__);
12827 if (!error) {
12828 error = grn_table_error;
12829 }
12830
12831 DBUG_RETURN(error);
12832 }
12833
storage_delete_all_rows()12834 int ha_mroonga::storage_delete_all_rows()
12835 {
12836 MRN_DBUG_ENTER_METHOD();
12837 int error = generic_delete_all_rows(grn_table, __FUNCTION__);
12838 if (!error) {
12839 uint n_keys = table->s->keys;
12840 for (uint i = 0; i < n_keys; i++) {
12841 if (i == table->s->primary_key) {
12842 continue;
12843 }
12844
12845 KEY *key_info = &(table->key_info[i]);
12846 if (!(key_info->flags & HA_NOSAME)) {
12847 continue;
12848 }
12849
12850 grn_obj *index_table = grn_index_tables[i];
12851 if (!index_table) {
12852 continue;
12853 }
12854
12855 error = generic_delete_all_rows(index_table, __FUNCTION__);
12856 if (error) {
12857 break;
12858 }
12859 }
12860 }
12861 DBUG_RETURN(error);
12862 }
12863
delete_all_rows()12864 int ha_mroonga::delete_all_rows()
12865 {
12866 MRN_DBUG_ENTER_METHOD();
12867 int error = 0;
12868 if (share->wrapper_mode)
12869 {
12870 error = wrapper_delete_all_rows();
12871 } else {
12872 error = storage_delete_all_rows();
12873 }
12874 DBUG_RETURN(error);
12875 }
12876
wrapper_truncate()12877 int ha_mroonga::wrapper_truncate()
12878 {
12879 int error = 0;
12880 MRN_SHARE *tmp_share;
12881 MRN_DBUG_ENTER_METHOD();
12882
12883 if (!(tmp_share = mrn_get_share(table->s->table_name.str, table, &error)))
12884 DBUG_RETURN(error);
12885
12886 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12887 MRN_SET_WRAP_TABLE_KEY(this, table);
12888 error = parse_engine_table_options(ha_thd(), tmp_share->hton, table->s)
12889 ? MRN_GET_ERROR_NUMBER
12890 : wrap_handler->ha_truncate();
12891 MRN_SET_BASE_SHARE_KEY(share, table->s);
12892 MRN_SET_BASE_TABLE_KEY(this, table);
12893
12894 mrn_free_share(tmp_share);
12895
12896 if (!error && wrapper_have_target_index()) {
12897 error = wrapper_truncate_index();
12898 }
12899
12900 DBUG_RETURN(error);
12901 }
12902
wrapper_truncate_index()12903 int ha_mroonga::wrapper_truncate_index()
12904 {
12905 MRN_DBUG_ENTER_METHOD();
12906
12907 int error = 0;
12908
12909 error = mrn_change_encoding(ctx, system_charset_info);
12910 if (error)
12911 DBUG_RETURN(error);
12912
12913 if (is_dry_write()) {
12914 DBUG_PRINT("info",
12915 ("mroonga: dry write: %s::%s", MRN_CLASS_NAME, __FUNCTION__));
12916 DBUG_RETURN(error);
12917 }
12918
12919 grn_rc rc;
12920 uint i;
12921 uint n_keys = table->s->keys;
12922 for (i = 0; i < n_keys; i++) {
12923 KEY *key_info = &(table->key_info[i]);
12924
12925 if (!(wrapper_is_target_index(key_info))) {
12926 continue;
12927 }
12928
12929 if (!grn_index_tables[i]) {
12930 /* disable keys */
12931 continue;
12932 }
12933
12934 rc = grn_table_truncate(ctx, grn_index_tables[i]);
12935 if (rc) {
12936 error = ER_ERROR_ON_WRITE;
12937 my_message(error, ctx->errbuf, MYF(0));
12938 goto err;
12939 }
12940 }
12941 err:
12942 rc = grn_table_truncate(ctx, grn_table);
12943 if (rc) {
12944 error = ER_ERROR_ON_WRITE;
12945 my_message(error, ctx->errbuf, MYF(0));
12946 }
12947
12948 DBUG_RETURN(error);
12949 }
12950
storage_truncate()12951 int ha_mroonga::storage_truncate()
12952 {
12953 MRN_DBUG_ENTER_METHOD();
12954 int error = 0;
12955
12956 if (is_dry_write()) {
12957 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
12958 DBUG_RETURN(error);
12959 }
12960
12961 grn_rc rc;
12962 rc = grn_table_truncate(ctx, grn_table);
12963 if (rc) {
12964 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
12965 DBUG_RETURN(ER_ERROR_ON_WRITE);
12966 }
12967 error = storage_truncate_index();
12968
12969 if (!error && thd_sql_command(ha_thd()) == SQLCOM_TRUNCATE) {
12970 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
12971 mrn::Lock lock(&long_term_share->auto_inc_mutex);
12972 long_term_share->auto_inc_value = 0;
12973 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
12974 long_term_share->auto_inc_value));
12975 long_term_share->auto_inc_inited = false;
12976 }
12977
12978 DBUG_RETURN(error);
12979 }
12980
storage_truncate_index()12981 int ha_mroonga::storage_truncate_index()
12982 {
12983 MRN_DBUG_ENTER_METHOD();
12984 int error = 0;
12985
12986 error = mrn_change_encoding(ctx, system_charset_info);
12987 if (error)
12988 DBUG_RETURN(error);
12989
12990 grn_rc rc;
12991 uint i;
12992 uint n_keys = table->s->keys;
12993 for (i = 0; i < n_keys; i++) {
12994 if (i == table->s->primary_key) {
12995 continue;
12996 }
12997
12998 KEY *key_info = &(table->key_info[i]);
12999
13000 if (
13001 !(key_info->flags & HA_NOSAME) &&
13002 (KEY_N_KEY_PARTS(key_info) == 1 || (key_info->flags & HA_FULLTEXT))
13003 ) {
13004 continue;
13005 }
13006
13007 if (!grn_index_tables[i]) {
13008 /* disable keys */
13009 continue;
13010 }
13011
13012 rc = grn_table_truncate(ctx, grn_index_tables[i]);
13013 if (rc) {
13014 error = ER_ERROR_ON_WRITE;
13015 my_message(error, ctx->errbuf, MYF(0));
13016 goto err;
13017 }
13018 }
13019 err:
13020 DBUG_RETURN(error);
13021 }
13022
truncate()13023 int ha_mroonga::truncate()
13024 {
13025 MRN_DBUG_ENTER_METHOD();
13026 int error = 0;
13027 if (share->wrapper_mode)
13028 {
13029 error = wrapper_truncate();
13030 } else {
13031 error = storage_truncate();
13032 }
13033 if (!error) {
13034 operations_->clear(table->s->table_name.str,
13035 table->s->table_name.length);
13036 }
13037 DBUG_RETURN(error);
13038 }
13039
wrapper_scan_time()13040 double ha_mroonga::wrapper_scan_time()
13041 {
13042 double res;
13043 MRN_DBUG_ENTER_METHOD();
13044 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13045 MRN_SET_WRAP_TABLE_KEY(this, table);
13046 res = wrap_handler->scan_time();
13047 MRN_SET_BASE_SHARE_KEY(share, table->s);
13048 MRN_SET_BASE_TABLE_KEY(this, table);
13049 DBUG_RETURN(res);
13050 }
13051
storage_scan_time()13052 double ha_mroonga::storage_scan_time()
13053 {
13054 MRN_DBUG_ENTER_METHOD();
13055 double time = handler::scan_time();
13056 DBUG_RETURN(time);
13057 }
13058
scan_time()13059 double ha_mroonga::scan_time()
13060 {
13061 MRN_DBUG_ENTER_METHOD();
13062 double time;
13063 if (share->wrapper_mode)
13064 {
13065 time = wrapper_scan_time();
13066 } else {
13067 time = storage_scan_time();
13068 }
13069 DBUG_RETURN(time);
13070 }
13071
wrapper_read_time(uint index,uint ranges,ha_rows rows)13072 double ha_mroonga::wrapper_read_time(uint index, uint ranges, ha_rows rows)
13073 {
13074 double res;
13075 MRN_DBUG_ENTER_METHOD();
13076 if (index < MAX_KEY) {
13077 KEY *key_info = &(table->key_info[index]);
13078 if (mrn_is_geo_key(key_info)) {
13079 res = handler::read_time(index, ranges, rows);
13080 DBUG_RETURN(res);
13081 }
13082 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13083 MRN_SET_WRAP_TABLE_KEY(this, table);
13084 res = wrap_handler->read_time(share->wrap_key_nr[index], ranges, rows);
13085 MRN_SET_BASE_SHARE_KEY(share, table->s);
13086 MRN_SET_BASE_TABLE_KEY(this, table);
13087 } else {
13088 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13089 MRN_SET_WRAP_TABLE_KEY(this, table);
13090 res = wrap_handler->read_time(index, ranges, rows);
13091 MRN_SET_BASE_SHARE_KEY(share, table->s);
13092 MRN_SET_BASE_TABLE_KEY(this, table);
13093 }
13094 DBUG_RETURN(res);
13095 }
13096
storage_read_time(uint index,uint ranges,ha_rows rows)13097 double ha_mroonga::storage_read_time(uint index, uint ranges, ha_rows rows)
13098 {
13099 MRN_DBUG_ENTER_METHOD();
13100 double time = handler::read_time(index, ranges, rows);
13101 DBUG_RETURN(time);
13102 }
13103
read_time(uint index,uint ranges,ha_rows rows)13104 double ha_mroonga::read_time(uint index, uint ranges, ha_rows rows)
13105 {
13106 MRN_DBUG_ENTER_METHOD();
13107 double time;
13108 if (share->wrapper_mode)
13109 {
13110 time = wrapper_read_time(index, ranges, rows);
13111 } else {
13112 time = storage_read_time(index, ranges, rows);
13113 }
13114 DBUG_RETURN(time);
13115 }
13116
13117 #ifdef MRN_HANDLER_HAVE_KEYS_TO_USE_FOR_SCANNING
wrapper_keys_to_use_for_scanning()13118 const key_map *ha_mroonga::wrapper_keys_to_use_for_scanning()
13119 {
13120 const key_map *res;
13121 MRN_DBUG_ENTER_METHOD();
13122 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13123 MRN_SET_WRAP_TABLE_KEY(this, table);
13124 res = wrap_handler->keys_to_use_for_scanning();
13125 MRN_SET_BASE_SHARE_KEY(share, table->s);
13126 MRN_SET_BASE_TABLE_KEY(this, table);
13127 DBUG_RETURN(res);
13128 }
13129
storage_keys_to_use_for_scanning()13130 const key_map *ha_mroonga::storage_keys_to_use_for_scanning()
13131 {
13132 MRN_DBUG_ENTER_METHOD();
13133 DBUG_RETURN(&key_map_full);
13134 }
13135
keys_to_use_for_scanning()13136 const key_map *ha_mroonga::keys_to_use_for_scanning()
13137 {
13138 MRN_DBUG_ENTER_METHOD();
13139 const key_map *key_map;
13140 if (share->wrapper_mode)
13141 {
13142 key_map = wrapper_keys_to_use_for_scanning();
13143 } else {
13144 key_map = storage_keys_to_use_for_scanning();
13145 }
13146 DBUG_RETURN(key_map);
13147 }
13148 #endif
13149
wrapper_estimate_rows_upper_bound()13150 ha_rows ha_mroonga::wrapper_estimate_rows_upper_bound()
13151 {
13152 ha_rows res;
13153 MRN_DBUG_ENTER_METHOD();
13154 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13155 MRN_SET_WRAP_TABLE_KEY(this, table);
13156 res = wrap_handler->estimate_rows_upper_bound();
13157 MRN_SET_BASE_SHARE_KEY(share, table->s);
13158 MRN_SET_BASE_TABLE_KEY(this, table);
13159 DBUG_RETURN(res);
13160 }
13161
storage_estimate_rows_upper_bound()13162 ha_rows ha_mroonga::storage_estimate_rows_upper_bound()
13163 {
13164 MRN_DBUG_ENTER_METHOD();
13165 ha_rows rows = handler::estimate_rows_upper_bound();
13166 DBUG_RETURN(rows);
13167 }
13168
estimate_rows_upper_bound()13169 ha_rows ha_mroonga::estimate_rows_upper_bound()
13170 {
13171 MRN_DBUG_ENTER_METHOD();
13172 ha_rows rows;
13173 if (share->wrapper_mode)
13174 {
13175 rows = wrapper_estimate_rows_upper_bound();
13176 } else {
13177 rows = storage_estimate_rows_upper_bound();
13178 }
13179 DBUG_RETURN(rows);
13180 }
13181
wrapper_update_create_info(HA_CREATE_INFO * create_info)13182 void ha_mroonga::wrapper_update_create_info(HA_CREATE_INFO* create_info)
13183 {
13184 MRN_DBUG_ENTER_METHOD();
13185 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13186 MRN_SET_WRAP_TABLE_KEY(this, table);
13187 wrap_handler->update_create_info(create_info);
13188 MRN_SET_BASE_SHARE_KEY(share, table->s);
13189 MRN_SET_BASE_TABLE_KEY(this, table);
13190 DBUG_VOID_RETURN;
13191 }
13192
storage_update_create_info(HA_CREATE_INFO * create_info)13193 void ha_mroonga::storage_update_create_info(HA_CREATE_INFO* create_info)
13194 {
13195 MRN_DBUG_ENTER_METHOD();
13196 handler::update_create_info(create_info);
13197 if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) {
13198 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
13199 if (!long_term_share->auto_inc_inited) {
13200 storage_info(HA_STATUS_AUTO);
13201 }
13202 create_info->auto_increment_value = long_term_share->auto_inc_value;
13203 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
13204 long_term_share->auto_inc_value));
13205 }
13206 DBUG_VOID_RETURN;
13207 }
13208
update_create_info(HA_CREATE_INFO * create_info)13209 void ha_mroonga::update_create_info(HA_CREATE_INFO* create_info)
13210 {
13211 MRN_DBUG_ENTER_METHOD();
13212 if (!create_info->connect_string.str)
13213 {
13214 create_info->connect_string.str = table->s->connect_string.str;
13215 create_info->connect_string.length = table->s->connect_string.length;
13216 }
13217 if (share->wrapper_mode)
13218 wrapper_update_create_info(create_info);
13219 else
13220 storage_update_create_info(create_info);
13221 st_mrn_slot_data *slot_data = mrn_get_slot_data(ha_thd(), true);
13222 if (slot_data) {
13223 slot_data->alter_create_info = create_info;
13224 if (slot_data->alter_connect_string) {
13225 my_free(slot_data->alter_connect_string);
13226 slot_data->alter_connect_string = NULL;
13227 }
13228 if (create_info->connect_string.str) {
13229 slot_data->alter_connect_string =
13230 mrn_my_strndup(create_info->connect_string.str,
13231 create_info->connect_string.length,
13232 MYF(MY_WME));
13233 }
13234 if (slot_data->alter_comment) {
13235 my_free(slot_data->alter_comment);
13236 slot_data->alter_comment = NULL;
13237 }
13238 if (create_info->comment.str) {
13239 slot_data->alter_comment =
13240 mrn_my_strndup(create_info->comment.str,
13241 create_info->comment.length,
13242 MYF(MY_WME));
13243 }
13244 if (share && share->disable_keys) {
13245 slot_data->disable_keys_create_info = create_info;
13246 }
13247 }
13248 DBUG_VOID_RETURN;
13249 }
13250
wrapper_rename_table(const char * from,const char * to,MRN_SHARE * tmp_share,const char * from_table_name,const char * to_table_name)13251 int ha_mroonga::wrapper_rename_table(const char *from, const char *to,
13252 MRN_SHARE *tmp_share,
13253 const char *from_table_name,
13254 const char *to_table_name)
13255 {
13256 int error = 0;
13257 handler *hnd;
13258 MRN_DBUG_ENTER_METHOD();
13259
13260 hnd = get_new_handler(tmp_share->table_share,
13261 current_thd->mem_root,
13262 tmp_share->hton);
13263 if (!hnd)
13264 {
13265 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
13266 }
13267
13268 if ((error = hnd->ha_rename_table(from, to)))
13269 {
13270 delete hnd;
13271 DBUG_RETURN(error);
13272 }
13273
13274 error = wrapper_rename_index(from, to, tmp_share,
13275 from_table_name, to_table_name);
13276
13277 delete hnd;
13278 DBUG_RETURN(error);
13279 }
13280
wrapper_rename_index(const char * from,const char * to,MRN_SHARE * tmp_share,const char * from_table_name,const char * to_table_name)13281 int ha_mroonga::wrapper_rename_index(const char *from, const char *to,
13282 MRN_SHARE *tmp_share,
13283 const char *from_table_name,
13284 const char *to_table_name)
13285 {
13286 int error;
13287 grn_rc rc;
13288 MRN_DBUG_ENTER_METHOD();
13289 error = mrn_change_encoding(ctx, system_charset_info);
13290 if (error)
13291 DBUG_RETURN(error);
13292
13293 error = ensure_database_open(from);
13294 if (error)
13295 DBUG_RETURN(error);
13296
13297 TABLE_SHARE *tmp_table_share = tmp_share->table_share;
13298
13299 uint i;
13300 for (i = 0; i < tmp_table_share->keys; i++) {
13301 const char *mysql_index_name = tmp_table_share->key_info[i].name.str;
13302 mrn::IndexTableName from_index_table_name(from_table_name, mysql_index_name);
13303 mrn::IndexTableName to_index_table_name(to_table_name, mysql_index_name);
13304 grn_obj *index_table;
13305 index_table = grn_ctx_get(ctx,
13306 from_index_table_name.c_str(),
13307 from_index_table_name.length());
13308 if (!index_table) {
13309 index_table = grn_ctx_get(ctx,
13310 from_index_table_name.old_c_str(),
13311 from_index_table_name.old_length());
13312 }
13313 if (index_table) {
13314 rc = grn_table_rename(ctx, index_table,
13315 to_index_table_name.c_str(),
13316 to_index_table_name.length());
13317 if (rc != GRN_SUCCESS) {
13318 error = ER_CANT_OPEN_FILE;
13319 my_message(error, ctx->errbuf, MYF(0));
13320 DBUG_RETURN(error);
13321 }
13322 }
13323 }
13324
13325 grn_obj *table = grn_ctx_get(ctx, from_table_name, strlen(from_table_name));
13326 if (ctx->rc != GRN_SUCCESS) {
13327 error = ER_CANT_OPEN_FILE;
13328 my_message(error, ctx->errbuf, MYF(0));
13329 DBUG_RETURN(error);
13330 }
13331 rc = grn_table_rename(ctx, table, to_table_name,
13332 strlen(to_table_name));
13333 if (rc != GRN_SUCCESS) {
13334 error = ER_CANT_OPEN_FILE;
13335 my_message(error, ctx->errbuf, MYF(0));
13336 DBUG_RETURN(error);
13337 }
13338 DBUG_RETURN(0);
13339 }
13340
storage_rename_table(const char * from,const char * to,MRN_SHARE * tmp_share,const char * from_table_name,const char * to_table_name)13341 int ha_mroonga::storage_rename_table(const char *from, const char *to,
13342 MRN_SHARE *tmp_share,
13343 const char *from_table_name,
13344 const char *to_table_name)
13345 {
13346 int error;
13347 grn_rc rc;
13348 TABLE_SHARE *tmp_table_share = tmp_share->table_share;
13349 MRN_LONG_TERM_SHARE *from_long_term_share = tmp_share->long_term_share,
13350 *to_long_term_share;
13351 MRN_DBUG_ENTER_METHOD();
13352 error = mrn_change_encoding(ctx, system_charset_info);
13353 if (error)
13354 DBUG_RETURN(error);
13355
13356 error = ensure_database_open(from);
13357 if (error)
13358 DBUG_RETURN(error);
13359
13360 if (!(to_long_term_share = mrn_get_long_term_share(to, strlen(to), &error)))
13361 DBUG_RETURN(error);
13362 to_long_term_share->auto_inc_value = from_long_term_share->auto_inc_value;
13363 DBUG_PRINT("info", ("mroonga: to_auto_inc_value=%llu",
13364 to_long_term_share->auto_inc_value));
13365 to_long_term_share->auto_inc_inited = from_long_term_share->auto_inc_inited;
13366
13367 uint i;
13368 for (i = 0; i < tmp_table_share->keys; i++) {
13369 const char *mysql_index_name = tmp_table_share->key_info[i].name.str;
13370 mrn::IndexTableName from_index_table_name(from_table_name,
13371 mysql_index_name);
13372 mrn::IndexTableName to_index_table_name(to_table_name,
13373 mysql_index_name);
13374 grn_obj *index_table;
13375 index_table = grn_ctx_get(ctx,
13376 from_index_table_name.c_str(),
13377 from_index_table_name.length());
13378 if (!index_table) {
13379 index_table = grn_ctx_get(ctx,
13380 from_index_table_name.old_c_str(),
13381 from_index_table_name.old_length());
13382 }
13383 if (index_table) {
13384 rc = grn_table_rename(ctx, index_table,
13385 to_index_table_name.c_str(),
13386 to_index_table_name.length());
13387 if (rc != GRN_SUCCESS) {
13388 error = ER_CANT_OPEN_FILE;
13389 my_message(error, ctx->errbuf, MYF(0));
13390 goto error_end;
13391 }
13392 }
13393 }
13394 #ifdef MRN_SUPPORT_FOREIGN_KEYS
13395 error = storage_rename_foreign_key(tmp_share, from_table_name, to_table_name);
13396 if (error) {
13397 goto error_end;
13398 }
13399 #endif
13400 {
13401 grn_obj *table_obj = grn_ctx_get(ctx, from_table_name, strlen(from_table_name));
13402 if (ctx->rc != GRN_SUCCESS) {
13403 error = ER_CANT_OPEN_FILE;
13404 my_message(error, ctx->errbuf, MYF(0));
13405 goto error_end;
13406 }
13407 rc = grn_table_rename(ctx, table_obj, to_table_name,
13408 strlen(to_table_name));
13409 if (rc != GRN_SUCCESS) {
13410 error = ER_CANT_OPEN_FILE;
13411 my_message(error, ctx->errbuf, MYF(0));
13412 goto error_end;
13413 }
13414 }
13415 DBUG_RETURN(0);
13416
13417 error_end:
13418 mrn_free_long_term_share(to_long_term_share);
13419 DBUG_RETURN(error);
13420 }
13421
13422 #ifdef MRN_SUPPORT_FOREIGN_KEYS
storage_rename_foreign_key(MRN_SHARE * tmp_share,const char * from_table_name,const char * to_table_name)13423 int ha_mroonga::storage_rename_foreign_key(MRN_SHARE *tmp_share,
13424 const char *from_table_name,
13425 const char *to_table_name)
13426 {
13427 int error;
13428 uint i;
13429 grn_obj *column, *ref_column;
13430 grn_rc rc;
13431 TABLE_SHARE *tmp_table_share = tmp_share->table_share;
13432 uint n_columns = tmp_table_share->fields;
13433 MRN_DBUG_ENTER_METHOD();
13434 for (i = 0; i < n_columns; ++i) {
13435 Field *field = tmp_table_share->field[i];
13436
13437 if (!is_foreign_key_field(from_table_name, field->field_name.str)) {
13438 continue;
13439 }
13440
13441 grn_obj *grn_from_table = grn_ctx_get(ctx, from_table_name, -1);
13442 mrn::ColumnName column_name(field->field_name);
13443 column = grn_obj_column(ctx,
13444 grn_from_table,
13445 column_name.c_str(),
13446 column_name.length());
13447 if (!column) {
13448 continue;
13449 }
13450 grn_id ref_table_id = grn_obj_get_range(ctx, column);
13451 grn_obj *ref_table = grn_ctx_at(ctx, ref_table_id);
13452 mrn::IndexColumnName from_index_column_name(from_table_name,
13453 column_name.c_str());
13454 ref_column = grn_obj_column(ctx, ref_table,
13455 from_index_column_name.c_str(),
13456 from_index_column_name.length());
13457 if (!ref_column) {
13458 continue;
13459 }
13460 mrn::IndexColumnName to_index_column_name(to_table_name,
13461 column_name.c_str());
13462 rc = grn_column_rename(ctx, ref_column,
13463 to_index_column_name.c_str(),
13464 to_index_column_name.length());
13465 if (rc != GRN_SUCCESS) {
13466 error = ER_CANT_OPEN_FILE;
13467 my_message(error, ctx->errbuf, MYF(0));
13468 DBUG_RETURN(error);
13469 }
13470 }
13471 DBUG_RETURN(0);
13472 }
13473 #endif
13474
rename_table(const char * from,const char * to)13475 int ha_mroonga::rename_table(const char *from, const char *to)
13476 {
13477 int error = 0;
13478 TABLE_LIST table_list;
13479 TABLE_SHARE *tmp_table_share;
13480 TABLE tmp_table;
13481 MRN_SHARE *tmp_share;
13482 MRN_DBUG_ENTER_METHOD();
13483 mrn::PathMapper to_mapper(to);
13484 mrn::PathMapper from_mapper(from);
13485 if (strcmp(from_mapper.db_name(), to_mapper.db_name()))
13486 DBUG_RETURN(HA_ERR_WRONG_COMMAND);
13487
13488 LEX_CSTRING db_name= { from_mapper.db_name(), strlen(from_mapper.db_name()) };
13489 LEX_CSTRING table_name= { from_mapper.mysql_table_name(),
13490 strlen(from_mapper.mysql_table_name()) };
13491 table_list.init_one_table(&db_name, &table_name, 0,TL_WRITE);
13492 mrn_open_mutex_lock(NULL);
13493 tmp_table_share = mrn_create_tmp_table_share(&table_list, from, &error);
13494 mrn_open_mutex_unlock(NULL);
13495 if (!tmp_table_share) {
13496 DBUG_RETURN(error);
13497 }
13498 tmp_table.s = tmp_table_share;
13499 #ifdef WITH_PARTITION_STORAGE_ENGINE
13500 tmp_table.part_info = NULL;
13501 #endif
13502 if (!(tmp_share = mrn_get_share(from, &tmp_table, &error)))
13503 {
13504 mrn_open_mutex_lock(NULL);
13505 mrn_free_tmp_table_share(tmp_table_share);
13506 mrn_open_mutex_unlock(NULL);
13507 DBUG_RETURN(error);
13508 }
13509
13510 if (tmp_share->wrapper_mode)
13511 {
13512 error = wrapper_rename_table(from, to, tmp_share,
13513 from_mapper.table_name(),
13514 to_mapper.table_name());
13515 } else {
13516 error = storage_rename_table(from, to, tmp_share,
13517 from_mapper.table_name(),
13518 to_mapper.table_name());
13519 }
13520
13521 if (!error && to_mapper.table_name()[0] == '#') {
13522 error = add_wrap_hton(to, tmp_share->hton);
13523 } else if (error && from_mapper.table_name()[0] == '#') {
13524 add_wrap_hton(from, tmp_share->hton);
13525 }
13526 if (!error) {
13527 mrn_free_long_term_share(tmp_share->long_term_share);
13528 tmp_share->long_term_share = NULL;
13529 }
13530 mrn_free_share(tmp_share);
13531 mrn_open_mutex_lock(NULL);
13532 mrn_free_tmp_table_share(tmp_table_share);
13533 mrn_open_mutex_unlock(NULL);
13534
13535 DBUG_RETURN(error);
13536 }
13537
wrapper_is_crashed() const13538 bool ha_mroonga::wrapper_is_crashed() const
13539 {
13540 bool res;
13541 MRN_DBUG_ENTER_METHOD();
13542 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13543 MRN_SET_WRAP_TABLE_KEY(this, table);
13544 res = wrap_handler->is_crashed();
13545 MRN_SET_BASE_SHARE_KEY(share, table->s);
13546 MRN_SET_BASE_TABLE_KEY(this, table);
13547 DBUG_RETURN(res);
13548 }
13549
storage_is_crashed() const13550 bool ha_mroonga::storage_is_crashed() const
13551 {
13552 MRN_DBUG_ENTER_METHOD();
13553 mrn::DatabaseRepairer repairer(ctx, ha_thd());
13554 bool crashed = repairer.is_crashed();
13555 DBUG_RETURN(crashed);
13556 }
13557
is_crashed() const13558 bool ha_mroonga::is_crashed() const
13559 {
13560 MRN_DBUG_ENTER_METHOD();
13561 bool crashed;
13562 if (share->wrapper_mode)
13563 {
13564 crashed = wrapper_is_crashed();
13565 } else {
13566 crashed = storage_is_crashed();
13567 }
13568 DBUG_RETURN(crashed);
13569 }
13570
wrapper_auto_repair(int error) const13571 bool ha_mroonga::wrapper_auto_repair(int error) const
13572 {
13573 bool repaired;
13574 MRN_DBUG_ENTER_METHOD();
13575 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13576 MRN_SET_WRAP_TABLE_KEY(this, table);
13577 #ifdef MRN_HANDLER_AUTO_REPAIR_HAVE_ERROR
13578 repaired = wrap_handler->auto_repair(error);
13579 #else
13580 repaired = wrap_handler->auto_repair();
13581 #endif
13582 MRN_SET_BASE_SHARE_KEY(share, table->s);
13583 MRN_SET_BASE_TABLE_KEY(this, table);
13584 DBUG_RETURN(repaired);
13585 }
13586
storage_auto_repair(int error) const13587 bool ha_mroonga::storage_auto_repair(int error) const
13588 {
13589 MRN_DBUG_ENTER_METHOD();
13590 bool repaired;
13591 #ifdef MRN_HANDLER_AUTO_REPAIR_HAVE_ERROR
13592 repaired = handler::auto_repair(error);
13593 #else
13594 repaired = handler::auto_repair();
13595 #endif
13596 DBUG_RETURN(repaired);
13597 }
13598
auto_repair(int error) const13599 bool ha_mroonga::auto_repair(int error) const
13600 {
13601 MRN_DBUG_ENTER_METHOD();
13602 bool repaired;
13603 // TODO: We should consider about creating share for error =
13604 // ER_CANT_OPEN_FILE. The following code just ignores the error.
13605 if (share && share->wrapper_mode)
13606 {
13607 repaired = wrapper_auto_repair(error);
13608 } else {
13609 repaired = storage_auto_repair(error);
13610 }
13611 DBUG_RETURN(repaired);
13612 }
13613
auto_repair() const13614 bool ha_mroonga::auto_repair() const
13615 {
13616 MRN_DBUG_ENTER_METHOD();
13617 bool repaired = auto_repair(HA_ERR_CRASHED_ON_USAGE);
13618 DBUG_RETURN(repaired);
13619 }
13620
generic_disable_index(int i,KEY * key_info)13621 int ha_mroonga::generic_disable_index(int i, KEY *key_info)
13622 {
13623 MRN_DBUG_ENTER_METHOD();
13624
13625 int error = 0;
13626 if (share->index_table[i]) {
13627 char index_column_name[GRN_TABLE_MAX_KEY_SIZE];
13628 snprintf(index_column_name, GRN_TABLE_MAX_KEY_SIZE - 1,
13629 "%s.%s", share->index_table[i], key_info[i].name.str);
13630 grn_obj *index_column = grn_ctx_get(ctx,
13631 index_column_name,
13632 strlen(index_column_name));
13633 if (index_column) {
13634 grn_obj_remove(ctx, index_column);
13635 }
13636 } else {
13637 mrn::PathMapper mapper(share->table_name);
13638 mrn::IndexTableName index_table_name(mapper.table_name(),
13639 key_info[i].name.str);
13640 grn_obj *index_table = grn_ctx_get(ctx,
13641 index_table_name.c_str(),
13642 index_table_name.length());
13643 if (!index_table) {
13644 index_table = grn_ctx_get(ctx,
13645 index_table_name.old_c_str(),
13646 index_table_name.old_length());
13647 }
13648 if (index_table) {
13649 grn_obj_remove(ctx, index_table);
13650 }
13651 }
13652 if (ctx->rc == GRN_SUCCESS) {
13653 grn_index_tables[i] = NULL;
13654 grn_index_columns[i] = NULL;
13655 } else {
13656 // TODO: Implement ctx->rc to error converter and use it.
13657 error = ER_ERROR_ON_WRITE;
13658 my_message(error, ctx->errbuf, MYF(0));
13659 }
13660
13661 DBUG_RETURN(error);
13662 }
13663
wrapper_disable_indexes_mroonga(uint mode)13664 int ha_mroonga::wrapper_disable_indexes_mroonga(uint mode)
13665 {
13666 int error = 0;
13667 MRN_DBUG_ENTER_METHOD();
13668 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
13669 uint i;
13670 for (i = 0; i < table_share->keys; i++) {
13671 if (i == table->s->primary_key) {
13672 continue;
13673 }
13674 if (share->wrap_key_nr[i] < MAX_KEY) {
13675 continue;
13676 }
13677 if (!grn_index_tables[i]) {
13678 DBUG_PRINT("info", ("mroonga: keys are disabled already %u", i));
13679 DBUG_RETURN(0);
13680 }
13681 }
13682 KEY *key_info = table_share->key_info;
13683 for (i = 0; i < table_share->keys; i++) {
13684 if (!(key_info[i].flags & HA_FULLTEXT) &&
13685 !mrn_is_geo_key(&key_info[i])) {
13686 continue;
13687 }
13688
13689 int sub_error = generic_disable_index(i, key_info);
13690 if (error != 0 && sub_error != 0) {
13691 error = sub_error;
13692 }
13693 }
13694 } else {
13695 error = HA_ERR_WRONG_COMMAND;
13696 }
13697 DBUG_RETURN(error);
13698 }
13699
wrapper_disable_indexes(uint mode)13700 int ha_mroonga::wrapper_disable_indexes(uint mode)
13701 {
13702 int error = 0;
13703 MRN_DBUG_ENTER_METHOD();
13704 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13705 MRN_SET_WRAP_TABLE_KEY(this, table);
13706 error = wrap_handler->ha_disable_indexes(mode);
13707 MRN_SET_BASE_SHARE_KEY(share, table->s);
13708 MRN_SET_BASE_TABLE_KEY(this, table);
13709 if (error == HA_ERR_WRONG_COMMAND) {
13710 error = 0;
13711 }
13712 if (!error) {
13713 error = wrapper_disable_indexes_mroonga(mode);
13714 }
13715 DBUG_RETURN(error);
13716 }
13717
storage_disable_indexes(uint mode)13718 int ha_mroonga::storage_disable_indexes(uint mode)
13719 {
13720 int error = 0;
13721 MRN_DBUG_ENTER_METHOD();
13722 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
13723 uint i;
13724 for (i = 0; i < table_share->keys; i++) {
13725 if (i == table->s->primary_key) {
13726 continue;
13727 }
13728 if (!grn_index_tables[i]) {
13729 DBUG_PRINT("info", ("mroonga: keys are disabled already %u", i));
13730 DBUG_RETURN(0);
13731 }
13732 }
13733 KEY *key_info = table_share->key_info;
13734 for (i = 0; i < table_share->keys; i++) {
13735 if (i == table->s->primary_key) {
13736 continue;
13737 }
13738 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE &&
13739 (key_info[i].flags & HA_NOSAME)) {
13740 continue;
13741 }
13742
13743 int sub_error = generic_disable_index(i, key_info);
13744 if (error != 0 && sub_error != 0) {
13745 error = sub_error;
13746 }
13747 }
13748 } else {
13749 DBUG_RETURN(HA_ERR_WRONG_COMMAND);
13750 }
13751 DBUG_RETURN(error);
13752 }
13753
disable_indexes(uint mode)13754 int ha_mroonga::disable_indexes(uint mode)
13755 {
13756 int error = 0;
13757 MRN_DBUG_ENTER_METHOD();
13758 if (share->wrapper_mode)
13759 {
13760 error = wrapper_disable_indexes(mode);
13761 } else {
13762 error = storage_disable_indexes(mode);
13763 }
13764 DBUG_RETURN(error);
13765 }
13766
wrapper_enable_indexes_mroonga(uint mode)13767 int ha_mroonga::wrapper_enable_indexes_mroonga(uint mode)
13768 {
13769 int error = 0;
13770 MRN_DBUG_ENTER_METHOD();
13771 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
13772 uint i, j;
13773 for (i = 0; i < table_share->keys; i++) {
13774 if (i == table->s->primary_key) {
13775 continue;
13776 }
13777 if (share->wrap_key_nr[i] < MAX_KEY) {
13778 continue;
13779 }
13780 if (!grn_index_columns[i]) {
13781 break;
13782 }
13783 }
13784 if (i == table_share->keys) {
13785 DBUG_PRINT("info", ("mroonga: keys are enabled already"));
13786 DBUG_RETURN(0);
13787 }
13788 KEY *p_key_info = &table->key_info[table_share->primary_key];
13789 KEY *key_info = table_share->key_info;
13790 uint n_keys = table_share->keys;
13791 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys);
13792 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, n_keys);
13793 bitmap_clear_all(table->read_set);
13794 mrn_set_bitmap_by_key(table->read_set, p_key_info);
13795 mrn::PathMapper mapper(share->table_name);
13796 for (i = 0, j = 0; i < n_keys; i++) {
13797 if (!(key_info[i].flags & HA_FULLTEXT) &&
13798 !mrn_is_geo_key(&key_info[i])) {
13799 j++;
13800 continue;
13801 }
13802
13803 if ((error = mrn_add_index_param(share, &key_info[i], i)))
13804 {
13805 break;
13806 }
13807 index_tables[i] = NULL;
13808 index_columns[i] = NULL;
13809 if (!grn_index_columns[i]) {
13810 if (
13811 (key_info[i].flags & HA_FULLTEXT) &&
13812 (error = wrapper_create_index_fulltext(mapper.table_name(),
13813 i, &key_info[i],
13814 index_tables, index_columns,
13815 share))
13816 ) {
13817 break;
13818 } else if (
13819 mrn_is_geo_key(&key_info[i]) &&
13820 (error = wrapper_create_index_geo(mapper.table_name(),
13821 i, &key_info[i],
13822 index_tables, index_columns,
13823 share))
13824 ) {
13825 break;
13826 }
13827 grn_index_columns[i] = index_columns[i];
13828 }
13829 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
13830 }
13831 if (!error && i > j)
13832 {
13833 error = wrapper_fill_indexes(ha_thd(), table->key_info, index_columns,
13834 n_keys);
13835 }
13836 bitmap_set_all(table->read_set);
13837 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
13838 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
13839 } else {
13840 error = HA_ERR_WRONG_COMMAND;
13841 }
13842 DBUG_RETURN(error);
13843 }
13844
wrapper_enable_indexes(uint mode)13845 int ha_mroonga::wrapper_enable_indexes(uint mode)
13846 {
13847 int error = 0;
13848 MRN_DBUG_ENTER_METHOD();
13849
13850 int mroonga_error = wrapper_enable_indexes_mroonga(mode);
13851
13852 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13853 MRN_SET_WRAP_TABLE_KEY(this, table);
13854 error = wrap_handler->ha_enable_indexes(mode);
13855 MRN_SET_BASE_SHARE_KEY(share, table->s);
13856 MRN_SET_BASE_TABLE_KEY(this, table);
13857 if (error == HA_ERR_WRONG_COMMAND) {
13858 error = mroonga_error;
13859 }
13860 DBUG_RETURN(error);
13861 }
13862
storage_enable_indexes(uint mode)13863 int ha_mroonga::storage_enable_indexes(uint mode)
13864 {
13865 int error = 0;
13866 uint n_keys = table_share->keys;
13867 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys);
13868 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, n_keys);
13869 bool have_multiple_column_index = false;
13870 bool skip_unique_key = (mode == HA_KEY_SWITCH_NONUNIQ_SAVE);
13871 MRN_DBUG_ENTER_METHOD();
13872 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
13873 uint i;
13874 for (i = 0; i < table_share->keys; i++) {
13875 if (i == table->s->primary_key) {
13876 continue;
13877 }
13878 if (!grn_index_columns[i]) {
13879 break;
13880 }
13881 }
13882 if (i == table_share->keys) {
13883 DBUG_PRINT("info", ("mroonga: keys are enabled already"));
13884 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
13885 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
13886 DBUG_RETURN(0);
13887 }
13888 KEY *key_info = table->key_info;
13889 bitmap_clear_all(table->read_set);
13890 mrn::PathMapper mapper(share->table_name);
13891 for (i = 0; i < n_keys; i++) {
13892 if (i == table->s->primary_key) {
13893 continue;
13894 }
13895 if (skip_unique_key && (key_info[i].flags & HA_NOSAME)) {
13896 continue;
13897 }
13898
13899 if ((error = mrn_add_index_param(share, &key_info[i], i)))
13900 {
13901 break;
13902 }
13903 index_tables[i] = NULL;
13904 if (!grn_index_columns[i]) {
13905 if ((error = storage_create_index(table, mapper.table_name(), grn_table,
13906 share, &key_info[i], index_tables,
13907 index_columns, i)))
13908 {
13909 break;
13910 }
13911 if (
13912 KEY_N_KEY_PARTS(&(key_info[i])) != 1 &&
13913 !(key_info[i].flags & HA_FULLTEXT)
13914 ) {
13915 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
13916 have_multiple_column_index = true;
13917 }
13918 grn_index_tables[i] = index_tables[i];
13919 grn_index_columns[i] = index_columns[i];
13920 } else {
13921 index_columns[i] = NULL;
13922 }
13923 }
13924 if (!error && have_multiple_column_index)
13925 {
13926 error = storage_add_index_multiple_columns(key_info, n_keys,
13927 index_tables,
13928 index_columns,
13929 skip_unique_key);
13930 }
13931 bitmap_set_all(table->read_set);
13932 } else {
13933 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
13934 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
13935 DBUG_RETURN(HA_ERR_WRONG_COMMAND);
13936 }
13937 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
13938 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
13939 DBUG_RETURN(error);
13940 }
13941
enable_indexes(uint mode)13942 int ha_mroonga::enable_indexes(uint mode)
13943 {
13944 int error = 0;
13945 MRN_DBUG_ENTER_METHOD();
13946 share->disable_keys = false;
13947 if (share->wrapper_mode)
13948 {
13949 error = wrapper_enable_indexes(mode);
13950 } else {
13951 error = storage_enable_indexes(mode);
13952 }
13953 DBUG_RETURN(error);
13954 }
13955
wrapper_check(THD * thd,HA_CHECK_OPT * check_opt)13956 int ha_mroonga::wrapper_check(THD* thd, HA_CHECK_OPT* check_opt)
13957 {
13958 int error = 0;
13959 MRN_DBUG_ENTER_METHOD();
13960 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13961 MRN_SET_WRAP_TABLE_KEY(this, table);
13962 error = wrap_handler->ha_check(thd, check_opt);
13963 MRN_SET_BASE_SHARE_KEY(share, table->s);
13964 MRN_SET_BASE_TABLE_KEY(this, table);
13965 DBUG_RETURN(error);
13966 }
13967
storage_check(THD * thd,HA_CHECK_OPT * check_opt)13968 int ha_mroonga::storage_check(THD* thd, HA_CHECK_OPT* check_opt)
13969 {
13970 MRN_DBUG_ENTER_METHOD();
13971 mrn::DatabaseRepairer repairer(ctx, thd);
13972 if (repairer.is_corrupt()) {
13973 DBUG_RETURN(HA_ADMIN_CORRUPT);
13974 } else {
13975 DBUG_RETURN(HA_ADMIN_OK);
13976 }
13977 }
13978
check(THD * thd,HA_CHECK_OPT * check_opt)13979 int ha_mroonga::check(THD* thd, HA_CHECK_OPT* check_opt)
13980 {
13981 MRN_DBUG_ENTER_METHOD();
13982 int error = 0;
13983 if (share->wrapper_mode)
13984 {
13985 error = wrapper_check(thd, check_opt);
13986 } else {
13987 error = storage_check(thd, check_opt);
13988 }
13989 DBUG_RETURN(error);
13990 }
13991
wrapper_fill_indexes(THD * thd,KEY * key_info,grn_obj ** index_columns,uint n_keys)13992 int ha_mroonga::wrapper_fill_indexes(THD *thd, KEY *key_info,
13993 grn_obj **index_columns, uint n_keys)
13994 {
13995 int error = 0;
13996 KEY *p_key_info = &table->key_info[table_share->primary_key];
13997 KEY *tmp_key_info;
13998 #ifdef MRN_NEED_M_LOCK_TYPE_CHECK_FOR_WRAPPER_EXTERNAL_LOCK
13999 int wrapper_lock_type_backup = wrap_handler->get_lock_type();
14000 #endif
14001 MRN_DBUG_ENTER_METHOD();
14002 DBUG_PRINT("info", ("mroonga: n_keys=%u", n_keys));
14003
14004 grn_bool need_lock = true;
14005 if (mrn_lock_type != F_UNLCK) {
14006 need_lock = false;
14007 }
14008 #ifdef MRN_NEED_M_LOCK_TYPE_CHECK_FOR_WRAPPER_EXTERNAL_LOCK
14009 if (wrapper_lock_type_backup != F_UNLCK) {
14010 need_lock = false;
14011 }
14012 #endif
14013 if (need_lock) {
14014 error = wrapper_external_lock(thd, F_WRLCK);
14015 }
14016 if (!error) {
14017 if (
14018 !(error = wrapper_start_stmt(thd, thr_lock_data.type)) &&
14019 !(error = wrapper_rnd_init(true))
14020 ) {
14021 grn_obj key;
14022 GRN_TEXT_INIT(&key, 0);
14023 grn_bulk_space(ctx, &key, p_key_info->key_length);
14024 while (!(error = wrapper_rnd_next(table->record[0])))
14025 {
14026 key_copy((uchar *)(GRN_TEXT_VALUE(&key)), table->record[0],
14027 p_key_info, p_key_info->key_length);
14028 int added;
14029 grn_id record_id;
14030 mrn_change_encoding(ctx, NULL);
14031 record_id = grn_table_add(ctx, grn_table,
14032 GRN_TEXT_VALUE(&key), p_key_info->key_length,
14033 &added);
14034 if (record_id == GRN_ID_NIL)
14035 {
14036 char error_message[MRN_MESSAGE_BUFFER_SIZE];
14037 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
14038 "failed to add a new record into groonga: key=<%.*s>",
14039 (int) p_key_info->key_length, GRN_TEXT_VALUE(&key));
14040 error = ER_ERROR_ON_WRITE;
14041 my_message(error, error_message, MYF(0));
14042 }
14043 if (error)
14044 break;
14045
14046 uint k;
14047 for (k = 0; k < n_keys; k++) {
14048 tmp_key_info = &key_info[k];
14049 if (!(tmp_key_info->flags & HA_FULLTEXT) &&
14050 !mrn_is_geo_key(tmp_key_info)) {
14051 continue;
14052 }
14053 if (!index_columns[k]) {
14054 continue;
14055 }
14056 DBUG_PRINT("info", ("mroonga: key_num=%u", k));
14057
14058 uint l;
14059 for (l = 0; l < KEY_N_KEY_PARTS(tmp_key_info); l++) {
14060 Field *field = tmp_key_info->key_part[l].field;
14061
14062 if (field->is_null())
14063 continue;
14064 error = mrn_change_encoding(ctx, field->charset());
14065 if (error)
14066 break;
14067
14068 error = generic_store_bulk(field, &new_value_buffer);
14069 if (error) {
14070 my_message(error,
14071 "mroonga: wrapper: "
14072 "failed to get new value for updating index.",
14073 MYF(0));
14074 break;
14075 }
14076
14077 grn_obj *index_column = index_columns[k];
14078 grn_rc rc;
14079 rc = grn_column_index_update(ctx, index_column, record_id, l + 1,
14080 NULL, &new_value_buffer);
14081 grn_obj_unlink(ctx, index_column);
14082 if (rc) {
14083 error = ER_ERROR_ON_WRITE;
14084 my_message(error, ctx->errbuf, MYF(0));
14085 break;
14086 }
14087 }
14088 if (error)
14089 break;
14090 }
14091 if (error)
14092 break;
14093 }
14094 grn_obj_unlink(ctx, &key);
14095 if (error != HA_ERR_END_OF_FILE)
14096 wrapper_rnd_end();
14097 else
14098 error = wrapper_rnd_end();
14099 }
14100 if (need_lock) {
14101 wrapper_external_lock(thd, F_UNLCK);
14102 }
14103 }
14104 DBUG_RETURN(error);
14105 }
14106
wrapper_recreate_indexes(THD * thd)14107 int ha_mroonga::wrapper_recreate_indexes(THD *thd)
14108 {
14109 int error;
14110 uint i, n_keys = table_share->keys;
14111 KEY *p_key_info = &table->key_info[table_share->primary_key];
14112 KEY *key_info = table->key_info;
14113 MRN_DBUG_ENTER_METHOD();
14114 mrn::PathMapper mapper(table_share->normalized_path.str);
14115 bitmap_clear_all(table->read_set);
14116 clear_indexes();
14117 remove_grn_obj_force(mapper.table_name());
14118 grn_table = NULL;
14119 mrn_set_bitmap_by_key(table->read_set, p_key_info);
14120 for (i = 0; i < n_keys; i++) {
14121 if (!(key_info[i].flags & HA_FULLTEXT) && !mrn_is_geo_key(&key_info[i])) {
14122 continue;
14123 }
14124 mrn::IndexTableName index_table_name(mapper.table_name(),
14125 table_share->key_info[i].name.str);
14126 char index_column_full_name[MRN_MAX_PATH_SIZE];
14127 snprintf(index_column_full_name, MRN_MAX_PATH_SIZE,
14128 "%s.%s", index_table_name.c_str(), INDEX_COLUMN_NAME);
14129 remove_grn_obj_force(index_column_full_name);
14130 remove_grn_obj_force(index_table_name.c_str());
14131
14132 char index_column_full_old_name[MRN_MAX_PATH_SIZE];
14133 snprintf(index_column_full_old_name, MRN_MAX_PATH_SIZE,
14134 "%s.%s", index_table_name.old_c_str(), INDEX_COLUMN_NAME);
14135 remove_grn_obj_force(index_column_full_old_name);
14136 remove_grn_obj_force(index_table_name.old_c_str());
14137
14138 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
14139 }
14140 error = wrapper_create_index(table_share->normalized_path.str, table, share);
14141 if (error)
14142 DBUG_RETURN(error);
14143 error = wrapper_open_indexes(table_share->normalized_path.str);
14144 if (error)
14145 DBUG_RETURN(error);
14146 error = wrapper_fill_indexes(thd, key_info, grn_index_columns, n_keys);
14147 bitmap_set_all(table->read_set);
14148 DBUG_RETURN(error);
14149 }
14150
storage_recreate_indexes(THD * thd)14151 int ha_mroonga::storage_recreate_indexes(THD *thd)
14152 {
14153 MRN_DBUG_ENTER_METHOD();
14154
14155 if (share->disable_keys)
14156 DBUG_RETURN(HA_ADMIN_OK);
14157
14158 clear_indexes();
14159
14160 int n_columns = table->s->fields;
14161 for (int i = 0; i < n_columns; i++) {
14162 grn_obj *column = grn_columns[i];
14163
14164 if (!column)
14165 continue;
14166
14167 int n_hooks = grn_obj_get_nhooks(ctx, column, GRN_HOOK_SET);
14168 for (int j = 0; j < n_hooks; j++) {
14169 grn_obj_delete_hook(ctx, column, GRN_HOOK_SET, j);
14170 }
14171 }
14172
14173 uint n_keys = table_share->keys;
14174 mrn::PathMapper mapper(table_share->normalized_path.str);
14175 for (uint i = 0; i < n_keys; i++) {
14176 if (share->index_table && share->index_table[i])
14177 continue;
14178
14179 if (i == table_share->primary_key)
14180 continue;
14181
14182 mrn::IndexTableName index_table_name(mapper.table_name(),
14183 table_share->key_info[i].name.str);
14184 char index_column_full_name[MRN_MAX_PATH_SIZE];
14185 snprintf(index_column_full_name, MRN_MAX_PATH_SIZE,
14186 "%s.%s", index_table_name.c_str(), INDEX_COLUMN_NAME);
14187 remove_grn_obj_force(index_column_full_name);
14188 remove_grn_obj_force(index_table_name.c_str());
14189
14190 char index_column_full_old_name[MRN_MAX_PATH_SIZE];
14191 snprintf(index_column_full_old_name, MRN_MAX_PATH_SIZE,
14192 "%s.%s", index_table_name.old_c_str(), INDEX_COLUMN_NAME);
14193 remove_grn_obj_force(index_column_full_old_name);
14194 remove_grn_obj_force(index_table_name.old_c_str());
14195 }
14196
14197 int error;
14198 error = storage_create_indexes(table, mapper.table_name(), grn_table, share);
14199 if (error)
14200 DBUG_RETURN(HA_ADMIN_FAILED);
14201
14202 error = storage_open_indexes(table_share->normalized_path.str);
14203 if (error)
14204 DBUG_RETURN(HA_ADMIN_FAILED);
14205
14206 DBUG_RETURN(HA_ADMIN_OK);
14207 }
14208
wrapper_repair(THD * thd,HA_CHECK_OPT * check_opt)14209 int ha_mroonga::wrapper_repair(THD* thd, HA_CHECK_OPT* check_opt)
14210 {
14211 int error;
14212 MRN_DBUG_ENTER_METHOD();
14213 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14214 MRN_SET_WRAP_TABLE_KEY(this, table);
14215 error = wrap_handler->ha_repair(thd, check_opt);
14216 MRN_SET_BASE_SHARE_KEY(share, table->s);
14217 MRN_SET_BASE_TABLE_KEY(this, table);
14218 if (error && error != HA_ADMIN_NOT_IMPLEMENTED)
14219 DBUG_RETURN(error);
14220 error = wrapper_recreate_indexes(thd);
14221 DBUG_RETURN(error);
14222 }
14223
storage_repair(THD * thd,HA_CHECK_OPT * check_opt)14224 int ha_mroonga::storage_repair(THD* thd, HA_CHECK_OPT* check_opt)
14225 {
14226 MRN_DBUG_ENTER_METHOD();
14227 int error = storage_recreate_indexes(thd);
14228 DBUG_RETURN(error);
14229 }
14230
repair(THD * thd,HA_CHECK_OPT * check_opt)14231 int ha_mroonga::repair(THD* thd, HA_CHECK_OPT* check_opt)
14232 {
14233 MRN_DBUG_ENTER_METHOD();
14234 int error = 0;
14235 share->disable_keys = false;
14236 if (share->wrapper_mode)
14237 {
14238 error = wrapper_repair(thd, check_opt);
14239 } else {
14240 error = storage_repair(thd, check_opt);
14241 }
14242 DBUG_RETURN(error);
14243 }
14244
wrapper_check_and_repair(THD * thd)14245 bool ha_mroonga::wrapper_check_and_repair(THD *thd)
14246 {
14247 bool is_error_or_not_supported;
14248 MRN_DBUG_ENTER_METHOD();
14249 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14250 MRN_SET_WRAP_TABLE_KEY(this, table);
14251 is_error_or_not_supported = wrap_handler->ha_check_and_repair(thd);
14252 MRN_SET_BASE_SHARE_KEY(share, table->s);
14253 MRN_SET_BASE_TABLE_KEY(this, table);
14254 DBUG_RETURN(is_error_or_not_supported);
14255 }
14256
storage_check_and_repair(THD * thd)14257 bool ha_mroonga::storage_check_and_repair(THD *thd)
14258 {
14259 MRN_DBUG_ENTER_METHOD();
14260 bool is_error = false;
14261 mrn::DatabaseRepairer repairer(ctx, thd);
14262 is_error = !repairer.repair();
14263 DBUG_RETURN(is_error);
14264 }
14265
check_and_repair(THD * thd)14266 bool ha_mroonga::check_and_repair(THD *thd)
14267 {
14268 MRN_DBUG_ENTER_METHOD();
14269 bool is_error_or_not_supported;
14270 if (share->wrapper_mode)
14271 {
14272 is_error_or_not_supported = wrapper_check_and_repair(thd);
14273 } else {
14274 is_error_or_not_supported = storage_check_and_repair(thd);
14275 }
14276 DBUG_RETURN(is_error_or_not_supported);
14277 }
14278
wrapper_analyze(THD * thd,HA_CHECK_OPT * check_opt)14279 int ha_mroonga::wrapper_analyze(THD* thd, HA_CHECK_OPT* check_opt)
14280 {
14281 int error = 0;
14282 MRN_DBUG_ENTER_METHOD();
14283 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14284 MRN_SET_WRAP_TABLE_KEY(this, table);
14285 error = wrap_handler->ha_analyze(thd, check_opt);
14286 MRN_SET_BASE_SHARE_KEY(share, table->s);
14287 MRN_SET_BASE_TABLE_KEY(this, table);
14288 DBUG_RETURN(error);
14289 }
14290
storage_analyze(THD * thd,HA_CHECK_OPT * check_opt)14291 int ha_mroonga::storage_analyze(THD* thd, HA_CHECK_OPT* check_opt)
14292 {
14293 MRN_DBUG_ENTER_METHOD();
14294 DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
14295 }
14296
analyze(THD * thd,HA_CHECK_OPT * check_opt)14297 int ha_mroonga::analyze(THD* thd, HA_CHECK_OPT* check_opt)
14298 {
14299 MRN_DBUG_ENTER_METHOD();
14300 int error = 0;
14301 if (share->wrapper_mode)
14302 {
14303 error = wrapper_analyze(thd, check_opt);
14304 } else {
14305 error = storage_analyze(thd, check_opt);
14306 }
14307 DBUG_RETURN(error);
14308 }
14309
wrapper_optimize(THD * thd,HA_CHECK_OPT * check_opt)14310 int ha_mroonga::wrapper_optimize(THD* thd, HA_CHECK_OPT* check_opt)
14311 {
14312 MRN_DBUG_ENTER_METHOD();
14313 DBUG_RETURN(HA_ADMIN_TRY_ALTER);
14314 }
14315
storage_optimize(THD * thd,HA_CHECK_OPT * check_opt)14316 int ha_mroonga::storage_optimize(THD* thd, HA_CHECK_OPT* check_opt)
14317 {
14318 MRN_DBUG_ENTER_METHOD();
14319 DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
14320 }
14321
optimize(THD * thd,HA_CHECK_OPT * check_opt)14322 int ha_mroonga::optimize(THD* thd, HA_CHECK_OPT* check_opt)
14323 {
14324 MRN_DBUG_ENTER_METHOD();
14325 int error = 0;
14326 if (share->wrapper_mode)
14327 {
14328 error = wrapper_optimize(thd, check_opt);
14329 } else {
14330 error = storage_optimize(thd, check_opt);
14331 }
14332 DBUG_RETURN(error);
14333 }
14334
wrapper_is_fatal_error(int error_num,uint flags)14335 bool ha_mroonga::wrapper_is_fatal_error(int error_num, uint flags)
14336 {
14337 bool res;
14338 MRN_DBUG_ENTER_METHOD();
14339 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14340 MRN_SET_WRAP_TABLE_KEY(this, table);
14341 #ifdef MRN_HANDLER_IS_FATAL_ERROR_HAVE_FLAGS
14342 res = wrap_handler->is_fatal_error(error_num, flags);
14343 #else
14344 res = wrap_handler->is_fatal_error(error_num);
14345 #endif
14346 MRN_SET_BASE_SHARE_KEY(share, table->s);
14347 MRN_SET_BASE_TABLE_KEY(this, table);
14348 DBUG_RETURN(res);
14349 }
14350
storage_is_fatal_error(int error_num,uint flags)14351 bool ha_mroonga::storage_is_fatal_error(int error_num, uint flags)
14352 {
14353 MRN_DBUG_ENTER_METHOD();
14354 #ifdef MRN_HANDLER_IS_FATAL_ERROR_HAVE_FLAGS
14355 bool is_fatal_error = handler::is_fatal_error(error_num, flags);
14356 #else
14357 bool is_fatal_error = handler::is_fatal_error(error_num);
14358 #endif
14359 DBUG_RETURN(is_fatal_error);
14360 }
14361
is_fatal_error(int error_num,uint flags)14362 bool ha_mroonga::is_fatal_error(int error_num, uint flags)
14363 {
14364 MRN_DBUG_ENTER_METHOD();
14365 bool is_fatal_error;
14366 if (share->wrapper_mode)
14367 {
14368 is_fatal_error = wrapper_is_fatal_error(error_num, flags);
14369 } else {
14370 is_fatal_error = storage_is_fatal_error(error_num, flags);
14371 }
14372 DBUG_RETURN(is_fatal_error);
14373 }
14374
wrapper_check_if_incompatible_data(HA_CREATE_INFO * create_info,uint table_changes)14375 bool ha_mroonga::wrapper_check_if_incompatible_data(
14376 HA_CREATE_INFO *create_info, uint table_changes)
14377 {
14378 bool res;
14379 MRN_DBUG_ENTER_METHOD();
14380 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14381 MRN_SET_WRAP_TABLE_KEY(this, table);
14382 res = wrap_handler->check_if_incompatible_data(create_info, table_changes);
14383 MRN_SET_BASE_SHARE_KEY(share, table->s);
14384 MRN_SET_BASE_TABLE_KEY(this, table);
14385 DBUG_RETURN(res);
14386 }
14387
storage_check_if_incompatible_data(HA_CREATE_INFO * create_info,uint table_changes)14388 bool ha_mroonga::storage_check_if_incompatible_data(
14389 HA_CREATE_INFO *create_info, uint table_changes)
14390 {
14391 MRN_DBUG_ENTER_METHOD();
14392 uint n = table_share->fields;
14393 for (uint i = 0; i < n; i++) {
14394 Field *field = table->field[i];
14395 if (field->flags & FIELD_IS_RENAMED) {
14396 DBUG_RETURN(COMPATIBLE_DATA_NO);
14397 }
14398 }
14399 DBUG_RETURN(COMPATIBLE_DATA_YES);
14400 }
14401
check_if_incompatible_data(HA_CREATE_INFO * create_info,uint table_changes)14402 bool ha_mroonga::check_if_incompatible_data(
14403 HA_CREATE_INFO *create_info, uint table_changes)
14404 {
14405 MRN_DBUG_ENTER_METHOD();
14406 bool res;
14407 if (
14408 create_info->comment.str != table_share->comment.str ||
14409 create_info->connect_string.str != table_share->connect_string.str
14410 ) {
14411 DBUG_RETURN(COMPATIBLE_DATA_NO);
14412 }
14413 if (share->wrapper_mode)
14414 {
14415 res = wrapper_check_if_incompatible_data(create_info, table_changes);
14416 } else {
14417 res = storage_check_if_incompatible_data(create_info, table_changes);
14418 }
14419 DBUG_RETURN(res);
14420 }
14421
storage_add_index_multiple_columns(KEY * key_info,uint num_of_keys,grn_obj ** index_tables,grn_obj ** index_columns,bool skip_unique_key)14422 int ha_mroonga::storage_add_index_multiple_columns(KEY *key_info,
14423 uint num_of_keys,
14424 grn_obj **index_tables,
14425 grn_obj **index_columns,
14426 bool skip_unique_key)
14427 {
14428 MRN_DBUG_ENTER_METHOD();
14429
14430 int error = 0;
14431
14432 if (!(error = storage_rnd_init(true)))
14433 {
14434 while (!(error = storage_rnd_next(table->record[0])))
14435 {
14436 for (uint i = 0; i < num_of_keys; i++) {
14437 KEY *current_key_info = key_info + i;
14438 if (
14439 KEY_N_KEY_PARTS(current_key_info) == 1 ||
14440 (current_key_info->flags & HA_FULLTEXT)
14441 ) {
14442 continue;
14443 }
14444 if (skip_unique_key && (key_info[i].flags & HA_NOSAME)) {
14445 continue;
14446 }
14447 if (!index_columns[i]) {
14448 continue;
14449 }
14450
14451 /* fix key_info.key_length */
14452 for (uint j = 0; j < KEY_N_KEY_PARTS(current_key_info); j++) {
14453 if (
14454 !current_key_info->key_part[j].null_bit &&
14455 current_key_info->key_part[j].field->null_bit
14456 ) {
14457 current_key_info->key_length++;
14458 current_key_info->key_part[j].null_bit =
14459 current_key_info->key_part[j].field->null_bit;
14460 }
14461 }
14462 if (key_info[i].flags & HA_NOSAME) {
14463 grn_id key_id;
14464 if ((error = storage_write_row_unique_index(table->record[0],
14465 current_key_info,
14466 index_tables[i],
14467 index_columns[i],
14468 &key_id)))
14469 {
14470 if (error == HA_ERR_FOUND_DUPP_KEY)
14471 {
14472 error = HA_ERR_FOUND_DUPP_UNIQUE;
14473 }
14474 break;
14475 }
14476 }
14477 if ((error = storage_write_row_multiple_column_index(table->record[0],
14478 record_id,
14479 current_key_info,
14480 index_columns[i])))
14481 {
14482 break;
14483 }
14484 }
14485 if (error)
14486 break;
14487 }
14488 if (error != HA_ERR_END_OF_FILE) {
14489 storage_rnd_end();
14490 } else {
14491 error = storage_rnd_end();
14492 }
14493 }
14494
14495 DBUG_RETURN(error);
14496 }
14497
14498 #ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER
wrapper_is_comment_changed(TABLE * table1,TABLE * table2)14499 bool ha_mroonga::wrapper_is_comment_changed(TABLE *table1, TABLE *table2)
14500 {
14501 MRN_DBUG_ENTER_METHOD();
14502
14503 if (table1->s->comment.length != table2->s->comment.length) {
14504 DBUG_RETURN(true);
14505 }
14506
14507 if (strncmp(table1->s->comment.str,
14508 table2->s->comment.str,
14509 table1->s->comment.length) == 0) {
14510 DBUG_RETURN(false);
14511 } else {
14512 DBUG_RETURN(true);
14513 }
14514 }
14515
wrapper_check_if_supported_inplace_alter(TABLE * altered_table,Alter_inplace_info * ha_alter_info)14516 enum_alter_inplace_result ha_mroonga::wrapper_check_if_supported_inplace_alter(
14517 TABLE *altered_table,
14518 Alter_inplace_info *ha_alter_info)
14519 {
14520 MRN_DBUG_ENTER_METHOD();
14521 uint n_keys;
14522 uint i;
14523 enum_alter_inplace_result result_mroonga = HA_ALTER_INPLACE_NO_LOCK;
14524 DBUG_PRINT("info",
14525 ("mroonga: handler_flags=%lu",
14526 static_cast<ulong>(ha_alter_info->handler_flags)));
14527
14528 if (wrapper_is_comment_changed(table, altered_table)) {
14529 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14530 }
14531 if (
14532 (ha_alter_info->handler_flags & ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX) &&
14533 (ha_alter_info->handler_flags &
14534 (
14535 ALTER_ADD_COLUMN |
14536 ALTER_DROP_COLUMN |
14537 MRN_ALTER_INPLACE_INFO_ALTER_STORED_COLUMN_TYPE |
14538 MRN_ALTER_INPLACE_INFO_ALTER_STORED_COLUMN_ORDER |
14539 ALTER_COLUMN_NULLABLE |
14540 ALTER_COLUMN_NOT_NULLABLE |
14541 ALTER_COLUMN_STORAGE_TYPE |
14542 ALTER_ADD_STORED_GENERATED_COLUMN |
14543 ALTER_COLUMN_COLUMN_FORMAT
14544 )
14545 )
14546 ) {
14547 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14548 }
14549 if (ha_alter_info->handler_flags & ALTER_RENAME)
14550 {
14551 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14552 }
14553
14554 DBUG_ASSERT(ha_alter_info->key_count == altered_table->s->keys);
14555 alter_key_count = 0;
14556 alter_index_drop_count = 0;
14557 alter_index_add_count = 0;
14558 alter_handler_flags = ha_alter_info->handler_flags;
14559 if (!(alter_key_info_buffer = (KEY *)
14560 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
14561 &alter_key_info_buffer, sizeof(KEY) * ha_alter_info->key_count,
14562 &alter_index_drop_buffer, sizeof(KEY) * ha_alter_info->index_drop_count,
14563 &alter_index_add_buffer, sizeof(uint) * ha_alter_info->index_add_count,
14564 &wrap_altered_table, sizeof(TABLE),
14565 &wrap_altered_table_key_info, sizeof(KEY) * altered_table->s->keys,
14566 &wrap_altered_table_share, sizeof(TABLE_SHARE),
14567 &wrap_altered_table_share_key_info, sizeof(KEY) * altered_table->s->keys,
14568 NullS))
14569 ) {
14570 DBUG_RETURN(HA_ALTER_ERROR);
14571 }
14572 *wrap_altered_table= *altered_table;
14573 *wrap_altered_table_share= *altered_table->s;
14574 mrn_init_sql_alloc(ha_thd(), &(wrap_altered_table_share->mem_root));
14575
14576 n_keys = ha_alter_info->index_drop_count;
14577 for (i = 0; i < n_keys; ++i) {
14578 const KEY *key = ha_alter_info->index_drop_buffer[i];
14579 if (key->flags & HA_FULLTEXT || mrn_is_geo_key(key)) {
14580 result_mroonga = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
14581 } else {
14582 memcpy(&alter_index_drop_buffer[alter_index_drop_count],
14583 ha_alter_info->index_drop_buffer[i], sizeof(KEY));
14584 ++alter_index_drop_count;
14585 }
14586 }
14587 if (!alter_index_drop_count) {
14588 alter_handler_flags &= ~ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX;
14589 }
14590 n_keys = ha_alter_info->index_add_count;
14591 for (i = 0; i < n_keys; ++i) {
14592 const KEY *key =
14593 &altered_table->key_info[ha_alter_info->index_add_buffer[i]];
14594 if (key->flags & HA_FULLTEXT || mrn_is_geo_key(key)) {
14595 result_mroonga = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
14596 } else {
14597 alter_index_add_buffer[alter_index_add_count] =
14598 ha_alter_info->index_add_buffer[i];
14599 ++alter_index_add_count;
14600 }
14601 }
14602 if (!alter_index_add_count) {
14603 alter_handler_flags &= ~ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX;
14604 }
14605 uint add_index_pos = 0;
14606 n_keys = ha_alter_info->key_count;
14607 for (i = 0; i < n_keys; ++i) {
14608 const KEY *key = &altered_table->key_info[i];
14609 if (!(key->flags & HA_FULLTEXT || mrn_is_geo_key(key))) {
14610 memcpy(&alter_key_info_buffer[alter_key_count],
14611 &ha_alter_info->key_info_buffer[i], sizeof(KEY));
14612 memcpy(&wrap_altered_table_key_info[alter_key_count],
14613 &altered_table->key_info[i], sizeof(KEY));
14614 memcpy(&wrap_altered_table_share_key_info[alter_key_count],
14615 &altered_table->s->key_info[i], sizeof(KEY));
14616 if (add_index_pos < alter_index_add_count &&
14617 alter_index_add_buffer[add_index_pos] == i) {
14618 alter_index_add_buffer[add_index_pos] = alter_key_count;
14619 ++add_index_pos;
14620 }
14621 ++alter_key_count;
14622 }
14623 }
14624 wrap_altered_table->key_info = wrap_altered_table_key_info;
14625 wrap_altered_table_share->key_info = wrap_altered_table_share_key_info;
14626 wrap_altered_table_share->keys = alter_key_count;
14627 wrap_altered_table->s = wrap_altered_table_share;
14628
14629 if (!alter_handler_flags) {
14630 DBUG_RETURN(result_mroonga);
14631 }
14632 enum_alter_inplace_result result;
14633 MRN_SET_WRAP_ALTER_KEY(this, ha_alter_info);
14634 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14635 MRN_SET_WRAP_TABLE_KEY(this, table);
14636 result = wrap_handler->check_if_supported_inplace_alter(wrap_altered_table,
14637 ha_alter_info);
14638 MRN_SET_BASE_ALTER_KEY(this, ha_alter_info);
14639 MRN_SET_BASE_SHARE_KEY(share, table->s);
14640 MRN_SET_BASE_TABLE_KEY(this, table);
14641 if (result_mroonga > result)
14642 DBUG_RETURN(result);
14643 DBUG_RETURN(result_mroonga);
14644 }
14645
storage_check_if_supported_inplace_alter(TABLE * altered_table,Alter_inplace_info * ha_alter_info)14646 enum_alter_inplace_result ha_mroonga::storage_check_if_supported_inplace_alter(
14647 TABLE *altered_table,
14648 Alter_inplace_info *ha_alter_info)
14649 {
14650 MRN_DBUG_ENTER_METHOD();
14651 alter_table_operations explicitly_unsupported_flags =
14652 ALTER_ADD_FOREIGN_KEY |
14653 ALTER_DROP_FOREIGN_KEY;
14654 alter_table_operations supported_flags =
14655 ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX |
14656 ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX |
14657 ALTER_ADD_UNIQUE_INDEX |
14658 ALTER_DROP_UNIQUE_INDEX |
14659 MRN_ALTER_INPLACE_INFO_ADD_VIRTUAL_COLUMN |
14660 MRN_ALTER_INPLACE_INFO_ADD_STORED_BASE_COLUMN |
14661 ALTER_DROP_COLUMN |
14662 ALTER_COLUMN_NAME;
14663 if (ha_alter_info->handler_flags & explicitly_unsupported_flags) {
14664 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14665 } else if (ha_alter_info->handler_flags & supported_flags) {
14666 DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
14667 } else {
14668 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14669 }
14670 }
14671
check_if_supported_inplace_alter(TABLE * altered_table,Alter_inplace_info * ha_alter_info)14672 enum_alter_inplace_result ha_mroonga::check_if_supported_inplace_alter(
14673 TABLE *altered_table,
14674 Alter_inplace_info *ha_alter_info)
14675 {
14676 MRN_DBUG_ENTER_METHOD();
14677 enum_alter_inplace_result result;
14678 if (share->wrapper_mode) {
14679 result = wrapper_check_if_supported_inplace_alter(altered_table,
14680 ha_alter_info);
14681 } else {
14682 result = storage_check_if_supported_inplace_alter(altered_table,
14683 ha_alter_info);
14684 }
14685 DBUG_RETURN(result);
14686 }
14687
wrapper_prepare_inplace_alter_table(TABLE * altered_table,Alter_inplace_info * ha_alter_info)14688 bool ha_mroonga::wrapper_prepare_inplace_alter_table(
14689 TABLE *altered_table,
14690 Alter_inplace_info *ha_alter_info)
14691 {
14692 bool result;
14693 MRN_DBUG_ENTER_METHOD();
14694 if (!alter_handler_flags) {
14695 DBUG_RETURN(false);
14696 }
14697
14698 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
14699 int error = 0;
14700 MRN_SHARE *tmp_share;
14701 tmp_share = mrn_get_share(altered_table->s->table_name.str,
14702 altered_table,
14703 &error);
14704 if (error != 0) {
14705 DBUG_RETURN(true);
14706 }
14707
14708 if (parse_engine_table_options(ha_thd(),
14709 tmp_share->hton,
14710 wrap_altered_table->s)) {
14711 mrn_free_share(tmp_share);
14712 DBUG_RETURN(true);
14713 }
14714 #endif
14715
14716 MRN_SET_WRAP_ALTER_KEY(this, ha_alter_info);
14717 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14718 MRN_SET_WRAP_TABLE_KEY(this, table);
14719 result = wrap_handler->ha_prepare_inplace_alter_table(wrap_altered_table,
14720 ha_alter_info);
14721 MRN_SET_BASE_ALTER_KEY(this, ha_alter_info);
14722 MRN_SET_BASE_SHARE_KEY(share, table->s);
14723 MRN_SET_BASE_TABLE_KEY(this, table);
14724
14725 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
14726 mrn_free_share(tmp_share);
14727 #endif
14728
14729 DBUG_RETURN(result);
14730 }
14731
storage_prepare_inplace_alter_table(TABLE * altered_table,Alter_inplace_info * ha_alter_info)14732 bool ha_mroonga::storage_prepare_inplace_alter_table(
14733 TABLE *altered_table,
14734 Alter_inplace_info *ha_alter_info)
14735 {
14736 MRN_DBUG_ENTER_METHOD();
14737 DBUG_RETURN(false);
14738 }
14739
prepare_inplace_alter_table(TABLE * altered_table,Alter_inplace_info * ha_alter_info)14740 bool ha_mroonga::prepare_inplace_alter_table(
14741 TABLE *altered_table,
14742 Alter_inplace_info *ha_alter_info)
14743 {
14744 MRN_DBUG_ENTER_METHOD();
14745 bool result;
14746 if (share->wrapper_mode) {
14747 result = wrapper_prepare_inplace_alter_table(altered_table, ha_alter_info);
14748 } else {
14749 result = storage_prepare_inplace_alter_table(altered_table, ha_alter_info);
14750 }
14751 DBUG_RETURN(result);
14752 }
14753
wrapper_inplace_alter_table(TABLE * altered_table,Alter_inplace_info * ha_alter_info)14754 bool ha_mroonga::wrapper_inplace_alter_table(
14755 TABLE *altered_table,
14756 Alter_inplace_info *ha_alter_info)
14757 {
14758 int error;
14759 bool result = false;
14760 uint n_keys;
14761 uint i, j = 0;
14762 KEY *key_info = table_share->key_info;
14763 MRN_DBUG_ENTER_METHOD();
14764 error = mrn_change_encoding(ctx, system_charset_info);
14765 if (error)
14766 DBUG_RETURN(true);
14767
14768 DBUG_PRINT("info", ("mroonga: table_name=%s", share->table_name));
14769 mrn::PathMapper mapper(share->table_name);
14770 n_keys = ha_alter_info->index_drop_count;
14771 for (i = 0; i < n_keys; ++i) {
14772 const KEY *key = ha_alter_info->index_drop_buffer[i];
14773 if (!(key->flags & HA_FULLTEXT || mrn_is_geo_key(key))) {
14774 continue;
14775 }
14776 while (strcmp(key_info[j].name.str, key->name.str)) {
14777 ++j;
14778 }
14779 DBUG_PRINT("info", ("mroonga: key_name=%s", key->name.str));
14780 error = drop_index(share, j);
14781 if (error)
14782 DBUG_RETURN(true);
14783 grn_index_tables[j] = NULL;
14784 grn_index_columns[j] = NULL;
14785 }
14786
14787 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables,
14788 ha_alter_info->key_count);
14789 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns,
14790 ha_alter_info->key_count);
14791 MRN_SHARE *tmp_share;
14792 TABLE_SHARE tmp_table_share;
14793 char **key_tokenizer;
14794 uint *key_tokenizer_length;
14795 KEY *p_key_info = &table->key_info[table_share->primary_key];
14796 bool need_fill_index = false;
14797 memset(index_tables, 0, sizeof(grn_obj *) * ha_alter_info->key_count);
14798 memset(index_columns, 0, sizeof(grn_obj *) * ha_alter_info->key_count);
14799 tmp_table_share.keys = ha_alter_info->key_count;
14800 tmp_table_share.fields = 0;
14801 if (!(tmp_share = (MRN_SHARE *)
14802 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
14803 &tmp_share, sizeof(*tmp_share),
14804 &key_tokenizer, sizeof(char *) * (tmp_table_share.keys),
14805 &key_tokenizer_length, sizeof(uint) * (tmp_table_share.keys),
14806 NullS))
14807 ) {
14808 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
14809 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
14810 DBUG_RETURN(true);
14811 }
14812 tmp_share->engine = NULL;
14813 tmp_share->table_share = &tmp_table_share;
14814 tmp_share->index_table = NULL;
14815 tmp_share->index_table_length = NULL;
14816 tmp_share->key_tokenizer = key_tokenizer;
14817 tmp_share->key_tokenizer_length = key_tokenizer_length;
14818 bitmap_clear_all(table->read_set);
14819 mrn_set_bitmap_by_key(table->read_set, p_key_info);
14820 n_keys = ha_alter_info->index_add_count;
14821 for (i = 0; i < n_keys; ++i) {
14822 uint key_pos = ha_alter_info->index_add_buffer[i];
14823 KEY *key = &altered_table->key_info[key_pos];
14824 if (!(key->flags & HA_FULLTEXT || mrn_is_geo_key(key))) {
14825 continue;
14826 }
14827 if (share->disable_keys) {
14828 continue;
14829 }
14830 if ((error = mrn_add_index_param(tmp_share, key, key_pos)))
14831 {
14832 break;
14833 }
14834 DBUG_PRINT("info", ("mroonga: add key pos=%u", key_pos));
14835 if (
14836 (key->flags & HA_FULLTEXT) &&
14837 (error = wrapper_create_index_fulltext(mapper.table_name(),
14838 key_pos,
14839 key, index_tables, NULL,
14840 tmp_share))
14841 ) {
14842 break;
14843 } else if (
14844 mrn_is_geo_key(key) &&
14845 (error = wrapper_create_index_geo(mapper.table_name(),
14846 key_pos, key,
14847 index_tables, NULL, tmp_share))
14848 ) {
14849 break;
14850 }
14851 mrn_set_bitmap_by_key(table->read_set, key);
14852 index_columns[key_pos] = grn_obj_column(ctx,
14853 index_tables[key_pos],
14854 INDEX_COLUMN_NAME,
14855 strlen(INDEX_COLUMN_NAME));
14856 need_fill_index = true;
14857 }
14858 if (!error && need_fill_index) {
14859 my_ptrdiff_t diff =
14860 PTR_BYTE_DIFF(table->record[0], altered_table->record[0]);
14861 mrn::TableFieldsOffsetMover mover(altered_table, diff);
14862 error = wrapper_fill_indexes(ha_thd(), altered_table->key_info,
14863 index_columns, ha_alter_info->key_count);
14864 }
14865 bitmap_set_all(table->read_set);
14866
14867 if (!error && alter_handler_flags) {
14868 #ifdef MRN_SUPPORT_CUSTOM_OPTIONS
14869 {
14870 MRN_SHARE *alter_tmp_share;
14871 alter_tmp_share = mrn_get_share(altered_table->s->table_name.str,
14872 altered_table,
14873 &error);
14874 if (alter_tmp_share) {
14875 if (parse_engine_table_options(ha_thd(),
14876 alter_tmp_share->hton,
14877 wrap_altered_table->s)) {
14878 error = MRN_GET_ERROR_NUMBER;
14879 }
14880 mrn_free_share(alter_tmp_share);
14881 }
14882 }
14883 #endif
14884 if (!error) {
14885 MRN_SET_WRAP_ALTER_KEY(this, ha_alter_info);
14886 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14887 MRN_SET_WRAP_TABLE_KEY(this, table);
14888 result = wrap_handler->ha_inplace_alter_table(wrap_altered_table,
14889 ha_alter_info);
14890 MRN_SET_BASE_ALTER_KEY(this, ha_alter_info);
14891 MRN_SET_BASE_SHARE_KEY(share, table->s);
14892 MRN_SET_BASE_TABLE_KEY(this, table);
14893 }
14894 }
14895
14896 if (result || error)
14897 {
14898 n_keys = ha_alter_info->index_add_count;
14899 for (i = 0; i < n_keys; ++i) {
14900 uint key_pos = ha_alter_info->index_add_buffer[i];
14901 KEY *key = &altered_table->key_info[key_pos];
14902 if (!(key->flags & HA_FULLTEXT || mrn_is_geo_key(key))) {
14903 continue;
14904 }
14905 if (share->disable_keys) {
14906 continue;
14907 }
14908 if (index_tables[key_pos])
14909 {
14910 grn_obj_remove(ctx, index_tables[key_pos]);
14911 }
14912 }
14913 result = true;
14914 }
14915 mrn_free_share_alloc(tmp_share);
14916 my_free(tmp_share);
14917 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
14918 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
14919 DBUG_RETURN(result);
14920 }
14921
storage_inplace_alter_table_add_index(TABLE * altered_table,Alter_inplace_info * ha_alter_info)14922 bool ha_mroonga::storage_inplace_alter_table_add_index(
14923 TABLE *altered_table,
14924 Alter_inplace_info *ha_alter_info)
14925 {
14926 MRN_DBUG_ENTER_METHOD();
14927
14928 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables,
14929 ha_alter_info->key_count);
14930 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns,
14931 ha_alter_info->key_count);
14932 MRN_SHARE *tmp_share;
14933 TABLE_SHARE tmp_table_share;
14934 char **index_table, **key_tokenizer, **col_flags, **col_type;
14935 uint *index_table_length, *key_tokenizer_length, *col_flags_length, *col_type_length;
14936 bool have_multiple_column_index = false;
14937 memset(index_tables, 0, sizeof(grn_obj *) * ha_alter_info->key_count);
14938 memset(index_columns, 0, sizeof(grn_obj *) * ha_alter_info->key_count);
14939 tmp_table_share.keys = ha_alter_info->key_count;
14940 tmp_table_share.fields = 0;
14941 if (!(tmp_share = (MRN_SHARE *)
14942 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
14943 &tmp_share, sizeof(*tmp_share),
14944 &index_table, sizeof(char *) * tmp_table_share.keys,
14945 &index_table_length, sizeof(uint) * tmp_table_share.keys,
14946 &key_tokenizer, sizeof(char *) * tmp_table_share.keys,
14947 &key_tokenizer_length, sizeof(uint) * tmp_table_share.keys,
14948 &col_flags, sizeof(char *) * tmp_table_share.fields,
14949 &col_flags_length, sizeof(uint) * tmp_table_share.fields,
14950 &col_type, sizeof(char *) * tmp_table_share.fields,
14951 &col_type_length, sizeof(uint) * tmp_table_share.fields,
14952 NullS))
14953 ) {
14954 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
14955 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
14956 DBUG_RETURN(true);
14957 }
14958 tmp_share->engine = NULL;
14959 tmp_share->table_share = &tmp_table_share;
14960 tmp_share->index_table = index_table;
14961 tmp_share->index_table_length = index_table_length;
14962 tmp_share->key_tokenizer = key_tokenizer;
14963 tmp_share->key_tokenizer_length = key_tokenizer_length;
14964 tmp_share->col_flags = col_flags;
14965 tmp_share->col_flags_length = col_flags_length;
14966 tmp_share->col_type = col_type;
14967 tmp_share->col_type_length = col_type_length;
14968 bitmap_clear_all(table->read_set);
14969 if (table_share->primary_key != MAX_KEY) {
14970 KEY *p_key_info = &table->key_info[table_share->primary_key];
14971 mrn_set_bitmap_by_key(table->read_set, p_key_info);
14972 }
14973 int error = 0;
14974 uint n_keys = ha_alter_info->index_add_count;
14975 for (uint i = 0; i < n_keys; ++i) {
14976 uint key_pos = ha_alter_info->index_add_buffer[i];
14977 KEY *key = &altered_table->key_info[key_pos];
14978 if (share->disable_keys && !(key->flags & HA_NOSAME)) {
14979 continue; // key is disabled
14980 }
14981 if ((error = mrn_add_index_param(tmp_share, key, key_pos)))
14982 {
14983 break;
14984 }
14985 DBUG_PRINT("info", ("mroonga: add key pos=%u", key_pos));
14986 mrn::PathMapper mapper(share->table_name);
14987 if ((error = storage_create_index(table, mapper.table_name(), grn_table,
14988 tmp_share, key, index_tables,
14989 index_columns, key_pos)))
14990 {
14991 break;
14992 }
14993 if (
14994 KEY_N_KEY_PARTS(key) == 1 &&
14995 (key->flags & HA_NOSAME) &&
14996 grn_table_size(ctx, grn_table) !=
14997 grn_table_size(ctx, index_tables[key_pos])
14998 ) {
14999 error = HA_ERR_FOUND_DUPP_UNIQUE;
15000 my_printf_error(ER_DUP_UNIQUE, ER(ER_DUP_UNIQUE), MYF(0),
15001 table_share->table_name);
15002 ++i;
15003 break;
15004 }
15005 if (
15006 KEY_N_KEY_PARTS(key) != 1 &&
15007 !(key->flags & HA_FULLTEXT)
15008 ) {
15009 mrn_set_bitmap_by_key(table->read_set, key);
15010 have_multiple_column_index = true;
15011 }
15012 }
15013 if (!error && have_multiple_column_index) {
15014 my_ptrdiff_t diff =
15015 PTR_BYTE_DIFF(table->record[0], altered_table->record[0]);
15016 mrn::TableFieldsOffsetMover mover(altered_table, diff);
15017 error = storage_add_index_multiple_columns(altered_table->key_info,
15018 ha_alter_info->key_count,
15019 index_tables,
15020 index_columns, false);
15021 if (error == HA_ERR_FOUND_DUPP_UNIQUE) {
15022 my_printf_error(ER_DUP_UNIQUE, ER(ER_DUP_UNIQUE), MYF(0),
15023 table_share->table_name);
15024 } else if (error) {
15025 my_message(error, "failed to create multiple column index", MYF(0));
15026 }
15027 }
15028 bitmap_set_all(table->read_set);
15029
15030 bool have_error = false;
15031 if (error)
15032 {
15033 n_keys = ha_alter_info->index_add_count;
15034 for (uint i = 0; i < n_keys; ++i) {
15035 uint key_pos = ha_alter_info->index_add_buffer[i];
15036 KEY *key =
15037 &altered_table->key_info[key_pos];
15038 if (share->disable_keys && !(key->flags & HA_NOSAME)) {
15039 continue;
15040 }
15041 if (index_tables[key_pos])
15042 {
15043 grn_obj_remove(ctx, index_columns[key_pos]);
15044 grn_obj_remove(ctx, index_tables[key_pos]);
15045 }
15046 }
15047 have_error = true;
15048 }
15049 mrn_free_share_alloc(tmp_share);
15050 my_free(tmp_share);
15051 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15052 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15053
15054 DBUG_RETURN(have_error);
15055 }
15056
storage_inplace_alter_table_drop_index(TABLE * altered_table,Alter_inplace_info * ha_alter_info)15057 bool ha_mroonga::storage_inplace_alter_table_drop_index(
15058 TABLE *altered_table,
15059 Alter_inplace_info *ha_alter_info)
15060 {
15061 MRN_DBUG_ENTER_METHOD();
15062
15063 bool have_error = false;
15064 uint n_keys;
15065 uint i, j = 0;
15066 KEY *key_info = table_share->key_info;
15067 mrn::PathMapper mapper(share->table_name);
15068 n_keys = ha_alter_info->index_drop_count;
15069 for (i = 0; i < n_keys; ++i) {
15070 KEY *key = ha_alter_info->index_drop_buffer[i];
15071 while (strcmp(key_info[j].name.str, key->name.str) != 0) {
15072 ++j;
15073 }
15074 int error = drop_index(share, j);
15075 if (error != 0)
15076 DBUG_RETURN(true);
15077 grn_index_tables[j] = NULL;
15078 grn_index_columns[j] = NULL;
15079 }
15080
15081 DBUG_RETURN(have_error);
15082 }
15083
storage_inplace_alter_table_add_column(TABLE * altered_table,Alter_inplace_info * ha_alter_info)15084 bool ha_mroonga::storage_inplace_alter_table_add_column(
15085 TABLE *altered_table,
15086 Alter_inplace_info *ha_alter_info)
15087 {
15088 MRN_DBUG_ENTER_METHOD();
15089
15090 bool have_error = false;
15091
15092 MRN_SHARE *tmp_share;
15093 TABLE_SHARE tmp_table_share;
15094 char **index_table, **key_tokenizer, **col_flags, **col_type;
15095 uint *index_table_length, *key_tokenizer_length, *col_flags_length, *col_type_length;
15096 tmp_table_share.keys = 0;
15097 tmp_table_share.fields = altered_table->s->fields;
15098 tmp_share = (MRN_SHARE *)mrn_my_multi_malloc(
15099 MYF(MY_WME | MY_ZEROFILL),
15100 &tmp_share, sizeof(*tmp_share),
15101 &index_table, sizeof(char *) * tmp_table_share.keys,
15102 &index_table_length, sizeof(uint) * tmp_table_share.keys,
15103 &key_tokenizer, sizeof(char *) * tmp_table_share.keys,
15104 &key_tokenizer_length, sizeof(uint) * tmp_table_share.keys,
15105 &col_flags, sizeof(char *) * tmp_table_share.fields,
15106 &col_flags_length, sizeof(uint) * tmp_table_share.fields,
15107 &col_type, sizeof(char *) * tmp_table_share.fields,
15108 &col_type_length, sizeof(uint) * tmp_table_share.fields,
15109 NullS);
15110 if (!tmp_share) {
15111 have_error = true;
15112 DBUG_RETURN(have_error);
15113 }
15114 tmp_share->engine = NULL;
15115 tmp_share->table_share = &tmp_table_share;
15116 tmp_share->index_table = index_table;
15117 tmp_share->index_table_length = index_table_length;
15118 tmp_share->key_tokenizer = key_tokenizer;
15119 tmp_share->key_tokenizer_length = key_tokenizer_length;
15120 tmp_share->col_flags = col_flags;
15121 tmp_share->col_flags_length = col_flags_length;
15122 tmp_share->col_type = col_type;
15123 tmp_share->col_type_length = col_type_length;
15124
15125 mrn::PathMapper mapper(share->table_name);
15126 grn_obj *table_obj;
15127 table_obj = grn_ctx_get(ctx, mapper.table_name(), strlen(mapper.table_name()));
15128
15129 Alter_info *alter_info = ha_alter_info->alter_info;
15130 List_iterator_fast<Create_field> create_fields(alter_info->create_list);
15131 for (uint i = 0; Create_field *create_field = create_fields++; i++) {
15132 if (create_field->field) {
15133 continue;
15134 }
15135
15136 Field *field = altered_table->s->field[i];
15137
15138 #ifdef MRN_SUPPORT_GENERATED_COLUMNS
15139 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
15140 continue;
15141 }
15142 #endif
15143
15144 mrn::ColumnName column_name(field->field_name);
15145 int error = mrn_add_column_param(tmp_share, field, i);
15146 if (error) {
15147 have_error = true;
15148 break;
15149 }
15150
15151 grn_obj_flags col_flags = GRN_OBJ_PERSISTENT;
15152 if (!find_column_flags(field, tmp_share, i, &col_flags)) {
15153 col_flags |= GRN_OBJ_COLUMN_SCALAR;
15154 }
15155
15156 grn_obj *col_type;
15157 {
15158 int column_type_error_code = ER_WRONG_FIELD_SPEC;
15159 col_type = find_column_type(field, tmp_share, i, column_type_error_code);
15160 if (!col_type) {
15161 error = column_type_error_code;
15162 have_error = true;
15163 break;
15164 }
15165 }
15166 char *col_path = NULL; // we don't specify path
15167
15168 grn_obj *column_obj =
15169 grn_column_create(ctx, table_obj,
15170 column_name.c_str(),
15171 column_name.length(),
15172 col_path, col_flags, col_type);
15173 if (ctx->rc) {
15174 error = ER_WRONG_COLUMN_NAME;
15175 my_message(error, ctx->errbuf, MYF(0));
15176 have_error = true;
15177 break;
15178 }
15179
15180 #ifdef MRN_SUPPORT_GENERATED_COLUMNS
15181 if (MRN_GENERATED_COLUMNS_FIELD_IS_STORED(field)) {
15182 # ifndef MRN_MARIADB_P
15183 MY_BITMAP generated_column_bitmap;
15184 if (bitmap_init(&generated_column_bitmap, NULL,
15185 altered_table->s->fields, false)) {
15186 error = HA_ERR_OUT_OF_MEM;
15187 my_message(ER_OUTOFMEMORY,
15188 "mroonga: storage: "
15189 "failed to allocate memory for getting generated value",
15190 MYF(0));
15191 have_error = true;
15192 grn_obj_remove(ctx, column_obj);
15193 break;
15194 }
15195 mrn::SmartBitmap smart_generated_column_bitmap(&generated_column_bitmap);
15196 bitmap_set_bit(&generated_column_bitmap, field->field_index);
15197 # endif
15198
15199 my_ptrdiff_t diff =
15200 PTR_BYTE_DIFF(table->record[0], altered_table->record[0]);
15201 mrn::TableFieldsOffsetMover mover(altered_table, diff);
15202
15203 error = storage_rnd_init(true);
15204 if (error) {
15205 have_error = true;
15206 grn_obj_remove(ctx, column_obj);
15207 break;
15208 }
15209
15210 Field *altered_field = altered_table->field[i];
15211 grn_obj new_value;
15212 GRN_VOID_INIT(&new_value);
15213 mrn::SmartGrnObj smart_new_value(ctx, &new_value);
15214 while (!have_error) {
15215 int next_error = storage_rnd_next(table->record[0]);
15216 if (next_error == HA_ERR_END_OF_FILE) {
15217 break;
15218 } else if (next_error != 0) {
15219 error = next_error;
15220 have_error = true;
15221 grn_obj_remove(ctx, column_obj);
15222 break;
15223 }
15224
15225 # ifdef MRN_MARIADB_P
15226 MRN_GENERATED_COLUMNS_UPDATE_VIRTUAL_FIELD(altered_table, altered_field);
15227 # else
15228 if (update_generated_write_fields(&generated_column_bitmap, altered_table)) {
15229 error = ER_ERROR_ON_WRITE;
15230 my_message(error,
15231 "mroonga: storage: "
15232 "failed to update generated value for updating column",
15233 MYF(0));
15234 have_error = true;
15235 grn_obj_remove(ctx, column_obj);
15236 break;
15237 }
15238 # endif
15239
15240 error = mrn_change_encoding(ctx, altered_field->charset());
15241 if (error) {
15242 my_message(error,
15243 "mroonga: storage: "
15244 "failed to change encoding to store generated value",
15245 MYF(0));
15246 have_error = true;
15247 grn_obj_remove(ctx, column_obj);
15248 break;
15249 }
15250 error = generic_store_bulk(altered_field, &new_value);
15251 if (error) {
15252 my_message(error,
15253 "mroonga: storage: "
15254 "failed to get generated value for updating column",
15255 MYF(0));
15256 have_error = true;
15257 grn_obj_remove(ctx, column_obj);
15258 break;
15259 }
15260
15261 grn_obj_set_value(ctx, column_obj, record_id, &new_value, GRN_OBJ_SET);
15262 if (ctx->rc) {
15263 error = ER_ERROR_ON_WRITE;
15264 my_message(error, ctx->errbuf, MYF(0));
15265 break;
15266 }
15267 }
15268
15269 int end_error = storage_rnd_end();
15270 if (end_error != 0 && error == 0) {
15271 error = end_error;
15272 grn_obj_remove(ctx, column_obj);
15273 break;
15274 }
15275 }
15276 #endif
15277 }
15278
15279 grn_obj_unlink(ctx, table_obj);
15280
15281 mrn_free_share_alloc(tmp_share);
15282 my_free(tmp_share);
15283
15284 DBUG_RETURN(have_error);
15285 }
15286
storage_inplace_alter_table_drop_column(TABLE * altered_table,Alter_inplace_info * ha_alter_info)15287 bool ha_mroonga::storage_inplace_alter_table_drop_column(
15288 TABLE *altered_table,
15289 Alter_inplace_info *ha_alter_info)
15290 {
15291 MRN_DBUG_ENTER_METHOD();
15292
15293 bool have_error = false;
15294
15295 mrn::PathMapper mapper(share->table_name);
15296 grn_obj *table_obj;
15297 table_obj = grn_ctx_get(ctx, mapper.table_name(), strlen(mapper.table_name()));
15298
15299 Alter_info *alter_info = ha_alter_info->alter_info;
15300
15301 uint n_fields = table->s->fields;
15302 for (uint i = 0; i < n_fields; i++) {
15303 Field *field = table->field[i];
15304
15305 bool dropped = true;
15306 List_iterator_fast<Create_field> create_fields(alter_info->create_list);
15307 while (Create_field *create_field = create_fields++) {
15308 if (create_field->field == field) {
15309 dropped = false;
15310 break;
15311 }
15312 }
15313 if (!dropped) {
15314 continue;
15315 }
15316
15317 const char *column_name = field->field_name.str;
15318 int column_name_size = field->field_name.length;
15319
15320 grn_obj *column_obj;
15321 column_obj = grn_obj_column(ctx, table_obj, column_name, column_name_size);
15322 if (column_obj) {
15323 grn_obj_remove(ctx, column_obj);
15324 }
15325 if (ctx->rc) {
15326 int error = ER_WRONG_COLUMN_NAME;
15327 my_message(error, ctx->errbuf, MYF(0));
15328 have_error = true;
15329 break;
15330 }
15331 }
15332 grn_obj_unlink(ctx, table_obj);
15333
15334 DBUG_RETURN(have_error);
15335 }
15336
storage_inplace_alter_table_rename_column(TABLE * altered_table,Alter_inplace_info * ha_alter_info)15337 bool ha_mroonga::storage_inplace_alter_table_rename_column(
15338 TABLE *altered_table,
15339 Alter_inplace_info *ha_alter_info)
15340 {
15341 MRN_DBUG_ENTER_METHOD();
15342
15343 bool have_error = false;
15344
15345 mrn::PathMapper mapper(share->table_name);
15346 grn_obj *table_obj;
15347 table_obj = grn_ctx_get(ctx, mapper.table_name(), strlen(mapper.table_name()));
15348
15349 Alter_info *alter_info = ha_alter_info->alter_info;
15350 uint n_fields = table->s->fields;
15351 for (uint i = 0; i < n_fields; i++) {
15352 Field *field = table->field[i];
15353
15354 if (!(field->flags & FIELD_IS_RENAMED)) {
15355 continue;
15356 }
15357
15358 LEX_CSTRING new_name;
15359 new_name.str= 0;
15360 List_iterator_fast<Create_field> create_fields(alter_info->create_list);
15361 while (Create_field *create_field = create_fields++) {
15362 if (create_field->field == field) {
15363 new_name = create_field->field_name;
15364 break;
15365 }
15366 }
15367
15368 if (!new_name.str) {
15369 continue;
15370 }
15371
15372 const char *old_name = field->field_name.str;
15373 grn_obj *column_obj;
15374 column_obj = grn_obj_column(ctx, table_obj, old_name,
15375 field->field_name.length);
15376 if (column_obj) {
15377 grn_column_rename(ctx, column_obj, new_name.str, new_name.length);
15378 if (ctx->rc) {
15379 int error = ER_WRONG_COLUMN_NAME;
15380 my_message(error, ctx->errbuf, MYF(0));
15381 have_error = true;
15382 }
15383 grn_obj_unlink(ctx, column_obj);
15384 }
15385
15386 if (have_error) {
15387 break;
15388 }
15389 }
15390 grn_obj_unlink(ctx, table_obj);
15391
15392 DBUG_RETURN(have_error);
15393 }
15394
storage_inplace_alter_table(TABLE * altered_table,Alter_inplace_info * ha_alter_info)15395 bool ha_mroonga::storage_inplace_alter_table(
15396 TABLE *altered_table,
15397 Alter_inplace_info *ha_alter_info)
15398 {
15399 MRN_DBUG_ENTER_METHOD();
15400
15401 bool have_error = false;
15402
15403 int error = mrn_change_encoding(ctx, system_charset_info);
15404 if (error) {
15405 have_error = true;
15406 }
15407
15408 alter_table_operations drop_index_related_flags =
15409 ALTER_DROP_INDEX |
15410 ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX |
15411 ALTER_DROP_UNIQUE_INDEX |
15412 ALTER_DROP_PK_INDEX;
15413 if (!have_error &&
15414 (ha_alter_info->handler_flags & drop_index_related_flags)) {
15415 have_error = storage_inplace_alter_table_drop_index(altered_table,
15416 ha_alter_info);
15417 }
15418
15419 alter_table_operations add_column_related_flags =
15420 ALTER_ADD_COLUMN;
15421 if (!have_error &&
15422 (ha_alter_info->handler_flags & add_column_related_flags)) {
15423 have_error = storage_inplace_alter_table_add_column(altered_table, ha_alter_info);
15424 }
15425
15426 alter_table_operations drop_column_related_flags = ALTER_DROP_COLUMN;
15427 if (!have_error &&
15428 (ha_alter_info->handler_flags & drop_column_related_flags)) {
15429 have_error = storage_inplace_alter_table_drop_column(altered_table, ha_alter_info);
15430 }
15431
15432 alter_table_operations rename_column_related_flags = ALTER_COLUMN_NAME;
15433 if (!have_error &&
15434 (ha_alter_info->handler_flags & rename_column_related_flags)) {
15435 have_error = storage_inplace_alter_table_rename_column(altered_table, ha_alter_info);
15436 }
15437
15438 alter_table_operations add_index_related_flags =
15439 ALTER_ADD_INDEX |
15440 ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX |
15441 ALTER_ADD_UNIQUE_INDEX |
15442 ALTER_ADD_PK_INDEX;
15443 if (!have_error &&
15444 (ha_alter_info->handler_flags & add_index_related_flags)) {
15445 have_error = storage_inplace_alter_table_add_index(altered_table,
15446 ha_alter_info);
15447 }
15448
15449 DBUG_RETURN(have_error);
15450 }
15451
inplace_alter_table(TABLE * altered_table,Alter_inplace_info * ha_alter_info)15452 bool ha_mroonga::inplace_alter_table(
15453 TABLE *altered_table,
15454 Alter_inplace_info *ha_alter_info)
15455 {
15456 MRN_DBUG_ENTER_METHOD();
15457 bool result;
15458 if (share->wrapper_mode) {
15459 result = wrapper_inplace_alter_table(altered_table, ha_alter_info);
15460 } else {
15461 result = storage_inplace_alter_table(altered_table, ha_alter_info);
15462 }
15463 DBUG_RETURN(result);
15464 }
15465
wrapper_commit_inplace_alter_table(TABLE * altered_table,Alter_inplace_info * ha_alter_info,bool commit)15466 bool ha_mroonga::wrapper_commit_inplace_alter_table(
15467 TABLE *altered_table,
15468 Alter_inplace_info *ha_alter_info,
15469 bool commit)
15470 {
15471 bool result;
15472 MRN_DBUG_ENTER_METHOD();
15473 if (!alter_handler_flags) {
15474 free_root(&(wrap_altered_table_share->mem_root), MYF(0));
15475 my_free(alter_key_info_buffer);
15476 alter_key_info_buffer = NULL;
15477 DBUG_RETURN(false);
15478 }
15479 MRN_SET_WRAP_ALTER_KEY(this, ha_alter_info);
15480 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15481 MRN_SET_WRAP_TABLE_KEY(this, table);
15482 result = wrap_handler->ha_commit_inplace_alter_table(wrap_altered_table,
15483 ha_alter_info,
15484 commit);
15485 MRN_SET_BASE_ALTER_KEY(this, ha_alter_info);
15486 MRN_SET_BASE_SHARE_KEY(share, table->s);
15487 MRN_SET_BASE_TABLE_KEY(this, table);
15488 free_root(&(wrap_altered_table_share->mem_root), MYF(0));
15489 my_free(alter_key_info_buffer);
15490 alter_key_info_buffer = NULL;
15491 DBUG_RETURN(result);
15492 }
15493
storage_commit_inplace_alter_table(TABLE * altered_table,Alter_inplace_info * ha_alter_info,bool commit)15494 bool ha_mroonga::storage_commit_inplace_alter_table(
15495 TABLE *altered_table,
15496 Alter_inplace_info *ha_alter_info,
15497 bool commit)
15498 {
15499 MRN_DBUG_ENTER_METHOD();
15500 DBUG_RETURN(false);
15501 }
15502
commit_inplace_alter_table(TABLE * altered_table,Alter_inplace_info * ha_alter_info,bool commit)15503 bool ha_mroonga::commit_inplace_alter_table(
15504 TABLE *altered_table,
15505 Alter_inplace_info *ha_alter_info,
15506 bool commit)
15507 {
15508 MRN_DBUG_ENTER_METHOD();
15509 bool result;
15510 if (share->wrapper_mode) {
15511 result = wrapper_commit_inplace_alter_table(altered_table, ha_alter_info,
15512 commit);
15513 } else {
15514 result = storage_commit_inplace_alter_table(altered_table, ha_alter_info,
15515 commit);
15516 }
15517 DBUG_RETURN(result);
15518 }
15519
wrapper_notify_table_changed()15520 void ha_mroonga::wrapper_notify_table_changed()
15521 {
15522 MRN_DBUG_ENTER_METHOD();
15523 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15524 MRN_SET_WRAP_TABLE_KEY(this, table);
15525 wrap_handler->ha_notify_table_changed();
15526 MRN_SET_BASE_SHARE_KEY(share, table->s);
15527 MRN_SET_BASE_TABLE_KEY(this, table);
15528 DBUG_VOID_RETURN;
15529 }
15530
storage_notify_table_changed()15531 void ha_mroonga::storage_notify_table_changed()
15532 {
15533 MRN_DBUG_ENTER_METHOD();
15534 DBUG_VOID_RETURN;
15535 }
15536
notify_table_changed()15537 void ha_mroonga::notify_table_changed()
15538 {
15539 MRN_DBUG_ENTER_METHOD();
15540 if (share->wrapper_mode) {
15541 wrapper_notify_table_changed();
15542 } else {
15543 storage_notify_table_changed();
15544 }
15545 DBUG_VOID_RETURN;
15546 }
15547 #else
wrapper_alter_table_flags(alter_table_operations flags)15548 alter_table_operations ha_mroonga::wrapper_alter_table_flags(alter_table_operations flags)
15549 {
15550 alter_table_operations res;
15551 MRN_DBUG_ENTER_METHOD();
15552 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15553 MRN_SET_WRAP_TABLE_KEY(this, table);
15554 res = wrap_handler->alter_table_flags(flags);
15555 MRN_SET_BASE_SHARE_KEY(share, table->s);
15556 MRN_SET_BASE_TABLE_KEY(this, table);
15557 DBUG_RETURN(res);
15558 }
15559
storage_alter_table_flags(alter_table_operations flags)15560 alter_table_operations ha_mroonga::storage_alter_table_flags(alter_table_operations flags)
15561 {
15562 MRN_DBUG_ENTER_METHOD();
15563 alter_table_operations res = handler::alter_table_flags(flags);
15564 DBUG_RETURN(res);
15565 }
15566
alter_table_flags(alter_table_operations flags)15567 alter_table_operations ha_mroonga::alter_table_flags(alter_table_operations flags)
15568 {
15569 MRN_DBUG_ENTER_METHOD();
15570 alter_table_operations res;
15571 if (share->wrapper_mode)
15572 {
15573 res = wrapper_alter_table_flags(flags);
15574 } else {
15575 res = storage_alter_table_flags(flags);
15576 }
15577 DBUG_RETURN(res);
15578 }
15579
15580 #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
wrapper_add_index(TABLE * table_arg,KEY * key_info,uint num_of_keys,handler_add_index ** add)15581 int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info,
15582 uint num_of_keys, handler_add_index **add)
15583 #else
15584 int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info,
15585 uint num_of_keys)
15586 #endif
15587 {
15588 int error = 0;
15589 uint i, j, k;
15590 uint n_keys = table->s->keys;
15591 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, num_of_keys + n_keys);
15592 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, num_of_keys + n_keys);
15593 THD *thd = ha_thd();
15594 MRN_SHARE *tmp_share;
15595 TABLE_SHARE tmp_table_share;
15596 char **key_tokenizer;
15597 uint *key_tokenizer_length;
15598 MRN_DBUG_ENTER_METHOD();
15599 if (!(wrap_alter_key_info = (KEY *) mrn_my_malloc(sizeof(KEY) * num_of_keys,
15600 MYF(MY_WME)))) {
15601 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15602 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15603 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
15604 }
15605 KEY *p_key_info = &table->key_info[table_share->primary_key], *tmp_key_info;
15606 tmp_table_share.keys = n_keys + num_of_keys;
15607 tmp_table_share.fields = 0;
15608 if (!(tmp_share = (MRN_SHARE *)
15609 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
15610 &tmp_share, sizeof(*tmp_share),
15611 &key_tokenizer, sizeof(char *) * (n_keys + num_of_keys),
15612 &key_tokenizer_length, sizeof(uint) * (n_keys + num_of_keys),
15613 NullS))
15614 ) {
15615 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15616 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15617 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
15618 }
15619 tmp_share->engine = NULL;
15620 tmp_share->table_share = &tmp_table_share;
15621 tmp_share->index_table = NULL;
15622 tmp_share->index_table_length = NULL;
15623 tmp_share->key_tokenizer = key_tokenizer;
15624 tmp_share->key_tokenizer_length = key_tokenizer_length;
15625 tmp_share->col_flags = NULL;
15626 tmp_share->col_type = NULL;
15627 #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15628 hnd_add_index = NULL;
15629 #endif
15630 bitmap_clear_all(table->read_set);
15631 mrn_set_bitmap_by_key(table->read_set, p_key_info);
15632 mrn::PathMapper mapper(share->table_name);
15633 for (i = 0, j = 0; i < num_of_keys; i++) {
15634 if (!(key_info[i].flags & HA_FULLTEXT) && !mrn_is_geo_key(&key_info[i])) {
15635 wrap_alter_key_info[j] = key_info[i];
15636 j++;
15637 continue;
15638 }
15639 if (share->disable_keys) {
15640 continue;
15641 }
15642 if ((error = mrn_add_index_param(tmp_share, &key_info[i], i + n_keys)))
15643 {
15644 break;
15645 }
15646 index_tables[i + n_keys] = NULL;
15647 if (
15648 (key_info[i].flags & HA_FULLTEXT) &&
15649 (error = wrapper_create_index_fulltext(mapper.table_name(),
15650 i + n_keys,
15651 &key_info[i], index_tables, NULL,
15652 tmp_share))
15653 ) {
15654 break;
15655 } else if (
15656 mrn_is_geo_key(&key_info[i]) &&
15657 (error = wrapper_create_index_geo(mapper.table_name(),
15658 i + n_keys, &key_info[i],
15659 index_tables, NULL, tmp_share))
15660 ) {
15661 break;
15662 }
15663 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
15664 }
15665 if (!error && i > j && !share->disable_keys) {
15666 for (k = 0; k < num_of_keys; k++) {
15667 tmp_key_info = &key_info[k];
15668 if (!(tmp_key_info->flags & HA_FULLTEXT) &&
15669 !mrn_is_geo_key(tmp_key_info)) {
15670 continue;
15671 }
15672 index_columns[k + n_keys] = grn_obj_column(ctx,
15673 index_tables[k + n_keys],
15674 INDEX_COLUMN_NAME,
15675 strlen(INDEX_COLUMN_NAME));
15676 }
15677 error = wrapper_fill_indexes(thd, key_info, &index_columns[n_keys],
15678 num_of_keys);
15679 }
15680 bitmap_set_all(table->read_set);
15681
15682 if (!error && j)
15683 {
15684 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15685 MRN_SET_WRAP_TABLE_KEY(this, table);
15686 #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15687 error = wrap_handler->add_index(table_arg, wrap_alter_key_info, j,
15688 &hnd_add_index);
15689 #else
15690 error = wrap_handler->add_index(table_arg, wrap_alter_key_info, j);
15691 #endif
15692 MRN_SET_BASE_SHARE_KEY(share, table->s);
15693 MRN_SET_BASE_TABLE_KEY(this, table);
15694 }
15695 if (error)
15696 {
15697 for (k = 0; k < i; k++) {
15698 if (!(key_info[k].flags & HA_FULLTEXT) && !mrn_is_geo_key(&key_info[k]))
15699 {
15700 continue;
15701 }
15702 if (index_tables[k + n_keys])
15703 {
15704 grn_obj_remove(ctx, index_tables[k + n_keys]);
15705 }
15706 }
15707 }
15708 #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15709 else {
15710 *add = new handler_add_index(table_arg, key_info, num_of_keys);
15711 }
15712 #endif
15713 mrn_free_share_alloc(tmp_share);
15714 my_free(tmp_share);
15715 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15716 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15717 DBUG_RETURN(error);
15718 }
15719
15720 #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
storage_add_index(TABLE * table_arg,KEY * key_info,uint num_of_keys,handler_add_index ** add)15721 int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info,
15722 uint num_of_keys, handler_add_index **add)
15723 #else
15724 int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info,
15725 uint num_of_keys)
15726 #endif
15727 {
15728 int error = 0;
15729 uint i;
15730 uint n_keys = table->s->keys;
15731 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, num_of_keys + n_keys);
15732 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, num_of_keys + n_keys);
15733 MRN_SHARE *tmp_share;
15734 TABLE_SHARE tmp_table_share;
15735 char **index_table, **key_tokenizer, **col_flags, **col_type;
15736 uint *index_table_length, *key_tokenizer_length, *col_flags_length, *col_type_length;
15737 bool have_multiple_column_index = false;
15738
15739 MRN_DBUG_ENTER_METHOD();
15740 tmp_table_share.keys = n_keys + num_of_keys;
15741 tmp_table_share.fields = 0;
15742 if (!(tmp_share = (MRN_SHARE *)
15743 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
15744 &tmp_share, sizeof(*tmp_share),
15745 &index_table, sizeof(char*) * tmp_table_share.keys,
15746 &index_table_length, sizeof(uint) * tmp_table_share.keys,
15747 &key_tokenizer, sizeof(char *) * tmp_table_share.keys,
15748 &key_tokenizer_length, sizeof(uint) * tmp_table_share.keys,
15749 &col_flags, sizeof(char *) * tmp_table_share.fields,
15750 &col_flags_length, sizeof(uint) * tmp_table_share.fields,
15751 &col_type, sizeof(char *) * tmp_table_share.fields,
15752 &col_type_length, sizeof(uint) * tmp_table_share.fields,
15753 NullS))
15754 ) {
15755 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15756 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15757 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
15758 }
15759 tmp_share->engine = NULL;
15760 tmp_share->table_share = &tmp_table_share;
15761 tmp_share->index_table = index_table;
15762 tmp_share->index_table_length = index_table_length;
15763 tmp_share->key_tokenizer = key_tokenizer;
15764 tmp_share->key_tokenizer_length = key_tokenizer_length;
15765 tmp_share->col_flags = col_flags;
15766 tmp_share->col_flags_length = col_flags_length;
15767 tmp_share->col_type = col_type;
15768 tmp_share->col_type_length = col_type_length;
15769 bitmap_clear_all(table->read_set);
15770 mrn::PathMapper mapper(share->table_name);
15771 for (i = 0; i < num_of_keys; i++) {
15772 if (share->disable_keys && !(key_info[i].flags & HA_NOSAME)) {
15773 continue; // key is disabled
15774 }
15775 index_tables[i + n_keys] = NULL;
15776 index_columns[i + n_keys] = NULL;
15777 if ((error = mrn_add_index_param(tmp_share, &key_info[i], i + n_keys)))
15778 {
15779 break;
15780 }
15781 if ((error = storage_create_index(table, mapper.table_name(), grn_table,
15782 tmp_share, &key_info[i], index_tables,
15783 index_columns, i + n_keys)))
15784 {
15785 break;
15786 }
15787 if (
15788 KEY_N_KEY_PARTS(&(key_info[i])) == 1 &&
15789 (key_info[i].flags & HA_NOSAME) &&
15790 grn_table_size(ctx, grn_table) !=
15791 grn_table_size(ctx, index_tables[i + n_keys])
15792 ) {
15793 error = HA_ERR_FOUND_DUPP_UNIQUE;
15794 i++;
15795 break;
15796 }
15797 if (
15798 KEY_N_KEY_PARTS(&(key_info[i])) != 1 &&
15799 !(key_info[i].flags & HA_FULLTEXT)
15800 ) {
15801 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
15802 have_multiple_column_index = true;
15803 }
15804 }
15805 if (!error && have_multiple_column_index)
15806 {
15807 error = storage_add_index_multiple_columns(key_info, num_of_keys,
15808 index_tables + n_keys,
15809 index_columns + n_keys, false);
15810 }
15811 bitmap_set_all(table->read_set);
15812 if (error)
15813 {
15814 for (uint j = 0; j < i; j++) {
15815 if (index_tables[j + n_keys])
15816 {
15817 grn_obj_remove(ctx, index_columns[j + n_keys]);
15818 grn_obj_remove(ctx, index_tables[j + n_keys]);
15819 }
15820 }
15821 }
15822 #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15823 else {
15824 *add = new handler_add_index(table_arg, key_info, num_of_keys);
15825 }
15826 #endif
15827 mrn_free_share_alloc(tmp_share);
15828 my_free(tmp_share);
15829 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15830 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15831 DBUG_RETURN(error);
15832 }
15833 #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
add_index(TABLE * table_arg,KEY * key_info,uint num_of_keys,handler_add_index ** add)15834 int ha_mroonga::add_index(TABLE *table_arg, KEY *key_info,
15835 uint num_of_keys, handler_add_index **add)
15836 {
15837 MRN_DBUG_ENTER_METHOD();
15838 int error;
15839 if (share->wrapper_mode)
15840 {
15841 error = wrapper_add_index(table_arg, key_info, num_of_keys, add);
15842 } else {
15843 error = storage_add_index(table_arg, key_info, num_of_keys, add);
15844 }
15845 DBUG_RETURN(error);
15846 }
15847 #else
add_index(TABLE * table_arg,KEY * key_info,uint num_of_keys)15848 int ha_mroonga::add_index(TABLE *table_arg, KEY *key_info,
15849 uint num_of_keys)
15850 {
15851 MRN_DBUG_ENTER_METHOD();
15852 int error;
15853 if (share->wrapper_mode)
15854 {
15855 error = wrapper_add_index(table_arg, key_info, num_of_keys);
15856 } else {
15857 error = storage_add_index(table_arg, key_info, num_of_keys);
15858 }
15859 DBUG_RETURN(error);
15860 }
15861 #endif
15862
15863 #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
wrapper_final_add_index(handler_add_index * add,bool commit)15864 int ha_mroonga::wrapper_final_add_index(handler_add_index *add, bool commit)
15865 {
15866 int error = 0;
15867 MRN_DBUG_ENTER_METHOD();
15868 if (hnd_add_index)
15869 {
15870 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15871 MRN_SET_WRAP_TABLE_KEY(this, table);
15872 error = wrap_handler->final_add_index(hnd_add_index, commit);
15873 MRN_SET_BASE_SHARE_KEY(share, table->s);
15874 MRN_SET_BASE_TABLE_KEY(this, table);
15875 }
15876 if (add)
15877 {
15878 delete add;
15879 }
15880 DBUG_RETURN(error);
15881 }
15882
storage_final_add_index(handler_add_index * add,bool commit)15883 int ha_mroonga::storage_final_add_index(handler_add_index *add, bool commit)
15884 {
15885 MRN_DBUG_ENTER_METHOD();
15886 if (add)
15887 {
15888 delete add;
15889 }
15890 DBUG_RETURN(0);
15891 }
15892
final_add_index(handler_add_index * add,bool commit)15893 int ha_mroonga::final_add_index(handler_add_index *add, bool commit)
15894 {
15895 MRN_DBUG_ENTER_METHOD();
15896 int error;
15897 if (share->wrapper_mode)
15898 {
15899 error = wrapper_final_add_index(add, commit);
15900 } else {
15901 error = storage_final_add_index(add, commit);
15902 }
15903 DBUG_RETURN(error);
15904 }
15905 #endif
15906
wrapper_prepare_drop_index(TABLE * table_arg,uint * key_num,uint num_of_keys)15907 int ha_mroonga::wrapper_prepare_drop_index(TABLE *table_arg, uint *key_num,
15908 uint num_of_keys)
15909 {
15910 int res = 0;
15911 uint i, j;
15912 KEY *key_info = table_share->key_info;
15913 MRN_DBUG_ENTER_METHOD();
15914 res = mrn_change_encoding(ctx, system_charset_info);
15915 if (res)
15916 DBUG_RETURN(res);
15917
15918 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(uint, wrap_key_num, num_of_keys);
15919 for (i = 0, j = 0; i < num_of_keys; i++) {
15920 uint key_index = key_num[i];
15921 if (!(key_info[key_index].flags & HA_FULLTEXT) &&
15922 !mrn_is_geo_key(&key_info[key_index])) {
15923 wrap_key_num[j] = share->wrap_key_nr[key_index];
15924 j++;
15925 continue;
15926 }
15927
15928 res = drop_index(share, key_index);
15929 if (res)
15930 DBUG_RETURN(res);
15931 grn_index_tables[key_index] = NULL;
15932 grn_index_columns[key_index] = NULL;
15933 }
15934 if (j)
15935 {
15936 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15937 MRN_SET_WRAP_TABLE_KEY(this, table);
15938 res = wrap_handler->prepare_drop_index(table_arg, wrap_key_num, j);
15939 MRN_SET_BASE_SHARE_KEY(share, table->s);
15940 MRN_SET_BASE_TABLE_KEY(this, table);
15941 }
15942 MRN_FREE_VARIABLE_LENGTH_ARRAYS(wrap_key_num);
15943 DBUG_RETURN(res);
15944 }
15945
storage_prepare_drop_index(TABLE * table_arg,uint * key_num,uint num_of_keys)15946 int ha_mroonga::storage_prepare_drop_index(TABLE *table_arg, uint *key_num,
15947 uint num_of_keys)
15948 {
15949 int error;
15950 uint i;
15951 MRN_DBUG_ENTER_METHOD();
15952 error = mrn_change_encoding(ctx, system_charset_info);
15953 if (error)
15954 DBUG_RETURN(error);
15955
15956 for (i = 0; i < num_of_keys; i++) {
15957 uint key_index = key_num[i];
15958 error = drop_index(share, key_index);
15959 if (error)
15960 break;
15961 grn_index_tables[key_index] = NULL;
15962 grn_index_columns[key_index] = NULL;
15963 }
15964 DBUG_RETURN(error);
15965 }
15966
prepare_drop_index(TABLE * table_arg,uint * key_num,uint num_of_keys)15967 int ha_mroonga::prepare_drop_index(TABLE *table_arg, uint *key_num,
15968 uint num_of_keys)
15969 {
15970 MRN_DBUG_ENTER_METHOD();
15971 int res;
15972 if (share->wrapper_mode)
15973 {
15974 res = wrapper_prepare_drop_index(table_arg, key_num, num_of_keys);
15975 } else {
15976 res = storage_prepare_drop_index(table_arg, key_num, num_of_keys);
15977 }
15978 DBUG_RETURN(res);
15979 }
15980
wrapper_final_drop_index(TABLE * table_arg)15981 int ha_mroonga::wrapper_final_drop_index(TABLE *table_arg)
15982 {
15983 uint res;
15984 MRN_DBUG_ENTER_METHOD();
15985 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15986 MRN_SET_WRAP_TABLE_KEY(this, table);
15987 res = wrap_handler->final_drop_index(table_arg);
15988 MRN_SET_BASE_SHARE_KEY(share, table->s);
15989 MRN_SET_BASE_TABLE_KEY(this, table);
15990 DBUG_RETURN(res);
15991 }
15992
storage_final_drop_index(TABLE * table_arg)15993 int ha_mroonga::storage_final_drop_index(TABLE *table_arg)
15994 {
15995 MRN_DBUG_ENTER_METHOD();
15996 DBUG_RETURN(0);
15997 }
15998
final_drop_index(TABLE * table_arg)15999 int ha_mroonga::final_drop_index(TABLE *table_arg)
16000 {
16001 MRN_DBUG_ENTER_METHOD();
16002 uint res;
16003 if (share->wrapper_mode)
16004 {
16005 res = wrapper_final_drop_index(table_arg);
16006 } else {
16007 res = storage_final_drop_index(table_arg);
16008 }
16009 DBUG_RETURN(res);
16010 }
16011 #endif
16012
wrapper_update_auto_increment()16013 int ha_mroonga::wrapper_update_auto_increment()
16014 {
16015 int res;
16016 MRN_DBUG_ENTER_METHOD();
16017 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16018 MRN_SET_WRAP_TABLE_KEY(this, table);
16019 res = wrap_handler->update_auto_increment();
16020 MRN_SET_BASE_SHARE_KEY(share, table->s);
16021 MRN_SET_BASE_TABLE_KEY(this, table);
16022 DBUG_RETURN(res);
16023 }
16024
storage_update_auto_increment()16025 int ha_mroonga::storage_update_auto_increment()
16026 {
16027 MRN_DBUG_ENTER_METHOD();
16028 int res = handler::update_auto_increment();
16029 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
16030 table->next_number_field->val_int()));
16031 DBUG_RETURN(res);
16032 }
16033
update_auto_increment()16034 int ha_mroonga::update_auto_increment()
16035 {
16036 MRN_DBUG_ENTER_METHOD();
16037 int res;
16038 if (share->wrapper_mode)
16039 {
16040 res = wrapper_update_auto_increment();
16041 } else {
16042 res = storage_update_auto_increment();
16043 }
16044 DBUG_RETURN(res);
16045 }
16046
wrapper_set_next_insert_id(ulonglong id)16047 void ha_mroonga::wrapper_set_next_insert_id(ulonglong id)
16048 {
16049 MRN_DBUG_ENTER_METHOD();
16050 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16051 MRN_SET_WRAP_TABLE_KEY(this, table);
16052 wrap_handler->set_next_insert_id(id);
16053 MRN_SET_BASE_SHARE_KEY(share, table->s);
16054 MRN_SET_BASE_TABLE_KEY(this, table);
16055 DBUG_VOID_RETURN;
16056 }
16057
storage_set_next_insert_id(ulonglong id)16058 void ha_mroonga::storage_set_next_insert_id(ulonglong id)
16059 {
16060 MRN_DBUG_ENTER_METHOD();
16061 handler::set_next_insert_id(id);
16062 DBUG_VOID_RETURN;
16063 }
16064
set_next_insert_id(ulonglong id)16065 void ha_mroonga::set_next_insert_id(ulonglong id)
16066 {
16067 MRN_DBUG_ENTER_METHOD();
16068 if (share->wrapper_mode)
16069 {
16070 wrapper_set_next_insert_id(id);
16071 } else {
16072 storage_set_next_insert_id(id);
16073 }
16074 DBUG_VOID_RETURN;
16075 }
16076
wrapper_get_auto_increment(ulonglong offset,ulonglong increment,ulonglong nb_desired_values,ulonglong * first_value,ulonglong * nb_reserved_values)16077 void ha_mroonga::wrapper_get_auto_increment(ulonglong offset,
16078 ulonglong increment,
16079 ulonglong nb_desired_values,
16080 ulonglong *first_value,
16081 ulonglong *nb_reserved_values)
16082 {
16083 MRN_DBUG_ENTER_METHOD();
16084 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16085 MRN_SET_WRAP_TABLE_KEY(this, table);
16086 wrap_handler->get_auto_increment(offset, increment, nb_desired_values,
16087 first_value, nb_reserved_values);
16088 MRN_SET_BASE_SHARE_KEY(share, table->s);
16089 MRN_SET_BASE_TABLE_KEY(this, table);
16090 DBUG_VOID_RETURN;
16091 }
16092
storage_get_auto_increment(ulonglong offset,ulonglong increment,ulonglong nb_desired_values,ulonglong * first_value,ulonglong * nb_reserved_values)16093 void ha_mroonga::storage_get_auto_increment(ulonglong offset,
16094 ulonglong increment,
16095 ulonglong nb_desired_values,
16096 ulonglong *first_value,
16097 ulonglong *nb_reserved_values)
16098 {
16099 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
16100 MRN_DBUG_ENTER_METHOD();
16101 if (table->found_next_number_field &&
16102 !table->s->next_number_keypart) {
16103 if (long_term_share->auto_inc_inited) {
16104 *first_value = long_term_share->auto_inc_value;
16105 DBUG_PRINT("info", ("mroonga: *first_value(auto_inc_value)=%llu",
16106 *first_value));
16107 *nb_reserved_values = UINT_MAX64;
16108 } else {
16109 handler::get_auto_increment(offset, increment, nb_desired_values,
16110 first_value, nb_reserved_values);
16111 long_term_share->auto_inc_value = *first_value;
16112 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
16113 long_term_share->auto_inc_value));
16114 long_term_share->auto_inc_inited = true;
16115 }
16116 } else {
16117 handler::get_auto_increment(offset, increment, nb_desired_values,
16118 first_value, nb_reserved_values);
16119 }
16120 DBUG_VOID_RETURN;
16121 }
16122
get_auto_increment(ulonglong offset,ulonglong increment,ulonglong nb_desired_values,ulonglong * first_value,ulonglong * nb_reserved_values)16123 void ha_mroonga::get_auto_increment(ulonglong offset, ulonglong increment,
16124 ulonglong nb_desired_values,
16125 ulonglong *first_value,
16126 ulonglong *nb_reserved_values)
16127 {
16128 MRN_DBUG_ENTER_METHOD();
16129 if (share->wrapper_mode)
16130 {
16131 wrapper_get_auto_increment(offset, increment, nb_desired_values,
16132 first_value, nb_reserved_values);
16133 } else {
16134 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
16135 mrn::Lock lock(&long_term_share->auto_inc_mutex);
16136 storage_get_auto_increment(offset, increment, nb_desired_values,
16137 first_value, nb_reserved_values);
16138 long_term_share->auto_inc_value += nb_desired_values * increment;
16139 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
16140 long_term_share->auto_inc_value));
16141 }
16142 DBUG_VOID_RETURN;
16143 }
16144
wrapper_restore_auto_increment(ulonglong prev_insert_id)16145 void ha_mroonga::wrapper_restore_auto_increment(ulonglong prev_insert_id)
16146 {
16147 MRN_DBUG_ENTER_METHOD();
16148 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16149 MRN_SET_WRAP_TABLE_KEY(this, table);
16150 wrap_handler->restore_auto_increment(prev_insert_id);
16151 MRN_SET_BASE_SHARE_KEY(share, table->s);
16152 MRN_SET_BASE_TABLE_KEY(this, table);
16153 DBUG_VOID_RETURN;
16154 }
16155
storage_restore_auto_increment(ulonglong prev_insert_id)16156 void ha_mroonga::storage_restore_auto_increment(ulonglong prev_insert_id)
16157 {
16158 MRN_DBUG_ENTER_METHOD();
16159 handler::restore_auto_increment(prev_insert_id);
16160 DBUG_VOID_RETURN;
16161 }
16162
restore_auto_increment(ulonglong prev_insert_id)16163 void ha_mroonga::restore_auto_increment(ulonglong prev_insert_id)
16164 {
16165 MRN_DBUG_ENTER_METHOD();
16166 if (share->wrapper_mode)
16167 {
16168 wrapper_restore_auto_increment(prev_insert_id);
16169 } else {
16170 storage_restore_auto_increment(prev_insert_id);
16171 }
16172 DBUG_VOID_RETURN;
16173 }
16174
wrapper_release_auto_increment()16175 void ha_mroonga::wrapper_release_auto_increment()
16176 {
16177 MRN_DBUG_ENTER_METHOD();
16178 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16179 MRN_SET_WRAP_TABLE_KEY(this, table);
16180 wrap_handler->ha_release_auto_increment();
16181 MRN_SET_BASE_SHARE_KEY(share, table->s);
16182 MRN_SET_BASE_TABLE_KEY(this, table);
16183 DBUG_VOID_RETURN;
16184 }
16185
storage_release_auto_increment()16186 void ha_mroonga::storage_release_auto_increment()
16187 {
16188 MRN_DBUG_ENTER_METHOD();
16189 DBUG_VOID_RETURN;
16190 }
16191
release_auto_increment()16192 void ha_mroonga::release_auto_increment()
16193 {
16194 MRN_DBUG_ENTER_METHOD();
16195 if (share->wrapper_mode)
16196 {
16197 wrapper_release_auto_increment();
16198 } else {
16199 storage_release_auto_increment();
16200 }
16201 DBUG_VOID_RETURN;
16202 }
16203
wrapper_check_for_upgrade(HA_CHECK_OPT * check_opt)16204 int ha_mroonga::wrapper_check_for_upgrade(HA_CHECK_OPT *check_opt)
16205 {
16206 MRN_DBUG_ENTER_METHOD();
16207 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16208 MRN_SET_WRAP_TABLE_KEY(this, table);
16209 int error = wrap_handler->ha_check_for_upgrade(check_opt);
16210 MRN_SET_BASE_SHARE_KEY(share, table->s);
16211 MRN_SET_BASE_TABLE_KEY(this, table);
16212 DBUG_RETURN(error);
16213 }
16214
storage_check_for_upgrade(HA_CHECK_OPT * check_opt)16215 int ha_mroonga::storage_check_for_upgrade(HA_CHECK_OPT *check_opt)
16216 {
16217 MRN_DBUG_ENTER_METHOD();
16218 for (uint i = 0; i < table->s->fields; ++i) {
16219 grn_obj *column = grn_columns[i];
16220 if (!column) {
16221 continue;
16222 }
16223 Field *field = table->field[i];
16224 grn_id column_range = grn_obj_get_range(ctx, column);
16225 switch (field->real_type()) {
16226 case MYSQL_TYPE_ENUM:
16227 if (column_range != GRN_DB_UINT16) {
16228 DBUG_RETURN(HA_ADMIN_NEEDS_ALTER);
16229 }
16230 break;
16231 case MYSQL_TYPE_SET:
16232 if (column_range != GRN_DB_UINT64) {
16233 DBUG_RETURN(HA_ADMIN_NEEDS_ALTER);
16234 }
16235 break;
16236 default:
16237 break;
16238 }
16239 }
16240 DBUG_RETURN(HA_ADMIN_OK);
16241 }
16242
check_for_upgrade(HA_CHECK_OPT * check_opt)16243 int ha_mroonga::check_for_upgrade(HA_CHECK_OPT *check_opt)
16244 {
16245 MRN_DBUG_ENTER_METHOD();
16246 int error;
16247 if (share->wrapper_mode) {
16248 error = wrapper_check_for_upgrade(check_opt);
16249 } else {
16250 error = storage_check_for_upgrade(check_opt);
16251 }
16252 DBUG_RETURN(error);
16253 }
16254
16255 #ifdef MRN_HANDLER_HAVE_RESET_AUTO_INCREMENT
wrapper_reset_auto_increment(ulonglong value)16256 int ha_mroonga::wrapper_reset_auto_increment(ulonglong value)
16257 {
16258 int res;
16259 MRN_DBUG_ENTER_METHOD();
16260 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16261 MRN_SET_WRAP_TABLE_KEY(this, table);
16262 res = wrap_handler->ha_reset_auto_increment(value);
16263 MRN_SET_BASE_SHARE_KEY(share, table->s);
16264 MRN_SET_BASE_TABLE_KEY(this, table);
16265 DBUG_RETURN(res);
16266 }
16267
storage_reset_auto_increment(ulonglong value)16268 int ha_mroonga::storage_reset_auto_increment(ulonglong value)
16269 {
16270 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
16271 MRN_DBUG_ENTER_METHOD();
16272 mrn::Lock lock(&long_term_share->auto_inc_mutex);
16273 long_term_share->auto_inc_value = value;
16274 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
16275 long_term_share->auto_inc_value));
16276 long_term_share->auto_inc_inited = true;
16277 DBUG_RETURN(0);
16278 }
16279
reset_auto_increment(ulonglong value)16280 int ha_mroonga::reset_auto_increment(ulonglong value)
16281 {
16282 MRN_DBUG_ENTER_METHOD();
16283 int res;
16284 if (share->wrapper_mode)
16285 {
16286 res = wrapper_reset_auto_increment(value);
16287 } else {
16288 res = storage_reset_auto_increment(value);
16289 }
16290 DBUG_RETURN(res);
16291 }
16292 #endif
16293
set_pk_bitmap()16294 void ha_mroonga::set_pk_bitmap()
16295 {
16296 MRN_DBUG_ENTER_METHOD();
16297 KEY *key_info = &(table->key_info[table_share->primary_key]);
16298 uint j;
16299 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
16300 Field *field = key_info->key_part[j].field;
16301 bitmap_set_bit(table->read_set, field->field_index);
16302 }
16303 DBUG_VOID_RETURN;
16304 }
16305
wrapper_was_semi_consistent_read()16306 bool ha_mroonga::wrapper_was_semi_consistent_read()
16307 {
16308 bool res;
16309 MRN_DBUG_ENTER_METHOD();
16310 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16311 MRN_SET_WRAP_TABLE_KEY(this, table);
16312 res = wrap_handler->was_semi_consistent_read();
16313 MRN_SET_BASE_SHARE_KEY(share, table->s);
16314 MRN_SET_BASE_TABLE_KEY(this, table);
16315 DBUG_RETURN(res);
16316 }
16317
storage_was_semi_consistent_read()16318 bool ha_mroonga::storage_was_semi_consistent_read()
16319 {
16320 bool res;
16321 MRN_DBUG_ENTER_METHOD();
16322 res = handler::was_semi_consistent_read();
16323 DBUG_RETURN(res);
16324 }
16325
was_semi_consistent_read()16326 bool ha_mroonga::was_semi_consistent_read()
16327 {
16328 bool res;
16329 MRN_DBUG_ENTER_METHOD();
16330 if (share->wrapper_mode)
16331 {
16332 res = wrapper_was_semi_consistent_read();
16333 } else {
16334 res = storage_was_semi_consistent_read();
16335 }
16336 DBUG_RETURN(res);
16337 }
16338
wrapper_try_semi_consistent_read(bool yes)16339 void ha_mroonga::wrapper_try_semi_consistent_read(bool yes)
16340 {
16341 MRN_DBUG_ENTER_METHOD();
16342 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16343 MRN_SET_WRAP_TABLE_KEY(this, table);
16344 wrap_handler->try_semi_consistent_read(yes);
16345 MRN_SET_BASE_SHARE_KEY(share, table->s);
16346 MRN_SET_BASE_TABLE_KEY(this, table);
16347 DBUG_VOID_RETURN;
16348 }
16349
storage_try_semi_consistent_read(bool yes)16350 void ha_mroonga::storage_try_semi_consistent_read(bool yes)
16351 {
16352 MRN_DBUG_ENTER_METHOD();
16353 handler::try_semi_consistent_read(yes);
16354 DBUG_VOID_RETURN;
16355 }
16356
try_semi_consistent_read(bool yes)16357 void ha_mroonga::try_semi_consistent_read(bool yes)
16358 {
16359 MRN_DBUG_ENTER_METHOD();
16360 if (share->wrapper_mode)
16361 {
16362 wrapper_try_semi_consistent_read(yes);
16363 } else {
16364 storage_try_semi_consistent_read(yes);
16365 }
16366 DBUG_VOID_RETURN;
16367 }
16368
wrapper_unlock_row()16369 void ha_mroonga::wrapper_unlock_row()
16370 {
16371 MRN_DBUG_ENTER_METHOD();
16372 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16373 MRN_SET_WRAP_TABLE_KEY(this, table);
16374 wrap_handler->unlock_row();
16375 MRN_SET_BASE_SHARE_KEY(share, table->s);
16376 MRN_SET_BASE_TABLE_KEY(this, table);
16377 DBUG_VOID_RETURN;
16378 }
16379
storage_unlock_row()16380 void ha_mroonga::storage_unlock_row()
16381 {
16382 MRN_DBUG_ENTER_METHOD();
16383 handler::unlock_row();
16384 DBUG_VOID_RETURN;
16385 }
16386
unlock_row()16387 void ha_mroonga::unlock_row()
16388 {
16389 MRN_DBUG_ENTER_METHOD();
16390 if (share->wrapper_mode)
16391 {
16392 wrapper_unlock_row();
16393 } else {
16394 storage_unlock_row();
16395 }
16396 DBUG_VOID_RETURN;
16397 }
16398
wrapper_start_stmt(THD * thd,thr_lock_type lock_type)16399 int ha_mroonga::wrapper_start_stmt(THD *thd, thr_lock_type lock_type)
16400 {
16401 int res;
16402 MRN_DBUG_ENTER_METHOD();
16403 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16404 MRN_SET_WRAP_TABLE_KEY(this, table);
16405 res = wrap_handler->start_stmt(thd, lock_type);
16406 MRN_SET_BASE_SHARE_KEY(share, table->s);
16407 MRN_SET_BASE_TABLE_KEY(this, table);
16408 DBUG_RETURN(res);
16409 }
16410
storage_start_stmt(THD * thd,thr_lock_type lock_type)16411 int ha_mroonga::storage_start_stmt(THD *thd, thr_lock_type lock_type)
16412 {
16413 int res;
16414 MRN_DBUG_ENTER_METHOD();
16415 res = handler::start_stmt(thd, lock_type);
16416 DBUG_RETURN(res);
16417 }
16418
start_stmt(THD * thd,thr_lock_type lock_type)16419 int ha_mroonga::start_stmt(THD *thd, thr_lock_type lock_type)
16420 {
16421 int res;
16422 MRN_DBUG_ENTER_METHOD();
16423 if (share->wrapper_mode)
16424 {
16425 res = wrapper_start_stmt(thd, lock_type);
16426 } else {
16427 res = storage_start_stmt(thd, lock_type);
16428 }
16429 DBUG_RETURN(res);
16430 }
16431
wrapper_change_table_ptr(TABLE * table_arg,TABLE_SHARE * share_arg)16432 void ha_mroonga::wrapper_change_table_ptr(TABLE *table_arg,
16433 TABLE_SHARE *share_arg)
16434 {
16435 MRN_DBUG_ENTER_METHOD();
16436 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16437 MRN_SET_WRAP_TABLE_KEY(this, table);
16438 wrap_handler->change_table_ptr(table_arg, share->wrap_table_share);
16439 MRN_SET_BASE_SHARE_KEY(share, table->s);
16440 MRN_SET_BASE_TABLE_KEY(this, table);
16441 DBUG_VOID_RETURN;
16442 }
16443
storage_change_table_ptr(TABLE * table_arg,TABLE_SHARE * share_arg)16444 void ha_mroonga::storage_change_table_ptr(TABLE *table_arg,
16445 TABLE_SHARE *share_arg)
16446 {
16447 MRN_DBUG_ENTER_METHOD();
16448 DBUG_VOID_RETURN;
16449 }
16450
change_table_ptr(TABLE * table_arg,TABLE_SHARE * share_arg)16451 void ha_mroonga::change_table_ptr(TABLE *table_arg, TABLE_SHARE *share_arg)
16452 {
16453 MRN_DBUG_ENTER_METHOD();
16454 handler::change_table_ptr(table_arg, share_arg);
16455 if (share && share->wrapper_mode)
16456 {
16457 wrapper_change_table_ptr(table_arg, share_arg);
16458 } else {
16459 storage_change_table_ptr(table_arg, share_arg);
16460 }
16461 DBUG_VOID_RETURN;
16462 }
16463
wrapper_primary_key_is_clustered()16464 bool ha_mroonga::wrapper_primary_key_is_clustered()
16465 {
16466 MRN_DBUG_ENTER_METHOD();
16467 bool is_clustered;
16468 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16469 MRN_SET_WRAP_TABLE_KEY(this, table);
16470 is_clustered = wrap_handler->primary_key_is_clustered();
16471 MRN_SET_BASE_SHARE_KEY(share, table->s);
16472 MRN_SET_BASE_TABLE_KEY(this, table);
16473 DBUG_RETURN(is_clustered);
16474 }
16475
storage_primary_key_is_clustered()16476 bool ha_mroonga::storage_primary_key_is_clustered()
16477 {
16478 MRN_DBUG_ENTER_METHOD();
16479 bool is_clustered = handler::primary_key_is_clustered();
16480 DBUG_RETURN(is_clustered);
16481 }
16482
primary_key_is_clustered()16483 bool ha_mroonga::primary_key_is_clustered()
16484 {
16485 MRN_DBUG_ENTER_METHOD();
16486 bool is_clustered;
16487 if (share && share->wrapper_mode)
16488 {
16489 is_clustered = wrapper_primary_key_is_clustered();
16490 } else {
16491 is_clustered = storage_primary_key_is_clustered();
16492 }
16493 DBUG_RETURN(is_clustered);
16494 }
16495
wrapper_is_fk_defined_on_table_or_index(uint index)16496 bool ha_mroonga::wrapper_is_fk_defined_on_table_or_index(uint index)
16497 {
16498 MRN_DBUG_ENTER_METHOD();
16499 bool res;
16500 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16501 MRN_SET_WRAP_TABLE_KEY(this, table);
16502 res = wrap_handler->is_fk_defined_on_table_or_index(index);
16503 MRN_SET_BASE_SHARE_KEY(share, table->s);
16504 MRN_SET_BASE_TABLE_KEY(this, table);
16505 DBUG_RETURN(res);
16506 }
16507
storage_is_fk_defined_on_table_or_index(uint index)16508 bool ha_mroonga::storage_is_fk_defined_on_table_or_index(uint index)
16509 {
16510 MRN_DBUG_ENTER_METHOD();
16511 bool res = handler::is_fk_defined_on_table_or_index(index);
16512 DBUG_RETURN(res);
16513 }
16514
is_fk_defined_on_table_or_index(uint index)16515 bool ha_mroonga::is_fk_defined_on_table_or_index(uint index)
16516 {
16517 MRN_DBUG_ENTER_METHOD();
16518 bool res;
16519 if (share->wrapper_mode)
16520 {
16521 res = wrapper_is_fk_defined_on_table_or_index(index);
16522 } else {
16523 res = storage_is_fk_defined_on_table_or_index(index);
16524 }
16525 DBUG_RETURN(res);
16526 }
16527
wrapper_get_foreign_key_create_info()16528 char *ha_mroonga::wrapper_get_foreign_key_create_info()
16529 {
16530 MRN_DBUG_ENTER_METHOD();
16531 char *res;
16532 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16533 MRN_SET_WRAP_TABLE_KEY(this, table);
16534 res = wrap_handler->get_foreign_key_create_info();
16535 MRN_SET_BASE_SHARE_KEY(share, table->s);
16536 MRN_SET_BASE_TABLE_KEY(this, table);
16537 DBUG_RETURN(res);
16538 }
16539
16540 #ifdef MRN_SUPPORT_FOREIGN_KEYS
storage_get_foreign_key_create_info()16541 char *ha_mroonga::storage_get_foreign_key_create_info()
16542 {
16543 int error;
16544 uint i;
16545 grn_obj *column;
16546 uint n_columns = table_share->fields;
16547 char create_info_buff[2048], *create_info;
16548 String create_info_str(create_info_buff, sizeof(create_info_buff),
16549 system_charset_info);
16550 MRN_DBUG_ENTER_METHOD();
16551 create_info_str.length(0);
16552 for (i = 0; i < n_columns; ++i) {
16553 Field *field = table_share->field[i];
16554
16555 if (!is_foreign_key_field(table_share->table_name.str,
16556 field->field_name.str)) {
16557 continue;
16558 }
16559
16560 mrn::ColumnName column_name(field->field_name);
16561 column = grn_obj_column(ctx,
16562 grn_table,
16563 column_name.c_str(),
16564 column_name.length());
16565 if (!column) {
16566 continue;
16567 }
16568 grn_id ref_table_id = grn_obj_get_range(ctx, column);
16569 grn_obj *ref_table = grn_ctx_at(ctx, ref_table_id);
16570 char ref_table_buff[NAME_LEN + 1];
16571 int ref_table_name_length = grn_obj_name(ctx, ref_table, ref_table_buff,
16572 NAME_LEN);
16573 ref_table_buff[ref_table_name_length] = '\0';
16574
16575 if (create_info_str.reserve(15)) {
16576 DBUG_RETURN(NULL);
16577 }
16578 create_info_str.q_append(",\n CONSTRAINT ", 15);
16579 append_identifier(ha_thd(),
16580 &create_info_str,
16581 column_name.c_str(),
16582 column_name.length());
16583 if (create_info_str.reserve(14)) {
16584 DBUG_RETURN(NULL);
16585 }
16586 create_info_str.q_append(" FOREIGN KEY (", 14);
16587 append_identifier(ha_thd(),
16588 &create_info_str,
16589 column_name.c_str(),
16590 column_name.length());
16591 if (create_info_str.reserve(13)) {
16592 DBUG_RETURN(NULL);
16593 }
16594 create_info_str.q_append(") REFERENCES ", 13);
16595 append_identifier(ha_thd(), &create_info_str, table_share->db.str,
16596 table_share->db.length);
16597 if (create_info_str.reserve(1)) {
16598 DBUG_RETURN(NULL);
16599 }
16600 create_info_str.q_append(".", 1);
16601 append_identifier(ha_thd(), &create_info_str, ref_table_buff,
16602 ref_table_name_length);
16603 if (create_info_str.reserve(2)) {
16604 DBUG_RETURN(NULL);
16605 }
16606 create_info_str.q_append(" (", 2);
16607
16608 char ref_path[FN_REFLEN + 1];
16609 TABLE_LIST table_list;
16610 TABLE_SHARE *tmp_ref_table_share;
16611 build_table_filename(ref_path, sizeof(ref_path) - 1,
16612 table_share->db.str, ref_table_buff, "", 0);
16613 DBUG_PRINT("info", ("mroonga: ref_path=%s", ref_path));
16614
16615 LEX_CSTRING table_name= { ref_table_buff, (size_t) ref_table_name_length };
16616 table_list.init_one_table(&table_share->db, &table_name, 0, TL_WRITE);
16617 mrn_open_mutex_lock(table_share);
16618 tmp_ref_table_share =
16619 mrn_create_tmp_table_share(&table_list, ref_path, &error);
16620 mrn_open_mutex_unlock(table_share);
16621 if (!tmp_ref_table_share) {
16622 DBUG_RETURN(NULL);
16623 }
16624 uint ref_pkey_nr = tmp_ref_table_share->primary_key;
16625 KEY *ref_key_info = &tmp_ref_table_share->key_info[ref_pkey_nr];
16626 Field *ref_field = &ref_key_info->key_part->field[0];
16627 append_identifier(ha_thd(), &create_info_str, ref_field->field_name.str,
16628 ref_field->field_name.length);
16629 mrn_open_mutex_lock(table_share);
16630 mrn_free_tmp_table_share(tmp_ref_table_share);
16631 mrn_open_mutex_unlock(table_share);
16632 if (create_info_str.reserve(39)) {
16633 DBUG_RETURN(NULL);
16634 }
16635 create_info_str.q_append(") ON DELETE RESTRICT ON UPDATE RESTRICT", 39);
16636 }
16637 if (!(create_info = (char *) mrn_my_malloc(create_info_str.length() + 1,
16638 MYF(MY_WME)))) {
16639 DBUG_RETURN(NULL);
16640 }
16641 memcpy(create_info, create_info_str.ptr(), create_info_str.length());
16642 create_info[create_info_str.length()] = '\0';
16643 DBUG_RETURN(create_info);
16644 }
16645 #else
storage_get_foreign_key_create_info()16646 char *ha_mroonga::storage_get_foreign_key_create_info()
16647 {
16648 MRN_DBUG_ENTER_METHOD();
16649 char *res = handler::get_foreign_key_create_info();
16650 DBUG_RETURN(res);
16651 }
16652 #endif
16653
get_foreign_key_create_info()16654 char *ha_mroonga::get_foreign_key_create_info()
16655 {
16656 MRN_DBUG_ENTER_METHOD();
16657 char *res;
16658 if (share->wrapper_mode)
16659 {
16660 res = wrapper_get_foreign_key_create_info();
16661 } else {
16662 res = storage_get_foreign_key_create_info();
16663 }
16664 DBUG_RETURN(res);
16665 }
16666
16667 #ifdef MRN_HANDLER_HAVE_GET_TABLESPACE_NAME
wrapper_get_tablespace_name(THD * thd,char * name,uint name_len)16668 char *ha_mroonga::wrapper_get_tablespace_name(THD *thd, char *name,
16669 uint name_len)
16670 {
16671 MRN_DBUG_ENTER_METHOD();
16672 char *res;
16673 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16674 MRN_SET_WRAP_TABLE_KEY(this, table);
16675 res = wrap_handler->get_tablespace_name(thd, name, name_len);
16676 MRN_SET_BASE_SHARE_KEY(share, table->s);
16677 MRN_SET_BASE_TABLE_KEY(this, table);
16678 DBUG_RETURN(res);
16679 }
16680
storage_get_tablespace_name(THD * thd,char * name,uint name_len)16681 char *ha_mroonga::storage_get_tablespace_name(THD *thd, char *name,
16682 uint name_len)
16683 {
16684 MRN_DBUG_ENTER_METHOD();
16685 char *res = handler::get_tablespace_name(thd, name, name_len);
16686 DBUG_RETURN(res);
16687 }
16688
get_tablespace_name(THD * thd,char * name,uint name_len)16689 char *ha_mroonga::get_tablespace_name(THD *thd, char *name, uint name_len)
16690 {
16691 MRN_DBUG_ENTER_METHOD();
16692 char *res;
16693 if (share->wrapper_mode)
16694 {
16695 res = wrapper_get_tablespace_name(thd, name, name_len);
16696 } else {
16697 res = storage_get_tablespace_name(thd, name, name_len);
16698 }
16699 DBUG_RETURN(res);
16700 }
16701 #endif
16702
wrapper_can_switch_engines()16703 bool ha_mroonga::wrapper_can_switch_engines()
16704 {
16705 MRN_DBUG_ENTER_METHOD();
16706 bool res;
16707 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16708 MRN_SET_WRAP_TABLE_KEY(this, table);
16709 res = wrap_handler->can_switch_engines();
16710 MRN_SET_BASE_SHARE_KEY(share, table->s);
16711 MRN_SET_BASE_TABLE_KEY(this, table);
16712 DBUG_RETURN(res);
16713 }
16714
storage_can_switch_engines()16715 bool ha_mroonga::storage_can_switch_engines()
16716 {
16717 MRN_DBUG_ENTER_METHOD();
16718 bool res = handler::can_switch_engines();
16719 DBUG_RETURN(res);
16720 }
16721
can_switch_engines()16722 bool ha_mroonga::can_switch_engines()
16723 {
16724 MRN_DBUG_ENTER_METHOD();
16725 bool res;
16726 if (share->wrapper_mode)
16727 {
16728 res = wrapper_can_switch_engines();
16729 } else {
16730 res = storage_can_switch_engines();
16731 }
16732 DBUG_RETURN(res);
16733 }
16734
wrapper_get_foreign_key_list(THD * thd,List<FOREIGN_KEY_INFO> * f_key_list)16735 int ha_mroonga::wrapper_get_foreign_key_list(THD *thd,
16736 List<FOREIGN_KEY_INFO> *f_key_list)
16737 {
16738 MRN_DBUG_ENTER_METHOD();
16739 int res;
16740 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16741 MRN_SET_WRAP_TABLE_KEY(this, table);
16742 res = wrap_handler->get_foreign_key_list(thd, f_key_list);
16743 MRN_SET_BASE_SHARE_KEY(share, table->s);
16744 MRN_SET_BASE_TABLE_KEY(this, table);
16745 DBUG_RETURN(res);
16746 }
16747
16748 #ifdef MRN_SUPPORT_FOREIGN_KEYS
storage_get_foreign_key_list(THD * thd,List<FOREIGN_KEY_INFO> * f_key_list)16749 int ha_mroonga::storage_get_foreign_key_list(THD *thd,
16750 List<FOREIGN_KEY_INFO> *f_key_list)
16751 {
16752 int error;
16753 uint i;
16754 grn_obj *column;
16755 uint n_columns = table_share->fields;
16756 MRN_DBUG_ENTER_METHOD();
16757 for (i = 0; i < n_columns; ++i) {
16758 Field *field = table_share->field[i];
16759
16760 if (!is_foreign_key_field(table_share->table_name.str,
16761 field->field_name.str)) {
16762 continue;
16763 }
16764
16765 mrn::ColumnName column_name(field->field_name);
16766 column = grn_obj_column(ctx,
16767 grn_table,
16768 column_name.c_str(),
16769 column_name.length());
16770 if (!column) {
16771 continue;
16772 }
16773 grn_id ref_table_id = grn_obj_get_range(ctx, column);
16774 grn_obj *ref_table = grn_ctx_at(ctx, ref_table_id);
16775 FOREIGN_KEY_INFO f_key_info;
16776 f_key_info.foreign_id = thd_make_lex_string(thd,
16777 NULL,
16778 column_name.c_str(),
16779 column_name.length(),
16780 TRUE);
16781 f_key_info.foreign_db = thd_make_lex_string(thd, NULL,
16782 table_share->db.str,
16783 table_share->db.length,
16784 TRUE);
16785 f_key_info.foreign_table = thd_make_lex_string(thd, NULL,
16786 table_share->table_name.str,
16787 table_share->table_name.length,
16788 TRUE);
16789 f_key_info.referenced_db = f_key_info.foreign_db;
16790
16791 char ref_table_buff[NAME_LEN + 1];
16792 int ref_table_name_length = grn_obj_name(ctx, ref_table, ref_table_buff,
16793 NAME_LEN);
16794 ref_table_buff[ref_table_name_length] = '\0';
16795 DBUG_PRINT("info", ("mroonga: ref_table_buff=%s", ref_table_buff));
16796 DBUG_PRINT("info", ("mroonga: ref_table_name_length=%d", ref_table_name_length));
16797 f_key_info.referenced_table = thd_make_lex_string(thd, NULL,
16798 ref_table_buff,
16799 ref_table_name_length,
16800 TRUE);
16801 f_key_info.update_method = FK_OPTION_RESTRICT;
16802 f_key_info.delete_method = FK_OPTION_RESTRICT;
16803 f_key_info.referenced_key_name = thd_make_lex_string(thd, NULL, "PRIMARY",
16804 7, TRUE);
16805 LEX_CSTRING *field_name = thd_make_lex_string(thd,
16806 NULL,
16807 column_name.c_str(),
16808 column_name.length(),
16809 TRUE);
16810 f_key_info.foreign_fields.push_back(field_name);
16811
16812 char ref_path[FN_REFLEN + 1];
16813 TABLE_LIST table_list;
16814 TABLE_SHARE *tmp_ref_table_share;
16815 build_table_filename(ref_path, sizeof(ref_path) - 1,
16816 table_share->db.str, ref_table_buff, "", 0);
16817 DBUG_PRINT("info", ("mroonga: ref_path=%s", ref_path));
16818
16819 LEX_CSTRING table_name= { ref_table_buff, (size_t) ref_table_name_length };
16820 table_list.init_one_table(&table_share->db, &table_name, 0, TL_WRITE);
16821 mrn_open_mutex_lock(table_share);
16822 tmp_ref_table_share =
16823 mrn_create_tmp_table_share(&table_list, ref_path, &error);
16824 mrn_open_mutex_unlock(table_share);
16825 if (!tmp_ref_table_share) {
16826 DBUG_RETURN(error);
16827 }
16828 uint ref_pkey_nr = tmp_ref_table_share->primary_key;
16829 KEY *ref_key_info = &tmp_ref_table_share->key_info[ref_pkey_nr];
16830 Field *ref_field = &ref_key_info->key_part->field[0];
16831 LEX_CSTRING *ref_col_name = thd_make_lex_string(thd, NULL,
16832 ref_field->field_name.str,
16833 ref_field->field_name.length,
16834 TRUE);
16835 f_key_info.referenced_fields.push_back(ref_col_name);
16836 mrn_open_mutex_lock(table_share);
16837 mrn_free_tmp_table_share(tmp_ref_table_share);
16838 mrn_open_mutex_unlock(table_share);
16839 FOREIGN_KEY_INFO *p_f_key_info =
16840 (FOREIGN_KEY_INFO *) thd_memdup(thd, &f_key_info,
16841 sizeof(FOREIGN_KEY_INFO));
16842 if (!p_f_key_info) {
16843 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
16844 }
16845 f_key_list->push_back(p_f_key_info);
16846 }
16847 DBUG_RETURN(0);
16848 }
16849 #else
storage_get_foreign_key_list(THD * thd,List<FOREIGN_KEY_INFO> * f_key_list)16850 int ha_mroonga::storage_get_foreign_key_list(THD *thd,
16851 List<FOREIGN_KEY_INFO> *f_key_list)
16852 {
16853 MRN_DBUG_ENTER_METHOD();
16854 int res = handler::get_foreign_key_list(thd, f_key_list);
16855 DBUG_RETURN(res);
16856 }
16857 #endif
16858
get_foreign_key_list(THD * thd,List<FOREIGN_KEY_INFO> * f_key_list)16859 int ha_mroonga::get_foreign_key_list(THD *thd,
16860 List<FOREIGN_KEY_INFO> *f_key_list)
16861 {
16862 MRN_DBUG_ENTER_METHOD();
16863 int res;
16864 if (share->wrapper_mode)
16865 {
16866 res = wrapper_get_foreign_key_list(thd, f_key_list);
16867 } else {
16868 res = storage_get_foreign_key_list(thd, f_key_list);
16869 }
16870 DBUG_RETURN(res);
16871 }
16872
wrapper_get_parent_foreign_key_list(THD * thd,List<FOREIGN_KEY_INFO> * f_key_list)16873 int ha_mroonga::wrapper_get_parent_foreign_key_list(THD *thd,
16874 List<FOREIGN_KEY_INFO> *f_key_list)
16875 {
16876 MRN_DBUG_ENTER_METHOD();
16877 int res;
16878 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16879 MRN_SET_WRAP_TABLE_KEY(this, table);
16880 res = wrap_handler->get_parent_foreign_key_list(thd, f_key_list);
16881 MRN_SET_BASE_SHARE_KEY(share, table->s);
16882 MRN_SET_BASE_TABLE_KEY(this, table);
16883 DBUG_RETURN(res);
16884 }
16885
storage_get_parent_foreign_key_list(THD * thd,List<FOREIGN_KEY_INFO> * f_key_list)16886 int ha_mroonga::storage_get_parent_foreign_key_list(THD *thd,
16887 List<FOREIGN_KEY_INFO> *f_key_list)
16888 {
16889 MRN_DBUG_ENTER_METHOD();
16890 int res = handler::get_parent_foreign_key_list(thd, f_key_list);
16891 DBUG_RETURN(res);
16892 }
16893
get_parent_foreign_key_list(THD * thd,List<FOREIGN_KEY_INFO> * f_key_list)16894 int ha_mroonga::get_parent_foreign_key_list(THD *thd,
16895 List<FOREIGN_KEY_INFO> *f_key_list)
16896 {
16897 MRN_DBUG_ENTER_METHOD();
16898 int res;
16899 if (share->wrapper_mode)
16900 {
16901 res = wrapper_get_parent_foreign_key_list(thd, f_key_list);
16902 } else {
16903 res = storage_get_parent_foreign_key_list(thd, f_key_list);
16904 }
16905 DBUG_RETURN(res);
16906 }
16907
wrapper_referenced_by_foreign_key()16908 uint ha_mroonga::wrapper_referenced_by_foreign_key()
16909 {
16910 MRN_DBUG_ENTER_METHOD();
16911 uint res;
16912 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16913 MRN_SET_WRAP_TABLE_KEY(this, table);
16914 res = wrap_handler->referenced_by_foreign_key();
16915 MRN_SET_BASE_SHARE_KEY(share, table->s);
16916 MRN_SET_BASE_TABLE_KEY(this, table);
16917 DBUG_RETURN(res);
16918 }
16919
storage_referenced_by_foreign_key()16920 uint ha_mroonga::storage_referenced_by_foreign_key()
16921 {
16922 MRN_DBUG_ENTER_METHOD();
16923 uint res = handler::referenced_by_foreign_key();
16924 DBUG_RETURN(res);
16925 }
16926
referenced_by_foreign_key()16927 uint ha_mroonga::referenced_by_foreign_key()
16928 {
16929 MRN_DBUG_ENTER_METHOD();
16930 uint res;
16931 if (share->wrapper_mode)
16932 {
16933 res = wrapper_referenced_by_foreign_key();
16934 } else {
16935 res = storage_referenced_by_foreign_key();
16936 }
16937 DBUG_RETURN(res);
16938 }
16939
wrapper_init_table_handle_for_HANDLER()16940 void ha_mroonga::wrapper_init_table_handle_for_HANDLER()
16941 {
16942 MRN_DBUG_ENTER_METHOD();
16943 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16944 MRN_SET_WRAP_TABLE_KEY(this, table);
16945 wrap_handler->init_table_handle_for_HANDLER();
16946 MRN_SET_BASE_SHARE_KEY(share, table->s);
16947 MRN_SET_BASE_TABLE_KEY(this, table);
16948 DBUG_VOID_RETURN;
16949 }
16950
storage_init_table_handle_for_HANDLER()16951 void ha_mroonga::storage_init_table_handle_for_HANDLER()
16952 {
16953 MRN_DBUG_ENTER_METHOD();
16954 handler::init_table_handle_for_HANDLER();
16955 DBUG_VOID_RETURN;
16956 }
16957
init_table_handle_for_HANDLER()16958 void ha_mroonga::init_table_handle_for_HANDLER()
16959 {
16960 MRN_DBUG_ENTER_METHOD();
16961 if (share->wrapper_mode)
16962 {
16963 wrapper_init_table_handle_for_HANDLER();
16964 } else {
16965 storage_init_table_handle_for_HANDLER();
16966 }
16967 DBUG_VOID_RETURN;
16968 }
16969
wrapper_free_foreign_key_create_info(char * str)16970 void ha_mroonga::wrapper_free_foreign_key_create_info(char* str)
16971 {
16972 MRN_DBUG_ENTER_METHOD();
16973 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16974 MRN_SET_WRAP_TABLE_KEY(this, table);
16975 wrap_handler->free_foreign_key_create_info(str);
16976 MRN_SET_BASE_SHARE_KEY(share, table->s);
16977 MRN_SET_BASE_TABLE_KEY(this, table);
16978 DBUG_VOID_RETURN;
16979 }
16980
16981 #ifdef MRN_SUPPORT_FOREIGN_KEYS
storage_free_foreign_key_create_info(char * str)16982 void ha_mroonga::storage_free_foreign_key_create_info(char* str)
16983 {
16984 MRN_DBUG_ENTER_METHOD();
16985 my_free(str);
16986 DBUG_VOID_RETURN;
16987 }
16988 #else
storage_free_foreign_key_create_info(char * str)16989 void ha_mroonga::storage_free_foreign_key_create_info(char* str)
16990 {
16991 MRN_DBUG_ENTER_METHOD();
16992 handler::free_foreign_key_create_info(str);
16993 DBUG_VOID_RETURN;
16994 }
16995 #endif
16996
free_foreign_key_create_info(char * str)16997 void ha_mroonga::free_foreign_key_create_info(char* str)
16998 {
16999 MRN_DBUG_ENTER_METHOD();
17000 if (share->wrapper_mode)
17001 {
17002 wrapper_free_foreign_key_create_info(str);
17003 } else {
17004 storage_free_foreign_key_create_info(str);
17005 }
17006 DBUG_VOID_RETURN;
17007 }
17008
17009 #ifdef MRN_RBR_UPDATE_NEED_ALL_COLUMNS
check_written_by_row_based_binlog()17010 bool ha_mroonga::check_written_by_row_based_binlog()
17011 {
17012 MRN_DBUG_ENTER_METHOD();
17013 THD *thd = ha_thd();
17014
17015 int current_stmt_binlog_row;
17016 #ifdef MRN_ROW_BASED_CHECK_IS_METHOD
17017 current_stmt_binlog_row = thd->is_current_stmt_binlog_format_row();
17018 #else
17019 current_stmt_binlog_row = thd->current_stmt_binlog_row_based;
17020 #endif
17021 if (!current_stmt_binlog_row) {
17022 DBUG_RETURN(false);
17023 }
17024
17025 if (table->s->tmp_table != NO_TMP_TABLE) {
17026 DBUG_RETURN(false);
17027 }
17028
17029 if (!mrn_binlog_filter->db_ok(table->s->db.str)) {
17030 DBUG_RETURN(false);
17031 }
17032
17033 if (!thd_test_options(thd, OPTION_BIN_LOG)) {
17034 DBUG_RETURN(false);
17035 }
17036
17037 if (!mysql_bin_log.is_open()) {
17038 DBUG_RETURN(false);
17039 }
17040
17041 DBUG_RETURN(true);
17042 }
17043 #endif
17044
17045 #ifdef MRN_HAVE_HA_REBIND_PSI
wrapper_unbind_psi()17046 void ha_mroonga::wrapper_unbind_psi()
17047 {
17048 MRN_DBUG_ENTER_METHOD();
17049 MRN_SET_WRAP_SHARE_KEY(share, table->s);
17050 MRN_SET_WRAP_TABLE_KEY(this, table);
17051 wrap_handler->unbind_psi();
17052 MRN_SET_BASE_SHARE_KEY(share, table->s);
17053 MRN_SET_BASE_TABLE_KEY(this, table);
17054 DBUG_VOID_RETURN;
17055 }
17056
storage_unbind_psi()17057 void ha_mroonga::storage_unbind_psi()
17058 {
17059 MRN_DBUG_ENTER_METHOD();
17060 DBUG_VOID_RETURN;
17061 }
17062
unbind_psi()17063 void ha_mroonga::unbind_psi()
17064 {
17065 MRN_DBUG_ENTER_METHOD();
17066 handler::unbind_psi();
17067 if (share->wrapper_mode)
17068 {
17069 wrapper_unbind_psi();
17070 } else {
17071 storage_unbind_psi();
17072 }
17073 DBUG_VOID_RETURN;
17074 }
17075
wrapper_rebind_psi()17076 void ha_mroonga::wrapper_rebind_psi()
17077 {
17078 MRN_DBUG_ENTER_METHOD();
17079 MRN_SET_WRAP_SHARE_KEY(share, table->s);
17080 MRN_SET_WRAP_TABLE_KEY(this, table);
17081 wrap_handler->rebind_psi();
17082 MRN_SET_BASE_SHARE_KEY(share, table->s);
17083 MRN_SET_BASE_TABLE_KEY(this, table);
17084 DBUG_VOID_RETURN;
17085 }
17086
storage_rebind_psi()17087 void ha_mroonga::storage_rebind_psi()
17088 {
17089 MRN_DBUG_ENTER_METHOD();
17090 DBUG_VOID_RETURN;
17091 }
17092
rebind_psi()17093 void ha_mroonga::rebind_psi()
17094 {
17095 MRN_DBUG_ENTER_METHOD();
17096 handler::rebind_psi();
17097 if (share->wrapper_mode)
17098 {
17099 wrapper_rebind_psi();
17100 } else {
17101 storage_rebind_psi();
17102 }
17103 DBUG_VOID_RETURN;
17104 }
17105 #endif
17106
wrapper_register_query_cache_table(THD * thd,const char * table_key,uint key_length,qc_engine_callback * engine_callback,ulonglong * engine_data)17107 my_bool ha_mroonga::wrapper_register_query_cache_table(THD *thd,
17108 const char *table_key,
17109 uint key_length,
17110 qc_engine_callback
17111 *engine_callback,
17112 ulonglong *engine_data)
17113 {
17114 MRN_DBUG_ENTER_METHOD();
17115 my_bool res;
17116 MRN_SET_WRAP_SHARE_KEY(share, table->s);
17117 MRN_SET_WRAP_TABLE_KEY(this, table);
17118 res = wrap_handler->register_query_cache_table(thd,
17119 table_key,
17120 key_length,
17121 engine_callback,
17122 engine_data);
17123 MRN_SET_BASE_SHARE_KEY(share, table->s);
17124 MRN_SET_BASE_TABLE_KEY(this, table);
17125 DBUG_RETURN(res);
17126 }
17127
storage_register_query_cache_table(THD * thd,const char * table_key,uint key_length,qc_engine_callback * engine_callback,ulonglong * engine_data)17128 my_bool ha_mroonga::storage_register_query_cache_table(THD *thd,
17129 const char *table_key,
17130 uint key_length,
17131 qc_engine_callback
17132 *engine_callback,
17133 ulonglong *engine_data)
17134 {
17135 MRN_DBUG_ENTER_METHOD();
17136 my_bool res = handler::register_query_cache_table(thd,
17137 table_key,
17138 key_length,
17139 engine_callback,
17140 engine_data);
17141 DBUG_RETURN(res);
17142 }
17143
register_query_cache_table(THD * thd,const char * table_key,uint key_length,qc_engine_callback * engine_callback,ulonglong * engine_data)17144 my_bool ha_mroonga::register_query_cache_table(THD *thd,
17145 const char *table_key,
17146 uint key_length,
17147 qc_engine_callback
17148 *engine_callback,
17149 ulonglong *engine_data)
17150 {
17151 MRN_DBUG_ENTER_METHOD();
17152 my_bool res;
17153 if (share->wrapper_mode)
17154 {
17155 res = wrapper_register_query_cache_table(thd,
17156 table_key,
17157 key_length,
17158 engine_callback,
17159 engine_data);
17160 } else {
17161 res = storage_register_query_cache_table(thd,
17162 table_key,
17163 key_length,
17164 engine_callback,
17165 engine_data);
17166 }
17167 DBUG_RETURN(res);
17168 }
17169
17170 #ifdef __cplusplus
17171 }
17172 #endif
17173
17174 namespace mrn {
17175 namespace variables {
get_boolean_mode_syntax_flags(THD * thd)17176 ulonglong get_boolean_mode_syntax_flags(THD *thd) {
17177 ulonglong flags = BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT;
17178 #ifdef MRN_SUPPORT_THDVAR_SET
17179 flags = THDVAR(thd, boolean_mode_syntax_flags);
17180 #endif
17181 return flags;
17182 }
17183
get_action_on_fulltext_query_error(THD * thd)17184 ActionOnError get_action_on_fulltext_query_error(THD *thd) {
17185 ulong action = THDVAR(thd, action_on_fulltext_query_error);
17186 return static_cast<ActionOnError>(action);
17187 }
17188 }
17189 }
17190