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-1301 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
137extern mysql_mutex_t LOCK_open;
138# endif
139# endif
140static 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
225Rpl_filter *mrn_binlog_filter;
226Time_zone *mrn_my_tz_UTC;
227#ifdef MRN_HAVE_TABLE_DEF_CACHE
228HASH *mrn_table_def_cache;
229#endif
230
231#ifdef MRN_HAVE_PSI_MEMORY_KEY
232PSI_memory_key mrn_memory_key;
233
234static PSI_memory_info mrn_all_memory_keys[]=
235{
236 {&mrn_memory_key, "Mroonga", 0}
237};
238#endif
239
240static const char *INDEX_COLUMN_NAME = "index";
241static const char *MRN_PLUGIN_AUTHOR = "The Mroonga project";
242
243#ifdef __cplusplus
244extern "C" {
245#endif
246
247#ifdef HAVE_PSI_INTERFACE
248# ifdef WIN32
249# ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE
250PSI_mutex_key *mrn_table_share_lock_share;
251# endif
252PSI_mutex_key *mrn_table_share_lock_ha_data;
253# endif
254static PSI_mutex_key mrn_open_tables_mutex_key;
255static PSI_mutex_key mrn_long_term_share_mutex_key;
256static PSI_mutex_key mrn_allocated_thds_mutex_key;
257PSI_mutex_key mrn_share_mutex_key;
258PSI_mutex_key mrn_long_term_share_auto_inc_mutex_key;
259static PSI_mutex_key mrn_log_mutex_key;
260static PSI_mutex_key mrn_query_log_mutex_key;
261static PSI_mutex_key mrn_db_manager_mutex_key;
262static PSI_mutex_key mrn_context_pool_mutex_key;
263static 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
273static 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 */
299handlerton *mrn_hton_ptr;
300HASH mrn_open_tables;
301mysql_mutex_t mrn_open_tables_mutex;
302HASH mrn_long_term_share;
303mysql_mutex_t mrn_long_term_share_mutex;
304
305HASH mrn_allocated_thds;
306mysql_mutex_t mrn_allocated_thds_mutex;
307
308/* internal variables */
309static grn_ctx mrn_ctx;
310static mysql_mutex_t mrn_log_mutex;
311static mysql_mutex_t mrn_query_log_mutex;
312static grn_obj *mrn_db;
313static grn_ctx mrn_db_manager_ctx;
314static mysql_mutex_t mrn_db_manager_mutex;
315mrn::DatabaseManager *mrn_db_manager = NULL;
316static mysql_mutex_t mrn_context_pool_mutex;
317mrn::ContextPool *mrn_context_pool = NULL;
318static mysql_mutex_t mrn_operations_mutex;
319
320
321#ifdef WIN32
322static inline double round(double x)
323{
324 return (floor(x + 0.5));
325}
326#endif
327
328static void mrn_init_encoding_map()
329{
330 mrn::encoding::init();
331}
332
333static 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)
339static 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
396static 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
601static 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
611static 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 */
623static long mrn_count_skip = 0;
624static long mrn_fast_order_limit = 0;
625
626/* logging */
627static char *mrn_log_file_path = NULL;
628static FILE *mrn_log_file = NULL;
629static bool mrn_log_file_opened = false;
630static grn_log_level mrn_log_level_default = GRN_LOG_DEFAULT_LEVEL;
631static ulong mrn_log_level = mrn_log_level_default;
632static char *mrn_query_log_file_path = NULL;
633
634char *mrn_default_tokenizer = NULL;
635char *mrn_default_wrapper_engine = NULL;
636static int mrn_lock_timeout = grn_get_lock_timeout();
637static char *mrn_libgroonga_version = const_cast<char *>(grn_get_version());
638static char *mrn_version = const_cast<char *>(MRN_VERSION);
639static char *mrn_vector_column_delimiter = NULL;
640static mrn_bool mrn_libgroonga_support_zlib = false;
641static mrn_bool mrn_libgroonga_support_lz4 = false;
642static mrn_bool mrn_libgroonga_support_zstd = false;
643static mrn_bool mrn_enable_operations_recording = true;
644#ifdef MRN_SUPPORT_THDVAR_SET
645static 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};
654static 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
662static mrn_bool mrn_libgroonga_embedded = true;
663#else
664static mrn_bool mrn_libgroonga_embedded = false;
665#endif
666
667static mrn::variables::ActionOnError mrn_action_on_fulltext_query_error_default =
668 mrn::variables::ACTION_ON_ERROR_ERROR_AND_LOG;
669
670static 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
688static 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
697static 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
708static 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
719static 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
732static 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};
745static 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
752static 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
770static 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
778static 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
847static 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
854static 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
925static 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
932static 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
962static 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
970static 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
977static 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
986static 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
995static 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
1005static 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
1022static 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
1029static 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
1049static 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
1057static 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
1064static const char *mrn_action_on_error_names[] = {
1065 "ERROR",
1066 "ERROR_AND_LOG",
1067 "IGNORE",
1068 "IGNORE_AND_LOG",
1069 NullS,
1070};
1071
1072static 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
1080static 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
1088static 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
1101static 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
1112static 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
1119static 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
1126static 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
1139static 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
1146static 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
1159static 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
1166static 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
1179static 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
1186static 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
1198static 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
1206static 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
1219static const int MRN_MAX_N_RECORDS_FOR_ESTIMATE_DEFAULT = 1000;
1220
1221static 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
1232static 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
1239static 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 */
1269static struct st_mysql_information_schema i_s_info =
1270{
1271 MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION
1272};
1273
1274static 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
1306static int i_s_mrn_stats_deinit(void* p)
1307{
1308 MRN_DBUG_ENTER_FUNCTION();
1309 DBUG_RETURN(0);
1310}
1311
1312static 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
1329static 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
1338struct 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
1358static 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
1370static 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
1377static 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
1394static bool mrn_flush_logs(handlerton *hton, bool binlog_group_flush)
1395#else
1396static 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
1409static 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
1586static 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
1659static 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
1714static 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
1757static 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
1788static 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
1795static 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
1805static 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
1989error_allocated_long_term_share_hash_init:
1990 mysql_mutex_destroy(&mrn_long_term_share_mutex);
1991error_allocated_long_term_share_mutex_init:
1992 my_hash_free(&mrn_open_tables);
1993error_allocated_open_tables_hash_init:
1994 mysql_mutex_destroy(&mrn_open_tables_mutex);
1995err_allocated_open_tables_mutex_init:
1996 my_hash_free(&mrn_allocated_thds);
1997error_allocated_thds_hash_init:
1998 mysql_mutex_destroy(&mrn_allocated_thds_mutex);
1999err_allocated_thds_mutex_init:
2000 mysql_mutex_destroy(&mrn_operations_mutex);
2001error_operations_mutex_init:
2002 delete mrn_context_pool;
2003 mysql_mutex_destroy(&mrn_context_pool_mutex);
2004error_context_pool_mutex_init:
2005err_db_manager_init:
2006 delete mrn_db_manager;
2007 mysql_mutex_destroy(&mrn_db_manager_mutex);
2008err_db_manager_mutex_init:
2009 grn_ctx_fin(&mrn_db_manager_ctx);
2010 grn_obj_unlink(ctx, mrn_db);
2011err_db_create:
2012 if (mrn_log_file_opened) {
2013 fclose(mrn_log_file);
2014 mrn_log_file_opened = false;
2015 }
2016err_log_file_open:
2017 mysql_mutex_destroy(&mrn_query_log_mutex);
2018err_query_log_mutex_init:
2019 mysql_mutex_destroy(&mrn_log_mutex);
2020err_log_mutex_init:
2021err_mrn_change_encoding:
2022 grn_ctx_fin(ctx);
2023 grn_fin();
2024err_grn_init:
2025 return -1;
2026}
2027
2028static 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
2084mrn_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},
2099i_s_mrn_stats
2100mrn_declare_plugin_end;
2101
2102static 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
2114static 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
2141static 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
2150static 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
2156static 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
2190static 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
2197static 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
2228static void mrn_wrapper_ft_reinit_search(FT_INFO *handler)
2229{
2230 MRN_DBUG_ENTER_FUNCTION();
2231 DBUG_VOID_RETURN;
2232}
2233
2234static _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
2242static 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
2248static 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
2274static 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
2281static 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
2306static void mrn_storage_ft_reinit_search(FT_INFO *handler)
2307{
2308 MRN_DBUG_ENTER_FUNCTION();
2309 DBUG_VOID_RETURN;
2310}
2311
2312static _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
2320static 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
2326static 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
2333static 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
2341static float mrn_no_such_key_ft_get_relevance(FT_INFO *handler)
2342{
2343 MRN_DBUG_ENTER_FUNCTION();
2344 DBUG_RETURN(0.0);
2345}
2346
2347static void mrn_no_such_key_ft_reinit_search(FT_INFO *handler)
2348{
2349 MRN_DBUG_ENTER_FUNCTION();
2350 DBUG_VOID_RETURN;
2351}
2352
2353static _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
2362static 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
2371static 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().
2385static 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
2392static 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
2400static 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
2407static 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
2414static 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
2421static 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
2428static _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
2435static 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
2442static 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
2449static 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
2456static 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
2463static _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
2470static 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
2477static 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
2484static 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
2491static 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
2498static _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 */
2507ha_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
2582ha_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
2616const char *ha_mroonga::table_type() const
2617{
2618 MRN_DBUG_ENTER_METHOD();
2619 DBUG_RETURN(MRN_PLUGIN_NAME_STRING);
2620}
2621
2622const 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
2635static const char *ha_mroonga_exts[] = {
2636 NullS
2637};
2638const char **ha_mroonga::bas_ext() const
2639{
2640 MRN_DBUG_ENTER_METHOD();
2641 DBUG_RETURN(ha_mroonga_exts);
2642}
2643
2644uint 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
2660uint ha_mroonga::storage_max_supported_record_length() const
2661{
2662 MRN_DBUG_ENTER_METHOD();
2663 DBUG_RETURN(HA_MAX_REC_LENGTH);
2664}
2665
2666uint 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
2691uint 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
2707uint ha_mroonga::storage_max_supported_keys() const
2708{
2709 MRN_DBUG_ENTER_METHOD();
2710 DBUG_RETURN(HA_MAX_REC_LENGTH);
2711}
2712
2713uint 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
2738uint 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
2754uint ha_mroonga::storage_max_supported_key_length() const
2755{
2756 MRN_DBUG_ENTER_METHOD();
2757 DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE);
2758}
2759
2760uint 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
2785uint 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
2801uint 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
2807uint 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
2832ulonglong 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
2862ulonglong 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
2897ulonglong 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
2922ulong 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
2940ulong 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
2973ulong 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
2995int 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 memset(&table_for_create, 0, sizeof(TABLE));
3005 memset(&share_for_create, 0, sizeof(MRN_SHARE));
3006 memset(&table_share_for_create, 0, sizeof(TABLE_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
3074error:
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
3085int 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
3164int 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
3191int 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
3292int 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
3351int 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
3415int 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
3616int 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
3647bool 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
3851int 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
3882int 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
3993int 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
4140int 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
4179int 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
4208int 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
4230int 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
4269int 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
4396int 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
4473error:
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
4494void 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
4549int 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
4629int 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
4688int 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
4717int 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 if (blob_buffers)
4737 {
4738 ::delete [] blob_buffers;
4739 }
4740 if (!(blob_buffers = ::new String[n_columns]))
4741 {
4742 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
4743 }
4744 }
4745
4746 for (int i = 0; i < n_columns; i++) {
4747 Field *field = table->field[i];
4748 mrn::ColumnName column_name(field->field_name);
4749 if (table_share->blob_fields)
4750 {
4751 blob_buffers[i].set_charset(field->charset());
4752 }
4753 if (strcmp(MRN_COLUMN_NAME_ID, column_name.mysql_name()) == 0) {
4754 continue;
4755 }
4756#ifdef MRN_SUPPORT_GENERATED_COLUMNS
4757 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
4758 grn_columns[i] = NULL;
4759 grn_column_ranges[i] = NULL;
4760 continue;
4761 }
4762#endif
4763
4764 grn_columns[i] = grn_obj_column(ctx,
4765 grn_table,
4766 column_name.c_str(),
4767 column_name.length());
4768 if (!grn_columns[i]) {
4769 error = ER_CANT_OPEN_FILE;
4770 my_message(error, ctx->errbuf, MYF(0));
4771 break;
4772 }
4773
4774 grn_id range_id = grn_obj_get_range(ctx, grn_columns[i]);
4775 grn_column_ranges[i] = grn_ctx_at(ctx, range_id);
4776 if (!grn_column_ranges[i]) {
4777 error = ER_CANT_OPEN_FILE;
4778 my_message(error, ctx->errbuf, MYF(0));
4779 break;
4780 }
4781 }
4782
4783 if (error != 0) {
4784 storage_close_columns();
4785 }
4786
4787 DBUG_RETURN(error);
4788}
4789
4790void ha_mroonga::storage_close_columns(void)
4791{
4792 int n_columns = table->s->fields;
4793 for (int i = 0; i < n_columns; i++) {
4794 grn_obj *column = grn_columns[i];
4795 if (column) {
4796 grn_obj_unlink(ctx, column);
4797 }
4798
4799 grn_obj *range = grn_column_ranges[i];
4800 if (range) {
4801 grn_obj_unlink(ctx, range);
4802 }
4803 }
4804
4805 free(grn_columns);
4806 grn_columns = NULL;
4807 free(grn_column_ranges);
4808 grn_column_ranges = NULL;
4809}
4810
4811int ha_mroonga::storage_open_indexes(const char *name)
4812{
4813 int error;
4814
4815 MRN_DBUG_ENTER_METHOD();
4816
4817 error = mrn_change_encoding(ctx, system_charset_info);
4818 if (error)
4819 DBUG_RETURN(error);
4820
4821 uint n_keys = table->s->keys;
4822 uint pkey_nr = table->s->primary_key;
4823 if (n_keys > 0) {
4824 grn_index_tables = (grn_obj **)malloc(sizeof(grn_obj *) * n_keys);
4825 grn_index_columns = (grn_obj **)malloc(sizeof(grn_obj *) * n_keys);
4826 key_id = (grn_id *)malloc(sizeof(grn_id) * n_keys);
4827 del_key_id = (grn_id *)malloc(sizeof(grn_id) * n_keys);
4828 } else {
4829 grn_index_tables = grn_index_columns = NULL;
4830 key_id = NULL;
4831 del_key_id = NULL;
4832 }
4833
4834 mrn::PathMapper mapper(name);
4835 uint i, j;
4836 for (i = 0; i < n_keys; i++) {
4837 if (i == pkey_nr) {
4838 grn_index_tables[i] = grn_index_columns[i] = NULL;
4839 continue;
4840 }
4841
4842 KEY *key_info = &(table->s->key_info[i]);
4843 if (KEY_N_KEY_PARTS(key_info) > 1) {
4844 KEY_PART_INFO *key_part = key_info->key_part;
4845 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
4846 bitmap_set_bit(&multiple_column_key_bitmap,
4847 key_part[j].field->field_index);
4848 }
4849 }
4850
4851 MRN_SHARE *tmp_share;
4852 tmp_share = mrn_get_share(name, table, &error);
4853 if (tmp_share->index_table[i]) {
4854 grn_index_tables[i] = grn_ctx_get(ctx,
4855 tmp_share->index_table[i],
4856 tmp_share->index_table_length[i]);
4857 if (ctx->rc == GRN_SUCCESS) {
4858 grn_index_columns[i] = grn_obj_column(ctx,
4859 grn_index_tables[i],
4860 key_info->name.str,
4861 key_info->name.length);
4862 }
4863 } else {
4864 mrn::IndexTableName index_table_name(mapper.table_name(),
4865 key_info->name.str);
4866 grn_index_tables[i] = grn_ctx_get(ctx,
4867 index_table_name.c_str(),
4868 index_table_name.length());
4869 if (ctx->rc == GRN_SUCCESS && !grn_index_tables[i]) {
4870 grn_index_tables[i] = grn_ctx_get(ctx,
4871 index_table_name.old_c_str(),
4872 index_table_name.old_length());
4873 }
4874 if (ctx->rc == GRN_SUCCESS) {
4875 grn_index_columns[i] = grn_obj_column(ctx,
4876 grn_index_tables[i],
4877 INDEX_COLUMN_NAME,
4878 strlen(INDEX_COLUMN_NAME));
4879 if (!grn_index_columns[i] && ctx->rc == GRN_SUCCESS) {
4880 /* just for backward compatibility before 1.0. */
4881 Field *field = key_info->key_part[0].field;
4882 grn_index_columns[i] = grn_obj_column(ctx, grn_index_tables[i],
4883 field->field_name.str,
4884 field->field_name.length);
4885 }
4886 }
4887 }
4888 mrn_free_share(tmp_share);
4889 if (ctx->rc) {
4890 error = ER_CANT_OPEN_FILE;
4891 my_message(error, ctx->errbuf, MYF(0));
4892 goto error;
4893 }
4894
4895 if (ctx->rc) {
4896 error = ER_CANT_OPEN_FILE;
4897 my_message(error, ctx->errbuf, MYF(0));
4898 goto error;
4899 }
4900 }
4901
4902error:
4903 if (error) {
4904 if (i) {
4905 while (true) {
4906 grn_obj *index_column = grn_index_columns[i];
4907 if (index_column) {
4908 grn_obj_unlink(ctx, index_column);
4909 }
4910 grn_obj *index_table = grn_index_tables[i];
4911 if (index_table) {
4912 grn_obj_unlink(ctx, index_table);
4913 }
4914 if (!i)
4915 break;
4916 i--;
4917 }
4918 }
4919 free(key_id);
4920 free(del_key_id);
4921 free(grn_index_columns);
4922 free(grn_index_tables);
4923 key_id = NULL;
4924 del_key_id = NULL;
4925 grn_index_columns = NULL;
4926 grn_index_tables = NULL;
4927 }
4928
4929 DBUG_RETURN(error);
4930}
4931
4932int ha_mroonga::open(const char *name,
4933 int mode,
4934 uint open_options
4935#ifdef MRN_HANDLER_OPEN_HAVE_TABLE_DEFINITION
4936 ,
4937 const dd::Table *table_def
4938#endif
4939 )
4940{
4941 int error = 0;
4942 MRN_DBUG_ENTER_METHOD();
4943
4944 if (!(share = mrn_get_share(name, table, &error)))
4945 DBUG_RETURN(error);
4946 thr_lock_data_init(&share->lock,&thr_lock_data,NULL);
4947
4948 if (bitmap_init(&multiple_column_key_bitmap, NULL, table->s->fields, false))
4949 {
4950 mrn_free_share(share);
4951 share = NULL;
4952 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
4953 }
4954
4955 if (share->wrapper_mode)
4956 {
4957 error = wrapper_open(name, mode, open_options);
4958 } else {
4959 error = storage_open(name, mode, open_options);
4960 }
4961
4962 if (error)
4963 {
4964 bitmap_free(&multiple_column_key_bitmap);
4965 mrn_free_share(share);
4966 share = NULL;
4967 }
4968 DBUG_RETURN(error);
4969}
4970
4971int ha_mroonga::wrapper_close()
4972{
4973 int error = 0;
4974 MRN_DBUG_ENTER_METHOD();
4975 MRN_SET_WRAP_SHARE_KEY(share, table->s);
4976 MRN_SET_WRAP_TABLE_KEY(this, table);
4977#ifdef MRN_HANDLER_HAVE_HA_CLOSE
4978 error = wrap_handler->ha_close();
4979#else
4980 error = wrap_handler->close();
4981#endif
4982 MRN_SET_BASE_SHARE_KEY(share, table->s);
4983 MRN_SET_BASE_TABLE_KEY(this, table);
4984 delete wrap_handler;
4985 wrap_handler = NULL;
4986 if (wrap_key_info)
4987 {
4988 my_free(wrap_key_info);
4989 wrap_key_info = NULL;
4990 }
4991 base_key_info = NULL;
4992 free_root(&mem_root, MYF(0));
4993 DBUG_RETURN(error);
4994}
4995
4996int ha_mroonga::storage_close()
4997{
4998 MRN_DBUG_ENTER_METHOD();
4999 grn_obj_unlink(ctx, grn_table);
5000 // TODO: unlink elements
5001 free(grn_columns);
5002 // TODO: unlink elements
5003 free(grn_column_ranges);
5004 DBUG_RETURN(0);
5005}
5006
5007int ha_mroonga::close()
5008{
5009 int error = 0;
5010 THD *thd = ha_thd();
5011 MRN_DBUG_ENTER_METHOD();
5012
5013 clear_indexes();
5014
5015 if (share->wrapper_mode)
5016 {
5017 error = wrapper_close();
5018 } else {
5019 error = storage_close();
5020 }
5021
5022 if (error != 0)
5023 {
5024 DBUG_RETURN(error);
5025 }
5026
5027 if (thd)
5028 {
5029 error = add_wrap_hton(share->table_name, share->hton);
5030 }
5031 bitmap_free(&multiple_column_key_bitmap);
5032 if (share->use_count == 1) {
5033 mrn_free_long_term_share(share->long_term_share);
5034 }
5035 mrn_free_share(share);
5036 share = NULL;
5037 is_clone = false;
5038
5039 if (
5040 thd &&
5041 thd_sql_command(thd) == SQLCOM_FLUSH
5042 ) {
5043 /* flush tables */
5044 mrn::Lock lock(&mrn_open_tables_mutex);
5045 if (!mrn_open_tables.records)
5046 {
5047 int tmp_error = mrn_db_manager->clear();
5048 if (tmp_error)
5049 error = tmp_error;
5050 }
5051 }
5052 DBUG_RETURN(error);
5053}
5054
5055int ha_mroonga::wrapper_delete_table(const char *name,
5056 handlerton *wrap_handlerton,
5057 const char *table_name)
5058{
5059 int error = 0;
5060 MRN_DBUG_ENTER_METHOD();
5061
5062 handler *hnd = get_new_handler(NULL, current_thd->mem_root, wrap_handlerton);
5063 if (!hnd)
5064 {
5065 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
5066 }
5067
5068 error = hnd->ha_delete_table(name);
5069 delete hnd;
5070
5071 DBUG_RETURN(error);
5072}
5073
5074int ha_mroonga::generic_delete_table(const char *name, const char *table_name)
5075{
5076 int error = 0;
5077 MRN_DBUG_ENTER_METHOD();
5078
5079 error = ensure_database_open(name);
5080 if (error)
5081 DBUG_RETURN(error);
5082
5083 error = mrn_change_encoding(ctx, system_charset_info);
5084 if (error)
5085 DBUG_RETURN(error);
5086
5087 error = drop_indexes(table_name);
5088 grn_obj *table_obj = grn_ctx_get(ctx, table_name, strlen(table_name));
5089 if (table_obj) {
5090 grn_obj_remove(ctx, table_obj);
5091 }
5092 if (ctx->rc) {
5093 error = ER_CANT_OPEN_FILE;
5094 my_message(error, ctx->errbuf, MYF(0));
5095 DBUG_RETURN(error);
5096 }
5097 DBUG_RETURN(error);
5098}
5099
5100int ha_mroonga::delete_table(const char *name)
5101{
5102 MRN_DBUG_ENTER_METHOD();
5103
5104 int error = 0;
5105 THD *thd = ha_thd();
5106 handlerton *wrap_handlerton = NULL;
5107 mrn::PathMapper mapper(name);
5108 st_mrn_slot_data *slot_data = mrn_get_slot_data(thd, false);
5109 if (slot_data && slot_data->first_wrap_hton)
5110 {
5111 st_mrn_wrap_hton *wrap_hton, *tmp_wrap_hton;
5112 tmp_wrap_hton = NULL;
5113 wrap_hton = slot_data->first_wrap_hton;
5114 while (wrap_hton)
5115 {
5116 if (!strcmp(wrap_hton->path, name))
5117 {
5118 /* found */
5119 wrap_handlerton = wrap_hton->hton;
5120 if (tmp_wrap_hton)
5121 tmp_wrap_hton->next = wrap_hton->next;
5122 else
5123 slot_data->first_wrap_hton = wrap_hton->next;
5124 free(wrap_hton);
5125 break;
5126 }
5127 tmp_wrap_hton = wrap_hton;
5128 wrap_hton = wrap_hton->next;
5129 }
5130 }
5131
5132 if (!wrap_handlerton) {
5133 bool open_table_to_get_wrap_handlerton = true;
5134 if (mapper.is_internal_table_name()) {
5135 open_table_to_get_wrap_handlerton = false;
5136 }
5137 if (open_table_to_get_wrap_handlerton) {
5138 TABLE_LIST table_list;
5139 LEX_CSTRING db_name= { mapper.db_name(), strlen(mapper.db_name()) };
5140 LEX_CSTRING table_name= { mapper.mysql_table_name(), strlen(mapper.mysql_table_name()) };
5141
5142 table_list.init_one_table(&db_name, &table_name, 0, TL_WRITE);
5143 mrn_open_mutex_lock(NULL);
5144 TABLE_SHARE *tmp_table_share =
5145 mrn_create_tmp_table_share(&table_list, name, &error);
5146 error = 0;
5147 mrn_open_mutex_unlock(NULL);
5148 if (tmp_table_share) {
5149 TABLE tmp_table;
5150 tmp_table.s = tmp_table_share;
5151#ifdef WITH_PARTITION_STORAGE_ENGINE
5152 tmp_table.part_info = NULL;
5153#endif
5154 MRN_SHARE *tmp_share = mrn_get_share(name, &tmp_table, &error);
5155 if (tmp_share) {
5156 wrap_handlerton = tmp_share->hton;
5157 mrn_free_long_term_share(tmp_share->long_term_share);
5158 tmp_share->long_term_share = NULL;
5159 mrn_free_share(tmp_share);
5160 }
5161 mrn_open_mutex_lock(NULL);
5162 mrn_free_tmp_table_share(tmp_table_share);
5163 mrn_open_mutex_unlock(NULL);
5164 if (error) {
5165 DBUG_RETURN(error);
5166 }
5167 }
5168 }
5169 }
5170
5171 if (wrap_handlerton)
5172 {
5173 error = wrapper_delete_table(name, wrap_handlerton, mapper.table_name());
5174 }
5175
5176 if (!error)
5177 {
5178 error = generic_delete_table(name, mapper.table_name());
5179 }
5180
5181 if (!error) {
5182 error = operations_->clear(name, strlen(name));
5183 }
5184
5185 DBUG_RETURN(error);
5186}
5187
5188void ha_mroonga::wrapper_set_keys_in_use()
5189{
5190 uint i, j;
5191 MRN_DBUG_ENTER_METHOD();
5192 mrn::AutoIncrementValueLock lock_(table_share);
5193 table_share->keys_in_use.set_prefix(table_share->keys);
5194 share->disable_keys = false;
5195 for (i = 0; i < table_share->keys; i++) {
5196 j = share->wrap_key_nr[i];
5197 if (j < MAX_KEY) {
5198 if (!share->wrap_table_share->keys_in_use.is_set(j)) {
5199 /* copy bitmap */
5200 table_share->keys_in_use.clear_bit(i);
5201 share->disable_keys = true;
5202 }
5203 } else {
5204 if (!grn_index_tables || !grn_index_tables[i]) {
5205 /* disabled */
5206 table_share->keys_in_use.clear_bit(i);
5207 share->disable_keys = true;
5208 }
5209 }
5210 }
5211 table_share->keys_for_keyread.set_prefix(table_share->keys);
5212 table_share->keys_for_keyread.intersect(table_share->keys_in_use);
5213 DBUG_VOID_RETURN;
5214}
5215
5216void ha_mroonga::storage_set_keys_in_use()
5217{
5218 uint i;
5219 MRN_DBUG_ENTER_METHOD();
5220 mrn::AutoIncrementValueLock lock_(table_share);
5221 table_share->keys_in_use.set_prefix(table_share->keys);
5222 share->disable_keys = false;
5223 for (i = 0; i < table_share->keys; i++) {
5224 if (i == table_share->primary_key) {
5225 continue;
5226 }
5227 if (!grn_index_tables[i]) {
5228 /* disabled */
5229 table_share->keys_in_use.clear_bit(i);
5230 DBUG_PRINT("info", ("mroonga: key %u disabled", i));
5231 share->disable_keys = true;
5232 }
5233 }
5234 table_share->keys_for_keyread.set_prefix(table_share->keys);
5235 table_share->keys_for_keyread.intersect(table_share->keys_in_use);
5236 DBUG_VOID_RETURN;
5237}
5238
5239int ha_mroonga::wrapper_info(uint flag)
5240{
5241 int error = 0;
5242 MRN_DBUG_ENTER_METHOD();
5243
5244 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5245 MRN_SET_WRAP_TABLE_KEY(this, table);
5246 error = wrap_handler->info(flag);
5247 MRN_SET_BASE_SHARE_KEY(share, table->s);
5248 MRN_SET_BASE_TABLE_KEY(this, table);
5249 if (flag & HA_STATUS_ERRKEY) {
5250 errkey = wrap_handler->errkey;
5251 memcpy(dup_ref, wrap_handler->dup_ref, wrap_handler->ref_length);
5252 }
5253 if (flag & HA_STATUS_TIME) {
5254 stats.update_time = wrap_handler->stats.update_time;
5255 }
5256 if (flag & HA_STATUS_CONST) {
5257 stats.max_data_file_length = wrap_handler->stats.max_data_file_length;
5258 stats.create_time = wrap_handler->stats.create_time;
5259 stats.block_size = wrap_handler->stats.block_size;
5260 wrapper_set_keys_in_use();
5261 }
5262 if (flag & HA_STATUS_VARIABLE) {
5263 stats.data_file_length = wrap_handler->stats.data_file_length;
5264 stats.index_file_length = wrap_handler->stats.index_file_length;
5265 stats.records = wrap_handler->stats.records;
5266 stats.mean_rec_length = wrap_handler->stats.mean_rec_length;
5267 stats.check_time = wrap_handler->stats.check_time;
5268 }
5269 if (flag & HA_STATUS_AUTO) {
5270 stats.auto_increment_value = wrap_handler->stats.auto_increment_value;
5271 }
5272 DBUG_RETURN(error);
5273}
5274
5275int ha_mroonga::storage_info(uint flag)
5276{
5277 MRN_DBUG_ENTER_METHOD();
5278 mrn_change_encoding(ctx, NULL);
5279
5280 if (flag & (HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK)) {
5281 errkey = dup_key;
5282 }
5283
5284 if ((flag & HA_STATUS_AUTO) && table->found_next_number_field) {
5285 THD *thd = ha_thd();
5286 ulonglong nb_reserved_values;
5287 bool next_number_field_is_null = !table->next_number_field;
5288 mrn::ExternalLock mrn_external_lock(ha_thd(), this,
5289 mrn_lock_type == F_UNLCK ?
5290 F_RDLCK : F_UNLCK);
5291 if (mrn_external_lock.error()) {
5292 DBUG_RETURN(mrn_external_lock.error());
5293 }
5294 if (next_number_field_is_null) {
5295 table->next_number_field = table->found_next_number_field;
5296 }
5297 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
5298 {
5299 mrn::Lock lock(&long_term_share->auto_inc_mutex);
5300 unsigned long auto_increment_offset, auto_increment_increment;
5301 MRN_THD_GET_AUTOINC(thd, &auto_increment_offset,
5302 &auto_increment_increment);
5303 storage_get_auto_increment(auto_increment_offset,
5304 auto_increment_increment, 1,
5305 &stats.auto_increment_value,
5306 &nb_reserved_values);
5307 }
5308 if (next_number_field_is_null) {
5309 table->next_number_field = NULL;
5310 }
5311 }
5312
5313 if (flag & HA_STATUS_CONST) {
5314 storage_set_keys_in_use();
5315 }
5316
5317 if (flag & HA_STATUS_VARIABLE) {
5318 storage_info_variable();
5319 }
5320
5321 DBUG_RETURN(0);
5322}
5323
5324void ha_mroonga::storage_info_variable()
5325{
5326 MRN_DBUG_ENTER_METHOD();
5327
5328 storage_info_variable_records();
5329 storage_info_variable_data_file_length();
5330
5331 DBUG_VOID_RETURN;
5332}
5333
5334void ha_mroonga::storage_info_variable_records()
5335{
5336 MRN_DBUG_ENTER_METHOD();
5337
5338 stats.records = grn_table_size(ctx, grn_table);
5339
5340 DBUG_VOID_RETURN;
5341}
5342
5343void ha_mroonga::storage_info_variable_data_file_length()
5344{
5345 MRN_DBUG_ENTER_METHOD();
5346
5347 stats.data_file_length = 0;
5348 stats.data_file_length += file_size(grn_obj_path(ctx, grn_table));
5349 grn_hash *columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
5350 GRN_OBJ_TABLE_HASH_KEY);
5351 grn_table_columns(ctx, grn_table, NULL, 0, (grn_obj *)columns);
5352 /* grn_id id __attribute__((unused)); */
5353 grn_id *column_id;
5354 GRN_HASH_EACH(ctx, columns, id, &column_id, NULL, NULL, {
5355 grn_obj *column = grn_ctx_at(ctx, *column_id);
5356 stats.data_file_length += file_size(grn_obj_path(ctx, column));
5357 grn_obj_unlink(ctx, column);
5358 });
5359 grn_hash_close(ctx, columns);
5360
5361 DBUG_VOID_RETURN;
5362}
5363
5364int ha_mroonga::info(uint flag)
5365{
5366 MRN_DBUG_ENTER_METHOD();
5367
5368 int error = 0;
5369 if (share->wrapper_mode)
5370 {
5371 error = wrapper_info(flag);
5372 } else {
5373 error = storage_info(flag);
5374 }
5375 DBUG_RETURN(error);
5376}
5377
5378uint ha_mroonga::wrapper_lock_count() const
5379{
5380 uint lock_count;
5381 MRN_DBUG_ENTER_METHOD();
5382 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5383 MRN_SET_WRAP_TABLE_KEY(this, table);
5384 lock_count = wrap_handler->lock_count();
5385 MRN_SET_BASE_SHARE_KEY(share, table->s);
5386 MRN_SET_BASE_TABLE_KEY(this, table);
5387 DBUG_RETURN(lock_count);
5388}
5389
5390uint ha_mroonga::storage_lock_count() const
5391{
5392 MRN_DBUG_ENTER_METHOD();
5393 DBUG_RETURN(1);
5394}
5395
5396uint ha_mroonga::lock_count() const
5397{
5398 MRN_DBUG_ENTER_METHOD();
5399 int error = 0;
5400 if (share->wrapper_mode)
5401 {
5402 error = wrapper_lock_count();
5403 } else {
5404 error = storage_lock_count();
5405 }
5406 DBUG_RETURN(error);
5407}
5408
5409THR_LOCK_DATA **ha_mroonga::wrapper_store_lock(THD *thd, THR_LOCK_DATA **to,
5410 enum thr_lock_type lock_type)
5411{
5412 MRN_DBUG_ENTER_METHOD();
5413 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5414 MRN_SET_WRAP_TABLE_KEY(this, table);
5415 to = wrap_handler->store_lock(thd, to, lock_type);
5416 MRN_SET_BASE_SHARE_KEY(share, table->s);
5417 MRN_SET_BASE_TABLE_KEY(this, table);
5418 DBUG_RETURN(to);
5419}
5420
5421THR_LOCK_DATA **ha_mroonga::storage_store_lock(THD *thd, THR_LOCK_DATA **to,
5422 enum thr_lock_type lock_type)
5423{
5424 MRN_DBUG_ENTER_METHOD();
5425 if (lock_type != TL_IGNORE && thr_lock_data.type == TL_UNLOCK) {
5426 if (!thd_in_lock_tables(thd)) {
5427 if (lock_type == TL_READ_NO_INSERT) {
5428 lock_type = TL_READ;
5429 } else if (lock_type >= TL_WRITE_CONCURRENT_INSERT &&
5430 lock_type <= TL_WRITE && !thd_tablespace_op(thd)) {
5431 lock_type = TL_WRITE_ALLOW_WRITE;
5432 }
5433 }
5434
5435 thr_lock_data.type = lock_type;
5436 }
5437 *to++ = &thr_lock_data;
5438 DBUG_RETURN(to);
5439}
5440
5441THR_LOCK_DATA **ha_mroonga::store_lock(THD *thd, THR_LOCK_DATA **to,
5442 enum thr_lock_type lock_type)
5443{
5444 MRN_DBUG_ENTER_METHOD();
5445 DBUG_PRINT("info", ("mroonga: lock_type=%s",
5446 mrn_inspect_thr_lock_type(lock_type)));
5447 if (share->wrapper_mode)
5448 to = wrapper_store_lock(thd, to, lock_type);
5449 else
5450 to = storage_store_lock(thd, to, lock_type);
5451 DBUG_RETURN(to);
5452}
5453
5454int ha_mroonga::wrapper_external_lock(THD *thd, int lock_type)
5455{
5456 int error = 0;
5457 MRN_DBUG_ENTER_METHOD();
5458 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5459 MRN_SET_WRAP_TABLE_KEY(this, table);
5460 error = wrap_handler->ha_external_lock(thd, lock_type);
5461 MRN_SET_BASE_SHARE_KEY(share, table->s);
5462 MRN_SET_BASE_TABLE_KEY(this, table);
5463 DBUG_RETURN(error);
5464}
5465
5466int ha_mroonga::storage_external_lock(THD *thd, int lock_type)
5467{
5468 MRN_DBUG_ENTER_METHOD();
5469 DBUG_RETURN(0);
5470}
5471
5472int ha_mroonga::external_lock(THD *thd, int lock_type)
5473{
5474 MRN_DBUG_ENTER_METHOD();
5475 int error = 0;
5476 mrn_lock_type = lock_type;
5477 if (share->wrapper_mode)
5478 {
5479 error = wrapper_external_lock(thd, lock_type);
5480 } else {
5481 error = storage_external_lock(thd, lock_type);
5482 }
5483 DBUG_RETURN(error);
5484}
5485
5486int ha_mroonga::wrapper_rnd_init(bool scan)
5487{
5488 int error = 0;
5489 MRN_DBUG_ENTER_METHOD();
5490 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5491 MRN_SET_WRAP_TABLE_KEY(this, table);
5492 error = wrap_handler->ha_rnd_init(scan);
5493 MRN_SET_BASE_SHARE_KEY(share, table->s);
5494 MRN_SET_BASE_TABLE_KEY(this, table);
5495 DBUG_RETURN(error);
5496}
5497
5498int ha_mroonga::storage_rnd_init(bool scan)
5499{
5500 MRN_DBUG_ENTER_METHOD();
5501 mrn_change_encoding(ctx, NULL);
5502 cursor = grn_table_cursor_open(ctx, grn_table, NULL, 0, NULL, 0, 0, -1, 0);
5503 if (ctx->rc) {
5504 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
5505 DBUG_RETURN(ER_ERROR_ON_READ);
5506 }
5507 DBUG_RETURN(0);
5508}
5509
5510int ha_mroonga::rnd_init(bool scan)
5511{
5512 MRN_DBUG_ENTER_METHOD();
5513 int error = 0;
5514 if (share->wrapper_mode)
5515 {
5516 error = wrapper_rnd_init(scan);
5517 } else {
5518 error = storage_rnd_init(scan);
5519 }
5520 DBUG_RETURN(error);
5521}
5522
5523int ha_mroonga::wrapper_rnd_end()
5524{
5525 int error = 0;
5526 MRN_DBUG_ENTER_METHOD();
5527 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5528 MRN_SET_WRAP_TABLE_KEY(this, table);
5529 error = wrap_handler->ha_rnd_end();
5530 MRN_SET_BASE_SHARE_KEY(share, table->s);
5531 MRN_SET_BASE_TABLE_KEY(this, table);
5532 DBUG_RETURN(error);
5533}
5534
5535int ha_mroonga::storage_rnd_end()
5536{
5537 MRN_DBUG_ENTER_METHOD();
5538 clear_cursor();
5539 DBUG_RETURN(0);
5540}
5541
5542int ha_mroonga::rnd_end()
5543{
5544 MRN_DBUG_ENTER_METHOD();
5545 int error = 0;
5546 if (share->wrapper_mode)
5547 {
5548 error = wrapper_rnd_end();
5549 } else {
5550 error = storage_rnd_end();
5551 }
5552 DBUG_RETURN(error);
5553}
5554
5555#ifdef MRN_HANDLER_RECORDS_RETURN_ERROR
5556int ha_mroonga::wrapper_records(ha_rows *num_rows)
5557{
5558 int error = 0;
5559 MRN_DBUG_ENTER_METHOD();
5560 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5561 MRN_SET_WRAP_TABLE_KEY(this, table);
5562 error = wrap_handler->ha_records(num_rows);
5563 MRN_SET_BASE_SHARE_KEY(share, table->s);
5564 MRN_SET_BASE_TABLE_KEY(this, table);
5565 DBUG_RETURN(error);
5566}
5567
5568int ha_mroonga::storage_records(ha_rows *num_rows)
5569{
5570 MRN_DBUG_ENTER_METHOD();
5571 int error = handler::records(num_rows);
5572 DBUG_RETURN(error);
5573}
5574
5575int ha_mroonga::records(ha_rows *num_rows)
5576{
5577 MRN_DBUG_ENTER_METHOD();
5578 int error = 0;
5579 if (share->wrapper_mode) {
5580 error = wrapper_records(num_rows);
5581 } else {
5582 error = storage_records(num_rows);
5583 }
5584 DBUG_RETURN(error);
5585}
5586#else
5587ha_rows ha_mroonga::wrapper_records()
5588{
5589 ha_rows num_rows;
5590 MRN_DBUG_ENTER_METHOD();
5591 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5592 MRN_SET_WRAP_TABLE_KEY(this, table);
5593 num_rows = wrap_handler->records();
5594 MRN_SET_BASE_SHARE_KEY(share, table->s);
5595 MRN_SET_BASE_TABLE_KEY(this, table);
5596 DBUG_RETURN(num_rows);
5597}
5598
5599ha_rows ha_mroonga::storage_records()
5600{
5601 MRN_DBUG_ENTER_METHOD();
5602 ha_rows num_rows = handler::records();
5603 DBUG_RETURN(num_rows);
5604}
5605
5606ha_rows ha_mroonga::records()
5607{
5608 MRN_DBUG_ENTER_METHOD();
5609 ha_rows num_rows;
5610 if (share->wrapper_mode) {
5611 num_rows = wrapper_records();
5612 } else {
5613 num_rows = storage_records();
5614 }
5615 DBUG_RETURN(num_rows);
5616}
5617#endif
5618
5619int ha_mroonga::wrapper_rnd_next(uchar *buf)
5620{
5621 int error = 0;
5622 MRN_DBUG_ENTER_METHOD();
5623 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5624 MRN_SET_WRAP_TABLE_KEY(this, table);
5625 if (fulltext_searching)
5626 set_pk_bitmap();
5627#ifdef MRN_HANDLER_HAVE_HA_RND_NEXT
5628 error = wrap_handler->ha_rnd_next(buf);
5629#else
5630 error = wrap_handler->rnd_next(buf);
5631#endif
5632 MRN_SET_BASE_SHARE_KEY(share, table->s);
5633 MRN_SET_BASE_TABLE_KEY(this, table);
5634 DBUG_RETURN(error);
5635}
5636
5637int ha_mroonga::storage_rnd_next(uchar *buf)
5638{
5639 MRN_DBUG_ENTER_METHOD();
5640 int error = storage_get_next_record(buf);
5641 DBUG_RETURN(error);
5642}
5643
5644int ha_mroonga::rnd_next(uchar *buf)
5645{
5646 MRN_DBUG_ENTER_METHOD();
5647 int error = 0;
5648 if (share->wrapper_mode)
5649 {
5650 error = wrapper_rnd_next(buf);
5651 } else {
5652 error = storage_rnd_next(buf);
5653 }
5654 DBUG_RETURN(error);
5655}
5656
5657int ha_mroonga::wrapper_rnd_pos(uchar *buf, uchar *pos)
5658{
5659 int error = 0;
5660 MRN_DBUG_ENTER_METHOD();
5661 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5662 MRN_SET_WRAP_TABLE_KEY(this, table);
5663#ifdef MRN_HANDLER_HAVE_HA_RND_POS
5664 error = wrap_handler->ha_rnd_pos(buf, pos);
5665#else
5666 error = wrap_handler->rnd_pos(buf, pos);
5667#endif
5668 MRN_SET_BASE_SHARE_KEY(share, table->s);
5669 MRN_SET_BASE_TABLE_KEY(this, table);
5670 DBUG_RETURN(error);
5671}
5672
5673int ha_mroonga::storage_rnd_pos(uchar *buf, uchar *pos)
5674{
5675 MRN_DBUG_ENTER_METHOD();
5676 record_id = *((grn_id*) pos);
5677 storage_store_fields(buf, record_id);
5678 DBUG_RETURN(0);
5679}
5680
5681int ha_mroonga::rnd_pos(uchar *buf, uchar *pos)
5682{
5683 MRN_DBUG_ENTER_METHOD();
5684 int error = 0;
5685 if (share->wrapper_mode)
5686 {
5687 error = wrapper_rnd_pos(buf, pos);
5688 } else {
5689 error = storage_rnd_pos(buf, pos);
5690 }
5691 DBUG_RETURN(error);
5692}
5693
5694void ha_mroonga::wrapper_position(const uchar *record)
5695{
5696 MRN_DBUG_ENTER_METHOD();
5697 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5698 MRN_SET_WRAP_TABLE_KEY(this, table);
5699 wrap_handler->ref = ref;
5700 wrap_handler->position(record);
5701 MRN_SET_BASE_SHARE_KEY(share, table->s);
5702 MRN_SET_BASE_TABLE_KEY(this, table);
5703 DBUG_VOID_RETURN;
5704}
5705
5706void ha_mroonga::storage_position(const uchar *record)
5707{
5708 MRN_DBUG_ENTER_METHOD();
5709 memcpy(ref, &record_id, sizeof(grn_id));
5710 DBUG_VOID_RETURN;
5711}
5712
5713void ha_mroonga::position(const uchar *record)
5714{
5715 MRN_DBUG_ENTER_METHOD();
5716 if (share->wrapper_mode)
5717 wrapper_position(record);
5718 else
5719 storage_position(record);
5720 DBUG_VOID_RETURN;
5721}
5722
5723int ha_mroonga::generic_extra(enum ha_extra_function operation)
5724{
5725 MRN_DBUG_ENTER_METHOD();
5726 switch (operation) {
5727 case HA_EXTRA_IGNORE_DUP_KEY:
5728 ignoring_duplicated_key = true;
5729 break;
5730 case HA_EXTRA_NO_IGNORE_DUP_KEY:
5731 ignoring_duplicated_key = false;
5732 break;
5733 case HA_EXTRA_WRITE_CAN_REPLACE:
5734 replacing_ = true;
5735 break;
5736 case HA_EXTRA_WRITE_CANNOT_REPLACE:
5737 replacing_ = false;
5738 break;
5739 case HA_EXTRA_INSERT_WITH_UPDATE:
5740 inserting_with_update = true;
5741 break;
5742 case HA_EXTRA_KEYREAD:
5743 ignoring_no_key_columns = true;
5744 break;
5745 case HA_EXTRA_NO_KEYREAD:
5746 ignoring_no_key_columns = false;
5747 break;
5748 default:
5749 break;
5750 }
5751 DBUG_RETURN(0);
5752}
5753
5754int ha_mroonga::wrapper_extra(enum ha_extra_function operation)
5755{
5756 int error = 0;
5757 MRN_DBUG_ENTER_METHOD();
5758 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5759 MRN_SET_WRAP_TABLE_KEY(this, table);
5760 error = wrap_handler->extra(operation);
5761 MRN_SET_BASE_SHARE_KEY(share, table->s);
5762 MRN_SET_BASE_TABLE_KEY(this, table);
5763 DBUG_RETURN(error);
5764}
5765
5766int ha_mroonga::storage_extra(enum ha_extra_function operation)
5767{
5768 MRN_DBUG_ENTER_METHOD();
5769 DBUG_RETURN(0);
5770}
5771
5772int ha_mroonga::extra(enum ha_extra_function operation)
5773{
5774 int error = 0;
5775 MRN_DBUG_ENTER_METHOD();
5776 DBUG_PRINT("info",
5777 ("mroonga: this=%p; extra-operation=%s",
5778 this, mrn_inspect_extra_function(operation)));
5779 if (share->wrapper_mode) {
5780 if ((error = wrapper_extra(operation)))
5781 DBUG_RETURN(error);
5782 } else {
5783 if ((error = storage_extra(operation)))
5784 DBUG_RETURN(error);
5785 }
5786 error = generic_extra(operation);
5787 DBUG_RETURN(error);
5788}
5789
5790int ha_mroonga::wrapper_extra_opt(enum ha_extra_function operation,
5791 ulong cache_size)
5792{
5793 int error = 0;
5794 MRN_DBUG_ENTER_METHOD();
5795 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5796 MRN_SET_WRAP_TABLE_KEY(this, table);
5797 error = wrap_handler->extra_opt(operation, cache_size);
5798 MRN_SET_BASE_SHARE_KEY(share, table->s);
5799 MRN_SET_BASE_TABLE_KEY(this, table);
5800 DBUG_RETURN(error);
5801}
5802
5803int ha_mroonga::storage_extra_opt(enum ha_extra_function operation,
5804 ulong cache_size)
5805{
5806 MRN_DBUG_ENTER_METHOD();
5807 DBUG_RETURN(0);
5808}
5809
5810int ha_mroonga::extra_opt(enum ha_extra_function operation, ulong cache_size)
5811{
5812 int error = 0;
5813 MRN_DBUG_ENTER_METHOD();
5814 if (share->wrapper_mode)
5815 {
5816 if ((error = wrapper_extra_opt(operation, cache_size)))
5817 DBUG_RETURN(error);
5818 } else {
5819 if ((error = storage_extra_opt(operation, cache_size)))
5820 DBUG_RETURN(error);
5821 }
5822 error = generic_extra(operation);
5823 DBUG_RETURN(error);
5824}
5825
5826bool ha_mroonga::wrapper_is_target_index(KEY *key_info)
5827{
5828 MRN_DBUG_ENTER_METHOD();
5829 bool target_index =
5830 (key_info->algorithm == HA_KEY_ALG_FULLTEXT) || mrn_is_geo_key(key_info);
5831 DBUG_PRINT("info", ("mroonga: %s", target_index ? "true" : "false"));
5832 DBUG_RETURN(target_index);
5833}
5834
5835bool ha_mroonga::wrapper_have_target_index()
5836{
5837 MRN_DBUG_ENTER_METHOD();
5838
5839 bool have_target_index = false;
5840
5841 uint i;
5842 uint n_keys = table->s->keys;
5843 for (i = 0; i < n_keys; i++) {
5844 KEY *key_info = &(table->key_info[i]);
5845
5846 if (wrapper_is_target_index(key_info)) {
5847 have_target_index = true;
5848 break;
5849 }
5850 }
5851
5852 DBUG_PRINT("info", ("mroonga: %s", have_target_index ? "true" : "false"));
5853 DBUG_RETURN(have_target_index);
5854}
5855
5856int ha_mroonga::wrapper_write_row(uchar *buf)
5857{
5858 int error = 0;
5859 THD *thd = ha_thd();
5860
5861 MRN_DBUG_ENTER_METHOD();
5862
5863 mrn::Operation operation(operations_,
5864 "write",
5865 table->s->table_name.str,
5866 table->s->table_name.length);
5867
5868 operation.record_target(record_id);
5869 MRN_SET_WRAP_SHARE_KEY(share, table->s);
5870 MRN_SET_WRAP_TABLE_KEY(this, table);
5871 tmp_disable_binlog(thd);
5872 error = wrap_handler->ha_write_row(buf);
5873 insert_id_for_cur_row = wrap_handler->insert_id_for_cur_row;
5874 reenable_binlog(thd);
5875 MRN_SET_BASE_SHARE_KEY(share, table->s);
5876 MRN_SET_BASE_TABLE_KEY(this, table);
5877
5878 if (!error && wrapper_have_target_index()) {
5879 error = wrapper_write_row_index(buf);
5880 }
5881
5882 DBUG_RETURN(error);
5883}
5884
5885int ha_mroonga::wrapper_write_row_index(uchar *buf)
5886{
5887 MRN_DBUG_ENTER_METHOD();
5888
5889 int error = 0;
5890
5891 if (is_dry_write()) {
5892 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
5893 DBUG_RETURN(error);
5894 }
5895
5896 mrn_change_encoding(ctx, NULL);
5897 GRN_BULK_REWIND(&key_buffer);
5898 grn_bulk_space(ctx, &key_buffer, table->key_info->key_length);
5899 key_copy((uchar *)(GRN_TEXT_VALUE(&key_buffer)),
5900 buf,
5901 &(table->key_info[table_share->primary_key]),
5902 table->key_info[table_share->primary_key].key_length);
5903
5904 int added;
5905 grn_id record_id;
5906 record_id = grn_table_add(ctx, grn_table,
5907 GRN_TEXT_VALUE(&key_buffer),
5908 GRN_TEXT_LEN(&key_buffer),
5909 &added);
5910 if (record_id == GRN_ID_NIL) {
5911 DBUG_PRINT("info", ("mroonga: failed to add a new record into groonga"));
5912 char error_message[MRN_MESSAGE_BUFFER_SIZE];
5913 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
5914 "failed to add a new record into groonga: key=<%.*s>",
5915 (int)GRN_TEXT_LEN(&key_buffer),
5916 GRN_TEXT_VALUE(&key_buffer));
5917 error = ER_ERROR_ON_WRITE;
5918 push_warning(ha_thd(), MRN_SEVERITY_WARNING, error,
5919 error_message);
5920 DBUG_RETURN(0);
5921 }
5922
5923 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
5924 uint i;
5925 uint n_keys = table->s->keys;
5926 for (i = 0; i < n_keys; i++) {
5927 KEY *key_info = &(table->key_info[i]);
5928
5929 if (!(wrapper_is_target_index(key_info))) {
5930 continue;
5931 }
5932
5933 grn_obj *index_column = grn_index_columns[i];
5934 if (!index_column) {
5935 continue;
5936 }
5937
5938 uint j;
5939 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
5940 Field *field = key_info->key_part[j].field;
5941
5942 if (field->is_null())
5943 continue;
5944
5945 error = mrn_change_encoding(ctx, field->charset());
5946 if (error)
5947 goto err;
5948 error = generic_store_bulk(field, &new_value_buffer);
5949 if (error) {
5950 my_message(error,
5951 "mroonga: wrapper: "
5952 "failed to get new value for updating index.",
5953 MYF(0));
5954 goto err;
5955 }
5956
5957 grn_rc rc;
5958 rc = grn_column_index_update(ctx, index_column, record_id, j + 1,
5959 NULL, &new_value_buffer);
5960 if (rc) {
5961 error = ER_ERROR_ON_WRITE;
5962 my_message(error, ctx->errbuf, MYF(0));
5963 goto err;
5964 }
5965 }
5966 }
5967err:
5968
5969 DBUG_RETURN(error);
5970}
5971
5972int ha_mroonga::storage_write_row(uchar *buf)
5973{
5974 MRN_DBUG_ENTER_METHOD();
5975 int error = 0;
5976 bool unique_indexes_are_processed = false;
5977
5978 if (is_dry_write()) {
5979 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
5980 DBUG_RETURN(error);
5981 }
5982
5983 mrn::Operation operation(operations_,
5984 "write",
5985 table->s->table_name.str,
5986 table->s->table_name.length);
5987
5988 THD *thd = ha_thd();
5989 int i;
5990 int n_columns = table->s->fields;
5991
5992 if (table->next_number_field && buf == table->record[0])
5993 {
5994 if ((error = update_auto_increment()))
5995 DBUG_RETURN(error);
5996 }
5997
5998 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
5999 for (i = 0; i < n_columns; i++) {
6000 Field *field = table->field[i];
6001
6002#ifdef MRN_SUPPORT_GENERATED_COLUMNS
6003 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
6004 continue;
6005 }
6006#endif
6007
6008 if (field->is_null()) continue;
6009
6010 mrn::ColumnName column_name(field->field_name);
6011 if (strcmp(MRN_COLUMN_NAME_ID, column_name.c_str()) == 0) {
6012 push_warning_printf(thd, MRN_SEVERITY_WARNING,
6013 WARN_DATA_TRUNCATED,
6014 MRN_GET_ERR_MSG(WARN_DATA_TRUNCATED),
6015 MRN_COLUMN_NAME_ID,
6016 MRN_GET_CURRENT_ROW_FOR_WARNING(thd));
6017 if (MRN_ABORT_ON_WARNING(thd)) {
6018 DBUG_RETURN(ER_DATA_TOO_LONG);
6019 }
6020 }
6021 }
6022
6023 uint pkey_nr = table->s->primary_key;
6024
6025 int added = 0;
6026 {
6027 mrn::Lock lock(&(share->record_mutex), have_unique_index());
6028 if ((error = storage_write_row_unique_indexes(buf)))
6029 {
6030 DBUG_RETURN(error);
6031 }
6032 unique_indexes_are_processed = true;
6033
6034 char *pkey;
6035 int pkey_size;
6036 GRN_BULK_REWIND(&key_buffer);
6037 if (pkey_nr == MAX_INDEXES) {
6038 pkey = NULL;
6039 pkey_size = 0;
6040 } else {
6041 KEY *key_info = &(table->key_info[pkey_nr]);
6042 if (KEY_N_KEY_PARTS(key_info) == 1) {
6043 Field *pkey_field = key_info->key_part[0].field;
6044 error = mrn_change_encoding(ctx, pkey_field->charset());
6045 if (error) {
6046 DBUG_RETURN(error);
6047 }
6048 generic_store_bulk(pkey_field, &key_buffer);
6049 pkey = GRN_TEXT_VALUE(&key_buffer);
6050 pkey_size = GRN_TEXT_LEN(&key_buffer);
6051 } else {
6052 mrn_change_encoding(ctx, NULL);
6053 uchar key[MRN_MAX_KEY_SIZE];
6054 key_copy(key, buf, key_info, key_info->key_length);
6055 grn_bulk_reserve(ctx, &key_buffer, MRN_MAX_KEY_SIZE);
6056 pkey = GRN_TEXT_VALUE(&key_buffer);
6057 storage_encode_multiple_column_key(key_info,
6058 key, key_info->key_length,
6059 (uchar *)pkey, (uint *)&pkey_size);
6060 }
6061 }
6062
6063 if (grn_table->header.type != GRN_TABLE_NO_KEY && pkey_size == 0) {
6064 my_message(ER_ERROR_ON_WRITE, "primary key is empty", MYF(0));
6065 DBUG_RETURN(ER_ERROR_ON_WRITE);
6066 }
6067
6068 record_id = grn_table_add(ctx, grn_table, pkey, pkey_size, &added);
6069 if (ctx->rc) {
6070 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
6071 DBUG_RETURN(ER_ERROR_ON_WRITE);
6072 }
6073 if (!added) {
6074 // duplicated error
6075 error = HA_ERR_FOUND_DUPP_KEY;
6076 memcpy(dup_ref, &record_id, sizeof(grn_id));
6077 dup_key = pkey_nr;
6078 if (!ignoring_duplicated_key) {
6079 GRN_LOG(ctx, GRN_LOG_ERROR,
6080 "duplicated id on insert: update primary key: <%.*s>",
6081 pkey_size, pkey);
6082 }
6083 uint j;
6084 for (j = 0; j < table->s->keys; j++) {
6085 if (j == pkey_nr) {
6086 continue;
6087 }
6088 KEY *key_info = &table->key_info[j];
6089 if (key_info->flags & HA_NOSAME) {
6090 grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]);
6091 }
6092 }
6093 DBUG_RETURN(error);
6094 }
6095 operation.record_target(record_id);
6096 }
6097
6098 grn_obj colbuf;
6099 GRN_VOID_INIT(&colbuf);
6100 for (i = 0; i < n_columns; i++) {
6101 Field *field = table->field[i];
6102
6103 if (field->is_null())
6104 continue;
6105
6106#ifdef MRN_SUPPORT_GENERATED_COLUMNS
6107 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
6108 continue;
6109 }
6110#endif
6111
6112 mrn::ColumnName column_name(field->field_name);
6113
6114#ifdef MRN_HAVE_SPATIAL
6115 bool is_null_geometry_value =
6116 field->real_type() == MYSQL_TYPE_GEOMETRY &&
6117 static_cast<Field_geom *>(field)->get_length() == 0;
6118 if (is_null_geometry_value) {
6119 continue;
6120 }
6121#endif
6122
6123 if (strcmp(MRN_COLUMN_NAME_ID, column_name.c_str()) == 0) {
6124 continue;
6125 }
6126
6127 error = mrn_change_encoding(ctx, field->charset());
6128 if (error) {
6129 GRN_OBJ_FIN(ctx, &colbuf);
6130 goto err;
6131 }
6132 error = generic_store_bulk(field, &colbuf);
6133 if (error) {
6134 GRN_OBJ_FIN(ctx, &colbuf);
6135 goto err;
6136 }
6137
6138 grn_obj *column = grn_columns[i];
6139 if (is_foreign_key_field(table->s->table_name.str, field->field_name.str)) {
6140 grn_obj value;
6141 GRN_RECORD_INIT(&value, 0, grn_obj_get_range(ctx, column));
6142 grn_rc cast_rc = grn_obj_cast(ctx, &colbuf, &value, GRN_FALSE);
6143 if (cast_rc != GRN_SUCCESS) {
6144 grn_obj inspected;
6145 GRN_TEXT_INIT(&inspected, 0);
6146 grn_inspect(ctx, &inspected, &colbuf);
6147 error = HA_ERR_NO_REFERENCED_ROW;
6148 GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
6149 "foreign record doesn't exist: <%s>:<%.*s>",
6150 field->field_name.str,
6151 static_cast<int>(GRN_TEXT_LEN(&inspected)),
6152 GRN_TEXT_VALUE(&inspected));
6153 GRN_OBJ_FIN(ctx, &value);
6154 GRN_OBJ_FIN(ctx, &colbuf);
6155 GRN_OBJ_FIN(ctx, &inspected);
6156 goto err;
6157 }
6158 grn_obj_set_value(ctx, column, record_id, &value, GRN_OBJ_SET);
6159 } else {
6160 if (added && is_grn_zero_column_value(column, &colbuf)) {
6161 // WORKAROUND: groonga can't index newly added '0' value for
6162 // fix size column. So we add non-'0' value first then add
6163 // real '0' value again. It will be removed when groonga
6164 // supports 'null' value.
6165 char *bytes = GRN_BULK_HEAD(&colbuf);
6166 bytes[0] = '\1';
6167 grn_obj_set_value(ctx, column, record_id, &colbuf, GRN_OBJ_SET);
6168 bytes[0] = '\0';
6169 }
6170 grn_obj_set_value(ctx, column, record_id, &colbuf, GRN_OBJ_SET);
6171 }
6172 if (ctx->rc) {
6173 GRN_OBJ_FIN(ctx, &colbuf);
6174 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
6175 error = ER_ERROR_ON_WRITE;
6176 goto err;
6177 }
6178 }
6179 GRN_OBJ_FIN(ctx, &colbuf);
6180
6181 error = storage_write_row_multiple_column_indexes(buf, record_id);
6182 if (error) {
6183 goto err;
6184 }
6185
6186 // for UDF last_insert_grn_id()
6187 st_mrn_slot_data *slot_data;
6188 slot_data = mrn_get_slot_data(thd, true);
6189 if (slot_data == NULL) {
6190 error = HA_ERR_OUT_OF_MEM;
6191 goto err;
6192 }
6193 slot_data->last_insert_record_id = record_id;
6194
6195 grn_db_touch(ctx, grn_ctx_db(ctx));
6196
6197 if (table->found_next_number_field &&
6198 !table->s->next_number_keypart) {
6199 Field_num *field = (Field_num *) table->found_next_number_field;
6200 if (field->unsigned_flag || field->val_int() > 0) {
6201 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
6202 ulonglong nr = (ulonglong) field->val_int();
6203 if (!long_term_share->auto_inc_inited) {
6204 storage_info(HA_STATUS_AUTO);
6205 }
6206 {
6207 mrn::Lock lock(&long_term_share->auto_inc_mutex);
6208 if (long_term_share->auto_inc_value <= nr) {
6209 long_term_share->auto_inc_value = nr + 1;
6210 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
6211 long_term_share->auto_inc_value));
6212 }
6213 }
6214 }
6215 }
6216 DBUG_RETURN(0);
6217
6218err:
6219 if (unique_indexes_are_processed) {
6220 uint j;
6221 for (j = 0; j < table->s->keys; j++) {
6222 if (j == pkey_nr) {
6223 continue;
6224 }
6225 KEY *key_info = &table->key_info[j];
6226 if (key_info->flags & HA_NOSAME) {
6227 grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]);
6228 }
6229 }
6230 }
6231 grn_table_delete_by_id(ctx, grn_table, record_id);
6232 DBUG_RETURN(error);
6233}
6234
6235int ha_mroonga::storage_write_row_multiple_column_index(uchar *buf,
6236 grn_id record_id,
6237 KEY *key_info,
6238 grn_obj *index_column)
6239{
6240 MRN_DBUG_ENTER_METHOD();
6241 int error = 0;
6242
6243 mrn_change_encoding(ctx, NULL);
6244 GRN_BULK_REWIND(&key_buffer);
6245 grn_bulk_space(ctx, &key_buffer, key_info->key_length);
6246 key_copy((uchar *)(GRN_TEXT_VALUE(&key_buffer)),
6247 buf,
6248 key_info,
6249 key_info->key_length);
6250 GRN_BULK_REWIND(&encoded_key_buffer);
6251 grn_bulk_reserve(ctx, &encoded_key_buffer, MRN_MAX_KEY_SIZE);
6252 uint encoded_key_length;
6253 storage_encode_multiple_column_key(key_info,
6254 (uchar *)(GRN_TEXT_VALUE(&key_buffer)),
6255 key_info->key_length,
6256 (uchar *)(GRN_TEXT_VALUE(&encoded_key_buffer)),
6257 &encoded_key_length);
6258 grn_bulk_space(ctx, &encoded_key_buffer, encoded_key_length);
6259 DBUG_PRINT("info", ("mroonga: key_length=%u", key_info->key_length));
6260 DBUG_PRINT("info", ("mroonga: encoded_key_length=%u", encoded_key_length));
6261
6262 grn_rc rc;
6263 rc = grn_column_index_update(ctx, index_column, record_id, 1, NULL,
6264 &encoded_key_buffer);
6265 if (rc) {
6266 error = ER_ERROR_ON_WRITE;
6267 my_message(error, ctx->errbuf, MYF(0));
6268 }
6269 DBUG_RETURN(error);
6270}
6271
6272int ha_mroonga::storage_write_row_multiple_column_indexes(uchar *buf,
6273 grn_id record_id)
6274{
6275 MRN_DBUG_ENTER_METHOD();
6276
6277 int error = 0;
6278
6279 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
6280 uint i;
6281 uint n_keys = table->s->keys;
6282 for (i = 0; i < n_keys; i++) {
6283 if (i == table->s->primary_key) {
6284 continue;
6285 }
6286
6287 KEY *key_info = &(table->key_info[i]);
6288
6289 if (KEY_N_KEY_PARTS(key_info) == 1 || (key_info->flags & HA_FULLTEXT)) {
6290 continue;
6291 }
6292
6293 grn_obj *index_column = grn_index_columns[i];
6294 if (!index_column) {
6295 continue;
6296 }
6297
6298 if ((error = storage_write_row_multiple_column_index(buf,
6299 record_id,
6300 key_info,
6301 index_column)))
6302 {
6303 goto err;
6304 }
6305 }
6306
6307err:
6308
6309 DBUG_RETURN(error);
6310}
6311
6312int ha_mroonga::storage_write_row_unique_index(const uchar *buf,
6313 KEY *key_info,
6314 grn_obj *index_table,
6315 grn_obj *index_column,
6316 grn_id *key_id)
6317{
6318 char *ukey = NULL;
6319 int error, ukey_size = 0;
6320 MRN_DBUG_ENTER_METHOD();
6321 GRN_BULK_REWIND(&key_buffer);
6322 if (KEY_N_KEY_PARTS(key_info) == 1) {
6323 Field *ukey_field = key_info->key_part[0].field;
6324 error = mrn_change_encoding(ctx, ukey_field->charset());
6325 if (error) {
6326 DBUG_RETURN(error);
6327 }
6328 generic_store_bulk(ukey_field, &key_buffer);
6329 ukey = GRN_TEXT_VALUE(&key_buffer);
6330 ukey_size = GRN_TEXT_LEN(&key_buffer);
6331 } else {
6332 mrn_change_encoding(ctx, NULL);
6333 uchar key[MRN_MAX_KEY_SIZE];
6334 key_copy(key, buf, key_info, key_info->key_length);
6335 grn_bulk_reserve(ctx, &key_buffer, MRN_MAX_KEY_SIZE);
6336 ukey = GRN_TEXT_VALUE(&key_buffer);
6337 storage_encode_multiple_column_key(key_info,
6338 key, key_info->key_length,
6339 (uchar *)(ukey), (uint *)&ukey_size);
6340 }
6341
6342 int added;
6343 *key_id = grn_table_add(ctx, index_table, ukey, ukey_size, &added);
6344 if (ctx->rc) {
6345 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
6346 DBUG_RETURN(ER_ERROR_ON_WRITE);
6347 }
6348 if (!added) {
6349 // duplicated error
6350 error = HA_ERR_FOUND_DUPP_KEY;
6351 grn_id duplicated_record_id = GRN_ID_NIL;
6352 {
6353 grn_table_cursor *table_cursor;
6354 table_cursor = grn_table_cursor_open(ctx, index_table,
6355 ukey, ukey_size,
6356 ukey, ukey_size,
6357 0, -1, 0);
6358 if (table_cursor) {
6359 grn_obj *index_cursor;
6360 index_cursor = grn_index_cursor_open(ctx, table_cursor, index_column,
6361 GRN_ID_NIL, GRN_ID_MAX, 0);
6362 if (index_cursor) {
6363 grn_posting *posting;
6364 posting = grn_index_cursor_next(ctx, index_cursor, NULL);
6365 if (posting) {
6366 duplicated_record_id = posting->rid;
6367 }
6368 }
6369 grn_obj_unlink(ctx, index_cursor);
6370 }
6371 grn_table_cursor_close(ctx, table_cursor);
6372 }
6373 memcpy(dup_ref, &duplicated_record_id, sizeof(grn_id));
6374 if (!ignoring_duplicated_key) {
6375 GRN_LOG(ctx, GRN_LOG_ERROR,
6376 "duplicated id on insert: update unique index: <%.*s>",
6377 ukey_size, ukey);
6378 }
6379 DBUG_RETURN(error);
6380 }
6381 DBUG_RETURN(0);
6382}
6383
6384int ha_mroonga::storage_write_row_unique_indexes(uchar *buf)
6385{
6386 int error = 0;
6387 uint i;
6388 uint n_keys = table->s->keys;
6389 MRN_DBUG_ENTER_METHOD();
6390
6391 for (i = 0; i < n_keys; i++) {
6392 if (i == table->s->primary_key) {
6393 continue;
6394 }
6395
6396 KEY *key_info = &table->key_info[i];
6397
6398 if (!(key_info->flags & HA_NOSAME)) {
6399 continue;
6400 }
6401
6402 grn_obj *index_table = grn_index_tables[i];
6403 if (!index_table) {
6404 continue;
6405 }
6406 grn_obj *index_column = grn_index_columns[i];
6407 if (!index_column) {
6408 continue;
6409 }
6410
6411 if ((error = storage_write_row_unique_index(buf, key_info,
6412 index_table, index_column,
6413 &key_id[i])))
6414 {
6415 if (error == HA_ERR_FOUND_DUPP_KEY)
6416 {
6417 dup_key = i;
6418 }
6419 goto err;
6420 }
6421 }
6422 DBUG_RETURN(0);
6423
6424err:
6425 if (i) {
6426 mrn_change_encoding(ctx, NULL);
6427 do {
6428 i--;
6429
6430 if (i == table->s->primary_key) {
6431 continue;
6432 }
6433
6434 KEY *key_info = &table->key_info[i];
6435 if (!(key_info->flags & HA_NOSAME)) {
6436 continue;
6437 }
6438
6439 if (key_info->flags & HA_NOSAME) {
6440 grn_table_delete_by_id(ctx, grn_index_tables[i], key_id[i]);
6441 }
6442 } while (i);
6443 }
6444 DBUG_RETURN(error);
6445}
6446
6447int ha_mroonga::write_row(uchar *buf)
6448{
6449 MRN_DBUG_ENTER_METHOD();
6450 int error = 0;
6451 if (share->wrapper_mode)
6452 {
6453 error = wrapper_write_row(buf);
6454 } else {
6455 error = storage_write_row(buf);
6456 }
6457 DBUG_RETURN(error);
6458}
6459
6460int ha_mroonga::wrapper_get_record_id(uchar *data, grn_id *record_id,
6461 const char *context)
6462{
6463 MRN_DBUG_ENTER_METHOD();
6464
6465 int error = 0;
6466
6467 grn_obj key;
6468 GRN_TEXT_INIT(&key, 0);
6469
6470 mrn_change_encoding(ctx, NULL);
6471 grn_bulk_space(ctx, &key, table->key_info->key_length);
6472 key_copy((uchar *)(GRN_TEXT_VALUE(&key)),
6473 data,
6474 &(table->key_info[table_share->primary_key]),
6475 table->key_info[table_share->primary_key].key_length);
6476
6477 *record_id = grn_table_get(ctx, grn_table,
6478 GRN_TEXT_VALUE(&key), GRN_TEXT_LEN(&key));
6479 if (*record_id == GRN_ID_NIL) {
6480 DBUG_PRINT("info", ("mroonga: %s", context));
6481 char error_message[MRN_MESSAGE_BUFFER_SIZE];
6482 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
6483 "%s: key=<%.*s>",
6484 context, (int)GRN_TEXT_LEN(&key), GRN_TEXT_VALUE(&key));
6485 error = ER_ERROR_ON_WRITE;
6486 push_warning(ha_thd(), MRN_SEVERITY_WARNING, error,
6487 error_message);
6488 }
6489 grn_obj_unlink(ctx, &key);
6490
6491 DBUG_RETURN(error);
6492}
6493
6494int ha_mroonga::wrapper_update_row(const uchar *old_data,
6495 const uchar *new_data)
6496{
6497 MRN_DBUG_ENTER_METHOD();
6498
6499 int error = 0;
6500 THD *thd = ha_thd();
6501
6502 mrn::Operation operation(operations_,
6503 "update",
6504 table->s->table_name.str,
6505 table->s->table_name.length);
6506
6507 MRN_SET_WRAP_SHARE_KEY(share, table->s);
6508 MRN_SET_WRAP_TABLE_KEY(this, table);
6509 tmp_disable_binlog(thd);
6510 error = wrap_handler->ha_update_row(old_data, new_data);
6511 reenable_binlog(thd);
6512 MRN_SET_BASE_SHARE_KEY(share, table->s);
6513 MRN_SET_BASE_TABLE_KEY(this, table);
6514
6515 if (!error && wrapper_have_target_index()) {
6516 error = wrapper_update_row_index(old_data, new_data);
6517 }
6518
6519 DBUG_RETURN(error);
6520}
6521
6522int ha_mroonga::wrapper_update_row_index(const uchar *old_data,
6523 const uchar *new_data)
6524{
6525 MRN_DBUG_ENTER_METHOD();
6526
6527 int error = 0;
6528
6529 if (is_dry_write()) {
6530 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
6531 DBUG_RETURN(error);
6532 }
6533
6534 mrn_change_encoding(ctx, NULL);
6535 KEY *key_info = &(table->key_info[table_share->primary_key]);
6536 GRN_BULK_REWIND(&key_buffer);
6537 key_copy((uchar *)(GRN_TEXT_VALUE(&key_buffer)),
6538 new_data,
6539 key_info, key_info->key_length);
6540 int added;
6541 grn_id new_record_id;
6542 new_record_id = grn_table_add(ctx, grn_table,
6543 GRN_TEXT_VALUE(&key_buffer),
6544 table->key_info->key_length,
6545 &added);
6546 if (new_record_id == GRN_ID_NIL) {
6547 char error_message[MRN_MESSAGE_BUFFER_SIZE];
6548 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
6549 "failed to get new record ID for updating from groonga: key=<%.*s>",
6550 (int)GRN_TEXT_LEN(&key_buffer), GRN_TEXT_VALUE(&key_buffer));
6551 error = ER_ERROR_ON_WRITE;
6552 my_message(error, error_message, MYF(0));
6553 DBUG_RETURN(error);
6554 }
6555
6556 grn_id old_record_id;
6557 my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(old_data, table->record[0]);
6558 for (uint j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6559 Field *field = key_info->key_part[j].field;
6560 field->move_field_offset(ptr_diff);
6561 }
6562 error = wrapper_get_record_id((uchar *)old_data, &old_record_id,
6563 "failed to get old record ID "
6564 "for updating from groonga");
6565 for (uint j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6566 Field *field = key_info->key_part[j].field;
6567 field->move_field_offset(-ptr_diff);
6568 }
6569 if (error) {
6570 DBUG_RETURN(0);
6571 }
6572
6573 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
6574 uint i;
6575 uint n_keys = table->s->keys;
6576 for (i = 0; i < n_keys; i++) {
6577 KEY *key_info = &(table->key_info[i]);
6578
6579 if (!(wrapper_is_target_index(key_info))) {
6580 continue;
6581 }
6582
6583 grn_obj *index_column = grn_index_columns[i];
6584 if (!index_column) {
6585 /* disable keys */
6586 continue;
6587 }
6588
6589 uint j;
6590 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6591 Field *field = key_info->key_part[j].field;
6592
6593 generic_store_bulk(field, &new_value_buffer);
6594
6595 field->move_field_offset(ptr_diff);
6596 generic_store_bulk(field, &old_value_buffer);
6597 field->move_field_offset(-ptr_diff);
6598
6599 grn_rc rc;
6600 if (old_record_id == new_record_id) {
6601 if (added) {
6602 rc = grn_column_index_update(ctx, index_column, old_record_id, j + 1,
6603 &old_value_buffer, NULL);
6604 if (!rc) {
6605 rc = grn_column_index_update(ctx, index_column, new_record_id, j + 1,
6606 NULL, &new_value_buffer);
6607 }
6608 } else {
6609 rc = grn_column_index_update(ctx, index_column, old_record_id, j + 1,
6610 &old_value_buffer, &new_value_buffer);
6611 }
6612 } else {
6613 rc = grn_column_index_update(ctx, index_column, old_record_id, j + 1,
6614 &old_value_buffer, NULL);
6615 if (!rc) {
6616 rc = grn_column_index_update(ctx, index_column, new_record_id, j + 1,
6617 NULL, &new_value_buffer);
6618 }
6619 if (!rc) {
6620 rc = grn_table_delete_by_id(ctx, grn_table, old_record_id);
6621 }
6622 }
6623 if (rc) {
6624 error = ER_ERROR_ON_WRITE;
6625 my_message(error, ctx->errbuf, MYF(0));
6626 goto err;
6627 }
6628 }
6629 }
6630err:
6631
6632 DBUG_RETURN(error);
6633}
6634
6635int ha_mroonga::storage_update_row(const uchar *old_data,
6636 const uchar *new_data)
6637{
6638 MRN_DBUG_ENTER_METHOD();
6639 int error = 0;
6640
6641 if (is_dry_write()) {
6642 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
6643 DBUG_RETURN(error);
6644 }
6645
6646 mrn::Operation operation(operations_,
6647 "update",
6648 table->s->table_name.str,
6649 table->s->table_name.length);
6650 operation.record_target(record_id);
6651
6652 grn_obj colbuf;
6653 int i;
6654 uint j;
6655 int n_columns = table->s->fields;
6656 THD *thd = ha_thd();
6657
6658 for (i = 0; i < n_columns; i++) {
6659 Field *field = table->field[i];
6660
6661#ifdef MRN_SUPPORT_GENERATED_COLUMNS
6662 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
6663 continue;
6664 }
6665#endif
6666
6667 if (!bitmap_is_set(table->write_set, field->field_index))
6668 continue;
6669
6670 if (field->is_null())
6671 continue;
6672
6673 {
6674 mrn::ColumnName column_name(field->field_name);
6675 if (strcmp(MRN_COLUMN_NAME_ID, column_name.c_str()) == 0) {
6676 push_warning_printf(thd, MRN_SEVERITY_WARNING,
6677 WARN_DATA_TRUNCATED, MRN_GET_ERR_MSG(WARN_DATA_TRUNCATED),
6678 MRN_COLUMN_NAME_ID,
6679 MRN_GET_CURRENT_ROW_FOR_WARNING(thd));
6680 if (MRN_ABORT_ON_WARNING(thd)) {
6681 DBUG_RETURN(ER_DATA_TOO_LONG);
6682 }
6683 }
6684 }
6685
6686 if (!is_foreign_key_field(table->s->table_name.str, field->field_name.str))
6687 continue;
6688
6689 {
6690 grn_obj *column = grn_columns[i];
6691 grn_obj new_value;
6692 GRN_VOID_INIT(&new_value);
6693 {
6694 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
6695 generic_store_bulk(field, &new_value);
6696 }
6697 grn_obj casted_value;
6698 GRN_RECORD_INIT(&casted_value, 0, grn_obj_get_range(ctx, column));
6699 grn_rc cast_rc = grn_obj_cast(ctx, &new_value, &casted_value, GRN_FALSE);
6700 GRN_OBJ_FIN(ctx, &casted_value);
6701 if (cast_rc != GRN_SUCCESS) {
6702 grn_obj inspected;
6703 GRN_TEXT_INIT(&inspected, 0);
6704 grn_inspect(ctx, &inspected, &new_value);
6705 GRN_OBJ_FIN(ctx, &new_value);
6706 error = HA_ERR_NO_REFERENCED_ROW;
6707 GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
6708 "foreign record doesn't exist: <%s>:<%.*s>",
6709 field->field_name.str,
6710 static_cast<int>(GRN_TEXT_LEN(&inspected)),
6711 GRN_TEXT_VALUE(&inspected));
6712 GRN_OBJ_FIN(ctx, &inspected);
6713 DBUG_RETURN(error);
6714 }
6715 GRN_OBJ_FIN(ctx, &new_value);
6716 }
6717 }
6718
6719 KEY *pkey_info = NULL;
6720 storage_store_fields_for_prep_update(old_data, new_data, record_id);
6721 {
6722 mrn::Lock lock(&(share->record_mutex), have_unique_index());
6723 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
6724 if ((error = storage_prepare_delete_row_unique_indexes(old_data,
6725 record_id))) {
6726 DBUG_RETURN(error);
6727 }
6728 if ((error = storage_update_row_unique_indexes(new_data)))
6729 {
6730 DBUG_RETURN(error);
6731 }
6732 }
6733
6734 if (table->s->primary_key != MAX_INDEXES) {
6735 pkey_info = &(table->key_info[table->s->primary_key]);
6736 }
6737 GRN_VOID_INIT(&colbuf);
6738 for (i = 0; i < n_columns; i++) {
6739 Field *field = table->field[i];
6740
6741#ifdef MRN_SUPPORT_GENERATED_COLUMNS
6742 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
6743 continue;
6744 }
6745#endif
6746
6747 if (bitmap_is_set(table->write_set, field->field_index)) {
6748 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
6749 DBUG_PRINT("info", ("mroonga: update column %d(%d)",i,field->field_index));
6750
6751 if (field->is_null()) continue;
6752
6753 mrn::ColumnName column_name(field->field_name);
6754 if (strcmp(MRN_COLUMN_NAME_ID, column_name.c_str()) == 0) {
6755 continue;
6756 }
6757
6758 error = mrn_change_encoding(ctx, field->charset());
6759 if (error)
6760 goto err;
6761
6762 bool is_pkey = false;
6763 bool on_duplicate_key_update =
6764 (inserting_with_update && ignoring_duplicated_key);
6765 if (pkey_info && !on_duplicate_key_update) {
6766 for (j = 0; j < KEY_N_KEY_PARTS(pkey_info); j++) {
6767 Field *pkey_field = pkey_info->key_part[j].field;
6768 if (strcmp(pkey_field->field_name.str, column_name.c_str()) == 0) {
6769 is_pkey = true;
6770 break;
6771 }
6772 }
6773 }
6774
6775 generic_store_bulk(field, &colbuf);
6776 if (is_pkey) {
6777 bool is_multiple_column_index = KEY_N_KEY_PARTS(pkey_info) > 1;
6778 bool is_same_value;
6779 if (is_multiple_column_index) {
6780 is_same_value = false;
6781 } else {
6782 grn_id found_record_id = grn_table_get(ctx,
6783 grn_table,
6784 GRN_BULK_HEAD(&colbuf),
6785 GRN_BULK_VSIZE(&colbuf));
6786 is_same_value = (record_id == found_record_id);
6787 }
6788 if (!is_same_value && !replacing_) {
6789 char message[MRN_BUFFER_SIZE];
6790 snprintf(message, MRN_BUFFER_SIZE,
6791 "data truncated for primary key column: <%s>",
6792 column_name.c_str());
6793 push_warning(thd, MRN_SEVERITY_WARNING,
6794 WARN_DATA_TRUNCATED, message);
6795 }
6796 continue;
6797 }
6798
6799 grn_obj_set_value(ctx, grn_columns[i], record_id, &colbuf, GRN_OBJ_SET);
6800 if (ctx->rc) {
6801 grn_obj_unlink(ctx, &colbuf);
6802 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
6803 error = ER_ERROR_ON_WRITE;
6804 goto err;
6805 }
6806 }
6807 }
6808 grn_obj_unlink(ctx, &colbuf);
6809
6810 if ((error = storage_update_row_index(old_data, new_data)))
6811 {
6812 goto err;
6813 }
6814
6815 if ((error = storage_delete_row_unique_indexes()))
6816 {
6817 DBUG_RETURN(error);
6818 }
6819
6820 grn_db_touch(ctx, grn_ctx_db(ctx));
6821
6822 if (table->found_next_number_field &&
6823 !table->s->next_number_keypart &&
6824 new_data == table->record[0]) {
6825 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
6826 Field_num *field = (Field_num *) table->found_next_number_field;
6827 if (field->unsigned_flag || field->val_int() > 0) {
6828 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
6829 ulonglong nr = (ulonglong) field->val_int();
6830 if (!long_term_share->auto_inc_inited) {
6831 storage_info(HA_STATUS_AUTO);
6832 }
6833 {
6834 mrn::Lock lock(&long_term_share->auto_inc_mutex);
6835 if (long_term_share->auto_inc_value <= nr) {
6836 long_term_share->auto_inc_value = nr + 1;
6837 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
6838 long_term_share->auto_inc_value));
6839 }
6840 }
6841 }
6842 }
6843 DBUG_RETURN(0);
6844
6845err:
6846 for (j = 0; j < table->s->keys; j++) {
6847 if (j == table->s->primary_key) {
6848 continue;
6849 }
6850 KEY *key_info = &table->key_info[j];
6851 if ((key_info->flags & HA_NOSAME) && key_id[j] != GRN_ID_NIL) {
6852 grn_table_delete_by_id(ctx, grn_index_tables[j], key_id[j]);
6853 }
6854 }
6855
6856 if (!error && thd_sql_command(ha_thd()) == SQLCOM_TRUNCATE) {
6857 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
6858 mrn::Lock lock(&long_term_share->auto_inc_mutex);
6859 long_term_share->auto_inc_value = 0;
6860 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
6861 long_term_share->auto_inc_value));
6862 long_term_share->auto_inc_inited = false;
6863 }
6864
6865 DBUG_RETURN(error);
6866}
6867
6868int ha_mroonga::storage_update_row_index(const uchar *old_data,
6869 const uchar *new_data)
6870{
6871 MRN_DBUG_ENTER_METHOD();
6872 int error = 0;
6873
6874 grn_obj old_key, old_encoded_key, new_key, new_encoded_key;
6875 GRN_TEXT_INIT(&old_key, 0);
6876 GRN_TEXT_INIT(&old_encoded_key, 0);
6877 GRN_TEXT_INIT(&new_key, 0);
6878 GRN_TEXT_INIT(&new_encoded_key, 0);
6879
6880 my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(old_data, table->record[0]);
6881
6882 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
6883 uint i;
6884 uint n_keys = table->s->keys;
6885 mrn_change_encoding(ctx, NULL);
6886 for (i = 0; i < n_keys; i++) {
6887 if (i == table->s->primary_key) {
6888 continue;
6889 }
6890
6891 KEY *key_info = &(table->key_info[i]);
6892
6893 if (KEY_N_KEY_PARTS(key_info) == 1 || (key_info->flags & HA_FULLTEXT)) {
6894 continue;
6895 }
6896
6897 grn_obj *index_column = grn_index_columns[i];
6898 if (!index_column) {
6899 /* disable keys */
6900 continue;
6901 }
6902
6903 GRN_BULK_REWIND(&old_key);
6904 grn_bulk_space(ctx, &old_key, key_info->key_length);
6905 for (uint j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6906 Field *field = key_info->key_part[j].field;
6907 field->move_field_offset(ptr_diff);
6908 }
6909 key_copy((uchar *)(GRN_TEXT_VALUE(&old_key)),
6910 (uchar *)old_data,
6911 key_info,
6912 key_info->key_length);
6913 for (uint j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
6914 Field *field = key_info->key_part[j].field;
6915 field->move_field_offset(-ptr_diff);
6916 }
6917 GRN_BULK_REWIND(&old_encoded_key);
6918 grn_bulk_reserve(ctx, &old_encoded_key, MRN_MAX_KEY_SIZE);
6919 uint old_encoded_key_length;
6920 storage_encode_multiple_column_key(key_info,
6921 (uchar *)(GRN_TEXT_VALUE(&old_key)),
6922 key_info->key_length,
6923 (uchar *)(GRN_TEXT_VALUE(&old_encoded_key)),
6924 &old_encoded_key_length);
6925 grn_bulk_space(ctx, &old_encoded_key, old_encoded_key_length);
6926
6927 GRN_BULK_REWIND(&new_key);
6928 grn_bulk_space(ctx, &new_key, key_info->key_length);
6929 key_copy((uchar *)(GRN_TEXT_VALUE(&new_key)),
6930 (uchar *)new_data,
6931 key_info,
6932 key_info->key_length);
6933 GRN_BULK_REWIND(&new_encoded_key);
6934 grn_bulk_reserve(ctx, &new_encoded_key, MRN_MAX_KEY_SIZE);
6935 uint new_encoded_key_length;
6936 storage_encode_multiple_column_key(key_info,
6937 (uchar *)(GRN_TEXT_VALUE(&new_key)),
6938 key_info->key_length,
6939 (uchar *)(GRN_TEXT_VALUE(&new_encoded_key)),
6940 &new_encoded_key_length);
6941 grn_bulk_space(ctx, &new_encoded_key, new_encoded_key_length);
6942
6943 grn_rc rc;
6944 rc = grn_column_index_update(ctx, index_column, record_id, 1,
6945 &old_encoded_key, &new_encoded_key);
6946 if (rc) {
6947 error = ER_ERROR_ON_WRITE;
6948 my_message(error, ctx->errbuf, MYF(0));
6949 goto err;
6950 }
6951 }
6952err:
6953 grn_obj_unlink(ctx, &old_key);
6954 grn_obj_unlink(ctx, &old_encoded_key);
6955 grn_obj_unlink(ctx, &new_key);
6956 grn_obj_unlink(ctx, &new_encoded_key);
6957
6958 DBUG_RETURN(error);
6959}
6960
6961int ha_mroonga::storage_update_row_unique_indexes(const uchar *new_data)
6962{
6963 int error;
6964 uint i;
6965 uint n_keys = table->s->keys;
6966 MRN_DBUG_ENTER_METHOD();
6967
6968 for (i = 0; i < n_keys; i++) {
6969 if (i == table->s->primary_key) {
6970 continue;
6971 }
6972
6973 KEY *key_info = &table->key_info[i];
6974 if (!(key_info->flags & HA_NOSAME)) {
6975 continue;
6976 }
6977
6978 grn_obj *index_table = grn_index_tables[i];
6979 if (!index_table) {
6980 key_id[i] = GRN_ID_NIL;
6981 del_key_id[i] = GRN_ID_NIL;
6982 continue;
6983 }
6984
6985 grn_obj *index_column = grn_index_columns[i];
6986 if (!index_column) {
6987 key_id[i] = GRN_ID_NIL;
6988 del_key_id[i] = GRN_ID_NIL;
6989 continue;
6990 }
6991
6992 if (
6993 KEY_N_KEY_PARTS(key_info) == 1 &&
6994 !bitmap_is_set(table->write_set,
6995 key_info->key_part[0].field->field_index)
6996 ) {
6997 /* no change */
6998 key_id[i] = GRN_ID_NIL;
6999 del_key_id[i] = GRN_ID_NIL;
7000 continue;
7001 }
7002
7003 if ((error = storage_write_row_unique_index(new_data, key_info,
7004 index_table, index_column,
7005 &key_id[i])))
7006 {
7007 if (error == HA_ERR_FOUND_DUPP_KEY)
7008 {
7009 if (key_id[i] == del_key_id[i]) {
7010 /* no change */
7011 key_id[i] = GRN_ID_NIL;
7012 del_key_id[i] = GRN_ID_NIL;
7013 continue;
7014 }
7015 dup_key = i;
7016 DBUG_PRINT("info", ("mroonga: different key ID: %d record ID: %d,%d",
7017 i, key_id[i], del_key_id[i]));
7018 }
7019 goto err;
7020 }
7021 }
7022 DBUG_RETURN(0);
7023
7024err:
7025 if (i) {
7026 mrn_change_encoding(ctx, NULL);
7027 do {
7028 i--;
7029 KEY *key_info = &table->key_info[i];
7030 if ((key_info->flags & HA_NOSAME) && key_id[i] != GRN_ID_NIL) {
7031 grn_table_delete_by_id(ctx, grn_index_tables[i], key_id[i]);
7032 }
7033 } while (i);
7034 }
7035 DBUG_RETURN(error);
7036}
7037
7038int ha_mroonga::update_row(const uchar *old_data, const uchar *new_data)
7039{
7040 MRN_DBUG_ENTER_METHOD();
7041 int error = 0;
7042 if (share->wrapper_mode)
7043 {
7044 error = wrapper_update_row(old_data, new_data);
7045 } else {
7046 error = storage_update_row(old_data, new_data);
7047 }
7048 DBUG_RETURN(error);
7049}
7050
7051int ha_mroonga::wrapper_delete_row(const uchar *buf)
7052{
7053 MRN_DBUG_ENTER_METHOD();
7054
7055 int error = 0;
7056 THD *thd= ha_thd();
7057
7058 mrn::Operation operation(operations_,
7059 "delete",
7060 table->s->table_name.str,
7061 table->s->table_name.length);
7062
7063 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7064 MRN_SET_WRAP_TABLE_KEY(this, table);
7065 tmp_disable_binlog(thd);
7066 error = wrap_handler->ha_delete_row(buf);
7067 reenable_binlog(thd);
7068 MRN_SET_BASE_SHARE_KEY(share, table->s);
7069 MRN_SET_BASE_TABLE_KEY(this, table);
7070
7071 if (!error && wrapper_have_target_index()) {
7072 error = wrapper_delete_row_index(buf);
7073 }
7074
7075 DBUG_RETURN(error);
7076}
7077
7078int ha_mroonga::wrapper_delete_row_index(const uchar *buf)
7079{
7080 MRN_DBUG_ENTER_METHOD();
7081
7082 int error = 0;
7083
7084 if (is_dry_write()) {
7085 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
7086 DBUG_RETURN(error);
7087 }
7088
7089 mrn_change_encoding(ctx, NULL);
7090 grn_id record_id;
7091 error = wrapper_get_record_id((uchar *)buf, &record_id,
7092 "failed to get record ID "
7093 "for deleting from groonga");
7094 if (error) {
7095 DBUG_RETURN(0);
7096 }
7097
7098 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
7099 uint i;
7100 uint n_keys = table->s->keys;
7101 for (i = 0; i < n_keys; i++) {
7102 KEY *key_info = &(table->key_info[i]);
7103
7104 if (!(wrapper_is_target_index(key_info))) {
7105 continue;
7106 }
7107
7108 grn_obj *index_column = grn_index_columns[i];
7109 if (!index_column) {
7110 /* disable keys */
7111 continue;
7112 }
7113
7114 uint j;
7115 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
7116 Field *field = key_info->key_part[j].field;
7117
7118 if (field->is_null())
7119 continue;
7120
7121 generic_store_bulk(field, &old_value_buffer);
7122 grn_rc rc;
7123 rc = grn_column_index_update(ctx, index_column, record_id, j + 1,
7124 &old_value_buffer, NULL);
7125 if (rc) {
7126 error = ER_ERROR_ON_WRITE;
7127 my_message(error, ctx->errbuf, MYF(0));
7128 goto err;
7129 }
7130 }
7131 }
7132err:
7133 grn_table_delete_by_id(ctx, grn_table, record_id);
7134 if (ctx->rc) {
7135 error = ER_ERROR_ON_WRITE;
7136 my_message(error, ctx->errbuf, MYF(0));
7137 }
7138
7139 DBUG_RETURN(error);
7140}
7141
7142int ha_mroonga::storage_delete_row(const uchar *buf)
7143{
7144 MRN_DBUG_ENTER_METHOD();
7145 int error;
7146
7147 if (is_dry_write()) {
7148 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
7149 DBUG_RETURN(0);
7150 }
7151
7152 mrn::Operation operation(operations_,
7153 "delete",
7154 table->s->table_name.str,
7155 table->s->table_name.length);
7156 operation.record_target(record_id);
7157
7158 {
7159 grn_id referencing_child_table_id = GRN_ID_NIL;
7160 grn_hash *columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0,
7161 GRN_OBJ_TABLE_HASH_KEY|GRN_HASH_TINY);
7162 grn_table_columns(ctx, grn_table, "", 0,
7163 reinterpret_cast<grn_obj *>(columns));
7164 GRN_HASH_EACH_BEGIN(ctx, columns, cursor, id) {
7165 void *key;
7166 grn_hash_cursor_get_key(ctx, cursor, &key);
7167 grn_id column_id = *static_cast<grn_id *>(key);
7168 grn_obj *column = grn_ctx_at(ctx, column_id);
7169 if (!column)
7170 continue;
7171
7172 if (column->header.type != GRN_COLUMN_INDEX)
7173 continue;
7174
7175 grn_ii_cursor *ii_cursor =
7176 grn_ii_cursor_open(ctx,
7177 reinterpret_cast<grn_ii *>(column),
7178 record_id,
7179 GRN_ID_NIL,
7180 GRN_ID_MAX,
7181 0,
7182 0);
7183 if (!ii_cursor)
7184 continue;
7185
7186 if (grn_ii_cursor_next(ctx, ii_cursor)) {
7187 referencing_child_table_id = grn_obj_get_range(ctx, column);
7188 }
7189
7190 grn_ii_cursor_close(ctx, ii_cursor);
7191
7192 if (referencing_child_table_id != GRN_ID_NIL)
7193 break;
7194 } GRN_HASH_EACH_END(ctx, cursor);
7195 grn_hash_close(ctx, columns);
7196
7197 if (referencing_child_table_id != GRN_ID_NIL) {
7198 grn_obj *referencing_child_table =
7199 grn_ctx_at(ctx, referencing_child_table_id);
7200 char name[GRN_TABLE_MAX_KEY_SIZE];
7201 int name_size;
7202 name_size = grn_obj_name(ctx,
7203 referencing_child_table,
7204 name,
7205 GRN_TABLE_MAX_KEY_SIZE);
7206 error = HA_ERR_ROW_IS_REFERENCED;
7207 GRN_PLUGIN_ERROR(ctx, GRN_INVALID_ARGUMENT,
7208 "one or more child rows exist in <%.*s>",
7209 name_size,
7210 name);
7211 DBUG_RETURN(error);
7212 }
7213 }
7214
7215 storage_store_fields_for_prep_update(buf, NULL, record_id);
7216 {
7217 mrn::Lock lock(&(share->record_mutex), have_unique_index());
7218 if ((error = storage_prepare_delete_row_unique_indexes(buf, record_id))) {
7219 DBUG_RETURN(error);
7220 }
7221 mrn_change_encoding(ctx, NULL);
7222 grn_table_delete_by_id(ctx, grn_table, record_id);
7223 if (ctx->rc) {
7224 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
7225 DBUG_RETURN(ER_ERROR_ON_WRITE);
7226 }
7227 if (
7228 (error = storage_delete_row_index(buf)) ||
7229 (error = storage_delete_row_unique_indexes())
7230 ) {
7231 DBUG_RETURN(error);
7232 }
7233 }
7234
7235 grn_db_touch(ctx, grn_ctx_db(ctx));
7236
7237 DBUG_RETURN(0);
7238}
7239
7240int ha_mroonga::storage_delete_row_index(const uchar *buf)
7241{
7242 MRN_DBUG_ENTER_METHOD();
7243 int error = 0;
7244
7245 grn_obj key, encoded_key;
7246 GRN_TEXT_INIT(&key, 0);
7247 GRN_TEXT_INIT(&encoded_key, 0);
7248
7249 mrn::DebugColumnAccess debug_column_access(table, table->read_set);
7250 uint i;
7251 uint n_keys = table->s->keys;
7252 mrn_change_encoding(ctx, NULL);
7253 for (i = 0; i < n_keys; i++) {
7254 if (i == table->s->primary_key) {
7255 continue;
7256 }
7257
7258 KEY *key_info = &(table->key_info[i]);
7259
7260 if (KEY_N_KEY_PARTS(key_info) == 1 || (key_info->flags & HA_FULLTEXT)) {
7261 continue;
7262 }
7263
7264 grn_obj *index_column = grn_index_columns[i];
7265 if (!index_column) {
7266 /* disable keys */
7267 continue;
7268 }
7269
7270 GRN_BULK_REWIND(&key);
7271 grn_bulk_space(ctx, &key, key_info->key_length);
7272 key_copy((uchar *)(GRN_TEXT_VALUE(&key)),
7273 (uchar *)buf,
7274 key_info,
7275 key_info->key_length);
7276 GRN_BULK_REWIND(&encoded_key);
7277 grn_bulk_reserve(ctx, &encoded_key, MRN_MAX_KEY_SIZE);
7278 uint encoded_key_length;
7279 storage_encode_multiple_column_key(key_info,
7280 (uchar *)(GRN_TEXT_VALUE(&key)),
7281 key_info->key_length,
7282 (uchar *)(GRN_TEXT_VALUE(&encoded_key)),
7283 &encoded_key_length);
7284 grn_bulk_space(ctx, &encoded_key, encoded_key_length);
7285
7286 grn_rc rc;
7287 rc = grn_column_index_update(ctx, index_column, record_id, 1,
7288 &encoded_key, NULL);
7289 if (rc) {
7290 error = ER_ERROR_ON_WRITE;
7291 my_message(error, ctx->errbuf, MYF(0));
7292 goto err;
7293 }
7294 }
7295err:
7296 grn_obj_unlink(ctx, &encoded_key);
7297 grn_obj_unlink(ctx, &key);
7298
7299 DBUG_RETURN(error);
7300}
7301
7302int ha_mroonga::storage_delete_row_unique_index(grn_obj *index_table,
7303 grn_id del_key_id)
7304{
7305 MRN_DBUG_ENTER_METHOD();
7306 grn_rc rc = grn_table_delete_by_id(ctx, index_table, del_key_id);
7307 if (rc) {
7308 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
7309 DBUG_RETURN(ER_ERROR_ON_WRITE);
7310 }
7311 DBUG_RETURN(0);
7312}
7313
7314int ha_mroonga::storage_delete_row_unique_indexes()
7315{
7316 int error = 0, tmp_error;
7317 uint i;
7318 uint n_keys = table->s->keys;
7319 MRN_DBUG_ENTER_METHOD();
7320
7321 for (i = 0; i < n_keys; i++) {
7322 if (i == table->s->primary_key) {
7323 continue;
7324 }
7325
7326 KEY *key_info = &table->key_info[i];
7327 if ((!(key_info->flags & HA_NOSAME)) || del_key_id[i] == GRN_ID_NIL) {
7328 continue;
7329 }
7330
7331 grn_obj *index_table = grn_index_tables[i];
7332 if ((tmp_error = storage_delete_row_unique_index(index_table,
7333 del_key_id[i])))
7334 {
7335 error = tmp_error;
7336 }
7337 }
7338 DBUG_RETURN(error);
7339}
7340
7341int ha_mroonga::storage_prepare_delete_row_unique_index(const uchar *buf,
7342 grn_id record_id,
7343 KEY *key_info,
7344 grn_obj *index_table,
7345 grn_obj *index_column,
7346 grn_id *del_key_id)
7347{
7348 const void *ukey = NULL;
7349 uint32 ukey_size = 0;
7350 MRN_DBUG_ENTER_METHOD();
7351 if (KEY_N_KEY_PARTS(key_info) == 1) {
7352 GRN_BULK_REWIND(&key_buffer);
7353 grn_obj_get_value(ctx, index_column, record_id, &key_buffer);
7354 ukey = GRN_TEXT_VALUE(&key_buffer);
7355 ukey_size = GRN_TEXT_LEN(&key_buffer);
7356 } else {
7357 mrn_change_encoding(ctx, NULL);
7358 uchar key[MRN_MAX_KEY_SIZE];
7359 key_copy(key, (uchar *) buf, key_info, key_info->key_length);
7360 grn_bulk_reserve(ctx, &key_buffer, MRN_MAX_KEY_SIZE);
7361 ukey = GRN_TEXT_VALUE(&key_buffer);
7362 storage_encode_multiple_column_key(key_info,
7363 key, key_info->key_length,
7364 (uchar *)ukey, (uint *)&ukey_size);
7365 }
7366 *del_key_id = grn_table_get(ctx, index_table, ukey, ukey_size);
7367 DBUG_RETURN(0);
7368}
7369
7370int ha_mroonga::storage_prepare_delete_row_unique_indexes(const uchar *buf,
7371 grn_id record_id)
7372{
7373 int error = 0, tmp_error;
7374 uint i;
7375 uint n_keys = table->s->keys;
7376 MRN_DBUG_ENTER_METHOD();
7377
7378 for (i = 0; i < n_keys; i++) {
7379 if (i == table->s->primary_key) {
7380 continue;
7381 }
7382
7383 KEY *key_info = &table->key_info[i];
7384 if (!(key_info->flags & HA_NOSAME)) {
7385 continue;
7386 }
7387
7388 grn_obj *index_table = grn_index_tables[i];
7389 if (!index_table) {
7390 del_key_id[i] = GRN_ID_NIL;
7391 continue;
7392 }
7393
7394 grn_obj *index_column;
7395 if (KEY_N_KEY_PARTS(key_info) == 1) {
7396 Field *field = key_info->key_part[0].field;
7397 mrn_change_encoding(ctx, field->charset());
7398 index_column = grn_columns[field->field_index];
7399 } else {
7400 mrn_change_encoding(ctx, NULL);
7401 index_column = grn_index_columns[i];
7402 }
7403 if ((tmp_error = storage_prepare_delete_row_unique_index(buf, record_id,
7404 key_info,
7405 index_table,
7406 index_column,
7407 &del_key_id[i])))
7408 {
7409 error = tmp_error;
7410 }
7411 }
7412 DBUG_RETURN(error);
7413}
7414
7415int ha_mroonga::delete_row(const uchar *buf)
7416{
7417 MRN_DBUG_ENTER_METHOD();
7418 int error = 0;
7419 if (share->wrapper_mode)
7420 {
7421 error = wrapper_delete_row(buf);
7422 } else {
7423 error = storage_delete_row(buf);
7424 }
7425 DBUG_RETURN(error);
7426}
7427
7428uint ha_mroonga::wrapper_max_supported_key_parts() const
7429{
7430 MRN_DBUG_ENTER_METHOD();
7431 DBUG_RETURN(MAX_REF_PARTS);
7432}
7433
7434uint ha_mroonga::storage_max_supported_key_parts() const
7435{
7436 MRN_DBUG_ENTER_METHOD();
7437 DBUG_RETURN(MAX_REF_PARTS);
7438}
7439
7440uint ha_mroonga::max_supported_key_parts() const
7441{
7442 MRN_DBUG_ENTER_METHOD();
7443
7444 uint parts;
7445 if (!share && !analyzed_for_create &&
7446 (
7447 thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE ||
7448 thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX ||
7449 thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE
7450 )
7451 ) {
7452 create_share_for_create();
7453 }
7454 if (analyzed_for_create && share_for_create.wrapper_mode) {
7455 parts = wrapper_max_supported_key_parts();
7456 } else if (wrap_handler && share && share->wrapper_mode) {
7457 parts = wrapper_max_supported_key_parts();
7458 } else {
7459 parts = storage_max_supported_key_parts();
7460 }
7461
7462 DBUG_RETURN(parts);
7463}
7464
7465ha_rows ha_mroonga::wrapper_records_in_range(uint key_nr, key_range *range_min,
7466 key_range *range_max)
7467{
7468 ha_rows row_count;
7469 MRN_DBUG_ENTER_METHOD();
7470 KEY *key_info = &(table->s->key_info[key_nr]);
7471 if (mrn_is_geo_key(key_info)) {
7472 row_count = generic_records_in_range_geo(key_nr, range_min, range_max);
7473 } else {
7474 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7475 MRN_SET_WRAP_TABLE_KEY(this, table);
7476 row_count = wrap_handler->records_in_range(key_nr, range_min, range_max);
7477 MRN_SET_BASE_SHARE_KEY(share, table->s);
7478 MRN_SET_BASE_TABLE_KEY(this, table);
7479 }
7480 DBUG_RETURN(row_count);
7481}
7482
7483ha_rows ha_mroonga::storage_records_in_range(uint key_nr, key_range *range_min,
7484 key_range *range_max)
7485{
7486 MRN_DBUG_ENTER_METHOD();
7487 int flags = 0;
7488 uint size_min = 0, size_max = 0;
7489 ha_rows row_count = 0;
7490 uchar *key_min = NULL, *key_max = NULL;
7491 uchar key_min_entity[MRN_MAX_KEY_SIZE];
7492 uchar key_max_entity[MRN_MAX_KEY_SIZE];
7493 KEY *key_info = &(table->s->key_info[key_nr]);
7494 bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1;
7495
7496 if (is_multiple_column_index) {
7497 mrn_change_encoding(ctx, NULL);
7498 if (range_min && range_max &&
7499 range_min->length == range_max->length &&
7500 memcmp(range_min->key, range_max->key, range_min->length) == 0) {
7501 flags |= GRN_CURSOR_PREFIX;
7502 key_min = key_min_entity;
7503 storage_encode_multiple_column_key(key_info,
7504 range_min->key, range_min->length,
7505 key_min, &size_min);
7506 } else {
7507 key_min = key_min_entity;
7508 key_max = key_max_entity;
7509 storage_encode_multiple_column_key_range(key_info,
7510 range_min, range_max,
7511 key_min, &size_min,
7512 key_max, &size_max);
7513 }
7514 } else if (mrn_is_geo_key(key_info)) {
7515 mrn_change_encoding(ctx, key_info->key_part->field->charset());
7516 row_count = generic_records_in_range_geo(key_nr, range_min, range_max);
7517 DBUG_RETURN(row_count);
7518 } else {
7519 Field *field = key_info->key_part[0].field;
7520 const char *column_name = field->field_name.str;
7521 mrn_change_encoding(ctx, field->charset());
7522
7523 if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
7524 DBUG_RETURN((ha_rows)1);
7525 }
7526
7527 if (range_min) {
7528 key_min = key_min_entity;
7529 storage_encode_key(field, range_min->key, key_min, &size_min);
7530 if (size_min == 0) {
7531 DBUG_RETURN(HA_POS_ERROR);
7532 }
7533 }
7534 if (range_max) {
7535 key_max = key_max_entity;
7536 storage_encode_key(field, range_max->key, key_max, &size_max);
7537 if (size_max == 0) {
7538 DBUG_RETURN(HA_POS_ERROR);
7539 }
7540 }
7541 }
7542
7543 if (range_min) {
7544 DBUG_PRINT("info", ("mroonga: range_min->flag=%u", range_min->flag));
7545 if (range_min->flag == HA_READ_AFTER_KEY) {
7546 flags |= GRN_CURSOR_GT;
7547 }
7548 }
7549 if (range_max) {
7550 DBUG_PRINT("info", ("mroonga: range_min->flag=%u", range_max->flag));
7551 if (range_max->flag == HA_READ_BEFORE_KEY) {
7552 flags |= GRN_CURSOR_LT;
7553 }
7554 }
7555
7556 int cursor_limit = THDVAR(ha_thd(), max_n_records_for_estimate);
7557 uint pkey_nr = table->s->primary_key;
7558 if (key_nr == pkey_nr) {
7559 DBUG_PRINT("info", ("mroonga: use primary key"));
7560 grn_table_cursor *cursor;
7561 cursor = grn_table_cursor_open(ctx, grn_table,
7562 key_min, size_min,
7563 key_max, size_max,
7564 0, cursor_limit, flags);
7565 while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) {
7566 row_count++;
7567 }
7568 grn_table_cursor_close(ctx, cursor);
7569 } else {
7570 if (is_multiple_column_index) {
7571 DBUG_PRINT("info", ("mroonga: use multiple column key%u", key_nr));
7572 } else {
7573 DBUG_PRINT("info", ("mroonga: use key%u", key_nr));
7574 }
7575
7576 grn_table_cursor *cursor;
7577 cursor = grn_table_cursor_open(ctx, grn_index_tables[key_nr],
7578 key_min, size_min,
7579 key_max, size_max,
7580 0, cursor_limit, flags);
7581 grn_obj *index_column = grn_index_columns[key_nr];
7582 grn_ii *ii = reinterpret_cast<grn_ii *>(index_column);
7583 row_count = grn_ii_estimate_size_for_lexicon_cursor(ctx, ii, cursor);
7584 grn_table_cursor_close(ctx, cursor);
7585
7586 unsigned int max_n_lexicon_records =
7587 grn_table_size(ctx, grn_index_tables[key_nr]);
7588 if (cursor_limit >= 0 &&
7589 static_cast<unsigned int>(cursor_limit) < max_n_lexicon_records) {
7590 row_count++;
7591 }
7592 }
7593 DBUG_RETURN(row_count);
7594}
7595
7596ha_rows ha_mroonga::generic_records_in_range_geo(uint key_nr,
7597 key_range *range_min,
7598 key_range *range_max)
7599{
7600 MRN_DBUG_ENTER_METHOD();
7601 ha_rows row_count;
7602 int error;
7603
7604 if (!range_min) {
7605 DBUG_PRINT("info",
7606 ("mroonga: range min is missing for geometry range search"));
7607 DBUG_RETURN(HA_POS_ERROR);
7608 }
7609 if (range_max) {
7610 DBUG_PRINT("info",
7611 ("mroonga: range max is specified for geometry range search"));
7612 DBUG_RETURN(HA_POS_ERROR);
7613 }
7614 error = mrn_change_encoding(ctx,
7615 table->key_info[key_nr].key_part->field->charset());
7616 if (error)
7617 DBUG_RETURN(error);
7618 if (!(range_min->flag & HA_READ_MBR_CONTAIN)) {
7619 push_warning_unsupported_spatial_index_search(range_min->flag);
7620 row_count = grn_table_size(ctx, grn_table);
7621 DBUG_RETURN(row_count);
7622 }
7623
7624 geo_store_rectangle(range_min->key);
7625 row_count = grn_geo_estimate_in_rectangle(ctx,
7626 grn_index_columns[key_nr],
7627 &top_left_point,
7628 &bottom_right_point);
7629 DBUG_RETURN(row_count);
7630}
7631
7632ha_rows ha_mroonga::records_in_range(uint key_nr, key_range *range_min, key_range *range_max)
7633{
7634 MRN_DBUG_ENTER_METHOD();
7635 ha_rows row_count = 0;
7636 if (share->wrapper_mode)
7637 {
7638 row_count = wrapper_records_in_range(key_nr, range_min, range_max);
7639 } else {
7640 row_count = storage_records_in_range(key_nr, range_min, range_max);
7641 }
7642 DBUG_PRINT("info", ("mroonga: row_count=%" MRN_HA_ROWS_FORMAT, row_count));
7643 DBUG_RETURN(row_count);
7644}
7645
7646int ha_mroonga::wrapper_index_init(uint idx, bool sorted)
7647{
7648 MRN_DBUG_ENTER_METHOD();
7649 int error = 0;
7650 KEY *key_info = &(table->s->key_info[idx]);
7651 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7652 MRN_SET_WRAP_TABLE_KEY(this, table);
7653 if (!mrn_is_geo_key(key_info) && key_info->algorithm != HA_KEY_ALG_FULLTEXT)
7654 {
7655 error = wrap_handler->ha_index_init(share->wrap_key_nr[idx], sorted);
7656 } else {
7657 error = wrap_handler->ha_index_init(share->wrap_primary_key, sorted);
7658 }
7659 MRN_SET_BASE_SHARE_KEY(share, table->s);
7660 MRN_SET_BASE_TABLE_KEY(this, table);
7661 DBUG_RETURN(error);
7662}
7663
7664int ha_mroonga::storage_index_init(uint idx, bool sorted)
7665{
7666 MRN_DBUG_ENTER_METHOD();
7667 DBUG_RETURN(0);
7668}
7669
7670int ha_mroonga::index_init(uint idx, bool sorted)
7671{
7672 MRN_DBUG_ENTER_METHOD();
7673 DBUG_PRINT("info", ("mroonga: idx=%u", idx));
7674 active_index = idx;
7675 int error = 0;
7676 if (share->wrapper_mode)
7677 {
7678 error = wrapper_index_init(idx, sorted);
7679 } else {
7680 error = storage_index_init(idx, sorted);
7681 }
7682 DBUG_RETURN(error);
7683}
7684
7685int ha_mroonga::wrapper_index_end()
7686{
7687 int error = 0;
7688 MRN_DBUG_ENTER_METHOD();
7689 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7690 MRN_SET_WRAP_TABLE_KEY(this, table);
7691 error = wrap_handler->ha_index_or_rnd_end();
7692 MRN_SET_BASE_SHARE_KEY(share, table->s);
7693 MRN_SET_BASE_TABLE_KEY(this, table);
7694 DBUG_RETURN(error);
7695}
7696
7697int ha_mroonga::storage_index_end()
7698{
7699 MRN_DBUG_ENTER_METHOD();
7700 clear_cursor();
7701 clear_cursor_geo();
7702 DBUG_RETURN(0);
7703}
7704
7705int ha_mroonga::index_end()
7706{
7707 MRN_DBUG_ENTER_METHOD();
7708 int error = 0;
7709 if (share->wrapper_mode)
7710 {
7711 error = wrapper_index_end();
7712 } else {
7713 error = storage_index_end();
7714 }
7715 DBUG_RETURN(error);
7716}
7717
7718int ha_mroonga::wrapper_index_read_map(uchar *buf, const uchar *key,
7719 key_part_map keypart_map,
7720 enum ha_rkey_function find_flag)
7721{
7722 int error = 0;
7723 MRN_DBUG_ENTER_METHOD();
7724 KEY *key_info = &(table->key_info[active_index]);
7725 if (mrn_is_geo_key(key_info)) {
7726 clear_cursor_geo();
7727 error = generic_geo_open_cursor(key, find_flag);
7728 if (!error) {
7729 error = wrapper_get_next_geo_record(buf);
7730 }
7731 DBUG_RETURN(error);
7732 } else {
7733 MRN_SET_WRAP_SHARE_KEY(share, table->s);
7734 MRN_SET_WRAP_TABLE_KEY(this, table);
7735 if (fulltext_searching)
7736 set_pk_bitmap();
7737#ifdef MRN_HANDLER_HAVE_HA_INDEX_READ_MAP
7738 error = wrap_handler->ha_index_read_map(buf, key, keypart_map, find_flag);
7739#else
7740 error = wrap_handler->index_read_map(buf, key, keypart_map, find_flag);
7741#endif
7742 MRN_SET_BASE_SHARE_KEY(share, table->s);
7743 MRN_SET_BASE_TABLE_KEY(this, table);
7744 }
7745 DBUG_RETURN(error);
7746}
7747
7748int ha_mroonga::storage_index_read_map(uchar *buf, const uchar *key,
7749 key_part_map keypart_map,
7750 enum ha_rkey_function find_flag)
7751{
7752 MRN_DBUG_ENTER_METHOD();
7753 check_count_skip(keypart_map);
7754
7755 int error = 0;
7756
7757 uint key_nr = active_index;
7758 KEY *key_info = &(table->key_info[key_nr]);
7759 int flags = 0;
7760 uint size_min = 0, size_max = 0;
7761 uchar *key_min = NULL, *key_max = NULL;
7762 uchar key_min_entity[MRN_MAX_KEY_SIZE];
7763 uchar key_max_entity[MRN_MAX_KEY_SIZE];
7764
7765 clear_cursor();
7766 clear_cursor_geo();
7767 clear_empty_value_records();
7768
7769 switch (find_flag) {
7770 case HA_READ_BEFORE_KEY:
7771 flags |= GRN_CURSOR_LT | GRN_CURSOR_DESCENDING;
7772 break;
7773 case HA_READ_PREFIX_LAST:
7774 flags |= GRN_CURSOR_PREFIX | GRN_CURSOR_DESCENDING;
7775 break;
7776 case HA_READ_PREFIX_LAST_OR_PREV:
7777 flags |= GRN_CURSOR_LE | GRN_CURSOR_DESCENDING;
7778 break;
7779 case HA_READ_AFTER_KEY:
7780 flags |= GRN_CURSOR_GT | GRN_CURSOR_ASCENDING;
7781 break;
7782 case HA_READ_KEY_OR_NEXT:
7783 flags |= GRN_CURSOR_GE | GRN_CURSOR_ASCENDING;
7784 break;
7785 case HA_READ_KEY_EXACT:
7786 flags |= GRN_CURSOR_LE | GRN_CURSOR_GE;
7787 break;
7788 default:
7789 break;
7790 }
7791
7792 bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1;
7793 if (is_multiple_column_index) {
7794 mrn_change_encoding(ctx, NULL);
7795 uint key_length =
7796 mrn_calculate_key_len(table, active_index, key, keypart_map);
7797 DBUG_PRINT("info",
7798 ("mroonga: multiple column index: "
7799 "search key length=<%u>, "
7800 "multiple column index key length=<%u>",
7801 key_length, key_info->key_length));
7802 if (key_length == key_info->key_length) {
7803 switch (find_flag) {
7804 case HA_READ_BEFORE_KEY:
7805 case HA_READ_PREFIX_LAST_OR_PREV:
7806 key_max = key_max_entity;
7807 storage_encode_multiple_column_key(key_info,
7808 key, key_length,
7809 key_max, &size_max);
7810 break;
7811 case HA_READ_PREFIX_LAST:
7812 key_min = key_min_entity;
7813 storage_encode_multiple_column_key(key_info,
7814 key, key_length,
7815 key_min, &size_min);
7816 break;
7817 default:
7818 key_min = key_min_entity;
7819 storage_encode_multiple_column_key(key_info,
7820 key, key_length,
7821 key_min, &size_min);
7822 if (find_flag == HA_READ_KEY_EXACT) {
7823 key_max = key_min;
7824 size_max = size_min;
7825 }
7826 break;
7827 }
7828 } else {
7829 const uchar *prev_key = NULL;
7830 uint prev_key_length = 0;
7831 if ((keypart_map >> 1) > 0) {
7832 prev_key = key;
7833 prev_key_length =
7834 mrn_calculate_key_len(table, active_index, key, keypart_map >> 1);
7835 }
7836 switch (find_flag) {
7837 case HA_READ_BEFORE_KEY:
7838 if (prev_key) {
7839 flags |= GRN_CURSOR_GE;
7840 key_min = key_min_entity;
7841 storage_encode_multiple_column_key_range(key_info,
7842 prev_key, prev_key_length,
7843 NULL, 0,
7844 key_min, &size_min,
7845 NULL, NULL);
7846 }
7847 key_max = key_max_entity;
7848 storage_encode_multiple_column_key_range(key_info,
7849 key, key_length,
7850 NULL, 0,
7851 key_max, &size_max,
7852 NULL, NULL);
7853 break;
7854 case HA_READ_PREFIX_LAST:
7855 key_min = key_min_entity;
7856 storage_encode_multiple_column_key(key_info,
7857 key, key_length,
7858 key_min, &size_min);
7859 break;
7860 case HA_READ_PREFIX_LAST_OR_PREV:
7861 if (prev_key) {
7862 flags |= GRN_CURSOR_GE;
7863 key_min = key_min_entity;
7864 storage_encode_multiple_column_key_range(key_info,
7865 prev_key, prev_key_length,
7866 NULL, 0,
7867 key_min, &size_min,
7868 NULL, NULL);
7869 }
7870 key_max = key_max_entity;
7871 storage_encode_multiple_column_key_range(key_info,
7872 NULL, 0,
7873 key, key_length,
7874 NULL, NULL,
7875 key_max, &size_max);
7876 break;
7877 case HA_READ_AFTER_KEY:
7878 key_min = key_min_entity;
7879 storage_encode_multiple_column_key_range(key_info,
7880 NULL, 0,
7881 key, key_length,
7882 NULL, NULL,
7883 key_min, &size_min);
7884 if (prev_key) {
7885 flags |= GRN_CURSOR_LE;
7886 key_max = key_max_entity;
7887 storage_encode_multiple_column_key_range(key_info,
7888 NULL, 0,
7889 prev_key, prev_key_length,
7890 NULL, NULL,
7891 key_max, &size_max);
7892 }
7893 break;
7894 case HA_READ_KEY_OR_NEXT:
7895 key_min = key_min_entity;
7896 storage_encode_multiple_column_key_range(key_info,
7897 key, key_length,
7898 NULL, 0,
7899 key_min, &size_min,
7900 NULL, NULL);
7901 if (prev_key) {
7902 flags |= GRN_CURSOR_LE;
7903 key_max = key_max_entity;
7904 storage_encode_multiple_column_key_range(key_info,
7905 NULL, 0,
7906 prev_key, prev_key_length,
7907 NULL, NULL,
7908 key_max, &size_max);
7909 }
7910 break;
7911 case HA_READ_KEY_EXACT:
7912 key_min = key_min_entity;
7913 key_max = key_max_entity;
7914 storage_encode_multiple_column_key_range(key_info,
7915 key, key_length,
7916 key, key_length,
7917 key_min, &size_min,
7918 key_max, &size_max);
7919 default:
7920 break;
7921 }
7922 }
7923 } else if (mrn_is_geo_key(key_info)) {
7924 error = mrn_change_encoding(ctx, key_info->key_part->field->charset());
7925 if (error)
7926 DBUG_RETURN(error);
7927 error = generic_geo_open_cursor(key, find_flag);
7928 if (!error) {
7929 error = storage_get_next_record(buf);
7930 }
7931 DBUG_RETURN(error);
7932 } else {
7933 Field *field = key_info->key_part[0].field;
7934 error = mrn_change_encoding(ctx, field->charset());
7935 if (error)
7936 DBUG_RETURN(error);
7937
7938 if (find_flag == HA_READ_KEY_EXACT) {
7939 const char *column_name = field->field_name.str;
7940
7941 key_min = key_min_entity;
7942 key_max = key_min_entity;
7943 storage_encode_key(field, key, key_min, &size_min);
7944 size_max = size_min;
7945 // for _id
7946 if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) {
7947 grn_id found_record_id = *((grn_id *)key_min);
7948 if (grn_table_at(ctx, grn_table, found_record_id) != GRN_ID_NIL) { // found
7949 storage_store_fields(buf, found_record_id);
7950 table->status = 0;
7951 record_id = found_record_id;
7952 DBUG_RETURN(0);
7953 } else {
7954 table->status = STATUS_NOT_FOUND;
7955 DBUG_RETURN(HA_ERR_END_OF_FILE);
7956 }
7957 }
7958 } else if (find_flag == HA_READ_BEFORE_KEY ||
7959 find_flag == HA_READ_PREFIX_LAST_OR_PREV) {
7960 key_max = key_max_entity;
7961 storage_encode_key(field, key, key_max_entity, &size_max);
7962 } else {
7963 key_min = key_min_entity;
7964 storage_encode_key(field, key, key_min_entity, &size_min);
7965 }
7966 }
7967
7968 uint pkey_nr = table->s->primary_key;
7969 if (key_nr == pkey_nr) {
7970 DBUG_PRINT("info", ("mroonga: use primary key"));
7971 cursor = grn_table_cursor_open(ctx, grn_table,
7972 key_min, size_min,
7973 key_max, size_max,
7974 0, -1, flags);
7975 } else {
7976 bool is_empty_value_records_search = false;
7977 if (is_multiple_column_index) {
7978 DBUG_PRINT("info", ("mroonga: use multiple column key%u", key_nr));
7979 } else if (flags == 0 && size_min == 0 && size_max == 0) {
7980 is_empty_value_records_search = true;
7981 DBUG_PRINT("info",
7982 ("mroonga: use table scan for searching empty value records"));
7983 } else {
7984 DBUG_PRINT("info", ("mroonga: use key%u", key_nr));
7985 }
7986 if (is_empty_value_records_search) {
7987 grn_obj *expression, *expression_variable;
7988 GRN_EXPR_CREATE_FOR_QUERY(ctx, grn_table,
7989 expression, expression_variable);
7990 grn_obj *target_column =
7991 grn_columns[key_info->key_part->field->field_index];
7992 grn_expr_append_const(ctx, expression, target_column, GRN_OP_GET_VALUE, 1);
7993 grn_obj empty_value;
7994 GRN_TEXT_INIT(&empty_value, 0);
7995 grn_expr_append_obj(ctx, expression, &empty_value, GRN_OP_PUSH, 1);
7996 grn_expr_append_op(ctx, expression, GRN_OP_EQUAL, 2);
7997
7998 empty_value_records =
7999 grn_table_create(ctx, NULL, 0, NULL,
8000 GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
8001 grn_table, 0);
8002 grn_table_select(ctx, grn_table, expression, empty_value_records,
8003 GRN_OP_OR);
8004 grn_obj_unlink(ctx, expression);
8005 grn_obj_unlink(ctx, &empty_value);
8006
8007 empty_value_records_cursor =
8008 grn_table_cursor_open(ctx, empty_value_records,
8009 NULL, 0, NULL, 0,
8010 0, -1, flags);
8011 } else {
8012 index_table_cursor = grn_table_cursor_open(ctx, grn_index_tables[key_nr],
8013 key_min, size_min,
8014 key_max, size_max,
8015 0, -1, flags);
8016 cursor = grn_index_cursor_open(ctx, index_table_cursor,
8017 grn_index_columns[key_nr],
8018 0, GRN_ID_MAX, 0);
8019 }
8020 }
8021 if (ctx->rc) {
8022 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8023 DBUG_RETURN(ER_ERROR_ON_READ);
8024 }
8025 error = storage_get_next_record(buf);
8026 DBUG_RETURN(error);
8027}
8028
8029int ha_mroonga::index_read_map(uchar *buf, const uchar *key,
8030 key_part_map keypart_map,
8031 enum ha_rkey_function find_flag)
8032{
8033 MRN_DBUG_ENTER_METHOD();
8034 int error = 0;
8035 if (share->wrapper_mode)
8036 {
8037 error = wrapper_index_read_map(buf, key, keypart_map, find_flag);
8038 } else {
8039 error = storage_index_read_map(buf, key, keypart_map, find_flag);
8040 }
8041 DBUG_PRINT("info", ("mroonga: error=%d", error));
8042 DBUG_RETURN(error);
8043}
8044
8045#ifdef MRN_HANDLER_HAVE_INDEX_READ_LAST_MAP
8046int ha_mroonga::wrapper_index_read_last_map(uchar *buf, const uchar *key,
8047 key_part_map keypart_map)
8048{
8049 int error = 0;
8050 MRN_DBUG_ENTER_METHOD();
8051 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8052 MRN_SET_WRAP_TABLE_KEY(this, table);
8053 if (fulltext_searching)
8054 set_pk_bitmap();
8055# ifdef MRN_HANDLER_HAVE_HA_INDEX_READ_LAST_MAP
8056 error = wrap_handler->ha_index_read_last_map(buf, key, keypart_map);
8057# else
8058 error = wrap_handler->index_read_last_map(buf, key, keypart_map);
8059# endif
8060 MRN_SET_BASE_SHARE_KEY(share, table->s);
8061 MRN_SET_BASE_TABLE_KEY(this, table);
8062 DBUG_RETURN(error);
8063}
8064
8065int ha_mroonga::storage_index_read_last_map(uchar *buf, const uchar *key,
8066 key_part_map keypart_map)
8067{
8068 MRN_DBUG_ENTER_METHOD();
8069 uint key_nr = active_index;
8070 KEY *key_info = &(table->key_info[key_nr]);
8071
8072 int flags = GRN_CURSOR_DESCENDING, error;
8073 uint size_min = 0, size_max = 0;
8074 uchar *key_min = NULL, *key_max = NULL;
8075 uchar key_min_entity[MRN_MAX_KEY_SIZE];
8076
8077 clear_cursor();
8078
8079 bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1;
8080 if (is_multiple_column_index) {
8081 mrn_change_encoding(ctx, NULL);
8082 flags |= GRN_CURSOR_PREFIX;
8083 uint key_length =
8084 mrn_calculate_key_len(table, active_index, key, keypart_map);
8085 key_min = key_min_entity;
8086 storage_encode_multiple_column_key(key_info,
8087 key, key_length,
8088 key_min, &size_min);
8089 } else {
8090 Field *field = key_info->key_part[0].field;
8091 error = mrn_change_encoding(ctx, field->charset());
8092 if (error)
8093 DBUG_RETURN(error);
8094
8095 key_min = key_min_entity;
8096 key_max = key_min_entity;
8097 storage_encode_key(field, key, key_min, &size_min);
8098 size_max = size_min;
8099 }
8100
8101 uint pkey_nr = table->s->primary_key;
8102 if (key_nr == pkey_nr) {
8103 DBUG_PRINT("info", ("mroonga: use primary key"));
8104 cursor = grn_table_cursor_open(ctx, grn_table,
8105 key_min, size_min, key_max, size_max,
8106 0, -1, flags);
8107 } else {
8108 if (is_multiple_column_index) {
8109 DBUG_PRINT("info", ("mroonga: use multiple column key%u", key_nr));
8110 } else {
8111 DBUG_PRINT("info", ("mroonga: use key%u", key_nr));
8112 }
8113 index_table_cursor = grn_table_cursor_open(ctx, grn_index_tables[key_nr],
8114 key_min, size_min,
8115 key_max, size_max,
8116 0, -1, flags);
8117 cursor = grn_index_cursor_open(ctx, index_table_cursor,
8118 grn_index_columns[key_nr],
8119 0, GRN_ID_MAX, 0);
8120 }
8121 if (ctx->rc) {
8122 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8123 DBUG_RETURN(ER_ERROR_ON_READ);
8124 }
8125 error = storage_get_next_record(buf);
8126 DBUG_RETURN(error);
8127}
8128
8129int ha_mroonga::index_read_last_map(uchar *buf, const uchar *key,
8130 key_part_map keypart_map)
8131{
8132 MRN_DBUG_ENTER_METHOD();
8133 int error = 0;
8134 if (share->wrapper_mode)
8135 {
8136 error = wrapper_index_read_last_map(buf, key, keypart_map);
8137 } else {
8138 error = storage_index_read_last_map(buf, key, keypart_map);
8139 }
8140 DBUG_RETURN(error);
8141}
8142#endif
8143
8144int ha_mroonga::wrapper_index_next(uchar *buf)
8145{
8146 int error = 0;
8147 MRN_DBUG_ENTER_METHOD();
8148 KEY *key_info = &(table->key_info[active_index]);
8149 if (mrn_is_geo_key(key_info)) {
8150 error = wrapper_get_next_geo_record(buf);
8151 } else {
8152 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8153 MRN_SET_WRAP_TABLE_KEY(this, table);
8154 if (fulltext_searching)
8155 set_pk_bitmap();
8156#ifdef MRN_HANDLER_HAVE_HA_INDEX_NEXT
8157 error = wrap_handler->ha_index_next(buf);
8158#else
8159 error = wrap_handler->index_next(buf);
8160#endif
8161 MRN_SET_BASE_SHARE_KEY(share, table->s);
8162 MRN_SET_BASE_TABLE_KEY(this, table);
8163 }
8164 DBUG_RETURN(error);
8165}
8166
8167int ha_mroonga::storage_index_next(uchar *buf)
8168{
8169 MRN_DBUG_ENTER_METHOD();
8170 int error = storage_get_next_record(buf);
8171 DBUG_RETURN(error);
8172}
8173
8174int ha_mroonga::index_next(uchar *buf)
8175{
8176 MRN_DBUG_ENTER_METHOD();
8177 int error = 0;
8178 if (share->wrapper_mode)
8179 {
8180 error = wrapper_index_next(buf);
8181 } else {
8182 error = storage_index_next(buf);
8183 }
8184 DBUG_RETURN(error);
8185}
8186
8187int ha_mroonga::wrapper_index_prev(uchar *buf)
8188{
8189 int error = 0;
8190 MRN_DBUG_ENTER_METHOD();
8191 KEY *key_info = &(table->key_info[active_index]);
8192 if (mrn_is_geo_key(key_info)) {
8193 error = wrapper_get_next_geo_record(buf);
8194 } else {
8195 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8196 MRN_SET_WRAP_TABLE_KEY(this, table);
8197 if (fulltext_searching)
8198 set_pk_bitmap();
8199#ifdef MRN_HANDLER_HAVE_HA_INDEX_NEXT
8200 error = wrap_handler->ha_index_prev(buf);
8201#else
8202 error = wrap_handler->index_prev(buf);
8203#endif
8204 MRN_SET_BASE_SHARE_KEY(share, table->s);
8205 MRN_SET_BASE_TABLE_KEY(this, table);
8206 }
8207 DBUG_RETURN(error);
8208}
8209
8210int ha_mroonga::storage_index_prev(uchar *buf)
8211{
8212 MRN_DBUG_ENTER_METHOD();
8213 int error = storage_get_next_record(buf);
8214 DBUG_RETURN(error);
8215}
8216
8217int ha_mroonga::index_prev(uchar *buf)
8218{
8219 MRN_DBUG_ENTER_METHOD();
8220 int error = 0;
8221 if (share->wrapper_mode)
8222 {
8223 error = wrapper_index_prev(buf);
8224 } else {
8225 error = storage_index_prev(buf);
8226 }
8227 DBUG_RETURN(error);
8228}
8229
8230int ha_mroonga::wrapper_index_first(uchar *buf)
8231{
8232 int error = 0;
8233 MRN_DBUG_ENTER_METHOD();
8234 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8235 MRN_SET_WRAP_TABLE_KEY(this, table);
8236 if (fulltext_searching)
8237 set_pk_bitmap();
8238#ifdef MRN_HANDLER_HAVE_HA_INDEX_FIRST
8239 error = wrap_handler->ha_index_first(buf);
8240#else
8241 error = wrap_handler->index_first(buf);
8242#endif
8243 MRN_SET_BASE_SHARE_KEY(share, table->s);
8244 MRN_SET_BASE_TABLE_KEY(this, table);
8245 DBUG_RETURN(error);
8246}
8247
8248int ha_mroonga::storage_index_first(uchar *buf)
8249{
8250 MRN_DBUG_ENTER_METHOD();
8251 clear_cursor();
8252 int flags = GRN_CURSOR_ASCENDING;
8253 uint pkey_nr = table->s->primary_key;
8254 mrn_change_encoding(ctx, NULL);
8255 if (active_index == pkey_nr) {
8256 DBUG_PRINT("info", ("mroonga: use primary key"));
8257 cursor = grn_table_cursor_open(ctx, grn_table, NULL, 0, NULL, 0,
8258 0, -1, flags);
8259 } else {
8260 if (KEY_N_KEY_PARTS(&(table->key_info[active_index])) > 1) {
8261 DBUG_PRINT("info", ("mroonga: use multiple column key%u", active_index));
8262 } else {
8263 DBUG_PRINT("info", ("mroonga: use key%u", active_index));
8264 }
8265 index_table_cursor = grn_table_cursor_open(ctx,
8266 grn_index_tables[active_index],
8267 NULL, 0,
8268 NULL, 0,
8269 0, -1, flags);
8270 cursor = grn_index_cursor_open(ctx, index_table_cursor,
8271 grn_index_columns[active_index],
8272 0, GRN_ID_MAX, 0);
8273 }
8274 if (ctx->rc) {
8275 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8276 DBUG_RETURN(ER_ERROR_ON_READ);
8277 }
8278 int error = storage_get_next_record(buf);
8279 DBUG_RETURN(error);
8280}
8281
8282int ha_mroonga::index_first(uchar *buf)
8283{
8284 MRN_DBUG_ENTER_METHOD();
8285 int error = 0;
8286 if (share->wrapper_mode)
8287 {
8288 error = wrapper_index_first(buf);
8289 } else {
8290 error = storage_index_first(buf);
8291 }
8292 DBUG_RETURN(error);
8293}
8294
8295int ha_mroonga::wrapper_index_last(uchar *buf)
8296{
8297 int error = 0;
8298 MRN_DBUG_ENTER_METHOD();
8299 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8300 MRN_SET_WRAP_TABLE_KEY(this, table);
8301 if (fulltext_searching)
8302 set_pk_bitmap();
8303#ifdef MRN_HANDLER_HAVE_HA_INDEX_LAST
8304 error = wrap_handler->ha_index_last(buf);
8305#else
8306 error = wrap_handler->index_last(buf);
8307#endif
8308 MRN_SET_BASE_SHARE_KEY(share, table->s);
8309 MRN_SET_BASE_TABLE_KEY(this, table);
8310 DBUG_RETURN(error);
8311}
8312
8313int ha_mroonga::storage_index_last(uchar *buf)
8314{
8315 MRN_DBUG_ENTER_METHOD();
8316 clear_cursor();
8317 int flags = GRN_CURSOR_DESCENDING;
8318 uint pkey_nr = table->s->primary_key;
8319 mrn_change_encoding(ctx, NULL);
8320 if (active_index == pkey_nr) {
8321 DBUG_PRINT("info", ("mroonga: use primary key"));
8322 cursor = grn_table_cursor_open(ctx, grn_table, NULL, 0, NULL, 0,
8323 0, -1, flags);
8324 } else {
8325 if (KEY_N_KEY_PARTS(&(table->key_info[active_index])) > 1) {
8326 DBUG_PRINT("info", ("mroonga: use multiple column key%u", active_index));
8327 } else {
8328 DBUG_PRINT("info", ("mroonga: use key%u", active_index));
8329 }
8330 index_table_cursor = grn_table_cursor_open(ctx,
8331 grn_index_tables[active_index],
8332 NULL, 0,
8333 NULL, 0,
8334 0, -1, flags);
8335 cursor = grn_index_cursor_open(ctx, index_table_cursor,
8336 grn_index_columns[active_index],
8337 0, GRN_ID_MAX, 0);
8338 }
8339 if (ctx->rc) {
8340 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8341 DBUG_RETURN(ER_ERROR_ON_READ);
8342 }
8343 int error = storage_get_next_record(buf);
8344 DBUG_RETURN(error);
8345}
8346
8347int ha_mroonga::index_last(uchar *buf)
8348{
8349 MRN_DBUG_ENTER_METHOD();
8350 int error = 0;
8351 if (share->wrapper_mode)
8352 {
8353 error = wrapper_index_last(buf);
8354 } else {
8355 error = storage_index_last(buf);
8356 }
8357 DBUG_RETURN(error);
8358}
8359
8360int ha_mroonga::wrapper_index_next_same(uchar *buf, const uchar *key,
8361 uint keylen)
8362{
8363 MRN_DBUG_ENTER_METHOD();
8364 int error = 0;
8365 KEY *key_info = &(table->s->key_info[active_index]);
8366 if (mrn_is_geo_key(key_info)) {
8367 error = wrapper_get_next_geo_record(buf);
8368 } else {
8369 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8370 MRN_SET_WRAP_TABLE_KEY(this, table);
8371 if (fulltext_searching)
8372 set_pk_bitmap();
8373#ifdef MRN_HANDLER_HAVE_HA_INDEX_NEXT_SAME
8374 error = wrap_handler->ha_index_next_same(buf, key, keylen);
8375#else
8376 error = wrap_handler->index_next_same(buf, key, keylen);
8377#endif
8378 MRN_SET_BASE_SHARE_KEY(share, table->s);
8379 MRN_SET_BASE_TABLE_KEY(this, table);
8380 }
8381 DBUG_RETURN(error);
8382}
8383
8384int ha_mroonga::storage_index_next_same(uchar *buf, const uchar *key,
8385 uint keylen)
8386{
8387 MRN_DBUG_ENTER_METHOD();
8388 int error = storage_get_next_record(count_skip ? NULL : buf);
8389 DBUG_RETURN(error);
8390}
8391
8392int ha_mroonga::index_next_same(uchar *buf, const uchar *key, uint keylen)
8393{
8394 MRN_DBUG_ENTER_METHOD();
8395 int error = 0;
8396 if (share->wrapper_mode)
8397 {
8398 error = wrapper_index_next_same(buf, key, keylen);
8399 } else {
8400 error = storage_index_next_same(buf, key, keylen);
8401 }
8402 DBUG_RETURN(error);
8403}
8404
8405int ha_mroonga::generic_ft_init()
8406{
8407 MRN_DBUG_ENTER_METHOD();
8408 struct st_mrn_ft_info *mrn_ft_info =
8409 reinterpret_cast<struct st_mrn_ft_info *>(ft_handler);
8410 GRN_CTX_SET_ENCODING(ctx, mrn_ft_info->encoding);
8411
8412 int error = 0;
8413 if (sorted_result) {
8414 mrn_ft_info->cursor = grn_table_cursor_open(ctx, sorted_result,
8415 NULL, 0, NULL, 0,
8416 0, -1, 0);
8417 } else {
8418 mrn_ft_info->cursor = grn_table_cursor_open(ctx, mrn_ft_info->result,
8419 NULL, 0, NULL, 0,
8420 0, -1, 0);
8421 }
8422 if (ctx->rc) {
8423 error = ER_ERROR_ON_READ;
8424 my_message(error, ctx->errbuf, MYF(0));
8425 } else {
8426 if (sorted_result) {
8427 if (grn_table->header.type == GRN_TABLE_NO_KEY) {
8428 mrn_ft_info->id_accessor = grn_obj_column(ctx, sorted_result,
8429 MRN_COLUMN_NAME_ID,
8430 strlen(MRN_COLUMN_NAME_ID));
8431 } else {
8432 mrn_ft_info->key_accessor = grn_obj_column(ctx, sorted_result,
8433 MRN_COLUMN_NAME_KEY,
8434 strlen(MRN_COLUMN_NAME_KEY));
8435 }
8436 } else {
8437 mrn_ft_info->key_accessor = grn_obj_column(ctx, mrn_ft_info->result,
8438 MRN_COLUMN_NAME_KEY,
8439 strlen(MRN_COLUMN_NAME_KEY));
8440 }
8441 }
8442 DBUG_RETURN(error);
8443}
8444
8445int ha_mroonga::wrapper_ft_init()
8446{
8447 MRN_DBUG_ENTER_METHOD();
8448 int error = generic_ft_init();
8449 DBUG_RETURN(error);
8450}
8451
8452int ha_mroonga::storage_ft_init()
8453{
8454 MRN_DBUG_ENTER_METHOD();
8455 int error = generic_ft_init();
8456 record_id = GRN_ID_NIL;
8457 DBUG_RETURN(error);
8458}
8459
8460int ha_mroonga::ft_init()
8461{
8462 MRN_DBUG_ENTER_METHOD();
8463 int error = 0;
8464 if (share->wrapper_mode)
8465 {
8466 error = wrapper_ft_init();
8467 } else {
8468 error = storage_ft_init();
8469 }
8470 DBUG_RETURN(error);
8471}
8472
8473void ha_mroonga::generic_ft_init_ext_add_conditions_fast_order_limit(
8474 struct st_mrn_ft_info *info, grn_obj *expression)
8475{
8476 MRN_DBUG_ENTER_METHOD();
8477
8478 Item *where =
8479 MRN_SELECT_LEX_GET_WHERE_COND(table->pos_in_table_list->select_lex);
8480
8481 bool is_storage_mode = !(share->wrapper_mode);
8482 mrn::ConditionConverter converter(info->ctx, grn_table, is_storage_mode);
8483 converter.convert(where, expression);
8484
8485 DBUG_VOID_RETURN;
8486}
8487
8488grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_boolean_mode(
8489 struct st_mrn_ft_info *info,
8490 String *key,
8491 grn_obj *index_column,
8492 grn_obj *match_columns,
8493 grn_obj *expression)
8494{
8495 MRN_DBUG_ENTER_METHOD();
8496
8497 mrn::QueryParser query_parser(info->ctx,
8498 ha_thd(),
8499 expression,
8500 index_column,
8501 KEY_N_KEY_PARTS(info->key_info),
8502 match_columns);
8503 grn_rc rc = query_parser.parse(key->ptr(), key->length());
8504
8505 DBUG_RETURN(rc);
8506}
8507
8508grn_rc ha_mroonga::generic_ft_init_ext_prepare_expression_in_normal_mode(
8509 struct st_mrn_ft_info *info,
8510 String *key,
8511 grn_obj *index_column,
8512 grn_obj *match_columns,
8513 grn_obj *expression)
8514{
8515 MRN_DBUG_ENTER_METHOD();
8516
8517 grn_rc rc = GRN_SUCCESS;
8518
8519 grn_obj query;
8520 GRN_TEXT_INIT(&query, GRN_OBJ_DO_SHALLOW_COPY);
8521 GRN_TEXT_SET(info->ctx, &query, key->ptr(), key->length());
8522 grn_expr_append_obj(info->ctx, match_columns, index_column, GRN_OP_PUSH, 1);
8523 grn_expr_append_obj(info->ctx, expression, match_columns, GRN_OP_PUSH, 1);
8524 grn_expr_append_const(info->ctx, expression, &query, GRN_OP_PUSH, 1);
8525 grn_expr_append_op(info->ctx, expression, GRN_OP_SIMILAR, 2);
8526 grn_obj_unlink(info->ctx, &query);
8527
8528 DBUG_RETURN(rc);
8529}
8530
8531struct st_mrn_ft_info *ha_mroonga::generic_ft_init_ext_select(uint flags,
8532 uint key_nr,
8533 String *key)
8534{
8535 MRN_DBUG_ENTER_METHOD();
8536
8537 struct st_mrn_ft_info *info = new st_mrn_ft_info();
8538 info->mroonga = this;
8539 info->ctx = ctx;
8540 mrn_change_encoding(info->ctx,
8541 table->key_info[key_nr].key_part->field->charset());
8542 info->encoding = GRN_CTX_GET_ENCODING(info->ctx);
8543 info->table = grn_table;
8544 info->result = grn_table_create(info->ctx, NULL, 0, NULL,
8545 GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
8546 grn_table, 0);
8547 if (!info->result) {
8548 char error_message[MRN_MESSAGE_BUFFER_SIZE];
8549 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
8550 "[mroonga][ft-init] failed to create a table "
8551 "to store matched records for one search: <%s>",
8552 ctx->errbuf);
8553 my_message(ER_ERROR_ON_READ, error_message, MYF(0));
8554 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
8555 delete info;
8556 DBUG_RETURN(NULL);
8557 }
8558
8559 info->score_column = grn_obj_column(info->ctx, info->result,
8560 MRN_COLUMN_NAME_SCORE,
8561 strlen(MRN_COLUMN_NAME_SCORE));
8562 GRN_TEXT_INIT(&(info->key), 0);
8563 grn_bulk_space(info->ctx, &(info->key), table->key_info->key_length);
8564 GRN_INT32_INIT(&(info->score), 0);
8565 info->active_index = key_nr;
8566 info->key_info = &(table->key_info[key_nr]);
8567 info->primary_key_info = &(table->key_info[table_share->primary_key]);
8568 info->cursor = NULL;
8569 info->id_accessor = NULL;
8570 info->key_accessor = NULL;
8571
8572 if (key->length() == 0) {
8573 DBUG_RETURN(info);
8574 }
8575
8576 grn_obj *index_column = grn_index_columns[key_nr];
8577 grn_obj *match_columns, *match_columns_variable;
8578 GRN_EXPR_CREATE_FOR_QUERY(info->ctx, info->table, match_columns,
8579 match_columns_variable);
8580
8581 grn_obj *expression, *expression_variable;
8582 GRN_EXPR_CREATE_FOR_QUERY(info->ctx, info->table,
8583 expression, expression_variable);
8584
8585 grn_rc rc = GRN_SUCCESS;
8586 if (flags & FT_BOOL) {
8587 rc = generic_ft_init_ext_prepare_expression_in_boolean_mode(info,
8588 key,
8589 index_column,
8590 match_columns,
8591 expression);
8592 } else {
8593 rc = generic_ft_init_ext_prepare_expression_in_normal_mode(info,
8594 key,
8595 index_column,
8596 match_columns,
8597 expression);
8598 }
8599
8600 if (rc == GRN_SUCCESS) {
8601 if (fast_order_limit) {
8602 generic_ft_init_ext_add_conditions_fast_order_limit(info, expression);
8603 }
8604 longlong escalation_threshold = THDVAR(ha_thd(), match_escalation_threshold);
8605 mrn::MatchEscalationThresholdScope scope(info->ctx, escalation_threshold);
8606 grn_table_select(info->ctx, info->table, expression,
8607 info->result, GRN_OP_OR);
8608 }
8609
8610 grn_obj_unlink(info->ctx, expression);
8611 grn_obj_unlink(info->ctx, match_columns);
8612
8613 DBUG_RETURN(info);
8614}
8615
8616FT_INFO *ha_mroonga::generic_ft_init_ext(uint flags, uint key_nr, String *key)
8617{
8618 MRN_DBUG_ENTER_METHOD();
8619
8620 check_count_skip(0);
8621
8622 mrn_change_encoding(ctx, system_charset_info);
8623 grn_operator operation = GRN_OP_OR;
8624 if (!matched_record_keys) {
8625 matched_record_keys = grn_table_create(ctx, NULL, 0, NULL,
8626 GRN_OBJ_TABLE_HASH_KEY | GRN_OBJ_WITH_SUBREC,
8627 grn_table, 0);
8628 if (!matched_record_keys) {
8629 char error_message[MRN_MESSAGE_BUFFER_SIZE];
8630 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
8631 "[mroonga][ft-init] "
8632 "failed to create a table to store all matched records: <%s>",
8633 ctx->errbuf);
8634 my_message(ER_ERROR_ON_READ, error_message, MYF(0));
8635 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
8636 DBUG_RETURN(NULL);
8637 }
8638 }
8639
8640 grn_table_sort_key *sort_keys = NULL;
8641 int n_sort_keys = 0;
8642 longlong limit = -1;
8643 check_fast_order_limit(&sort_keys, &n_sort_keys, &limit);
8644
8645 struct st_mrn_ft_info *info = generic_ft_init_ext_select(flags, key_nr, key);
8646 if (!info) {
8647 DBUG_RETURN(NULL);
8648 }
8649
8650 grn_rc rc;
8651 rc = grn_table_setoperation(ctx, matched_record_keys, info->result,
8652 matched_record_keys, operation);
8653 if (rc) {
8654 char error_message[MRN_MESSAGE_BUFFER_SIZE];
8655 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
8656 "failed to merge matched record keys: <%s>",
8657 ctx->errbuf);
8658 my_message(ER_ERROR_ON_READ, error_message, MYF(0));
8659 GRN_LOG(ctx, GRN_LOG_ERROR, "%s", error_message);
8660 }
8661 if (fast_order_limit) {
8662 if (sorted_result) {
8663 grn_obj_close(ctx, sorted_result);
8664 }
8665 sorted_result = grn_table_create(ctx, NULL,
8666 0, NULL,
8667 GRN_OBJ_TABLE_NO_KEY, NULL,
8668 matched_record_keys);
8669 grn_table_sort(ctx, matched_record_keys, 0, static_cast<int>(limit),
8670 sorted_result, sort_keys, n_sort_keys);
8671 } else if (flags & FT_SORTED) {
8672 grn_table_sort_key score_sort_key;
8673 score_sort_key.key = grn_obj_column(ctx,
8674 matched_record_keys,
8675 MRN_COLUMN_NAME_SCORE,
8676 strlen(MRN_COLUMN_NAME_SCORE));
8677 score_sort_key.offset = 0;
8678 score_sort_key.flags = GRN_TABLE_SORT_DESC;
8679 if (sorted_result) {
8680 grn_obj_unlink(ctx, sorted_result);
8681 }
8682 sorted_result = grn_table_create(ctx, NULL,
8683 0, NULL,
8684 GRN_OBJ_TABLE_NO_KEY, NULL,
8685 matched_record_keys);
8686 grn_table_sort(ctx, matched_record_keys, 0, -1,
8687 sorted_result, &score_sort_key, 1);
8688 grn_obj_unlink(ctx, score_sort_key.key);
8689 }
8690 if (sort_keys) {
8691 for (int i = 0; i < n_sort_keys; i++) {
8692 grn_obj_unlink(info->ctx, sort_keys[i].key);
8693 }
8694 my_free(sort_keys);
8695 }
8696
8697 DBUG_RETURN((FT_INFO *)info);
8698}
8699
8700FT_INFO *ha_mroonga::wrapper_ft_init_ext(uint flags, uint key_nr, String *key)
8701{
8702 MRN_DBUG_ENTER_METHOD();
8703
8704 FT_INFO *info = generic_ft_init_ext(flags, key_nr, key);
8705 if (!info) {
8706 DBUG_RETURN(NULL);
8707 }
8708
8709 struct st_mrn_ft_info *mrn_ft_info = (struct st_mrn_ft_info *)info;
8710 mrn_ft_info->please = &mrn_wrapper_ft_vft;
8711#ifdef HA_CAN_FULLTEXT_EXT
8712 mrn_ft_info->could_you = &mrn_wrapper_ft_vft_ext;
8713#endif
8714 ++wrap_ft_init_count;
8715
8716 DBUG_RETURN(info);
8717}
8718
8719FT_INFO *ha_mroonga::storage_ft_init_ext(uint flags, uint key_nr, String *key)
8720{
8721 MRN_DBUG_ENTER_METHOD();
8722
8723 FT_INFO *info = generic_ft_init_ext(flags, key_nr, key);
8724 if (!info) {
8725 DBUG_RETURN(NULL);
8726 }
8727
8728 struct st_mrn_ft_info *mrn_ft_info = (struct st_mrn_ft_info *)info;
8729 mrn_ft_info->please = &mrn_storage_ft_vft;
8730#ifdef HA_CAN_FULLTEXT_EXT
8731 mrn_ft_info->could_you = &mrn_storage_ft_vft_ext;
8732#endif
8733 DBUG_RETURN(info);
8734}
8735
8736FT_INFO *ha_mroonga::ft_init_ext(uint flags, uint key_nr, String *key)
8737{
8738 MRN_DBUG_ENTER_METHOD();
8739 fulltext_searching = true;
8740 FT_INFO *info;
8741 if (key_nr == NO_SUCH_KEY) {
8742 struct st_mrn_ft_info *mrn_ft_info = new st_mrn_ft_info();
8743 mrn_ft_info->please = &mrn_no_such_key_ft_vft;
8744#ifdef HA_CAN_FULLTEXT_EXT
8745 mrn_ft_info->could_you = &mrn_no_such_key_ft_vft_ext;
8746#endif
8747 info = (FT_INFO *)mrn_ft_info;
8748 } else {
8749 if (share->wrapper_mode)
8750 {
8751 info = wrapper_ft_init_ext(flags, key_nr, key);
8752 } else {
8753 info = storage_ft_init_ext(flags, key_nr, key);
8754 }
8755 }
8756 DBUG_RETURN(info);
8757}
8758
8759int ha_mroonga::wrapper_ft_read(uchar *buf)
8760{
8761 MRN_DBUG_ENTER_METHOD();
8762 if (wrap_ft_init_count)
8763 set_pk_bitmap();
8764
8765 struct st_mrn_ft_info *mrn_ft_info =
8766 reinterpret_cast<struct st_mrn_ft_info *>(ft_handler);
8767 GRN_CTX_SET_ENCODING(ctx, mrn_ft_info->encoding);
8768
8769 int error = 0;
8770 do {
8771 grn_id found_record_id;
8772 found_record_id = grn_table_cursor_next(ctx, mrn_ft_info->cursor);
8773 if (found_record_id == GRN_ID_NIL) {
8774 error = HA_ERR_END_OF_FILE;
8775 break;
8776 }
8777
8778 GRN_BULK_REWIND(&key_buffer);
8779 if (mrn_ft_info->key_accessor) {
8780 grn_obj_get_value(ctx, mrn_ft_info->key_accessor,
8781 found_record_id, &key_buffer);
8782 } else {
8783 void *key;
8784 int key_length;
8785 key_length = grn_table_cursor_get_key(ctx, mrn_ft_info->cursor, &key);
8786 GRN_TEXT_SET(ctx, &key_buffer, key, key_length);
8787 }
8788 error = wrapper_get_record(buf, (const uchar *)GRN_TEXT_VALUE(&key_buffer));
8789 } while (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND);
8790 DBUG_RETURN(error);
8791}
8792
8793int ha_mroonga::storage_ft_read(uchar *buf)
8794{
8795 MRN_DBUG_ENTER_METHOD();
8796 struct st_mrn_ft_info *mrn_ft_info =
8797 reinterpret_cast<struct st_mrn_ft_info *>(ft_handler);
8798 GRN_CTX_SET_ENCODING(ctx, mrn_ft_info->encoding);
8799
8800 grn_id found_record_id;
8801 found_record_id = grn_table_cursor_next(ctx, mrn_ft_info->cursor);
8802 if (ctx->rc) {
8803 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8804 DBUG_RETURN(ER_ERROR_ON_READ);
8805 }
8806
8807 if (found_record_id == GRN_ID_NIL) {
8808 table->status = STATUS_NOT_FOUND;
8809 DBUG_RETURN(HA_ERR_END_OF_FILE);
8810 }
8811 table->status = 0;
8812
8813 if (count_skip && record_id != GRN_ID_NIL) {
8814 DBUG_RETURN(0);
8815 }
8816
8817 GRN_BULK_REWIND(&key_buffer);
8818 if (mrn_ft_info->id_accessor) {
8819 grn_obj id_buffer;
8820 GRN_RECORD_INIT(&id_buffer, 0, grn_obj_id(ctx, grn_table));
8821 grn_obj_get_value(ctx, mrn_ft_info->id_accessor,
8822 found_record_id, &id_buffer);
8823 record_id = GRN_RECORD_VALUE(&id_buffer);
8824 } else if (mrn_ft_info->key_accessor) {
8825 grn_obj_get_value(ctx, mrn_ft_info->key_accessor,
8826 found_record_id, &key_buffer);
8827 record_id = grn_table_get(ctx, grn_table,
8828 GRN_TEXT_VALUE(&key_buffer),
8829 GRN_TEXT_LEN(&key_buffer));
8830 } else {
8831 void *key;
8832 grn_table_cursor_get_key(ctx, mrn_ft_info->cursor, &key);
8833 if (ctx->rc) {
8834 record_id = GRN_ID_NIL;
8835 my_message(ER_ERROR_ON_READ, ctx->errbuf, MYF(0));
8836 DBUG_RETURN(ER_ERROR_ON_READ);
8837 } else {
8838 record_id = *((grn_id *)key);
8839 }
8840 }
8841 storage_store_fields(buf, record_id);
8842 DBUG_RETURN(0);
8843}
8844
8845int ha_mroonga::ft_read(uchar *buf)
8846{
8847 MRN_DBUG_ENTER_METHOD();
8848 int error = 0;
8849 if (share->wrapper_mode)
8850 {
8851 error = wrapper_ft_read(buf);
8852 } else {
8853 error = storage_ft_read(buf);
8854 }
8855 DBUG_RETURN(error);
8856}
8857
8858const Item *ha_mroonga::wrapper_cond_push(const Item *cond)
8859{
8860 const Item *reminder_cond;
8861 MRN_DBUG_ENTER_METHOD();
8862 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8863 MRN_SET_WRAP_TABLE_KEY(this, table);
8864 reminder_cond = wrap_handler->cond_push(cond);
8865 MRN_SET_BASE_SHARE_KEY(share, table->s);
8866 MRN_SET_BASE_TABLE_KEY(this, table);
8867 DBUG_RETURN(reminder_cond);
8868}
8869
8870const Item *ha_mroonga::storage_cond_push(const Item *cond)
8871{
8872 MRN_DBUG_ENTER_METHOD();
8873 const Item *reminder_cond = cond;
8874 if (!pushed_cond) {
8875 mrn::ConditionConverter converter(ctx, grn_table, true);
8876 if (converter.count_match_against(cond) == 1 &&
8877 converter.is_convertable(cond)) {
8878 reminder_cond = NULL;
8879 }
8880 }
8881 DBUG_RETURN(reminder_cond);
8882}
8883
8884const Item *ha_mroonga::cond_push(const Item *cond)
8885{
8886 MRN_DBUG_ENTER_METHOD();
8887 const Item *reminder_cond;
8888 if (share->wrapper_mode)
8889 {
8890 reminder_cond = wrapper_cond_push(cond);
8891 } else {
8892 reminder_cond = storage_cond_push(cond);
8893 }
8894 DBUG_RETURN(reminder_cond);
8895}
8896
8897void ha_mroonga::wrapper_cond_pop()
8898{
8899 MRN_DBUG_ENTER_METHOD();
8900 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8901 MRN_SET_WRAP_TABLE_KEY(this, table);
8902 wrap_handler->cond_pop();
8903 MRN_SET_BASE_SHARE_KEY(share, table->s);
8904 MRN_SET_BASE_TABLE_KEY(this, table);
8905 DBUG_VOID_RETURN;
8906}
8907
8908void ha_mroonga::storage_cond_pop()
8909{
8910 MRN_DBUG_ENTER_METHOD();
8911 DBUG_VOID_RETURN;
8912}
8913
8914void ha_mroonga::cond_pop()
8915{
8916 MRN_DBUG_ENTER_METHOD();
8917 if (share->wrapper_mode)
8918 wrapper_cond_pop();
8919 else
8920 storage_cond_pop();
8921 DBUG_VOID_RETURN;
8922}
8923
8924bool ha_mroonga::wrapper_get_error_message(int error, String *buf)
8925{
8926 bool temporary_error;
8927 MRN_DBUG_ENTER_METHOD();
8928 MRN_SET_WRAP_SHARE_KEY(share, table->s);
8929 MRN_SET_WRAP_TABLE_KEY(this, table);
8930 temporary_error = wrap_handler->get_error_message(error, buf);
8931 MRN_SET_BASE_SHARE_KEY(share, table->s);
8932 MRN_SET_BASE_TABLE_KEY(this, table);
8933 DBUG_RETURN(temporary_error);
8934}
8935
8936bool ha_mroonga::storage_get_error_message(int error, String *buf)
8937{
8938 MRN_DBUG_ENTER_METHOD();
8939 bool temporary_error = false;
8940 // latest error message
8941 buf->copy(ctx->errbuf, (uint) strlen(ctx->errbuf), system_charset_info);
8942 DBUG_RETURN(temporary_error);
8943}
8944
8945bool ha_mroonga::get_error_message(int error, String *buf)
8946{
8947 MRN_DBUG_ENTER_METHOD();
8948 bool temporary_error;
8949 if (share && share->wrapper_mode)
8950 {
8951 temporary_error = wrapper_get_error_message(error, buf);
8952 } else {
8953 temporary_error = storage_get_error_message(error, buf);
8954 }
8955 DBUG_RETURN(temporary_error);
8956}
8957
8958ulonglong ha_mroonga::file_size(const char *path)
8959{
8960 MRN_DBUG_ENTER_METHOD();
8961
8962 struct stat file_status;
8963 if (stat(path, &file_status) == 0) {
8964 DBUG_RETURN(file_status.st_size);
8965 } else {
8966 DBUG_RETURN(0);
8967 }
8968}
8969
8970bool ha_mroonga::have_unique_index()
8971{
8972 MRN_DBUG_ENTER_METHOD();
8973
8974 uint n_keys = table->s->keys;
8975
8976 for (uint i = 0; i < n_keys; i++) {
8977 if (i == table->s->primary_key) {
8978 continue;
8979 }
8980
8981 KEY *key_info = &(table->key_info[i]);
8982 if (key_info->flags & HA_NOSAME) {
8983 DBUG_RETURN(true);
8984 }
8985 }
8986
8987 DBUG_RETURN(false);
8988}
8989
8990bool ha_mroonga::is_foreign_key_field(const char *table_name,
8991 const char *field_name)
8992{
8993 MRN_DBUG_ENTER_METHOD();
8994
8995 grn_obj *table = grn_ctx_get(ctx, table_name, -1);
8996 if (!table) {
8997 DBUG_RETURN(false);
8998 }
8999
9000 mrn::ColumnName column_name(field_name);
9001 grn_obj *column = grn_obj_column(ctx,
9002 table,
9003 column_name.c_str(),
9004 column_name.length());
9005 if (!column) {
9006 DBUG_RETURN(false);
9007 }
9008
9009 grn_obj *range = grn_ctx_at(ctx, grn_obj_get_range(ctx, column));
9010 if (!range) {
9011 DBUG_RETURN(false);
9012 }
9013
9014 if (!mrn::grn::is_table(range)) {
9015 DBUG_RETURN(false);
9016 }
9017
9018 grn_obj *foreign_index_column;
9019 mrn::IndexColumnName index_column_name(table_name, field_name);
9020 foreign_index_column = grn_obj_column(ctx, range,
9021 index_column_name.c_str(),
9022 index_column_name.length());
9023 if (foreign_index_column) {
9024 grn_obj_unlink(ctx, foreign_index_column);
9025 DBUG_RETURN(true);
9026 }
9027
9028 DBUG_RETURN(false);
9029}
9030
9031void 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
9053void 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
9067void 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
9077void 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
9091void 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
9106void 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
9117void 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
9157int 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
9182void 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
9224void 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
9246int 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
9298int 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
9423int 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
9510int 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
9533bool 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
9565grn_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
9599grn_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
9619grn_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
9654bool 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
9674grn_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
9698grn_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
9720bool 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
9760bool 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
9787bool 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
9811bool 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
9855break_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
9880int 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
9920int 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
9944int 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
10015void 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
10043int 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
10079bool 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
10086bool 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
10093bool 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
10101void 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
10148bool 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
10167bool 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
10188void 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
10356int 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
10365int 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
10380int 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
10444int 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
10484int 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
10511long 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(&micro_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
10538int 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
10549int 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
10572int 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
10592int 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
10616int 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
10653int 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
10679int 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
10703int 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
10727int 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
10739int 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
10751int 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
10767int 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
10780int 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
10882void 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
10891void 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
10969void 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
11021void 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
11032void 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
11056void 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
11075void 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
11095void 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
11115void 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
11131void 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
11152void 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
11169void 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
11186void 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
11200void 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
11236void 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
11247void 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
11341void 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
11406void 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
11458void 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
11524void 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
11552int 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
11581int 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
11592int 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
11604int 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
11651int 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
11711int 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
11741int 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
11795int 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
11827int ha_mroonga::storage_encode_key_datetime2(Field *field, const uchar *key,
11828 uchar *buf, uint *size)
11829{
11830 MRN_DBUG_ENTER_METHOD();
11831 int error = 0;
11832 bool truncated = false;
11833
11834 Field_datetimef *datetime2_field = (Field_datetimef *)field;
11835 longlong packed_time =
11836 my_datetime_packed_from_binary(key, datetime2_field->decimals());
11837 MYSQL_TIME mysql_time;
11838 TIME_from_longlong_datetime_packed(&mysql_time, packed_time);
11839 mrn::TimeConverter time_converter;
11840 long long int grn_time = time_converter.mysql_time_to_grn_time(&mysql_time,
11841 &truncated);
11842 if (truncated) {
11843 if (MRN_ABORT_ON_WARNING(ha_thd())) {
11844 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
11845 }
11846 field->set_warning(MRN_SEVERITY_WARNING,
11847 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
11848 1);
11849 }
11850 memcpy(buf, &grn_time, 8);
11851 *size = 8;
11852
11853 DBUG_RETURN(error);
11854}
11855#endif
11856
11857#ifdef MRN_HAVE_MYSQL_TYPE_TIME2
11858int ha_mroonga::storage_encode_key_time2(Field *field, const uchar *key,
11859 uchar *buf, uint *size)
11860{
11861 MRN_DBUG_ENTER_METHOD();
11862 int error = 0;
11863 bool truncated = false;
11864
11865 Field_timef *time2_field = (Field_timef *)field;
11866 longlong packed_time =
11867 my_time_packed_from_binary(key, time2_field->decimals());
11868 MYSQL_TIME mysql_time;
11869 TIME_from_longlong_time_packed(&mysql_time, packed_time);
11870 mrn::TimeConverter time_converter;
11871 long long int grn_time = time_converter.mysql_time_to_grn_time(&mysql_time,
11872 &truncated);
11873 if (truncated) {
11874 if (MRN_ABORT_ON_WARNING(ha_thd())) {
11875 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
11876 }
11877 field->set_warning(MRN_SEVERITY_WARNING,
11878 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
11879 1);
11880 }
11881 memcpy(buf, &grn_time, 8);
11882 *size = 8;
11883
11884 DBUG_RETURN(error);
11885}
11886#endif
11887
11888int ha_mroonga::storage_encode_key_enum(Field *field, const uchar *key,
11889 uchar *buf, uint *size)
11890{
11891 MRN_DBUG_ENTER_METHOD();
11892 int error = 0;
11893 if (field->pack_length() == 1) {
11894 uchar value;
11895 value = key[0];
11896 *size = 1;
11897 memcpy(buf, &value, *size);
11898 } else {
11899 uint16 value;
11900 mrn::value_decoder::decode(&value, key);
11901 *size = 2;
11902 memcpy(buf, &value, *size);
11903 }
11904 DBUG_RETURN(error);
11905}
11906
11907int ha_mroonga::storage_encode_key_set(Field *field, const uchar *key,
11908 uchar *buf, uint *size)
11909{
11910 MRN_DBUG_ENTER_METHOD();
11911 int error = 0;
11912 Field_set unpacker((uchar *)key, field->field_length, (uchar *)(key - 1),
11913 field->null_bit, field->unireg_check,
11914 &field->field_name,
11915 field->pack_length(),
11916 static_cast<Field_set*>(field)->typelib,
11917 static_cast<Field_set*>(field)->charset());
11918 switch (field->pack_length()) {
11919 case 1:
11920 {
11921 int8 signed_value = (int8)(unpacker.val_int());
11922 uint8 unsigned_value = *((uint8 *)&signed_value);
11923 *size = 1;
11924 memcpy(buf, &unsigned_value, *size);
11925 }
11926 break;
11927 case 2:
11928 {
11929 int16 signed_value = (int16)(unpacker.val_int());
11930 uint16 unsigned_value = *((uint16 *)&signed_value);
11931 *size = 2;
11932 memcpy(buf, &unsigned_value, *size);
11933 }
11934 break;
11935 case 3:
11936 case 4:
11937 {
11938 int32 signed_value = (int32)(unpacker.val_int());
11939 uint32 unsigned_value = *((uint32 *)&signed_value);
11940 *size = 4;
11941 memcpy(buf, &unsigned_value, *size);
11942 }
11943 break;
11944 case 8:
11945 default:
11946 {
11947 int64 signed_value = (int64)(unpacker.val_int());
11948 uint64 unsigned_value = *((uint64 *)&signed_value);
11949 *size = 8;
11950 memcpy(buf, &unsigned_value, *size);
11951 }
11952 break;
11953 }
11954 DBUG_RETURN(error);
11955}
11956
11957int ha_mroonga::storage_encode_key(Field *field, const uchar *key,
11958 uchar *buf, uint *size)
11959{
11960 MRN_DBUG_ENTER_METHOD();
11961 int error;
11962 bool truncated = false;
11963 const uchar *ptr = key;
11964
11965 error = mrn_change_encoding(ctx, field->charset());
11966 if (error)
11967 DBUG_RETURN(error);
11968
11969 if (field->null_bit) {
11970 ptr += 1;
11971 }
11972
11973 switch (field->real_type()) {
11974 case MYSQL_TYPE_BIT:
11975 case MYSQL_TYPE_TINY:
11976 {
11977 memcpy(buf, ptr, 1);
11978 *size = 1;
11979 break;
11980 }
11981 case MYSQL_TYPE_SHORT:
11982 {
11983 memcpy(buf, ptr, 2);
11984 *size = 2;
11985 break;
11986 }
11987 case MYSQL_TYPE_INT24:
11988 {
11989 memcpy(buf, ptr, 3);
11990 buf[3] = 0;
11991 *size = 4;
11992 break;
11993 }
11994 case MYSQL_TYPE_LONG:
11995 {
11996 memcpy(buf, ptr, 4);
11997 *size = 4;
11998 break;
11999 }
12000 case MYSQL_TYPE_TIMESTAMP:
12001 error = storage_encode_key_timestamp(field, ptr, buf, size);
12002 break;
12003 case MYSQL_TYPE_LONGLONG:
12004 {
12005 memcpy(buf, ptr, 8);
12006 *size = 8;
12007 break;
12008 }
12009 case MYSQL_TYPE_FLOAT:
12010 {
12011 float float_value;
12012 double double_value;
12013 mrn::value_decoder::decode(&float_value, ptr);
12014 double_value = float_value;
12015 memcpy(buf, &double_value, 8);
12016 *size = 8;
12017 break;
12018 }
12019 case MYSQL_TYPE_DOUBLE:
12020 {
12021 double val;
12022 mrn::value_decoder::decode(&val, ptr);
12023 memcpy(buf, &val, 8);
12024 *size = 8;
12025 break;
12026 }
12027 case MYSQL_TYPE_TIME:
12028 error = storage_encode_key_time(field, ptr, buf, size);
12029 break;
12030 case MYSQL_TYPE_YEAR:
12031 error = storage_encode_key_year(field, ptr, buf, size);
12032 break;
12033 case MYSQL_TYPE_DATETIME:
12034 error = storage_encode_key_datetime(field, ptr, buf, size);
12035 break;
12036 case MYSQL_TYPE_NEWDATE:
12037 {
12038 uint32 encoded_date = uint3korr(ptr);
12039 struct tm date;
12040 memset(&date, 0, sizeof(struct tm));
12041 date.tm_year = encoded_date / (16 * 32) - mrn::TimeConverter::TM_YEAR_BASE;
12042 date.tm_mon = encoded_date / 32 % 16 - 1;
12043 date.tm_mday = encoded_date % 32;
12044 int usec = 0;
12045 mrn::TimeConverter time_converter;
12046 long long int time = time_converter.tm_to_grn_time(&date, usec,
12047 &truncated);
12048 if (truncated) {
12049 if (MRN_ABORT_ON_WARNING(ha_thd())) {
12050 error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd());
12051 }
12052 field->set_warning(MRN_SEVERITY_WARNING,
12053 MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()),
12054 1);
12055 }
12056 memcpy(buf, &time, 8);
12057 *size = 8;
12058 break;
12059 }
12060#ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2
12061 case MYSQL_TYPE_TIMESTAMP2:
12062 error = storage_encode_key_timestamp2(field, ptr, buf, size);
12063 break;
12064#endif
12065#ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2
12066 case MYSQL_TYPE_DATETIME2:
12067 error = storage_encode_key_datetime2(field, ptr, buf, size);
12068 break;
12069#endif
12070#ifdef MRN_HAVE_MYSQL_TYPE_TIME2
12071 case MYSQL_TYPE_TIME2:
12072 error = storage_encode_key_time2(field, ptr, buf, size);
12073 break;
12074#endif
12075 case MYSQL_TYPE_STRING:
12076 error = storage_encode_key_fixed_size_string(field, ptr, buf, size);
12077 break;
12078 case MYSQL_TYPE_VARCHAR:
12079 case MYSQL_TYPE_BLOB:
12080 error = storage_encode_key_variable_size_string(field, ptr, buf, size);
12081 break;
12082 case MYSQL_TYPE_ENUM:
12083 error = storage_encode_key_enum(field, ptr, buf, size);
12084 break;
12085 case MYSQL_TYPE_SET:
12086 error = storage_encode_key_set(field, ptr, buf, size);
12087 break;
12088 default:
12089 error = HA_ERR_UNSUPPORTED;
12090 break;
12091 }
12092 DBUG_RETURN(error);
12093}
12094
12095int ha_mroonga::storage_encode_multiple_column_key(KEY *key_info,
12096 const uchar *key,
12097 uint key_length,
12098 uchar *buffer,
12099 uint *encoded_length)
12100{
12101 MRN_DBUG_ENTER_METHOD();
12102 mrn::MultipleColumnKeyCodec codec(ctx, ha_thd(), key_info);
12103 int error = codec.encode(key, key_length, buffer, encoded_length);
12104 DBUG_RETURN(error);
12105}
12106
12107int ha_mroonga::storage_encode_multiple_column_key_range(KEY *key_info,
12108 const uchar *start,
12109 uint start_size,
12110 const uchar *end,
12111 uint end_size,
12112 uchar *min_buffer,
12113 uint *min_encoded_size,
12114 uchar *max_buffer,
12115 uint *max_encoded_size)
12116{
12117 MRN_DBUG_ENTER_METHOD();
12118 int error = 0;
12119 mrn::MultipleColumnKeyCodec codec(ctx, ha_thd(), key_info);
12120 uint encoded_key_size = codec.size();
12121 if (start) {
12122 memset(min_buffer, 0, encoded_key_size);
12123 error = codec.encode(start, start_size,
12124 min_buffer, min_encoded_size);
12125 // TODO: handle error?
12126 *min_encoded_size = encoded_key_size;
12127 }
12128 if (end) {
12129 memset(max_buffer, 0xff, encoded_key_size);
12130 error = codec.encode(end, end_size,
12131 max_buffer, max_encoded_size);
12132 // TODO: handle error?
12133 *max_encoded_size = encoded_key_size;
12134 }
12135 DBUG_RETURN(error);
12136}
12137
12138int ha_mroonga::storage_encode_multiple_column_key_range(KEY *key_info,
12139 const key_range *start,
12140 const key_range *end,
12141 uchar *min_buffer,
12142 uint *min_encoded_size,
12143 uchar *max_buffer,
12144 uint *max_encoded_size)
12145{
12146 MRN_DBUG_ENTER_METHOD();
12147
12148 const uchar *start_data = NULL;
12149 uint start_size = 0;
12150 const uchar *end_data = NULL;
12151 uint end_size = 0;
12152 if (start) {
12153 start_data = start->key;
12154 start_size = start->length;
12155 }
12156 if (end) {
12157 end_data = end->key;
12158 end_size = end->length;
12159 }
12160
12161 int error = storage_encode_multiple_column_key_range(key_info,
12162 start_data, start_size,
12163 end_data, end_size,
12164 min_buffer,
12165 min_encoded_size,
12166 max_buffer,
12167 max_encoded_size);
12168
12169 DBUG_RETURN(error);
12170}
12171
12172int ha_mroonga::generic_reset()
12173{
12174 MRN_DBUG_ENTER_METHOD();
12175 int error = 0;
12176
12177 if (thd_sql_command(ha_thd()) != SQLCOM_SELECT) {
12178 DBUG_RETURN(error);
12179 }
12180
12181 TABLE_LIST *table_list = table->pos_in_table_list;
12182 if (!table_list) {
12183 DBUG_RETURN(error);
12184 }
12185
12186 st_select_lex *select_lex = table_list->select_lex;
12187 if (!select_lex) {
12188 DBUG_RETURN(error);
12189 }
12190
12191 List_iterator<Item_func_match> iterator(*(select_lex->ftfunc_list));
12192 Item_func_match *item;
12193 while ((item = iterator++)) {
12194 if (item->ft_handler) {
12195 mrn_generic_ft_clear(item->ft_handler);
12196 }
12197 }
12198
12199 DBUG_RETURN(error);
12200}
12201
12202int ha_mroonga::wrapper_reset()
12203{
12204 MRN_DBUG_ENTER_METHOD();
12205 int error = 0;
12206 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12207 MRN_SET_WRAP_TABLE_KEY(this, table);
12208 error = wrap_handler->ha_reset();
12209 MRN_SET_BASE_SHARE_KEY(share, table->s);
12210 MRN_SET_BASE_TABLE_KEY(this, table);
12211#ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER
12212 if (alter_key_info_buffer) {
12213 my_free(alter_key_info_buffer);
12214 alter_key_info_buffer = NULL;
12215 }
12216#else
12217 if (wrap_alter_key_info) {
12218 my_free(wrap_alter_key_info);
12219 wrap_alter_key_info = NULL;
12220 }
12221#endif
12222 wrap_ft_init_count = 0;
12223 int generic_error = generic_reset();
12224 if (error == 0) {
12225 error = generic_error;
12226 }
12227 DBUG_RETURN(error);
12228}
12229
12230int ha_mroonga::storage_reset()
12231{
12232 MRN_DBUG_ENTER_METHOD();
12233 int error;
12234 error = generic_reset();
12235 DBUG_RETURN(error);
12236}
12237
12238int ha_mroonga::reset()
12239{
12240 int error = 0;
12241 THD *thd = ha_thd();
12242 MRN_DBUG_ENTER_METHOD();
12243 DBUG_PRINT("info", ("mroonga: this=%p", this));
12244 clear_empty_value_records();
12245 clear_search_result();
12246 clear_search_result_geo();
12247 if (share->wrapper_mode)
12248 error = wrapper_reset();
12249 else
12250 error = storage_reset();
12251 ignoring_no_key_columns = false;
12252 inserting_with_update = false;
12253 ignoring_duplicated_key = false;
12254 fulltext_searching = false;
12255 replacing_ = false;
12256 written_by_row_based_binlog = 0;
12257 mrn_lock_type = F_UNLCK;
12258 mrn_clear_slot_data(thd);
12259 current_ft_item = NULL;
12260 DBUG_RETURN(error);
12261}
12262
12263handler *ha_mroonga::wrapper_clone(const char *name, MEM_ROOT *mem_root)
12264{
12265 handler *cloned_handler;
12266 MRN_DBUG_ENTER_METHOD();
12267 if (!(cloned_handler = get_new_handler(table->s, mem_root,
12268 table->s->db_type())))
12269 DBUG_RETURN(NULL);
12270 ((ha_mroonga *) cloned_handler)->is_clone = true;
12271 ((ha_mroonga *) cloned_handler)->parent_for_clone = this;
12272 ((ha_mroonga *) cloned_handler)->mem_root_for_clone = mem_root;
12273 if (cloned_handler->ha_open(table, table->s->normalized_path.str,
12274 table->db_stat, HA_OPEN_IGNORE_IF_LOCKED))
12275 {
12276 delete cloned_handler;
12277 DBUG_RETURN(NULL);
12278 }
12279 DBUG_RETURN(cloned_handler);
12280}
12281
12282handler *ha_mroonga::storage_clone(const char *name, MEM_ROOT *mem_root)
12283{
12284 MRN_DBUG_ENTER_METHOD();
12285 handler *cloned_handler;
12286 cloned_handler = handler::clone(name, mem_root);
12287 DBUG_RETURN(cloned_handler);
12288}
12289
12290handler *ha_mroonga::clone(const char *name, MEM_ROOT *mem_root)
12291{
12292 MRN_DBUG_ENTER_METHOD();
12293 handler *cloned_handler;
12294 if (share->wrapper_mode)
12295 {
12296 cloned_handler = wrapper_clone(name, mem_root);
12297 } else {
12298 cloned_handler = storage_clone(name, mem_root);
12299 }
12300 DBUG_RETURN(cloned_handler);
12301}
12302
12303uint8 ha_mroonga::wrapper_table_cache_type()
12304{
12305 uint8 res;
12306 MRN_DBUG_ENTER_METHOD();
12307 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12308 MRN_SET_WRAP_TABLE_KEY(this, table);
12309 res = wrap_handler->table_cache_type();
12310 MRN_SET_BASE_SHARE_KEY(share, table->s);
12311 MRN_SET_BASE_TABLE_KEY(this, table);
12312 DBUG_RETURN(res);
12313}
12314
12315uint8 ha_mroonga::storage_table_cache_type()
12316{
12317 MRN_DBUG_ENTER_METHOD();
12318 uint8 type = handler::table_cache_type();
12319 DBUG_RETURN(type);
12320}
12321
12322uint8 ha_mroonga::table_cache_type()
12323{
12324 MRN_DBUG_ENTER_METHOD();
12325 uint8 type;
12326 if (share->wrapper_mode)
12327 {
12328 type = wrapper_table_cache_type();
12329 } else {
12330 type = storage_table_cache_type();
12331 }
12332 DBUG_RETURN(type);
12333}
12334
12335#ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ
12336ha_rows ha_mroonga::wrapper_multi_range_read_info_const(uint keyno,
12337 RANGE_SEQ_IF *seq,
12338 void *seq_init_param,
12339 uint n_ranges,
12340 uint *bufsz,
12341 uint *flags,
12342 Cost_estimate *cost)
12343{
12344 MRN_DBUG_ENTER_METHOD();
12345 ha_rows rows;
12346 KEY *key_info = &(table->key_info[keyno]);
12347 if (mrn_is_geo_key(key_info)) {
12348 rows = handler::multi_range_read_info_const(keyno, seq, seq_init_param,
12349 n_ranges, bufsz, flags, cost);
12350 DBUG_RETURN(rows);
12351 }
12352 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12353 MRN_SET_WRAP_TABLE_KEY(this, table);
12354 if (fulltext_searching)
12355 set_pk_bitmap();
12356 rows = wrap_handler->multi_range_read_info_const(keyno, seq, seq_init_param,
12357 n_ranges, bufsz, flags,
12358 cost);
12359 MRN_SET_BASE_SHARE_KEY(share, table->s);
12360 MRN_SET_BASE_TABLE_KEY(this, table);
12361 DBUG_RETURN(rows);
12362}
12363
12364ha_rows ha_mroonga::storage_multi_range_read_info_const(uint keyno,
12365 RANGE_SEQ_IF *seq,
12366 void *seq_init_param,
12367 uint n_ranges,
12368 uint *bufsz,
12369 uint *flags,
12370 Cost_estimate *cost)
12371{
12372 MRN_DBUG_ENTER_METHOD();
12373 ha_rows rows = handler::multi_range_read_info_const(keyno, seq,
12374 seq_init_param,
12375 n_ranges, bufsz, flags,
12376 cost);
12377 DBUG_RETURN(rows);
12378}
12379
12380ha_rows ha_mroonga::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
12381 void *seq_init_param,
12382 uint n_ranges, uint *bufsz,
12383 uint *flags,
12384 Cost_estimate *cost)
12385{
12386 MRN_DBUG_ENTER_METHOD();
12387 ha_rows rows;
12388 if (share->wrapper_mode)
12389 {
12390 rows = wrapper_multi_range_read_info_const(keyno, seq, seq_init_param,
12391 n_ranges, bufsz,
12392 flags, cost);
12393 } else {
12394 rows = storage_multi_range_read_info_const(keyno, seq, seq_init_param,
12395 n_ranges, bufsz,
12396 flags, cost);
12397 }
12398 DBUG_RETURN(rows);
12399}
12400
12401ha_rows ha_mroonga::wrapper_multi_range_read_info(uint keyno, uint n_ranges,
12402 uint keys,
12403#ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12404 uint key_parts,
12405#endif
12406 uint *bufsz,
12407 uint *flags,
12408 Cost_estimate *cost)
12409{
12410 MRN_DBUG_ENTER_METHOD();
12411 ha_rows rows;
12412 KEY *key_info = &(table->key_info[keyno]);
12413 if (mrn_is_geo_key(key_info)) {
12414 rows = handler::multi_range_read_info(keyno, n_ranges, keys,
12415#ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12416 key_parts,
12417#endif
12418 bufsz, flags, cost);
12419 DBUG_RETURN(rows);
12420 }
12421 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12422 MRN_SET_WRAP_TABLE_KEY(this, table);
12423 if (fulltext_searching)
12424 set_pk_bitmap();
12425 rows = wrap_handler->multi_range_read_info(keyno, n_ranges, keys,
12426#ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12427 key_parts,
12428#endif
12429 bufsz, flags, cost);
12430 MRN_SET_BASE_SHARE_KEY(share, table->s);
12431 MRN_SET_BASE_TABLE_KEY(this, table);
12432 DBUG_RETURN(rows);
12433}
12434
12435ha_rows ha_mroonga::storage_multi_range_read_info(uint keyno, uint n_ranges,
12436 uint keys,
12437#ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12438 uint key_parts,
12439#endif
12440 uint *bufsz,
12441 uint *flags,
12442 Cost_estimate *cost)
12443{
12444 MRN_DBUG_ENTER_METHOD();
12445 ha_rows rows = handler::multi_range_read_info(keyno, n_ranges, keys,
12446#ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12447 key_parts,
12448#endif
12449 bufsz, flags, cost);
12450 DBUG_RETURN(rows);
12451}
12452
12453ha_rows ha_mroonga::multi_range_read_info(uint keyno, uint n_ranges, uint keys,
12454#ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12455 uint key_parts,
12456#endif
12457 uint *bufsz, uint *flags,
12458 Cost_estimate *cost)
12459{
12460 MRN_DBUG_ENTER_METHOD();
12461 ha_rows rows;
12462 if (share->wrapper_mode)
12463 {
12464 rows = wrapper_multi_range_read_info(keyno, n_ranges, keys,
12465#ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12466 key_parts,
12467#endif
12468 bufsz, flags, cost);
12469 } else {
12470 rows = storage_multi_range_read_info(keyno, n_ranges, keys,
12471#ifdef MRN_HANDLER_HAVE_MULTI_RANGE_READ_INFO_KEY_PARTS
12472 key_parts,
12473#endif
12474 bufsz, flags, cost);
12475 }
12476 DBUG_RETURN(rows);
12477}
12478
12479int ha_mroonga::wrapper_multi_range_read_init(RANGE_SEQ_IF *seq,
12480 void *seq_init_param,
12481 uint n_ranges, uint mode,
12482 HANDLER_BUFFER *buf)
12483{
12484 MRN_DBUG_ENTER_METHOD();
12485 int error = 0;
12486 KEY *key_info = &(table->key_info[active_index]);
12487 if (mrn_is_geo_key(key_info)) {
12488 error = handler::multi_range_read_init(seq, seq_init_param,
12489 n_ranges, mode, buf);
12490 DBUG_RETURN(error);
12491 }
12492 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12493 MRN_SET_WRAP_TABLE_KEY(this, table);
12494 if (fulltext_searching)
12495 set_pk_bitmap();
12496 error = wrap_handler->multi_range_read_init(seq, seq_init_param,
12497 n_ranges, mode, buf);
12498 MRN_SET_BASE_SHARE_KEY(share, table->s);
12499 MRN_SET_BASE_TABLE_KEY(this, table);
12500 DBUG_RETURN(error);
12501}
12502
12503int ha_mroonga::storage_multi_range_read_init(RANGE_SEQ_IF *seq,
12504 void *seq_init_param,
12505 uint n_ranges, uint mode,
12506 HANDLER_BUFFER *buf)
12507{
12508 MRN_DBUG_ENTER_METHOD();
12509 int error = handler::multi_range_read_init(seq, seq_init_param,
12510 n_ranges, mode, buf);
12511 DBUG_RETURN(error);
12512}
12513
12514int ha_mroonga::multi_range_read_init(RANGE_SEQ_IF *seq, void *seq_init_param,
12515 uint n_ranges, uint mode,
12516 HANDLER_BUFFER *buf)
12517{
12518 MRN_DBUG_ENTER_METHOD();
12519 int error = 0;
12520 if (share->wrapper_mode)
12521 {
12522 error = wrapper_multi_range_read_init(seq, seq_init_param,
12523 n_ranges, mode, buf);
12524 } else {
12525 error = storage_multi_range_read_init(seq, seq_init_param,
12526 n_ranges, mode, buf);
12527 }
12528 DBUG_RETURN(error);
12529}
12530
12531int ha_mroonga::wrapper_multi_range_read_next(range_id_t *range_info)
12532{
12533 MRN_DBUG_ENTER_METHOD();
12534 int error = 0;
12535 KEY *key_info = &(table->key_info[active_index]);
12536 if (mrn_is_geo_key(key_info)) {
12537 error = handler::multi_range_read_next(range_info);
12538 DBUG_RETURN(error);
12539 }
12540 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12541 MRN_SET_WRAP_TABLE_KEY(this, table);
12542 if (fulltext_searching)
12543 set_pk_bitmap();
12544 error = wrap_handler->multi_range_read_next(range_info);
12545 MRN_SET_BASE_SHARE_KEY(share, table->s);
12546 MRN_SET_BASE_TABLE_KEY(this, table);
12547 DBUG_RETURN(error);
12548}
12549
12550int ha_mroonga::storage_multi_range_read_next(range_id_t *range_info)
12551{
12552 MRN_DBUG_ENTER_METHOD();
12553 int error = handler::multi_range_read_next(range_info);
12554 DBUG_RETURN(error);
12555}
12556
12557int ha_mroonga::multi_range_read_next(range_id_t *range_info)
12558{
12559 MRN_DBUG_ENTER_METHOD();
12560 int error = 0;
12561 if (share->wrapper_mode)
12562 {
12563 error = wrapper_multi_range_read_next(range_info);
12564 } else {
12565 error = storage_multi_range_read_next(range_info);
12566 }
12567 DBUG_RETURN(error);
12568}
12569#else // MRN_HANDLER_HAVE_MULTI_RANGE_READ
12570int ha_mroonga::wrapper_read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
12571 KEY_MULTI_RANGE *ranges,
12572 uint range_count,
12573 bool sorted,
12574 HANDLER_BUFFER *buffer)
12575{
12576 int error = 0;
12577 MRN_DBUG_ENTER_METHOD();
12578 KEY *key_info = &(table->key_info[active_index]);
12579 if (mrn_is_geo_key(key_info)) {
12580 error = handler::read_multi_range_first(found_range_p, ranges,
12581 range_count, sorted, buffer);
12582 DBUG_RETURN(error);
12583 }
12584 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12585 MRN_SET_WRAP_TABLE_KEY(this, table);
12586 if (fulltext_searching)
12587 set_pk_bitmap();
12588 error = wrap_handler->read_multi_range_first(found_range_p, ranges,
12589 range_count, sorted, buffer);
12590 MRN_SET_BASE_SHARE_KEY(share, table->s);
12591 MRN_SET_BASE_TABLE_KEY(this, table);
12592 DBUG_RETURN(error);
12593}
12594
12595int ha_mroonga::storage_read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
12596 KEY_MULTI_RANGE *ranges,
12597 uint range_count,
12598 bool sorted,
12599 HANDLER_BUFFER *buffer)
12600{
12601 MRN_DBUG_ENTER_METHOD();
12602 int error = handler::read_multi_range_first(found_range_p, ranges,
12603 range_count, sorted, buffer);
12604 DBUG_RETURN(error);
12605}
12606
12607int ha_mroonga::read_multi_range_first(KEY_MULTI_RANGE **found_range_p,
12608 KEY_MULTI_RANGE *ranges,
12609 uint range_count,
12610 bool sorted,
12611 HANDLER_BUFFER *buffer)
12612{
12613 MRN_DBUG_ENTER_METHOD();
12614 int error = 0;
12615 if (share->wrapper_mode)
12616 {
12617 error = wrapper_read_multi_range_first(found_range_p, ranges,
12618 range_count, sorted, buffer);
12619 } else {
12620 error = storage_read_multi_range_first(found_range_p, ranges,
12621 range_count, sorted, buffer);
12622 }
12623 DBUG_RETURN(error);
12624}
12625
12626int ha_mroonga::wrapper_read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
12627{
12628 int error = 0;
12629 MRN_DBUG_ENTER_METHOD();
12630 KEY *key_info = &(table->key_info[active_index]);
12631 if (mrn_is_geo_key(key_info)) {
12632 error = handler::read_multi_range_next(found_range_p);
12633 DBUG_RETURN(error);
12634 }
12635 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12636 MRN_SET_WRAP_TABLE_KEY(this, table);
12637 if (fulltext_searching)
12638 set_pk_bitmap();
12639 error = wrap_handler->read_multi_range_next(found_range_p);
12640 MRN_SET_BASE_SHARE_KEY(share, table->s);
12641 MRN_SET_BASE_TABLE_KEY(this, table);
12642 DBUG_RETURN(error);
12643}
12644
12645int ha_mroonga::storage_read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
12646{
12647 MRN_DBUG_ENTER_METHOD();
12648 int error = handler::read_multi_range_next(found_range_p);
12649 DBUG_RETURN(error);
12650}
12651
12652int ha_mroonga::read_multi_range_next(KEY_MULTI_RANGE **found_range_p)
12653{
12654 MRN_DBUG_ENTER_METHOD();
12655 int error = 0;
12656 if (share->wrapper_mode)
12657 {
12658 error = wrapper_read_multi_range_next(found_range_p);
12659 } else {
12660 error = storage_read_multi_range_next(found_range_p);
12661 }
12662 DBUG_RETURN(error);
12663}
12664#endif // MRN_HANDLER_HAVE_MULTI_RANGE_READ
12665
12666#ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
12667void ha_mroonga::wrapper_start_bulk_insert(ha_rows rows, uint flags)
12668#else
12669void ha_mroonga::wrapper_start_bulk_insert(ha_rows rows)
12670#endif
12671{
12672 MRN_DBUG_ENTER_METHOD();
12673 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12674 MRN_SET_WRAP_TABLE_KEY(this, table);
12675#ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
12676 wrap_handler->ha_start_bulk_insert(rows, flags);
12677#else
12678 wrap_handler->ha_start_bulk_insert(rows);
12679#endif
12680 MRN_SET_BASE_SHARE_KEY(share, table->s);
12681 MRN_SET_BASE_TABLE_KEY(this, table);
12682 DBUG_VOID_RETURN;
12683}
12684
12685#ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
12686void ha_mroonga::storage_start_bulk_insert(ha_rows rows, uint flags)
12687#else
12688void ha_mroonga::storage_start_bulk_insert(ha_rows rows)
12689#endif
12690{
12691 MRN_DBUG_ENTER_METHOD();
12692 DBUG_VOID_RETURN;
12693}
12694
12695#ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
12696void ha_mroonga::start_bulk_insert(ha_rows rows, uint flags)
12697#else
12698void ha_mroonga::start_bulk_insert(ha_rows rows)
12699#endif
12700{
12701 MRN_DBUG_ENTER_METHOD();
12702 if (share->wrapper_mode) {
12703#ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
12704 wrapper_start_bulk_insert(rows, flags);
12705#else
12706 wrapper_start_bulk_insert(rows);
12707#endif
12708 } else {
12709#ifdef MRN_HANDLER_START_BULK_INSERT_HAS_FLAGS
12710 storage_start_bulk_insert(rows, flags);
12711#else
12712 storage_start_bulk_insert(rows);
12713#endif
12714 }
12715 DBUG_VOID_RETURN;
12716}
12717
12718int ha_mroonga::wrapper_end_bulk_insert()
12719{
12720 int error = 0;
12721 MRN_DBUG_ENTER_METHOD();
12722 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12723 MRN_SET_WRAP_TABLE_KEY(this, table);
12724 error = wrap_handler->ha_end_bulk_insert();
12725 MRN_SET_BASE_SHARE_KEY(share, table->s);
12726 MRN_SET_BASE_TABLE_KEY(this, table);
12727 DBUG_RETURN(error);
12728}
12729
12730int ha_mroonga::storage_end_bulk_insert()
12731{
12732 MRN_DBUG_ENTER_METHOD();
12733 DBUG_RETURN(0);
12734}
12735
12736int ha_mroonga::end_bulk_insert()
12737{
12738 MRN_DBUG_ENTER_METHOD();
12739 int error = 0;
12740 if (share->wrapper_mode)
12741 {
12742 error = wrapper_end_bulk_insert();
12743 } else {
12744 error = storage_end_bulk_insert();
12745 }
12746 DBUG_RETURN(error);
12747}
12748
12749int ha_mroonga::generic_delete_all_rows(grn_obj *target_grn_table,
12750 const char *function_name)
12751{
12752 MRN_DBUG_ENTER_METHOD();
12753
12754 int error = 0;
12755
12756 error = mrn_change_encoding(ctx, system_charset_info);
12757 if (error)
12758 DBUG_RETURN(error);
12759
12760 if (is_dry_write()) {
12761 DBUG_PRINT("info",
12762 ("mroonga: dry write: %s::%s", MRN_CLASS_NAME, function_name));
12763 DBUG_RETURN(error);
12764 }
12765
12766 grn_table_cursor *cursor;
12767 cursor = grn_table_cursor_open(ctx, target_grn_table,
12768 NULL, 0,
12769 NULL, 0,
12770 0, -1,
12771 0);
12772 if (cursor) {
12773 while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) {
12774 grn_table_cursor_delete(ctx, cursor);
12775 }
12776 grn_table_cursor_close(ctx, cursor);
12777 } else {
12778 error = ER_ERROR_ON_WRITE;
12779 my_message(error, ctx->errbuf, MYF(0));
12780 }
12781 DBUG_RETURN(error);
12782}
12783
12784int ha_mroonga::wrapper_delete_all_rows()
12785{
12786 int error = 0;
12787 MRN_DBUG_ENTER_METHOD();
12788 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12789 MRN_SET_WRAP_TABLE_KEY(this, table);
12790 error = wrap_handler->ha_delete_all_rows();
12791 MRN_SET_BASE_SHARE_KEY(share, table->s);
12792 MRN_SET_BASE_TABLE_KEY(this, table);
12793
12794 if (error) {
12795 DBUG_RETURN(error);
12796 }
12797
12798 if (!wrapper_have_target_index()) {
12799 DBUG_RETURN(error);
12800 }
12801
12802 uint i;
12803 uint n_keys = table->s->keys;
12804 for (i = 0; i < n_keys; i++) {
12805 KEY *key_info = &(table->key_info[i]);
12806
12807 if (!(wrapper_is_target_index(key_info))) {
12808 continue;
12809 }
12810
12811 if (!grn_index_tables[i]) {
12812 /* disable keys */
12813 continue;
12814 }
12815
12816 error = generic_delete_all_rows(grn_index_tables[i], __FUNCTION__);
12817 if (error) {
12818 break;
12819 }
12820 }
12821
12822 int grn_table_error;
12823 grn_table_error = generic_delete_all_rows(grn_table, __FUNCTION__);
12824 if (!error) {
12825 error = grn_table_error;
12826 }
12827
12828 DBUG_RETURN(error);
12829}
12830
12831int ha_mroonga::storage_delete_all_rows()
12832{
12833 MRN_DBUG_ENTER_METHOD();
12834 int error = generic_delete_all_rows(grn_table, __FUNCTION__);
12835 if (!error) {
12836 uint n_keys = table->s->keys;
12837 for (uint i = 0; i < n_keys; i++) {
12838 if (i == table->s->primary_key) {
12839 continue;
12840 }
12841
12842 KEY *key_info = &(table->key_info[i]);
12843 if (!(key_info->flags & HA_NOSAME)) {
12844 continue;
12845 }
12846
12847 grn_obj *index_table = grn_index_tables[i];
12848 if (!index_table) {
12849 continue;
12850 }
12851
12852 error = generic_delete_all_rows(index_table, __FUNCTION__);
12853 if (error) {
12854 break;
12855 }
12856 }
12857 }
12858 DBUG_RETURN(error);
12859}
12860
12861int ha_mroonga::delete_all_rows()
12862{
12863 MRN_DBUG_ENTER_METHOD();
12864 int error = 0;
12865 if (share->wrapper_mode)
12866 {
12867 error = wrapper_delete_all_rows();
12868 } else {
12869 error = storage_delete_all_rows();
12870 }
12871 DBUG_RETURN(error);
12872}
12873
12874int ha_mroonga::wrapper_truncate()
12875{
12876 int error = 0;
12877 MRN_DBUG_ENTER_METHOD();
12878 MRN_SET_WRAP_SHARE_KEY(share, table->s);
12879 MRN_SET_WRAP_TABLE_KEY(this, table);
12880 error = wrap_handler->ha_truncate();
12881 MRN_SET_BASE_SHARE_KEY(share, table->s);
12882 MRN_SET_BASE_TABLE_KEY(this, table);
12883
12884 if (!error && wrapper_have_target_index()) {
12885 error = wrapper_truncate_index();
12886 }
12887
12888 DBUG_RETURN(error);
12889}
12890
12891int ha_mroonga::wrapper_truncate_index()
12892{
12893 MRN_DBUG_ENTER_METHOD();
12894
12895 int error = 0;
12896
12897 error = mrn_change_encoding(ctx, system_charset_info);
12898 if (error)
12899 DBUG_RETURN(error);
12900
12901 if (is_dry_write()) {
12902 DBUG_PRINT("info",
12903 ("mroonga: dry write: %s::%s", MRN_CLASS_NAME, __FUNCTION__));
12904 DBUG_RETURN(error);
12905 }
12906
12907 grn_rc rc;
12908 uint i;
12909 uint n_keys = table->s->keys;
12910 for (i = 0; i < n_keys; i++) {
12911 KEY *key_info = &(table->key_info[i]);
12912
12913 if (!(wrapper_is_target_index(key_info))) {
12914 continue;
12915 }
12916
12917 if (!grn_index_tables[i]) {
12918 /* disable keys */
12919 continue;
12920 }
12921
12922 rc = grn_table_truncate(ctx, grn_index_tables[i]);
12923 if (rc) {
12924 error = ER_ERROR_ON_WRITE;
12925 my_message(error, ctx->errbuf, MYF(0));
12926 goto err;
12927 }
12928 }
12929err:
12930 rc = grn_table_truncate(ctx, grn_table);
12931 if (rc) {
12932 error = ER_ERROR_ON_WRITE;
12933 my_message(error, ctx->errbuf, MYF(0));
12934 }
12935
12936 DBUG_RETURN(error);
12937}
12938
12939int ha_mroonga::storage_truncate()
12940{
12941 MRN_DBUG_ENTER_METHOD();
12942 int error = 0;
12943
12944 if (is_dry_write()) {
12945 DBUG_PRINT("info", ("mroonga: dry write: ha_mroonga::%s", __FUNCTION__));
12946 DBUG_RETURN(error);
12947 }
12948
12949 grn_rc rc;
12950 rc = grn_table_truncate(ctx, grn_table);
12951 if (rc) {
12952 my_message(ER_ERROR_ON_WRITE, ctx->errbuf, MYF(0));
12953 DBUG_RETURN(ER_ERROR_ON_WRITE);
12954 }
12955 error = storage_truncate_index();
12956
12957 if (!error && thd_sql_command(ha_thd()) == SQLCOM_TRUNCATE) {
12958 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
12959 mrn::Lock lock(&long_term_share->auto_inc_mutex);
12960 long_term_share->auto_inc_value = 0;
12961 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
12962 long_term_share->auto_inc_value));
12963 long_term_share->auto_inc_inited = false;
12964 }
12965
12966 DBUG_RETURN(error);
12967}
12968
12969int ha_mroonga::storage_truncate_index()
12970{
12971 MRN_DBUG_ENTER_METHOD();
12972 int error = 0;
12973
12974 error = mrn_change_encoding(ctx, system_charset_info);
12975 if (error)
12976 DBUG_RETURN(error);
12977
12978 grn_rc rc;
12979 uint i;
12980 uint n_keys = table->s->keys;
12981 for (i = 0; i < n_keys; i++) {
12982 if (i == table->s->primary_key) {
12983 continue;
12984 }
12985
12986 KEY *key_info = &(table->key_info[i]);
12987
12988 if (
12989 !(key_info->flags & HA_NOSAME) &&
12990 (KEY_N_KEY_PARTS(key_info) == 1 || (key_info->flags & HA_FULLTEXT))
12991 ) {
12992 continue;
12993 }
12994
12995 if (!grn_index_tables[i]) {
12996 /* disable keys */
12997 continue;
12998 }
12999
13000 rc = grn_table_truncate(ctx, grn_index_tables[i]);
13001 if (rc) {
13002 error = ER_ERROR_ON_WRITE;
13003 my_message(error, ctx->errbuf, MYF(0));
13004 goto err;
13005 }
13006 }
13007err:
13008 DBUG_RETURN(error);
13009}
13010
13011int ha_mroonga::truncate()
13012{
13013 MRN_DBUG_ENTER_METHOD();
13014 int error = 0;
13015 if (share->wrapper_mode)
13016 {
13017 error = wrapper_truncate();
13018 } else {
13019 error = storage_truncate();
13020 }
13021 if (!error) {
13022 operations_->clear(table->s->table_name.str,
13023 table->s->table_name.length);
13024 }
13025 DBUG_RETURN(error);
13026}
13027
13028double ha_mroonga::wrapper_scan_time()
13029{
13030 double res;
13031 MRN_DBUG_ENTER_METHOD();
13032 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13033 MRN_SET_WRAP_TABLE_KEY(this, table);
13034 res = wrap_handler->scan_time();
13035 MRN_SET_BASE_SHARE_KEY(share, table->s);
13036 MRN_SET_BASE_TABLE_KEY(this, table);
13037 DBUG_RETURN(res);
13038}
13039
13040double ha_mroonga::storage_scan_time()
13041{
13042 MRN_DBUG_ENTER_METHOD();
13043 double time = handler::scan_time();
13044 DBUG_RETURN(time);
13045}
13046
13047double ha_mroonga::scan_time()
13048{
13049 MRN_DBUG_ENTER_METHOD();
13050 double time;
13051 if (share->wrapper_mode)
13052 {
13053 time = wrapper_scan_time();
13054 } else {
13055 time = storage_scan_time();
13056 }
13057 DBUG_RETURN(time);
13058}
13059
13060double ha_mroonga::wrapper_read_time(uint index, uint ranges, ha_rows rows)
13061{
13062 double res;
13063 MRN_DBUG_ENTER_METHOD();
13064 if (index < MAX_KEY) {
13065 KEY *key_info = &(table->key_info[index]);
13066 if (mrn_is_geo_key(key_info)) {
13067 res = handler::read_time(index, ranges, rows);
13068 DBUG_RETURN(res);
13069 }
13070 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13071 MRN_SET_WRAP_TABLE_KEY(this, table);
13072 res = wrap_handler->read_time(share->wrap_key_nr[index], ranges, rows);
13073 MRN_SET_BASE_SHARE_KEY(share, table->s);
13074 MRN_SET_BASE_TABLE_KEY(this, table);
13075 } else {
13076 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13077 MRN_SET_WRAP_TABLE_KEY(this, table);
13078 res = wrap_handler->read_time(index, ranges, rows);
13079 MRN_SET_BASE_SHARE_KEY(share, table->s);
13080 MRN_SET_BASE_TABLE_KEY(this, table);
13081 }
13082 DBUG_RETURN(res);
13083}
13084
13085double ha_mroonga::storage_read_time(uint index, uint ranges, ha_rows rows)
13086{
13087 MRN_DBUG_ENTER_METHOD();
13088 double time = handler::read_time(index, ranges, rows);
13089 DBUG_RETURN(time);
13090}
13091
13092double ha_mroonga::read_time(uint index, uint ranges, ha_rows rows)
13093{
13094 MRN_DBUG_ENTER_METHOD();
13095 double time;
13096 if (share->wrapper_mode)
13097 {
13098 time = wrapper_read_time(index, ranges, rows);
13099 } else {
13100 time = storage_read_time(index, ranges, rows);
13101 }
13102 DBUG_RETURN(time);
13103}
13104
13105#ifdef MRN_HANDLER_HAVE_KEYS_TO_USE_FOR_SCANNING
13106const key_map *ha_mroonga::wrapper_keys_to_use_for_scanning()
13107{
13108 const key_map *res;
13109 MRN_DBUG_ENTER_METHOD();
13110 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13111 MRN_SET_WRAP_TABLE_KEY(this, table);
13112 res = wrap_handler->keys_to_use_for_scanning();
13113 MRN_SET_BASE_SHARE_KEY(share, table->s);
13114 MRN_SET_BASE_TABLE_KEY(this, table);
13115 DBUG_RETURN(res);
13116}
13117
13118const key_map *ha_mroonga::storage_keys_to_use_for_scanning()
13119{
13120 MRN_DBUG_ENTER_METHOD();
13121 DBUG_RETURN(&key_map_full);
13122}
13123
13124const key_map *ha_mroonga::keys_to_use_for_scanning()
13125{
13126 MRN_DBUG_ENTER_METHOD();
13127 const key_map *key_map;
13128 if (share->wrapper_mode)
13129 {
13130 key_map = wrapper_keys_to_use_for_scanning();
13131 } else {
13132 key_map = storage_keys_to_use_for_scanning();
13133 }
13134 DBUG_RETURN(key_map);
13135}
13136#endif
13137
13138ha_rows ha_mroonga::wrapper_estimate_rows_upper_bound()
13139{
13140 ha_rows res;
13141 MRN_DBUG_ENTER_METHOD();
13142 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13143 MRN_SET_WRAP_TABLE_KEY(this, table);
13144 res = wrap_handler->estimate_rows_upper_bound();
13145 MRN_SET_BASE_SHARE_KEY(share, table->s);
13146 MRN_SET_BASE_TABLE_KEY(this, table);
13147 DBUG_RETURN(res);
13148}
13149
13150ha_rows ha_mroonga::storage_estimate_rows_upper_bound()
13151{
13152 MRN_DBUG_ENTER_METHOD();
13153 ha_rows rows = handler::estimate_rows_upper_bound();
13154 DBUG_RETURN(rows);
13155}
13156
13157ha_rows ha_mroonga::estimate_rows_upper_bound()
13158{
13159 MRN_DBUG_ENTER_METHOD();
13160 ha_rows rows;
13161 if (share->wrapper_mode)
13162 {
13163 rows = wrapper_estimate_rows_upper_bound();
13164 } else {
13165 rows = storage_estimate_rows_upper_bound();
13166 }
13167 DBUG_RETURN(rows);
13168}
13169
13170void ha_mroonga::wrapper_update_create_info(HA_CREATE_INFO* create_info)
13171{
13172 MRN_DBUG_ENTER_METHOD();
13173 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13174 MRN_SET_WRAP_TABLE_KEY(this, table);
13175 wrap_handler->update_create_info(create_info);
13176 MRN_SET_BASE_SHARE_KEY(share, table->s);
13177 MRN_SET_BASE_TABLE_KEY(this, table);
13178 DBUG_VOID_RETURN;
13179}
13180
13181void ha_mroonga::storage_update_create_info(HA_CREATE_INFO* create_info)
13182{
13183 MRN_DBUG_ENTER_METHOD();
13184 handler::update_create_info(create_info);
13185 if (!(create_info->used_fields & HA_CREATE_USED_AUTO)) {
13186 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
13187 if (!long_term_share->auto_inc_inited) {
13188 storage_info(HA_STATUS_AUTO);
13189 }
13190 create_info->auto_increment_value = long_term_share->auto_inc_value;
13191 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
13192 long_term_share->auto_inc_value));
13193 }
13194 DBUG_VOID_RETURN;
13195}
13196
13197void ha_mroonga::update_create_info(HA_CREATE_INFO* create_info)
13198{
13199 MRN_DBUG_ENTER_METHOD();
13200 if (!create_info->connect_string.str)
13201 {
13202 create_info->connect_string.str = table->s->connect_string.str;
13203 create_info->connect_string.length = table->s->connect_string.length;
13204 }
13205 if (share->wrapper_mode)
13206 wrapper_update_create_info(create_info);
13207 else
13208 storage_update_create_info(create_info);
13209 st_mrn_slot_data *slot_data = mrn_get_slot_data(ha_thd(), true);
13210 if (slot_data) {
13211 slot_data->alter_create_info = create_info;
13212 if (slot_data->alter_connect_string) {
13213 my_free(slot_data->alter_connect_string);
13214 slot_data->alter_connect_string = NULL;
13215 }
13216 if (create_info->connect_string.str) {
13217 slot_data->alter_connect_string =
13218 mrn_my_strndup(create_info->connect_string.str,
13219 create_info->connect_string.length,
13220 MYF(MY_WME));
13221 }
13222 if (slot_data->alter_comment) {
13223 my_free(slot_data->alter_comment);
13224 slot_data->alter_comment = NULL;
13225 }
13226 if (create_info->comment.str) {
13227 slot_data->alter_comment =
13228 mrn_my_strndup(create_info->comment.str,
13229 create_info->comment.length,
13230 MYF(MY_WME));
13231 }
13232 if (share && share->disable_keys) {
13233 slot_data->disable_keys_create_info = create_info;
13234 }
13235 }
13236 DBUG_VOID_RETURN;
13237}
13238
13239int ha_mroonga::wrapper_rename_table(const char *from, const char *to,
13240 MRN_SHARE *tmp_share,
13241 const char *from_table_name,
13242 const char *to_table_name)
13243{
13244 int error = 0;
13245 handler *hnd;
13246 MRN_DBUG_ENTER_METHOD();
13247
13248 hnd = get_new_handler(tmp_share->table_share,
13249 current_thd->mem_root,
13250 tmp_share->hton);
13251 if (!hnd)
13252 {
13253 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
13254 }
13255
13256 if ((error = hnd->ha_rename_table(from, to)))
13257 {
13258 delete hnd;
13259 DBUG_RETURN(error);
13260 }
13261
13262 error = wrapper_rename_index(from, to, tmp_share,
13263 from_table_name, to_table_name);
13264
13265 delete hnd;
13266 DBUG_RETURN(error);
13267}
13268
13269int ha_mroonga::wrapper_rename_index(const char *from, const char *to,
13270 MRN_SHARE *tmp_share,
13271 const char *from_table_name,
13272 const char *to_table_name)
13273{
13274 int error;
13275 grn_rc rc;
13276 MRN_DBUG_ENTER_METHOD();
13277 error = mrn_change_encoding(ctx, system_charset_info);
13278 if (error)
13279 DBUG_RETURN(error);
13280
13281 error = ensure_database_open(from);
13282 if (error)
13283 DBUG_RETURN(error);
13284
13285 TABLE_SHARE *tmp_table_share = tmp_share->table_share;
13286
13287 uint i;
13288 for (i = 0; i < tmp_table_share->keys; i++) {
13289 const char *mysql_index_name = tmp_table_share->key_info[i].name.str;
13290 mrn::IndexTableName from_index_table_name(from_table_name, mysql_index_name);
13291 mrn::IndexTableName to_index_table_name(to_table_name, mysql_index_name);
13292 grn_obj *index_table;
13293 index_table = grn_ctx_get(ctx,
13294 from_index_table_name.c_str(),
13295 from_index_table_name.length());
13296 if (!index_table) {
13297 index_table = grn_ctx_get(ctx,
13298 from_index_table_name.old_c_str(),
13299 from_index_table_name.old_length());
13300 }
13301 if (index_table) {
13302 rc = grn_table_rename(ctx, index_table,
13303 to_index_table_name.c_str(),
13304 to_index_table_name.length());
13305 if (rc != GRN_SUCCESS) {
13306 error = ER_CANT_OPEN_FILE;
13307 my_message(error, ctx->errbuf, MYF(0));
13308 DBUG_RETURN(error);
13309 }
13310 }
13311 }
13312
13313 grn_obj *table = grn_ctx_get(ctx, from_table_name, strlen(from_table_name));
13314 if (ctx->rc != GRN_SUCCESS) {
13315 error = ER_CANT_OPEN_FILE;
13316 my_message(error, ctx->errbuf, MYF(0));
13317 DBUG_RETURN(error);
13318 }
13319 rc = grn_table_rename(ctx, table, to_table_name,
13320 strlen(to_table_name));
13321 if (rc != GRN_SUCCESS) {
13322 error = ER_CANT_OPEN_FILE;
13323 my_message(error, ctx->errbuf, MYF(0));
13324 DBUG_RETURN(error);
13325 }
13326 DBUG_RETURN(0);
13327}
13328
13329int ha_mroonga::storage_rename_table(const char *from, const char *to,
13330 MRN_SHARE *tmp_share,
13331 const char *from_table_name,
13332 const char *to_table_name)
13333{
13334 int error;
13335 grn_rc rc;
13336 TABLE_SHARE *tmp_table_share = tmp_share->table_share;
13337 MRN_LONG_TERM_SHARE *from_long_term_share = tmp_share->long_term_share,
13338 *to_long_term_share;
13339 MRN_DBUG_ENTER_METHOD();
13340 error = mrn_change_encoding(ctx, system_charset_info);
13341 if (error)
13342 DBUG_RETURN(error);
13343
13344 error = ensure_database_open(from);
13345 if (error)
13346 DBUG_RETURN(error);
13347
13348 if (!(to_long_term_share = mrn_get_long_term_share(to, strlen(to), &error)))
13349 DBUG_RETURN(error);
13350 to_long_term_share->auto_inc_value = from_long_term_share->auto_inc_value;
13351 DBUG_PRINT("info", ("mroonga: to_auto_inc_value=%llu",
13352 to_long_term_share->auto_inc_value));
13353 to_long_term_share->auto_inc_inited = from_long_term_share->auto_inc_inited;
13354
13355 uint i;
13356 for (i = 0; i < tmp_table_share->keys; i++) {
13357 const char *mysql_index_name = tmp_table_share->key_info[i].name.str;
13358 mrn::IndexTableName from_index_table_name(from_table_name,
13359 mysql_index_name);
13360 mrn::IndexTableName to_index_table_name(to_table_name,
13361 mysql_index_name);
13362 grn_obj *index_table;
13363 index_table = grn_ctx_get(ctx,
13364 from_index_table_name.c_str(),
13365 from_index_table_name.length());
13366 if (!index_table) {
13367 index_table = grn_ctx_get(ctx,
13368 from_index_table_name.old_c_str(),
13369 from_index_table_name.old_length());
13370 }
13371 if (index_table) {
13372 rc = grn_table_rename(ctx, index_table,
13373 to_index_table_name.c_str(),
13374 to_index_table_name.length());
13375 if (rc != GRN_SUCCESS) {
13376 error = ER_CANT_OPEN_FILE;
13377 my_message(error, ctx->errbuf, MYF(0));
13378 goto error_end;
13379 }
13380 }
13381 }
13382#ifdef MRN_SUPPORT_FOREIGN_KEYS
13383 error = storage_rename_foreign_key(tmp_share, from_table_name, to_table_name);
13384 if (error) {
13385 goto error_end;
13386 }
13387#endif
13388 {
13389 grn_obj *table_obj = grn_ctx_get(ctx, from_table_name, strlen(from_table_name));
13390 if (ctx->rc != GRN_SUCCESS) {
13391 error = ER_CANT_OPEN_FILE;
13392 my_message(error, ctx->errbuf, MYF(0));
13393 goto error_end;
13394 }
13395 rc = grn_table_rename(ctx, table_obj, to_table_name,
13396 strlen(to_table_name));
13397 if (rc != GRN_SUCCESS) {
13398 error = ER_CANT_OPEN_FILE;
13399 my_message(error, ctx->errbuf, MYF(0));
13400 goto error_end;
13401 }
13402 }
13403 DBUG_RETURN(0);
13404
13405error_end:
13406 mrn_free_long_term_share(to_long_term_share);
13407 DBUG_RETURN(error);
13408}
13409
13410#ifdef MRN_SUPPORT_FOREIGN_KEYS
13411int ha_mroonga::storage_rename_foreign_key(MRN_SHARE *tmp_share,
13412 const char *from_table_name,
13413 const char *to_table_name)
13414{
13415 int error;
13416 uint i;
13417 grn_obj *column, *ref_column;
13418 grn_rc rc;
13419 TABLE_SHARE *tmp_table_share = tmp_share->table_share;
13420 uint n_columns = tmp_table_share->fields;
13421 MRN_DBUG_ENTER_METHOD();
13422 for (i = 0; i < n_columns; ++i) {
13423 Field *field = tmp_table_share->field[i];
13424
13425 if (!is_foreign_key_field(from_table_name, field->field_name.str)) {
13426 continue;
13427 }
13428
13429 grn_obj *grn_from_table = grn_ctx_get(ctx, from_table_name, -1);
13430 mrn::ColumnName column_name(field->field_name);
13431 column = grn_obj_column(ctx,
13432 grn_from_table,
13433 column_name.c_str(),
13434 column_name.length());
13435 if (!column) {
13436 continue;
13437 }
13438 grn_id ref_table_id = grn_obj_get_range(ctx, column);
13439 grn_obj *ref_table = grn_ctx_at(ctx, ref_table_id);
13440 mrn::IndexColumnName from_index_column_name(from_table_name,
13441 column_name.c_str());
13442 ref_column = grn_obj_column(ctx, ref_table,
13443 from_index_column_name.c_str(),
13444 from_index_column_name.length());
13445 if (!ref_column) {
13446 continue;
13447 }
13448 mrn::IndexColumnName to_index_column_name(to_table_name,
13449 column_name.c_str());
13450 rc = grn_column_rename(ctx, ref_column,
13451 to_index_column_name.c_str(),
13452 to_index_column_name.length());
13453 if (rc != GRN_SUCCESS) {
13454 error = ER_CANT_OPEN_FILE;
13455 my_message(error, ctx->errbuf, MYF(0));
13456 DBUG_RETURN(error);
13457 }
13458 }
13459 DBUG_RETURN(0);
13460}
13461#endif
13462
13463int ha_mroonga::rename_table(const char *from, const char *to)
13464{
13465 int error = 0;
13466 TABLE_LIST table_list;
13467 TABLE_SHARE *tmp_table_share;
13468 TABLE tmp_table;
13469 MRN_SHARE *tmp_share;
13470 MRN_DBUG_ENTER_METHOD();
13471 mrn::PathMapper to_mapper(to);
13472 mrn::PathMapper from_mapper(from);
13473 if (strcmp(from_mapper.db_name(), to_mapper.db_name()))
13474 DBUG_RETURN(HA_ERR_WRONG_COMMAND);
13475
13476 LEX_CSTRING db_name= { from_mapper.db_name(), strlen(from_mapper.db_name()) };
13477 LEX_CSTRING table_name= { from_mapper.mysql_table_name(),
13478 strlen(from_mapper.mysql_table_name()) };
13479 table_list.init_one_table(&db_name, &table_name, 0,TL_WRITE);
13480 mrn_open_mutex_lock(NULL);
13481 tmp_table_share = mrn_create_tmp_table_share(&table_list, from, &error);
13482 mrn_open_mutex_unlock(NULL);
13483 if (!tmp_table_share) {
13484 DBUG_RETURN(error);
13485 }
13486 tmp_table.s = tmp_table_share;
13487#ifdef WITH_PARTITION_STORAGE_ENGINE
13488 tmp_table.part_info = NULL;
13489#endif
13490 if (!(tmp_share = mrn_get_share(from, &tmp_table, &error)))
13491 {
13492 mrn_open_mutex_lock(NULL);
13493 mrn_free_tmp_table_share(tmp_table_share);
13494 mrn_open_mutex_unlock(NULL);
13495 DBUG_RETURN(error);
13496 }
13497
13498 if (tmp_share->wrapper_mode)
13499 {
13500 error = wrapper_rename_table(from, to, tmp_share,
13501 from_mapper.table_name(),
13502 to_mapper.table_name());
13503 } else {
13504 error = storage_rename_table(from, to, tmp_share,
13505 from_mapper.table_name(),
13506 to_mapper.table_name());
13507 }
13508
13509 if (!error && to_mapper.table_name()[0] == '#') {
13510 error = add_wrap_hton(to, tmp_share->hton);
13511 } else if (error && from_mapper.table_name()[0] == '#') {
13512 add_wrap_hton(from, tmp_share->hton);
13513 }
13514 if (!error) {
13515 mrn_free_long_term_share(tmp_share->long_term_share);
13516 tmp_share->long_term_share = NULL;
13517 }
13518 mrn_free_share(tmp_share);
13519 mrn_open_mutex_lock(NULL);
13520 mrn_free_tmp_table_share(tmp_table_share);
13521 mrn_open_mutex_unlock(NULL);
13522
13523 DBUG_RETURN(error);
13524}
13525
13526bool ha_mroonga::wrapper_is_crashed() const
13527{
13528 bool res;
13529 MRN_DBUG_ENTER_METHOD();
13530 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13531 MRN_SET_WRAP_TABLE_KEY(this, table);
13532 res = wrap_handler->is_crashed();
13533 MRN_SET_BASE_SHARE_KEY(share, table->s);
13534 MRN_SET_BASE_TABLE_KEY(this, table);
13535 DBUG_RETURN(res);
13536}
13537
13538bool ha_mroonga::storage_is_crashed() const
13539{
13540 MRN_DBUG_ENTER_METHOD();
13541 mrn::DatabaseRepairer repairer(ctx, ha_thd());
13542 bool crashed = repairer.is_crashed();
13543 DBUG_RETURN(crashed);
13544}
13545
13546bool ha_mroonga::is_crashed() const
13547{
13548 MRN_DBUG_ENTER_METHOD();
13549 bool crashed;
13550 if (share->wrapper_mode)
13551 {
13552 crashed = wrapper_is_crashed();
13553 } else {
13554 crashed = storage_is_crashed();
13555 }
13556 DBUG_RETURN(crashed);
13557}
13558
13559bool ha_mroonga::wrapper_auto_repair(int error) const
13560{
13561 bool repaired;
13562 MRN_DBUG_ENTER_METHOD();
13563 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13564 MRN_SET_WRAP_TABLE_KEY(this, table);
13565#ifdef MRN_HANDLER_AUTO_REPAIR_HAVE_ERROR
13566 repaired = wrap_handler->auto_repair(error);
13567#else
13568 repaired = wrap_handler->auto_repair();
13569#endif
13570 MRN_SET_BASE_SHARE_KEY(share, table->s);
13571 MRN_SET_BASE_TABLE_KEY(this, table);
13572 DBUG_RETURN(repaired);
13573}
13574
13575bool ha_mroonga::storage_auto_repair(int error) const
13576{
13577 MRN_DBUG_ENTER_METHOD();
13578 bool repaired;
13579#ifdef MRN_HANDLER_AUTO_REPAIR_HAVE_ERROR
13580 repaired = handler::auto_repair(error);
13581#else
13582 repaired = handler::auto_repair();
13583#endif
13584 DBUG_RETURN(repaired);
13585}
13586
13587bool ha_mroonga::auto_repair(int error) const
13588{
13589 MRN_DBUG_ENTER_METHOD();
13590 bool repaired;
13591 // TODO: We should consider about creating share for error =
13592 // ER_CANT_OPEN_FILE. The following code just ignores the error.
13593 if (share && share->wrapper_mode)
13594 {
13595 repaired = wrapper_auto_repair(error);
13596 } else {
13597 repaired = storage_auto_repair(error);
13598 }
13599 DBUG_RETURN(repaired);
13600}
13601
13602bool ha_mroonga::auto_repair() const
13603{
13604 MRN_DBUG_ENTER_METHOD();
13605 bool repaired = auto_repair(HA_ERR_CRASHED_ON_USAGE);
13606 DBUG_RETURN(repaired);
13607}
13608
13609int ha_mroonga::generic_disable_index(int i, KEY *key_info)
13610{
13611 MRN_DBUG_ENTER_METHOD();
13612
13613 int error = 0;
13614 if (share->index_table[i]) {
13615 char index_column_name[GRN_TABLE_MAX_KEY_SIZE];
13616 snprintf(index_column_name, GRN_TABLE_MAX_KEY_SIZE - 1,
13617 "%s.%s", share->index_table[i], key_info[i].name.str);
13618 grn_obj *index_column = grn_ctx_get(ctx,
13619 index_column_name,
13620 strlen(index_column_name));
13621 if (index_column) {
13622 grn_obj_remove(ctx, index_column);
13623 }
13624 } else {
13625 mrn::PathMapper mapper(share->table_name);
13626 mrn::IndexTableName index_table_name(mapper.table_name(),
13627 key_info[i].name.str);
13628 grn_obj *index_table = grn_ctx_get(ctx,
13629 index_table_name.c_str(),
13630 index_table_name.length());
13631 if (!index_table) {
13632 index_table = grn_ctx_get(ctx,
13633 index_table_name.old_c_str(),
13634 index_table_name.old_length());
13635 }
13636 if (index_table) {
13637 grn_obj_remove(ctx, index_table);
13638 }
13639 }
13640 if (ctx->rc == GRN_SUCCESS) {
13641 grn_index_tables[i] = NULL;
13642 grn_index_columns[i] = NULL;
13643 } else {
13644 // TODO: Implement ctx->rc to error converter and use it.
13645 error = ER_ERROR_ON_WRITE;
13646 my_message(error, ctx->errbuf, MYF(0));
13647 }
13648
13649 DBUG_RETURN(error);
13650}
13651
13652int ha_mroonga::wrapper_disable_indexes_mroonga(uint mode)
13653{
13654 int error = 0;
13655 MRN_DBUG_ENTER_METHOD();
13656 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
13657 uint i;
13658 for (i = 0; i < table_share->keys; i++) {
13659 if (i == table->s->primary_key) {
13660 continue;
13661 }
13662 if (share->wrap_key_nr[i] < MAX_KEY) {
13663 continue;
13664 }
13665 if (!grn_index_tables[i]) {
13666 DBUG_PRINT("info", ("mroonga: keys are disabled already %u", i));
13667 DBUG_RETURN(0);
13668 }
13669 }
13670 KEY *key_info = table_share->key_info;
13671 for (i = 0; i < table_share->keys; i++) {
13672 if (!(key_info[i].flags & HA_FULLTEXT) &&
13673 !mrn_is_geo_key(&key_info[i])) {
13674 continue;
13675 }
13676
13677 int sub_error = generic_disable_index(i, key_info);
13678 if (error != 0 && sub_error != 0) {
13679 error = sub_error;
13680 }
13681 }
13682 } else {
13683 error = HA_ERR_WRONG_COMMAND;
13684 }
13685 DBUG_RETURN(error);
13686}
13687
13688int ha_mroonga::wrapper_disable_indexes(uint mode)
13689{
13690 int error = 0;
13691 MRN_DBUG_ENTER_METHOD();
13692 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13693 MRN_SET_WRAP_TABLE_KEY(this, table);
13694 error = wrap_handler->ha_disable_indexes(mode);
13695 MRN_SET_BASE_SHARE_KEY(share, table->s);
13696 MRN_SET_BASE_TABLE_KEY(this, table);
13697 if (error == HA_ERR_WRONG_COMMAND) {
13698 error = 0;
13699 }
13700 if (!error) {
13701 error = wrapper_disable_indexes_mroonga(mode);
13702 }
13703 DBUG_RETURN(error);
13704}
13705
13706int ha_mroonga::storage_disable_indexes(uint mode)
13707{
13708 int error = 0;
13709 MRN_DBUG_ENTER_METHOD();
13710 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
13711 uint i;
13712 for (i = 0; i < table_share->keys; i++) {
13713 if (i == table->s->primary_key) {
13714 continue;
13715 }
13716 if (!grn_index_tables[i]) {
13717 DBUG_PRINT("info", ("mroonga: keys are disabled already %u", i));
13718 DBUG_RETURN(0);
13719 }
13720 }
13721 KEY *key_info = table_share->key_info;
13722 for (i = 0; i < table_share->keys; i++) {
13723 if (i == table->s->primary_key) {
13724 continue;
13725 }
13726 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE &&
13727 (key_info[i].flags & HA_NOSAME)) {
13728 continue;
13729 }
13730
13731 int sub_error = generic_disable_index(i, key_info);
13732 if (error != 0 && sub_error != 0) {
13733 error = sub_error;
13734 }
13735 }
13736 } else {
13737 DBUG_RETURN(HA_ERR_WRONG_COMMAND);
13738 }
13739 DBUG_RETURN(error);
13740}
13741
13742int ha_mroonga::disable_indexes(uint mode)
13743{
13744 int error = 0;
13745 MRN_DBUG_ENTER_METHOD();
13746 if (share->wrapper_mode)
13747 {
13748 error = wrapper_disable_indexes(mode);
13749 } else {
13750 error = storage_disable_indexes(mode);
13751 }
13752 DBUG_RETURN(error);
13753}
13754
13755int ha_mroonga::wrapper_enable_indexes_mroonga(uint mode)
13756{
13757 int error = 0;
13758 MRN_DBUG_ENTER_METHOD();
13759 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
13760 uint i, j;
13761 for (i = 0; i < table_share->keys; i++) {
13762 if (i == table->s->primary_key) {
13763 continue;
13764 }
13765 if (share->wrap_key_nr[i] < MAX_KEY) {
13766 continue;
13767 }
13768 if (!grn_index_columns[i]) {
13769 break;
13770 }
13771 }
13772 if (i == table_share->keys) {
13773 DBUG_PRINT("info", ("mroonga: keys are enabled already"));
13774 DBUG_RETURN(0);
13775 }
13776 KEY *p_key_info = &table->key_info[table_share->primary_key];
13777 KEY *key_info = table_share->key_info;
13778 uint n_keys = table_share->keys;
13779 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys);
13780 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, n_keys);
13781 bitmap_clear_all(table->read_set);
13782 mrn_set_bitmap_by_key(table->read_set, p_key_info);
13783 mrn::PathMapper mapper(share->table_name);
13784 for (i = 0, j = 0; i < n_keys; i++) {
13785 if (!(key_info[i].flags & HA_FULLTEXT) &&
13786 !mrn_is_geo_key(&key_info[i])) {
13787 j++;
13788 continue;
13789 }
13790
13791 if ((error = mrn_add_index_param(share, &key_info[i], i)))
13792 {
13793 break;
13794 }
13795 index_tables[i] = NULL;
13796 index_columns[i] = NULL;
13797 if (!grn_index_columns[i]) {
13798 if (
13799 (key_info[i].flags & HA_FULLTEXT) &&
13800 (error = wrapper_create_index_fulltext(mapper.table_name(),
13801 i, &key_info[i],
13802 index_tables, index_columns,
13803 share))
13804 ) {
13805 break;
13806 } else if (
13807 mrn_is_geo_key(&key_info[i]) &&
13808 (error = wrapper_create_index_geo(mapper.table_name(),
13809 i, &key_info[i],
13810 index_tables, index_columns,
13811 share))
13812 ) {
13813 break;
13814 }
13815 grn_index_columns[i] = index_columns[i];
13816 }
13817 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
13818 }
13819 if (!error && i > j)
13820 {
13821 error = wrapper_fill_indexes(ha_thd(), table->key_info, index_columns,
13822 n_keys);
13823 }
13824 bitmap_set_all(table->read_set);
13825 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
13826 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
13827 } else {
13828 error = HA_ERR_WRONG_COMMAND;
13829 }
13830 DBUG_RETURN(error);
13831}
13832
13833int ha_mroonga::wrapper_enable_indexes(uint mode)
13834{
13835 int error = 0;
13836 MRN_DBUG_ENTER_METHOD();
13837
13838 int mroonga_error = wrapper_enable_indexes_mroonga(mode);
13839
13840 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13841 MRN_SET_WRAP_TABLE_KEY(this, table);
13842 error = wrap_handler->ha_enable_indexes(mode);
13843 MRN_SET_BASE_SHARE_KEY(share, table->s);
13844 MRN_SET_BASE_TABLE_KEY(this, table);
13845 if (error == HA_ERR_WRONG_COMMAND) {
13846 error = mroonga_error;
13847 }
13848 DBUG_RETURN(error);
13849}
13850
13851int ha_mroonga::storage_enable_indexes(uint mode)
13852{
13853 int error = 0;
13854 uint n_keys = table_share->keys;
13855 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys);
13856 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, n_keys);
13857 bool have_multiple_column_index = false;
13858 bool skip_unique_key = (mode == HA_KEY_SWITCH_NONUNIQ_SAVE);
13859 MRN_DBUG_ENTER_METHOD();
13860 if (mode == HA_KEY_SWITCH_NONUNIQ_SAVE || mode == HA_KEY_SWITCH_ALL) {
13861 uint i;
13862 for (i = 0; i < table_share->keys; i++) {
13863 if (i == table->s->primary_key) {
13864 continue;
13865 }
13866 if (!grn_index_columns[i]) {
13867 break;
13868 }
13869 }
13870 if (i == table_share->keys) {
13871 DBUG_PRINT("info", ("mroonga: keys are enabled already"));
13872 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
13873 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
13874 DBUG_RETURN(0);
13875 }
13876 KEY *key_info = table->key_info;
13877 bitmap_clear_all(table->read_set);
13878 mrn::PathMapper mapper(share->table_name);
13879 for (i = 0; i < n_keys; i++) {
13880 if (i == table->s->primary_key) {
13881 continue;
13882 }
13883 if (skip_unique_key && (key_info[i].flags & HA_NOSAME)) {
13884 continue;
13885 }
13886
13887 if ((error = mrn_add_index_param(share, &key_info[i], i)))
13888 {
13889 break;
13890 }
13891 index_tables[i] = NULL;
13892 if (!grn_index_columns[i]) {
13893 if ((error = storage_create_index(table, mapper.table_name(), grn_table,
13894 share, &key_info[i], index_tables,
13895 index_columns, i)))
13896 {
13897 break;
13898 }
13899 if (
13900 KEY_N_KEY_PARTS(&(key_info[i])) != 1 &&
13901 !(key_info[i].flags & HA_FULLTEXT)
13902 ) {
13903 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
13904 have_multiple_column_index = true;
13905 }
13906 grn_index_tables[i] = index_tables[i];
13907 grn_index_columns[i] = index_columns[i];
13908 } else {
13909 index_columns[i] = NULL;
13910 }
13911 }
13912 if (!error && have_multiple_column_index)
13913 {
13914 error = storage_add_index_multiple_columns(key_info, n_keys,
13915 index_tables,
13916 index_columns,
13917 skip_unique_key);
13918 }
13919 bitmap_set_all(table->read_set);
13920 } else {
13921 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
13922 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
13923 DBUG_RETURN(HA_ERR_WRONG_COMMAND);
13924 }
13925 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
13926 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
13927 DBUG_RETURN(error);
13928}
13929
13930int ha_mroonga::enable_indexes(uint mode)
13931{
13932 int error = 0;
13933 MRN_DBUG_ENTER_METHOD();
13934 share->disable_keys = false;
13935 if (share->wrapper_mode)
13936 {
13937 error = wrapper_enable_indexes(mode);
13938 } else {
13939 error = storage_enable_indexes(mode);
13940 }
13941 DBUG_RETURN(error);
13942}
13943
13944int ha_mroonga::wrapper_check(THD* thd, HA_CHECK_OPT* check_opt)
13945{
13946 int error = 0;
13947 MRN_DBUG_ENTER_METHOD();
13948 MRN_SET_WRAP_SHARE_KEY(share, table->s);
13949 MRN_SET_WRAP_TABLE_KEY(this, table);
13950 error = wrap_handler->ha_check(thd, check_opt);
13951 MRN_SET_BASE_SHARE_KEY(share, table->s);
13952 MRN_SET_BASE_TABLE_KEY(this, table);
13953 DBUG_RETURN(error);
13954}
13955
13956int ha_mroonga::storage_check(THD* thd, HA_CHECK_OPT* check_opt)
13957{
13958 MRN_DBUG_ENTER_METHOD();
13959 mrn::DatabaseRepairer repairer(ctx, thd);
13960 if (repairer.is_corrupt()) {
13961 DBUG_RETURN(HA_ADMIN_CORRUPT);
13962 } else {
13963 DBUG_RETURN(HA_ADMIN_OK);
13964 }
13965}
13966
13967int ha_mroonga::check(THD* thd, HA_CHECK_OPT* check_opt)
13968{
13969 MRN_DBUG_ENTER_METHOD();
13970 int error = 0;
13971 if (share->wrapper_mode)
13972 {
13973 error = wrapper_check(thd, check_opt);
13974 } else {
13975 error = storage_check(thd, check_opt);
13976 }
13977 DBUG_RETURN(error);
13978}
13979
13980int ha_mroonga::wrapper_fill_indexes(THD *thd, KEY *key_info,
13981 grn_obj **index_columns, uint n_keys)
13982{
13983 int error = 0;
13984 KEY *p_key_info = &table->key_info[table_share->primary_key];
13985 KEY *tmp_key_info;
13986#ifdef MRN_NEED_M_LOCK_TYPE_CHECK_FOR_WRAPPER_EXTERNAL_LOCK
13987 int wrapper_lock_type_backup = wrap_handler->get_lock_type();
13988#endif
13989 MRN_DBUG_ENTER_METHOD();
13990 DBUG_PRINT("info", ("mroonga: n_keys=%u", n_keys));
13991
13992 grn_bool need_lock = true;
13993 if (mrn_lock_type != F_UNLCK) {
13994 need_lock = false;
13995 }
13996#ifdef MRN_NEED_M_LOCK_TYPE_CHECK_FOR_WRAPPER_EXTERNAL_LOCK
13997 if (wrapper_lock_type_backup != F_UNLCK) {
13998 need_lock = false;
13999 }
14000#endif
14001 if (need_lock) {
14002 error = wrapper_external_lock(thd, F_WRLCK);
14003 }
14004 if (!error) {
14005 if (
14006 !(error = wrapper_start_stmt(thd, thr_lock_data.type)) &&
14007 !(error = wrapper_rnd_init(true))
14008 ) {
14009 grn_obj key;
14010 GRN_TEXT_INIT(&key, 0);
14011 grn_bulk_space(ctx, &key, p_key_info->key_length);
14012 while (!(error = wrapper_rnd_next(table->record[0])))
14013 {
14014 key_copy((uchar *)(GRN_TEXT_VALUE(&key)), table->record[0],
14015 p_key_info, p_key_info->key_length);
14016 int added;
14017 grn_id record_id;
14018 mrn_change_encoding(ctx, NULL);
14019 record_id = grn_table_add(ctx, grn_table,
14020 GRN_TEXT_VALUE(&key), p_key_info->key_length,
14021 &added);
14022 if (record_id == GRN_ID_NIL)
14023 {
14024 char error_message[MRN_MESSAGE_BUFFER_SIZE];
14025 snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE,
14026 "failed to add a new record into groonga: key=<%.*s>",
14027 (int) p_key_info->key_length, GRN_TEXT_VALUE(&key));
14028 error = ER_ERROR_ON_WRITE;
14029 my_message(error, error_message, MYF(0));
14030 }
14031 if (error)
14032 break;
14033
14034 uint k;
14035 for (k = 0; k < n_keys; k++) {
14036 tmp_key_info = &key_info[k];
14037 if (!(tmp_key_info->flags & HA_FULLTEXT) &&
14038 !mrn_is_geo_key(tmp_key_info)) {
14039 continue;
14040 }
14041 if (!index_columns[k]) {
14042 continue;
14043 }
14044 DBUG_PRINT("info", ("mroonga: key_num=%u", k));
14045
14046 uint l;
14047 for (l = 0; l < KEY_N_KEY_PARTS(tmp_key_info); l++) {
14048 Field *field = tmp_key_info->key_part[l].field;
14049
14050 if (field->is_null())
14051 continue;
14052 error = mrn_change_encoding(ctx, field->charset());
14053 if (error)
14054 break;
14055
14056 error = generic_store_bulk(field, &new_value_buffer);
14057 if (error) {
14058 my_message(error,
14059 "mroonga: wrapper: "
14060 "failed to get new value for updating index.",
14061 MYF(0));
14062 break;
14063 }
14064
14065 grn_obj *index_column = index_columns[k];
14066 grn_rc rc;
14067 rc = grn_column_index_update(ctx, index_column, record_id, l + 1,
14068 NULL, &new_value_buffer);
14069 grn_obj_unlink(ctx, index_column);
14070 if (rc) {
14071 error = ER_ERROR_ON_WRITE;
14072 my_message(error, ctx->errbuf, MYF(0));
14073 break;
14074 }
14075 }
14076 if (error)
14077 break;
14078 }
14079 if (error)
14080 break;
14081 }
14082 grn_obj_unlink(ctx, &key);
14083 if (error != HA_ERR_END_OF_FILE)
14084 wrapper_rnd_end();
14085 else
14086 error = wrapper_rnd_end();
14087 }
14088 if (need_lock) {
14089 wrapper_external_lock(thd, F_UNLCK);
14090 }
14091 }
14092 DBUG_RETURN(error);
14093}
14094
14095int ha_mroonga::wrapper_recreate_indexes(THD *thd)
14096{
14097 int error;
14098 uint i, n_keys = table_share->keys;
14099 KEY *p_key_info = &table->key_info[table_share->primary_key];
14100 KEY *key_info = table->key_info;
14101 MRN_DBUG_ENTER_METHOD();
14102 mrn::PathMapper mapper(table_share->normalized_path.str);
14103 bitmap_clear_all(table->read_set);
14104 clear_indexes();
14105 remove_grn_obj_force(mapper.table_name());
14106 grn_table = NULL;
14107 mrn_set_bitmap_by_key(table->read_set, p_key_info);
14108 for (i = 0; i < n_keys; i++) {
14109 if (!(key_info[i].flags & HA_FULLTEXT) && !mrn_is_geo_key(&key_info[i])) {
14110 continue;
14111 }
14112 mrn::IndexTableName index_table_name(mapper.table_name(),
14113 table_share->key_info[i].name.str);
14114 char index_column_full_name[MRN_MAX_PATH_SIZE];
14115 snprintf(index_column_full_name, MRN_MAX_PATH_SIZE,
14116 "%s.%s", index_table_name.c_str(), INDEX_COLUMN_NAME);
14117 remove_grn_obj_force(index_column_full_name);
14118 remove_grn_obj_force(index_table_name.c_str());
14119
14120 char index_column_full_old_name[MRN_MAX_PATH_SIZE];
14121 snprintf(index_column_full_old_name, MRN_MAX_PATH_SIZE,
14122 "%s.%s", index_table_name.old_c_str(), INDEX_COLUMN_NAME);
14123 remove_grn_obj_force(index_column_full_old_name);
14124 remove_grn_obj_force(index_table_name.old_c_str());
14125
14126 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
14127 }
14128 error = wrapper_create_index(table_share->normalized_path.str, table, share);
14129 if (error)
14130 DBUG_RETURN(error);
14131 error = wrapper_open_indexes(table_share->normalized_path.str);
14132 if (error)
14133 DBUG_RETURN(error);
14134 error = wrapper_fill_indexes(thd, key_info, grn_index_columns, n_keys);
14135 bitmap_set_all(table->read_set);
14136 DBUG_RETURN(error);
14137}
14138
14139int ha_mroonga::storage_recreate_indexes(THD *thd)
14140{
14141 MRN_DBUG_ENTER_METHOD();
14142
14143 if (share->disable_keys)
14144 DBUG_RETURN(HA_ADMIN_OK);
14145
14146 clear_indexes();
14147
14148 int n_columns = table->s->fields;
14149 for (int i = 0; i < n_columns; i++) {
14150 grn_obj *column = grn_columns[i];
14151
14152 if (!column)
14153 continue;
14154
14155 int n_hooks = grn_obj_get_nhooks(ctx, column, GRN_HOOK_SET);
14156 for (int j = 0; j < n_hooks; j++) {
14157 grn_obj_delete_hook(ctx, column, GRN_HOOK_SET, j);
14158 }
14159 }
14160
14161 uint n_keys = table_share->keys;
14162 mrn::PathMapper mapper(table_share->normalized_path.str);
14163 for (uint i = 0; i < n_keys; i++) {
14164 if (share->index_table && share->index_table[i])
14165 continue;
14166
14167 if (i == table_share->primary_key)
14168 continue;
14169
14170 mrn::IndexTableName index_table_name(mapper.table_name(),
14171 table_share->key_info[i].name.str);
14172 char index_column_full_name[MRN_MAX_PATH_SIZE];
14173 snprintf(index_column_full_name, MRN_MAX_PATH_SIZE,
14174 "%s.%s", index_table_name.c_str(), INDEX_COLUMN_NAME);
14175 remove_grn_obj_force(index_column_full_name);
14176 remove_grn_obj_force(index_table_name.c_str());
14177
14178 char index_column_full_old_name[MRN_MAX_PATH_SIZE];
14179 snprintf(index_column_full_old_name, MRN_MAX_PATH_SIZE,
14180 "%s.%s", index_table_name.old_c_str(), INDEX_COLUMN_NAME);
14181 remove_grn_obj_force(index_column_full_old_name);
14182 remove_grn_obj_force(index_table_name.old_c_str());
14183 }
14184
14185 int error;
14186 error = storage_create_indexes(table, mapper.table_name(), grn_table, share);
14187 if (error)
14188 DBUG_RETURN(HA_ADMIN_FAILED);
14189
14190 error = storage_open_indexes(table_share->normalized_path.str);
14191 if (error)
14192 DBUG_RETURN(HA_ADMIN_FAILED);
14193
14194 DBUG_RETURN(HA_ADMIN_OK);
14195}
14196
14197int ha_mroonga::wrapper_repair(THD* thd, HA_CHECK_OPT* check_opt)
14198{
14199 int error;
14200 MRN_DBUG_ENTER_METHOD();
14201 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14202 MRN_SET_WRAP_TABLE_KEY(this, table);
14203 error = wrap_handler->ha_repair(thd, check_opt);
14204 MRN_SET_BASE_SHARE_KEY(share, table->s);
14205 MRN_SET_BASE_TABLE_KEY(this, table);
14206 if (error && error != HA_ADMIN_NOT_IMPLEMENTED)
14207 DBUG_RETURN(error);
14208 error = wrapper_recreate_indexes(thd);
14209 DBUG_RETURN(error);
14210}
14211
14212int ha_mroonga::storage_repair(THD* thd, HA_CHECK_OPT* check_opt)
14213{
14214 MRN_DBUG_ENTER_METHOD();
14215 int error = storage_recreate_indexes(thd);
14216 DBUG_RETURN(error);
14217}
14218
14219int ha_mroonga::repair(THD* thd, HA_CHECK_OPT* check_opt)
14220{
14221 MRN_DBUG_ENTER_METHOD();
14222 int error = 0;
14223 share->disable_keys = false;
14224 if (share->wrapper_mode)
14225 {
14226 error = wrapper_repair(thd, check_opt);
14227 } else {
14228 error = storage_repair(thd, check_opt);
14229 }
14230 DBUG_RETURN(error);
14231}
14232
14233bool ha_mroonga::wrapper_check_and_repair(THD *thd)
14234{
14235 bool is_error_or_not_supported;
14236 MRN_DBUG_ENTER_METHOD();
14237 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14238 MRN_SET_WRAP_TABLE_KEY(this, table);
14239 is_error_or_not_supported = wrap_handler->ha_check_and_repair(thd);
14240 MRN_SET_BASE_SHARE_KEY(share, table->s);
14241 MRN_SET_BASE_TABLE_KEY(this, table);
14242 DBUG_RETURN(is_error_or_not_supported);
14243}
14244
14245bool ha_mroonga::storage_check_and_repair(THD *thd)
14246{
14247 MRN_DBUG_ENTER_METHOD();
14248 bool is_error = false;
14249 mrn::DatabaseRepairer repairer(ctx, thd);
14250 is_error = !repairer.repair();
14251 DBUG_RETURN(is_error);
14252}
14253
14254bool ha_mroonga::check_and_repair(THD *thd)
14255{
14256 MRN_DBUG_ENTER_METHOD();
14257 bool is_error_or_not_supported;
14258 if (share->wrapper_mode)
14259 {
14260 is_error_or_not_supported = wrapper_check_and_repair(thd);
14261 } else {
14262 is_error_or_not_supported = storage_check_and_repair(thd);
14263 }
14264 DBUG_RETURN(is_error_or_not_supported);
14265}
14266
14267int ha_mroonga::wrapper_analyze(THD* thd, HA_CHECK_OPT* check_opt)
14268{
14269 int error = 0;
14270 MRN_DBUG_ENTER_METHOD();
14271 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14272 MRN_SET_WRAP_TABLE_KEY(this, table);
14273 error = wrap_handler->ha_analyze(thd, check_opt);
14274 MRN_SET_BASE_SHARE_KEY(share, table->s);
14275 MRN_SET_BASE_TABLE_KEY(this, table);
14276 DBUG_RETURN(error);
14277}
14278
14279int ha_mroonga::storage_analyze(THD* thd, HA_CHECK_OPT* check_opt)
14280{
14281 MRN_DBUG_ENTER_METHOD();
14282 DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
14283}
14284
14285int ha_mroonga::analyze(THD* thd, HA_CHECK_OPT* check_opt)
14286{
14287 MRN_DBUG_ENTER_METHOD();
14288 int error = 0;
14289 if (share->wrapper_mode)
14290 {
14291 error = wrapper_analyze(thd, check_opt);
14292 } else {
14293 error = storage_analyze(thd, check_opt);
14294 }
14295 DBUG_RETURN(error);
14296}
14297
14298int ha_mroonga::wrapper_optimize(THD* thd, HA_CHECK_OPT* check_opt)
14299{
14300 MRN_DBUG_ENTER_METHOD();
14301 DBUG_RETURN(HA_ADMIN_TRY_ALTER);
14302}
14303
14304int ha_mroonga::storage_optimize(THD* thd, HA_CHECK_OPT* check_opt)
14305{
14306 MRN_DBUG_ENTER_METHOD();
14307 DBUG_RETURN(HA_ADMIN_NOT_IMPLEMENTED);
14308}
14309
14310int ha_mroonga::optimize(THD* thd, HA_CHECK_OPT* check_opt)
14311{
14312 MRN_DBUG_ENTER_METHOD();
14313 int error = 0;
14314 if (share->wrapper_mode)
14315 {
14316 error = wrapper_optimize(thd, check_opt);
14317 } else {
14318 error = storage_optimize(thd, check_opt);
14319 }
14320 DBUG_RETURN(error);
14321}
14322
14323bool ha_mroonga::wrapper_is_fatal_error(int error_num, uint flags)
14324{
14325 bool res;
14326 MRN_DBUG_ENTER_METHOD();
14327 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14328 MRN_SET_WRAP_TABLE_KEY(this, table);
14329#ifdef MRN_HANDLER_IS_FATAL_ERROR_HAVE_FLAGS
14330 res = wrap_handler->is_fatal_error(error_num, flags);
14331#else
14332 res = wrap_handler->is_fatal_error(error_num);
14333#endif
14334 MRN_SET_BASE_SHARE_KEY(share, table->s);
14335 MRN_SET_BASE_TABLE_KEY(this, table);
14336 DBUG_RETURN(res);
14337}
14338
14339bool ha_mroonga::storage_is_fatal_error(int error_num, uint flags)
14340{
14341 MRN_DBUG_ENTER_METHOD();
14342#ifdef MRN_HANDLER_IS_FATAL_ERROR_HAVE_FLAGS
14343 bool is_fatal_error = handler::is_fatal_error(error_num, flags);
14344#else
14345 bool is_fatal_error = handler::is_fatal_error(error_num);
14346#endif
14347 DBUG_RETURN(is_fatal_error);
14348}
14349
14350bool ha_mroonga::is_fatal_error(int error_num, uint flags)
14351{
14352 MRN_DBUG_ENTER_METHOD();
14353 bool is_fatal_error;
14354 if (share->wrapper_mode)
14355 {
14356 is_fatal_error = wrapper_is_fatal_error(error_num, flags);
14357 } else {
14358 is_fatal_error = storage_is_fatal_error(error_num, flags);
14359 }
14360 DBUG_RETURN(is_fatal_error);
14361}
14362
14363bool ha_mroonga::wrapper_check_if_incompatible_data(
14364 HA_CREATE_INFO *create_info, uint table_changes)
14365{
14366 bool res;
14367 MRN_DBUG_ENTER_METHOD();
14368 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14369 MRN_SET_WRAP_TABLE_KEY(this, table);
14370 res = wrap_handler->check_if_incompatible_data(create_info, table_changes);
14371 MRN_SET_BASE_SHARE_KEY(share, table->s);
14372 MRN_SET_BASE_TABLE_KEY(this, table);
14373 DBUG_RETURN(res);
14374}
14375
14376bool ha_mroonga::storage_check_if_incompatible_data(
14377 HA_CREATE_INFO *create_info, uint table_changes)
14378{
14379 MRN_DBUG_ENTER_METHOD();
14380 uint n = table_share->fields;
14381 for (uint i = 0; i < n; i++) {
14382 Field *field = table->field[i];
14383 if (field->flags & FIELD_IS_RENAMED) {
14384 DBUG_RETURN(COMPATIBLE_DATA_NO);
14385 }
14386 }
14387 DBUG_RETURN(COMPATIBLE_DATA_YES);
14388}
14389
14390bool ha_mroonga::check_if_incompatible_data(
14391 HA_CREATE_INFO *create_info, uint table_changes)
14392{
14393 MRN_DBUG_ENTER_METHOD();
14394 bool res;
14395 if (
14396 create_info->comment.str != table_share->comment.str ||
14397 create_info->connect_string.str != table_share->connect_string.str
14398 ) {
14399 DBUG_RETURN(COMPATIBLE_DATA_NO);
14400 }
14401 if (share->wrapper_mode)
14402 {
14403 res = wrapper_check_if_incompatible_data(create_info, table_changes);
14404 } else {
14405 res = storage_check_if_incompatible_data(create_info, table_changes);
14406 }
14407 DBUG_RETURN(res);
14408}
14409
14410int ha_mroonga::storage_add_index_multiple_columns(KEY *key_info,
14411 uint num_of_keys,
14412 grn_obj **index_tables,
14413 grn_obj **index_columns,
14414 bool skip_unique_key)
14415{
14416 MRN_DBUG_ENTER_METHOD();
14417
14418 int error = 0;
14419
14420 if (!(error = storage_rnd_init(true)))
14421 {
14422 while (!(error = storage_rnd_next(table->record[0])))
14423 {
14424 for (uint i = 0; i < num_of_keys; i++) {
14425 KEY *current_key_info = key_info + i;
14426 if (
14427 KEY_N_KEY_PARTS(current_key_info) == 1 ||
14428 (current_key_info->flags & HA_FULLTEXT)
14429 ) {
14430 continue;
14431 }
14432 if (skip_unique_key && (key_info[i].flags & HA_NOSAME)) {
14433 continue;
14434 }
14435 if (!index_columns[i]) {
14436 continue;
14437 }
14438
14439 /* fix key_info.key_length */
14440 for (uint j = 0; j < KEY_N_KEY_PARTS(current_key_info); j++) {
14441 if (
14442 !current_key_info->key_part[j].null_bit &&
14443 current_key_info->key_part[j].field->null_bit
14444 ) {
14445 current_key_info->key_length++;
14446 current_key_info->key_part[j].null_bit =
14447 current_key_info->key_part[j].field->null_bit;
14448 }
14449 }
14450 if (key_info[i].flags & HA_NOSAME) {
14451 grn_id key_id;
14452 if ((error = storage_write_row_unique_index(table->record[0],
14453 current_key_info,
14454 index_tables[i],
14455 index_columns[i],
14456 &key_id)))
14457 {
14458 if (error == HA_ERR_FOUND_DUPP_KEY)
14459 {
14460 error = HA_ERR_FOUND_DUPP_UNIQUE;
14461 }
14462 break;
14463 }
14464 }
14465 if ((error = storage_write_row_multiple_column_index(table->record[0],
14466 record_id,
14467 current_key_info,
14468 index_columns[i])))
14469 {
14470 break;
14471 }
14472 }
14473 if (error)
14474 break;
14475 }
14476 if (error != HA_ERR_END_OF_FILE) {
14477 storage_rnd_end();
14478 } else {
14479 error = storage_rnd_end();
14480 }
14481 }
14482
14483 DBUG_RETURN(error);
14484}
14485
14486#ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER
14487bool ha_mroonga::wrapper_is_comment_changed(TABLE *table1, TABLE *table2)
14488{
14489 MRN_DBUG_ENTER_METHOD();
14490
14491 if (table1->s->comment.length != table2->s->comment.length) {
14492 DBUG_RETURN(true);
14493 }
14494
14495 if (strncmp(table1->s->comment.str,
14496 table2->s->comment.str,
14497 table1->s->comment.length) == 0) {
14498 DBUG_RETURN(false);
14499 } else {
14500 DBUG_RETURN(true);
14501 }
14502}
14503
14504enum_alter_inplace_result ha_mroonga::wrapper_check_if_supported_inplace_alter(
14505 TABLE *altered_table,
14506 Alter_inplace_info *ha_alter_info)
14507{
14508 MRN_DBUG_ENTER_METHOD();
14509 uint n_keys;
14510 uint i;
14511 enum_alter_inplace_result result_mroonga = HA_ALTER_INPLACE_NO_LOCK;
14512 DBUG_PRINT("info",
14513 ("mroonga: handler_flags=%lu",
14514 static_cast<ulong>(ha_alter_info->handler_flags)));
14515
14516 if (wrapper_is_comment_changed(table, altered_table)) {
14517 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14518 }
14519 if (
14520 (ha_alter_info->handler_flags & ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX) &&
14521 (ha_alter_info->handler_flags &
14522 (
14523 ALTER_ADD_COLUMN |
14524 ALTER_DROP_COLUMN |
14525 MRN_ALTER_INPLACE_INFO_ALTER_STORED_COLUMN_TYPE |
14526 MRN_ALTER_INPLACE_INFO_ALTER_STORED_COLUMN_ORDER |
14527 ALTER_COLUMN_NULLABLE |
14528 ALTER_COLUMN_NOT_NULLABLE |
14529 ALTER_COLUMN_STORAGE_TYPE |
14530 ALTER_COLUMN_COLUMN_FORMAT
14531 )
14532 )
14533 ) {
14534 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14535 }
14536 if (ha_alter_info->handler_flags & ALTER_RENAME)
14537 {
14538 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14539 }
14540
14541 DBUG_ASSERT(ha_alter_info->key_count == altered_table->s->keys);
14542 alter_key_count = 0;
14543 alter_index_drop_count = 0;
14544 alter_index_add_count = 0;
14545 alter_handler_flags = ha_alter_info->handler_flags;
14546 if (!(alter_key_info_buffer = (KEY *)
14547 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
14548 &alter_key_info_buffer, sizeof(KEY) * ha_alter_info->key_count,
14549 &alter_index_drop_buffer, sizeof(KEY) * ha_alter_info->index_drop_count,
14550 &alter_index_add_buffer, sizeof(uint) * ha_alter_info->index_add_count,
14551 &wrap_altered_table, sizeof(TABLE),
14552 &wrap_altered_table_key_info, sizeof(KEY) * altered_table->s->keys,
14553 &wrap_altered_table_share, sizeof(TABLE_SHARE),
14554 &wrap_altered_table_share_key_info, sizeof(KEY) * altered_table->s->keys,
14555 NullS))
14556 ) {
14557 DBUG_RETURN(HA_ALTER_ERROR);
14558 }
14559 memcpy(wrap_altered_table, altered_table, sizeof(TABLE));
14560 memcpy(wrap_altered_table_share, altered_table->s, sizeof(TABLE_SHARE));
14561 mrn_init_sql_alloc(ha_thd(), &(wrap_altered_table_share->mem_root));
14562
14563 n_keys = ha_alter_info->index_drop_count;
14564 for (i = 0; i < n_keys; ++i) {
14565 const KEY *key = ha_alter_info->index_drop_buffer[i];
14566 if (key->flags & HA_FULLTEXT || mrn_is_geo_key(key)) {
14567 result_mroonga = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
14568 } else {
14569 memcpy(&alter_index_drop_buffer[alter_index_drop_count],
14570 ha_alter_info->index_drop_buffer[i], sizeof(KEY));
14571 ++alter_index_drop_count;
14572 }
14573 }
14574 if (!alter_index_drop_count) {
14575 alter_handler_flags &= ~ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX;
14576 }
14577 n_keys = ha_alter_info->index_add_count;
14578 for (i = 0; i < n_keys; ++i) {
14579 const KEY *key =
14580 &altered_table->key_info[ha_alter_info->index_add_buffer[i]];
14581 if (key->flags & HA_FULLTEXT || mrn_is_geo_key(key)) {
14582 result_mroonga = HA_ALTER_INPLACE_EXCLUSIVE_LOCK;
14583 } else {
14584 alter_index_add_buffer[alter_index_add_count] =
14585 ha_alter_info->index_add_buffer[i];
14586 ++alter_index_add_count;
14587 }
14588 }
14589 if (!alter_index_add_count) {
14590 alter_handler_flags &= ~ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX;
14591 }
14592 uint add_index_pos = 0;
14593 n_keys = ha_alter_info->key_count;
14594 for (i = 0; i < n_keys; ++i) {
14595 const KEY *key = &altered_table->key_info[i];
14596 if (!(key->flags & HA_FULLTEXT || mrn_is_geo_key(key))) {
14597 memcpy(&alter_key_info_buffer[alter_key_count],
14598 &ha_alter_info->key_info_buffer[i], sizeof(KEY));
14599 memcpy(&wrap_altered_table_key_info[alter_key_count],
14600 &altered_table->key_info[i], sizeof(KEY));
14601 memcpy(&wrap_altered_table_share_key_info[alter_key_count],
14602 &altered_table->s->key_info[i], sizeof(KEY));
14603 if (add_index_pos < alter_index_add_count &&
14604 alter_index_add_buffer[add_index_pos] == i) {
14605 alter_index_add_buffer[add_index_pos] = alter_key_count;
14606 ++add_index_pos;
14607 }
14608 ++alter_key_count;
14609 }
14610 }
14611 wrap_altered_table->key_info = wrap_altered_table_key_info;
14612 wrap_altered_table_share->key_info = wrap_altered_table_share_key_info;
14613 wrap_altered_table_share->keys = alter_key_count;
14614 wrap_altered_table->s = wrap_altered_table_share;
14615
14616 if (!alter_handler_flags) {
14617 DBUG_RETURN(result_mroonga);
14618 }
14619 enum_alter_inplace_result result;
14620 MRN_SET_WRAP_ALTER_KEY(this, ha_alter_info);
14621 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14622 MRN_SET_WRAP_TABLE_KEY(this, table);
14623 result = wrap_handler->check_if_supported_inplace_alter(wrap_altered_table,
14624 ha_alter_info);
14625 MRN_SET_BASE_ALTER_KEY(this, ha_alter_info);
14626 MRN_SET_BASE_SHARE_KEY(share, table->s);
14627 MRN_SET_BASE_TABLE_KEY(this, table);
14628 if (result_mroonga > result)
14629 DBUG_RETURN(result);
14630 DBUG_RETURN(result_mroonga);
14631}
14632
14633enum_alter_inplace_result ha_mroonga::storage_check_if_supported_inplace_alter(
14634 TABLE *altered_table,
14635 Alter_inplace_info *ha_alter_info)
14636{
14637 MRN_DBUG_ENTER_METHOD();
14638 alter_table_operations explicitly_unsupported_flags =
14639 ALTER_ADD_FOREIGN_KEY |
14640 ALTER_DROP_FOREIGN_KEY;
14641 alter_table_operations supported_flags =
14642 ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX |
14643 ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX |
14644 ALTER_ADD_UNIQUE_INDEX |
14645 ALTER_DROP_UNIQUE_INDEX |
14646 MRN_ALTER_INPLACE_INFO_ADD_VIRTUAL_COLUMN |
14647 MRN_ALTER_INPLACE_INFO_ADD_STORED_BASE_COLUMN |
14648 MRN_ALTER_INPLACE_INFO_ADD_STORED_GENERATED_COLUMN |
14649 ALTER_DROP_COLUMN |
14650 ALTER_COLUMN_NAME;
14651 if (ha_alter_info->handler_flags & explicitly_unsupported_flags) {
14652 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14653 } else if (ha_alter_info->handler_flags & supported_flags) {
14654 DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
14655 } else {
14656 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
14657 }
14658}
14659
14660enum_alter_inplace_result ha_mroonga::check_if_supported_inplace_alter(
14661 TABLE *altered_table,
14662 Alter_inplace_info *ha_alter_info)
14663{
14664 MRN_DBUG_ENTER_METHOD();
14665 enum_alter_inplace_result result;
14666 if (share->wrapper_mode) {
14667 result = wrapper_check_if_supported_inplace_alter(altered_table,
14668 ha_alter_info);
14669 } else {
14670 result = storage_check_if_supported_inplace_alter(altered_table,
14671 ha_alter_info);
14672 }
14673 DBUG_RETURN(result);
14674}
14675
14676bool ha_mroonga::wrapper_prepare_inplace_alter_table(
14677 TABLE *altered_table,
14678 Alter_inplace_info *ha_alter_info)
14679{
14680 bool result;
14681 MRN_DBUG_ENTER_METHOD();
14682 if (!alter_handler_flags) {
14683 DBUG_RETURN(false);
14684 }
14685
14686#ifdef MRN_SUPPORT_CUSTOM_OPTIONS
14687 int error = 0;
14688 MRN_SHARE *tmp_share;
14689 tmp_share = mrn_get_share(altered_table->s->table_name.str,
14690 altered_table,
14691 &error);
14692 if (error != 0) {
14693 DBUG_RETURN(true);
14694 }
14695
14696 if (parse_engine_table_options(ha_thd(),
14697 tmp_share->hton,
14698 wrap_altered_table->s)) {
14699 mrn_free_share(tmp_share);
14700 DBUG_RETURN(true);
14701 }
14702#endif
14703
14704 MRN_SET_WRAP_ALTER_KEY(this, ha_alter_info);
14705 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14706 MRN_SET_WRAP_TABLE_KEY(this, table);
14707 result = wrap_handler->ha_prepare_inplace_alter_table(wrap_altered_table,
14708 ha_alter_info);
14709 MRN_SET_BASE_ALTER_KEY(this, ha_alter_info);
14710 MRN_SET_BASE_SHARE_KEY(share, table->s);
14711 MRN_SET_BASE_TABLE_KEY(this, table);
14712
14713#ifdef MRN_SUPPORT_CUSTOM_OPTIONS
14714 mrn_free_share(tmp_share);
14715#endif
14716
14717 DBUG_RETURN(result);
14718}
14719
14720bool ha_mroonga::storage_prepare_inplace_alter_table(
14721 TABLE *altered_table,
14722 Alter_inplace_info *ha_alter_info)
14723{
14724 MRN_DBUG_ENTER_METHOD();
14725 DBUG_RETURN(false);
14726}
14727
14728bool ha_mroonga::prepare_inplace_alter_table(
14729 TABLE *altered_table,
14730 Alter_inplace_info *ha_alter_info)
14731{
14732 MRN_DBUG_ENTER_METHOD();
14733 bool result;
14734 if (share->wrapper_mode) {
14735 result = wrapper_prepare_inplace_alter_table(altered_table, ha_alter_info);
14736 } else {
14737 result = storage_prepare_inplace_alter_table(altered_table, ha_alter_info);
14738 }
14739 DBUG_RETURN(result);
14740}
14741
14742bool ha_mroonga::wrapper_inplace_alter_table(
14743 TABLE *altered_table,
14744 Alter_inplace_info *ha_alter_info)
14745{
14746 int error;
14747 bool result = false;
14748 uint n_keys;
14749 uint i, j = 0;
14750 KEY *key_info = table_share->key_info;
14751 MRN_DBUG_ENTER_METHOD();
14752 error = mrn_change_encoding(ctx, system_charset_info);
14753 if (error)
14754 DBUG_RETURN(true);
14755
14756 DBUG_PRINT("info", ("mroonga: table_name=%s", share->table_name));
14757 mrn::PathMapper mapper(share->table_name);
14758 n_keys = ha_alter_info->index_drop_count;
14759 for (i = 0; i < n_keys; ++i) {
14760 const KEY *key = ha_alter_info->index_drop_buffer[i];
14761 if (!(key->flags & HA_FULLTEXT || mrn_is_geo_key(key))) {
14762 continue;
14763 }
14764 while (strcmp(key_info[j].name.str, key->name.str)) {
14765 ++j;
14766 }
14767 DBUG_PRINT("info", ("mroonga: key_name=%s", key->name.str));
14768 error = drop_index(share, j);
14769 if (error)
14770 DBUG_RETURN(true);
14771 grn_index_tables[j] = NULL;
14772 grn_index_columns[j] = NULL;
14773 }
14774
14775 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables,
14776 ha_alter_info->key_count);
14777 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns,
14778 ha_alter_info->key_count);
14779 MRN_SHARE *tmp_share;
14780 TABLE_SHARE tmp_table_share;
14781 char **key_tokenizer;
14782 uint *key_tokenizer_length;
14783 KEY *p_key_info = &table->key_info[table_share->primary_key];
14784 bool need_fill_index = false;
14785 memset(index_tables, 0, sizeof(grn_obj *) * ha_alter_info->key_count);
14786 memset(index_columns, 0, sizeof(grn_obj *) * ha_alter_info->key_count);
14787 tmp_table_share.keys = ha_alter_info->key_count;
14788 tmp_table_share.fields = 0;
14789 if (!(tmp_share = (MRN_SHARE *)
14790 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
14791 &tmp_share, sizeof(*tmp_share),
14792 &key_tokenizer, sizeof(char *) * (tmp_table_share.keys),
14793 &key_tokenizer_length, sizeof(uint) * (tmp_table_share.keys),
14794 NullS))
14795 ) {
14796 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
14797 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
14798 DBUG_RETURN(true);
14799 }
14800 tmp_share->engine = NULL;
14801 tmp_share->table_share = &tmp_table_share;
14802 tmp_share->index_table = NULL;
14803 tmp_share->index_table_length = NULL;
14804 tmp_share->key_tokenizer = key_tokenizer;
14805 tmp_share->key_tokenizer_length = key_tokenizer_length;
14806 bitmap_clear_all(table->read_set);
14807 mrn_set_bitmap_by_key(table->read_set, p_key_info);
14808 n_keys = ha_alter_info->index_add_count;
14809 for (i = 0; i < n_keys; ++i) {
14810 uint key_pos = ha_alter_info->index_add_buffer[i];
14811 KEY *key = &altered_table->key_info[key_pos];
14812 if (!(key->flags & HA_FULLTEXT || mrn_is_geo_key(key))) {
14813 continue;
14814 }
14815 if (share->disable_keys) {
14816 continue;
14817 }
14818 if ((error = mrn_add_index_param(tmp_share, key, key_pos)))
14819 {
14820 break;
14821 }
14822 DBUG_PRINT("info", ("mroonga: add key pos=%u", key_pos));
14823 if (
14824 (key->flags & HA_FULLTEXT) &&
14825 (error = wrapper_create_index_fulltext(mapper.table_name(),
14826 key_pos,
14827 key, index_tables, NULL,
14828 tmp_share))
14829 ) {
14830 break;
14831 } else if (
14832 mrn_is_geo_key(key) &&
14833 (error = wrapper_create_index_geo(mapper.table_name(),
14834 key_pos, key,
14835 index_tables, NULL, tmp_share))
14836 ) {
14837 break;
14838 }
14839 mrn_set_bitmap_by_key(table->read_set, key);
14840 index_columns[key_pos] = grn_obj_column(ctx,
14841 index_tables[key_pos],
14842 INDEX_COLUMN_NAME,
14843 strlen(INDEX_COLUMN_NAME));
14844 need_fill_index = true;
14845 }
14846 if (!error && need_fill_index) {
14847 my_ptrdiff_t diff =
14848 PTR_BYTE_DIFF(table->record[0], altered_table->record[0]);
14849 mrn::TableFieldsOffsetMover mover(altered_table, diff);
14850 error = wrapper_fill_indexes(ha_thd(), altered_table->key_info,
14851 index_columns, ha_alter_info->key_count);
14852 }
14853 bitmap_set_all(table->read_set);
14854
14855 if (!error && alter_handler_flags) {
14856#ifdef MRN_SUPPORT_CUSTOM_OPTIONS
14857 {
14858 MRN_SHARE *alter_tmp_share;
14859 alter_tmp_share = mrn_get_share(altered_table->s->table_name.str,
14860 altered_table,
14861 &error);
14862 if (alter_tmp_share) {
14863 if (parse_engine_table_options(ha_thd(),
14864 alter_tmp_share->hton,
14865 wrap_altered_table->s)) {
14866 error = MRN_GET_ERROR_NUMBER;
14867 }
14868 mrn_free_share(alter_tmp_share);
14869 }
14870 }
14871#endif
14872 if (!error) {
14873 MRN_SET_WRAP_ALTER_KEY(this, ha_alter_info);
14874 MRN_SET_WRAP_SHARE_KEY(share, table->s);
14875 MRN_SET_WRAP_TABLE_KEY(this, table);
14876 result = wrap_handler->ha_inplace_alter_table(wrap_altered_table,
14877 ha_alter_info);
14878 MRN_SET_BASE_ALTER_KEY(this, ha_alter_info);
14879 MRN_SET_BASE_SHARE_KEY(share, table->s);
14880 MRN_SET_BASE_TABLE_KEY(this, table);
14881 }
14882 }
14883
14884 if (result || error)
14885 {
14886 n_keys = ha_alter_info->index_add_count;
14887 for (i = 0; i < n_keys; ++i) {
14888 uint key_pos = ha_alter_info->index_add_buffer[i];
14889 KEY *key = &altered_table->key_info[key_pos];
14890 if (!(key->flags & HA_FULLTEXT || mrn_is_geo_key(key))) {
14891 continue;
14892 }
14893 if (share->disable_keys) {
14894 continue;
14895 }
14896 if (index_tables[key_pos])
14897 {
14898 grn_obj_remove(ctx, index_tables[key_pos]);
14899 }
14900 }
14901 result = true;
14902 }
14903 mrn_free_share_alloc(tmp_share);
14904 my_free(tmp_share);
14905 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
14906 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
14907 DBUG_RETURN(result);
14908}
14909
14910bool ha_mroonga::storage_inplace_alter_table_add_index(
14911 TABLE *altered_table,
14912 Alter_inplace_info *ha_alter_info)
14913{
14914 MRN_DBUG_ENTER_METHOD();
14915
14916 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables,
14917 ha_alter_info->key_count);
14918 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns,
14919 ha_alter_info->key_count);
14920 MRN_SHARE *tmp_share;
14921 TABLE_SHARE tmp_table_share;
14922 char **index_table, **key_tokenizer, **col_flags, **col_type;
14923 uint *index_table_length, *key_tokenizer_length, *col_flags_length, *col_type_length;
14924 bool have_multiple_column_index = false;
14925 memset(index_tables, 0, sizeof(grn_obj *) * ha_alter_info->key_count);
14926 memset(index_columns, 0, sizeof(grn_obj *) * ha_alter_info->key_count);
14927 tmp_table_share.keys = ha_alter_info->key_count;
14928 tmp_table_share.fields = 0;
14929 if (!(tmp_share = (MRN_SHARE *)
14930 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
14931 &tmp_share, sizeof(*tmp_share),
14932 &index_table, sizeof(char *) * tmp_table_share.keys,
14933 &index_table_length, sizeof(uint) * tmp_table_share.keys,
14934 &key_tokenizer, sizeof(char *) * tmp_table_share.keys,
14935 &key_tokenizer_length, sizeof(uint) * tmp_table_share.keys,
14936 &col_flags, sizeof(char *) * tmp_table_share.fields,
14937 &col_flags_length, sizeof(uint) * tmp_table_share.fields,
14938 &col_type, sizeof(char *) * tmp_table_share.fields,
14939 &col_type_length, sizeof(uint) * tmp_table_share.fields,
14940 NullS))
14941 ) {
14942 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
14943 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
14944 DBUG_RETURN(true);
14945 }
14946 tmp_share->engine = NULL;
14947 tmp_share->table_share = &tmp_table_share;
14948 tmp_share->index_table = index_table;
14949 tmp_share->index_table_length = index_table_length;
14950 tmp_share->key_tokenizer = key_tokenizer;
14951 tmp_share->key_tokenizer_length = key_tokenizer_length;
14952 tmp_share->col_flags = col_flags;
14953 tmp_share->col_flags_length = col_flags_length;
14954 tmp_share->col_type = col_type;
14955 tmp_share->col_type_length = col_type_length;
14956 bitmap_clear_all(table->read_set);
14957 if (table_share->primary_key != MAX_KEY) {
14958 KEY *p_key_info = &table->key_info[table_share->primary_key];
14959 mrn_set_bitmap_by_key(table->read_set, p_key_info);
14960 }
14961 int error = 0;
14962 uint n_keys = ha_alter_info->index_add_count;
14963 for (uint i = 0; i < n_keys; ++i) {
14964 uint key_pos = ha_alter_info->index_add_buffer[i];
14965 KEY *key = &altered_table->key_info[key_pos];
14966 if (share->disable_keys && !(key->flags & HA_NOSAME)) {
14967 continue; // key is disabled
14968 }
14969 if ((error = mrn_add_index_param(tmp_share, key, key_pos)))
14970 {
14971 break;
14972 }
14973 DBUG_PRINT("info", ("mroonga: add key pos=%u", key_pos));
14974 mrn::PathMapper mapper(share->table_name);
14975 if ((error = storage_create_index(table, mapper.table_name(), grn_table,
14976 tmp_share, key, index_tables,
14977 index_columns, key_pos)))
14978 {
14979 break;
14980 }
14981 if (
14982 KEY_N_KEY_PARTS(key) == 1 &&
14983 (key->flags & HA_NOSAME) &&
14984 grn_table_size(ctx, grn_table) !=
14985 grn_table_size(ctx, index_tables[key_pos])
14986 ) {
14987 error = HA_ERR_FOUND_DUPP_UNIQUE;
14988 my_printf_error(ER_DUP_UNIQUE, ER(ER_DUP_UNIQUE), MYF(0),
14989 table_share->table_name);
14990 ++i;
14991 break;
14992 }
14993 if (
14994 KEY_N_KEY_PARTS(key) != 1 &&
14995 !(key->flags & HA_FULLTEXT)
14996 ) {
14997 mrn_set_bitmap_by_key(table->read_set, key);
14998 have_multiple_column_index = true;
14999 }
15000 }
15001 if (!error && have_multiple_column_index) {
15002 my_ptrdiff_t diff =
15003 PTR_BYTE_DIFF(table->record[0], altered_table->record[0]);
15004 mrn::TableFieldsOffsetMover mover(altered_table, diff);
15005 error = storage_add_index_multiple_columns(altered_table->key_info,
15006 ha_alter_info->key_count,
15007 index_tables,
15008 index_columns, false);
15009 if (error == HA_ERR_FOUND_DUPP_UNIQUE) {
15010 my_printf_error(ER_DUP_UNIQUE, ER(ER_DUP_UNIQUE), MYF(0),
15011 table_share->table_name);
15012 } else if (error) {
15013 my_message(error, "failed to create multiple column index", MYF(0));
15014 }
15015 }
15016 bitmap_set_all(table->read_set);
15017
15018 bool have_error = false;
15019 if (error)
15020 {
15021 n_keys = ha_alter_info->index_add_count;
15022 for (uint i = 0; i < n_keys; ++i) {
15023 uint key_pos = ha_alter_info->index_add_buffer[i];
15024 KEY *key =
15025 &altered_table->key_info[key_pos];
15026 if (share->disable_keys && !(key->flags & HA_NOSAME)) {
15027 continue;
15028 }
15029 if (index_tables[key_pos])
15030 {
15031 grn_obj_remove(ctx, index_columns[key_pos]);
15032 grn_obj_remove(ctx, index_tables[key_pos]);
15033 }
15034 }
15035 have_error = true;
15036 }
15037 mrn_free_share_alloc(tmp_share);
15038 my_free(tmp_share);
15039 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15040 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15041
15042 DBUG_RETURN(have_error);
15043}
15044
15045bool ha_mroonga::storage_inplace_alter_table_drop_index(
15046 TABLE *altered_table,
15047 Alter_inplace_info *ha_alter_info)
15048{
15049 MRN_DBUG_ENTER_METHOD();
15050
15051 bool have_error = false;
15052 uint n_keys;
15053 uint i, j = 0;
15054 KEY *key_info = table_share->key_info;
15055 mrn::PathMapper mapper(share->table_name);
15056 n_keys = ha_alter_info->index_drop_count;
15057 for (i = 0; i < n_keys; ++i) {
15058 KEY *key = ha_alter_info->index_drop_buffer[i];
15059 while (strcmp(key_info[j].name.str, key->name.str) != 0) {
15060 ++j;
15061 }
15062 int error = drop_index(share, j);
15063 if (error != 0)
15064 DBUG_RETURN(true);
15065 grn_index_tables[j] = NULL;
15066 grn_index_columns[j] = NULL;
15067 }
15068
15069 DBUG_RETURN(have_error);
15070}
15071
15072bool ha_mroonga::storage_inplace_alter_table_add_column(
15073 TABLE *altered_table,
15074 Alter_inplace_info *ha_alter_info)
15075{
15076 MRN_DBUG_ENTER_METHOD();
15077
15078 bool have_error = false;
15079
15080 MRN_SHARE *tmp_share;
15081 TABLE_SHARE tmp_table_share;
15082 char **index_table, **key_tokenizer, **col_flags, **col_type;
15083 uint *index_table_length, *key_tokenizer_length, *col_flags_length, *col_type_length;
15084 tmp_table_share.keys = 0;
15085 tmp_table_share.fields = altered_table->s->fields;
15086 tmp_share = (MRN_SHARE *)mrn_my_multi_malloc(
15087 MYF(MY_WME | MY_ZEROFILL),
15088 &tmp_share, sizeof(*tmp_share),
15089 &index_table, sizeof(char *) * tmp_table_share.keys,
15090 &index_table_length, sizeof(uint) * tmp_table_share.keys,
15091 &key_tokenizer, sizeof(char *) * tmp_table_share.keys,
15092 &key_tokenizer_length, sizeof(uint) * tmp_table_share.keys,
15093 &col_flags, sizeof(char *) * tmp_table_share.fields,
15094 &col_flags_length, sizeof(uint) * tmp_table_share.fields,
15095 &col_type, sizeof(char *) * tmp_table_share.fields,
15096 &col_type_length, sizeof(uint) * tmp_table_share.fields,
15097 NullS);
15098 if (!tmp_share) {
15099 have_error = true;
15100 DBUG_RETURN(have_error);
15101 }
15102 tmp_share->engine = NULL;
15103 tmp_share->table_share = &tmp_table_share;
15104 tmp_share->index_table = index_table;
15105 tmp_share->index_table_length = index_table_length;
15106 tmp_share->key_tokenizer = key_tokenizer;
15107 tmp_share->key_tokenizer_length = key_tokenizer_length;
15108 tmp_share->col_flags = col_flags;
15109 tmp_share->col_flags_length = col_flags_length;
15110 tmp_share->col_type = col_type;
15111 tmp_share->col_type_length = col_type_length;
15112
15113 mrn::PathMapper mapper(share->table_name);
15114 grn_obj *table_obj;
15115 table_obj = grn_ctx_get(ctx, mapper.table_name(), strlen(mapper.table_name()));
15116
15117 Alter_info *alter_info = ha_alter_info->alter_info;
15118 List_iterator_fast<Create_field> create_fields(alter_info->create_list);
15119 for (uint i = 0; Create_field *create_field = create_fields++; i++) {
15120 if (create_field->field) {
15121 continue;
15122 }
15123
15124 Field *field = altered_table->s->field[i];
15125
15126#ifdef MRN_SUPPORT_GENERATED_COLUMNS
15127 if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) {
15128 continue;
15129 }
15130#endif
15131
15132 mrn::ColumnName column_name(field->field_name);
15133 int error = mrn_add_column_param(tmp_share, field, i);
15134 if (error) {
15135 have_error = true;
15136 break;
15137 }
15138
15139 grn_obj_flags col_flags = GRN_OBJ_PERSISTENT;
15140 if (!find_column_flags(field, tmp_share, i, &col_flags)) {
15141 col_flags |= GRN_OBJ_COLUMN_SCALAR;
15142 }
15143
15144 grn_obj *col_type;
15145 {
15146 int column_type_error_code = ER_WRONG_FIELD_SPEC;
15147 col_type = find_column_type(field, tmp_share, i, column_type_error_code);
15148 if (!col_type) {
15149 error = column_type_error_code;
15150 have_error = true;
15151 break;
15152 }
15153 }
15154 char *col_path = NULL; // we don't specify path
15155
15156 grn_obj *column_obj =
15157 grn_column_create(ctx, table_obj,
15158 column_name.c_str(),
15159 column_name.length(),
15160 col_path, col_flags, col_type);
15161 if (ctx->rc) {
15162 error = ER_WRONG_COLUMN_NAME;
15163 my_message(error, ctx->errbuf, MYF(0));
15164 have_error = true;
15165 break;
15166 }
15167
15168#ifdef MRN_SUPPORT_GENERATED_COLUMNS
15169 if (MRN_GENERATED_COLUMNS_FIELD_IS_STORED(field)) {
15170# ifndef MRN_MARIADB_P
15171 MY_BITMAP generated_column_bitmap;
15172 if (bitmap_init(&generated_column_bitmap, NULL,
15173 altered_table->s->fields, false)) {
15174 error = HA_ERR_OUT_OF_MEM;
15175 my_message(ER_OUTOFMEMORY,
15176 "mroonga: storage: "
15177 "failed to allocate memory for getting generated value",
15178 MYF(0));
15179 have_error = true;
15180 grn_obj_remove(ctx, column_obj);
15181 break;
15182 }
15183 mrn::SmartBitmap smart_generated_column_bitmap(&generated_column_bitmap);
15184 bitmap_set_bit(&generated_column_bitmap, field->field_index);
15185# endif
15186
15187 my_ptrdiff_t diff =
15188 PTR_BYTE_DIFF(table->record[0], altered_table->record[0]);
15189 mrn::TableFieldsOffsetMover mover(altered_table, diff);
15190
15191 error = storage_rnd_init(true);
15192 if (error) {
15193 have_error = true;
15194 grn_obj_remove(ctx, column_obj);
15195 break;
15196 }
15197
15198 Field *altered_field = altered_table->field[i];
15199 grn_obj new_value;
15200 GRN_VOID_INIT(&new_value);
15201 mrn::SmartGrnObj smart_new_value(ctx, &new_value);
15202 while (!have_error) {
15203 int next_error = storage_rnd_next(table->record[0]);
15204 if (next_error == HA_ERR_END_OF_FILE) {
15205 break;
15206 } else if (next_error != 0) {
15207 error = next_error;
15208 have_error = true;
15209 grn_obj_remove(ctx, column_obj);
15210 break;
15211 }
15212
15213# ifdef MRN_MARIADB_P
15214 MRN_GENERATED_COLUMNS_UPDATE_VIRTUAL_FIELD(altered_table, altered_field);
15215# else
15216 if (update_generated_write_fields(&generated_column_bitmap, altered_table)) {
15217 error = ER_ERROR_ON_WRITE;
15218 my_message(error,
15219 "mroonga: storage: "
15220 "failed to update generated value for updating column",
15221 MYF(0));
15222 have_error = true;
15223 grn_obj_remove(ctx, column_obj);
15224 break;
15225 }
15226# endif
15227
15228 error = mrn_change_encoding(ctx, altered_field->charset());
15229 if (error) {
15230 my_message(error,
15231 "mroonga: storage: "
15232 "failed to change encoding to store generated value",
15233 MYF(0));
15234 have_error = true;
15235 grn_obj_remove(ctx, column_obj);
15236 break;
15237 }
15238 error = generic_store_bulk(altered_field, &new_value);
15239 if (error) {
15240 my_message(error,
15241 "mroonga: storage: "
15242 "failed to get generated value for updating column",
15243 MYF(0));
15244 have_error = true;
15245 grn_obj_remove(ctx, column_obj);
15246 break;
15247 }
15248
15249 grn_obj_set_value(ctx, column_obj, record_id, &new_value, GRN_OBJ_SET);
15250 if (ctx->rc) {
15251 error = ER_ERROR_ON_WRITE;
15252 my_message(error, ctx->errbuf, MYF(0));
15253 break;
15254 }
15255 }
15256
15257 int end_error = storage_rnd_end();
15258 if (end_error != 0 && error == 0) {
15259 error = end_error;
15260 grn_obj_remove(ctx, column_obj);
15261 break;
15262 }
15263 }
15264#endif
15265 }
15266
15267 grn_obj_unlink(ctx, table_obj);
15268
15269 mrn_free_share_alloc(tmp_share);
15270 my_free(tmp_share);
15271
15272 DBUG_RETURN(have_error);
15273}
15274
15275bool ha_mroonga::storage_inplace_alter_table_drop_column(
15276 TABLE *altered_table,
15277 Alter_inplace_info *ha_alter_info)
15278{
15279 MRN_DBUG_ENTER_METHOD();
15280
15281 bool have_error = false;
15282
15283 mrn::PathMapper mapper(share->table_name);
15284 grn_obj *table_obj;
15285 table_obj = grn_ctx_get(ctx, mapper.table_name(), strlen(mapper.table_name()));
15286
15287 Alter_info *alter_info = ha_alter_info->alter_info;
15288
15289 uint n_fields = table->s->fields;
15290 for (uint i = 0; i < n_fields; i++) {
15291 Field *field = table->field[i];
15292
15293 bool dropped = true;
15294 List_iterator_fast<Create_field> create_fields(alter_info->create_list);
15295 while (Create_field *create_field = create_fields++) {
15296 if (create_field->field == field) {
15297 dropped = false;
15298 break;
15299 }
15300 }
15301 if (!dropped) {
15302 continue;
15303 }
15304
15305 const char *column_name = field->field_name.str;
15306 int column_name_size = field->field_name.length;
15307
15308 grn_obj *column_obj;
15309 column_obj = grn_obj_column(ctx, table_obj, column_name, column_name_size);
15310 if (column_obj) {
15311 grn_obj_remove(ctx, column_obj);
15312 }
15313 if (ctx->rc) {
15314 int error = ER_WRONG_COLUMN_NAME;
15315 my_message(error, ctx->errbuf, MYF(0));
15316 have_error = true;
15317 break;
15318 }
15319 }
15320 grn_obj_unlink(ctx, table_obj);
15321
15322 DBUG_RETURN(have_error);
15323}
15324
15325bool ha_mroonga::storage_inplace_alter_table_rename_column(
15326 TABLE *altered_table,
15327 Alter_inplace_info *ha_alter_info)
15328{
15329 MRN_DBUG_ENTER_METHOD();
15330
15331 bool have_error = false;
15332
15333 mrn::PathMapper mapper(share->table_name);
15334 grn_obj *table_obj;
15335 table_obj = grn_ctx_get(ctx, mapper.table_name(), strlen(mapper.table_name()));
15336
15337 Alter_info *alter_info = ha_alter_info->alter_info;
15338 uint n_fields = table->s->fields;
15339 for (uint i = 0; i < n_fields; i++) {
15340 Field *field = table->field[i];
15341
15342 if (!(field->flags & FIELD_IS_RENAMED)) {
15343 continue;
15344 }
15345
15346 LEX_CSTRING new_name;
15347 new_name.str= 0;
15348 List_iterator_fast<Create_field> create_fields(alter_info->create_list);
15349 while (Create_field *create_field = create_fields++) {
15350 if (create_field->field == field) {
15351 new_name = create_field->field_name;
15352 break;
15353 }
15354 }
15355
15356 if (!new_name.str) {
15357 continue;
15358 }
15359
15360 const char *old_name = field->field_name.str;
15361 grn_obj *column_obj;
15362 column_obj = grn_obj_column(ctx, table_obj, old_name,
15363 field->field_name.length);
15364 if (column_obj) {
15365 grn_column_rename(ctx, column_obj, new_name.str, new_name.length);
15366 if (ctx->rc) {
15367 int error = ER_WRONG_COLUMN_NAME;
15368 my_message(error, ctx->errbuf, MYF(0));
15369 have_error = true;
15370 }
15371 grn_obj_unlink(ctx, column_obj);
15372 }
15373
15374 if (have_error) {
15375 break;
15376 }
15377 }
15378 grn_obj_unlink(ctx, table_obj);
15379
15380 DBUG_RETURN(have_error);
15381}
15382
15383bool ha_mroonga::storage_inplace_alter_table(
15384 TABLE *altered_table,
15385 Alter_inplace_info *ha_alter_info)
15386{
15387 MRN_DBUG_ENTER_METHOD();
15388
15389 bool have_error = false;
15390
15391 int error = mrn_change_encoding(ctx, system_charset_info);
15392 if (error) {
15393 have_error = true;
15394 }
15395
15396 alter_table_operations drop_index_related_flags =
15397 ALTER_DROP_INDEX |
15398 ALTER_DROP_NON_UNIQUE_NON_PRIM_INDEX |
15399 ALTER_DROP_UNIQUE_INDEX |
15400 ALTER_DROP_PK_INDEX;
15401 if (!have_error &&
15402 (ha_alter_info->handler_flags & drop_index_related_flags)) {
15403 have_error = storage_inplace_alter_table_drop_index(altered_table,
15404 ha_alter_info);
15405 }
15406
15407 alter_table_operations add_column_related_flags =
15408 ALTER_ADD_COLUMN;
15409 if (!have_error &&
15410 (ha_alter_info->handler_flags & add_column_related_flags)) {
15411 have_error = storage_inplace_alter_table_add_column(altered_table, ha_alter_info);
15412 }
15413
15414 alter_table_operations drop_column_related_flags = ALTER_DROP_COLUMN;
15415 if (!have_error &&
15416 (ha_alter_info->handler_flags & drop_column_related_flags)) {
15417 have_error = storage_inplace_alter_table_drop_column(altered_table, ha_alter_info);
15418 }
15419
15420 alter_table_operations rename_column_related_flags = ALTER_COLUMN_NAME;
15421 if (!have_error &&
15422 (ha_alter_info->handler_flags & rename_column_related_flags)) {
15423 have_error = storage_inplace_alter_table_rename_column(altered_table, ha_alter_info);
15424 }
15425
15426 alter_table_operations add_index_related_flags =
15427 ALTER_ADD_INDEX |
15428 ALTER_ADD_NON_UNIQUE_NON_PRIM_INDEX |
15429 ALTER_ADD_UNIQUE_INDEX |
15430 ALTER_ADD_PK_INDEX;
15431 if (!have_error &&
15432 (ha_alter_info->handler_flags & add_index_related_flags)) {
15433 have_error = storage_inplace_alter_table_add_index(altered_table,
15434 ha_alter_info);
15435 }
15436
15437 DBUG_RETURN(have_error);
15438}
15439
15440bool ha_mroonga::inplace_alter_table(
15441 TABLE *altered_table,
15442 Alter_inplace_info *ha_alter_info)
15443{
15444 MRN_DBUG_ENTER_METHOD();
15445 bool result;
15446 if (share->wrapper_mode) {
15447 result = wrapper_inplace_alter_table(altered_table, ha_alter_info);
15448 } else {
15449 result = storage_inplace_alter_table(altered_table, ha_alter_info);
15450 }
15451 DBUG_RETURN(result);
15452}
15453
15454bool ha_mroonga::wrapper_commit_inplace_alter_table(
15455 TABLE *altered_table,
15456 Alter_inplace_info *ha_alter_info,
15457 bool commit)
15458{
15459 bool result;
15460 MRN_DBUG_ENTER_METHOD();
15461 if (!alter_handler_flags) {
15462 free_root(&(wrap_altered_table_share->mem_root), MYF(0));
15463 my_free(alter_key_info_buffer);
15464 alter_key_info_buffer = NULL;
15465 DBUG_RETURN(false);
15466 }
15467 MRN_SET_WRAP_ALTER_KEY(this, ha_alter_info);
15468 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15469 MRN_SET_WRAP_TABLE_KEY(this, table);
15470 result = wrap_handler->ha_commit_inplace_alter_table(wrap_altered_table,
15471 ha_alter_info,
15472 commit);
15473 MRN_SET_BASE_ALTER_KEY(this, ha_alter_info);
15474 MRN_SET_BASE_SHARE_KEY(share, table->s);
15475 MRN_SET_BASE_TABLE_KEY(this, table);
15476 free_root(&(wrap_altered_table_share->mem_root), MYF(0));
15477 my_free(alter_key_info_buffer);
15478 alter_key_info_buffer = NULL;
15479 DBUG_RETURN(result);
15480}
15481
15482bool ha_mroonga::storage_commit_inplace_alter_table(
15483 TABLE *altered_table,
15484 Alter_inplace_info *ha_alter_info,
15485 bool commit)
15486{
15487 MRN_DBUG_ENTER_METHOD();
15488 DBUG_RETURN(false);
15489}
15490
15491bool ha_mroonga::commit_inplace_alter_table(
15492 TABLE *altered_table,
15493 Alter_inplace_info *ha_alter_info,
15494 bool commit)
15495{
15496 MRN_DBUG_ENTER_METHOD();
15497 bool result;
15498 if (share->wrapper_mode) {
15499 result = wrapper_commit_inplace_alter_table(altered_table, ha_alter_info,
15500 commit);
15501 } else {
15502 result = storage_commit_inplace_alter_table(altered_table, ha_alter_info,
15503 commit);
15504 }
15505 DBUG_RETURN(result);
15506}
15507
15508void ha_mroonga::wrapper_notify_table_changed()
15509{
15510 MRN_DBUG_ENTER_METHOD();
15511 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15512 MRN_SET_WRAP_TABLE_KEY(this, table);
15513 wrap_handler->ha_notify_table_changed();
15514 MRN_SET_BASE_SHARE_KEY(share, table->s);
15515 MRN_SET_BASE_TABLE_KEY(this, table);
15516 DBUG_VOID_RETURN;
15517}
15518
15519void ha_mroonga::storage_notify_table_changed()
15520{
15521 MRN_DBUG_ENTER_METHOD();
15522 DBUG_VOID_RETURN;
15523}
15524
15525void ha_mroonga::notify_table_changed()
15526{
15527 MRN_DBUG_ENTER_METHOD();
15528 if (share->wrapper_mode) {
15529 wrapper_notify_table_changed();
15530 } else {
15531 storage_notify_table_changed();
15532 }
15533 DBUG_VOID_RETURN;
15534}
15535#else
15536alter_table_operations ha_mroonga::wrapper_alter_table_flags(alter_table_operations flags)
15537{
15538 alter_table_operations res;
15539 MRN_DBUG_ENTER_METHOD();
15540 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15541 MRN_SET_WRAP_TABLE_KEY(this, table);
15542 res = wrap_handler->alter_table_flags(flags);
15543 MRN_SET_BASE_SHARE_KEY(share, table->s);
15544 MRN_SET_BASE_TABLE_KEY(this, table);
15545 DBUG_RETURN(res);
15546}
15547
15548alter_table_operations ha_mroonga::storage_alter_table_flags(alter_table_operations flags)
15549{
15550 MRN_DBUG_ENTER_METHOD();
15551 alter_table_operations res = handler::alter_table_flags(flags);
15552 DBUG_RETURN(res);
15553}
15554
15555alter_table_operations ha_mroonga::alter_table_flags(alter_table_operations flags)
15556{
15557 MRN_DBUG_ENTER_METHOD();
15558 alter_table_operations res;
15559 if (share->wrapper_mode)
15560 {
15561 res = wrapper_alter_table_flags(flags);
15562 } else {
15563 res = storage_alter_table_flags(flags);
15564 }
15565 DBUG_RETURN(res);
15566}
15567
15568#ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15569int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info,
15570 uint num_of_keys, handler_add_index **add)
15571#else
15572int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info,
15573 uint num_of_keys)
15574#endif
15575{
15576 int error = 0;
15577 uint i, j, k;
15578 uint n_keys = table->s->keys;
15579 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, num_of_keys + n_keys);
15580 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, num_of_keys + n_keys);
15581 THD *thd = ha_thd();
15582 MRN_SHARE *tmp_share;
15583 TABLE_SHARE tmp_table_share;
15584 char **key_tokenizer;
15585 uint *key_tokenizer_length;
15586 MRN_DBUG_ENTER_METHOD();
15587 if (!(wrap_alter_key_info = (KEY *) mrn_my_malloc(sizeof(KEY) * num_of_keys,
15588 MYF(MY_WME)))) {
15589 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15590 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15591 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
15592 }
15593 KEY *p_key_info = &table->key_info[table_share->primary_key], *tmp_key_info;
15594 tmp_table_share.keys = n_keys + num_of_keys;
15595 tmp_table_share.fields = 0;
15596 if (!(tmp_share = (MRN_SHARE *)
15597 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
15598 &tmp_share, sizeof(*tmp_share),
15599 &key_tokenizer, sizeof(char *) * (n_keys + num_of_keys),
15600 &key_tokenizer_length, sizeof(uint) * (n_keys + num_of_keys),
15601 NullS))
15602 ) {
15603 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15604 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15605 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
15606 }
15607 tmp_share->engine = NULL;
15608 tmp_share->table_share = &tmp_table_share;
15609 tmp_share->index_table = NULL;
15610 tmp_share->index_table_length = NULL;
15611 tmp_share->key_tokenizer = key_tokenizer;
15612 tmp_share->key_tokenizer_length = key_tokenizer_length;
15613 tmp_share->col_flags = NULL;
15614 tmp_share->col_type = NULL;
15615#ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15616 hnd_add_index = NULL;
15617#endif
15618 bitmap_clear_all(table->read_set);
15619 mrn_set_bitmap_by_key(table->read_set, p_key_info);
15620 mrn::PathMapper mapper(share->table_name);
15621 for (i = 0, j = 0; i < num_of_keys; i++) {
15622 if (!(key_info[i].flags & HA_FULLTEXT) && !mrn_is_geo_key(&key_info[i])) {
15623 wrap_alter_key_info[j] = key_info[i];
15624 j++;
15625 continue;
15626 }
15627 if (share->disable_keys) {
15628 continue;
15629 }
15630 if ((error = mrn_add_index_param(tmp_share, &key_info[i], i + n_keys)))
15631 {
15632 break;
15633 }
15634 index_tables[i + n_keys] = NULL;
15635 if (
15636 (key_info[i].flags & HA_FULLTEXT) &&
15637 (error = wrapper_create_index_fulltext(mapper.table_name(),
15638 i + n_keys,
15639 &key_info[i], index_tables, NULL,
15640 tmp_share))
15641 ) {
15642 break;
15643 } else if (
15644 mrn_is_geo_key(&key_info[i]) &&
15645 (error = wrapper_create_index_geo(mapper.table_name(),
15646 i + n_keys, &key_info[i],
15647 index_tables, NULL, tmp_share))
15648 ) {
15649 break;
15650 }
15651 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
15652 }
15653 if (!error && i > j && !share->disable_keys) {
15654 for (k = 0; k < num_of_keys; k++) {
15655 tmp_key_info = &key_info[k];
15656 if (!(tmp_key_info->flags & HA_FULLTEXT) &&
15657 !mrn_is_geo_key(tmp_key_info)) {
15658 continue;
15659 }
15660 index_columns[k + n_keys] = grn_obj_column(ctx,
15661 index_tables[k + n_keys],
15662 INDEX_COLUMN_NAME,
15663 strlen(INDEX_COLUMN_NAME));
15664 }
15665 error = wrapper_fill_indexes(thd, key_info, &index_columns[n_keys],
15666 num_of_keys);
15667 }
15668 bitmap_set_all(table->read_set);
15669
15670 if (!error && j)
15671 {
15672 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15673 MRN_SET_WRAP_TABLE_KEY(this, table);
15674#ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15675 error = wrap_handler->add_index(table_arg, wrap_alter_key_info, j,
15676 &hnd_add_index);
15677#else
15678 error = wrap_handler->add_index(table_arg, wrap_alter_key_info, j);
15679#endif
15680 MRN_SET_BASE_SHARE_KEY(share, table->s);
15681 MRN_SET_BASE_TABLE_KEY(this, table);
15682 }
15683 if (error)
15684 {
15685 for (k = 0; k < i; k++) {
15686 if (!(key_info[k].flags & HA_FULLTEXT) && !mrn_is_geo_key(&key_info[k]))
15687 {
15688 continue;
15689 }
15690 if (index_tables[k + n_keys])
15691 {
15692 grn_obj_remove(ctx, index_tables[k + n_keys]);
15693 }
15694 }
15695 }
15696#ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15697 else {
15698 *add = new handler_add_index(table_arg, key_info, num_of_keys);
15699 }
15700#endif
15701 mrn_free_share_alloc(tmp_share);
15702 my_free(tmp_share);
15703 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15704 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15705 DBUG_RETURN(error);
15706}
15707
15708#ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15709int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info,
15710 uint num_of_keys, handler_add_index **add)
15711#else
15712int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info,
15713 uint num_of_keys)
15714#endif
15715{
15716 int error = 0;
15717 uint i;
15718 uint n_keys = table->s->keys;
15719 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, num_of_keys + n_keys);
15720 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_columns, num_of_keys + n_keys);
15721 MRN_SHARE *tmp_share;
15722 TABLE_SHARE tmp_table_share;
15723 char **index_table, **key_tokenizer, **col_flags, **col_type;
15724 uint *index_table_length, *key_tokenizer_length, *col_flags_length, *col_type_length;
15725 bool have_multiple_column_index = false;
15726
15727 MRN_DBUG_ENTER_METHOD();
15728 tmp_table_share.keys = n_keys + num_of_keys;
15729 tmp_table_share.fields = 0;
15730 if (!(tmp_share = (MRN_SHARE *)
15731 mrn_my_multi_malloc(MYF(MY_WME | MY_ZEROFILL),
15732 &tmp_share, sizeof(*tmp_share),
15733 &index_table, sizeof(char*) * tmp_table_share.keys,
15734 &index_table_length, sizeof(uint) * tmp_table_share.keys,
15735 &key_tokenizer, sizeof(char *) * tmp_table_share.keys,
15736 &key_tokenizer_length, sizeof(uint) * tmp_table_share.keys,
15737 &col_flags, sizeof(char *) * tmp_table_share.fields,
15738 &col_flags_length, sizeof(uint) * tmp_table_share.fields,
15739 &col_type, sizeof(char *) * tmp_table_share.fields,
15740 &col_type_length, sizeof(uint) * tmp_table_share.fields,
15741 NullS))
15742 ) {
15743 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15744 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15745 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
15746 }
15747 tmp_share->engine = NULL;
15748 tmp_share->table_share = &tmp_table_share;
15749 tmp_share->index_table = index_table;
15750 tmp_share->index_table_length = index_table_length;
15751 tmp_share->key_tokenizer = key_tokenizer;
15752 tmp_share->key_tokenizer_length = key_tokenizer_length;
15753 tmp_share->col_flags = col_flags;
15754 tmp_share->col_flags_length = col_flags_length;
15755 tmp_share->col_type = col_type;
15756 tmp_share->col_type_length = col_type_length;
15757 bitmap_clear_all(table->read_set);
15758 mrn::PathMapper mapper(share->table_name);
15759 for (i = 0; i < num_of_keys; i++) {
15760 if (share->disable_keys && !(key_info[i].flags & HA_NOSAME)) {
15761 continue; // key is disabled
15762 }
15763 index_tables[i + n_keys] = NULL;
15764 index_columns[i + n_keys] = NULL;
15765 if ((error = mrn_add_index_param(tmp_share, &key_info[i], i + n_keys)))
15766 {
15767 break;
15768 }
15769 if ((error = storage_create_index(table, mapper.table_name(), grn_table,
15770 tmp_share, &key_info[i], index_tables,
15771 index_columns, i + n_keys)))
15772 {
15773 break;
15774 }
15775 if (
15776 KEY_N_KEY_PARTS(&(key_info[i])) == 1 &&
15777 (key_info[i].flags & HA_NOSAME) &&
15778 grn_table_size(ctx, grn_table) !=
15779 grn_table_size(ctx, index_tables[i + n_keys])
15780 ) {
15781 error = HA_ERR_FOUND_DUPP_UNIQUE;
15782 i++;
15783 break;
15784 }
15785 if (
15786 KEY_N_KEY_PARTS(&(key_info[i])) != 1 &&
15787 !(key_info[i].flags & HA_FULLTEXT)
15788 ) {
15789 mrn_set_bitmap_by_key(table->read_set, &key_info[i]);
15790 have_multiple_column_index = true;
15791 }
15792 }
15793 if (!error && have_multiple_column_index)
15794 {
15795 error = storage_add_index_multiple_columns(key_info, num_of_keys,
15796 index_tables + n_keys,
15797 index_columns + n_keys, false);
15798 }
15799 bitmap_set_all(table->read_set);
15800 if (error)
15801 {
15802 for (uint j = 0; j < i; j++) {
15803 if (index_tables[j + n_keys])
15804 {
15805 grn_obj_remove(ctx, index_columns[j + n_keys]);
15806 grn_obj_remove(ctx, index_tables[j + n_keys]);
15807 }
15808 }
15809 }
15810#ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15811 else {
15812 *add = new handler_add_index(table_arg, key_info, num_of_keys);
15813 }
15814#endif
15815 mrn_free_share_alloc(tmp_share);
15816 my_free(tmp_share);
15817 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables);
15818 MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_columns);
15819 DBUG_RETURN(error);
15820}
15821#ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15822int ha_mroonga::add_index(TABLE *table_arg, KEY *key_info,
15823 uint num_of_keys, handler_add_index **add)
15824{
15825 MRN_DBUG_ENTER_METHOD();
15826 int error;
15827 if (share->wrapper_mode)
15828 {
15829 error = wrapper_add_index(table_arg, key_info, num_of_keys, add);
15830 } else {
15831 error = storage_add_index(table_arg, key_info, num_of_keys, add);
15832 }
15833 DBUG_RETURN(error);
15834}
15835#else
15836int ha_mroonga::add_index(TABLE *table_arg, KEY *key_info,
15837 uint num_of_keys)
15838{
15839 MRN_DBUG_ENTER_METHOD();
15840 int error;
15841 if (share->wrapper_mode)
15842 {
15843 error = wrapper_add_index(table_arg, key_info, num_of_keys);
15844 } else {
15845 error = storage_add_index(table_arg, key_info, num_of_keys);
15846 }
15847 DBUG_RETURN(error);
15848}
15849#endif
15850
15851#ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX
15852int ha_mroonga::wrapper_final_add_index(handler_add_index *add, bool commit)
15853{
15854 int error = 0;
15855 MRN_DBUG_ENTER_METHOD();
15856 if (hnd_add_index)
15857 {
15858 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15859 MRN_SET_WRAP_TABLE_KEY(this, table);
15860 error = wrap_handler->final_add_index(hnd_add_index, commit);
15861 MRN_SET_BASE_SHARE_KEY(share, table->s);
15862 MRN_SET_BASE_TABLE_KEY(this, table);
15863 }
15864 if (add)
15865 {
15866 delete add;
15867 }
15868 DBUG_RETURN(error);
15869}
15870
15871int ha_mroonga::storage_final_add_index(handler_add_index *add, bool commit)
15872{
15873 MRN_DBUG_ENTER_METHOD();
15874 if (add)
15875 {
15876 delete add;
15877 }
15878 DBUG_RETURN(0);
15879}
15880
15881int ha_mroonga::final_add_index(handler_add_index *add, bool commit)
15882{
15883 MRN_DBUG_ENTER_METHOD();
15884 int error;
15885 if (share->wrapper_mode)
15886 {
15887 error = wrapper_final_add_index(add, commit);
15888 } else {
15889 error = storage_final_add_index(add, commit);
15890 }
15891 DBUG_RETURN(error);
15892}
15893#endif
15894
15895int ha_mroonga::wrapper_prepare_drop_index(TABLE *table_arg, uint *key_num,
15896 uint num_of_keys)
15897{
15898 int res = 0;
15899 uint i, j;
15900 KEY *key_info = table_share->key_info;
15901 MRN_DBUG_ENTER_METHOD();
15902 res = mrn_change_encoding(ctx, system_charset_info);
15903 if (res)
15904 DBUG_RETURN(res);
15905
15906 MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(uint, wrap_key_num, num_of_keys);
15907 for (i = 0, j = 0; i < num_of_keys; i++) {
15908 uint key_index = key_num[i];
15909 if (!(key_info[key_index].flags & HA_FULLTEXT) &&
15910 !mrn_is_geo_key(&key_info[key_index])) {
15911 wrap_key_num[j] = share->wrap_key_nr[key_index];
15912 j++;
15913 continue;
15914 }
15915
15916 res = drop_index(share, key_index);
15917 if (res)
15918 DBUG_RETURN(res);
15919 grn_index_tables[key_index] = NULL;
15920 grn_index_columns[key_index] = NULL;
15921 }
15922 if (j)
15923 {
15924 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15925 MRN_SET_WRAP_TABLE_KEY(this, table);
15926 res = wrap_handler->prepare_drop_index(table_arg, wrap_key_num, j);
15927 MRN_SET_BASE_SHARE_KEY(share, table->s);
15928 MRN_SET_BASE_TABLE_KEY(this, table);
15929 }
15930 MRN_FREE_VARIABLE_LENGTH_ARRAYS(wrap_key_num);
15931 DBUG_RETURN(res);
15932}
15933
15934int ha_mroonga::storage_prepare_drop_index(TABLE *table_arg, uint *key_num,
15935 uint num_of_keys)
15936{
15937 int error;
15938 uint i;
15939 MRN_DBUG_ENTER_METHOD();
15940 error = mrn_change_encoding(ctx, system_charset_info);
15941 if (error)
15942 DBUG_RETURN(error);
15943
15944 for (i = 0; i < num_of_keys; i++) {
15945 uint key_index = key_num[i];
15946 error = drop_index(share, key_index);
15947 if (error)
15948 break;
15949 grn_index_tables[key_index] = NULL;
15950 grn_index_columns[key_index] = NULL;
15951 }
15952 DBUG_RETURN(error);
15953}
15954
15955int ha_mroonga::prepare_drop_index(TABLE *table_arg, uint *key_num,
15956 uint num_of_keys)
15957{
15958 MRN_DBUG_ENTER_METHOD();
15959 int res;
15960 if (share->wrapper_mode)
15961 {
15962 res = wrapper_prepare_drop_index(table_arg, key_num, num_of_keys);
15963 } else {
15964 res = storage_prepare_drop_index(table_arg, key_num, num_of_keys);
15965 }
15966 DBUG_RETURN(res);
15967}
15968
15969int ha_mroonga::wrapper_final_drop_index(TABLE *table_arg)
15970{
15971 uint res;
15972 MRN_DBUG_ENTER_METHOD();
15973 MRN_SET_WRAP_SHARE_KEY(share, table->s);
15974 MRN_SET_WRAP_TABLE_KEY(this, table);
15975 res = wrap_handler->final_drop_index(table_arg);
15976 MRN_SET_BASE_SHARE_KEY(share, table->s);
15977 MRN_SET_BASE_TABLE_KEY(this, table);
15978 DBUG_RETURN(res);
15979}
15980
15981int ha_mroonga::storage_final_drop_index(TABLE *table_arg)
15982{
15983 MRN_DBUG_ENTER_METHOD();
15984 DBUG_RETURN(0);
15985}
15986
15987int ha_mroonga::final_drop_index(TABLE *table_arg)
15988{
15989 MRN_DBUG_ENTER_METHOD();
15990 uint res;
15991 if (share->wrapper_mode)
15992 {
15993 res = wrapper_final_drop_index(table_arg);
15994 } else {
15995 res = storage_final_drop_index(table_arg);
15996 }
15997 DBUG_RETURN(res);
15998}
15999#endif
16000
16001int ha_mroonga::wrapper_update_auto_increment()
16002{
16003 int res;
16004 MRN_DBUG_ENTER_METHOD();
16005 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16006 MRN_SET_WRAP_TABLE_KEY(this, table);
16007 res = wrap_handler->update_auto_increment();
16008 MRN_SET_BASE_SHARE_KEY(share, table->s);
16009 MRN_SET_BASE_TABLE_KEY(this, table);
16010 DBUG_RETURN(res);
16011}
16012
16013int ha_mroonga::storage_update_auto_increment()
16014{
16015 MRN_DBUG_ENTER_METHOD();
16016 int res = handler::update_auto_increment();
16017 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
16018 table->next_number_field->val_int()));
16019 DBUG_RETURN(res);
16020}
16021
16022int ha_mroonga::update_auto_increment()
16023{
16024 MRN_DBUG_ENTER_METHOD();
16025 int res;
16026 if (share->wrapper_mode)
16027 {
16028 res = wrapper_update_auto_increment();
16029 } else {
16030 res = storage_update_auto_increment();
16031 }
16032 DBUG_RETURN(res);
16033}
16034
16035void ha_mroonga::wrapper_set_next_insert_id(ulonglong id)
16036{
16037 MRN_DBUG_ENTER_METHOD();
16038 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16039 MRN_SET_WRAP_TABLE_KEY(this, table);
16040 wrap_handler->set_next_insert_id(id);
16041 MRN_SET_BASE_SHARE_KEY(share, table->s);
16042 MRN_SET_BASE_TABLE_KEY(this, table);
16043 DBUG_VOID_RETURN;
16044}
16045
16046void ha_mroonga::storage_set_next_insert_id(ulonglong id)
16047{
16048 MRN_DBUG_ENTER_METHOD();
16049 handler::set_next_insert_id(id);
16050 DBUG_VOID_RETURN;
16051}
16052
16053void ha_mroonga::set_next_insert_id(ulonglong id)
16054{
16055 MRN_DBUG_ENTER_METHOD();
16056 if (share->wrapper_mode)
16057 {
16058 wrapper_set_next_insert_id(id);
16059 } else {
16060 storage_set_next_insert_id(id);
16061 }
16062 DBUG_VOID_RETURN;
16063}
16064
16065void ha_mroonga::wrapper_get_auto_increment(ulonglong offset,
16066 ulonglong increment,
16067 ulonglong nb_desired_values,
16068 ulonglong *first_value,
16069 ulonglong *nb_reserved_values)
16070{
16071 MRN_DBUG_ENTER_METHOD();
16072 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16073 MRN_SET_WRAP_TABLE_KEY(this, table);
16074 wrap_handler->get_auto_increment(offset, increment, nb_desired_values,
16075 first_value, nb_reserved_values);
16076 MRN_SET_BASE_SHARE_KEY(share, table->s);
16077 MRN_SET_BASE_TABLE_KEY(this, table);
16078 DBUG_VOID_RETURN;
16079}
16080
16081void ha_mroonga::storage_get_auto_increment(ulonglong offset,
16082 ulonglong increment,
16083 ulonglong nb_desired_values,
16084 ulonglong *first_value,
16085 ulonglong *nb_reserved_values)
16086{
16087 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
16088 MRN_DBUG_ENTER_METHOD();
16089 if (table->found_next_number_field &&
16090 !table->s->next_number_keypart) {
16091 if (long_term_share->auto_inc_inited) {
16092 *first_value = long_term_share->auto_inc_value;
16093 DBUG_PRINT("info", ("mroonga: *first_value(auto_inc_value)=%llu",
16094 *first_value));
16095 *nb_reserved_values = UINT_MAX64;
16096 } else {
16097 handler::get_auto_increment(offset, increment, nb_desired_values,
16098 first_value, nb_reserved_values);
16099 long_term_share->auto_inc_value = *first_value;
16100 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
16101 long_term_share->auto_inc_value));
16102 long_term_share->auto_inc_inited = true;
16103 }
16104 } else {
16105 handler::get_auto_increment(offset, increment, nb_desired_values,
16106 first_value, nb_reserved_values);
16107 }
16108 DBUG_VOID_RETURN;
16109}
16110
16111void ha_mroonga::get_auto_increment(ulonglong offset, ulonglong increment,
16112 ulonglong nb_desired_values,
16113 ulonglong *first_value,
16114 ulonglong *nb_reserved_values)
16115{
16116 MRN_DBUG_ENTER_METHOD();
16117 if (share->wrapper_mode)
16118 {
16119 wrapper_get_auto_increment(offset, increment, nb_desired_values,
16120 first_value, nb_reserved_values);
16121 } else {
16122 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
16123 mrn::Lock lock(&long_term_share->auto_inc_mutex);
16124 storage_get_auto_increment(offset, increment, nb_desired_values,
16125 first_value, nb_reserved_values);
16126 long_term_share->auto_inc_value += nb_desired_values * increment;
16127 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
16128 long_term_share->auto_inc_value));
16129 }
16130 DBUG_VOID_RETURN;
16131}
16132
16133void ha_mroonga::wrapper_restore_auto_increment(ulonglong prev_insert_id)
16134{
16135 MRN_DBUG_ENTER_METHOD();
16136 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16137 MRN_SET_WRAP_TABLE_KEY(this, table);
16138 wrap_handler->restore_auto_increment(prev_insert_id);
16139 MRN_SET_BASE_SHARE_KEY(share, table->s);
16140 MRN_SET_BASE_TABLE_KEY(this, table);
16141 DBUG_VOID_RETURN;
16142}
16143
16144void ha_mroonga::storage_restore_auto_increment(ulonglong prev_insert_id)
16145{
16146 MRN_DBUG_ENTER_METHOD();
16147 handler::restore_auto_increment(prev_insert_id);
16148 DBUG_VOID_RETURN;
16149}
16150
16151void ha_mroonga::restore_auto_increment(ulonglong prev_insert_id)
16152{
16153 MRN_DBUG_ENTER_METHOD();
16154 if (share->wrapper_mode)
16155 {
16156 wrapper_restore_auto_increment(prev_insert_id);
16157 } else {
16158 storage_restore_auto_increment(prev_insert_id);
16159 }
16160 DBUG_VOID_RETURN;
16161}
16162
16163void ha_mroonga::wrapper_release_auto_increment()
16164{
16165 MRN_DBUG_ENTER_METHOD();
16166 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16167 MRN_SET_WRAP_TABLE_KEY(this, table);
16168 wrap_handler->ha_release_auto_increment();
16169 MRN_SET_BASE_SHARE_KEY(share, table->s);
16170 MRN_SET_BASE_TABLE_KEY(this, table);
16171 DBUG_VOID_RETURN;
16172}
16173
16174void ha_mroonga::storage_release_auto_increment()
16175{
16176 MRN_DBUG_ENTER_METHOD();
16177 DBUG_VOID_RETURN;
16178}
16179
16180void ha_mroonga::release_auto_increment()
16181{
16182 MRN_DBUG_ENTER_METHOD();
16183 if (share->wrapper_mode)
16184 {
16185 wrapper_release_auto_increment();
16186 } else {
16187 storage_release_auto_increment();
16188 }
16189 DBUG_VOID_RETURN;
16190}
16191
16192int ha_mroonga::wrapper_check_for_upgrade(HA_CHECK_OPT *check_opt)
16193{
16194 MRN_DBUG_ENTER_METHOD();
16195 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16196 MRN_SET_WRAP_TABLE_KEY(this, table);
16197 int error = wrap_handler->ha_check_for_upgrade(check_opt);
16198 MRN_SET_BASE_SHARE_KEY(share, table->s);
16199 MRN_SET_BASE_TABLE_KEY(this, table);
16200 DBUG_RETURN(error);
16201}
16202
16203int ha_mroonga::storage_check_for_upgrade(HA_CHECK_OPT *check_opt)
16204{
16205 MRN_DBUG_ENTER_METHOD();
16206 for (uint i = 0; i < table->s->fields; ++i) {
16207 grn_obj *column = grn_columns[i];
16208 if (!column) {
16209 continue;
16210 }
16211 Field *field = table->field[i];
16212 grn_id column_range = grn_obj_get_range(ctx, column);
16213 switch (field->real_type()) {
16214 case MYSQL_TYPE_ENUM:
16215 if (column_range != GRN_DB_UINT16) {
16216 DBUG_RETURN(HA_ADMIN_NEEDS_ALTER);
16217 }
16218 break;
16219 case MYSQL_TYPE_SET:
16220 if (column_range != GRN_DB_UINT64) {
16221 DBUG_RETURN(HA_ADMIN_NEEDS_ALTER);
16222 }
16223 break;
16224 default:
16225 break;
16226 }
16227 }
16228 DBUG_RETURN(HA_ADMIN_OK);
16229}
16230
16231int ha_mroonga::check_for_upgrade(HA_CHECK_OPT *check_opt)
16232{
16233 MRN_DBUG_ENTER_METHOD();
16234 int error;
16235 if (share->wrapper_mode) {
16236 error = wrapper_check_for_upgrade(check_opt);
16237 } else {
16238 error = storage_check_for_upgrade(check_opt);
16239 }
16240 DBUG_RETURN(error);
16241}
16242
16243#ifdef MRN_HANDLER_HAVE_RESET_AUTO_INCREMENT
16244int ha_mroonga::wrapper_reset_auto_increment(ulonglong value)
16245{
16246 int res;
16247 MRN_DBUG_ENTER_METHOD();
16248 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16249 MRN_SET_WRAP_TABLE_KEY(this, table);
16250 res = wrap_handler->ha_reset_auto_increment(value);
16251 MRN_SET_BASE_SHARE_KEY(share, table->s);
16252 MRN_SET_BASE_TABLE_KEY(this, table);
16253 DBUG_RETURN(res);
16254}
16255
16256int ha_mroonga::storage_reset_auto_increment(ulonglong value)
16257{
16258 MRN_LONG_TERM_SHARE *long_term_share = share->long_term_share;
16259 MRN_DBUG_ENTER_METHOD();
16260 mrn::Lock lock(&long_term_share->auto_inc_mutex);
16261 long_term_share->auto_inc_value = value;
16262 DBUG_PRINT("info", ("mroonga: auto_inc_value=%llu",
16263 long_term_share->auto_inc_value));
16264 long_term_share->auto_inc_inited = true;
16265 DBUG_RETURN(0);
16266}
16267
16268int ha_mroonga::reset_auto_increment(ulonglong value)
16269{
16270 MRN_DBUG_ENTER_METHOD();
16271 int res;
16272 if (share->wrapper_mode)
16273 {
16274 res = wrapper_reset_auto_increment(value);
16275 } else {
16276 res = storage_reset_auto_increment(value);
16277 }
16278 DBUG_RETURN(res);
16279}
16280#endif
16281
16282void ha_mroonga::set_pk_bitmap()
16283{
16284 MRN_DBUG_ENTER_METHOD();
16285 KEY *key_info = &(table->key_info[table_share->primary_key]);
16286 uint j;
16287 for (j = 0; j < KEY_N_KEY_PARTS(key_info); j++) {
16288 Field *field = key_info->key_part[j].field;
16289 bitmap_set_bit(table->read_set, field->field_index);
16290 }
16291 DBUG_VOID_RETURN;
16292}
16293
16294bool ha_mroonga::wrapper_was_semi_consistent_read()
16295{
16296 bool res;
16297 MRN_DBUG_ENTER_METHOD();
16298 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16299 MRN_SET_WRAP_TABLE_KEY(this, table);
16300 res = wrap_handler->was_semi_consistent_read();
16301 MRN_SET_BASE_SHARE_KEY(share, table->s);
16302 MRN_SET_BASE_TABLE_KEY(this, table);
16303 DBUG_RETURN(res);
16304}
16305
16306bool ha_mroonga::storage_was_semi_consistent_read()
16307{
16308 bool res;
16309 MRN_DBUG_ENTER_METHOD();
16310 res = handler::was_semi_consistent_read();
16311 DBUG_RETURN(res);
16312}
16313
16314bool ha_mroonga::was_semi_consistent_read()
16315{
16316 bool res;
16317 MRN_DBUG_ENTER_METHOD();
16318 if (share->wrapper_mode)
16319 {
16320 res = wrapper_was_semi_consistent_read();
16321 } else {
16322 res = storage_was_semi_consistent_read();
16323 }
16324 DBUG_RETURN(res);
16325}
16326
16327void ha_mroonga::wrapper_try_semi_consistent_read(bool yes)
16328{
16329 MRN_DBUG_ENTER_METHOD();
16330 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16331 MRN_SET_WRAP_TABLE_KEY(this, table);
16332 wrap_handler->try_semi_consistent_read(yes);
16333 MRN_SET_BASE_SHARE_KEY(share, table->s);
16334 MRN_SET_BASE_TABLE_KEY(this, table);
16335 DBUG_VOID_RETURN;
16336}
16337
16338void ha_mroonga::storage_try_semi_consistent_read(bool yes)
16339{
16340 MRN_DBUG_ENTER_METHOD();
16341 handler::try_semi_consistent_read(yes);
16342 DBUG_VOID_RETURN;
16343}
16344
16345void ha_mroonga::try_semi_consistent_read(bool yes)
16346{
16347 MRN_DBUG_ENTER_METHOD();
16348 if (share->wrapper_mode)
16349 {
16350 wrapper_try_semi_consistent_read(yes);
16351 } else {
16352 storage_try_semi_consistent_read(yes);
16353 }
16354 DBUG_VOID_RETURN;
16355}
16356
16357void ha_mroonga::wrapper_unlock_row()
16358{
16359 MRN_DBUG_ENTER_METHOD();
16360 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16361 MRN_SET_WRAP_TABLE_KEY(this, table);
16362 wrap_handler->unlock_row();
16363 MRN_SET_BASE_SHARE_KEY(share, table->s);
16364 MRN_SET_BASE_TABLE_KEY(this, table);
16365 DBUG_VOID_RETURN;
16366}
16367
16368void ha_mroonga::storage_unlock_row()
16369{
16370 MRN_DBUG_ENTER_METHOD();
16371 handler::unlock_row();
16372 DBUG_VOID_RETURN;
16373}
16374
16375void ha_mroonga::unlock_row()
16376{
16377 MRN_DBUG_ENTER_METHOD();
16378 if (share->wrapper_mode)
16379 {
16380 wrapper_unlock_row();
16381 } else {
16382 storage_unlock_row();
16383 }
16384 DBUG_VOID_RETURN;
16385}
16386
16387int ha_mroonga::wrapper_start_stmt(THD *thd, thr_lock_type lock_type)
16388{
16389 int res;
16390 MRN_DBUG_ENTER_METHOD();
16391 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16392 MRN_SET_WRAP_TABLE_KEY(this, table);
16393 res = wrap_handler->start_stmt(thd, lock_type);
16394 MRN_SET_BASE_SHARE_KEY(share, table->s);
16395 MRN_SET_BASE_TABLE_KEY(this, table);
16396 DBUG_RETURN(res);
16397}
16398
16399int ha_mroonga::storage_start_stmt(THD *thd, thr_lock_type lock_type)
16400{
16401 int res;
16402 MRN_DBUG_ENTER_METHOD();
16403 res = handler::start_stmt(thd, lock_type);
16404 DBUG_RETURN(res);
16405}
16406
16407int ha_mroonga::start_stmt(THD *thd, thr_lock_type lock_type)
16408{
16409 int res;
16410 MRN_DBUG_ENTER_METHOD();
16411 if (share->wrapper_mode)
16412 {
16413 res = wrapper_start_stmt(thd, lock_type);
16414 } else {
16415 res = storage_start_stmt(thd, lock_type);
16416 }
16417 DBUG_RETURN(res);
16418}
16419
16420void ha_mroonga::wrapper_change_table_ptr(TABLE *table_arg,
16421 TABLE_SHARE *share_arg)
16422{
16423 MRN_DBUG_ENTER_METHOD();
16424 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16425 MRN_SET_WRAP_TABLE_KEY(this, table);
16426 wrap_handler->change_table_ptr(table_arg, share->wrap_table_share);
16427 MRN_SET_BASE_SHARE_KEY(share, table->s);
16428 MRN_SET_BASE_TABLE_KEY(this, table);
16429 DBUG_VOID_RETURN;
16430}
16431
16432void ha_mroonga::storage_change_table_ptr(TABLE *table_arg,
16433 TABLE_SHARE *share_arg)
16434{
16435 MRN_DBUG_ENTER_METHOD();
16436 DBUG_VOID_RETURN;
16437}
16438
16439void ha_mroonga::change_table_ptr(TABLE *table_arg, TABLE_SHARE *share_arg)
16440{
16441 MRN_DBUG_ENTER_METHOD();
16442 handler::change_table_ptr(table_arg, share_arg);
16443 if (share && share->wrapper_mode)
16444 {
16445 wrapper_change_table_ptr(table_arg, share_arg);
16446 } else {
16447 storage_change_table_ptr(table_arg, share_arg);
16448 }
16449 DBUG_VOID_RETURN;
16450}
16451
16452bool ha_mroonga::wrapper_primary_key_is_clustered()
16453{
16454 MRN_DBUG_ENTER_METHOD();
16455 bool is_clustered;
16456 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16457 MRN_SET_WRAP_TABLE_KEY(this, table);
16458 is_clustered = wrap_handler->primary_key_is_clustered();
16459 MRN_SET_BASE_SHARE_KEY(share, table->s);
16460 MRN_SET_BASE_TABLE_KEY(this, table);
16461 DBUG_RETURN(is_clustered);
16462}
16463
16464bool ha_mroonga::storage_primary_key_is_clustered()
16465{
16466 MRN_DBUG_ENTER_METHOD();
16467 bool is_clustered = handler::primary_key_is_clustered();
16468 DBUG_RETURN(is_clustered);
16469}
16470
16471bool ha_mroonga::primary_key_is_clustered()
16472{
16473 MRN_DBUG_ENTER_METHOD();
16474 bool is_clustered;
16475 if (share && share->wrapper_mode)
16476 {
16477 is_clustered = wrapper_primary_key_is_clustered();
16478 } else {
16479 is_clustered = storage_primary_key_is_clustered();
16480 }
16481 DBUG_RETURN(is_clustered);
16482}
16483
16484bool ha_mroonga::wrapper_is_fk_defined_on_table_or_index(uint index)
16485{
16486 MRN_DBUG_ENTER_METHOD();
16487 bool res;
16488 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16489 MRN_SET_WRAP_TABLE_KEY(this, table);
16490 res = wrap_handler->is_fk_defined_on_table_or_index(index);
16491 MRN_SET_BASE_SHARE_KEY(share, table->s);
16492 MRN_SET_BASE_TABLE_KEY(this, table);
16493 DBUG_RETURN(res);
16494}
16495
16496bool ha_mroonga::storage_is_fk_defined_on_table_or_index(uint index)
16497{
16498 MRN_DBUG_ENTER_METHOD();
16499 bool res = handler::is_fk_defined_on_table_or_index(index);
16500 DBUG_RETURN(res);
16501}
16502
16503bool ha_mroonga::is_fk_defined_on_table_or_index(uint index)
16504{
16505 MRN_DBUG_ENTER_METHOD();
16506 bool res;
16507 if (share->wrapper_mode)
16508 {
16509 res = wrapper_is_fk_defined_on_table_or_index(index);
16510 } else {
16511 res = storage_is_fk_defined_on_table_or_index(index);
16512 }
16513 DBUG_RETURN(res);
16514}
16515
16516char *ha_mroonga::wrapper_get_foreign_key_create_info()
16517{
16518 MRN_DBUG_ENTER_METHOD();
16519 char *res;
16520 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16521 MRN_SET_WRAP_TABLE_KEY(this, table);
16522 res = wrap_handler->get_foreign_key_create_info();
16523 MRN_SET_BASE_SHARE_KEY(share, table->s);
16524 MRN_SET_BASE_TABLE_KEY(this, table);
16525 DBUG_RETURN(res);
16526}
16527
16528#ifdef MRN_SUPPORT_FOREIGN_KEYS
16529char *ha_mroonga::storage_get_foreign_key_create_info()
16530{
16531 int error;
16532 uint i;
16533 grn_obj *column;
16534 uint n_columns = table_share->fields;
16535 char create_info_buff[2048], *create_info;
16536 String create_info_str(create_info_buff, sizeof(create_info_buff),
16537 system_charset_info);
16538 MRN_DBUG_ENTER_METHOD();
16539 create_info_str.length(0);
16540 for (i = 0; i < n_columns; ++i) {
16541 Field *field = table_share->field[i];
16542
16543 if (!is_foreign_key_field(table_share->table_name.str,
16544 field->field_name.str)) {
16545 continue;
16546 }
16547
16548 mrn::ColumnName column_name(field->field_name);
16549 column = grn_obj_column(ctx,
16550 grn_table,
16551 column_name.c_str(),
16552 column_name.length());
16553 if (!column) {
16554 continue;
16555 }
16556 grn_id ref_table_id = grn_obj_get_range(ctx, column);
16557 grn_obj *ref_table = grn_ctx_at(ctx, ref_table_id);
16558 char ref_table_buff[NAME_LEN + 1];
16559 int ref_table_name_length = grn_obj_name(ctx, ref_table, ref_table_buff,
16560 NAME_LEN);
16561 ref_table_buff[ref_table_name_length] = '\0';
16562
16563 if (create_info_str.reserve(15)) {
16564 DBUG_RETURN(NULL);
16565 }
16566 create_info_str.q_append(",\n CONSTRAINT ", 15);
16567 append_identifier(ha_thd(),
16568 &create_info_str,
16569 column_name.c_str(),
16570 column_name.length());
16571 if (create_info_str.reserve(14)) {
16572 DBUG_RETURN(NULL);
16573 }
16574 create_info_str.q_append(" FOREIGN KEY (", 14);
16575 append_identifier(ha_thd(),
16576 &create_info_str,
16577 column_name.c_str(),
16578 column_name.length());
16579 if (create_info_str.reserve(13)) {
16580 DBUG_RETURN(NULL);
16581 }
16582 create_info_str.q_append(") REFERENCES ", 13);
16583 append_identifier(ha_thd(), &create_info_str, table_share->db.str,
16584 table_share->db.length);
16585 if (create_info_str.reserve(1)) {
16586 DBUG_RETURN(NULL);
16587 }
16588 create_info_str.q_append(".", 1);
16589 append_identifier(ha_thd(), &create_info_str, ref_table_buff,
16590 ref_table_name_length);
16591 if (create_info_str.reserve(2)) {
16592 DBUG_RETURN(NULL);
16593 }
16594 create_info_str.q_append(" (", 2);
16595
16596 char ref_path[FN_REFLEN + 1];
16597 TABLE_LIST table_list;
16598 TABLE_SHARE *tmp_ref_table_share;
16599 build_table_filename(ref_path, sizeof(ref_path) - 1,
16600 table_share->db.str, ref_table_buff, "", 0);
16601 DBUG_PRINT("info", ("mroonga: ref_path=%s", ref_path));
16602
16603 LEX_CSTRING table_name= { ref_table_buff, (size_t) ref_table_name_length };
16604 table_list.init_one_table(&table_share->db, &table_name, 0, TL_WRITE);
16605 mrn_open_mutex_lock(table_share);
16606 tmp_ref_table_share =
16607 mrn_create_tmp_table_share(&table_list, ref_path, &error);
16608 mrn_open_mutex_unlock(table_share);
16609 if (!tmp_ref_table_share) {
16610 DBUG_RETURN(NULL);
16611 }
16612 uint ref_pkey_nr = tmp_ref_table_share->primary_key;
16613 KEY *ref_key_info = &tmp_ref_table_share->key_info[ref_pkey_nr];
16614 Field *ref_field = &ref_key_info->key_part->field[0];
16615 append_identifier(ha_thd(), &create_info_str, ref_field->field_name.str,
16616 ref_field->field_name.length);
16617 mrn_open_mutex_lock(table_share);
16618 mrn_free_tmp_table_share(tmp_ref_table_share);
16619 mrn_open_mutex_unlock(table_share);
16620 if (create_info_str.reserve(39)) {
16621 DBUG_RETURN(NULL);
16622 }
16623 create_info_str.q_append(") ON DELETE RESTRICT ON UPDATE RESTRICT", 39);
16624 }
16625 if (!(create_info = (char *) mrn_my_malloc(create_info_str.length() + 1,
16626 MYF(MY_WME)))) {
16627 DBUG_RETURN(NULL);
16628 }
16629 memcpy(create_info, create_info_str.ptr(), create_info_str.length());
16630 create_info[create_info_str.length()] = '\0';
16631 DBUG_RETURN(create_info);
16632}
16633#else
16634char *ha_mroonga::storage_get_foreign_key_create_info()
16635{
16636 MRN_DBUG_ENTER_METHOD();
16637 char *res = handler::get_foreign_key_create_info();
16638 DBUG_RETURN(res);
16639}
16640#endif
16641
16642char *ha_mroonga::get_foreign_key_create_info()
16643{
16644 MRN_DBUG_ENTER_METHOD();
16645 char *res;
16646 if (share->wrapper_mode)
16647 {
16648 res = wrapper_get_foreign_key_create_info();
16649 } else {
16650 res = storage_get_foreign_key_create_info();
16651 }
16652 DBUG_RETURN(res);
16653}
16654
16655#ifdef MRN_HANDLER_HAVE_GET_TABLESPACE_NAME
16656char *ha_mroonga::wrapper_get_tablespace_name(THD *thd, char *name,
16657 uint name_len)
16658{
16659 MRN_DBUG_ENTER_METHOD();
16660 char *res;
16661 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16662 MRN_SET_WRAP_TABLE_KEY(this, table);
16663 res = wrap_handler->get_tablespace_name(thd, name, name_len);
16664 MRN_SET_BASE_SHARE_KEY(share, table->s);
16665 MRN_SET_BASE_TABLE_KEY(this, table);
16666 DBUG_RETURN(res);
16667}
16668
16669char *ha_mroonga::storage_get_tablespace_name(THD *thd, char *name,
16670 uint name_len)
16671{
16672 MRN_DBUG_ENTER_METHOD();
16673 char *res = handler::get_tablespace_name(thd, name, name_len);
16674 DBUG_RETURN(res);
16675}
16676
16677char *ha_mroonga::get_tablespace_name(THD *thd, char *name, uint name_len)
16678{
16679 MRN_DBUG_ENTER_METHOD();
16680 char *res;
16681 if (share->wrapper_mode)
16682 {
16683 res = wrapper_get_tablespace_name(thd, name, name_len);
16684 } else {
16685 res = storage_get_tablespace_name(thd, name, name_len);
16686 }
16687 DBUG_RETURN(res);
16688}
16689#endif
16690
16691bool ha_mroonga::wrapper_can_switch_engines()
16692{
16693 MRN_DBUG_ENTER_METHOD();
16694 bool res;
16695 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16696 MRN_SET_WRAP_TABLE_KEY(this, table);
16697 res = wrap_handler->can_switch_engines();
16698 MRN_SET_BASE_SHARE_KEY(share, table->s);
16699 MRN_SET_BASE_TABLE_KEY(this, table);
16700 DBUG_RETURN(res);
16701}
16702
16703bool ha_mroonga::storage_can_switch_engines()
16704{
16705 MRN_DBUG_ENTER_METHOD();
16706 bool res = handler::can_switch_engines();
16707 DBUG_RETURN(res);
16708}
16709
16710bool ha_mroonga::can_switch_engines()
16711{
16712 MRN_DBUG_ENTER_METHOD();
16713 bool res;
16714 if (share->wrapper_mode)
16715 {
16716 res = wrapper_can_switch_engines();
16717 } else {
16718 res = storage_can_switch_engines();
16719 }
16720 DBUG_RETURN(res);
16721}
16722
16723int ha_mroonga::wrapper_get_foreign_key_list(THD *thd,
16724 List<FOREIGN_KEY_INFO> *f_key_list)
16725{
16726 MRN_DBUG_ENTER_METHOD();
16727 int res;
16728 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16729 MRN_SET_WRAP_TABLE_KEY(this, table);
16730 res = wrap_handler->get_foreign_key_list(thd, f_key_list);
16731 MRN_SET_BASE_SHARE_KEY(share, table->s);
16732 MRN_SET_BASE_TABLE_KEY(this, table);
16733 DBUG_RETURN(res);
16734}
16735
16736#ifdef MRN_SUPPORT_FOREIGN_KEYS
16737int ha_mroonga::storage_get_foreign_key_list(THD *thd,
16738 List<FOREIGN_KEY_INFO> *f_key_list)
16739{
16740 int error;
16741 uint i;
16742 grn_obj *column;
16743 uint n_columns = table_share->fields;
16744 MRN_DBUG_ENTER_METHOD();
16745 for (i = 0; i < n_columns; ++i) {
16746 Field *field = table_share->field[i];
16747
16748 if (!is_foreign_key_field(table_share->table_name.str,
16749 field->field_name.str)) {
16750 continue;
16751 }
16752
16753 mrn::ColumnName column_name(field->field_name);
16754 column = grn_obj_column(ctx,
16755 grn_table,
16756 column_name.c_str(),
16757 column_name.length());
16758 if (!column) {
16759 continue;
16760 }
16761 grn_id ref_table_id = grn_obj_get_range(ctx, column);
16762 grn_obj *ref_table = grn_ctx_at(ctx, ref_table_id);
16763 FOREIGN_KEY_INFO f_key_info;
16764 f_key_info.foreign_id = thd_make_lex_string(thd,
16765 NULL,
16766 column_name.c_str(),
16767 column_name.length(),
16768 TRUE);
16769 f_key_info.foreign_db = thd_make_lex_string(thd, NULL,
16770 table_share->db.str,
16771 table_share->db.length,
16772 TRUE);
16773 f_key_info.foreign_table = thd_make_lex_string(thd, NULL,
16774 table_share->table_name.str,
16775 table_share->table_name.length,
16776 TRUE);
16777 f_key_info.referenced_db = f_key_info.foreign_db;
16778
16779 char ref_table_buff[NAME_LEN + 1];
16780 int ref_table_name_length = grn_obj_name(ctx, ref_table, ref_table_buff,
16781 NAME_LEN);
16782 ref_table_buff[ref_table_name_length] = '\0';
16783 DBUG_PRINT("info", ("mroonga: ref_table_buff=%s", ref_table_buff));
16784 DBUG_PRINT("info", ("mroonga: ref_table_name_length=%d", ref_table_name_length));
16785 f_key_info.referenced_table = thd_make_lex_string(thd, NULL,
16786 ref_table_buff,
16787 ref_table_name_length,
16788 TRUE);
16789#ifdef MRN_FOREIGN_KEY_USE_METHOD_ENUM
16790 f_key_info.update_method = FK_OPTION_RESTRICT;
16791 f_key_info.delete_method = FK_OPTION_RESTRICT;
16792#else
16793 f_key_info.update_method = thd_make_lex_string(thd, NULL, "RESTRICT",
16794 8, TRUE);
16795 f_key_info.delete_method = thd_make_lex_string(thd, NULL, "RESTRICT",
16796 8, TRUE);
16797#endif
16798 f_key_info.referenced_key_name = thd_make_lex_string(thd, NULL, "PRIMARY",
16799 7, TRUE);
16800 LEX_CSTRING *field_name = thd_make_lex_string(thd,
16801 NULL,
16802 column_name.c_str(),
16803 column_name.length(),
16804 TRUE);
16805 f_key_info.foreign_fields.push_back(field_name);
16806
16807 char ref_path[FN_REFLEN + 1];
16808 TABLE_LIST table_list;
16809 TABLE_SHARE *tmp_ref_table_share;
16810 build_table_filename(ref_path, sizeof(ref_path) - 1,
16811 table_share->db.str, ref_table_buff, "", 0);
16812 DBUG_PRINT("info", ("mroonga: ref_path=%s", ref_path));
16813
16814 LEX_CSTRING table_name= { ref_table_buff, (size_t) ref_table_name_length };
16815 table_list.init_one_table(&table_share->db, &table_name, 0, TL_WRITE);
16816 mrn_open_mutex_lock(table_share);
16817 tmp_ref_table_share =
16818 mrn_create_tmp_table_share(&table_list, ref_path, &error);
16819 mrn_open_mutex_unlock(table_share);
16820 if (!tmp_ref_table_share) {
16821 DBUG_RETURN(error);
16822 }
16823 uint ref_pkey_nr = tmp_ref_table_share->primary_key;
16824 KEY *ref_key_info = &tmp_ref_table_share->key_info[ref_pkey_nr];
16825 Field *ref_field = &ref_key_info->key_part->field[0];
16826 LEX_CSTRING *ref_col_name = thd_make_lex_string(thd, NULL,
16827 ref_field->field_name.str,
16828 ref_field->field_name.length,
16829 TRUE);
16830 f_key_info.referenced_fields.push_back(ref_col_name);
16831 mrn_open_mutex_lock(table_share);
16832 mrn_free_tmp_table_share(tmp_ref_table_share);
16833 mrn_open_mutex_unlock(table_share);
16834 FOREIGN_KEY_INFO *p_f_key_info =
16835 (FOREIGN_KEY_INFO *) thd_memdup(thd, &f_key_info,
16836 sizeof(FOREIGN_KEY_INFO));
16837 if (!p_f_key_info) {
16838 DBUG_RETURN(HA_ERR_OUT_OF_MEM);
16839 }
16840 f_key_list->push_back(p_f_key_info);
16841 }
16842 DBUG_RETURN(0);
16843}
16844#else
16845int ha_mroonga::storage_get_foreign_key_list(THD *thd,
16846 List<FOREIGN_KEY_INFO> *f_key_list)
16847{
16848 MRN_DBUG_ENTER_METHOD();
16849 int res = handler::get_foreign_key_list(thd, f_key_list);
16850 DBUG_RETURN(res);
16851}
16852#endif
16853
16854int ha_mroonga::get_foreign_key_list(THD *thd,
16855 List<FOREIGN_KEY_INFO> *f_key_list)
16856{
16857 MRN_DBUG_ENTER_METHOD();
16858 int res;
16859 if (share->wrapper_mode)
16860 {
16861 res = wrapper_get_foreign_key_list(thd, f_key_list);
16862 } else {
16863 res = storage_get_foreign_key_list(thd, f_key_list);
16864 }
16865 DBUG_RETURN(res);
16866}
16867
16868int ha_mroonga::wrapper_get_parent_foreign_key_list(THD *thd,
16869 List<FOREIGN_KEY_INFO> *f_key_list)
16870{
16871 MRN_DBUG_ENTER_METHOD();
16872 int res;
16873 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16874 MRN_SET_WRAP_TABLE_KEY(this, table);
16875 res = wrap_handler->get_parent_foreign_key_list(thd, f_key_list);
16876 MRN_SET_BASE_SHARE_KEY(share, table->s);
16877 MRN_SET_BASE_TABLE_KEY(this, table);
16878 DBUG_RETURN(res);
16879}
16880
16881int ha_mroonga::storage_get_parent_foreign_key_list(THD *thd,
16882 List<FOREIGN_KEY_INFO> *f_key_list)
16883{
16884 MRN_DBUG_ENTER_METHOD();
16885 int res = handler::get_parent_foreign_key_list(thd, f_key_list);
16886 DBUG_RETURN(res);
16887}
16888
16889int ha_mroonga::get_parent_foreign_key_list(THD *thd,
16890 List<FOREIGN_KEY_INFO> *f_key_list)
16891{
16892 MRN_DBUG_ENTER_METHOD();
16893 int res;
16894 if (share->wrapper_mode)
16895 {
16896 res = wrapper_get_parent_foreign_key_list(thd, f_key_list);
16897 } else {
16898 res = storage_get_parent_foreign_key_list(thd, f_key_list);
16899 }
16900 DBUG_RETURN(res);
16901}
16902
16903uint ha_mroonga::wrapper_referenced_by_foreign_key()
16904{
16905 MRN_DBUG_ENTER_METHOD();
16906 uint res;
16907 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16908 MRN_SET_WRAP_TABLE_KEY(this, table);
16909 res = wrap_handler->referenced_by_foreign_key();
16910 MRN_SET_BASE_SHARE_KEY(share, table->s);
16911 MRN_SET_BASE_TABLE_KEY(this, table);
16912 DBUG_RETURN(res);
16913}
16914
16915uint ha_mroonga::storage_referenced_by_foreign_key()
16916{
16917 MRN_DBUG_ENTER_METHOD();
16918 uint res = handler::referenced_by_foreign_key();
16919 DBUG_RETURN(res);
16920}
16921
16922uint ha_mroonga::referenced_by_foreign_key()
16923{
16924 MRN_DBUG_ENTER_METHOD();
16925 uint res;
16926 if (share->wrapper_mode)
16927 {
16928 res = wrapper_referenced_by_foreign_key();
16929 } else {
16930 res = storage_referenced_by_foreign_key();
16931 }
16932 DBUG_RETURN(res);
16933}
16934
16935void ha_mroonga::wrapper_init_table_handle_for_HANDLER()
16936{
16937 MRN_DBUG_ENTER_METHOD();
16938 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16939 MRN_SET_WRAP_TABLE_KEY(this, table);
16940 wrap_handler->init_table_handle_for_HANDLER();
16941 MRN_SET_BASE_SHARE_KEY(share, table->s);
16942 MRN_SET_BASE_TABLE_KEY(this, table);
16943 DBUG_VOID_RETURN;
16944}
16945
16946void ha_mroonga::storage_init_table_handle_for_HANDLER()
16947{
16948 MRN_DBUG_ENTER_METHOD();
16949 handler::init_table_handle_for_HANDLER();
16950 DBUG_VOID_RETURN;
16951}
16952
16953void ha_mroonga::init_table_handle_for_HANDLER()
16954{
16955 MRN_DBUG_ENTER_METHOD();
16956 if (share->wrapper_mode)
16957 {
16958 wrapper_init_table_handle_for_HANDLER();
16959 } else {
16960 storage_init_table_handle_for_HANDLER();
16961 }
16962 DBUG_VOID_RETURN;
16963}
16964
16965void ha_mroonga::wrapper_free_foreign_key_create_info(char* str)
16966{
16967 MRN_DBUG_ENTER_METHOD();
16968 MRN_SET_WRAP_SHARE_KEY(share, table->s);
16969 MRN_SET_WRAP_TABLE_KEY(this, table);
16970 wrap_handler->free_foreign_key_create_info(str);
16971 MRN_SET_BASE_SHARE_KEY(share, table->s);
16972 MRN_SET_BASE_TABLE_KEY(this, table);
16973 DBUG_VOID_RETURN;
16974}
16975
16976#ifdef MRN_SUPPORT_FOREIGN_KEYS
16977void ha_mroonga::storage_free_foreign_key_create_info(char* str)
16978{
16979 MRN_DBUG_ENTER_METHOD();
16980 my_free(str);
16981 DBUG_VOID_RETURN;
16982}
16983#else
16984void ha_mroonga::storage_free_foreign_key_create_info(char* str)
16985{
16986 MRN_DBUG_ENTER_METHOD();
16987 handler::free_foreign_key_create_info(str);
16988 DBUG_VOID_RETURN;
16989}
16990#endif
16991
16992void ha_mroonga::free_foreign_key_create_info(char* str)
16993{
16994 MRN_DBUG_ENTER_METHOD();
16995 if (share->wrapper_mode)
16996 {
16997 wrapper_free_foreign_key_create_info(str);
16998 } else {
16999 storage_free_foreign_key_create_info(str);
17000 }
17001 DBUG_VOID_RETURN;
17002}
17003
17004#ifdef MRN_RBR_UPDATE_NEED_ALL_COLUMNS
17005bool ha_mroonga::check_written_by_row_based_binlog()
17006{
17007 MRN_DBUG_ENTER_METHOD();
17008 THD *thd = ha_thd();
17009
17010 int current_stmt_binlog_row;
17011#ifdef MRN_ROW_BASED_CHECK_IS_METHOD
17012 current_stmt_binlog_row = thd->is_current_stmt_binlog_format_row();
17013#else
17014 current_stmt_binlog_row = thd->current_stmt_binlog_row_based;
17015#endif
17016 if (!current_stmt_binlog_row) {
17017 DBUG_RETURN(false);
17018 }
17019
17020 if (table->s->tmp_table != NO_TMP_TABLE) {
17021 DBUG_RETURN(false);
17022 }
17023
17024 if (!mrn_binlog_filter->db_ok(table->s->db.str)) {
17025 DBUG_RETURN(false);
17026 }
17027
17028 if (!thd_test_options(thd, OPTION_BIN_LOG)) {
17029 DBUG_RETURN(false);
17030 }
17031
17032 if (!mysql_bin_log.is_open()) {
17033 DBUG_RETURN(false);
17034 }
17035
17036 DBUG_RETURN(true);
17037}
17038#endif
17039
17040#ifdef MRN_HAVE_HA_REBIND_PSI
17041void ha_mroonga::wrapper_unbind_psi()
17042{
17043 MRN_DBUG_ENTER_METHOD();
17044 MRN_SET_WRAP_SHARE_KEY(share, table->s);
17045 MRN_SET_WRAP_TABLE_KEY(this, table);
17046 wrap_handler->unbind_psi();
17047 MRN_SET_BASE_SHARE_KEY(share, table->s);
17048 MRN_SET_BASE_TABLE_KEY(this, table);
17049 DBUG_VOID_RETURN;
17050}
17051
17052void ha_mroonga::storage_unbind_psi()
17053{
17054 MRN_DBUG_ENTER_METHOD();
17055 DBUG_VOID_RETURN;
17056}
17057
17058void ha_mroonga::unbind_psi()
17059{
17060 MRN_DBUG_ENTER_METHOD();
17061 handler::unbind_psi();
17062 if (share->wrapper_mode)
17063 {
17064 wrapper_unbind_psi();
17065 } else {
17066 storage_unbind_psi();
17067 }
17068 DBUG_VOID_RETURN;
17069}
17070
17071void ha_mroonga::wrapper_rebind_psi()
17072{
17073 MRN_DBUG_ENTER_METHOD();
17074 MRN_SET_WRAP_SHARE_KEY(share, table->s);
17075 MRN_SET_WRAP_TABLE_KEY(this, table);
17076 wrap_handler->rebind_psi();
17077 MRN_SET_BASE_SHARE_KEY(share, table->s);
17078 MRN_SET_BASE_TABLE_KEY(this, table);
17079 DBUG_VOID_RETURN;
17080}
17081
17082void ha_mroonga::storage_rebind_psi()
17083{
17084 MRN_DBUG_ENTER_METHOD();
17085 DBUG_VOID_RETURN;
17086}
17087
17088void ha_mroonga::rebind_psi()
17089{
17090 MRN_DBUG_ENTER_METHOD();
17091 handler::rebind_psi();
17092 if (share->wrapper_mode)
17093 {
17094 wrapper_rebind_psi();
17095 } else {
17096 storage_rebind_psi();
17097 }
17098 DBUG_VOID_RETURN;
17099}
17100#endif
17101
17102my_bool ha_mroonga::wrapper_register_query_cache_table(THD *thd,
17103 const char *table_key,
17104 uint key_length,
17105 qc_engine_callback
17106 *engine_callback,
17107 ulonglong *engine_data)
17108{
17109 MRN_DBUG_ENTER_METHOD();
17110 my_bool res;
17111 MRN_SET_WRAP_SHARE_KEY(share, table->s);
17112 MRN_SET_WRAP_TABLE_KEY(this, table);
17113 res = wrap_handler->register_query_cache_table(thd,
17114 table_key,
17115 key_length,
17116 engine_callback,
17117 engine_data);
17118 MRN_SET_BASE_SHARE_KEY(share, table->s);
17119 MRN_SET_BASE_TABLE_KEY(this, table);
17120 DBUG_RETURN(res);
17121}
17122
17123my_bool ha_mroonga::storage_register_query_cache_table(THD *thd,
17124 const char *table_key,
17125 uint key_length,
17126 qc_engine_callback
17127 *engine_callback,
17128 ulonglong *engine_data)
17129{
17130 MRN_DBUG_ENTER_METHOD();
17131 my_bool res = handler::register_query_cache_table(thd,
17132 table_key,
17133 key_length,
17134 engine_callback,
17135 engine_data);
17136 DBUG_RETURN(res);
17137}
17138
17139my_bool ha_mroonga::register_query_cache_table(THD *thd,
17140 const char *table_key,
17141 uint key_length,
17142 qc_engine_callback
17143 *engine_callback,
17144 ulonglong *engine_data)
17145{
17146 MRN_DBUG_ENTER_METHOD();
17147 my_bool res;
17148 if (share->wrapper_mode)
17149 {
17150 res = wrapper_register_query_cache_table(thd,
17151 table_key,
17152 key_length,
17153 engine_callback,
17154 engine_data);
17155 } else {
17156 res = storage_register_query_cache_table(thd,
17157 table_key,
17158 key_length,
17159 engine_callback,
17160 engine_data);
17161 }
17162 DBUG_RETURN(res);
17163}
17164
17165#ifdef __cplusplus
17166}
17167#endif
17168
17169namespace mrn {
17170 namespace variables {
17171 ulonglong get_boolean_mode_syntax_flags(THD *thd) {
17172 ulonglong flags = BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT;
17173#ifdef MRN_SUPPORT_THDVAR_SET
17174 flags = THDVAR(thd, boolean_mode_syntax_flags);
17175#endif
17176 return flags;
17177 }
17178
17179 ActionOnError get_action_on_fulltext_query_error(THD *thd) {
17180 ulong action = THDVAR(thd, action_on_fulltext_query_error);
17181 return static_cast<ActionOnError>(action);
17182 }
17183 }
17184}
17185