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 |
137 | extern mysql_mutex_t LOCK_open; |
138 | # endif |
139 | # endif |
140 | static mysql_mutex_t *mrn_LOCK_open; |
141 | # define mrn_open_mutex_lock(share) mysql_mutex_lock(mrn_LOCK_open) |
142 | # define mrn_open_mutex_unlock(share) mysql_mutex_unlock(mrn_LOCK_open) |
143 | #endif |
144 | |
145 | #if MYSQL_VERSION_ID >= 50600 |
146 | # define MRN_NEED_M_LOCK_TYPE_CHECK_FOR_WRAPPER_EXTERNAL_LOCK |
147 | #endif |
148 | |
149 | #ifdef MRN_MARIADB_P |
150 | # if MYSQL_VERSION_ID >= 100200 |
151 | # define MRN_ORDER_IS_ASC(order) ((order)->direction == ORDER::ORDER_ASC) |
152 | # else |
153 | # define MRN_ORDER_IS_ASC(order) ((order)->asc) |
154 | # endif |
155 | #else |
156 | # if MYSQL_VERSION_ID >= 50603 |
157 | # define MRN_ORDER_IS_ASC(order) ((order)->direction == ORDER::ORDER_ASC) |
158 | # else |
159 | # define MRN_ORDER_IS_ASC(order) ((order)->asc) |
160 | # endif |
161 | #endif |
162 | |
163 | #define MRN_STRINGIFY(macro_or_string) MRN_STRINGIFY_ARG(macro_or_string) |
164 | #define MRN_STRINGIFY_ARG(contents) #contents |
165 | |
166 | #define MRN_PLUGIN_NAME mroonga |
167 | #define MRN_PLUGIN_NAME_STRING "Mroonga" |
168 | #define MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "Mroonga" |
169 | |
170 | #ifdef MRN_MARIADB_P |
171 | # define st_mysql_plugin st_maria_plugin |
172 | # define mrn_declare_plugin(NAME) maria_declare_plugin(NAME) |
173 | # define mrn_declare_plugin_end maria_declare_plugin_end |
174 | # define MRN_PLUGIN_LAST_VALUES MRN_VERSION, MariaDB_PLUGIN_MATURITY_STABLE |
175 | #else |
176 | # define mrn_declare_plugin(NAME) mysql_declare_plugin(NAME) |
177 | # define mrn_declare_plugin_end mysql_declare_plugin_end |
178 | # define MRN_PLUGIN_LAST_VALUES NULL, 0 |
179 | #endif |
180 | |
181 | #if MYSQL_VERSION_ID >= 100007 && defined(MRN_MARIADB_P) |
182 | # define MRN_THD_GET_AUTOINC(thd, off, inc) thd_get_autoinc(thd, off, inc) |
183 | # define MRN_GET_ERR_MSG(code) my_get_err_msg(code) |
184 | #else |
185 | # define MRN_THD_GET_AUTOINC(thd, off, inc) \ |
186 | { \ |
187 | *(off) = thd->variables.auto_increment_offset; \ |
188 | *(inc) = thd->variables.auto_increment_increment; \ |
189 | } |
190 | # define MRN_GET_ERR_MSG(code) ER(code) |
191 | #endif |
192 | |
193 | #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) |
194 | # define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex->table_list.first |
195 | #else |
196 | # define MRN_LEX_GET_TABLE_LIST(lex) (lex)->select_lex.table_list.first |
197 | #endif |
198 | |
199 | #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) |
200 | # define MRN_KEYTYPE_FOREIGN KEYTYPE_FOREIGN |
201 | #else |
202 | # define MRN_KEYTYPE_FOREIGN Key::FOREIGN_KEY |
203 | #endif |
204 | |
205 | #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) |
206 | # define mrn_calculate_key_len(table, key_index, buffer, keypart_map) \ |
207 | calculate_key_len(table, key_index, keypart_map) |
208 | #else |
209 | # define mrn_calculate_key_len(table, key_index, buffer, keypart_map) \ |
210 | calculate_key_len(table, key_index, buffer, keypart_map) |
211 | #endif |
212 | |
213 | #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) |
214 | # define MRN_TABLE_LIST_GET_DERIVED(table_list) NULL |
215 | #else |
216 | # define MRN_TABLE_LIST_GET_DERIVED(table_list) (table_list)->derived |
217 | #endif |
218 | |
219 | #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) |
220 | # define MRN_GEOMETRY_FREE(geometry) |
221 | #else |
222 | # define MRN_GEOMETRY_FREE(geometry) delete (geometry) |
223 | #endif |
224 | |
225 | Rpl_filter *mrn_binlog_filter; |
226 | Time_zone *mrn_my_tz_UTC; |
227 | #ifdef MRN_HAVE_TABLE_DEF_CACHE |
228 | HASH *mrn_table_def_cache; |
229 | #endif |
230 | |
231 | #ifdef MRN_HAVE_PSI_MEMORY_KEY |
232 | PSI_memory_key mrn_memory_key; |
233 | |
234 | static PSI_memory_info mrn_all_memory_keys[]= |
235 | { |
236 | {&mrn_memory_key, "Mroonga" , 0} |
237 | }; |
238 | #endif |
239 | |
240 | static const char *INDEX_COLUMN_NAME = "index" ; |
241 | static const char *MRN_PLUGIN_AUTHOR = "The Mroonga project" ; |
242 | |
243 | #ifdef __cplusplus |
244 | extern "C" { |
245 | #endif |
246 | |
247 | #ifdef HAVE_PSI_INTERFACE |
248 | # ifdef WIN32 |
249 | # ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE |
250 | PSI_mutex_key *mrn_table_share_lock_share; |
251 | # endif |
252 | PSI_mutex_key *mrn_table_share_lock_ha_data; |
253 | # endif |
254 | static PSI_mutex_key mrn_open_tables_mutex_key; |
255 | static PSI_mutex_key mrn_long_term_share_mutex_key; |
256 | static PSI_mutex_key mrn_allocated_thds_mutex_key; |
257 | PSI_mutex_key mrn_share_mutex_key; |
258 | PSI_mutex_key mrn_long_term_share_auto_inc_mutex_key; |
259 | static PSI_mutex_key mrn_log_mutex_key; |
260 | static PSI_mutex_key mrn_query_log_mutex_key; |
261 | static PSI_mutex_key mrn_db_manager_mutex_key; |
262 | static PSI_mutex_key mrn_context_pool_mutex_key; |
263 | static PSI_mutex_key mrn_operations_mutex_key; |
264 | |
265 | # if (!defined(MRN_MARIADB_P) && MYSQL_VERSION_ID >= 80002) |
266 | # define MRN_MUTEXT_INFO_ENTRY(key, name, flags, volatility) \ |
267 | {key, name, flags, volatility} |
268 | # else |
269 | # define MRN_MUTEXT_INFO_ENTRY(key, name, flags, volatility) \ |
270 | {key, name, flags} |
271 | # endif |
272 | |
273 | static PSI_mutex_info mrn_mutexes[] = |
274 | { |
275 | MRN_MUTEXT_INFO_ENTRY(&mrn_open_tables_mutex_key, |
276 | "mrn::open_tables" , PSI_FLAG_GLOBAL, 0), |
277 | MRN_MUTEXT_INFO_ENTRY(&mrn_long_term_share_mutex_key, |
278 | "mrn::long_term_share" , PSI_FLAG_GLOBAL, 0), |
279 | MRN_MUTEXT_INFO_ENTRY(&mrn_allocated_thds_mutex_key, |
280 | "mrn::allocated_thds" , PSI_FLAG_GLOBAL, 0), |
281 | MRN_MUTEXT_INFO_ENTRY(&mrn_share_mutex_key, |
282 | "mrn::share" , 0, 0), |
283 | MRN_MUTEXT_INFO_ENTRY(&mrn_long_term_share_auto_inc_mutex_key, |
284 | "mrn::long_term_share::auto_inc" , 0, 0), |
285 | MRN_MUTEXT_INFO_ENTRY(&mrn_log_mutex_key, |
286 | "mrn::log" , PSI_FLAG_GLOBAL, 0), |
287 | MRN_MUTEXT_INFO_ENTRY(&mrn_query_log_mutex_key, |
288 | "mrn::query_log" , PSI_FLAG_GLOBAL, 0), |
289 | MRN_MUTEXT_INFO_ENTRY(&mrn_db_manager_mutex_key, |
290 | "mrn::DatabaseManager" , PSI_FLAG_GLOBAL, 0), |
291 | MRN_MUTEXT_INFO_ENTRY(&mrn_context_pool_mutex_key, |
292 | "mrn::ContextPool" , PSI_FLAG_GLOBAL, 0), |
293 | MRN_MUTEXT_INFO_ENTRY(&mrn_operations_mutex_key, |
294 | "mrn::Operations" , PSI_FLAG_GLOBAL, 0) |
295 | }; |
296 | #endif |
297 | |
298 | /* global variables */ |
299 | handlerton *mrn_hton_ptr; |
300 | HASH mrn_open_tables; |
301 | mysql_mutex_t mrn_open_tables_mutex; |
302 | HASH mrn_long_term_share; |
303 | mysql_mutex_t mrn_long_term_share_mutex; |
304 | |
305 | HASH mrn_allocated_thds; |
306 | mysql_mutex_t mrn_allocated_thds_mutex; |
307 | |
308 | /* internal variables */ |
309 | static grn_ctx mrn_ctx; |
310 | static mysql_mutex_t mrn_log_mutex; |
311 | static mysql_mutex_t mrn_query_log_mutex; |
312 | static grn_obj *mrn_db; |
313 | static grn_ctx mrn_db_manager_ctx; |
314 | static mysql_mutex_t mrn_db_manager_mutex; |
315 | mrn::DatabaseManager *mrn_db_manager = NULL; |
316 | static mysql_mutex_t mrn_context_pool_mutex; |
317 | mrn::ContextPool *mrn_context_pool = NULL; |
318 | static mysql_mutex_t mrn_operations_mutex; |
319 | |
320 | |
321 | #ifdef WIN32 |
322 | static inline double round(double x) |
323 | { |
324 | return (floor(x + 0.5)); |
325 | } |
326 | #endif |
327 | |
328 | static void mrn_init_encoding_map() |
329 | { |
330 | mrn::encoding::init(); |
331 | } |
332 | |
333 | static int mrn_change_encoding(grn_ctx *ctx, const CHARSET_INFO *charset) |
334 | { |
335 | return mrn::encoding::set(ctx, charset); |
336 | } |
337 | |
338 | #if !defined(DBUG_OFF) && !defined(_lint) |
339 | static const char *mrn_inspect_thr_lock_type(enum thr_lock_type lock_type) |
340 | { |
341 | const char *inspected = "<unknown>" ; |
342 | switch (lock_type) { |
343 | case TL_IGNORE: |
344 | inspected = "TL_IGNORE" ; |
345 | break; |
346 | case TL_UNLOCK: |
347 | inspected = "TL_UNLOCK" ; |
348 | break; |
349 | case TL_READ_DEFAULT: |
350 | inspected = "TL_READ_DEFAULT" ; |
351 | break; |
352 | case TL_READ: |
353 | inspected = "TL_READ" ; |
354 | break; |
355 | case TL_READ_WITH_SHARED_LOCKS: |
356 | inspected = "TL_READ_WITH_SHARED_LOCKS" ; |
357 | break; |
358 | case TL_READ_HIGH_PRIORITY: |
359 | inspected = "TL_READ_HIGH_PRIORITY" ; |
360 | break; |
361 | case TL_READ_NO_INSERT: |
362 | inspected = "TL_READ_NO_INSERT" ; |
363 | break; |
364 | case TL_WRITE_ALLOW_WRITE: |
365 | inspected = "TL_WRITE_ALLOW_WRITE" ; |
366 | break; |
367 | #ifdef MRN_HAVE_TL_WRITE_CONCURRENT_DEFAULT |
368 | case TL_WRITE_CONCURRENT_DEFAULT: |
369 | inspected = "TL_WRITE_CONCURRENT_DEFAULT" ; |
370 | break; |
371 | #endif |
372 | case TL_WRITE_CONCURRENT_INSERT: |
373 | inspected = "TL_WRITE_CONCURRENT_INSERT" ; |
374 | break; |
375 | #ifdef MRN_HAVE_TL_WRITE_DELAYED |
376 | case TL_WRITE_DELAYED: |
377 | inspected = "TL_WRITE_DELAYED" ; |
378 | break; |
379 | #endif |
380 | case TL_WRITE_DEFAULT: |
381 | inspected = "TL_WRITE_DEFAULT" ; |
382 | break; |
383 | case TL_WRITE_LOW_PRIORITY: |
384 | inspected = "TL_WRITE_LOW_PRIORITY" ; |
385 | break; |
386 | case TL_WRITE: |
387 | inspected = "TL_WRITE" ; |
388 | break; |
389 | case TL_WRITE_ONLY: |
390 | inspected = "TL_WRITE_ONLY" ; |
391 | break; |
392 | } |
393 | return inspected; |
394 | } |
395 | |
396 | static const char *mrn_inspect_extra_function(enum ha_extra_function operation) |
397 | { |
398 | const char *inspected = "<unknown>" ; |
399 | switch (operation) { |
400 | case HA_EXTRA_NORMAL: |
401 | inspected = "HA_EXTRA_NORMAL" ; |
402 | break; |
403 | case HA_EXTRA_QUICK: |
404 | inspected = "HA_EXTRA_QUICK" ; |
405 | break; |
406 | case HA_EXTRA_NOT_USED: |
407 | inspected = "HA_EXTRA_NOT_USED" ; |
408 | break; |
409 | case HA_EXTRA_CACHE: |
410 | inspected = "HA_EXTRA_CACHE" ; |
411 | break; |
412 | case HA_EXTRA_NO_CACHE: |
413 | inspected = "HA_EXTRA_NO_CACHE" ; |
414 | break; |
415 | case HA_EXTRA_NO_READCHECK: |
416 | inspected = "HA_EXTRA_NO_READCHECK" ; |
417 | break; |
418 | case HA_EXTRA_READCHECK: |
419 | inspected = "HA_EXTRA_READCHECK" ; |
420 | break; |
421 | case HA_EXTRA_KEYREAD: |
422 | inspected = "HA_EXTRA_KEYREAD" ; |
423 | break; |
424 | case HA_EXTRA_NO_KEYREAD: |
425 | inspected = "HA_EXTRA_NO_KEYREAD" ; |
426 | break; |
427 | case HA_EXTRA_NO_USER_CHANGE: |
428 | inspected = "HA_EXTRA_NO_USER_CHANGE" ; |
429 | break; |
430 | case HA_EXTRA_KEY_CACHE: |
431 | inspected = "HA_EXTRA_KEY_CACHE" ; |
432 | break; |
433 | case HA_EXTRA_NO_KEY_CACHE: |
434 | inspected = "HA_EXTRA_NO_KEY_CACHE" ; |
435 | break; |
436 | case HA_EXTRA_WAIT_LOCK: |
437 | inspected = "HA_EXTRA_WAIT_LOCK" ; |
438 | break; |
439 | case HA_EXTRA_NO_WAIT_LOCK: |
440 | inspected = "HA_EXTRA_NO_WAIT_LOCK" ; |
441 | break; |
442 | case HA_EXTRA_WRITE_CACHE: |
443 | inspected = "HA_EXTRA_WRITE_CACHE" ; |
444 | break; |
445 | case HA_EXTRA_FLUSH_CACHE: |
446 | inspected = "HA_EXTRA_FLUSH_CACHE" ; |
447 | break; |
448 | case HA_EXTRA_NO_KEYS: |
449 | inspected = "HA_EXTRA_NO_KEYS" ; |
450 | break; |
451 | case HA_EXTRA_KEYREAD_CHANGE_POS: |
452 | inspected = "HA_EXTRA_KEYREAD_CHANGE_POS" ; |
453 | break; |
454 | case HA_EXTRA_REMEMBER_POS: |
455 | inspected = "HA_EXTRA_REMEMBER_POS" ; |
456 | break; |
457 | case HA_EXTRA_RESTORE_POS: |
458 | inspected = "HA_EXTRA_RESTORE_POS" ; |
459 | break; |
460 | case HA_EXTRA_REINIT_CACHE: |
461 | inspected = "HA_EXTRA_REINIT_CACHE" ; |
462 | break; |
463 | case HA_EXTRA_FORCE_REOPEN: |
464 | inspected = "HA_EXTRA_FORCE_REOPEN" ; |
465 | break; |
466 | case HA_EXTRA_FLUSH: |
467 | inspected = "HA_EXTRA_FLUSH" ; |
468 | break; |
469 | case HA_EXTRA_NO_ROWS: |
470 | inspected = "HA_EXTRA_NO_ROWS" ; |
471 | break; |
472 | case HA_EXTRA_RESET_STATE: |
473 | inspected = "HA_EXTRA_RESET_STATE" ; |
474 | break; |
475 | case HA_EXTRA_IGNORE_DUP_KEY: |
476 | inspected = "HA_EXTRA_IGNORE_DUP_KEY" ; |
477 | break; |
478 | case HA_EXTRA_NO_IGNORE_DUP_KEY: |
479 | inspected = "HA_EXTRA_NO_IGNORE_DUP_KEY" ; |
480 | break; |
481 | case HA_EXTRA_PREPARE_FOR_DROP: |
482 | inspected = "HA_EXTRA_PREPARE_FOR_DROP" ; |
483 | break; |
484 | case HA_EXTRA_PREPARE_FOR_ALTER_TABLE: |
485 | inspected = "HA_EXTRA_PREPARE_FOR_ALTER_TABLE" ; |
486 | break; |
487 | case HA_EXTRA_PREPARE_FOR_UPDATE: |
488 | inspected = "HA_EXTRA_PREPARE_FOR_UPDATE" ; |
489 | break; |
490 | case HA_EXTRA_PRELOAD_BUFFER_SIZE: |
491 | inspected = "HA_EXTRA_PRELOAD_BUFFER_SIZE" ; |
492 | break; |
493 | case HA_EXTRA_CHANGE_KEY_TO_UNIQUE: |
494 | inspected = "HA_EXTRA_CHANGE_KEY_TO_UNIQUE" ; |
495 | break; |
496 | case HA_EXTRA_CHANGE_KEY_TO_DUP: |
497 | inspected = "HA_EXTRA_CHANGE_KEY_TO_DUP" ; |
498 | break; |
499 | case HA_EXTRA_KEYREAD_PRESERVE_FIELDS: |
500 | inspected = "HA_EXTRA_KEYREAD_PRESERVE_FIELDS" ; |
501 | break; |
502 | case HA_EXTRA_MMAP: |
503 | inspected = "HA_EXTRA_MMAP" ; |
504 | break; |
505 | case HA_EXTRA_IGNORE_NO_KEY: |
506 | inspected = "HA_EXTRA_IGNORE_NO_KEY" ; |
507 | break; |
508 | case HA_EXTRA_NO_IGNORE_NO_KEY: |
509 | inspected = "HA_EXTRA_NO_IGNORE_NO_KEY" ; |
510 | break; |
511 | case HA_EXTRA_MARK_AS_LOG_TABLE: |
512 | inspected = "HA_EXTRA_MARK_AS_LOG_TABLE" ; |
513 | break; |
514 | case HA_EXTRA_WRITE_CAN_REPLACE: |
515 | inspected = "HA_EXTRA_WRITE_CAN_REPLACE" ; |
516 | break; |
517 | case HA_EXTRA_WRITE_CANNOT_REPLACE: |
518 | inspected = "HA_EXTRA_WRITE_CANNOT_REPLACE" ; |
519 | break; |
520 | case HA_EXTRA_DELETE_CANNOT_BATCH: |
521 | inspected = "HA_EXTRA_DELETE_CANNOT_BATCH" ; |
522 | break; |
523 | case HA_EXTRA_UPDATE_CANNOT_BATCH: |
524 | inspected = "HA_EXTRA_UPDATE_CANNOT_BATCH" ; |
525 | break; |
526 | case HA_EXTRA_INSERT_WITH_UPDATE: |
527 | inspected = "HA_EXTRA_INSERT_WITH_UPDATE" ; |
528 | break; |
529 | case HA_EXTRA_PREPARE_FOR_RENAME: |
530 | inspected = "HA_EXTRA_PREPARE_FOR_RENAME" ; |
531 | break; |
532 | case HA_EXTRA_ADD_CHILDREN_LIST: |
533 | inspected = "HA_EXTRA_ADD_CHILDREN_LIST" ; |
534 | break; |
535 | case HA_EXTRA_ATTACH_CHILDREN: |
536 | inspected = "HA_EXTRA_ATTACH_CHILDREN" ; |
537 | break; |
538 | case HA_EXTRA_IS_ATTACHED_CHILDREN: |
539 | inspected = "HA_EXTRA_IS_ATTACHED_CHILDREN" ; |
540 | break; |
541 | case HA_EXTRA_DETACH_CHILDREN: |
542 | inspected = "HA_EXTRA_DETACH_CHILDREN" ; |
543 | break; |
544 | case HA_EXTRA_STARTING_ORDERED_INDEX_SCAN: |
545 | inspected = "HA_EXTRA_STARTING_ORDERED_INDEX_SCAN" ; |
546 | break; |
547 | case HA_EXTRA_BEGIN_ALTER_COPY: |
548 | inspected = "HA_EXTRA_BEGIN_ALTER_COPY" ; |
549 | break; |
550 | case HA_EXTRA_END_ALTER_COPY: |
551 | inspected = "HA_EXTRA_END_ALTER_COPY" ; |
552 | break; |
553 | case HA_EXTRA_FAKE_START_STMT: |
554 | inspected = "HA_EXTRA_FAKE_START_STMT" ; |
555 | break; |
556 | #ifdef MRN_HAVE_HA_EXTRA_EXPORT |
557 | case HA_EXTRA_EXPORT: |
558 | inspected = "HA_EXTRA_EXPORT" ; |
559 | break; |
560 | #endif |
561 | #ifdef MRN_HAVE_HA_EXTRA_SECONDARY_SORT_ROWID |
562 | case HA_EXTRA_SECONDARY_SORT_ROWID: |
563 | inspected = "HA_EXTRA_SECONDARY_SORT_ROWID" ; |
564 | break; |
565 | #endif |
566 | #ifdef MRN_HAVE_HA_EXTRA_DETACH_CHILD |
567 | case HA_EXTRA_DETACH_CHILD: |
568 | inspected = "HA_EXTRA_DETACH_CHILD" ; |
569 | break; |
570 | #endif |
571 | #ifdef MRN_HAVE_HA_EXTRA_PREPARE_FOR_FORCED_CLOSE |
572 | case HA_EXTRA_PREPARE_FOR_FORCED_CLOSE: |
573 | inspected = "HA_EXTRA_PREPARE_FOR_FORCED_CLOSE" ; |
574 | break; |
575 | #endif |
576 | #ifdef MRN_HAVE_HA_EXTRA_SKIP_SERIALIZABLE_DD_VIEW |
577 | case HA_EXTRA_SKIP_SERIALIZABLE_DD_VIEW: |
578 | inspected = "HA_EXTRA_SKIP_SERIALIZABLE_DD_VIEW" ; |
579 | break; |
580 | #endif |
581 | #ifdef MRN_HAVE_HA_EXTRA_BEGIN_ALTER_COPY |
582 | case HA_EXTRA_BEGIN_ALTER_COPY: |
583 | inspected = "HA_EXTRA_BEGIN_ALTER_COPY" ; |
584 | break; |
585 | #endif |
586 | #ifdef MRN_HAVE_HA_EXTRA_END_ALTER_COPY |
587 | case HA_EXTRA_END_ALTER_COPY: |
588 | inspected = "HA_EXTRA_END_ALTER_COPY" ; |
589 | break; |
590 | #endif |
591 | #ifdef MRN_HAVE_HA_EXTRA_NO_AUTOINC_LOCKING |
592 | case HA_EXTRA_NO_AUTOINC_LOCKING: |
593 | inspected = "HA_EXTRA_NO_AUTOINC_LOCKING" ; |
594 | break; |
595 | #endif |
596 | } |
597 | return inspected; |
598 | } |
599 | #endif |
600 | |
601 | static uchar *mrn_open_tables_get_key(const uchar *record, |
602 | size_t *length, |
603 | my_bool not_used __attribute__ ((unused))) |
604 | { |
605 | MRN_DBUG_ENTER_FUNCTION(); |
606 | MRN_SHARE *share = reinterpret_cast<MRN_SHARE *>(const_cast<uchar *>(record)); |
607 | *length = share->table_name_length; |
608 | DBUG_RETURN(reinterpret_cast<uchar *>(share->table_name)); |
609 | } |
610 | |
611 | static uchar *mrn_long_term_share_get_key(const uchar *record, |
612 | size_t *length, |
613 | my_bool not_used __attribute__ ((unused))) |
614 | { |
615 | MRN_DBUG_ENTER_FUNCTION(); |
616 | MRN_LONG_TERM_SHARE *long_term_share = |
617 | reinterpret_cast<MRN_LONG_TERM_SHARE *>(const_cast<uchar *>(record)); |
618 | *length = long_term_share->table_name_length; |
619 | DBUG_RETURN(reinterpret_cast<uchar *>(long_term_share->table_name)); |
620 | } |
621 | |
622 | /* status */ |
623 | static long mrn_count_skip = 0; |
624 | static long mrn_fast_order_limit = 0; |
625 | |
626 | /* logging */ |
627 | static char *mrn_log_file_path = NULL; |
628 | static FILE *mrn_log_file = NULL; |
629 | static bool mrn_log_file_opened = false; |
630 | static grn_log_level mrn_log_level_default = GRN_LOG_DEFAULT_LEVEL; |
631 | static ulong mrn_log_level = mrn_log_level_default; |
632 | static char *mrn_query_log_file_path = NULL; |
633 | |
634 | char *mrn_default_tokenizer = NULL; |
635 | char *mrn_default_wrapper_engine = NULL; |
636 | static int mrn_lock_timeout = grn_get_lock_timeout(); |
637 | static char *mrn_libgroonga_version = const_cast<char *>(grn_get_version()); |
638 | static char *mrn_version = const_cast<char *>(MRN_VERSION); |
639 | static char *mrn_vector_column_delimiter = NULL; |
640 | static mrn_bool mrn_libgroonga_support_zlib = false; |
641 | static mrn_bool mrn_libgroonga_support_lz4 = false; |
642 | static mrn_bool mrn_libgroonga_support_zstd = false; |
643 | static mrn_bool mrn_enable_operations_recording = true; |
644 | #ifdef MRN_SUPPORT_THDVAR_SET |
645 | static const char *mrn_boolean_mode_sytnax_flag_names[] = { |
646 | "DEFAULT" , |
647 | "SYNTAX_QUERY" , |
648 | "SYNTAX_SCRIPT" , |
649 | "ALLOW_COLUMN" , |
650 | "ALLOW_UPDATE" , |
651 | "ALLOW_LEADING_NOT" , |
652 | NullS |
653 | }; |
654 | static TYPELIB mrn_boolean_mode_syntax_flags_typelib = { |
655 | array_elements(mrn_boolean_mode_sytnax_flag_names) - 1, |
656 | "" , |
657 | mrn_boolean_mode_sytnax_flag_names, |
658 | NULL |
659 | }; |
660 | #endif |
661 | #ifdef MRN_GROONGA_EMBEDDED |
662 | static mrn_bool mrn_libgroonga_embedded = true; |
663 | #else |
664 | static mrn_bool mrn_libgroonga_embedded = false; |
665 | #endif |
666 | |
667 | static mrn::variables::ActionOnError mrn_action_on_fulltext_query_error_default = |
668 | mrn::variables::ACTION_ON_ERROR_ERROR_AND_LOG; |
669 | |
670 | static void mrn_logger_log(grn_ctx *ctx, grn_log_level level, |
671 | const char *timestamp, const char *title, |
672 | const char *message, const char *location, |
673 | void *user_data) |
674 | { |
675 | const char level_marks[] = " EACewnid-" ; |
676 | if (mrn_log_file_opened) { |
677 | mrn::Lock lock(&mrn_log_mutex); |
678 | fprintf(mrn_log_file, |
679 | "%s|%c|%08x|%s\n" , |
680 | timestamp, |
681 | level_marks[level], |
682 | static_cast<uint>((ulong)(pthread_self())), |
683 | message); |
684 | fflush(mrn_log_file); |
685 | } |
686 | } |
687 | |
688 | static grn_logger mrn_logger = { |
689 | mrn_log_level_default, |
690 | GRN_LOG_TIME|GRN_LOG_MESSAGE, |
691 | NULL, |
692 | mrn_logger_log, |
693 | NULL, |
694 | NULL |
695 | }; |
696 | |
697 | static uchar *mrn_allocated_thds_get_key(const uchar *record, |
698 | size_t *length, |
699 | my_bool not_used __attribute__ ((unused))) |
700 | { |
701 | MRN_DBUG_ENTER_FUNCTION(); |
702 | *length = sizeof(THD *); |
703 | DBUG_RETURN(const_cast<uchar *>(record)); |
704 | } |
705 | |
706 | /* system functions */ |
707 | |
708 | static struct st_mysql_storage_engine storage_engine_structure = |
709 | { MYSQL_HANDLERTON_INTERFACE_VERSION }; |
710 | |
711 | #if MYSQL_VERSION_ID >= 50706 && !defined(MRN_MARIADB_P) |
712 | # define MRN_STATUS_VARIABLE_ENTRY(name, value, type, scope) \ |
713 | {name, value, type, scope} |
714 | #else |
715 | # define MRN_STATUS_VARIABLE_ENTRY(name, value, type, scope) \ |
716 | {name, value, type} |
717 | #endif |
718 | |
719 | static struct st_mysql_show_var mrn_status_variables[] = |
720 | { |
721 | MRN_STATUS_VARIABLE_ENTRY(MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_count_skip" , |
722 | (char *)&mrn_count_skip, |
723 | SHOW_LONG, |
724 | SHOW_SCOPE_GLOBAL), |
725 | MRN_STATUS_VARIABLE_ENTRY(MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_fast_order_limit" , |
726 | (char *)&mrn_fast_order_limit, |
727 | SHOW_LONG, |
728 | SHOW_SCOPE_GLOBAL), |
729 | MRN_STATUS_VARIABLE_ENTRY(NullS, NullS, SHOW_LONG, SHOW_SCOPE_GLOBAL) |
730 | }; |
731 | |
732 | static const char *mrn_log_level_type_names[] = { |
733 | "NONE" , |
734 | "EMERG" , |
735 | "ALERT" , |
736 | "CRIT" , |
737 | "ERROR" , |
738 | "WARNING" , |
739 | "NOTICE" , |
740 | "INFO" , |
741 | "DEBUG" , |
742 | "DUMP" , |
743 | NullS |
744 | }; |
745 | static TYPELIB mrn_log_level_typelib = { |
746 | array_elements(mrn_log_level_type_names) - 1, |
747 | "mrn_log_level_typelib" , |
748 | mrn_log_level_type_names, |
749 | NULL |
750 | }; |
751 | |
752 | static void mrn_log_level_update(THD *thd, struct st_mysql_sys_var *var, |
753 | void *var_ptr, const void *save) |
754 | { |
755 | MRN_DBUG_ENTER_FUNCTION(); |
756 | ulong new_value = *static_cast<const ulong *>(save); |
757 | ulong old_value = mrn_log_level; |
758 | mrn_log_level = new_value; |
759 | mrn_logger.max_level = static_cast<grn_log_level>(mrn_log_level); |
760 | grn_logger_set(&mrn_ctx, &mrn_logger); |
761 | grn_ctx *ctx = grn_ctx_open(0); |
762 | mrn_change_encoding(ctx, system_charset_info); |
763 | GRN_LOG(ctx, GRN_LOG_NOTICE, "log level changed from '%s' to '%s'" , |
764 | mrn_log_level_type_names[old_value], |
765 | mrn_log_level_type_names[new_value]); |
766 | grn_ctx_fin(ctx); |
767 | DBUG_VOID_RETURN; |
768 | } |
769 | |
770 | static MYSQL_SYSVAR_ENUM(log_level, mrn_log_level, |
771 | PLUGIN_VAR_RQCMDARG, |
772 | "logging level" , |
773 | NULL, |
774 | mrn_log_level_update, |
775 | static_cast<ulong>(mrn_log_level), |
776 | &mrn_log_level_typelib); |
777 | |
778 | static void mrn_log_file_update(THD *thd, struct st_mysql_sys_var *var, |
779 | void *var_ptr, const void *save) |
780 | { |
781 | MRN_DBUG_ENTER_FUNCTION(); |
782 | const char *new_value = *((const char **)save); |
783 | char **old_value_ptr = (char **)var_ptr; |
784 | |
785 | grn_ctx *ctx = &mrn_ctx; |
786 | mrn_change_encoding(ctx, system_charset_info); |
787 | |
788 | const char *new_log_file_name; |
789 | new_log_file_name = *old_value_ptr; |
790 | |
791 | if (strcmp(*old_value_ptr, new_value) == 0) { |
792 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
793 | "log file isn't changed " |
794 | "because the requested path isn't different: <%s>" , |
795 | new_value); |
796 | } else { |
797 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
798 | "log file is changed: <%s> -> <%s>" , |
799 | *old_value_ptr, new_value); |
800 | |
801 | int log_file_open_errno = 0; |
802 | { |
803 | mrn::Lock lock(&mrn_log_mutex); |
804 | FILE *new_log_file; |
805 | new_log_file = fopen(new_value, "a" ); |
806 | if (new_log_file) { |
807 | if (mrn_log_file_opened) { |
808 | fclose(mrn_log_file); |
809 | } |
810 | mrn_log_file = new_log_file; |
811 | mrn_log_file_opened = true; |
812 | } else { |
813 | log_file_open_errno = errno; |
814 | } |
815 | } |
816 | |
817 | if (log_file_open_errno == 0) { |
818 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
819 | "log file is changed: <%s> -> <%s>" , |
820 | *old_value_ptr, new_value); |
821 | new_log_file_name = new_value; |
822 | } else { |
823 | if (mrn_log_file) { |
824 | GRN_LOG(ctx, GRN_LOG_ERROR, |
825 | "log file isn't changed " |
826 | "because the requested path can't be opened: <%s>: <%s>" , |
827 | new_value, strerror(log_file_open_errno)); |
828 | } else { |
829 | GRN_LOG(ctx, GRN_LOG_ERROR, |
830 | "log file can't be opened: <%s>: <%s>" , |
831 | new_value, strerror(log_file_open_errno)); |
832 | } |
833 | } |
834 | } |
835 | |
836 | #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR |
837 | char *old_log_file_name = *old_value_ptr; |
838 | *old_value_ptr = mrn_my_strdup(new_log_file_name, MYF(MY_WME)); |
839 | my_free(old_log_file_name); |
840 | #else |
841 | *old_value_ptr = mrn_my_strdup(new_log_file_name, MYF(MY_WME)); |
842 | #endif |
843 | |
844 | DBUG_VOID_RETURN; |
845 | } |
846 | |
847 | static MYSQL_SYSVAR_STR(log_file, mrn_log_file_path, |
848 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, |
849 | "log file for " MRN_PLUGIN_NAME_STRING, |
850 | NULL, |
851 | mrn_log_file_update, |
852 | MRN_LOG_FILE_PATH); |
853 | |
854 | static void mrn_query_log_file_update(THD *thd, struct st_mysql_sys_var *var, |
855 | void *var_ptr, const void *save) |
856 | { |
857 | MRN_DBUG_ENTER_FUNCTION(); |
858 | const char *new_value = *((const char **)save); |
859 | char **old_value_ptr = (char **)var_ptr; |
860 | const char *normalized_new_value = NULL; |
861 | |
862 | grn_ctx *ctx = &mrn_ctx; |
863 | mrn_change_encoding(ctx, system_charset_info); |
864 | |
865 | const char *new_query_log_file_name; |
866 | new_query_log_file_name = *old_value_ptr; |
867 | |
868 | bool need_update = false; |
869 | if (!*old_value_ptr) { |
870 | if (new_value && new_value[0] != '\0') { |
871 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
872 | "query log is enabled: <%s>" , |
873 | new_value); |
874 | need_update = true; |
875 | normalized_new_value = new_value; |
876 | } else { |
877 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
878 | "query log file is still disabled" ); |
879 | } |
880 | } else { |
881 | if (!new_value || new_value[0] == '\0') { |
882 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
883 | "query log file is disabled: <%s>" , |
884 | *old_value_ptr); |
885 | need_update = true; |
886 | normalized_new_value = NULL; |
887 | } else if (strcmp(*old_value_ptr, new_value) == 0) { |
888 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
889 | "query log file isn't changed " |
890 | "because the requested path isn't different: <%s>" , |
891 | new_value); |
892 | } else { |
893 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
894 | "query log file is changed: <%s> -> <%s>" , |
895 | *old_value_ptr, new_value); |
896 | need_update = true; |
897 | normalized_new_value = new_value; |
898 | } |
899 | } |
900 | |
901 | if (need_update) { |
902 | { // TODO: Remove me when Groonga 7.0.5 is released. |
903 | mrn::Lock lock(&mrn_query_log_mutex); |
904 | grn_default_query_logger_set_path(normalized_new_value); |
905 | } |
906 | grn_query_logger_reopen(ctx); |
907 | new_query_log_file_name = normalized_new_value; |
908 | } |
909 | |
910 | #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR |
911 | char *old_query_log_file_name = *old_value_ptr; |
912 | #endif |
913 | if (new_query_log_file_name) { |
914 | *old_value_ptr = mrn_my_strdup(new_query_log_file_name, MYF(0)); |
915 | } else { |
916 | *old_value_ptr = NULL; |
917 | } |
918 | #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR |
919 | my_free(old_query_log_file_name); |
920 | #endif |
921 | |
922 | DBUG_VOID_RETURN; |
923 | } |
924 | |
925 | static MYSQL_SYSVAR_STR(query_log_file, mrn_query_log_file_path, |
926 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, |
927 | "query log file for " MRN_PLUGIN_NAME_STRING, |
928 | NULL, |
929 | mrn_query_log_file_update, |
930 | NULL); |
931 | |
932 | static void mrn_default_tokenizer_update(THD *thd, struct st_mysql_sys_var *var, |
933 | void *var_ptr, const void *save) |
934 | { |
935 | MRN_DBUG_ENTER_FUNCTION(); |
936 | const char *new_value = *((const char **)save); |
937 | char **old_value_ptr = (char **)var_ptr; |
938 | grn_ctx *ctx = &mrn_ctx; |
939 | |
940 | mrn_change_encoding(ctx, system_charset_info); |
941 | if (strcmp(*old_value_ptr, new_value) == 0) { |
942 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
943 | "default tokenizer for fulltext index isn't changed " |
944 | "because the requested default tokenizer isn't different: <%s>" , |
945 | new_value); |
946 | } else { |
947 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
948 | "default tokenizer for fulltext index is changed: <%s> -> <%s>" , |
949 | *old_value_ptr, new_value); |
950 | } |
951 | |
952 | #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR |
953 | my_free(*old_value_ptr); |
954 | *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME)); |
955 | #else |
956 | *old_value_ptr = (char *)new_value; |
957 | #endif |
958 | |
959 | DBUG_VOID_RETURN; |
960 | } |
961 | |
962 | static MYSQL_SYSVAR_STR(default_parser, mrn_default_tokenizer, |
963 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, |
964 | "default fulltext parser " |
965 | "(Deprecated. Use mroonga_default_tokenizer instead.)" , |
966 | NULL, |
967 | mrn_default_tokenizer_update, |
968 | MRN_DEFAULT_TOKENIZER); |
969 | |
970 | static MYSQL_SYSVAR_STR(default_tokenizer, mrn_default_tokenizer, |
971 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, |
972 | "default tokenizer for fulltext index" , |
973 | NULL, |
974 | mrn_default_tokenizer_update, |
975 | MRN_DEFAULT_TOKENIZER); |
976 | |
977 | static MYSQL_THDVAR_BOOL( |
978 | dry_write, /* name */ |
979 | PLUGIN_VAR_OPCMDARG, /* options */ |
980 | "If dry_write is true, any write operations are ignored." , /* comment */ |
981 | NULL, /* check */ |
982 | NULL, /* update */ |
983 | false /* default */ |
984 | ); |
985 | |
986 | static MYSQL_THDVAR_BOOL( |
987 | enable_optimization, /* name */ |
988 | PLUGIN_VAR_OPCMDARG, /* options */ |
989 | "If enable_optimization is true, some optimizations will be applied." , /* comment */ |
990 | NULL, /* check */ |
991 | NULL, /* update */ |
992 | true /* default */ |
993 | ); |
994 | |
995 | static MYSQL_THDVAR_LONGLONG(match_escalation_threshold, |
996 | PLUGIN_VAR_RQCMDARG, |
997 | "The threshold to determin whether search method is escalated" , |
998 | NULL, |
999 | NULL, |
1000 | grn_get_default_match_escalation_threshold(), |
1001 | -1, |
1002 | INT_MAX64, |
1003 | 0); |
1004 | |
1005 | static void mrn_vector_column_delimiter_update(THD *thd, struct st_mysql_sys_var *var, |
1006 | void *var_ptr, const void *save) |
1007 | { |
1008 | MRN_DBUG_ENTER_FUNCTION(); |
1009 | const char *new_value = *((const char **)save); |
1010 | char **old_value_ptr = (char **)var_ptr; |
1011 | |
1012 | #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR |
1013 | my_free(*old_value_ptr); |
1014 | *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME)); |
1015 | #else |
1016 | *old_value_ptr = (char *)new_value; |
1017 | #endif |
1018 | |
1019 | DBUG_VOID_RETURN; |
1020 | } |
1021 | |
1022 | static MYSQL_SYSVAR_STR(vector_column_delimiter, mrn_vector_column_delimiter, |
1023 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, |
1024 | "The vector column delimiter" , |
1025 | NULL, |
1026 | &mrn_vector_column_delimiter_update, |
1027 | " " ); |
1028 | |
1029 | static void mrn_database_path_prefix_update(THD *thd, |
1030 | struct st_mysql_sys_var *var, |
1031 | void *var_ptr, const void *save) |
1032 | { |
1033 | MRN_DBUG_ENTER_FUNCTION(); |
1034 | const char *new_value = *((const char **)save); |
1035 | char **old_value_ptr = (char **)var_ptr; |
1036 | #ifdef MRN_NEED_FREE_STRING_MEMALLOC_PLUGIN_VAR |
1037 | if (*old_value_ptr) |
1038 | my_free(*old_value_ptr); |
1039 | if (new_value) |
1040 | *old_value_ptr = mrn_my_strdup(new_value, MYF(MY_WME)); |
1041 | else |
1042 | *old_value_ptr = NULL; |
1043 | #else |
1044 | *old_value_ptr = (char *)new_value; |
1045 | #endif |
1046 | DBUG_VOID_RETURN; |
1047 | } |
1048 | |
1049 | static MYSQL_SYSVAR_STR(database_path_prefix, |
1050 | mrn::PathMapper::default_path_prefix, |
1051 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_MEMALLOC, |
1052 | "The database path prefix" , |
1053 | NULL, |
1054 | &mrn_database_path_prefix_update, |
1055 | NULL); |
1056 | |
1057 | static MYSQL_SYSVAR_STR(default_wrapper_engine, mrn_default_wrapper_engine, |
1058 | PLUGIN_VAR_RQCMDARG | PLUGIN_VAR_READONLY, |
1059 | "The default engine for wrapper mode" , |
1060 | NULL, |
1061 | NULL, |
1062 | NULL); |
1063 | |
1064 | static const char *mrn_action_on_error_names[] = { |
1065 | "ERROR" , |
1066 | "ERROR_AND_LOG" , |
1067 | "IGNORE" , |
1068 | "IGNORE_AND_LOG" , |
1069 | NullS, |
1070 | }; |
1071 | |
1072 | static TYPELIB mrn_action_on_error_typelib = |
1073 | { |
1074 | array_elements(mrn_action_on_error_names) - 1, |
1075 | "mrn_action_on_error_typelib" , |
1076 | mrn_action_on_error_names, |
1077 | NULL |
1078 | }; |
1079 | |
1080 | static MYSQL_THDVAR_ENUM(action_on_fulltext_query_error, |
1081 | PLUGIN_VAR_RQCMDARG, |
1082 | "action on fulltext query error" , |
1083 | NULL, |
1084 | NULL, |
1085 | mrn_action_on_fulltext_query_error_default, |
1086 | &mrn_action_on_error_typelib); |
1087 | |
1088 | static void mrn_lock_timeout_update(THD *thd, struct st_mysql_sys_var *var, |
1089 | void *var_ptr, const void *save) |
1090 | { |
1091 | MRN_DBUG_ENTER_FUNCTION(); |
1092 | const int new_value = *static_cast<const int *>(save); |
1093 | int *old_value_ptr = static_cast<int *>(var_ptr); |
1094 | |
1095 | *old_value_ptr = new_value; |
1096 | grn_set_lock_timeout(new_value); |
1097 | |
1098 | DBUG_VOID_RETURN; |
1099 | } |
1100 | |
1101 | static MYSQL_SYSVAR_INT(lock_timeout, |
1102 | mrn_lock_timeout, |
1103 | PLUGIN_VAR_RQCMDARG, |
1104 | "lock timeout used in Groonga" , |
1105 | NULL, |
1106 | mrn_lock_timeout_update, |
1107 | grn_get_lock_timeout(), |
1108 | -1, |
1109 | INT_MAX, |
1110 | 1); |
1111 | |
1112 | static MYSQL_SYSVAR_STR(libgroonga_version, mrn_libgroonga_version, |
1113 | PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY, |
1114 | "The version of libgroonga" , |
1115 | NULL, |
1116 | NULL, |
1117 | grn_get_version()); |
1118 | |
1119 | static MYSQL_SYSVAR_STR(version, mrn_version, |
1120 | PLUGIN_VAR_NOCMDOPT | PLUGIN_VAR_READONLY, |
1121 | "The version of mroonga" , |
1122 | NULL, |
1123 | NULL, |
1124 | MRN_VERSION); |
1125 | |
1126 | static mrn_bool grn_check_zlib_support() |
1127 | { |
1128 | bool is_zlib_support = false; |
1129 | grn_obj grn_support_p; |
1130 | |
1131 | GRN_BOOL_INIT(&grn_support_p, 0); |
1132 | grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_ZLIB, &grn_support_p); |
1133 | is_zlib_support = (GRN_BOOL_VALUE(&grn_support_p)); |
1134 | grn_obj_unlink(&mrn_ctx, &grn_support_p); |
1135 | |
1136 | return is_zlib_support; |
1137 | } |
1138 | |
1139 | static MYSQL_SYSVAR_BOOL(libgroonga_support_zlib, mrn_libgroonga_support_zlib, |
1140 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, |
1141 | "The status of libgroonga supports zlib" , |
1142 | NULL, |
1143 | NULL, |
1144 | grn_check_zlib_support()); |
1145 | |
1146 | static mrn_bool grn_check_lz4_support() |
1147 | { |
1148 | bool is_lz4_support = false; |
1149 | grn_obj grn_support_p; |
1150 | |
1151 | GRN_BOOL_INIT(&grn_support_p, 0); |
1152 | grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_LZ4, &grn_support_p); |
1153 | is_lz4_support = (GRN_BOOL_VALUE(&grn_support_p)); |
1154 | grn_obj_unlink(&mrn_ctx, &grn_support_p); |
1155 | |
1156 | return is_lz4_support; |
1157 | } |
1158 | |
1159 | static MYSQL_SYSVAR_BOOL(libgroonga_support_lz4, mrn_libgroonga_support_lz4, |
1160 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, |
1161 | "The status of libgroonga supports LZ4" , |
1162 | NULL, |
1163 | NULL, |
1164 | grn_check_lz4_support()); |
1165 | |
1166 | static mrn_bool grn_check_zstd_support() |
1167 | { |
1168 | bool is_zstd_support = false; |
1169 | grn_obj grn_support_p; |
1170 | |
1171 | GRN_BOOL_INIT(&grn_support_p, 0); |
1172 | grn_obj_get_info(&mrn_ctx, NULL, GRN_INFO_SUPPORT_ZSTD, &grn_support_p); |
1173 | is_zstd_support = (GRN_BOOL_VALUE(&grn_support_p)); |
1174 | grn_obj_unlink(&mrn_ctx, &grn_support_p); |
1175 | |
1176 | return is_zstd_support; |
1177 | } |
1178 | |
1179 | static MYSQL_SYSVAR_BOOL(libgroonga_support_zstd, mrn_libgroonga_support_zstd, |
1180 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, |
1181 | "The status of libgroonga supports Zstandard" , |
1182 | NULL, |
1183 | NULL, |
1184 | grn_check_zstd_support()); |
1185 | |
1186 | static void mrn_enable_operations_recording_update(THD *thd, struct st_mysql_sys_var *var, |
1187 | void *var_ptr, const void *save) |
1188 | { |
1189 | MRN_DBUG_ENTER_FUNCTION(); |
1190 | const bool new_value = *static_cast<const bool *>(save); |
1191 | bool *old_value_ptr = static_cast<bool *>(var_ptr); |
1192 | |
1193 | *old_value_ptr = new_value; |
1194 | |
1195 | DBUG_VOID_RETURN; |
1196 | } |
1197 | |
1198 | static MYSQL_SYSVAR_BOOL(enable_operations_recording, mrn_enable_operations_recording, |
1199 | PLUGIN_VAR_RQCMDARG, |
1200 | "Whether recording operations for recovery is enabled or not" , |
1201 | NULL, |
1202 | mrn_enable_operations_recording_update, |
1203 | true); |
1204 | |
1205 | #ifdef MRN_SUPPORT_THDVAR_SET |
1206 | static MYSQL_THDVAR_SET(boolean_mode_syntax_flags, |
1207 | PLUGIN_VAR_RQCMDARG, |
1208 | "The flags to custom syntax in BOOLEAN MODE. " |
1209 | "Available flags: " |
1210 | "DEFAULT(=SYNTAX_QUERY,ALLOW_LEADING_NOT), " |
1211 | "SYNTAX_QUERY, SYNTAX_SCRIPT, " |
1212 | "ALLOW_COLUMN, ALLOW_UPDATE and ALLOW_LEADING_NOT" , |
1213 | NULL, |
1214 | NULL, |
1215 | mrn::variables::BOOLEAN_MODE_SYNTAX_FLAG_DEFAULT, |
1216 | &mrn_boolean_mode_syntax_flags_typelib); |
1217 | #endif |
1218 | |
1219 | static const int MRN_MAX_N_RECORDS_FOR_ESTIMATE_DEFAULT = 1000; |
1220 | |
1221 | static MYSQL_THDVAR_INT(max_n_records_for_estimate, |
1222 | PLUGIN_VAR_RQCMDARG, |
1223 | "The max number of records to " |
1224 | "estimate the number of matched records" , |
1225 | NULL, |
1226 | NULL, |
1227 | MRN_MAX_N_RECORDS_FOR_ESTIMATE_DEFAULT, |
1228 | -1, |
1229 | INT_MAX, |
1230 | 0); |
1231 | |
1232 | static MYSQL_SYSVAR_BOOL(libgroonga_embedded, mrn_libgroonga_embedded, |
1233 | PLUGIN_VAR_NOCMDARG | PLUGIN_VAR_READONLY, |
1234 | "Whether libgroonga is embedded or not" , |
1235 | NULL, |
1236 | NULL, |
1237 | mrn_libgroonga_embedded); |
1238 | |
1239 | static struct st_mysql_sys_var *mrn_system_variables[] = |
1240 | { |
1241 | MYSQL_SYSVAR(log_level), |
1242 | MYSQL_SYSVAR(log_file), |
1243 | MYSQL_SYSVAR(default_parser), |
1244 | MYSQL_SYSVAR(default_tokenizer), |
1245 | MYSQL_SYSVAR(dry_write), |
1246 | MYSQL_SYSVAR(enable_optimization), |
1247 | MYSQL_SYSVAR(match_escalation_threshold), |
1248 | MYSQL_SYSVAR(database_path_prefix), |
1249 | MYSQL_SYSVAR(default_wrapper_engine), |
1250 | MYSQL_SYSVAR(action_on_fulltext_query_error), |
1251 | MYSQL_SYSVAR(lock_timeout), |
1252 | MYSQL_SYSVAR(libgroonga_version), |
1253 | MYSQL_SYSVAR(version), |
1254 | MYSQL_SYSVAR(vector_column_delimiter), |
1255 | MYSQL_SYSVAR(libgroonga_support_zlib), |
1256 | MYSQL_SYSVAR(libgroonga_support_lz4), |
1257 | MYSQL_SYSVAR(libgroonga_support_zstd), |
1258 | #ifdef MRN_SUPPORT_THDVAR_SET |
1259 | MYSQL_SYSVAR(boolean_mode_syntax_flags), |
1260 | #endif |
1261 | MYSQL_SYSVAR(max_n_records_for_estimate), |
1262 | MYSQL_SYSVAR(libgroonga_embedded), |
1263 | MYSQL_SYSVAR(query_log_file), |
1264 | MYSQL_SYSVAR(enable_operations_recording), |
1265 | NULL |
1266 | }; |
1267 | |
1268 | /* mroonga information schema */ |
1269 | static struct st_mysql_information_schema i_s_info = |
1270 | { |
1271 | MYSQL_INFORMATION_SCHEMA_INTERFACE_VERSION |
1272 | }; |
1273 | |
1274 | static ST_FIELD_INFO i_s_mrn_stats_fields_info[] = |
1275 | { |
1276 | { |
1277 | "VERSION" , |
1278 | 40, |
1279 | MYSQL_TYPE_STRING, |
1280 | 0, |
1281 | 0, |
1282 | "" , |
1283 | SKIP_OPEN_TABLE |
1284 | }, |
1285 | { |
1286 | "rows_written" , |
1287 | MY_INT32_NUM_DECIMAL_DIGITS, |
1288 | MYSQL_TYPE_LONG, |
1289 | 0, |
1290 | 0, |
1291 | "Rows written to Groonga" , |
1292 | SKIP_OPEN_TABLE |
1293 | }, |
1294 | { |
1295 | "rows_read" , |
1296 | MY_INT32_NUM_DECIMAL_DIGITS, |
1297 | MYSQL_TYPE_LONG, |
1298 | 0, |
1299 | 0, |
1300 | "Rows read from Groonga" , |
1301 | SKIP_OPEN_TABLE |
1302 | }, |
1303 | { 0, 0, MYSQL_TYPE_NULL, 0, 0, 0, 0} |
1304 | }; |
1305 | |
1306 | static int i_s_mrn_stats_deinit(void* p) |
1307 | { |
1308 | MRN_DBUG_ENTER_FUNCTION(); |
1309 | DBUG_RETURN(0); |
1310 | } |
1311 | |
1312 | static int i_s_mrn_stats_fill( |
1313 | THD* thd, TABLE_LIST* tables, Item* cond) |
1314 | { |
1315 | TABLE* table = (TABLE *) tables->table; |
1316 | int status = 0; |
1317 | MRN_DBUG_ENTER_FUNCTION(); |
1318 | table->field[0]->store(grn_get_version(), strlen(grn_get_version()), |
1319 | system_charset_info); |
1320 | table->field[0]->set_notnull(); |
1321 | table->field[1]->store(1); /* TODO */ |
1322 | table->field[2]->store(2); /* TODO */ |
1323 | if (schema_table_store_record(thd, table)) { |
1324 | status = 1; |
1325 | } |
1326 | DBUG_RETURN(status); |
1327 | } |
1328 | |
1329 | static int i_s_mrn_stats_init(void* p) |
1330 | { |
1331 | MRN_DBUG_ENTER_FUNCTION(); |
1332 | ST_SCHEMA_TABLE* schema = (ST_SCHEMA_TABLE*) p; |
1333 | schema->fields_info = i_s_mrn_stats_fields_info; |
1334 | schema->fill_table = i_s_mrn_stats_fill; |
1335 | DBUG_RETURN(0); |
1336 | } |
1337 | |
1338 | struct st_mysql_plugin i_s_mrn_stats = |
1339 | { |
1340 | MYSQL_INFORMATION_SCHEMA_PLUGIN, |
1341 | &i_s_info, |
1342 | MRN_STATUS_VARIABLE_NAME_PREFIX_STRING "_stats" , |
1343 | MRN_PLUGIN_AUTHOR, |
1344 | "Statistics for " MRN_PLUGIN_NAME_STRING, |
1345 | PLUGIN_LICENSE_GPL, |
1346 | i_s_mrn_stats_init, |
1347 | #ifdef MRN_ST_MYSQL_PLUGIN_HAVE_CHECK_UNINSTALL |
1348 | NULL, |
1349 | #endif |
1350 | i_s_mrn_stats_deinit, |
1351 | MRN_VERSION_IN_HEX, |
1352 | NULL, |
1353 | NULL, |
1354 | MRN_PLUGIN_LAST_VALUES |
1355 | }; |
1356 | /* End of mroonga information schema implementations */ |
1357 | |
1358 | static handler *mrn_handler_create(handlerton *hton, |
1359 | TABLE_SHARE *share, |
1360 | #ifdef MRN_HANDLERTON_CREATE_HAVE_PARTITIONED |
1361 | bool partitioned, |
1362 | #endif |
1363 | MEM_ROOT *root) |
1364 | { |
1365 | MRN_DBUG_ENTER_FUNCTION(); |
1366 | handler *new_handler = new (root) ha_mroonga(hton, share); |
1367 | DBUG_RETURN(new_handler); |
1368 | } |
1369 | |
1370 | static void mrn_drop_database(handlerton *hton, char *path) |
1371 | { |
1372 | MRN_DBUG_ENTER_FUNCTION(); |
1373 | mrn_db_manager->drop(path); |
1374 | DBUG_VOID_RETURN; |
1375 | } |
1376 | |
1377 | static int mrn_close_connection(handlerton *hton, THD *thd) |
1378 | { |
1379 | MRN_DBUG_ENTER_FUNCTION(); |
1380 | void *p = *thd_ha_data(thd, mrn_hton_ptr); |
1381 | if (p) { |
1382 | mrn_clear_slot_data(thd); |
1383 | free(p); |
1384 | *thd_ha_data(thd, mrn_hton_ptr) = (void *) NULL; |
1385 | { |
1386 | mrn::Lock lock(&mrn_allocated_thds_mutex); |
1387 | my_hash_delete(&mrn_allocated_thds, (uchar*) thd); |
1388 | } |
1389 | } |
1390 | DBUG_RETURN(0); |
1391 | } |
1392 | |
1393 | #ifdef MRN_FLUSH_LOGS_HAVE_BINLOG_GROUP_FLUSH |
1394 | static bool mrn_flush_logs(handlerton *hton, bool binlog_group_flush) |
1395 | #else |
1396 | static bool mrn_flush_logs(handlerton *hton) |
1397 | #endif |
1398 | { |
1399 | MRN_DBUG_ENTER_FUNCTION(); |
1400 | bool result = 0; |
1401 | if (mrn_log_file_opened) { |
1402 | mrn::Lock lock(&mrn_log_mutex); |
1403 | fclose(mrn_log_file); |
1404 | mrn_log_file = fopen(mrn_log_file_path, "a" ); |
1405 | } |
1406 | DBUG_RETURN(result); |
1407 | } |
1408 | |
1409 | static grn_builtin_type mrn_grn_type_from_field(grn_ctx *ctx, Field *field, |
1410 | bool for_index_key) |
1411 | { |
1412 | grn_builtin_type type = GRN_DB_VOID; |
1413 | enum_field_types mysql_field_type = field->real_type(); |
1414 | switch (mysql_field_type) { |
1415 | case MYSQL_TYPE_DECIMAL: // DECIMAL; <= 65bytes |
1416 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1417 | break; |
1418 | case MYSQL_TYPE_TINY: // TINYINT; 1byte |
1419 | if (static_cast<Field_num *>(field)->unsigned_flag) { |
1420 | type = GRN_DB_UINT8; // 1byte |
1421 | } else { |
1422 | type = GRN_DB_INT8; // 1byte |
1423 | } |
1424 | break; |
1425 | case MYSQL_TYPE_SHORT: // SMALLINT; 2bytes |
1426 | if (static_cast<Field_num *>(field)->unsigned_flag) { |
1427 | type = GRN_DB_UINT16; // 2bytes |
1428 | } else { |
1429 | type = GRN_DB_INT16; // 2bytes |
1430 | } |
1431 | break; |
1432 | case MYSQL_TYPE_LONG: // INT; 4bytes |
1433 | if (static_cast<Field_num *>(field)->unsigned_flag) { |
1434 | type = GRN_DB_UINT32; // 4bytes |
1435 | } else { |
1436 | type = GRN_DB_INT32; // 4bytes |
1437 | } |
1438 | break; |
1439 | case MYSQL_TYPE_FLOAT: // FLOAT; 4 or 8bytes |
1440 | case MYSQL_TYPE_DOUBLE: // DOUBLE; 8bytes |
1441 | type = GRN_DB_FLOAT; // 8bytes |
1442 | break; |
1443 | case MYSQL_TYPE_NULL: // NULL; 1byte |
1444 | type = GRN_DB_INT8; // 1byte |
1445 | break; |
1446 | case MYSQL_TYPE_TIMESTAMP: // TIMESTAMP; 4bytes |
1447 | type = GRN_DB_TIME; // 8bytes |
1448 | break; |
1449 | case MYSQL_TYPE_LONGLONG: // BIGINT; 8bytes |
1450 | if (static_cast<Field_num *>(field)->unsigned_flag) { |
1451 | type = GRN_DB_UINT64; // 8bytes |
1452 | } else { |
1453 | type = GRN_DB_INT64; // 8bytes |
1454 | } |
1455 | break; |
1456 | case MYSQL_TYPE_INT24: // MEDIUMINT; 3bytes |
1457 | if (static_cast<Field_num *>(field)->unsigned_flag) { |
1458 | type = GRN_DB_UINT32; // 4bytes |
1459 | } else { |
1460 | type = GRN_DB_INT32; // 4bytes |
1461 | } |
1462 | break; |
1463 | case MYSQL_TYPE_DATE: // DATE; 4bytes |
1464 | case MYSQL_TYPE_TIME: // TIME; 3bytes |
1465 | case MYSQL_TYPE_DATETIME: // DATETIME; 8bytes |
1466 | case MYSQL_TYPE_YEAR: // YEAR; 1byte |
1467 | case MYSQL_TYPE_NEWDATE: // DATE; 3bytes |
1468 | type = GRN_DB_TIME; // 8bytes |
1469 | break; |
1470 | case MYSQL_TYPE_VARCHAR: // VARCHAR; <= 64KB * 4 + 2bytes |
1471 | if (for_index_key) { |
1472 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1473 | } else { |
1474 | if (field->field_length <= MRN_SHORT_TEXT_SIZE) { |
1475 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1476 | } else if (field->field_length <= MRN_TEXT_SIZE) { |
1477 | type = GRN_DB_TEXT; // 64Kbytes |
1478 | } else { |
1479 | type = GRN_DB_LONG_TEXT; // 2Gbytes |
1480 | } |
1481 | } |
1482 | break; |
1483 | case MYSQL_TYPE_BIT: // BIT; <= 8bytes |
1484 | type = GRN_DB_INT64; // 8bytes |
1485 | break; |
1486 | #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2 |
1487 | case MYSQL_TYPE_TIMESTAMP2: // TIMESTAMP; 4bytes |
1488 | type = GRN_DB_TIME; // 8bytes |
1489 | break; |
1490 | #endif |
1491 | #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 |
1492 | case MYSQL_TYPE_DATETIME2: // DATETIME; 8bytes |
1493 | type = GRN_DB_TIME; // 8bytes |
1494 | break; |
1495 | #endif |
1496 | #ifdef MRN_HAVE_MYSQL_TYPE_TIME2 |
1497 | case MYSQL_TYPE_TIME2: // TIME(FSP); 3 + (FSP + 1) / 2 bytes |
1498 | // 0 <= FSP <= 6; 3-6bytes |
1499 | type = GRN_DB_TIME; // 8bytes |
1500 | break; |
1501 | #endif |
1502 | case MYSQL_TYPE_NEWDECIMAL: // DECIMAL; <= 9bytes |
1503 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1504 | break; |
1505 | case MYSQL_TYPE_ENUM: // ENUM; <= 2bytes |
1506 | if (field->pack_length() == 1) { |
1507 | type = GRN_DB_UINT8; // 1bytes |
1508 | } else { |
1509 | type = GRN_DB_UINT16; // 2bytes |
1510 | } |
1511 | break; |
1512 | case MYSQL_TYPE_SET: // SET; <= 8bytes |
1513 | switch (field->pack_length()) { |
1514 | case 1: |
1515 | type = GRN_DB_UINT8; // 1byte |
1516 | break; |
1517 | case 2: |
1518 | type = GRN_DB_UINT16; // 2bytes |
1519 | break; |
1520 | case 3: |
1521 | case 4: |
1522 | type = GRN_DB_UINT32; // 3bytes |
1523 | break; |
1524 | case 8: |
1525 | default: |
1526 | type = GRN_DB_UINT64; // 8bytes |
1527 | break; |
1528 | } |
1529 | break; |
1530 | case MYSQL_TYPE_TINY_BLOB: // TINYBLOB; <= 256bytes + 1byte |
1531 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1532 | break; |
1533 | case MYSQL_TYPE_MEDIUM_BLOB: // MEDIUMBLOB; <= 16Mbytes + 3bytes |
1534 | if (for_index_key) { |
1535 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1536 | } else { |
1537 | type = GRN_DB_LONG_TEXT; // 2Gbytes |
1538 | } |
1539 | break; |
1540 | case MYSQL_TYPE_LONG_BLOB: // LONGBLOB; <= 4Gbytes + 4bytes |
1541 | if (for_index_key) { |
1542 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1543 | } else { |
1544 | type = GRN_DB_LONG_TEXT; // 2Gbytes |
1545 | } |
1546 | break; |
1547 | case MYSQL_TYPE_BLOB: // BLOB; <= 64Kbytes + 2bytes |
1548 | if (for_index_key) { |
1549 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1550 | } else { |
1551 | type = GRN_DB_LONG_TEXT; // 2Gbytes |
1552 | } |
1553 | break; |
1554 | case MYSQL_TYPE_VAR_STRING: // VARCHAR; <= 255byte * 4 + 1bytes |
1555 | if (for_index_key) { |
1556 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1557 | } else { |
1558 | if (field->field_length <= MRN_SHORT_TEXT_SIZE) { |
1559 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1560 | } else if (field->field_length <= MRN_TEXT_SIZE) { |
1561 | type = GRN_DB_TEXT; // 64Kbytes |
1562 | } else { |
1563 | type = GRN_DB_LONG_TEXT; // 2Gbytes |
1564 | } |
1565 | } |
1566 | break; |
1567 | case MYSQL_TYPE_STRING: // CHAR; < 1Kbytes =~ (255 * 4)bytes |
1568 | // 4 is the maximum size of a character |
1569 | type = GRN_DB_SHORT_TEXT; // 4Kbytes |
1570 | break; |
1571 | case MYSQL_TYPE_GEOMETRY: // case-by-case |
1572 | type = GRN_DB_WGS84_GEO_POINT; // 8bytes |
1573 | break; |
1574 | case MYSQL_TYPE_VARCHAR_COMPRESSED: |
1575 | case MYSQL_TYPE_BLOB_COMPRESSED: |
1576 | DBUG_ASSERT(0); |
1577 | #ifdef MRN_HAVE_MYSQL_TYPE_JSON |
1578 | case MYSQL_TYPE_JSON: |
1579 | type = GRN_DB_TEXT; |
1580 | break; |
1581 | #endif |
1582 | } |
1583 | return type; |
1584 | } |
1585 | |
1586 | static bool mrn_parse_grn_column_create_flags(THD *thd, |
1587 | grn_ctx *ctx, |
1588 | const char *flag_names, |
1589 | uint flag_names_length, |
1590 | grn_obj_flags *column_flags) |
1591 | { |
1592 | const char *flag_names_end = flag_names + flag_names_length; |
1593 | bool found = false; |
1594 | |
1595 | while (flag_names < flag_names_end) { |
1596 | uint rest_length = flag_names_end - flag_names; |
1597 | |
1598 | if (*flag_names == '|' || *flag_names == ' ') { |
1599 | flag_names += 1; |
1600 | continue; |
1601 | } |
1602 | if (rest_length >= 13 && !memcmp(flag_names, "COLUMN_SCALAR" , 13)) { |
1603 | *column_flags |= GRN_OBJ_COLUMN_SCALAR; |
1604 | flag_names += 13; |
1605 | found = true; |
1606 | } else if (rest_length >= 13 && !memcmp(flag_names, "COLUMN_VECTOR" , 13)) { |
1607 | *column_flags |= GRN_OBJ_COLUMN_VECTOR; |
1608 | flag_names += 13; |
1609 | found = true; |
1610 | } else if (rest_length >= 13 && !memcmp(flag_names, "COMPRESS_ZLIB" , 13)) { |
1611 | if (mrn_libgroonga_support_zlib) { |
1612 | *column_flags |= GRN_OBJ_COMPRESS_ZLIB; |
1613 | found = true; |
1614 | } else { |
1615 | push_warning_printf(thd, MRN_SEVERITY_WARNING, |
1616 | ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM, |
1617 | ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR, |
1618 | "COMPRESS_ZLIB" ); |
1619 | } |
1620 | flag_names += 13; |
1621 | } else if (rest_length >= 12 && !memcmp(flag_names, "COMPRESS_LZ4" , 12)) { |
1622 | if (mrn_libgroonga_support_lz4) { |
1623 | *column_flags |= GRN_OBJ_COMPRESS_LZ4; |
1624 | found = true; |
1625 | } else { |
1626 | push_warning_printf(thd, MRN_SEVERITY_WARNING, |
1627 | ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM, |
1628 | ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR, |
1629 | "COMPRESS_LZ4" ); |
1630 | } |
1631 | flag_names += 12; |
1632 | } else if (rest_length >= 13 && !memcmp(flag_names, "COMPRESS_ZSTD" , 13)) { |
1633 | if (mrn_libgroonga_support_zstd) { |
1634 | *column_flags |= GRN_OBJ_COMPRESS_ZSTD; |
1635 | found = true; |
1636 | } else { |
1637 | push_warning_printf(thd, MRN_SEVERITY_WARNING, |
1638 | ER_MRN_UNSUPPORTED_COLUMN_FLAG_NUM, |
1639 | ER_MRN_UNSUPPORTED_COLUMN_FLAG_STR, |
1640 | "COMPRESS_ZSTD" ); |
1641 | } |
1642 | flag_names += 13; |
1643 | } else { |
1644 | char invalid_flag_name[MRN_MESSAGE_BUFFER_SIZE]; |
1645 | snprintf(invalid_flag_name, MRN_MESSAGE_BUFFER_SIZE, |
1646 | "%.*s" , |
1647 | static_cast<int>(rest_length), |
1648 | flag_names); |
1649 | push_warning_printf(thd, MRN_SEVERITY_WARNING, |
1650 | ER_MRN_INVALID_COLUMN_FLAG_NUM, |
1651 | ER_MRN_INVALID_COLUMN_FLAG_STR, |
1652 | invalid_flag_name); |
1653 | break; |
1654 | } |
1655 | } |
1656 | return found; |
1657 | } |
1658 | |
1659 | static bool mrn_parse_grn_index_column_flags(THD *thd, |
1660 | grn_ctx *ctx, |
1661 | const char *flag_names, |
1662 | uint flag_names_length, |
1663 | grn_column_flags *index_column_flags) |
1664 | { |
1665 | const char *flag_names_end = flag_names + flag_names_length; |
1666 | bool found = false; |
1667 | |
1668 | while (flag_names < flag_names_end) { |
1669 | uint rest_length = flag_names_end - flag_names; |
1670 | |
1671 | if (*flag_names == '|' || *flag_names == ' ') { |
1672 | flag_names += 1; |
1673 | continue; |
1674 | } |
1675 | if (rest_length >= 4 && !memcmp(flag_names, "NONE" , 4)) { |
1676 | flag_names += 4; |
1677 | found = true; |
1678 | } else if (rest_length >= 13 && !memcmp(flag_names, "WITH_POSITION" , 13)) { |
1679 | *index_column_flags |= GRN_OBJ_WITH_POSITION; |
1680 | flag_names += 13; |
1681 | found = true; |
1682 | } else if (rest_length >= 12 && !memcmp(flag_names, "WITH_SECTION" , 12)) { |
1683 | *index_column_flags |= GRN_OBJ_WITH_SECTION; |
1684 | flag_names += 12; |
1685 | found = true; |
1686 | } else if (rest_length >= 11 && !memcmp(flag_names, "WITH_WEIGHT" , 11)) { |
1687 | *index_column_flags |= GRN_OBJ_WITH_WEIGHT; |
1688 | flag_names += 11; |
1689 | found = true; |
1690 | } else if (rest_length >= 11 && !memcmp(flag_names, "INDEX_SMALL" , 11)) { |
1691 | *index_column_flags |= GRN_OBJ_INDEX_SMALL; |
1692 | flag_names += 11; |
1693 | found = true; |
1694 | } else if (rest_length >= 12 && !memcmp(flag_names, "INDEX_MEDIUM" , 12)) { |
1695 | *index_column_flags |= GRN_OBJ_INDEX_MEDIUM; |
1696 | flag_names += 12; |
1697 | found = true; |
1698 | } else { |
1699 | char invalid_flag_name[MRN_MESSAGE_BUFFER_SIZE]; |
1700 | snprintf(invalid_flag_name, MRN_MESSAGE_BUFFER_SIZE, |
1701 | "%.*s" , |
1702 | static_cast<int>(rest_length), |
1703 | flag_names); |
1704 | push_warning_printf(thd, MRN_SEVERITY_WARNING, |
1705 | ER_MRN_INVALID_INDEX_FLAG_NUM, |
1706 | ER_MRN_INVALID_INDEX_FLAG_STR, |
1707 | invalid_flag_name); |
1708 | } |
1709 | } |
1710 | return found; |
1711 | } |
1712 | |
1713 | #ifdef MRN_HAVE_SPATIAL |
1714 | static int mrn_set_geometry(grn_ctx *ctx, grn_obj *buf, |
1715 | const char *wkb, uint wkb_size) |
1716 | { |
1717 | int error = 0; |
1718 | Geometry_buffer buffer; |
1719 | Geometry *geometry; |
1720 | |
1721 | geometry = Geometry::construct(&buffer, wkb, wkb_size); |
1722 | if (!geometry) { |
1723 | return ER_CANT_CREATE_GEOMETRY_OBJECT; |
1724 | } |
1725 | switch (geometry->get_class_info()->m_type_id) { |
1726 | case Geometry::wkb_point: |
1727 | { |
1728 | Gis_point *point = (Gis_point *)geometry; |
1729 | double latitude = 0.0, longitude = 0.0; |
1730 | #ifdef MRN_HAVE_POINT_XY |
1731 | point_xy xy(0.0, 0.0); |
1732 | point->get_xy(&xy); |
1733 | longitude = xy.x; |
1734 | latitude = xy.y; |
1735 | #else |
1736 | point->get_xy(&longitude, &latitude); |
1737 | #endif |
1738 | grn_obj_reinit(ctx, buf, GRN_DB_WGS84_GEO_POINT, 0); |
1739 | GRN_GEO_POINT_SET(ctx, buf, |
1740 | GRN_GEO_DEGREE2MSEC(latitude), |
1741 | GRN_GEO_DEGREE2MSEC(longitude)); |
1742 | break; |
1743 | } |
1744 | default: |
1745 | my_printf_error(ER_MRN_GEOMETRY_NOT_SUPPORT_NUM, |
1746 | ER_MRN_GEOMETRY_NOT_SUPPORT_STR, MYF(0)); |
1747 | error = ER_MRN_GEOMETRY_NOT_SUPPORT_NUM; |
1748 | break; |
1749 | } |
1750 | MRN_GEOMETRY_FREE(geometry); |
1751 | |
1752 | return error; |
1753 | } |
1754 | #endif |
1755 | |
1756 | #ifdef MRN_HAVE_HTON_ALTER_TABLE_FLAGS |
1757 | static alter_table_operations mrn_alter_table_flags(alter_table_operations flags) |
1758 | { |
1759 | ulonglong alter_flags = 0; |
1760 | #ifdef HA_INPLACE_ADD_INDEX_NO_READ_WRITE |
1761 | bool is_inplace_index_change; |
1762 | # ifdef MRN_HAVE_ALTER_INFO |
1763 | is_inplace_index_change = (((flags & ALTER_ADD_INDEX) && |
1764 | (flags & ALTER_DROP_INDEX)) || |
1765 | (flags & ALTER_CHANGE_COLUMN)); |
1766 | # else |
1767 | is_inplace_index_change = (((flags & ALTER_ADD_INDEX) && |
1768 | (flags & ALTER_DROP_INDEX)) || |
1769 | (flags & ALTER_CHANGE_COLUMN)); |
1770 | # endif |
1771 | if (!is_inplace_index_change) { |
1772 | alter_flags |= |
1773 | HA_INPLACE_ADD_INDEX_NO_READ_WRITE | |
1774 | HA_INPLACE_DROP_INDEX_NO_READ_WRITE | |
1775 | HA_INPLACE_ADD_UNIQUE_INDEX_NO_READ_WRITE | |
1776 | HA_INPLACE_DROP_UNIQUE_INDEX_NO_READ_WRITE | |
1777 | HA_INPLACE_ADD_INDEX_NO_WRITE | |
1778 | HA_INPLACE_DROP_INDEX_NO_WRITE | |
1779 | HA_INPLACE_ADD_UNIQUE_INDEX_NO_WRITE | |
1780 | HA_INPLACE_DROP_UNIQUE_INDEX_NO_WRITE; |
1781 | } |
1782 | #endif |
1783 | return alter_flags; |
1784 | } |
1785 | #endif |
1786 | |
1787 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
1788 | static ha_create_table_option mrn_field_options[] = |
1789 | { |
1790 | HA_FOPTION_STRING("GROONGA_TYPE" , groonga_type), |
1791 | HA_FOPTION_STRING("FLAGS" , flags), |
1792 | HA_FOPTION_END |
1793 | }; |
1794 | |
1795 | static ha_create_table_option mrn_index_options[] = |
1796 | { |
1797 | HA_IOPTION_STRING("TOKENIZER" , tokenizer), |
1798 | HA_IOPTION_STRING("NORMALIZER" , normalizer), |
1799 | HA_IOPTION_STRING("TOKEN_FILTERS" , token_filters), |
1800 | HA_IOPTION_STRING("FLAGS" , flags), |
1801 | HA_IOPTION_END |
1802 | }; |
1803 | #endif |
1804 | |
1805 | static int mrn_init(void *p) |
1806 | { |
1807 | // init handlerton |
1808 | grn_ctx *ctx = NULL; |
1809 | handlerton *hton = static_cast<handlerton *>(p); |
1810 | hton->state = SHOW_OPTION_YES; |
1811 | hton->create = mrn_handler_create; |
1812 | hton->flags = HTON_NO_FLAGS; |
1813 | #ifndef MRN_SUPPORT_PARTITION |
1814 | hton->flags |= HTON_NO_PARTITION; |
1815 | #endif |
1816 | hton->drop_database = mrn_drop_database; |
1817 | hton->close_connection = mrn_close_connection; |
1818 | hton->flush_logs = mrn_flush_logs; |
1819 | #ifdef MRN_HAVE_HTON_ALTER_TABLE_FLAGS |
1820 | hton->alter_table_flags = mrn_alter_table_flags; |
1821 | #endif |
1822 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
1823 | hton->field_options = mrn_field_options; |
1824 | hton->index_options = mrn_index_options; |
1825 | #endif |
1826 | mrn_hton_ptr = hton; |
1827 | |
1828 | #ifdef _WIN32 |
1829 | HMODULE current_module = GetModuleHandle(NULL); |
1830 | mrn_binlog_filter = |
1831 | *((Rpl_filter **)GetProcAddress(current_module, MRN_BINLOG_FILTER_PROC)); |
1832 | mrn_my_tz_UTC = |
1833 | *((Time_zone **)GetProcAddress(current_module, MRN_MY_TZ_UTC_PROC)); |
1834 | # ifdef MRN_HAVE_TABLE_DEF_CACHE |
1835 | mrn_table_def_cache = (HASH *)GetProcAddress(current_module, |
1836 | "?table_def_cache@@3Ust_hash@@A" ); |
1837 | # endif |
1838 | # ifndef MRN_HAVE_TDC_LOCK_TABLE_SHARE |
1839 | mrn_LOCK_open = |
1840 | (mysql_mutex_t *)GetProcAddress(current_module, |
1841 | "?LOCK_open@@3Ust_mysql_mutex@@A" ); |
1842 | # endif |
1843 | # ifdef HAVE_PSI_INTERFACE |
1844 | # ifdef MRN_TABLE_SHARE_HAVE_LOCK_SHARE |
1845 | mrn_table_share_lock_share = |
1846 | (PSI_mutex_key *)GetProcAddress(current_module, |
1847 | MRN_TABLE_SHARE_LOCK_SHARE_PROC); |
1848 | # endif |
1849 | mrn_table_share_lock_ha_data = |
1850 | (PSI_mutex_key *)GetProcAddress(current_module, |
1851 | MRN_TABLE_SHARE_LOCK_HA_DATA_PROC); |
1852 | # endif |
1853 | #else |
1854 | mrn_binlog_filter = binlog_filter; |
1855 | mrn_my_tz_UTC = my_tz_UTC; |
1856 | # ifdef MRN_HAVE_TABLE_DEF_CACHE |
1857 | mrn_table_def_cache = &table_def_cache; |
1858 | # endif |
1859 | # ifndef MRN_HAVE_TDC_LOCK_TABLE_SHARE |
1860 | mrn_LOCK_open = &LOCK_open; |
1861 | # endif |
1862 | #endif |
1863 | |
1864 | #ifdef MRN_HAVE_PSI_SERVER |
1865 | if (PSI_server) { |
1866 | const char *category = "mroonga" ; |
1867 | int n_mutexes = array_elements(mrn_mutexes); |
1868 | PSI_server->register_mutex(category, mrn_mutexes, n_mutexes); |
1869 | } |
1870 | #endif |
1871 | |
1872 | grn_default_query_logger_set_path(mrn_query_log_file_path); |
1873 | |
1874 | if (grn_init() != GRN_SUCCESS) { |
1875 | goto err_grn_init; |
1876 | } |
1877 | |
1878 | grn_set_lock_timeout(mrn_lock_timeout); |
1879 | |
1880 | mrn_init_encoding_map(); |
1881 | |
1882 | grn_ctx_init(&mrn_ctx, 0); |
1883 | ctx = &mrn_ctx; |
1884 | if (mrn_change_encoding(ctx, system_charset_info)) |
1885 | goto err_mrn_change_encoding; |
1886 | |
1887 | #ifdef MRN_HAVE_PSI_MEMORY_KEY |
1888 | { |
1889 | const char *category = "ha_mroonga" ; |
1890 | int n_keys = array_elements(mrn_all_memory_keys); |
1891 | mysql_memory_register(category, mrn_all_memory_keys, n_keys); |
1892 | } |
1893 | #endif |
1894 | |
1895 | if (mysql_mutex_init(mrn_log_mutex_key, |
1896 | &mrn_log_mutex, |
1897 | MY_MUTEX_INIT_FAST) != 0) { |
1898 | goto err_log_mutex_init; |
1899 | } |
1900 | if (mysql_mutex_init(mrn_query_log_mutex_key, |
1901 | &mrn_query_log_mutex, |
1902 | MY_MUTEX_INIT_FAST) != 0) { |
1903 | goto err_query_log_mutex_init; |
1904 | } |
1905 | |
1906 | mrn_logger.max_level = static_cast<grn_log_level>(mrn_log_level); |
1907 | grn_logger_set(ctx, &mrn_logger); |
1908 | if (!(mrn_log_file = fopen(mrn_log_file_path, "a" ))) { |
1909 | goto err_log_file_open; |
1910 | } |
1911 | mrn_log_file_opened = true; |
1912 | GRN_LOG(ctx, GRN_LOG_NOTICE, "%s started." , MRN_PACKAGE_STRING); |
1913 | GRN_LOG(ctx, GRN_LOG_NOTICE, "log level is '%s'" , |
1914 | mrn_log_level_type_names[mrn_log_level]); |
1915 | |
1916 | // init meta-info database |
1917 | if (!(mrn_db = grn_db_create(ctx, NULL, NULL))) { |
1918 | GRN_LOG(ctx, GRN_LOG_ERROR, "cannot create system database, exiting" ); |
1919 | goto err_db_create; |
1920 | } |
1921 | grn_ctx_use(ctx, mrn_db); |
1922 | |
1923 | grn_ctx_init(&mrn_db_manager_ctx, 0); |
1924 | grn_logger_set(&mrn_db_manager_ctx, &mrn_logger); |
1925 | if (mysql_mutex_init(mrn_db_manager_mutex_key, |
1926 | &mrn_db_manager_mutex, |
1927 | MY_MUTEX_INIT_FAST) != 0) { |
1928 | GRN_LOG(&mrn_db_manager_ctx, GRN_LOG_ERROR, |
1929 | "failed to initialize mutex for database manager" ); |
1930 | goto err_db_manager_mutex_init; |
1931 | } |
1932 | mrn_db_manager = new mrn::DatabaseManager(&mrn_db_manager_ctx, |
1933 | &mrn_db_manager_mutex); |
1934 | if (!mrn_db_manager->init()) { |
1935 | goto err_db_manager_init; |
1936 | } |
1937 | |
1938 | if (mysql_mutex_init(mrn_context_pool_mutex_key, |
1939 | &mrn_context_pool_mutex, |
1940 | MY_MUTEX_INIT_FAST) != 0) { |
1941 | GRN_LOG(ctx, GRN_LOG_ERROR, |
1942 | "failed to initialize mutex for context pool" ); |
1943 | goto error_context_pool_mutex_init; |
1944 | } |
1945 | mrn_context_pool = new mrn::ContextPool(&mrn_context_pool_mutex); |
1946 | |
1947 | if (mysql_mutex_init(mrn_operations_mutex_key, |
1948 | &mrn_operations_mutex, |
1949 | MY_MUTEX_INIT_FAST) != 0) { |
1950 | GRN_LOG(ctx, GRN_LOG_ERROR, |
1951 | "failed to initialize mutex for operations" ); |
1952 | goto error_operations_mutex_init; |
1953 | } |
1954 | |
1955 | if ((mysql_mutex_init(mrn_allocated_thds_mutex_key, |
1956 | &mrn_allocated_thds_mutex, |
1957 | MY_MUTEX_INIT_FAST) != 0)) { |
1958 | goto err_allocated_thds_mutex_init; |
1959 | } |
1960 | if (mrn_my_hash_init(&mrn_allocated_thds, system_charset_info, 32, 0, 0, |
1961 | mrn_allocated_thds_get_key, 0, 0)) { |
1962 | goto error_allocated_thds_hash_init; |
1963 | } |
1964 | if ((mysql_mutex_init(mrn_open_tables_mutex_key, |
1965 | &mrn_open_tables_mutex, |
1966 | MY_MUTEX_INIT_FAST) != 0)) { |
1967 | goto err_allocated_open_tables_mutex_init; |
1968 | } |
1969 | if (mrn_my_hash_init(&mrn_open_tables, system_charset_info, 32, 0, 0, |
1970 | mrn_open_tables_get_key, 0, 0)) { |
1971 | goto error_allocated_open_tables_hash_init; |
1972 | } |
1973 | if ((mysql_mutex_init(mrn_long_term_share_mutex_key, |
1974 | &mrn_long_term_share_mutex, |
1975 | MY_MUTEX_INIT_FAST) != 0)) { |
1976 | goto error_allocated_long_term_share_mutex_init; |
1977 | } |
1978 | if (mrn_my_hash_init(&mrn_long_term_share, system_charset_info, 32, 0, 0, |
1979 | mrn_long_term_share_get_key, 0, 0)) { |
1980 | goto error_allocated_long_term_share_hash_init; |
1981 | } |
1982 | |
1983 | #ifdef MRN_USE_MYSQL_DATA_HOME |
1984 | mrn::PathMapper::default_mysql_data_home_path = mysql_data_home; |
1985 | #endif |
1986 | |
1987 | return 0; |
1988 | |
1989 | error_allocated_long_term_share_hash_init: |
1990 | mysql_mutex_destroy(&mrn_long_term_share_mutex); |
1991 | error_allocated_long_term_share_mutex_init: |
1992 | my_hash_free(&mrn_open_tables); |
1993 | error_allocated_open_tables_hash_init: |
1994 | mysql_mutex_destroy(&mrn_open_tables_mutex); |
1995 | err_allocated_open_tables_mutex_init: |
1996 | my_hash_free(&mrn_allocated_thds); |
1997 | error_allocated_thds_hash_init: |
1998 | mysql_mutex_destroy(&mrn_allocated_thds_mutex); |
1999 | err_allocated_thds_mutex_init: |
2000 | mysql_mutex_destroy(&mrn_operations_mutex); |
2001 | error_operations_mutex_init: |
2002 | delete mrn_context_pool; |
2003 | mysql_mutex_destroy(&mrn_context_pool_mutex); |
2004 | error_context_pool_mutex_init: |
2005 | err_db_manager_init: |
2006 | delete mrn_db_manager; |
2007 | mysql_mutex_destroy(&mrn_db_manager_mutex); |
2008 | err_db_manager_mutex_init: |
2009 | grn_ctx_fin(&mrn_db_manager_ctx); |
2010 | grn_obj_unlink(ctx, mrn_db); |
2011 | err_db_create: |
2012 | if (mrn_log_file_opened) { |
2013 | fclose(mrn_log_file); |
2014 | mrn_log_file_opened = false; |
2015 | } |
2016 | err_log_file_open: |
2017 | mysql_mutex_destroy(&mrn_query_log_mutex); |
2018 | err_query_log_mutex_init: |
2019 | mysql_mutex_destroy(&mrn_log_mutex); |
2020 | err_log_mutex_init: |
2021 | err_mrn_change_encoding: |
2022 | grn_ctx_fin(ctx); |
2023 | grn_fin(); |
2024 | err_grn_init: |
2025 | return -1; |
2026 | } |
2027 | |
2028 | static int mrn_deinit(void *p) |
2029 | { |
2030 | THD *thd = current_thd, *tmp_thd; |
2031 | grn_ctx *ctx = &mrn_ctx; |
2032 | MRN_LONG_TERM_SHARE *long_term_share; |
2033 | |
2034 | GRN_LOG(ctx, GRN_LOG_NOTICE, "%s deinit" , MRN_PACKAGE_STRING); |
2035 | |
2036 | if (thd && thd_sql_command(thd) == SQLCOM_UNINSTALL_PLUGIN) { |
2037 | mrn::Lock lock(&mrn_allocated_thds_mutex); |
2038 | while ((tmp_thd = (THD *) my_hash_element(&mrn_allocated_thds, 0))) |
2039 | { |
2040 | mrn_clear_slot_data(tmp_thd); |
2041 | void *slot_ptr = mrn_get_slot_data(tmp_thd, false); |
2042 | if (slot_ptr) free(slot_ptr); |
2043 | *thd_ha_data(tmp_thd, mrn_hton_ptr) = (void *) NULL; |
2044 | my_hash_delete(&mrn_allocated_thds, (uchar *) tmp_thd); |
2045 | } |
2046 | } |
2047 | |
2048 | { |
2049 | mrn::Lock lock(&mrn_open_tables_mutex); |
2050 | while ((long_term_share = (MRN_LONG_TERM_SHARE *) |
2051 | my_hash_element(&mrn_long_term_share, 0))) |
2052 | { |
2053 | mrn_free_long_term_share(long_term_share); |
2054 | } |
2055 | } |
2056 | |
2057 | my_hash_free(&mrn_long_term_share); |
2058 | mysql_mutex_destroy(&mrn_long_term_share_mutex); |
2059 | my_hash_free(&mrn_open_tables); |
2060 | mysql_mutex_destroy(&mrn_open_tables_mutex); |
2061 | my_hash_free(&mrn_allocated_thds); |
2062 | mysql_mutex_destroy(&mrn_allocated_thds_mutex); |
2063 | mysql_mutex_destroy(&mrn_operations_mutex); |
2064 | delete mrn_context_pool; |
2065 | mysql_mutex_destroy(&mrn_context_pool_mutex); |
2066 | delete mrn_db_manager; |
2067 | mysql_mutex_destroy(&mrn_db_manager_mutex); |
2068 | grn_ctx_fin(&mrn_db_manager_ctx); |
2069 | |
2070 | grn_obj_unlink(ctx, mrn_db); |
2071 | grn_ctx_fin(ctx); |
2072 | grn_fin(); |
2073 | |
2074 | if (mrn_log_file_opened) { |
2075 | fclose(mrn_log_file); |
2076 | mrn_log_file_opened = false; |
2077 | } |
2078 | mysql_mutex_destroy(&mrn_query_log_mutex); |
2079 | mysql_mutex_destroy(&mrn_log_mutex); |
2080 | |
2081 | return 0; |
2082 | } |
2083 | |
2084 | mrn_declare_plugin(MRN_PLUGIN_NAME) |
2085 | { |
2086 | MYSQL_STORAGE_ENGINE_PLUGIN, |
2087 | &storage_engine_structure, |
2088 | MRN_PLUGIN_NAME_STRING, |
2089 | MRN_PLUGIN_AUTHOR, |
2090 | "CJK-ready fulltext search, column store" , |
2091 | PLUGIN_LICENSE_GPL, |
2092 | mrn_init, |
2093 | mrn_deinit, |
2094 | MRN_VERSION_IN_HEX, |
2095 | mrn_status_variables, |
2096 | mrn_system_variables, |
2097 | MRN_PLUGIN_LAST_VALUES |
2098 | }, |
2099 | i_s_mrn_stats |
2100 | mrn_declare_plugin_end; |
2101 | |
2102 | static double mrn_get_score_value(grn_obj *score) |
2103 | { |
2104 | MRN_DBUG_ENTER_FUNCTION(); |
2105 | double score_value; |
2106 | if (score->header.domain == GRN_DB_FLOAT) { |
2107 | score_value = GRN_FLOAT_VALUE(score); |
2108 | } else { |
2109 | score_value = (double)GRN_INT32_VALUE(score); |
2110 | } |
2111 | DBUG_RETURN(score_value); |
2112 | } |
2113 | |
2114 | static void mrn_generic_ft_clear(FT_INFO *handler) |
2115 | { |
2116 | MRN_DBUG_ENTER_FUNCTION(); |
2117 | st_mrn_ft_info *info = (st_mrn_ft_info *)handler; |
2118 | if (!info->ctx) { |
2119 | DBUG_VOID_RETURN; |
2120 | } |
2121 | |
2122 | if (info->cursor) { |
2123 | grn_obj_unlink(info->ctx, info->cursor); |
2124 | } |
2125 | if (info->id_accessor) { |
2126 | grn_obj_unlink(info->ctx, info->id_accessor); |
2127 | } |
2128 | if (info->key_accessor) { |
2129 | grn_obj_unlink(info->ctx, info->key_accessor); |
2130 | } |
2131 | grn_obj_unlink(info->ctx, info->result); |
2132 | grn_obj_unlink(info->ctx, info->score_column); |
2133 | grn_obj_unlink(info->ctx, &(info->key)); |
2134 | grn_obj_unlink(info->ctx, &(info->score)); |
2135 | |
2136 | info->ctx = NULL; |
2137 | |
2138 | DBUG_VOID_RETURN; |
2139 | } |
2140 | |
2141 | static void mrn_generic_ft_close_search(FT_INFO *handler) |
2142 | { |
2143 | MRN_DBUG_ENTER_FUNCTION(); |
2144 | st_mrn_ft_info *info = (st_mrn_ft_info *)handler; |
2145 | mrn_generic_ft_clear(handler); |
2146 | delete info; |
2147 | DBUG_VOID_RETURN; |
2148 | } |
2149 | |
2150 | static int mrn_wrapper_ft_read_next(FT_INFO *handler, char *record) |
2151 | { |
2152 | MRN_DBUG_ENTER_FUNCTION(); |
2153 | DBUG_RETURN(HA_ERR_END_OF_FILE); |
2154 | } |
2155 | |
2156 | static float mrn_wrapper_ft_find_relevance(FT_INFO *handler, uchar *record, |
2157 | uint length) |
2158 | { |
2159 | MRN_DBUG_ENTER_FUNCTION(); |
2160 | st_mrn_ft_info *info = (st_mrn_ft_info *)handler; |
2161 | float score = 0.0; |
2162 | grn_id record_id; |
2163 | |
2164 | mrn_change_encoding(info->ctx, NULL); |
2165 | key_copy((uchar *)(GRN_TEXT_VALUE(&(info->key))), record, |
2166 | info->primary_key_info, info->primary_key_info->key_length); |
2167 | record_id = grn_table_get(info->ctx, |
2168 | info->table, |
2169 | GRN_TEXT_VALUE(&(info->key)), |
2170 | GRN_TEXT_LEN(&(info->key))); |
2171 | |
2172 | if (record_id != GRN_ID_NIL) { |
2173 | grn_id result_record_id; |
2174 | result_record_id = grn_table_get(info->ctx, info->result, |
2175 | &record_id, sizeof(grn_id)); |
2176 | if (result_record_id != GRN_ID_NIL) { |
2177 | GRN_BULK_REWIND(&(info->score)); |
2178 | grn_obj_get_value(info->ctx, info->score_column, |
2179 | result_record_id, &(info->score)); |
2180 | score = mrn_get_score_value(&(info->score)); |
2181 | } |
2182 | } |
2183 | |
2184 | DBUG_PRINT("info" , |
2185 | ("mroonga: record_id=%d score=%g" , record_id, score)); |
2186 | |
2187 | DBUG_RETURN(score); |
2188 | } |
2189 | |
2190 | static void mrn_wrapper_ft_close_search(FT_INFO *handler) |
2191 | { |
2192 | MRN_DBUG_ENTER_FUNCTION(); |
2193 | mrn_generic_ft_close_search(handler); |
2194 | DBUG_VOID_RETURN; |
2195 | } |
2196 | |
2197 | static float mrn_wrapper_ft_get_relevance(FT_INFO *handler) |
2198 | { |
2199 | MRN_DBUG_ENTER_FUNCTION(); |
2200 | st_mrn_ft_info *info = (st_mrn_ft_info *)handler; |
2201 | float score = 0.0; |
2202 | grn_id record_id; |
2203 | ha_mroonga *mroonga = info->mroonga; |
2204 | mrn_change_encoding(info->ctx, NULL); |
2205 | record_id = grn_table_get(info->ctx, |
2206 | info->table, |
2207 | GRN_TEXT_VALUE(&(mroonga->key_buffer)), |
2208 | GRN_TEXT_LEN(&(mroonga->key_buffer))); |
2209 | |
2210 | if (record_id != GRN_ID_NIL) { |
2211 | grn_id result_record_id; |
2212 | result_record_id = grn_table_get(info->ctx, info->result, |
2213 | &record_id, sizeof(grn_id)); |
2214 | if (result_record_id != GRN_ID_NIL) { |
2215 | GRN_BULK_REWIND(&(info->score)); |
2216 | grn_obj_get_value(info->ctx, info->score_column, |
2217 | result_record_id, &(info->score)); |
2218 | score = mrn_get_score_value(&(info->score)); |
2219 | } |
2220 | } |
2221 | |
2222 | DBUG_PRINT("info" , |
2223 | ("mroonga: record_id=%d score=%g" , record_id, score)); |
2224 | |
2225 | DBUG_RETURN(score); |
2226 | } |
2227 | |
2228 | static void mrn_wrapper_ft_reinit_search(FT_INFO *handler) |
2229 | { |
2230 | MRN_DBUG_ENTER_FUNCTION(); |
2231 | DBUG_VOID_RETURN; |
2232 | } |
2233 | |
2234 | static _ft_vft mrn_wrapper_ft_vft = { |
2235 | mrn_wrapper_ft_read_next, |
2236 | mrn_wrapper_ft_find_relevance, |
2237 | mrn_wrapper_ft_close_search, |
2238 | mrn_wrapper_ft_get_relevance, |
2239 | mrn_wrapper_ft_reinit_search |
2240 | }; |
2241 | |
2242 | static int mrn_storage_ft_read_next(FT_INFO *handler, char *record) |
2243 | { |
2244 | MRN_DBUG_ENTER_FUNCTION(); |
2245 | DBUG_RETURN(HA_ERR_END_OF_FILE); |
2246 | } |
2247 | |
2248 | static float mrn_storage_ft_find_relevance(FT_INFO *handler, uchar *record, |
2249 | uint length) |
2250 | { |
2251 | MRN_DBUG_ENTER_FUNCTION(); |
2252 | st_mrn_ft_info *info = (st_mrn_ft_info *)handler; |
2253 | ha_mroonga *mroonga = info->mroonga; |
2254 | mrn_change_encoding(info->ctx, NULL); |
2255 | |
2256 | float score = 0.0; |
2257 | if (mroonga->record_id != GRN_ID_NIL) { |
2258 | grn_id result_record_id; |
2259 | result_record_id = grn_table_get(info->ctx, info->result, |
2260 | &(mroonga->record_id), sizeof(grn_id)); |
2261 | if (result_record_id != GRN_ID_NIL) { |
2262 | GRN_BULK_REWIND(&(info->score)); |
2263 | grn_obj_get_value(info->ctx, info->score_column, |
2264 | result_record_id, &(info->score)); |
2265 | score = mrn_get_score_value(&(info->score)); |
2266 | } |
2267 | } |
2268 | DBUG_PRINT("info" , ("mroonga: record_id=%d score=%g" , |
2269 | mroonga->record_id, score)); |
2270 | |
2271 | DBUG_RETURN(score); |
2272 | } |
2273 | |
2274 | static void mrn_storage_ft_close_search(FT_INFO *handler) |
2275 | { |
2276 | MRN_DBUG_ENTER_FUNCTION(); |
2277 | mrn_generic_ft_close_search(handler); |
2278 | DBUG_VOID_RETURN; |
2279 | } |
2280 | |
2281 | static float mrn_storage_ft_get_relevance(FT_INFO *handler) |
2282 | { |
2283 | MRN_DBUG_ENTER_FUNCTION(); |
2284 | st_mrn_ft_info *info = (st_mrn_ft_info *)handler; |
2285 | ha_mroonga *mroonga = info->mroonga; |
2286 | mrn_change_encoding(info->ctx, NULL); |
2287 | |
2288 | float score = 0.0; |
2289 | if (mroonga->record_id != GRN_ID_NIL) { |
2290 | grn_id result_record_id; |
2291 | result_record_id = grn_table_get(info->ctx, info->result, |
2292 | &(mroonga->record_id), sizeof(grn_id)); |
2293 | if (result_record_id != GRN_ID_NIL) { |
2294 | GRN_BULK_REWIND(&(info->score)); |
2295 | grn_obj_get_value(info->ctx, info->score_column, |
2296 | result_record_id, &(info->score)); |
2297 | score = mrn_get_score_value(&(info->score)); |
2298 | } |
2299 | } |
2300 | DBUG_PRINT("info" , |
2301 | ("mroonga: record_id=%d score=%g" , mroonga->record_id, score)); |
2302 | |
2303 | DBUG_RETURN(score); |
2304 | } |
2305 | |
2306 | static void mrn_storage_ft_reinit_search(FT_INFO *handler) |
2307 | { |
2308 | MRN_DBUG_ENTER_FUNCTION(); |
2309 | DBUG_VOID_RETURN; |
2310 | } |
2311 | |
2312 | static _ft_vft mrn_storage_ft_vft = { |
2313 | mrn_storage_ft_read_next, |
2314 | mrn_storage_ft_find_relevance, |
2315 | mrn_storage_ft_close_search, |
2316 | mrn_storage_ft_get_relevance, |
2317 | mrn_storage_ft_reinit_search |
2318 | }; |
2319 | |
2320 | static int mrn_no_such_key_ft_read_next(FT_INFO *handler, char *record) |
2321 | { |
2322 | MRN_DBUG_ENTER_FUNCTION(); |
2323 | DBUG_RETURN(HA_ERR_END_OF_FILE); |
2324 | } |
2325 | |
2326 | static float mrn_no_such_key_ft_find_relevance(FT_INFO *handler, uchar *record, |
2327 | uint length) |
2328 | { |
2329 | MRN_DBUG_ENTER_FUNCTION(); |
2330 | DBUG_RETURN(0.0); |
2331 | } |
2332 | |
2333 | static void mrn_no_such_key_ft_close_search(FT_INFO *handler) |
2334 | { |
2335 | MRN_DBUG_ENTER_FUNCTION(); |
2336 | st_mrn_ft_info *info = (st_mrn_ft_info *)handler; |
2337 | delete info; |
2338 | DBUG_VOID_RETURN; |
2339 | } |
2340 | |
2341 | static float mrn_no_such_key_ft_get_relevance(FT_INFO *handler) |
2342 | { |
2343 | MRN_DBUG_ENTER_FUNCTION(); |
2344 | DBUG_RETURN(0.0); |
2345 | } |
2346 | |
2347 | static void mrn_no_such_key_ft_reinit_search(FT_INFO *handler) |
2348 | { |
2349 | MRN_DBUG_ENTER_FUNCTION(); |
2350 | DBUG_VOID_RETURN; |
2351 | } |
2352 | |
2353 | static _ft_vft mrn_no_such_key_ft_vft = { |
2354 | mrn_no_such_key_ft_read_next, |
2355 | mrn_no_such_key_ft_find_relevance, |
2356 | mrn_no_such_key_ft_close_search, |
2357 | mrn_no_such_key_ft_get_relevance, |
2358 | mrn_no_such_key_ft_reinit_search |
2359 | }; |
2360 | |
2361 | #ifdef HA_CAN_FULLTEXT_EXT |
2362 | static uint mrn_generic_ft_get_version() |
2363 | { |
2364 | MRN_DBUG_ENTER_FUNCTION(); |
2365 | // This value is not used in MySQL 5.6.7-rc. So it is |
2366 | // meaningless. It may be used in the future... |
2367 | uint version = 1; |
2368 | DBUG_RETURN(version); |
2369 | } |
2370 | |
2371 | static ulonglong mrn_generic_ft_ext_get_flags() |
2372 | { |
2373 | MRN_DBUG_ENTER_FUNCTION(); |
2374 | // TODO: Should we support FTS_ORDERED_RESULT? |
2375 | // TODO: Shuold we support FTS_DOCID_IN_RESULT? |
2376 | ulonglong flags = 0; |
2377 | DBUG_RETURN(flags); |
2378 | } |
2379 | |
2380 | // This function is used if we enable FTS_DOCID_IN_RESULT flag and the |
2381 | // table has "FTS_DOC_ID" (defined as FTS_DOC_ID_COL_NAME macro) |
2382 | // special name column. Should we support "FTS_DOC_ID" special name |
2383 | // column? |
2384 | // See also sql/sql_optimizer.cc:JOIN::optimize_fts_query(). |
2385 | static ulonglong mrn_generic_ft_ext_get_docid(FT_INFO_EXT *handler) |
2386 | { |
2387 | MRN_DBUG_ENTER_FUNCTION(); |
2388 | ulonglong id = GRN_ID_NIL; |
2389 | DBUG_RETURN(id); |
2390 | } |
2391 | |
2392 | static ulonglong mrn_generic_ft_ext_count_matches(FT_INFO_EXT *handler) |
2393 | { |
2394 | MRN_DBUG_ENTER_FUNCTION(); |
2395 | st_mrn_ft_info *info = reinterpret_cast<st_mrn_ft_info *>(handler); |
2396 | ulonglong n_records = grn_table_size(info->ctx, info->result); |
2397 | DBUG_RETURN(n_records); |
2398 | } |
2399 | |
2400 | static uint mrn_wrapper_ft_ext_get_version() |
2401 | { |
2402 | MRN_DBUG_ENTER_FUNCTION(); |
2403 | uint version = mrn_generic_ft_get_version(); |
2404 | DBUG_RETURN(version); |
2405 | } |
2406 | |
2407 | static ulonglong mrn_wrapper_ft_ext_get_flags() |
2408 | { |
2409 | MRN_DBUG_ENTER_FUNCTION(); |
2410 | ulonglong flags = mrn_generic_ft_ext_get_flags(); |
2411 | DBUG_RETURN(flags); |
2412 | } |
2413 | |
2414 | static ulonglong mrn_wrapper_ft_ext_get_docid(FT_INFO_EXT *handler) |
2415 | { |
2416 | MRN_DBUG_ENTER_FUNCTION(); |
2417 | ulonglong id = mrn_generic_ft_ext_get_docid(handler); |
2418 | DBUG_RETURN(id); |
2419 | } |
2420 | |
2421 | static ulonglong mrn_wrapper_ft_ext_count_matches(FT_INFO_EXT *handler) |
2422 | { |
2423 | MRN_DBUG_ENTER_FUNCTION(); |
2424 | ulonglong n_records = mrn_generic_ft_ext_count_matches(handler); |
2425 | DBUG_RETURN(n_records); |
2426 | } |
2427 | |
2428 | static _ft_vft_ext mrn_wrapper_ft_vft_ext = { |
2429 | mrn_wrapper_ft_ext_get_version, |
2430 | mrn_wrapper_ft_ext_get_flags, |
2431 | mrn_wrapper_ft_ext_get_docid, |
2432 | mrn_wrapper_ft_ext_count_matches |
2433 | }; |
2434 | |
2435 | static uint mrn_storage_ft_ext_get_version() |
2436 | { |
2437 | MRN_DBUG_ENTER_FUNCTION(); |
2438 | uint version = mrn_generic_ft_get_version(); |
2439 | DBUG_RETURN(version); |
2440 | } |
2441 | |
2442 | static ulonglong mrn_storage_ft_ext_get_flags() |
2443 | { |
2444 | MRN_DBUG_ENTER_FUNCTION(); |
2445 | ulonglong flags = mrn_generic_ft_ext_get_flags(); |
2446 | DBUG_RETURN(flags); |
2447 | } |
2448 | |
2449 | static ulonglong mrn_storage_ft_ext_get_docid(FT_INFO_EXT *handler) |
2450 | { |
2451 | MRN_DBUG_ENTER_FUNCTION(); |
2452 | ulonglong id = mrn_generic_ft_ext_get_docid(handler); |
2453 | DBUG_RETURN(id); |
2454 | } |
2455 | |
2456 | static ulonglong mrn_storage_ft_ext_count_matches(FT_INFO_EXT *handler) |
2457 | { |
2458 | MRN_DBUG_ENTER_FUNCTION(); |
2459 | ulonglong n_records = mrn_generic_ft_ext_count_matches(handler); |
2460 | DBUG_RETURN(n_records); |
2461 | } |
2462 | |
2463 | static _ft_vft_ext mrn_storage_ft_vft_ext = { |
2464 | mrn_storage_ft_ext_get_version, |
2465 | mrn_storage_ft_ext_get_flags, |
2466 | mrn_storage_ft_ext_get_docid, |
2467 | mrn_storage_ft_ext_count_matches |
2468 | }; |
2469 | |
2470 | static uint mrn_no_such_key_ft_ext_get_version() |
2471 | { |
2472 | MRN_DBUG_ENTER_FUNCTION(); |
2473 | uint version = mrn_generic_ft_get_version(); |
2474 | DBUG_RETURN(version); |
2475 | } |
2476 | |
2477 | static ulonglong mrn_no_such_key_ft_ext_get_flags() |
2478 | { |
2479 | MRN_DBUG_ENTER_FUNCTION(); |
2480 | ulonglong flags = mrn_generic_ft_ext_get_flags(); |
2481 | DBUG_RETURN(flags); |
2482 | } |
2483 | |
2484 | static ulonglong mrn_no_such_key_ft_ext_get_docid(FT_INFO_EXT *handler) |
2485 | { |
2486 | MRN_DBUG_ENTER_FUNCTION(); |
2487 | ulonglong id = GRN_ID_NIL; |
2488 | DBUG_RETURN(id); |
2489 | } |
2490 | |
2491 | static ulonglong mrn_no_such_key_ft_ext_count_matches(FT_INFO_EXT *handler) |
2492 | { |
2493 | MRN_DBUG_ENTER_FUNCTION(); |
2494 | ulonglong n_records = 0; |
2495 | DBUG_RETURN(n_records); |
2496 | } |
2497 | |
2498 | static _ft_vft_ext mrn_no_such_key_ft_vft_ext = { |
2499 | mrn_no_such_key_ft_ext_get_version, |
2500 | mrn_no_such_key_ft_ext_get_flags, |
2501 | mrn_no_such_key_ft_ext_get_docid, |
2502 | mrn_no_such_key_ft_ext_count_matches |
2503 | }; |
2504 | #endif |
2505 | |
2506 | /* handler implementation */ |
2507 | ha_mroonga::ha_mroonga(handlerton *hton, TABLE_SHARE *share_arg) |
2508 | :handler(hton, share_arg), |
2509 | wrap_handler(NULL), |
2510 | is_clone(false), |
2511 | parent_for_clone(NULL), |
2512 | mem_root_for_clone(NULL), |
2513 | record_id(GRN_ID_NIL), |
2514 | key_id(NULL), |
2515 | del_key_id(NULL), |
2516 | |
2517 | wrap_ft_init_count(0), |
2518 | share(NULL), |
2519 | wrap_key_info(NULL), |
2520 | base_key_info(NULL), |
2521 | |
2522 | analyzed_for_create(false), |
2523 | wrap_handler_for_create(NULL), |
2524 | #ifdef MRN_HANDLER_HAVE_FINAL_ADD_INDEX |
2525 | hnd_add_index(NULL), |
2526 | #endif |
2527 | #ifdef MRN_HANDLER_HAVE_CHECK_IF_SUPPORTED_INPLACE_ALTER |
2528 | alter_key_info_buffer(NULL), |
2529 | #else |
2530 | wrap_alter_key_info(NULL), |
2531 | #endif |
2532 | mrn_lock_type(F_UNLCK), |
2533 | |
2534 | ctx_entity_(), |
2535 | ctx(&ctx_entity_), |
2536 | grn_table(NULL), |
2537 | grn_columns(NULL), |
2538 | grn_column_ranges(NULL), |
2539 | grn_index_tables(NULL), |
2540 | grn_index_columns(NULL), |
2541 | |
2542 | grn_source_column_geo(NULL), |
2543 | cursor_geo(NULL), |
2544 | cursor(NULL), |
2545 | index_table_cursor(NULL), |
2546 | empty_value_records(NULL), |
2547 | empty_value_records_cursor(NULL), |
2548 | |
2549 | sorted_result(NULL), |
2550 | matched_record_keys(NULL), |
2551 | blob_buffers(NULL), |
2552 | |
2553 | dup_key(0), |
2554 | |
2555 | count_skip(false), |
2556 | fast_order_limit(false), |
2557 | fast_order_limit_with_index(false), |
2558 | |
2559 | ignoring_duplicated_key(false), |
2560 | inserting_with_update(false), |
2561 | fulltext_searching(false), |
2562 | ignoring_no_key_columns(false), |
2563 | replacing_(false), |
2564 | written_by_row_based_binlog(0), |
2565 | current_ft_item(NULL), |
2566 | operations_(NULL) |
2567 | { |
2568 | MRN_DBUG_ENTER_METHOD(); |
2569 | grn_ctx_init(ctx, 0); |
2570 | mrn_change_encoding(ctx, system_charset_info); |
2571 | grn_ctx_use(ctx, mrn_db); |
2572 | GRN_WGS84_GEO_POINT_INIT(&top_left_point, 0); |
2573 | GRN_WGS84_GEO_POINT_INIT(&bottom_right_point, 0); |
2574 | GRN_WGS84_GEO_POINT_INIT(&source_point, 0); |
2575 | GRN_TEXT_INIT(&key_buffer, 0); |
2576 | GRN_TEXT_INIT(&encoded_key_buffer, 0); |
2577 | GRN_VOID_INIT(&old_value_buffer); |
2578 | GRN_VOID_INIT(&new_value_buffer); |
2579 | DBUG_VOID_RETURN; |
2580 | } |
2581 | |
2582 | ha_mroonga::~ha_mroonga() |
2583 | { |
2584 | MRN_DBUG_ENTER_METHOD(); |
2585 | |
2586 | delete operations_; |
2587 | |
2588 | if (analyzed_for_create) { |
2589 | if (wrap_handler_for_create) { |
2590 | delete wrap_handler_for_create; |
2591 | } |
2592 | if (share_for_create.wrapper_mode) { |
2593 | plugin_unlock(NULL, share_for_create.plugin); |
2594 | } |
2595 | if (share_for_create.table_name) { |
2596 | my_free(share_for_create.table_name); |
2597 | } |
2598 | mrn_free_share_alloc(&share_for_create); |
2599 | free_root(&mem_root_for_create, MYF(0)); |
2600 | } |
2601 | if (blob_buffers) |
2602 | { |
2603 | delete [] blob_buffers; |
2604 | } |
2605 | grn_obj_unlink(ctx, &top_left_point); |
2606 | grn_obj_unlink(ctx, &bottom_right_point); |
2607 | grn_obj_unlink(ctx, &source_point); |
2608 | grn_obj_unlink(ctx, &key_buffer); |
2609 | grn_obj_unlink(ctx, &encoded_key_buffer); |
2610 | grn_obj_unlink(ctx, &old_value_buffer); |
2611 | grn_obj_unlink(ctx, &new_value_buffer); |
2612 | grn_ctx_fin(ctx); |
2613 | DBUG_VOID_RETURN; |
2614 | } |
2615 | |
2616 | const char *ha_mroonga::table_type() const |
2617 | { |
2618 | MRN_DBUG_ENTER_METHOD(); |
2619 | DBUG_RETURN(MRN_PLUGIN_NAME_STRING); |
2620 | } |
2621 | |
2622 | const char *ha_mroonga::index_type(uint key_nr) |
2623 | { |
2624 | MRN_DBUG_ENTER_METHOD(); |
2625 | KEY *key_info = &(table->s->key_info[key_nr]); |
2626 | if (key_info->algorithm == HA_KEY_ALG_FULLTEXT) { |
2627 | DBUG_RETURN("FULLTEXT" ); |
2628 | } else if (key_info->algorithm == HA_KEY_ALG_HASH) { |
2629 | DBUG_RETURN("HASH" ); |
2630 | } else { |
2631 | DBUG_RETURN("BTREE" ); |
2632 | } |
2633 | } |
2634 | |
2635 | static const char *ha_mroonga_exts[] = { |
2636 | NullS |
2637 | }; |
2638 | const char **ha_mroonga::bas_ext() const |
2639 | { |
2640 | MRN_DBUG_ENTER_METHOD(); |
2641 | DBUG_RETURN(ha_mroonga_exts); |
2642 | } |
2643 | |
2644 | uint ha_mroonga::wrapper_max_supported_record_length() const |
2645 | { |
2646 | uint res; |
2647 | MRN_DBUG_ENTER_METHOD(); |
2648 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2649 | res = wrap_handler_for_create->max_supported_record_length(); |
2650 | } else { |
2651 | MRN_SET_WRAP_SHARE_KEY(share, table->s); |
2652 | MRN_SET_WRAP_TABLE_KEY(this, table); |
2653 | res = wrap_handler->max_supported_record_length(); |
2654 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
2655 | MRN_SET_BASE_TABLE_KEY(this, table); |
2656 | } |
2657 | DBUG_RETURN(res); |
2658 | } |
2659 | |
2660 | uint ha_mroonga::storage_max_supported_record_length() const |
2661 | { |
2662 | MRN_DBUG_ENTER_METHOD(); |
2663 | DBUG_RETURN(HA_MAX_REC_LENGTH); |
2664 | } |
2665 | |
2666 | uint ha_mroonga::max_supported_record_length() const |
2667 | { |
2668 | MRN_DBUG_ENTER_METHOD(); |
2669 | |
2670 | uint res; |
2671 | if (!share && !analyzed_for_create && |
2672 | ( |
2673 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE || |
2674 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX || |
2675 | thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE |
2676 | ) |
2677 | ) { |
2678 | create_share_for_create(); |
2679 | } |
2680 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2681 | res = wrapper_max_supported_record_length(); |
2682 | } else if (wrap_handler && share && share->wrapper_mode) { |
2683 | res = wrapper_max_supported_record_length(); |
2684 | } else { |
2685 | res = storage_max_supported_record_length(); |
2686 | } |
2687 | |
2688 | DBUG_RETURN(res); |
2689 | } |
2690 | |
2691 | uint ha_mroonga::wrapper_max_supported_keys() const |
2692 | { |
2693 | uint res; |
2694 | MRN_DBUG_ENTER_METHOD(); |
2695 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2696 | res = wrap_handler_for_create->max_supported_keys(); |
2697 | } else { |
2698 | MRN_SET_WRAP_SHARE_KEY(share, table->s); |
2699 | MRN_SET_WRAP_TABLE_KEY(this, table); |
2700 | res = wrap_handler->max_supported_keys(); |
2701 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
2702 | MRN_SET_BASE_TABLE_KEY(this, table); |
2703 | } |
2704 | DBUG_RETURN(res); |
2705 | } |
2706 | |
2707 | uint ha_mroonga::storage_max_supported_keys() const |
2708 | { |
2709 | MRN_DBUG_ENTER_METHOD(); |
2710 | DBUG_RETURN(HA_MAX_REC_LENGTH); |
2711 | } |
2712 | |
2713 | uint ha_mroonga::max_supported_keys() const |
2714 | { |
2715 | MRN_DBUG_ENTER_METHOD(); |
2716 | |
2717 | uint res; |
2718 | if (!share && !analyzed_for_create && |
2719 | ( |
2720 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE || |
2721 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX || |
2722 | thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE |
2723 | ) |
2724 | ) { |
2725 | create_share_for_create(); |
2726 | } |
2727 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2728 | res = wrapper_max_supported_keys(); |
2729 | } else if (wrap_handler && share && share->wrapper_mode) { |
2730 | res = wrapper_max_supported_keys(); |
2731 | } else { |
2732 | res = storage_max_supported_keys(); |
2733 | } |
2734 | |
2735 | DBUG_RETURN(res); |
2736 | } |
2737 | |
2738 | uint ha_mroonga::wrapper_max_supported_key_length() const |
2739 | { |
2740 | uint res; |
2741 | MRN_DBUG_ENTER_METHOD(); |
2742 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2743 | res = wrap_handler_for_create->max_supported_key_length(); |
2744 | } else { |
2745 | MRN_SET_WRAP_SHARE_KEY(share, table->s); |
2746 | MRN_SET_WRAP_TABLE_KEY(this, table); |
2747 | res = wrap_handler->max_supported_key_length(); |
2748 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
2749 | MRN_SET_BASE_TABLE_KEY(this, table); |
2750 | } |
2751 | DBUG_RETURN(res); |
2752 | } |
2753 | |
2754 | uint ha_mroonga::storage_max_supported_key_length() const |
2755 | { |
2756 | MRN_DBUG_ENTER_METHOD(); |
2757 | DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE); |
2758 | } |
2759 | |
2760 | uint ha_mroonga::max_supported_key_length() const |
2761 | { |
2762 | MRN_DBUG_ENTER_METHOD(); |
2763 | |
2764 | uint res; |
2765 | if (!share && !analyzed_for_create && |
2766 | ( |
2767 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE || |
2768 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX || |
2769 | thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE |
2770 | ) |
2771 | ) { |
2772 | create_share_for_create(); |
2773 | } |
2774 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2775 | res = wrapper_max_supported_key_length(); |
2776 | } else if (wrap_handler && share && share->wrapper_mode) { |
2777 | res = wrapper_max_supported_key_length(); |
2778 | } else { |
2779 | res = storage_max_supported_key_length(); |
2780 | } |
2781 | |
2782 | DBUG_RETURN(res); |
2783 | } |
2784 | |
2785 | uint ha_mroonga::wrapper_max_supported_key_part_length() const |
2786 | { |
2787 | uint res; |
2788 | MRN_DBUG_ENTER_METHOD(); |
2789 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2790 | res = wrap_handler_for_create->max_supported_key_part_length(); |
2791 | } else { |
2792 | MRN_SET_WRAP_SHARE_KEY(share, table->s); |
2793 | MRN_SET_WRAP_TABLE_KEY(this, table); |
2794 | res = wrap_handler->max_supported_key_part_length(); |
2795 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
2796 | MRN_SET_BASE_TABLE_KEY(this, table); |
2797 | } |
2798 | DBUG_RETURN(res); |
2799 | } |
2800 | |
2801 | uint ha_mroonga::storage_max_supported_key_part_length() const |
2802 | { |
2803 | MRN_DBUG_ENTER_METHOD(); |
2804 | DBUG_RETURN(GRN_TABLE_MAX_KEY_SIZE); |
2805 | } |
2806 | |
2807 | uint ha_mroonga::max_supported_key_part_length() const |
2808 | { |
2809 | MRN_DBUG_ENTER_METHOD(); |
2810 | |
2811 | uint res; |
2812 | if (!share && !analyzed_for_create && |
2813 | ( |
2814 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE || |
2815 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX || |
2816 | thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE |
2817 | ) |
2818 | ) { |
2819 | create_share_for_create(); |
2820 | } |
2821 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2822 | res = wrapper_max_supported_key_part_length(); |
2823 | } else if (wrap_handler && share && share->wrapper_mode) { |
2824 | res = wrapper_max_supported_key_part_length(); |
2825 | } else { |
2826 | res = storage_max_supported_key_part_length(); |
2827 | } |
2828 | |
2829 | DBUG_RETURN(res); |
2830 | } |
2831 | |
2832 | ulonglong ha_mroonga::wrapper_table_flags() const |
2833 | { |
2834 | ulonglong table_flags; |
2835 | MRN_DBUG_ENTER_METHOD(); |
2836 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2837 | table_flags = wrap_handler_for_create->ha_table_flags(); |
2838 | } else { |
2839 | MRN_SET_WRAP_SHARE_KEY(share, table->s); |
2840 | MRN_SET_WRAP_TABLE_KEY(this, table); |
2841 | table_flags = wrap_handler->ha_table_flags(); |
2842 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
2843 | MRN_SET_BASE_TABLE_KEY(this, table); |
2844 | } |
2845 | table_flags |= HA_CAN_FULLTEXT | HA_PRIMARY_KEY_REQUIRED_FOR_DELETE | |
2846 | HA_CAN_RTREEKEYS | HA_REC_NOT_IN_SEQ; |
2847 | #ifdef HA_CAN_REPAIR |
2848 | table_flags |= HA_CAN_REPAIR; |
2849 | #endif |
2850 | #ifdef HA_CAN_FULLTEXT_EXT |
2851 | table_flags |= HA_CAN_FULLTEXT_EXT; |
2852 | #endif |
2853 | #ifdef HA_GENERATED_COLUMNS |
2854 | table_flags |= HA_GENERATED_COLUMNS; |
2855 | #endif |
2856 | #ifdef HA_CAN_VIRTUAL_COLUMNS |
2857 | table_flags |= HA_CAN_VIRTUAL_COLUMNS; |
2858 | #endif |
2859 | DBUG_RETURN(table_flags); |
2860 | } |
2861 | |
2862 | ulonglong ha_mroonga::storage_table_flags() const |
2863 | { |
2864 | MRN_DBUG_ENTER_METHOD(); |
2865 | ulonglong flags = |
2866 | HA_NO_TRANSACTIONS | |
2867 | HA_PARTIAL_COLUMN_READ | |
2868 | HA_REC_NOT_IN_SEQ | |
2869 | HA_NULL_IN_KEY | |
2870 | HA_CAN_INDEX_BLOBS | |
2871 | HA_STATS_RECORDS_IS_EXACT | |
2872 | HA_CAN_FULLTEXT | |
2873 | HA_BINLOG_FLAGS | |
2874 | HA_CAN_BIT_FIELD | |
2875 | HA_DUPLICATE_POS | |
2876 | HA_CAN_GEOMETRY | |
2877 | HA_CAN_RTREEKEYS; |
2878 | //HA_HAS_RECORDS; |
2879 | #ifdef HA_MUST_USE_TABLE_CONDITION_PUSHDOWN |
2880 | flags |= HA_MUST_USE_TABLE_CONDITION_PUSHDOWN; |
2881 | #endif |
2882 | #ifdef HA_CAN_REPAIR |
2883 | flags |= HA_CAN_REPAIR; |
2884 | #endif |
2885 | #ifdef HA_CAN_FULLTEXT_EXT |
2886 | flags |= HA_CAN_FULLTEXT_EXT; |
2887 | #endif |
2888 | #ifdef HA_GENERATED_COLUMNS |
2889 | flags |= HA_GENERATED_COLUMNS; |
2890 | #endif |
2891 | #ifdef HA_CAN_VIRTUAL_COLUMNS |
2892 | flags |= HA_CAN_VIRTUAL_COLUMNS; |
2893 | #endif |
2894 | DBUG_RETURN(flags); |
2895 | } |
2896 | |
2897 | ulonglong ha_mroonga::table_flags() const |
2898 | { |
2899 | MRN_DBUG_ENTER_METHOD(); |
2900 | |
2901 | ulonglong flags; |
2902 | if (!share && !analyzed_for_create && |
2903 | ( |
2904 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_TABLE || |
2905 | thd_sql_command(ha_thd()) == SQLCOM_CREATE_INDEX || |
2906 | thd_sql_command(ha_thd()) == SQLCOM_ALTER_TABLE |
2907 | ) |
2908 | ) { |
2909 | create_share_for_create(); |
2910 | } |
2911 | if (analyzed_for_create && share_for_create.wrapper_mode) { |
2912 | flags = wrapper_table_flags(); |
2913 | } else if (wrap_handler && share && share->wrapper_mode) { |
2914 | flags = wrapper_table_flags(); |
2915 | } else { |
2916 | flags = storage_table_flags(); |
2917 | } |
2918 | |
2919 | DBUG_RETURN(flags); |
2920 | } |
2921 | |
2922 | ulong ha_mroonga::wrapper_index_flags(uint idx, uint part, bool all_parts) const |
2923 | { |
2924 | ulong index_flags; |
2925 | KEY *key = &(table_share->key_info[idx]); |
2926 | MRN_DBUG_ENTER_METHOD(); |
2927 | if (key->algorithm == HA_KEY_ALG_BTREE || |
2928 | key->algorithm == HA_KEY_ALG_UNDEF) { |
2929 | MRN_SET_WRAP_SHARE_KEY(share, table->s); |
2930 | MRN_SET_WRAP_TABLE_KEY(this, table); |
2931 | index_flags = wrap_handler->index_flags(idx, part, all_parts); |
2932 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
2933 | MRN_SET_BASE_TABLE_KEY(this, table); |
2934 | } else { |
2935 | index_flags = HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR; |
2936 | } |
2937 | DBUG_RETURN(index_flags); |
2938 | } |
2939 | |
2940 | ulong ha_mroonga::storage_index_flags(uint idx, uint part, bool all_parts) const |
2941 | { |
2942 | MRN_DBUG_ENTER_METHOD(); |
2943 | ulong flags; |
2944 | KEY *key = &(table_share->key_info[idx]); |
2945 | if (key->algorithm == HA_KEY_ALG_BTREE || |
2946 | key->algorithm == HA_KEY_ALG_UNDEF) { |
2947 | flags = HA_READ_NEXT | HA_READ_PREV | HA_READ_RANGE; |
2948 | bool need_normalize_p = false; |
2949 | // TODO: MariaDB 10.1 passes key->user_defined_key_parts as part |
2950 | // for ORDER BY DESC. We just it fallback to part = 0. We may use |
2951 | // it for optimization in the future. |
2952 | // |
2953 | // See also: test_if_order_by_key() in sql/sql_select.cc. |
2954 | if (KEY_N_KEY_PARTS(key) == part) { |
2955 | part = 0; |
2956 | } |
2957 | Field *field = &(key->key_part[part].field[0]); |
2958 | if (field && (have_custom_normalizer(key) || should_normalize(field))) { |
2959 | need_normalize_p = true; |
2960 | } |
2961 | if (!need_normalize_p) { |
2962 | flags |= HA_KEYREAD_ONLY; |
2963 | } |
2964 | if (KEY_N_KEY_PARTS(key) > 1 || !need_normalize_p) { |
2965 | flags |= HA_READ_ORDER; |
2966 | } |
2967 | } else { |
2968 | flags = HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR; |
2969 | } |
2970 | DBUG_RETURN(flags); |
2971 | } |
2972 | |
2973 | ulong ha_mroonga::index_flags(uint idx, uint part, bool all_parts) const |
2974 | { |
2975 | MRN_DBUG_ENTER_METHOD(); |
2976 | |
2977 | KEY *key = &(table_share->key_info[idx]); |
2978 | if (key->algorithm == HA_KEY_ALG_FULLTEXT) { |
2979 | DBUG_RETURN(HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR); |
2980 | } |
2981 | if (mrn_is_geo_key(key)) { |
2982 | DBUG_RETURN(HA_ONLY_WHOLE_INDEX | HA_KEY_SCAN_NOT_ROR | HA_READ_RANGE); |
2983 | } |
2984 | |
2985 | int error = 0; |
2986 | if (wrap_handler && share && share->wrapper_mode) |
2987 | { |
2988 | error = wrapper_index_flags(idx, part, all_parts); |
2989 | } else { |
2990 | error = storage_index_flags(idx, part, all_parts); |
2991 | } |
2992 | DBUG_RETURN(error); |
2993 | } |
2994 | |
2995 | int ha_mroonga::create_share_for_create() const |
2996 | { |
2997 | int error; |
2998 | THD *thd = ha_thd(); |
2999 | LEX *lex = thd->lex; |
3000 | HA_CREATE_INFO *create_info = &lex->create_info; |
3001 | TABLE_LIST *table_list = MRN_LEX_GET_TABLE_LIST(lex); |
3002 | MRN_DBUG_ENTER_METHOD(); |
3003 | wrap_handler_for_create = NULL; |
3004 | 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 | |
3074 | error: |
3075 | if (share_for_create.wrapper_mode) { |
3076 | plugin_unlock(NULL, share_for_create.plugin); |
3077 | } |
3078 | mrn_free_share_alloc(&share_for_create); |
3079 | free_root(&mem_root_for_create, MYF(0)); |
3080 | analyzed_for_create = false; |
3081 | thd->clear_error(); |
3082 | DBUG_RETURN(error); |
3083 | } |
3084 | |
3085 | int ha_mroonga::wrapper_create(const char *name, TABLE *table, |
3086 | HA_CREATE_INFO *info, MRN_SHARE *tmp_share) |
3087 | { |
3088 | int error = 0; |
3089 | handler *hnd; |
3090 | MRN_DBUG_ENTER_METHOD(); |
3091 | |
3092 | if (table_share->primary_key == MAX_KEY) |
3093 | { |
3094 | my_message(ER_REQUIRES_PRIMARY_KEY, |
3095 | MRN_GET_ERR_MSG(ER_REQUIRES_PRIMARY_KEY), MYF(0)); |
3096 | DBUG_RETURN(ER_REQUIRES_PRIMARY_KEY); |
3097 | } |
3098 | |
3099 | error = ensure_database_open(name); |
3100 | if (error) |
3101 | DBUG_RETURN(error); |
3102 | |
3103 | error = wrapper_create_index(name, table, tmp_share); |
3104 | if (error) |
3105 | DBUG_RETURN(error); |
3106 | |
3107 | wrap_key_info = mrn_create_key_info_for_table(tmp_share, table, &error); |
3108 | if (error) |
3109 | DBUG_RETURN(error); |
3110 | base_key_info = table->key_info; |
3111 | |
3112 | share = tmp_share; |
3113 | MRN_SET_WRAP_SHARE_KEY(tmp_share, table->s); |
3114 | MRN_SET_WRAP_TABLE_KEY(this, table); |
3115 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
3116 | if (parse_engine_table_options(ha_thd(), tmp_share->hton, table->s)) { |
3117 | MRN_SET_BASE_SHARE_KEY(tmp_share, table->s); |
3118 | MRN_SET_BASE_TABLE_KEY(this, table); |
3119 | share = NULL; |
3120 | if (wrap_key_info) |
3121 | { |
3122 | my_free(wrap_key_info); |
3123 | wrap_key_info = NULL; |
3124 | } |
3125 | base_key_info = NULL; |
3126 | error = MRN_GET_ERROR_NUMBER; |
3127 | DBUG_RETURN(error); |
3128 | } |
3129 | #endif |
3130 | hnd = get_new_handler(table->s, current_thd->mem_root, tmp_share->hton); |
3131 | if (!hnd) |
3132 | { |
3133 | MRN_SET_BASE_SHARE_KEY(tmp_share, table->s); |
3134 | MRN_SET_BASE_TABLE_KEY(this, table); |
3135 | share = NULL; |
3136 | if (wrap_key_info) |
3137 | { |
3138 | my_free(wrap_key_info); |
3139 | wrap_key_info = NULL; |
3140 | } |
3141 | base_key_info = NULL; |
3142 | DBUG_RETURN(HA_ERR_OUT_OF_MEM); |
3143 | } |
3144 | error = hnd->ha_create(name, table, info); |
3145 | MRN_SET_BASE_SHARE_KEY(tmp_share, table->s); |
3146 | MRN_SET_BASE_TABLE_KEY(this, table); |
3147 | share = NULL; |
3148 | delete hnd; |
3149 | |
3150 | if (error) { |
3151 | mrn::PathMapper mapper(name); |
3152 | generic_delete_table(name, mapper.table_name()); |
3153 | } |
3154 | |
3155 | if (wrap_key_info) |
3156 | { |
3157 | my_free(wrap_key_info); |
3158 | wrap_key_info = NULL; |
3159 | } |
3160 | base_key_info = NULL; |
3161 | DBUG_RETURN(error); |
3162 | } |
3163 | |
3164 | int ha_mroonga::wrapper_create_index_fulltext_validate(KEY *key_info) |
3165 | { |
3166 | MRN_DBUG_ENTER_METHOD(); |
3167 | |
3168 | int error = 0; |
3169 | uint i; |
3170 | for (i = 0; i < KEY_N_KEY_PARTS(key_info); i++) { |
3171 | Field *field = key_info->key_part[i].field; |
3172 | |
3173 | grn_builtin_type gtype = mrn_grn_type_from_field(ctx, field, true); |
3174 | if (gtype != GRN_DB_SHORT_TEXT) |
3175 | { |
3176 | error = ER_CANT_CREATE_TABLE; |
3177 | GRN_LOG(ctx, GRN_LOG_ERROR, |
3178 | "key type must be text: <%d> " |
3179 | "(TODO: We should show type name not type ID.)" , |
3180 | field->type()); |
3181 | my_message(ER_CANT_CREATE_TABLE, |
3182 | "key type must be text. (TODO: We should show type name.)" , |
3183 | MYF(0)); |
3184 | DBUG_RETURN(error); |
3185 | } |
3186 | } |
3187 | |
3188 | DBUG_RETURN(error); |
3189 | } |
3190 | |
3191 | int ha_mroonga::wrapper_create_index_fulltext(const char *grn_table_name, |
3192 | int i, |
3193 | KEY *key_info, |
3194 | grn_obj **index_tables, |
3195 | grn_obj **index_columns, |
3196 | MRN_SHARE *tmp_share) |
3197 | { |
3198 | MRN_DBUG_ENTER_METHOD(); |
3199 | int error = 0; |
3200 | |
3201 | error = wrapper_create_index_fulltext_validate(key_info); |
3202 | if (error) { |
3203 | DBUG_RETURN(error); |
3204 | } |
3205 | |
3206 | error = mrn_change_encoding(ctx, system_charset_info); |
3207 | if (error) |
3208 | DBUG_RETURN(error); |
3209 | |
3210 | grn_obj_flags index_table_flags = |
3211 | GRN_OBJ_TABLE_PAT_KEY | |
3212 | GRN_OBJ_PERSISTENT; |
3213 | grn_obj *index_table; |
3214 | |
3215 | grn_column_flags index_column_flags = GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT; |
3216 | |
3217 | if (!find_index_column_flags(key_info, &index_column_flags)) { |
3218 | index_column_flags |= GRN_OBJ_WITH_POSITION; |
3219 | if (KEY_N_KEY_PARTS(key_info) > 1) { |
3220 | index_column_flags |= GRN_OBJ_WITH_SECTION; |
3221 | } |
3222 | } |
3223 | |
3224 | mrn::SmartGrnObj lexicon_key_type(ctx, GRN_DB_SHORT_TEXT); |
3225 | error = mrn_change_encoding(ctx, key_info->key_part->field->charset()); |
3226 | if (error) { |
3227 | DBUG_RETURN(error); |
3228 | } |
3229 | mrn::IndexTableName index_table_name(grn_table_name, key_info->name.str); |
3230 | index_table = grn_table_create(ctx, |
3231 | index_table_name.c_str(), |
3232 | index_table_name.length(), |
3233 | NULL, |
3234 | index_table_flags, |
3235 | lexicon_key_type.get(), |
3236 | 0); |
3237 | if (ctx->rc) { |
3238 | error = ER_CANT_CREATE_TABLE; |
3239 | my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0)); |
3240 | DBUG_RETURN(error); |
3241 | } |
3242 | mrn_change_encoding(ctx, system_charset_info); |
3243 | index_tables[i] = index_table; |
3244 | |
3245 | grn_obj *tokenizer = find_tokenizer(key_info, tmp_share, i); |
3246 | if (tokenizer) { |
3247 | grn_info_type info_type = GRN_INFO_DEFAULT_TOKENIZER; |
3248 | grn_obj_set_info(ctx, index_table, info_type, tokenizer); |
3249 | grn_obj_unlink(ctx, tokenizer); |
3250 | } |
3251 | |
3252 | { |
3253 | grn_obj token_filters; |
3254 | GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, 0); |
3255 | if (find_token_filters(key_info, &token_filters)) { |
3256 | grn_obj_set_info(ctx, index_table, |
3257 | GRN_INFO_TOKEN_FILTERS, &token_filters); |
3258 | } |
3259 | grn_obj_unlink(ctx, &token_filters); |
3260 | } |
3261 | |
3262 | if (have_custom_normalizer(key_info) || |
3263 | should_normalize(&key_info->key_part->field[0])) { |
3264 | grn_info_type info_type = GRN_INFO_NORMALIZER; |
3265 | grn_obj *normalizer = find_normalizer(key_info); |
3266 | if (normalizer) { |
3267 | grn_obj_set_info(ctx, index_table, info_type, normalizer); |
3268 | grn_obj_unlink(ctx, normalizer); |
3269 | } |
3270 | } |
3271 | |
3272 | grn_obj *index_column = grn_column_create(ctx, index_table, |
3273 | INDEX_COLUMN_NAME, |
3274 | strlen(INDEX_COLUMN_NAME), |
3275 | NULL, |
3276 | index_column_flags, |
3277 | grn_table); |
3278 | if (ctx->rc) { |
3279 | error = ER_CANT_CREATE_TABLE; |
3280 | my_message(error, ctx->errbuf, MYF(0)); |
3281 | DBUG_RETURN(error); |
3282 | } |
3283 | if (index_columns) { |
3284 | index_columns[i] = index_column; |
3285 | } else { |
3286 | grn_obj_unlink(ctx, index_column); |
3287 | } |
3288 | |
3289 | DBUG_RETURN(error); |
3290 | } |
3291 | |
3292 | int ha_mroonga::wrapper_create_index_geo(const char *grn_table_name, |
3293 | int i, |
3294 | KEY *key_info, |
3295 | grn_obj **index_tables, |
3296 | grn_obj **index_columns, |
3297 | MRN_SHARE *tmp_share) |
3298 | { |
3299 | MRN_DBUG_ENTER_METHOD(); |
3300 | int error; |
3301 | |
3302 | error = mrn_change_encoding(ctx, system_charset_info); |
3303 | if (error) |
3304 | DBUG_RETURN(error); |
3305 | |
3306 | mrn::IndexTableName index_table_name(grn_table_name, key_info->name.str); |
3307 | |
3308 | grn_obj_flags index_table_flags = |
3309 | GRN_OBJ_TABLE_PAT_KEY | |
3310 | GRN_OBJ_PERSISTENT; |
3311 | grn_obj *index_table; |
3312 | |
3313 | grn_obj_flags index_column_flags = |
3314 | GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT; |
3315 | |
3316 | grn_obj *lexicon_key_type = grn_ctx_at(ctx, GRN_DB_WGS84_GEO_POINT); |
3317 | index_table = grn_table_create(ctx, |
3318 | index_table_name.c_str(), |
3319 | index_table_name.length(), |
3320 | NULL, |
3321 | index_table_flags, lexicon_key_type, 0); |
3322 | if (ctx->rc) { |
3323 | error = ER_CANT_CREATE_TABLE; |
3324 | my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0)); |
3325 | grn_obj_unlink(ctx, lexicon_key_type); |
3326 | DBUG_RETURN(error); |
3327 | } |
3328 | grn_obj_unlink(ctx, lexicon_key_type); |
3329 | index_tables[i] = index_table; |
3330 | |
3331 | grn_obj *index_column = grn_column_create(ctx, index_table, |
3332 | INDEX_COLUMN_NAME, |
3333 | strlen(INDEX_COLUMN_NAME), |
3334 | NULL, |
3335 | index_column_flags, |
3336 | grn_table); |
3337 | if (ctx->rc) { |
3338 | error = ER_CANT_CREATE_TABLE; |
3339 | my_message(error, ctx->errbuf, MYF(0)); |
3340 | DBUG_RETURN(error); |
3341 | } |
3342 | if (index_columns) { |
3343 | index_columns[i] = index_column; |
3344 | } else { |
3345 | grn_obj_unlink(ctx, index_column); |
3346 | } |
3347 | |
3348 | DBUG_RETURN(error); |
3349 | } |
3350 | |
3351 | int ha_mroonga::wrapper_create_index(const char *name, TABLE *table, |
3352 | MRN_SHARE *tmp_share) |
3353 | { |
3354 | MRN_DBUG_ENTER_METHOD(); |
3355 | |
3356 | int error = 0; |
3357 | error = mrn_change_encoding(ctx, system_charset_info); |
3358 | if (error) |
3359 | DBUG_RETURN(error); |
3360 | |
3361 | grn_obj *grn_index_table; |
3362 | mrn::PathMapper mapper(name); |
3363 | const char *grn_table_name = mapper.table_name(); |
3364 | char *grn_table_path = NULL; // we don't specify path |
3365 | grn_obj *pkey_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT); |
3366 | grn_obj *pkey_value_type = NULL; // we don't use this |
3367 | grn_obj_flags grn_table_flags = GRN_OBJ_PERSISTENT | GRN_OBJ_TABLE_HASH_KEY; |
3368 | |
3369 | grn_index_table = grn_table_create(ctx, grn_table_name, strlen(grn_table_name), |
3370 | grn_table_path, grn_table_flags, |
3371 | pkey_type, pkey_value_type); |
3372 | if (ctx->rc) { |
3373 | error = ER_CANT_CREATE_TABLE; |
3374 | my_message(error, ctx->errbuf, MYF(0)); |
3375 | DBUG_RETURN(error); |
3376 | } |
3377 | if (grn_table) { |
3378 | grn_obj_unlink(ctx, grn_table); |
3379 | } |
3380 | grn_table = grn_index_table; |
3381 | |
3382 | uint i; |
3383 | uint n_keys = table->s->keys; |
3384 | MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys); |
3385 | if (!tmp_share->disable_keys) { |
3386 | for (i = 0; i < n_keys; i++) { |
3387 | index_tables[i] = NULL; |
3388 | |
3389 | KEY *key_info = &(table->s->key_info[i]); |
3390 | if (key_info->algorithm == HA_KEY_ALG_FULLTEXT) { |
3391 | error = wrapper_create_index_fulltext(grn_table_name, |
3392 | i, key_info, |
3393 | index_tables, NULL, tmp_share); |
3394 | } else if (mrn_is_geo_key(key_info)) { |
3395 | error = wrapper_create_index_geo(grn_table_name, |
3396 | i, key_info, |
3397 | index_tables, NULL, tmp_share); |
3398 | } |
3399 | } |
3400 | } |
3401 | |
3402 | if (error) { |
3403 | for (uint j = 0; j < i; j++) { |
3404 | if (index_tables[j]) { |
3405 | grn_obj_remove(ctx, index_tables[j]); |
3406 | } |
3407 | } |
3408 | grn_obj_remove(ctx, grn_table); |
3409 | grn_table = NULL; |
3410 | } |
3411 | MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); |
3412 | DBUG_RETURN(error); |
3413 | } |
3414 | |
3415 | int ha_mroonga::storage_create(const char *name, TABLE *table, |
3416 | HA_CREATE_INFO *info, MRN_SHARE *tmp_share) |
3417 | { |
3418 | int error; |
3419 | MRN_LONG_TERM_SHARE *long_term_share = tmp_share->long_term_share; |
3420 | MRN_DBUG_ENTER_METHOD(); |
3421 | |
3422 | if (info->auto_increment_value) { |
3423 | mrn::Lock lock(&long_term_share->auto_inc_mutex); |
3424 | long_term_share->auto_inc_value = info->auto_increment_value; |
3425 | DBUG_PRINT("info" , ("mroonga: auto_inc_value=%llu" , |
3426 | long_term_share->auto_inc_value)); |
3427 | long_term_share->auto_inc_inited = true; |
3428 | } |
3429 | |
3430 | error = storage_create_validate_pseudo_column(table); |
3431 | if (error) |
3432 | DBUG_RETURN(error); |
3433 | |
3434 | error = storage_create_validate_index(table); |
3435 | if (error) |
3436 | DBUG_RETURN(error); |
3437 | |
3438 | error = ensure_database_open(name); |
3439 | if (error) |
3440 | DBUG_RETURN(error); |
3441 | |
3442 | error = mrn_change_encoding(ctx, system_charset_info); |
3443 | if (error) |
3444 | DBUG_RETURN(error); |
3445 | |
3446 | grn_obj_flags table_flags = GRN_OBJ_PERSISTENT; |
3447 | |
3448 | /* primary key must be handled before creating table */ |
3449 | grn_obj *pkey_type; |
3450 | uint pkey_nr = table->s->primary_key; |
3451 | if (pkey_nr != MAX_INDEXES) { |
3452 | KEY *key_info = &(table->s->key_info[pkey_nr]); |
3453 | bool is_id; |
3454 | |
3455 | int key_parts = KEY_N_KEY_PARTS(key_info); |
3456 | if (key_parts == 1) { |
3457 | Field *pkey_field = key_info->key_part[0].field; |
3458 | const char *column_name = pkey_field->field_name.str; |
3459 | is_id = (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0); |
3460 | |
3461 | grn_builtin_type gtype = mrn_grn_type_from_field(ctx, pkey_field, false); |
3462 | pkey_type = grn_ctx_at(ctx, gtype); |
3463 | } else { |
3464 | is_id = false; |
3465 | pkey_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT); |
3466 | } |
3467 | |
3468 | // default algorithm is BTREE ==> PAT |
3469 | if (!is_id && key_info->algorithm == HA_KEY_ALG_HASH) { |
3470 | table_flags |= GRN_OBJ_TABLE_HASH_KEY; |
3471 | } else if (!is_id) { |
3472 | table_flags |= GRN_OBJ_TABLE_PAT_KEY; |
3473 | } else { |
3474 | // for _id |
3475 | table_flags |= GRN_OBJ_TABLE_NO_KEY; |
3476 | pkey_type = NULL; |
3477 | } |
3478 | |
3479 | } else { |
3480 | // primary key doesn't exists |
3481 | table_flags |= GRN_OBJ_TABLE_NO_KEY; |
3482 | pkey_type = NULL; |
3483 | } |
3484 | |
3485 | /* create table */ |
3486 | grn_obj *table_obj; |
3487 | mrn::PathMapper mapper(name); |
3488 | |
3489 | char *table_path = NULL; // we don't specify path |
3490 | grn_obj *pkey_value_type = NULL; // we don't use this |
3491 | |
3492 | table_obj = grn_table_create(ctx, |
3493 | mapper.table_name(), strlen(mapper.table_name()), |
3494 | table_path, |
3495 | table_flags, pkey_type, pkey_value_type); |
3496 | if (ctx->rc) { |
3497 | error = ER_CANT_CREATE_TABLE; |
3498 | my_message(error, ctx->errbuf, MYF(0)); |
3499 | DBUG_RETURN(error); |
3500 | } |
3501 | |
3502 | if (table_flags == (GRN_OBJ_PERSISTENT | GRN_OBJ_TABLE_PAT_KEY) || |
3503 | table_flags == (GRN_OBJ_PERSISTENT | GRN_OBJ_TABLE_HASH_KEY)) { |
3504 | KEY *key_info = &(table->s->key_info[pkey_nr]); |
3505 | int key_parts = KEY_N_KEY_PARTS(key_info); |
3506 | if (key_parts == 1) { |
3507 | grn_obj *normalizer = NULL; |
3508 | if (tmp_share->normalizer) { |
3509 | normalizer = grn_ctx_get(ctx, |
3510 | tmp_share->normalizer, |
3511 | tmp_share->normalizer_length); |
3512 | } else { |
3513 | Field *field = &(key_info->key_part->field[0]); |
3514 | if (should_normalize(field)) { |
3515 | normalizer = find_normalizer(key_info); |
3516 | } |
3517 | } |
3518 | if (normalizer) { |
3519 | grn_info_type info_type = GRN_INFO_NORMALIZER; |
3520 | grn_obj_set_info(ctx, table_obj, info_type, normalizer); |
3521 | grn_obj_unlink(ctx, normalizer); |
3522 | } |
3523 | if (tmp_share->default_tokenizer) { |
3524 | grn_obj *default_tokenizer = |
3525 | grn_ctx_get(ctx, |
3526 | tmp_share->default_tokenizer, |
3527 | tmp_share->default_tokenizer_length); |
3528 | if (default_tokenizer) { |
3529 | grn_info_type info_type = GRN_INFO_DEFAULT_TOKENIZER; |
3530 | grn_obj_set_info(ctx, table_obj, info_type, default_tokenizer); |
3531 | grn_obj_unlink(ctx, default_tokenizer); |
3532 | } |
3533 | } |
3534 | if (tmp_share->token_filters) { |
3535 | grn_obj token_filters; |
3536 | GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, 0); |
3537 | if (find_token_filters_fill(&token_filters, |
3538 | tmp_share->token_filters, |
3539 | tmp_share->token_filters_length)) { |
3540 | grn_obj_set_info(ctx, table_obj, |
3541 | GRN_INFO_TOKEN_FILTERS, &token_filters); |
3542 | } |
3543 | grn_obj_unlink(ctx, &token_filters); |
3544 | } |
3545 | } |
3546 | } |
3547 | |
3548 | /* create columns */ |
3549 | uint n_columns = table->s->fields; |
3550 | for (uint i = 0; i < n_columns; i++) { |
3551 | Field *field = table->s->field[i]; |
3552 | mrn::ColumnName column_name(field->field_name); |
3553 | |
3554 | if (strcmp(MRN_COLUMN_NAME_ID, column_name.mysql_name()) == 0) { |
3555 | continue; |
3556 | } |
3557 | |
3558 | #ifdef MRN_SUPPORT_FOREIGN_KEYS |
3559 | if (storage_create_foreign_key(table, mapper.table_name(), field, table_obj, |
3560 | error)) { |
3561 | continue; |
3562 | } |
3563 | if (error) { |
3564 | grn_obj_remove(ctx, table_obj); |
3565 | DBUG_RETURN(error); |
3566 | } |
3567 | #endif |
3568 | |
3569 | #ifdef MRN_SUPPORT_GENERATED_COLUMNS |
3570 | if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) { |
3571 | continue; |
3572 | } |
3573 | #endif |
3574 | |
3575 | grn_obj_flags col_flags = GRN_OBJ_PERSISTENT; |
3576 | if (!find_column_flags(field, tmp_share, i, &col_flags)) { |
3577 | col_flags |= GRN_OBJ_COLUMN_SCALAR; |
3578 | } |
3579 | |
3580 | grn_obj *col_type; |
3581 | { |
3582 | int column_type_error_code = ER_CANT_CREATE_TABLE; |
3583 | col_type = find_column_type(field, tmp_share, i, column_type_error_code); |
3584 | if (!col_type) { |
3585 | grn_obj_remove(ctx, table_obj); |
3586 | DBUG_RETURN(column_type_error_code); |
3587 | } |
3588 | } |
3589 | char *col_path = NULL; // we don't specify path |
3590 | |
3591 | grn_column_create(ctx, table_obj, |
3592 | column_name.c_str(), column_name.length(), |
3593 | col_path, col_flags, col_type); |
3594 | if (ctx->rc) { |
3595 | error = ER_CANT_CREATE_TABLE; |
3596 | my_message(error, ctx->errbuf, MYF(0)); |
3597 | grn_obj_remove(ctx, table_obj); |
3598 | DBUG_RETURN(error); |
3599 | } |
3600 | } |
3601 | |
3602 | error = storage_create_indexes(table, mapper.table_name(), table_obj, |
3603 | tmp_share); |
3604 | if (error) { |
3605 | grn_obj_remove(ctx, table_obj); |
3606 | table_obj = NULL; |
3607 | } |
3608 | |
3609 | if (table_obj) { |
3610 | grn_obj_unlink(ctx, table_obj); |
3611 | } |
3612 | |
3613 | DBUG_RETURN(error); |
3614 | } |
3615 | |
3616 | int ha_mroonga::storage_create_validate_pseudo_column(TABLE *table) |
3617 | { |
3618 | int error = 0; |
3619 | uint i, n_columns; |
3620 | |
3621 | MRN_DBUG_ENTER_METHOD(); |
3622 | n_columns = table->s->fields; |
3623 | for (i = 0; i < n_columns; i++) { |
3624 | Field *field = table->s->field[i]; |
3625 | const char *column_name = field->field_name.str; |
3626 | if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) { |
3627 | switch (field->type()) { |
3628 | case MYSQL_TYPE_TINY : |
3629 | case MYSQL_TYPE_SHORT : |
3630 | case MYSQL_TYPE_INT24 : |
3631 | case MYSQL_TYPE_LONG : |
3632 | case MYSQL_TYPE_LONGLONG : |
3633 | break; |
3634 | default: |
3635 | GRN_LOG(ctx, GRN_LOG_ERROR, "_id must be numeric data type" ); |
3636 | error = ER_CANT_CREATE_TABLE; |
3637 | my_message(error, "_id must be numeric data type" , MYF(0)); |
3638 | DBUG_RETURN(error); |
3639 | } |
3640 | } |
3641 | } |
3642 | |
3643 | DBUG_RETURN(error); |
3644 | } |
3645 | |
3646 | #ifdef MRN_SUPPORT_FOREIGN_KEYS |
3647 | bool ha_mroonga::storage_create_foreign_key(TABLE *table, |
3648 | const char *grn_table_name, |
3649 | Field *field, |
3650 | grn_obj *table_obj, int &error) |
3651 | { |
3652 | MRN_DBUG_ENTER_METHOD(); |
3653 | LEX *lex = ha_thd()->lex; |
3654 | Alter_info *alter_info = &lex->alter_info; |
3655 | List_iterator<Key> key_iterator(alter_info->key_list); |
3656 | Key *key; |
3657 | char ref_db_buff[NAME_LEN + 1], ref_table_buff[NAME_LEN + 1]; |
3658 | while ((key = key_iterator++)) |
3659 | { |
3660 | if (key->type != MRN_KEYTYPE_FOREIGN) |
3661 | { |
3662 | continue; |
3663 | } |
3664 | if (key->columns.elements > 1) |
3665 | { |
3666 | error = ER_CANT_CREATE_TABLE; |
3667 | my_message(error, "mroonga can't use FOREIGN_KEY with multiple columns" , |
3668 | MYF(0)); |
3669 | DBUG_RETURN(false); |
3670 | } |
3671 | List_iterator<Key_part_spec> key_part_col_iterator(key->columns); |
3672 | Key_part_spec *key_part_col = key_part_col_iterator++; |
3673 | LEX_CSTRING field_name = key_part_col->field_name; |
3674 | DBUG_PRINT("info" , ("mroonga: field_name=%s" , field_name.str)); |
3675 | DBUG_PRINT("info" , ("mroonga: field->field_name=%s" , field->field_name.str)); |
3676 | if (strcmp(field->field_name.str, field_name.str)) |
3677 | { |
3678 | continue; |
3679 | } |
3680 | Foreign_key *fk = (Foreign_key *) key; |
3681 | List_iterator<Key_part_spec> key_part_ref_col_iterator(fk->ref_columns); |
3682 | Key_part_spec *key_part_ref_col = key_part_ref_col_iterator++; |
3683 | LEX_CSTRING ref_field_name = key_part_ref_col->field_name; |
3684 | DBUG_PRINT("info" , ("mroonga: ref_field_name=%s" , ref_field_name.str)); |
3685 | #ifdef MRN_FOREIGN_KEY_USE_CONST_STRING |
3686 | LEX_CSTRING ref_db_name = fk->ref_db; |
3687 | #else |
3688 | LEX_STRING ref_db_name = fk->ref_db; |
3689 | #endif |
3690 | DBUG_PRINT("info" , ("mroonga: ref_db_name=%s" , ref_db_name.str)); |
3691 | if (ref_db_name.str && lower_case_table_names) { |
3692 | strmake(ref_db_buff, ref_db_name.str, sizeof(ref_db_buff) - 1); |
3693 | my_casedn_str(system_charset_info, ref_db_buff); |
3694 | ref_db_name.str = ref_db_buff; |
3695 | DBUG_PRINT("info" , ("mroonga: casedn ref_db_name=%s" , ref_db_name.str)); |
3696 | } |
3697 | #ifdef MRN_FOREIGN_KEY_USE_CONST_STRING |
3698 | LEX_CSTRING ref_table_name = fk->ref_table; |
3699 | #else |
3700 | LEX_STRING ref_table_name = fk->ref_table; |
3701 | #endif |
3702 | DBUG_PRINT("info" , ("mroonga: ref_table_name=%s" , ref_table_name.str)); |
3703 | if (ref_table_name.str && lower_case_table_names) { |
3704 | strmake(ref_table_buff, ref_table_name.str, sizeof(ref_table_buff) - 1); |
3705 | my_casedn_str(system_charset_info, ref_table_buff); |
3706 | ref_table_name.str = ref_table_buff; |
3707 | DBUG_PRINT("info" , ("mroonga: casedn ref_table_name=%s" , ref_table_name.str)); |
3708 | } |
3709 | if (ref_db_name.str && strcmp(table->s->db.str, ref_db_name.str)) |
3710 | { |
3711 | error = ER_CANT_CREATE_TABLE; |
3712 | my_message(error, |
3713 | "mroonga can't use FOREIGN_KEY during different database tables" , |
3714 | MYF(0)); |
3715 | DBUG_RETURN(false); |
3716 | } |
3717 | |
3718 | grn_obj *column, *column_ref = NULL, *grn_table_ref = NULL; |
3719 | char ref_path[FN_REFLEN + 1]; |
3720 | TABLE_LIST table_list; |
3721 | TABLE_SHARE *tmp_ref_table_share; |
3722 | build_table_filename(ref_path, sizeof(ref_path) - 1, |
3723 | table->s->db.str, ref_table_name.str, "" , 0); |
3724 | |
3725 | DBUG_PRINT("info" , ("mroonga: ref_path=%s" , ref_path)); |
3726 | error = mrn_change_encoding(ctx, system_charset_info); |
3727 | if (error) |
3728 | DBUG_RETURN(false); |
3729 | mrn::PathMapper mapper(ref_path); |
3730 | grn_table_ref = grn_ctx_get(ctx, mapper.table_name(), |
3731 | strlen(mapper.table_name())); |
3732 | if (!grn_table_ref) { |
3733 | error = ER_CANT_CREATE_TABLE; |
3734 | char err_msg[MRN_BUFFER_SIZE]; |
3735 | sprintf(err_msg, "reference table [%s.%s] is not mroonga table" , |
3736 | table->s->db.str, ref_table_name.str); |
3737 | my_message(error, err_msg, MYF(0)); |
3738 | DBUG_RETURN(false); |
3739 | } |
3740 | |
3741 | LEX_CSTRING tmp_db_name= { mapper.db_name(), strlen(mapper.db_name()) }; |
3742 | LEX_CSTRING tmp_table_name= { mapper.mysql_table_name(), strlen(mapper.mysql_table_name()) }; |
3743 | table_list.init_one_table(&tmp_db_name, &tmp_table_name, 0, TL_WRITE); |
3744 | mrn_open_mutex_lock(table->s); |
3745 | tmp_ref_table_share = |
3746 | mrn_create_tmp_table_share(&table_list, ref_path, &error); |
3747 | mrn_open_mutex_unlock(table->s); |
3748 | if (!tmp_ref_table_share) { |
3749 | grn_obj_unlink(ctx, grn_table_ref); |
3750 | error = ER_CANT_CREATE_TABLE; |
3751 | char err_msg[MRN_BUFFER_SIZE]; |
3752 | sprintf(err_msg, "reference table [%s.%s] is not found" , |
3753 | table->s->db.str, ref_table_name.str); |
3754 | my_message(error, err_msg, MYF(0)); |
3755 | DBUG_RETURN(false); |
3756 | } |
3757 | uint ref_pkey_nr = tmp_ref_table_share->primary_key; |
3758 | if (ref_pkey_nr == MAX_KEY) { |
3759 | mrn_open_mutex_lock(table->s); |
3760 | mrn_free_tmp_table_share(tmp_ref_table_share); |
3761 | mrn_open_mutex_unlock(table->s); |
3762 | grn_obj_unlink(ctx, grn_table_ref); |
3763 | error = ER_CANT_CREATE_TABLE; |
3764 | char err_msg[MRN_BUFFER_SIZE]; |
3765 | sprintf(err_msg, "reference table [%s.%s] has no primary key" , |
3766 | table->s->db.str, ref_table_name.str); |
3767 | my_message(error, err_msg, MYF(0)); |
3768 | DBUG_RETURN(false); |
3769 | } |
3770 | KEY *ref_key_info = &tmp_ref_table_share->key_info[ref_pkey_nr]; |
3771 | uint ref_key_parts = KEY_N_KEY_PARTS(ref_key_info); |
3772 | if (ref_key_parts > 1) { |
3773 | mrn_open_mutex_lock(table->s); |
3774 | mrn_free_tmp_table_share(tmp_ref_table_share); |
3775 | mrn_open_mutex_unlock(table->s); |
3776 | grn_obj_unlink(ctx, grn_table_ref); |
3777 | error = ER_CANT_CREATE_TABLE; |
3778 | char err_msg[MRN_BUFFER_SIZE]; |
3779 | sprintf(err_msg, |
3780 | "reference table [%s.%s] primary key is multiple column" , |
3781 | table->s->db.str, ref_table_name.str); |
3782 | my_message(error, err_msg, MYF(0)); |
3783 | DBUG_RETURN(false); |
3784 | } |
3785 | Field *ref_field = &ref_key_info->key_part->field[0]; |
3786 | if (strcmp(ref_field->field_name.str, ref_field_name.str)) { |
3787 | mrn_open_mutex_lock(table->s); |
3788 | mrn_free_tmp_table_share(tmp_ref_table_share); |
3789 | mrn_open_mutex_unlock(table->s); |
3790 | grn_obj_unlink(ctx, grn_table_ref); |
3791 | error = ER_CANT_CREATE_TABLE; |
3792 | char err_msg[MRN_BUFFER_SIZE]; |
3793 | sprintf(err_msg, |
3794 | "reference column [%s.%s.%s] is not used for primary key" , |
3795 | table->s->db.str, ref_table_name.str, ref_field_name.str); |
3796 | my_message(error, err_msg, MYF(0)); |
3797 | DBUG_RETURN(false); |
3798 | } |
3799 | mrn_open_mutex_lock(table->s); |
3800 | mrn_free_tmp_table_share(tmp_ref_table_share); |
3801 | mrn_open_mutex_unlock(table->s); |
3802 | grn_obj_flags col_flags = GRN_OBJ_PERSISTENT; |
3803 | column = grn_column_create(ctx, table_obj, field->field_name.str, |
3804 | field->field_name.length, |
3805 | NULL, col_flags, grn_table_ref); |
3806 | if (ctx->rc) { |
3807 | grn_obj_unlink(ctx, grn_table_ref); |
3808 | error = ER_CANT_CREATE_TABLE; |
3809 | my_message(error, ctx->errbuf, MYF(0)); |
3810 | DBUG_RETURN(false); |
3811 | } |
3812 | |
3813 | mrn::IndexColumnName index_column_name(grn_table_name, field->field_name.str); |
3814 | grn_obj_flags ref_col_flags = GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT; |
3815 | column_ref = grn_column_create(ctx, grn_table_ref, |
3816 | index_column_name.c_str(), |
3817 | index_column_name.length(), |
3818 | NULL, ref_col_flags, table_obj); |
3819 | if (ctx->rc) { |
3820 | grn_obj_unlink(ctx, column); |
3821 | grn_obj_unlink(ctx, grn_table_ref); |
3822 | error = ER_CANT_CREATE_TABLE; |
3823 | my_message(error, ctx->errbuf, MYF(0)); |
3824 | DBUG_RETURN(false); |
3825 | } |
3826 | |
3827 | grn_obj source_ids; |
3828 | grn_id source_id = grn_obj_id(ctx, column); |
3829 | GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); |
3830 | GRN_UINT32_PUT(ctx, &source_ids, source_id); |
3831 | if (error) { |
3832 | grn_obj_unlink(ctx, &source_ids); |
3833 | grn_obj_unlink(ctx, column_ref); |
3834 | grn_obj_unlink(ctx, column); |
3835 | grn_obj_unlink(ctx, grn_table_ref); |
3836 | DBUG_RETURN(false); |
3837 | } |
3838 | grn_obj_set_info(ctx, column_ref, GRN_INFO_SOURCE, &source_ids); |
3839 | grn_obj_unlink(ctx, &source_ids); |
3840 | grn_obj_unlink(ctx, column_ref); |
3841 | grn_obj_unlink(ctx, column); |
3842 | grn_obj_unlink(ctx, grn_table_ref); |
3843 | error = 0; |
3844 | DBUG_RETURN(true); |
3845 | } |
3846 | error = 0; |
3847 | DBUG_RETURN(false); |
3848 | } |
3849 | #endif |
3850 | |
3851 | int ha_mroonga::storage_create_validate_index(TABLE *table) |
3852 | { |
3853 | int error = 0; |
3854 | uint i; |
3855 | |
3856 | MRN_DBUG_ENTER_METHOD(); |
3857 | /* checking if index is used for virtual columns */ |
3858 | uint n_keys = table->s->keys; |
3859 | for (i = 0; i < n_keys; i++) { |
3860 | KEY *key_info = &(table->s->key_info[i]); |
3861 | // must be single column key |
3862 | int key_parts = KEY_N_KEY_PARTS(key_info); |
3863 | if (key_parts != 1) { |
3864 | continue; |
3865 | } |
3866 | Field *field = key_info->key_part[0].field; |
3867 | const char *column_name = field->field_name.str; |
3868 | if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) { |
3869 | if (key_info->algorithm == HA_KEY_ALG_HASH) { |
3870 | continue; // hash index is ok |
3871 | } |
3872 | GRN_LOG(ctx, GRN_LOG_ERROR, "only hash index can be defined for _id" ); |
3873 | error = ER_CANT_CREATE_TABLE; |
3874 | my_message(error, "only hash index can be defined for _id" , MYF(0)); |
3875 | DBUG_RETURN(error); |
3876 | } |
3877 | } |
3878 | |
3879 | DBUG_RETURN(error); |
3880 | } |
3881 | |
3882 | int ha_mroonga::storage_create_index_table(TABLE *table, |
3883 | const char *grn_table_name, |
3884 | grn_obj *grn_table, |
3885 | MRN_SHARE *tmp_share, |
3886 | KEY *key_info, |
3887 | grn_obj **index_tables, |
3888 | uint i) |
3889 | { |
3890 | MRN_DBUG_ENTER_METHOD(); |
3891 | int error = 0; |
3892 | grn_obj *index_type; |
3893 | grn_obj *index_table; |
3894 | grn_obj_flags index_table_flags = GRN_OBJ_PERSISTENT; |
3895 | bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1; |
3896 | |
3897 | if (tmp_share->index_table && tmp_share->index_table[i]) { |
3898 | index_table = grn_ctx_get(ctx, |
3899 | tmp_share->index_table[i], |
3900 | tmp_share->index_table_length[i]); |
3901 | // TODO: add error check |
3902 | index_tables[i] = index_table; |
3903 | DBUG_RETURN(error); |
3904 | } |
3905 | |
3906 | if (is_multiple_column_index) { |
3907 | index_type = grn_ctx_at(ctx, GRN_DB_SHORT_TEXT); |
3908 | } else { |
3909 | Field *field = key_info->key_part[0].field; |
3910 | grn_builtin_type groonga_type = mrn_grn_type_from_field(ctx, field, true); |
3911 | index_type = grn_ctx_at(ctx, groonga_type); |
3912 | } |
3913 | // TODO: Add NULL check for index_type |
3914 | |
3915 | int key_alg = key_info->algorithm; |
3916 | if (key_info->flags & HA_FULLTEXT) { |
3917 | index_table_flags |= GRN_OBJ_TABLE_PAT_KEY; |
3918 | error = mrn_change_encoding(ctx, key_info->key_part->field->charset()); |
3919 | if (error) { |
3920 | grn_obj_remove(ctx, grn_table); |
3921 | DBUG_RETURN(error); |
3922 | } |
3923 | } else if (key_alg == HA_KEY_ALG_HASH) { |
3924 | index_table_flags |= GRN_OBJ_TABLE_HASH_KEY; |
3925 | } else { |
3926 | index_table_flags |= GRN_OBJ_TABLE_PAT_KEY; |
3927 | } |
3928 | |
3929 | { |
3930 | mrn::IndexTableName index_table_name(grn_table_name, key_info->name.str); |
3931 | index_table = grn_table_create(ctx, |
3932 | index_table_name.c_str(), |
3933 | index_table_name.length(), |
3934 | NULL, |
3935 | index_table_flags, |
3936 | index_type, |
3937 | NULL); |
3938 | } |
3939 | if (ctx->rc) { |
3940 | grn_obj_unlink(ctx, index_type); |
3941 | grn_obj_remove(ctx, grn_table); |
3942 | error = ER_CANT_CREATE_TABLE; |
3943 | my_message(ER_CANT_CREATE_TABLE, ctx->errbuf, MYF(0)); |
3944 | DBUG_RETURN(error); |
3945 | } |
3946 | |
3947 | if (key_info->flags & HA_FULLTEXT) { |
3948 | grn_obj *tokenizer = find_tokenizer(key_info, tmp_share, i); |
3949 | if (tokenizer) { |
3950 | grn_info_type info_type = GRN_INFO_DEFAULT_TOKENIZER; |
3951 | grn_obj_set_info(ctx, index_table, info_type, tokenizer); |
3952 | grn_obj_unlink(ctx, tokenizer); |
3953 | } |
3954 | |
3955 | { |
3956 | grn_obj token_filters; |
3957 | GRN_PTR_INIT(&token_filters, GRN_OBJ_VECTOR, 0); |
3958 | if (find_token_filters(key_info, &token_filters)) { |
3959 | grn_obj_set_info(ctx, index_table, |
3960 | GRN_INFO_TOKEN_FILTERS, &token_filters); |
3961 | } |
3962 | grn_obj_unlink(ctx, &token_filters); |
3963 | } |
3964 | } |
3965 | |
3966 | { |
3967 | grn_obj *normalizer = NULL; |
3968 | Field *field = &(key_info->key_part->field[0]); |
3969 | if (key_info->flags & HA_FULLTEXT) { |
3970 | if (have_custom_normalizer(key_info) || |
3971 | should_normalize(field)) { |
3972 | normalizer = find_normalizer(key_info); |
3973 | } |
3974 | } else if (key_alg != HA_KEY_ALG_HASH) { |
3975 | if (!is_multiple_column_index && |
3976 | (have_custom_normalizer(key_info) || |
3977 | should_normalize(field))) { |
3978 | normalizer = find_normalizer(key_info); |
3979 | } |
3980 | } |
3981 | if (normalizer) { |
3982 | grn_info_type info_type = GRN_INFO_NORMALIZER; |
3983 | grn_obj_set_info(ctx, index_table, info_type, normalizer); |
3984 | grn_obj_unlink(ctx, normalizer); |
3985 | } |
3986 | } |
3987 | |
3988 | index_tables[i] = index_table; |
3989 | |
3990 | DBUG_RETURN(error); |
3991 | } |
3992 | |
3993 | int ha_mroonga::storage_create_index(TABLE *table, const char *grn_table_name, |
3994 | grn_obj *grn_table, MRN_SHARE *tmp_share, |
3995 | KEY *key_info, grn_obj **index_tables, |
3996 | grn_obj **index_columns, uint i) |
3997 | { |
3998 | MRN_DBUG_ENTER_METHOD(); |
3999 | int error = 0; |
4000 | grn_obj *index_column; |
4001 | |
4002 | bool is_multiple_column_index = KEY_N_KEY_PARTS(key_info) > 1; |
4003 | if (!is_multiple_column_index) { |
4004 | Field *field = key_info->key_part[0].field; |
4005 | if (strcmp(MRN_COLUMN_NAME_ID, field->field_name.str) == 0) { |
4006 | // skipping _id virtual column |
4007 | DBUG_RETURN(0); |
4008 | } |
4009 | |
4010 | if (is_foreign_key_field(table->s->table_name.str, |
4011 | field->field_name.str)) { |
4012 | DBUG_RETURN(0); |
4013 | } |
4014 | |
4015 | #ifdef HA_CAN_VIRTUAL_COLUMNS |
4016 | if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) { |
4017 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
4018 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
4019 | "mroonga: storage: failed to create index: " |
4020 | ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_STR, |
4021 | field->field_name.str); |
4022 | error = ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_NUM; |
4023 | my_message(error, error_message, MYF(0)); |
4024 | DBUG_RETURN(error); |
4025 | } |
4026 | } else { |
4027 | int j, n_key_parts = KEY_N_KEY_PARTS(key_info); |
4028 | for (j = 0; j < n_key_parts; j++) { |
4029 | Field *field = key_info->key_part[j].field; |
4030 | if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) { |
4031 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
4032 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
4033 | "mroonga: storage: failed to create index: " |
4034 | ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_STR, |
4035 | field->field_name.str); |
4036 | error = ER_MRN_KEY_BASED_ON_GENERATED_VIRTUAL_COLUMN_NUM; |
4037 | my_message(error, error_message, MYF(0)); |
4038 | DBUG_RETURN(error); |
4039 | } |
4040 | } |
4041 | #endif |
4042 | } |
4043 | |
4044 | error = mrn_change_encoding(ctx, system_charset_info); |
4045 | if (error) |
4046 | DBUG_RETURN(error); |
4047 | |
4048 | error = storage_create_index_table(table, grn_table_name, |
4049 | grn_table, tmp_share, |
4050 | key_info, index_tables, i); |
4051 | if (error) |
4052 | DBUG_RETURN(error); |
4053 | |
4054 | grn_obj *index_table = index_tables[i]; |
4055 | |
4056 | grn_column_flags index_column_flags = GRN_OBJ_COLUMN_INDEX | GRN_OBJ_PERSISTENT; |
4057 | |
4058 | if (!find_index_column_flags(key_info, &index_column_flags)) { |
4059 | grn_obj *tokenizer = grn_obj_get_info(ctx, index_table, |
4060 | GRN_INFO_DEFAULT_TOKENIZER, NULL); |
4061 | if (tokenizer) { |
4062 | index_column_flags |= GRN_OBJ_WITH_POSITION; |
4063 | } |
4064 | if (is_multiple_column_index && (key_info->flags & HA_FULLTEXT)) { |
4065 | index_column_flags |= GRN_OBJ_WITH_SECTION; |
4066 | } |
4067 | } |
4068 | |
4069 | const char *index_column_name; |
4070 | if (tmp_share->index_table && tmp_share->index_table[i]) { |
4071 | index_column_name = key_info->name.str; |
4072 | } else { |
4073 | index_column_name = INDEX_COLUMN_NAME; |
4074 | } |
4075 | index_column = grn_column_create(ctx, |
4076 | index_table, |
4077 | index_column_name, |
4078 | strlen(index_column_name), |
4079 | NULL, |
4080 | index_column_flags, |
4081 | grn_table); |
4082 | |
4083 | if (ctx->rc) { |
4084 | grn_obj_remove(ctx, index_table); |
4085 | error = ER_CANT_CREATE_TABLE; |
4086 | my_message(error, ctx->errbuf, MYF(0)); |
4087 | DBUG_RETURN(error); |
4088 | } |
4089 | |
4090 | mrn_change_encoding(ctx, system_charset_info); |
4091 | if (is_multiple_column_index) { |
4092 | if (key_info->flags & HA_FULLTEXT) { |
4093 | grn_obj source_ids; |
4094 | GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); |
4095 | |
4096 | int j, n_key_parts = KEY_N_KEY_PARTS(key_info); |
4097 | for (j = 0; j < n_key_parts; j++) { |
4098 | Field *field = key_info->key_part[j].field; |
4099 | mrn::ColumnName column_name(field->field_name); |
4100 | grn_obj *source_column = grn_obj_column(ctx, |
4101 | grn_table, |
4102 | column_name.c_str(), |
4103 | column_name.length()); |
4104 | grn_id source_id = grn_obj_id(ctx, source_column); |
4105 | GRN_UINT32_PUT(ctx, &source_ids, source_id); |
4106 | grn_obj_unlink(ctx, source_column); |
4107 | } |
4108 | mrn_change_encoding(ctx, key_info->key_part->field->charset()); |
4109 | grn_obj_set_info(ctx, index_column, GRN_INFO_SOURCE, &source_ids); |
4110 | grn_obj_unlink(ctx, &source_ids); |
4111 | } |
4112 | } else { |
4113 | Field *field = key_info->key_part[0].field; |
4114 | mrn::ColumnName column_name(field->field_name); |
4115 | grn_obj *column; |
4116 | column = grn_obj_column(ctx, |
4117 | grn_table, |
4118 | column_name.c_str(), |
4119 | column_name.length()); |
4120 | if (column) { |
4121 | grn_obj source_ids; |
4122 | grn_id source_id = grn_obj_id(ctx, column); |
4123 | GRN_UINT32_INIT(&source_ids, GRN_OBJ_VECTOR); |
4124 | GRN_UINT32_PUT(ctx, &source_ids, source_id); |
4125 | mrn_change_encoding(ctx, key_info->key_part->field->charset()); |
4126 | grn_obj_set_info(ctx, index_column, GRN_INFO_SOURCE, &source_ids); |
4127 | grn_obj_unlink(ctx, &source_ids); |
4128 | grn_obj_unlink(ctx, column); |
4129 | } |
4130 | } |
4131 | mrn_change_encoding(ctx, system_charset_info); |
4132 | |
4133 | if (index_columns) { |
4134 | index_columns[i] = index_column; |
4135 | } |
4136 | |
4137 | DBUG_RETURN(error); |
4138 | } |
4139 | |
4140 | int ha_mroonga::storage_create_indexes(TABLE *table, const char *grn_table_name, |
4141 | grn_obj *grn_table, MRN_SHARE *tmp_share) |
4142 | { |
4143 | MRN_DBUG_ENTER_METHOD(); |
4144 | int error = 0; |
4145 | |
4146 | uint n_keys = table->s->keys; |
4147 | uint i; |
4148 | MRN_ALLOCATE_VARIABLE_LENGTH_ARRAYS(grn_obj *, index_tables, n_keys); |
4149 | for (i = 0; i < n_keys; i++) { |
4150 | index_tables[i] = NULL; |
4151 | if (i == table->s->primary_key) { |
4152 | continue; // pkey is already handled |
4153 | } |
4154 | KEY *key_info = &table->s->key_info[i]; |
4155 | if (tmp_share->disable_keys && !(key_info->flags & HA_NOSAME)) { |
4156 | continue; // key is disabled |
4157 | } |
4158 | if ((error = storage_create_index(table, grn_table_name, grn_table, |
4159 | tmp_share, key_info, |
4160 | index_tables, NULL, i))) { |
4161 | break; |
4162 | } |
4163 | } |
4164 | if (error) { |
4165 | while (true) { |
4166 | if (index_tables[i] && |
4167 | !(tmp_share->index_table && tmp_share->index_table[i])) { |
4168 | grn_obj_remove(ctx, index_tables[i]); |
4169 | } |
4170 | if (!i) |
4171 | break; |
4172 | i--; |
4173 | } |
4174 | } |
4175 | MRN_FREE_VARIABLE_LENGTH_ARRAYS(index_tables); |
4176 | DBUG_RETURN(error); |
4177 | } |
4178 | |
4179 | int ha_mroonga::ensure_database_open(const char *name, mrn::Database **db) |
4180 | { |
4181 | int error; |
4182 | |
4183 | MRN_DBUG_ENTER_METHOD(); |
4184 | |
4185 | if (db) |
4186 | *db = NULL; |
4187 | |
4188 | mrn::Database *local_db; |
4189 | error = mrn_db_manager->open(name, &local_db); |
4190 | if (error) |
4191 | DBUG_RETURN(error); |
4192 | |
4193 | if (db) |
4194 | *db = local_db; |
4195 | grn_ctx_use(ctx, local_db->get()); |
4196 | |
4197 | delete operations_; |
4198 | operations_ = new mrn::Operations(ctx); |
4199 | if (mrn_enable_operations_recording) { |
4200 | operations_->enable_recording(); |
4201 | } else { |
4202 | operations_->disable_recording(); |
4203 | } |
4204 | |
4205 | DBUG_RETURN(error); |
4206 | } |
4207 | |
4208 | int ha_mroonga::ensure_database_remove(const char *name) |
4209 | { |
4210 | int error; |
4211 | |
4212 | MRN_DBUG_ENTER_METHOD(); |
4213 | |
4214 | error = mrn_change_encoding(ctx, system_charset_info); |
4215 | if (error) |
4216 | DBUG_RETURN(error); |
4217 | |
4218 | delete operations_; |
4219 | operations_ = NULL; |
4220 | |
4221 | mrn_db_manager->close(name); |
4222 | |
4223 | mrn::PathMapper mapper(name); |
4224 | remove_related_files(mapper.db_path()); |
4225 | |
4226 | DBUG_RETURN(error); |
4227 | } |
4228 | |
4229 | |
4230 | int ha_mroonga::create(const char *name, |
4231 | TABLE *table, |
4232 | HA_CREATE_INFO *info |
4233 | #ifdef MRN_HANDLER_CREATE_HAVE_TABLE_DEFINITION |
4234 | , |
4235 | dd::Table *table_def |
4236 | #endif |
4237 | ) |
4238 | { |
4239 | int error = 0; |
4240 | MRN_SHARE *tmp_share; |
4241 | MRN_DBUG_ENTER_METHOD(); |
4242 | /* checking data type of virtual columns */ |
4243 | |
4244 | if (!(tmp_share = mrn_get_share(name, table, &error))) |
4245 | DBUG_RETURN(error); |
4246 | |
4247 | st_mrn_slot_data *slot_data = mrn_get_slot_data(ha_thd(), false); |
4248 | if (slot_data && slot_data->disable_keys_create_info == info) { |
4249 | tmp_share->disable_keys = true; |
4250 | } |
4251 | |
4252 | if (tmp_share->wrapper_mode) |
4253 | { |
4254 | error = wrapper_create(name, table, info, tmp_share); |
4255 | } else { |
4256 | error = storage_create(name, table, info, tmp_share); |
4257 | } |
4258 | |
4259 | if (error) { |
4260 | mrn_free_long_term_share(tmp_share->long_term_share); |
4261 | tmp_share->long_term_share = NULL; |
4262 | } else { |
4263 | error = add_wrap_hton(tmp_share->table_name, tmp_share->hton); |
4264 | } |
4265 | mrn_free_share(tmp_share); |
4266 | DBUG_RETURN(error); |
4267 | } |
4268 | |
4269 | int ha_mroonga::wrapper_open(const char *name, int mode, uint open_options) |
4270 | { |
4271 | int error = 0; |
4272 | MRN_DBUG_ENTER_METHOD(); |
4273 | |
4274 | mrn::Database *db = NULL; |
4275 | error = ensure_database_open(name, &db); |
4276 | if (error) |
4277 | DBUG_RETURN(error); |
4278 | |
4279 | if (!(open_options & HA_OPEN_FOR_REPAIR)) { |
4280 | error = open_table(name); |
4281 | if (error) |
4282 | DBUG_RETURN(error); |
4283 | |
4284 | error = wrapper_open_indexes(name); |
4285 | if (error) { |
4286 | grn_obj_unlink(ctx, grn_table); |
4287 | grn_table = NULL; |
4288 | DBUG_RETURN(error); |
4289 | } |
4290 | } |
4291 | |
4292 | mrn_init_alloc_root(&mem_root, 1024, 0, MYF(0)); |
4293 | wrap_key_info = mrn_create_key_info_for_table(share, table, &error); |
4294 | if (error) |
4295 | DBUG_RETURN(error); |
4296 | base_key_info = table->key_info; |
4297 | |
4298 | MRN_SET_WRAP_SHARE_KEY(share, table->s); |
4299 | MRN_SET_WRAP_TABLE_KEY(this, table); |
4300 | if (!is_clone) |
4301 | { |
4302 | wrap_handler = get_new_handler(table->s, &mem_root, share->hton); |
4303 | if (!wrap_handler) |
4304 | { |
4305 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
4306 | MRN_SET_BASE_TABLE_KEY(this, table); |
4307 | if (wrap_key_info) |
4308 | { |
4309 | my_free(wrap_key_info); |
4310 | wrap_key_info = NULL; |
4311 | } |
4312 | base_key_info = NULL; |
4313 | DBUG_RETURN(HA_ERR_OUT_OF_MEM); |
4314 | } |
4315 | #ifdef MRN_HANDLER_HAVE_SET_HA_SHARE_REF |
4316 | wrap_handler->set_ha_share_ref(&table->s->ha_share); |
4317 | #endif |
4318 | error = wrap_handler->ha_open(table, name, mode, open_options); |
4319 | } else { |
4320 | if (!(wrap_handler = parent_for_clone->wrap_handler->clone(name, |
4321 | mem_root_for_clone))) |
4322 | { |
4323 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
4324 | MRN_SET_BASE_TABLE_KEY(this, table); |
4325 | if (wrap_key_info) |
4326 | { |
4327 | my_free(wrap_key_info); |
4328 | wrap_key_info = NULL; |
4329 | } |
4330 | base_key_info = NULL; |
4331 | DBUG_RETURN(HA_ERR_OUT_OF_MEM); |
4332 | } |
4333 | } |
4334 | ref_length = wrap_handler->ref_length; |
4335 | key_used_on_scan = wrap_handler->key_used_on_scan; |
4336 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
4337 | MRN_SET_BASE_TABLE_KEY(this, table); |
4338 | init(); |
4339 | wrapper_overwrite_index_bits(); |
4340 | wrapper_set_keys_in_use(); |
4341 | |
4342 | pk_keypart_map = make_prev_keypart_map( |
4343 | KEY_N_KEY_PARTS(&(table->key_info[table_share->primary_key]))); |
4344 | |
4345 | if (!error) { |
4346 | if (open_options & HA_OPEN_FOR_REPAIR) { |
4347 | // TODO: How to check whether is DISABLE KEYS used or not? |
4348 | error = wrapper_recreate_indexes(ha_thd()); |
4349 | } else if (db) { |
4350 | mrn::Lock lock(&mrn_operations_mutex); |
4351 | mrn::PathMapper mapper(name); |
4352 | const char *table_name = mapper.table_name(); |
4353 | size_t table_name_size = strlen(table_name); |
4354 | if (db->is_broken_table(table_name, table_name_size)) { |
4355 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
4356 | "Auto repair is started: <%s>" , |
4357 | name); |
4358 | error = operations_->clear(table_name, table_name_size); |
4359 | if (!error) { |
4360 | db->mark_table_repaired(table_name, table_name_size); |
4361 | if (!share->disable_keys) { |
4362 | // TODO: implemented by "reindex" instead of "remove and recreate". |
4363 | // Because "remove and recreate" invalidates opened indexes by |
4364 | // other threads. |
4365 | error = wrapper_disable_indexes_mroonga(HA_KEY_SWITCH_ALL); |
4366 | if (!error) { |
4367 | error = wrapper_enable_indexes_mroonga(HA_KEY_SWITCH_ALL); |
4368 | } |
4369 | } |
4370 | } |
4371 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
4372 | "Auto repair is done: <%s>: %s" , |
4373 | name, error == 0 ? "success" : "failure" ); |
4374 | } |
4375 | } |
4376 | } |
4377 | |
4378 | if (error) |
4379 | { |
4380 | grn_obj_unlink(ctx, grn_table); |
4381 | grn_table = NULL; |
4382 | // TODO: free indexes. |
4383 | |
4384 | delete wrap_handler; |
4385 | wrap_handler = NULL; |
4386 | if (wrap_key_info) |
4387 | { |
4388 | my_free(wrap_key_info); |
4389 | wrap_key_info = NULL; |
4390 | } |
4391 | base_key_info = NULL; |
4392 | } |
4393 | DBUG_RETURN(error); |
4394 | } |
4395 | |
4396 | int ha_mroonga::wrapper_open_indexes(const char *name) |
4397 | { |
4398 | int error; |
4399 | |
4400 | MRN_DBUG_ENTER_METHOD(); |
4401 | |
4402 | error = mrn_change_encoding(ctx, system_charset_info); |
4403 | if (error) |
4404 | DBUG_RETURN(error); |
4405 | |
4406 | uint n_keys = table->s->keys; |
4407 | uint n_primary_keys = table->s->primary_key; |
4408 | if (n_keys > 0) { |
4409 | // TODO: reduce allocate memories. We only need just |
4410 | // for HA_KEY_ALG_FULLTEXT keys. |
4411 | grn_index_tables = (grn_obj **)malloc(sizeof(grn_obj *) * n_keys); |
4412 | grn_index_columns = (grn_obj **)malloc(sizeof(grn_obj *) * n_keys); |
4413 | } else { |
4414 | grn_index_tables = grn_index_columns = NULL; |
4415 | } |
4416 | |
4417 | mrn::PathMapper mapper(name); |
4418 | uint i = 0; |
4419 | for (i = 0; i < n_keys; i++) { |
4420 | KEY *key_info = &(table->s->key_info[i]); |
4421 | |
4422 | grn_index_tables[i] = NULL; |
4423 | grn_index_columns[i] = NULL; |
4424 | |
4425 | if (!(wrapper_is_target_index(key_info))) { |
4426 | continue; |
4427 | } |
4428 | |
4429 | if (i == n_primary_keys) { |
4430 | continue; |
4431 | } |
4432 | |
4433 | mrn::IndexTableName index_table_name(mapper.table_name(), key_info->name.str); |
4434 | grn_index_tables[i] = grn_ctx_get(ctx, |
4435 | index_table_name.c_str(), |
4436 | index_table_name.length()); |
4437 | if (ctx->rc == GRN_SUCCESS && !grn_index_tables[i]) { |
4438 | grn_index_tables[i] = grn_ctx_get(ctx, |
4439 | index_table_name.old_c_str(), |
4440 | index_table_name.old_length()); |
4441 | } |
4442 | if (ctx->rc) { |
4443 | DBUG_PRINT("info" , |
4444 | ("mroonga: sql_command=%u" , thd_sql_command(ha_thd()))); |
4445 | error = ER_CANT_OPEN_FILE; |
4446 | my_message(error, ctx->errbuf, MYF(0)); |
4447 | goto error; |
4448 | } |
4449 | |
4450 | grn_index_columns[i] = grn_obj_column(ctx, grn_index_tables[i], |
4451 | INDEX_COLUMN_NAME, |
4452 | strlen(INDEX_COLUMN_NAME)); |
4453 | if (!grn_index_columns[i]) { |
4454 | /* just for backward compatibility before 1.0. */ |
4455 | Field *field = key_info->key_part[0].field; |
4456 | grn_index_columns[i] = grn_obj_column(ctx, grn_index_tables[i], |
4457 | field->field_name.str, |
4458 | field->field_name.length); |
4459 | } |
4460 | |
4461 | if (ctx->rc) { |
4462 | DBUG_PRINT("info" , |
4463 | ("mroonga: sql_command=%u" , thd_sql_command(ha_thd()))); |
4464 | error = ER_CANT_OPEN_FILE; |
4465 | my_message(error, ctx->errbuf, MYF(0)); |
4466 | grn_obj_unlink(ctx, grn_index_tables[i]); |
4467 | goto error; |
4468 | } |
4469 | } |
4470 | |
4471 | grn_bulk_space(ctx, &key_buffer, table->key_info->key_length); |
4472 | |
4473 | error: |
4474 | if (error) { |
4475 | while (i-- > 0) { |
4476 | grn_obj *index_column = grn_index_columns[i]; |
4477 | if (index_column) { |
4478 | grn_obj_unlink(ctx, index_column); |
4479 | } |
4480 | grn_obj *index_table = grn_index_tables[i]; |
4481 | if (index_table) { |
4482 | grn_obj_unlink(ctx, index_table); |
4483 | } |
4484 | } |
4485 | free(grn_index_columns); |
4486 | free(grn_index_tables); |
4487 | grn_index_columns = NULL; |
4488 | grn_index_tables = NULL; |
4489 | } |
4490 | |
4491 | DBUG_RETURN(error); |
4492 | } |
4493 | |
4494 | void ha_mroonga::wrapper_overwrite_index_bits() |
4495 | { |
4496 | uint i, j; |
4497 | longlong table_option = table_flags(); |
4498 | MRN_DBUG_ENTER_METHOD(); |
4499 | table_share->keys_for_keyread.clear_all(); |
4500 | for (i = 0; i < table_share->fields; i++) |
4501 | { |
4502 | Field *field = table_share->field[i]; |
4503 | field->part_of_key.clear_all(); |
4504 | #ifdef MRN_HAVE_MYSQL_FIELD_PART_OF_KEY_NOT_CLUSTERED |
4505 | field->part_of_key_not_clustered.clear_all(); |
4506 | #endif |
4507 | field->part_of_sortkey.clear_all(); |
4508 | /* |
4509 | TODO: We may need to update field->part_of_key_not_extended for |
4510 | MySQL >= 5.7.18. If users report "raw InnoDB can use index for |
4511 | this case but Mroonga wrapper mode for InnoDB can't use index |
4512 | for the same case", we'll reconsider it again. |
4513 | */ |
4514 | } |
4515 | for (i = 0; i < table_share->keys; i++) { |
4516 | KEY *key_info = &table->s->key_info[i]; |
4517 | KEY_PART_INFO *key_part = key_info->key_part; |
4518 | for (j = 0 ; j < KEY_N_KEY_PARTS(key_info); key_part++, j++) |
4519 | { |
4520 | Field *field = key_part->field; |
4521 | if (field->key_length() == key_part->length && |
4522 | !(field->flags & BLOB_FLAG)) |
4523 | { |
4524 | if (index_flags(i, j, 0) & HA_KEYREAD_ONLY) |
4525 | { |
4526 | table_share->keys_for_keyread.set_bit(i); |
4527 | field->part_of_key.set_bit(i); |
4528 | #ifdef MRN_HAVE_MYSQL_FIELD_PART_OF_KEY_NOT_CLUSTERED |
4529 | field->part_of_key_not_clustered.set_bit(i); |
4530 | #endif |
4531 | } |
4532 | if (index_flags(i, j, 1) & HA_READ_ORDER) |
4533 | field->part_of_sortkey.set_bit(i); |
4534 | } |
4535 | if (i == table_share->primary_key && |
4536 | (table_option & HA_PRIMARY_KEY_IN_READ_INDEX)) |
4537 | { |
4538 | if (field->key_length() == key_part->length && |
4539 | !(field->flags & BLOB_FLAG)) |
4540 | field->part_of_key = table_share->keys_in_use; |
4541 | if (field->part_of_sortkey.is_set(i)) |
4542 | field->part_of_sortkey = table_share->keys_in_use; |
4543 | } |
4544 | } |
4545 | } |
4546 | DBUG_VOID_RETURN; |
4547 | } |
4548 | |
4549 | int ha_mroonga::storage_reindex() |
4550 | { |
4551 | int error = 0; |
4552 | MRN_DBUG_ENTER_METHOD(); |
4553 | |
4554 | uint n_keys = table_share->keys; |
4555 | KEY *key_info = table->key_info; |
4556 | |
4557 | bool have_multiple_column_index = false; |
4558 | bitmap_clear_all(table->read_set); |
4559 | for (uint i = 0; i < n_keys; ++i) { |
4560 | if (!grn_index_columns[i]) |
4561 | continue; |
4562 | |
4563 | grn_hash *columns = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
4564 | GRN_OBJ_TABLE_HASH_KEY); |
4565 | grn_table_columns(ctx, grn_index_tables[i], NULL, 0, |
4566 | reinterpret_cast<grn_obj *>(columns)); |
4567 | unsigned int n_columns = |
4568 | grn_table_size(ctx, reinterpret_cast<grn_obj *>(columns)); |
4569 | grn_hash_close(ctx, columns); |
4570 | |
4571 | bool is_multiple_column_index = |
4572 | (KEY_N_KEY_PARTS(&(key_info[i])) != 1 && |
4573 | !(key_info[i].flags & HA_FULLTEXT)); |
4574 | |
4575 | if (n_columns == 1 || is_multiple_column_index) { |
4576 | grn_table_truncate(ctx, grn_index_tables[i]); |
4577 | if (ctx->rc != GRN_SUCCESS) { |
4578 | error = ER_ERROR_ON_WRITE; |
4579 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
4580 | char index_table_name[GRN_TABLE_MAX_KEY_SIZE]; |
4581 | int index_table_name_size; |
4582 | index_table_name_size = |
4583 | grn_obj_name(ctx, grn_index_tables[i], |
4584 | index_table_name, GRN_TABLE_MAX_KEY_SIZE); |
4585 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
4586 | "mroonga: reindex: failed to truncate index table: " |
4587 | "<%.*s>: <%s>(%d)" , |
4588 | index_table_name_size, index_table_name, |
4589 | ctx->errbuf, ctx->rc); |
4590 | my_message(error, error_message, MYF(0)); |
4591 | break; |
4592 | } |
4593 | } |
4594 | |
4595 | if (is_multiple_column_index) { |
4596 | mrn_set_bitmap_by_key(table->read_set, &key_info[i]); |
4597 | have_multiple_column_index = true; |
4598 | } else { |
4599 | grn_obj_reindex(ctx, grn_index_columns[i]); |
4600 | if (ctx->rc != GRN_SUCCESS) { |
4601 | error = ER_ERROR_ON_WRITE; |
4602 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
4603 | char index_column_name[GRN_TABLE_MAX_KEY_SIZE]; |
4604 | int index_column_name_size; |
4605 | index_column_name_size = |
4606 | grn_obj_name(ctx, grn_index_columns[i], |
4607 | index_column_name, GRN_TABLE_MAX_KEY_SIZE); |
4608 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
4609 | "mroonga: reindex: failed to reindex: " |
4610 | "<%.*s>: <%s>(%d)" , |
4611 | index_column_name_size, index_column_name, |
4612 | ctx->errbuf, ctx->rc); |
4613 | my_message(error, error_message, MYF(0)); |
4614 | break; |
4615 | } |
4616 | } |
4617 | } |
4618 | |
4619 | if (!error && have_multiple_column_index) |
4620 | error = storage_add_index_multiple_columns(key_info, n_keys, |
4621 | grn_index_tables, |
4622 | grn_index_columns, |
4623 | false); |
4624 | bitmap_set_all(table->read_set); |
4625 | |
4626 | DBUG_RETURN(error); |
4627 | } |
4628 | |
4629 | int ha_mroonga::storage_open(const char *name, int mode, uint open_options) |
4630 | { |
4631 | int error = 0; |
4632 | MRN_DBUG_ENTER_METHOD(); |
4633 | |
4634 | mrn::Database *db; |
4635 | error = ensure_database_open(name, &db); |
4636 | if (error) |
4637 | DBUG_RETURN(error); |
4638 | |
4639 | error = open_table(name); |
4640 | if (error) |
4641 | DBUG_RETURN(error); |
4642 | |
4643 | error = storage_open_columns(); |
4644 | if (error) { |
4645 | grn_obj_unlink(ctx, grn_table); |
4646 | grn_table = NULL; |
4647 | DBUG_RETURN(error); |
4648 | } |
4649 | |
4650 | if (!(open_options & HA_OPEN_FOR_REPAIR)) { |
4651 | error = storage_open_indexes(name); |
4652 | if (error) { |
4653 | storage_close_columns(); |
4654 | grn_obj_unlink(ctx, grn_table); |
4655 | grn_table = NULL; |
4656 | DBUG_RETURN(error); |
4657 | } |
4658 | |
4659 | storage_set_keys_in_use(); |
4660 | |
4661 | { |
4662 | mrn::Lock lock(&mrn_operations_mutex); |
4663 | mrn::PathMapper mapper(name); |
4664 | const char *table_name = mapper.table_name(); |
4665 | size_t table_name_size = strlen(table_name); |
4666 | if (db->is_broken_table(table_name, table_name_size)) { |
4667 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
4668 | "Auto repair is started: <%s>" , |
4669 | name); |
4670 | error = operations_->repair(table_name, table_name_size); |
4671 | if (!error) |
4672 | db->mark_table_repaired(table_name, table_name_size); |
4673 | if (!share->disable_keys) { |
4674 | if (!error) |
4675 | error = storage_reindex(); |
4676 | } |
4677 | GRN_LOG(ctx, GRN_LOG_NOTICE, |
4678 | "Auto repair is done: <%s>: %s" , |
4679 | name, error == 0 ? "success" : "failure" ); |
4680 | } |
4681 | } |
4682 | } |
4683 | |
4684 | ref_length = sizeof(grn_id); |
4685 | DBUG_RETURN(0); |
4686 | } |
4687 | |
4688 | int ha_mroonga::open_table(const char *name) |
4689 | { |
4690 | int error; |
4691 | MRN_DBUG_ENTER_METHOD(); |
4692 | |
4693 | error = mrn_change_encoding(ctx, system_charset_info); |
4694 | if (error) |
4695 | DBUG_RETURN(error); |
4696 | |
4697 | mrn::PathMapper mapper(name); |
4698 | grn_table = grn_ctx_get(ctx, mapper.table_name(), strlen(mapper.table_name())); |
4699 | if (ctx->rc) { |
4700 | error = ER_CANT_OPEN_FILE; |
4701 | my_message(error, ctx->errbuf, MYF(0)); |
4702 | DBUG_RETURN(error); |
4703 | } |
4704 | if (!grn_table) { |
4705 | error = ER_CANT_OPEN_FILE; |
4706 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
4707 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
4708 | "mroonga: failed to open table: <%s>" , |
4709 | mapper.table_name()); |
4710 | my_message(error, error_message, MYF(0)); |
4711 | DBUG_RETURN(error); |
4712 | } |
4713 | |
4714 | DBUG_RETURN(0); |
4715 | } |
4716 | |
4717 | int ha_mroonga::storage_open_columns(void) |
4718 | { |
4719 | int error; |
4720 | MRN_DBUG_ENTER_METHOD(); |
4721 | |
4722 | error = mrn_change_encoding(ctx, system_charset_info); |
4723 | if (error) |
4724 | DBUG_RETURN(error); |
4725 | |
4726 | int n_columns = table->s->fields; |
4727 | grn_columns = (grn_obj **)malloc(sizeof(grn_obj *) * n_columns); |
4728 | grn_column_ranges = (grn_obj **)malloc(sizeof(grn_obj *) * n_columns); |
4729 | for (int i = 0; i < n_columns; i++) { |
4730 | grn_columns[i] = NULL; |
4731 | grn_column_ranges[i] = NULL; |
4732 | } |
4733 | |
4734 | if (table_share->blob_fields) |
4735 | { |
4736 | 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 | |
4790 | void 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 | |
4811 | int 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 | |
4902 | error: |
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 | |
4932 | int 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 | |
4971 | int 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 | |
4996 | int 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 | |
5007 | int 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 | |
5055 | int 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 | |
5074 | int 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 | |
5100 | int 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 | |
5188 | void 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 | |
5216 | void 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 | |
5239 | int 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 | |
5275 | int 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 | |
5324 | void 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 | |
5334 | void 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 | |
5343 | void 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 | |
5364 | int 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 | |
5378 | uint 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 | |
5390 | uint ha_mroonga::storage_lock_count() const |
5391 | { |
5392 | MRN_DBUG_ENTER_METHOD(); |
5393 | DBUG_RETURN(1); |
5394 | } |
5395 | |
5396 | uint 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 | |
5409 | THR_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 | |
5421 | THR_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 | |
5441 | THR_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 | |
5454 | int 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 | |
5466 | int ha_mroonga::storage_external_lock(THD *thd, int lock_type) |
5467 | { |
5468 | MRN_DBUG_ENTER_METHOD(); |
5469 | DBUG_RETURN(0); |
5470 | } |
5471 | |
5472 | int 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 | |
5486 | int 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 | |
5498 | int 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 | |
5510 | int 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 | |
5523 | int 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 | |
5535 | int ha_mroonga::storage_rnd_end() |
5536 | { |
5537 | MRN_DBUG_ENTER_METHOD(); |
5538 | clear_cursor(); |
5539 | DBUG_RETURN(0); |
5540 | } |
5541 | |
5542 | int 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 |
5556 | int 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 | |
5568 | int 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 | |
5575 | int 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 |
5587 | ha_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 | |
5599 | ha_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 | |
5606 | ha_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 | |
5619 | int 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 | |
5637 | int 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 | |
5644 | int 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 | |
5657 | int 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 | |
5673 | int 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 | |
5681 | int 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 | |
5694 | void 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 | |
5706 | void 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 | |
5713 | void 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 | |
5723 | int ha_mroonga::(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 | |
5754 | int ha_mroonga::(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 | |
5766 | int ha_mroonga::(enum ha_extra_function operation) |
5767 | { |
5768 | MRN_DBUG_ENTER_METHOD(); |
5769 | DBUG_RETURN(0); |
5770 | } |
5771 | |
5772 | int ha_mroonga::(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 | |
5790 | int ha_mroonga::(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 | |
5803 | int ha_mroonga::(enum ha_extra_function operation, |
5804 | ulong cache_size) |
5805 | { |
5806 | MRN_DBUG_ENTER_METHOD(); |
5807 | DBUG_RETURN(0); |
5808 | } |
5809 | |
5810 | int ha_mroonga::(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 | |
5826 | bool 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 | |
5835 | bool 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 | |
5856 | int 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 | |
5885 | int 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 | } |
5967 | err: |
5968 | |
5969 | DBUG_RETURN(error); |
5970 | } |
5971 | |
5972 | int 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 | |
6218 | err: |
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 | |
6235 | int 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 | |
6272 | int 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 | |
6307 | err: |
6308 | |
6309 | DBUG_RETURN(error); |
6310 | } |
6311 | |
6312 | int 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 | |
6384 | int 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 | |
6424 | err: |
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 | |
6447 | int 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 | |
6460 | int 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 | |
6494 | int 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 | |
6522 | int 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 | } |
6630 | err: |
6631 | |
6632 | DBUG_RETURN(error); |
6633 | } |
6634 | |
6635 | int 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 | |
6845 | err: |
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 | |
6868 | int 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 | } |
6952 | err: |
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 | |
6961 | int 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 | |
7024 | err: |
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 | |
7038 | int 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 | |
7051 | int 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 | |
7078 | int 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 | } |
7132 | err: |
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 | |
7142 | int 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 | |
7240 | int 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 | } |
7295 | err: |
7296 | grn_obj_unlink(ctx, &encoded_key); |
7297 | grn_obj_unlink(ctx, &key); |
7298 | |
7299 | DBUG_RETURN(error); |
7300 | } |
7301 | |
7302 | int 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 | |
7314 | int 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 | |
7341 | int 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 | |
7370 | int 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 | |
7415 | int 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 | |
7428 | uint ha_mroonga::wrapper_max_supported_key_parts() const |
7429 | { |
7430 | MRN_DBUG_ENTER_METHOD(); |
7431 | DBUG_RETURN(MAX_REF_PARTS); |
7432 | } |
7433 | |
7434 | uint ha_mroonga::storage_max_supported_key_parts() const |
7435 | { |
7436 | MRN_DBUG_ENTER_METHOD(); |
7437 | DBUG_RETURN(MAX_REF_PARTS); |
7438 | } |
7439 | |
7440 | uint 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 | |
7465 | ha_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 | |
7483 | ha_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 | |
7596 | ha_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 | |
7632 | ha_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 | |
7646 | int 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 | |
7664 | int ha_mroonga::storage_index_init(uint idx, bool sorted) |
7665 | { |
7666 | MRN_DBUG_ENTER_METHOD(); |
7667 | DBUG_RETURN(0); |
7668 | } |
7669 | |
7670 | int 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 | |
7685 | int 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 | |
7697 | int ha_mroonga::storage_index_end() |
7698 | { |
7699 | MRN_DBUG_ENTER_METHOD(); |
7700 | clear_cursor(); |
7701 | clear_cursor_geo(); |
7702 | DBUG_RETURN(0); |
7703 | } |
7704 | |
7705 | int 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 | |
7718 | int 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 | |
7748 | int 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 | |
8029 | int 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 |
8046 | int 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 | |
8065 | int 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 | |
8129 | int 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 | |
8144 | int 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 | |
8167 | int 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 | |
8174 | int 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 | |
8187 | int 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 | |
8210 | int 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 | |
8217 | int 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 | |
8230 | int 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 | |
8248 | int 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 | |
8282 | int 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 | |
8295 | int 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 | |
8313 | int 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 | |
8347 | int 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 | |
8360 | int 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 | |
8384 | int 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 | |
8392 | int 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 | |
8405 | int 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 | |
8445 | int ha_mroonga::wrapper_ft_init() |
8446 | { |
8447 | MRN_DBUG_ENTER_METHOD(); |
8448 | int error = generic_ft_init(); |
8449 | DBUG_RETURN(error); |
8450 | } |
8451 | |
8452 | int 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 | |
8460 | int 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 | |
8473 | void 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 | |
8488 | grn_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 | |
8508 | grn_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 | |
8531 | struct 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 | |
8616 | FT_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 | |
8700 | FT_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 | |
8719 | FT_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 | |
8736 | FT_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 | |
8759 | int 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 | |
8793 | int 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 | |
8845 | int 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 | |
8858 | const 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 | |
8870 | const 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 | |
8884 | const 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 | |
8897 | void 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 | |
8908 | void ha_mroonga::storage_cond_pop() |
8909 | { |
8910 | MRN_DBUG_ENTER_METHOD(); |
8911 | DBUG_VOID_RETURN; |
8912 | } |
8913 | |
8914 | void 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 | |
8924 | bool 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 | |
8936 | bool 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 | |
8945 | bool 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 | |
8958 | ulonglong 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 | |
8970 | bool 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 | |
8990 | bool 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 | |
9031 | void ha_mroonga::push_warning_unsupported_spatial_index_search(enum ha_rkey_function flag) |
9032 | { |
9033 | char search_name[MRN_BUFFER_SIZE]; |
9034 | if (flag == HA_READ_MBR_INTERSECT) { |
9035 | strcpy(search_name, "intersect" ); |
9036 | } else if (flag == HA_READ_MBR_WITHIN) { |
9037 | strcpy(search_name, "within" ); |
9038 | } else if (flag & HA_READ_MBR_DISJOINT) { |
9039 | strcpy(search_name, "disjoint" ); |
9040 | } else if (flag & HA_READ_MBR_EQUAL) { |
9041 | strcpy(search_name, "equal" ); |
9042 | } else { |
9043 | sprintf(search_name, "unknown: %d" , flag); |
9044 | } |
9045 | push_warning_printf(ha_thd(), |
9046 | MRN_SEVERITY_WARNING, |
9047 | ER_UNSUPPORTED_EXTENSION, |
9048 | "spatial index search " |
9049 | "except MBRContains aren't supported: <%s>" , |
9050 | search_name); |
9051 | } |
9052 | |
9053 | void ha_mroonga::clear_cursor() |
9054 | { |
9055 | MRN_DBUG_ENTER_METHOD(); |
9056 | if (cursor) { |
9057 | grn_obj_unlink(ctx, cursor); |
9058 | cursor = NULL; |
9059 | } |
9060 | if (index_table_cursor) { |
9061 | grn_table_cursor_close(ctx, index_table_cursor); |
9062 | index_table_cursor = NULL; |
9063 | } |
9064 | DBUG_VOID_RETURN; |
9065 | } |
9066 | |
9067 | void ha_mroonga::clear_cursor_geo() |
9068 | { |
9069 | MRN_DBUG_ENTER_METHOD(); |
9070 | if (cursor_geo) { |
9071 | grn_obj_unlink(ctx, cursor_geo); |
9072 | cursor_geo = NULL; |
9073 | } |
9074 | DBUG_VOID_RETURN; |
9075 | } |
9076 | |
9077 | void ha_mroonga::clear_empty_value_records() |
9078 | { |
9079 | MRN_DBUG_ENTER_METHOD(); |
9080 | if (empty_value_records_cursor) { |
9081 | grn_table_cursor_close(ctx, empty_value_records_cursor); |
9082 | empty_value_records_cursor = NULL; |
9083 | } |
9084 | if (empty_value_records) { |
9085 | grn_obj_unlink(ctx, empty_value_records); |
9086 | empty_value_records = NULL; |
9087 | } |
9088 | DBUG_VOID_RETURN; |
9089 | } |
9090 | |
9091 | void ha_mroonga::clear_search_result() |
9092 | { |
9093 | MRN_DBUG_ENTER_METHOD(); |
9094 | clear_cursor(); |
9095 | if (sorted_result) { |
9096 | grn_obj_unlink(ctx, sorted_result); |
9097 | sorted_result = NULL; |
9098 | } |
9099 | if (matched_record_keys) { |
9100 | grn_obj_unlink(ctx, matched_record_keys); |
9101 | matched_record_keys = NULL; |
9102 | } |
9103 | DBUG_VOID_RETURN; |
9104 | } |
9105 | |
9106 | void ha_mroonga::clear_search_result_geo() |
9107 | { |
9108 | MRN_DBUG_ENTER_METHOD(); |
9109 | clear_cursor_geo(); |
9110 | if (grn_source_column_geo) { |
9111 | grn_obj_unlink(ctx, grn_source_column_geo); |
9112 | grn_source_column_geo = NULL; |
9113 | } |
9114 | DBUG_VOID_RETURN; |
9115 | } |
9116 | |
9117 | void ha_mroonga::clear_indexes() |
9118 | { |
9119 | MRN_DBUG_ENTER_METHOD(); |
9120 | uint n_keys = table->s->keys; |
9121 | uint pkey_nr = table->s->primary_key; |
9122 | |
9123 | for (uint i = 0; i < n_keys; i++) { |
9124 | if (i != pkey_nr) { |
9125 | if (grn_index_tables) { |
9126 | grn_obj_unlink(ctx, grn_index_tables[i]); |
9127 | } |
9128 | if (grn_index_columns) { |
9129 | grn_obj_unlink(ctx, grn_index_columns[i]); |
9130 | } |
9131 | } |
9132 | } |
9133 | |
9134 | if (grn_index_tables) { |
9135 | free(grn_index_tables); |
9136 | grn_index_tables = NULL; |
9137 | } |
9138 | |
9139 | if (grn_index_columns) { |
9140 | free(grn_index_columns); |
9141 | grn_index_columns = NULL; |
9142 | } |
9143 | |
9144 | if (key_id) { |
9145 | free(key_id); |
9146 | key_id = NULL; |
9147 | } |
9148 | |
9149 | if (del_key_id) { |
9150 | free(del_key_id); |
9151 | del_key_id = NULL; |
9152 | } |
9153 | |
9154 | DBUG_VOID_RETURN; |
9155 | } |
9156 | |
9157 | int ha_mroonga::add_wrap_hton(const char *path, handlerton *wrap_handlerton) |
9158 | { |
9159 | MRN_DBUG_ENTER_METHOD(); |
9160 | st_mrn_slot_data *slot_data = mrn_get_slot_data(ha_thd(), true); |
9161 | if (!slot_data) |
9162 | DBUG_RETURN(HA_ERR_OUT_OF_MEM); |
9163 | st_mrn_wrap_hton *wrap_hton = |
9164 | (st_mrn_wrap_hton *)malloc(sizeof(st_mrn_wrap_hton)); |
9165 | if (!wrap_hton) |
9166 | DBUG_RETURN(HA_ERR_OUT_OF_MEM); |
9167 | wrap_hton->next = NULL; |
9168 | strcpy(wrap_hton->path, path); |
9169 | wrap_hton->hton = wrap_handlerton; |
9170 | if (slot_data->first_wrap_hton) |
9171 | { |
9172 | st_mrn_wrap_hton *tmp_wrap_hton = slot_data->first_wrap_hton; |
9173 | while (tmp_wrap_hton->next) |
9174 | tmp_wrap_hton = tmp_wrap_hton->next; |
9175 | tmp_wrap_hton->next = wrap_hton; |
9176 | } else { |
9177 | slot_data->first_wrap_hton = wrap_hton; |
9178 | } |
9179 | DBUG_RETURN(0); |
9180 | } |
9181 | |
9182 | void ha_mroonga::remove_related_files(const char *base_path) |
9183 | { |
9184 | MRN_DBUG_ENTER_METHOD(); |
9185 | |
9186 | const char *base_directory_name = "." ; |
9187 | size_t base_path_length = strlen(base_path); |
9188 | #ifdef WIN32 |
9189 | WIN32_FIND_DATA data; |
9190 | HANDLE finder = FindFirstFile(base_directory_name, &data); |
9191 | if (finder != INVALID_HANDLE_VALUE) { |
9192 | do { |
9193 | if (!(data.dwFileAttributes & FILE_ATTRIBUTE_NORMAL)) { |
9194 | continue; |
9195 | } |
9196 | if (strncmp(data.cFileName, base_path, base_path_length) == 0) { |
9197 | unlink(data.cFileName); |
9198 | } |
9199 | } while (FindNextFile(finder, &data) != 0); |
9200 | FindClose(finder); |
9201 | } |
9202 | #else |
9203 | DIR *dir = opendir(base_directory_name); |
9204 | if (dir) { |
9205 | while (struct dirent *entry = readdir(dir)) { |
9206 | struct stat file_status; |
9207 | if (stat(entry->d_name, &file_status) != 0) { |
9208 | continue; |
9209 | } |
9210 | if (!((file_status.st_mode & S_IFMT) && S_IFREG)) { |
9211 | continue; |
9212 | } |
9213 | if (strncmp(entry->d_name, base_path, base_path_length) == 0) { |
9214 | unlink(entry->d_name); |
9215 | } |
9216 | } |
9217 | closedir(dir); |
9218 | } |
9219 | #endif |
9220 | |
9221 | DBUG_VOID_RETURN; |
9222 | } |
9223 | |
9224 | void ha_mroonga::remove_grn_obj_force(const char *name) |
9225 | { |
9226 | MRN_DBUG_ENTER_METHOD(); |
9227 | |
9228 | grn_obj *obj = grn_ctx_get(ctx, name, strlen(name)); |
9229 | if (obj) { |
9230 | grn_obj_remove(ctx, obj); |
9231 | } else { |
9232 | grn_obj *db = grn_ctx_db(ctx); |
9233 | grn_id id = grn_table_get(ctx, db, name, strlen(name)); |
9234 | if (id) { |
9235 | char path[MRN_MAX_PATH_SIZE]; |
9236 | grn_obj_delete_by_id(ctx, db, id, GRN_TRUE); |
9237 | if (grn_obj_path_by_id(ctx, db, id, path) == GRN_SUCCESS) { |
9238 | remove_related_files(path); |
9239 | } |
9240 | } |
9241 | } |
9242 | |
9243 | DBUG_VOID_RETURN; |
9244 | } |
9245 | |
9246 | int ha_mroonga::drop_index(MRN_SHARE *target_share, uint key_index) |
9247 | { |
9248 | MRN_DBUG_ENTER_METHOD(); |
9249 | int error = 0; |
9250 | grn_rc rc = GRN_SUCCESS; |
9251 | char target_name[GRN_TABLE_MAX_KEY_SIZE]; |
9252 | int target_name_length; |
9253 | |
9254 | KEY *key_info = target_share->table_share->key_info; |
9255 | if (!target_share->wrapper_mode && target_share->index_table[key_index]) { |
9256 | const char *table_name = target_share->index_table[key_index]; |
9257 | snprintf(target_name, GRN_TABLE_MAX_KEY_SIZE, |
9258 | "%s.%s" , table_name, key_info[key_index].name.str); |
9259 | target_name_length = strlen(target_name); |
9260 | grn_obj *index_column = grn_ctx_get(ctx, target_name, target_name_length); |
9261 | if (index_column) { |
9262 | rc = grn_obj_remove(ctx, index_column); |
9263 | } |
9264 | } else { |
9265 | mrn::PathMapper mapper(target_share->table_name); |
9266 | mrn::IndexTableName index_table_name(mapper.table_name(), |
9267 | key_info[key_index].name.str); |
9268 | grn_obj *index_table = grn_ctx_get(ctx, |
9269 | index_table_name.c_str(), |
9270 | index_table_name.length()); |
9271 | if (!index_table) { |
9272 | index_table = grn_ctx_get(ctx, |
9273 | index_table_name.old_c_str(), |
9274 | index_table_name.old_length()); |
9275 | } |
9276 | if (index_table) { |
9277 | target_name_length = grn_obj_name(ctx, index_table, |
9278 | target_name, GRN_TABLE_MAX_KEY_SIZE); |
9279 | rc = grn_obj_remove(ctx, index_table); |
9280 | } else { |
9281 | target_name_length = 0; |
9282 | } |
9283 | } |
9284 | |
9285 | if (rc != GRN_SUCCESS) { |
9286 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
9287 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
9288 | "failed to drop index: <%.*s>: <%s>" , |
9289 | target_name_length, target_name, |
9290 | ctx->errbuf); |
9291 | my_message(ER_ERROR_ON_WRITE, error_message, MYF(0)); |
9292 | GRN_LOG(ctx, GRN_LOG_ERROR, "%s" , error_message); |
9293 | } |
9294 | |
9295 | DBUG_RETURN(error); |
9296 | } |
9297 | |
9298 | int ha_mroonga::drop_indexes_normal(const char *table_name, grn_obj *table) |
9299 | { |
9300 | MRN_DBUG_ENTER_METHOD(); |
9301 | |
9302 | int error = 0; |
9303 | |
9304 | grn_hash *columns_raw = grn_hash_create(ctx, NULL, sizeof(grn_id), 0, |
9305 | GRN_OBJ_TABLE_HASH_KEY); |
9306 | mrn::SmartGrnObj columns(ctx, reinterpret_cast<grn_obj *>(columns_raw)); |
9307 | if (!columns.get()) { |
9308 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
9309 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
9310 | "failed to allocate columns buffer: <%s>: <%s>" , |
9311 | table_name, ctx->errbuf); |
9312 | error = HA_ERR_OUT_OF_MEM; |
9313 | my_message(ER_ERROR_ON_WRITE, error_message, MYF(0)); |
9314 | GRN_LOG(ctx, GRN_LOG_ERROR, "%s" , error_message); |
9315 | DBUG_RETURN(error); |
9316 | } |
9317 | |
9318 | grn_table_columns(ctx, table, "" , 0, columns.get()); |
9319 | grn_table_cursor *cursor = grn_table_cursor_open(ctx, |
9320 | columns.get(), |
9321 | NULL, 0, |
9322 | NULL, 0, |
9323 | 0, -1, |
9324 | 0); |
9325 | if (!cursor) { |
9326 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
9327 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
9328 | "failed to allocate columns cursor: <%s>: <%s>" , |
9329 | table_name, ctx->errbuf); |
9330 | error = HA_ERR_OUT_OF_MEM; |
9331 | my_message(ER_ERROR_ON_WRITE, error_message, MYF(0)); |
9332 | GRN_LOG(ctx, GRN_LOG_ERROR, "%s" , error_message); |
9333 | DBUG_RETURN(error); |
9334 | } |
9335 | |
9336 | while (grn_table_cursor_next(ctx, cursor) != GRN_ID_NIL) { |
9337 | void *key; |
9338 | grn_table_cursor_get_key(ctx, cursor, &key); |
9339 | grn_id *id = reinterpret_cast<grn_id *>(key); |
9340 | mrn::SmartGrnObj column(ctx, grn_ctx_at(ctx, *id)); |
9341 | if (!column.get()) { |
9342 | continue; |
9343 | } |
9344 | |
9345 | grn_operator index_operators[] = { |
9346 | GRN_OP_EQUAL, |
9347 | GRN_OP_MATCH, |
9348 | GRN_OP_LESS, |
9349 | GRN_OP_REGEXP |
9350 | }; |
9351 | size_t n_index_operators = sizeof(index_operators) / sizeof(grn_operator); |
9352 | for (size_t i = 0; i < n_index_operators; i++) { |
9353 | grn_index_datum index_datum; |
9354 | while (grn_column_find_index_data(ctx, |
9355 | column.get(), |
9356 | index_operators[i], |
9357 | &index_datum, |
9358 | 1) > 0) { |
9359 | grn_id index_table_id = index_datum.index->header.domain; |
9360 | mrn::SmartGrnObj index_table(ctx, grn_ctx_at(ctx, index_table_id)); |
9361 | char index_table_name[GRN_TABLE_MAX_KEY_SIZE]; |
9362 | int index_table_name_length; |
9363 | index_table_name_length = grn_obj_name(ctx, index_table.get(), |
9364 | index_table_name, |
9365 | GRN_TABLE_MAX_KEY_SIZE); |
9366 | if (mrn::IndexTableName::is_custom_name(table_name, |
9367 | strlen(table_name), |
9368 | index_table_name, |
9369 | index_table_name_length)) { |
9370 | char index_column_name[GRN_TABLE_MAX_KEY_SIZE]; |
9371 | int index_column_name_length; |
9372 | index_column_name_length = grn_obj_name(ctx, |
9373 | index_datum.index, |
9374 | index_column_name, |
9375 | GRN_TABLE_MAX_KEY_SIZE); |
9376 | grn_rc rc = grn_obj_remove(ctx, index_datum.index); |
9377 | if (rc != GRN_SUCCESS) { |
9378 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
9379 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
9380 | "failed to drop index column: <%.*s>: <%s>" , |
9381 | index_column_name_length, index_column_name, |
9382 | ctx->errbuf); |
9383 | error = ER_ERROR_ON_WRITE; |
9384 | my_message(error, error_message, MYF(0)); |
9385 | GRN_LOG(ctx, GRN_LOG_ERROR, "%s" , error_message); |
9386 | } |
9387 | } else { |
9388 | grn_rc rc = grn_obj_remove(ctx, index_table.get()); |
9389 | if (rc == GRN_SUCCESS) { |
9390 | index_table.release(); |
9391 | } else { |
9392 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
9393 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
9394 | "failed to drop index table: <%.*s>: <%s>" , |
9395 | index_table_name_length, index_table_name, |
9396 | ctx->errbuf); |
9397 | error = ER_ERROR_ON_WRITE; |
9398 | my_message(error, error_message, MYF(0)); |
9399 | GRN_LOG(ctx, GRN_LOG_ERROR, "%s" , error_message); |
9400 | } |
9401 | } |
9402 | |
9403 | if (error != 0) { |
9404 | break; |
9405 | } |
9406 | } |
9407 | |
9408 | if (error != 0) { |
9409 | break; |
9410 | } |
9411 | } |
9412 | |
9413 | if (error != 0) { |
9414 | break; |
9415 | } |
9416 | } |
9417 | |
9418 | grn_table_cursor_close(ctx, cursor); |
9419 | |
9420 | DBUG_RETURN(error); |
9421 | } |
9422 | |
9423 | int ha_mroonga::drop_indexes_multiple(const char *table_name, |
9424 | grn_obj *table, |
9425 | const char *index_table_name_separator) |
9426 | { |
9427 | MRN_DBUG_ENTER_METHOD(); |
9428 | |
9429 | int error = 0; |
9430 | |
9431 | char index_table_name_prefix[GRN_TABLE_MAX_KEY_SIZE]; |
9432 | snprintf(index_table_name_prefix, GRN_TABLE_MAX_KEY_SIZE, |
9433 | "%s%s" , table_name, index_table_name_separator); |
9434 | grn_table_cursor *cursor = |
9435 | grn_table_cursor_open(ctx, |
9436 | grn_ctx_db(ctx), |
9437 | index_table_name_prefix, |
9438 | strlen(index_table_name_prefix), |
9439 | NULL, 0, |
9440 | 0, -1, |
9441 | GRN_CURSOR_PREFIX); |
9442 | if (!cursor) { |
9443 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
9444 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
9445 | "failed to allocate index tables cursor: <%s>: <%s>" , |
9446 | table_name, ctx->errbuf); |
9447 | error = HA_ERR_OUT_OF_MEM; |
9448 | my_message(ER_ERROR_ON_WRITE, error_message, MYF(0)); |
9449 | GRN_LOG(ctx, GRN_LOG_ERROR, "%s" , error_message); |
9450 | DBUG_RETURN(error); |
9451 | } |
9452 | |
9453 | grn_id table_id = grn_obj_id(ctx, table); |
9454 | grn_id id; |
9455 | while ((id = grn_table_cursor_next(ctx, cursor)) != GRN_ID_NIL) { |
9456 | mrn::SmartGrnObj object(ctx, grn_ctx_at(ctx, id)); |
9457 | if (!object.get()) { |
9458 | continue; |
9459 | } |
9460 | if (!grn_obj_is_table(ctx, object.get())) { |
9461 | continue; |
9462 | } |
9463 | |
9464 | char multiple_column_index_table_name[GRN_TABLE_MAX_KEY_SIZE]; |
9465 | int multiple_column_index_table_name_length; |
9466 | multiple_column_index_table_name_length = |
9467 | grn_obj_name(ctx, |
9468 | object.get(), |
9469 | multiple_column_index_table_name, |
9470 | GRN_TABLE_MAX_KEY_SIZE); |
9471 | |
9472 | char multiple_column_index_name[GRN_TABLE_MAX_KEY_SIZE]; |
9473 | snprintf(multiple_column_index_name, GRN_TABLE_MAX_KEY_SIZE, |
9474 | "%.*s.%s" , |
9475 | multiple_column_index_table_name_length, |
9476 | multiple_column_index_table_name, |
9477 | INDEX_COLUMN_NAME); |
9478 | mrn::SmartGrnObj index_column(ctx, multiple_column_index_name); |
9479 | if (!index_column.get()) { |
9480 | continue; |
9481 | } |
9482 | |
9483 | if (grn_obj_get_range(ctx, index_column.get()) != table_id) { |
9484 | continue; |
9485 | } |
9486 | |
9487 | grn_rc rc = grn_obj_remove(ctx, object.get()); |
9488 | if (rc == GRN_SUCCESS) { |
9489 | object.release(); |
9490 | index_column.release(); |
9491 | } else { |
9492 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
9493 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
9494 | "failed to drop multiple column index table: <%.*s>: <%s>" , |
9495 | multiple_column_index_table_name_length, |
9496 | multiple_column_index_table_name, |
9497 | ctx->errbuf); |
9498 | error = ER_ERROR_ON_WRITE; |
9499 | my_message(error, error_message, MYF(0)); |
9500 | GRN_LOG(ctx, GRN_LOG_ERROR, "%s" , error_message); |
9501 | break; |
9502 | } |
9503 | } |
9504 | |
9505 | grn_table_cursor_close(ctx, cursor); |
9506 | |
9507 | DBUG_RETURN(error); |
9508 | } |
9509 | |
9510 | int ha_mroonga::drop_indexes(const char *table_name) |
9511 | { |
9512 | MRN_DBUG_ENTER_METHOD(); |
9513 | int error = 0; |
9514 | |
9515 | mrn::SmartGrnObj table(ctx, table_name); |
9516 | if (!table.get()) { |
9517 | DBUG_RETURN(0); |
9518 | } |
9519 | |
9520 | error = drop_indexes_normal(table_name, table.get()); |
9521 | if (error == 0) { |
9522 | error = drop_indexes_multiple(table_name, table.get(), |
9523 | mrn::IndexTableName::SEPARATOR); |
9524 | } |
9525 | if (error == 0) { |
9526 | error = drop_indexes_multiple(table_name, table.get(), |
9527 | mrn::IndexTableName::OLD_SEPARATOR); |
9528 | } |
9529 | |
9530 | DBUG_RETURN(error); |
9531 | } |
9532 | |
9533 | bool ha_mroonga::find_column_flags(Field *field, MRN_SHARE *mrn_share, int i, |
9534 | grn_obj_flags *column_flags) |
9535 | { |
9536 | MRN_DBUG_ENTER_METHOD(); |
9537 | bool found = false; |
9538 | |
9539 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
9540 | { |
9541 | const char *names = field->option_struct->flags; |
9542 | if (names) { |
9543 | found = mrn_parse_grn_column_create_flags(ha_thd(), |
9544 | ctx, |
9545 | names, |
9546 | strlen(names), |
9547 | column_flags); |
9548 | DBUG_RETURN(found); |
9549 | } |
9550 | } |
9551 | #endif |
9552 | |
9553 | if (mrn_share->col_flags[i]) { |
9554 | found = mrn_parse_grn_column_create_flags(ha_thd(), |
9555 | ctx, |
9556 | mrn_share->col_flags[i], |
9557 | mrn_share->col_flags_length[i], |
9558 | column_flags); |
9559 | DBUG_RETURN(found); |
9560 | } |
9561 | |
9562 | DBUG_RETURN(found); |
9563 | } |
9564 | |
9565 | grn_obj *ha_mroonga::find_column_type(Field *field, MRN_SHARE *mrn_share, int i, |
9566 | int error_code) |
9567 | { |
9568 | MRN_DBUG_ENTER_METHOD(); |
9569 | |
9570 | const char *grn_type_name = NULL; |
9571 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
9572 | grn_type_name = field->option_struct->groonga_type; |
9573 | #endif |
9574 | if (!grn_type_name) { |
9575 | grn_type_name = mrn_share->col_type[i]; |
9576 | } |
9577 | |
9578 | grn_obj *type = NULL; |
9579 | if (grn_type_name) { |
9580 | type = grn_ctx_get(ctx, grn_type_name, -1); |
9581 | if (!type) { |
9582 | char error_message[MRN_BUFFER_SIZE]; |
9583 | snprintf(error_message, MRN_BUFFER_SIZE, |
9584 | "unknown custom Groonga type name for <%s> column: <%s>" , |
9585 | field->field_name.str, grn_type_name); |
9586 | GRN_LOG(ctx, GRN_LOG_ERROR, "%s" , error_message); |
9587 | my_message(error_code, error_message, MYF(0)); |
9588 | |
9589 | DBUG_RETURN(NULL); |
9590 | } |
9591 | } else { |
9592 | grn_builtin_type grn_type_id = mrn_grn_type_from_field(ctx, field, false); |
9593 | type = grn_ctx_at(ctx, grn_type_id); |
9594 | } |
9595 | |
9596 | DBUG_RETURN(type); |
9597 | } |
9598 | |
9599 | grn_obj *ha_mroonga::find_tokenizer(KEY *key, MRN_SHARE *mrn_share, int i) |
9600 | { |
9601 | MRN_DBUG_ENTER_METHOD(); |
9602 | grn_obj *tokenizer; |
9603 | const char *tokenizer_name = NULL; |
9604 | uint tokenizer_name_length = 0; |
9605 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
9606 | if (key->option_struct->tokenizer) { |
9607 | tokenizer_name = key->option_struct->tokenizer; |
9608 | tokenizer_name_length = strlen(tokenizer_name); |
9609 | } |
9610 | #endif |
9611 | if (!tokenizer_name) { |
9612 | tokenizer_name = mrn_share->key_tokenizer[i]; |
9613 | tokenizer_name_length = mrn_share->key_tokenizer_length[i]; |
9614 | } |
9615 | tokenizer = find_tokenizer(tokenizer_name, tokenizer_name_length); |
9616 | DBUG_RETURN(tokenizer); |
9617 | } |
9618 | |
9619 | grn_obj *ha_mroonga::find_tokenizer(const char *name, int name_length) |
9620 | { |
9621 | MRN_DBUG_ENTER_METHOD(); |
9622 | |
9623 | if (strncasecmp("off" , name, name_length) == 0) { |
9624 | DBUG_RETURN(NULL); |
9625 | } |
9626 | |
9627 | grn_obj *tokenizer; |
9628 | mrn_change_encoding(ctx, system_charset_info); |
9629 | tokenizer = grn_ctx_get(ctx, name, name_length); |
9630 | if (!tokenizer) { |
9631 | char message[MRN_BUFFER_SIZE]; |
9632 | sprintf(message, |
9633 | "specified tokenizer for fulltext index <%.*s> doesn't exist. " |
9634 | "The default tokenizer for fulltext index <%s> is used instead." , |
9635 | name_length, name, |
9636 | MRN_DEFAULT_TOKENIZER); |
9637 | push_warning(ha_thd(), |
9638 | MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION, |
9639 | message); |
9640 | tokenizer = grn_ctx_get(ctx, |
9641 | MRN_DEFAULT_TOKENIZER, |
9642 | strlen(MRN_DEFAULT_TOKENIZER)); |
9643 | } |
9644 | if (!tokenizer) { |
9645 | push_warning(ha_thd(), |
9646 | MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION, |
9647 | "couldn't find tokenizer for fulltext index. " |
9648 | "Bigram tokenizer is used instead." ); |
9649 | tokenizer = grn_ctx_at(ctx, GRN_DB_BIGRAM); |
9650 | } |
9651 | DBUG_RETURN(tokenizer); |
9652 | } |
9653 | |
9654 | bool ha_mroonga::have_custom_normalizer(KEY *key) const |
9655 | { |
9656 | MRN_DBUG_ENTER_METHOD(); |
9657 | |
9658 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
9659 | if (key->option_struct && key->option_struct->normalizer) { |
9660 | DBUG_RETURN(true); |
9661 | } |
9662 | #endif |
9663 | |
9664 | if (key->comment.length > 0) { |
9665 | mrn::ParametersParser parser(key->comment.str, |
9666 | key->comment.length); |
9667 | parser.parse(); |
9668 | DBUG_RETURN(parser["normalizer" ] != NULL); |
9669 | } |
9670 | |
9671 | DBUG_RETURN(false); |
9672 | } |
9673 | |
9674 | grn_obj *ha_mroonga::find_normalizer(KEY *key) |
9675 | { |
9676 | MRN_DBUG_ENTER_METHOD(); |
9677 | |
9678 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
9679 | if (key->option_struct->normalizer) { |
9680 | grn_obj *normalizer = find_normalizer(key, |
9681 | key->option_struct->normalizer); |
9682 | DBUG_RETURN(normalizer); |
9683 | } |
9684 | #endif |
9685 | |
9686 | if (key->comment.length > 0) { |
9687 | mrn::ParametersParser parser(key->comment.str, |
9688 | key->comment.length); |
9689 | parser.parse(); |
9690 | grn_obj *normalizer = find_normalizer(key, parser["normalizer" ]); |
9691 | DBUG_RETURN(normalizer); |
9692 | } |
9693 | |
9694 | grn_obj *normalizer = find_normalizer(key, NULL); |
9695 | DBUG_RETURN(normalizer); |
9696 | } |
9697 | |
9698 | grn_obj *ha_mroonga::find_normalizer(KEY *key, const char *name) |
9699 | { |
9700 | MRN_DBUG_ENTER_METHOD(); |
9701 | |
9702 | grn_obj *normalizer = NULL; |
9703 | bool use_normalizer = true; |
9704 | if (name) { |
9705 | if (strcmp(name, "none" ) == 0) { |
9706 | use_normalizer = false; |
9707 | } else { |
9708 | normalizer = grn_ctx_get(ctx, name, -1); |
9709 | } |
9710 | } |
9711 | if (use_normalizer && !normalizer) { |
9712 | Field *field = key->key_part[0].field; |
9713 | mrn::FieldNormalizer field_normalizer(ctx, ha_thd(), field); |
9714 | normalizer = field_normalizer.find_grn_normalizer(); |
9715 | } |
9716 | |
9717 | DBUG_RETURN(normalizer); |
9718 | } |
9719 | |
9720 | bool ha_mroonga::find_index_column_flags(KEY *key, grn_column_flags *index_column_flags) |
9721 | { |
9722 | MRN_DBUG_ENTER_METHOD(); |
9723 | bool found = false; |
9724 | |
9725 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
9726 | { |
9727 | const char *names = key->option_struct->flags; |
9728 | if (names) { |
9729 | found = mrn_parse_grn_index_column_flags(ha_thd(), |
9730 | ctx, |
9731 | names, |
9732 | strlen(names), |
9733 | index_column_flags); |
9734 | DBUG_RETURN(found); |
9735 | } |
9736 | } |
9737 | #endif |
9738 | |
9739 | if (key->comment.length > 0) { |
9740 | mrn::ParametersParser parser(key->comment.str, |
9741 | key->comment.length); |
9742 | parser.parse(); |
9743 | const char *names = parser["flags" ]; |
9744 | if (!names) { |
9745 | // Deprecated. It's for backward compatibility. |
9746 | names = parser["index_flags" ]; |
9747 | } |
9748 | if (names) { |
9749 | found = mrn_parse_grn_index_column_flags(ha_thd(), |
9750 | ctx, |
9751 | names, |
9752 | strlen(names), |
9753 | index_column_flags); |
9754 | } |
9755 | } |
9756 | |
9757 | DBUG_RETURN(found); |
9758 | } |
9759 | |
9760 | bool ha_mroonga::find_token_filters(KEY *key, grn_obj *token_filters) |
9761 | { |
9762 | MRN_DBUG_ENTER_METHOD(); |
9763 | bool found = false; |
9764 | |
9765 | #ifdef MRN_SUPPORT_CUSTOM_OPTIONS |
9766 | if (key->option_struct->token_filters) { |
9767 | found = find_token_filters_fill(token_filters, |
9768 | key->option_struct->token_filters, |
9769 | strlen(key->option_struct->token_filters)); |
9770 | DBUG_RETURN(found); |
9771 | } |
9772 | #endif |
9773 | |
9774 | if (key->comment.length > 0) { |
9775 | mrn::ParametersParser parser(key->comment.str, |
9776 | key->comment.length); |
9777 | parser.parse(); |
9778 | const char *names = parser["token_filters" ]; |
9779 | if (names) { |
9780 | found = find_token_filters_fill(token_filters, names, strlen(names)); |
9781 | } |
9782 | } |
9783 | |
9784 | DBUG_RETURN(found); |
9785 | } |
9786 | |
9787 | bool ha_mroonga::find_token_filters_put(grn_obj *token_filters, |
9788 | const char *token_filter_name, |
9789 | int token_filter_name_length) |
9790 | { |
9791 | grn_obj *token_filter; |
9792 | |
9793 | token_filter = grn_ctx_get(ctx, |
9794 | token_filter_name, |
9795 | token_filter_name_length); |
9796 | if (token_filter) { |
9797 | GRN_PTR_PUT(ctx, token_filters, token_filter); |
9798 | return true; |
9799 | } else { |
9800 | char message[MRN_BUFFER_SIZE]; |
9801 | sprintf(message, |
9802 | "nonexistent token filter: <%.*s>" , |
9803 | token_filter_name_length, token_filter_name); |
9804 | push_warning(ha_thd(), |
9805 | MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION, |
9806 | message); |
9807 | return false; |
9808 | } |
9809 | } |
9810 | |
9811 | bool ha_mroonga::find_token_filters_fill(grn_obj *token_filters, |
9812 | const char *token_filter_names, |
9813 | int token_filter_names_length) |
9814 | { |
9815 | const char *start, *current, *end; |
9816 | const char *name_start, *name_end; |
9817 | const char *last_name_end; |
9818 | |
9819 | start = token_filter_names; |
9820 | end = start + token_filter_names_length; |
9821 | current = start; |
9822 | name_start = NULL; |
9823 | name_end = NULL; |
9824 | last_name_end = start; |
9825 | while (current < end) { |
9826 | switch (current[0]) { |
9827 | case ' ' : |
9828 | if (name_start && !name_end) { |
9829 | name_end = current; |
9830 | } |
9831 | break; |
9832 | case ',' : |
9833 | if (!name_start) { |
9834 | goto break_loop; |
9835 | } |
9836 | if (!name_end) { |
9837 | name_end = current; |
9838 | } |
9839 | find_token_filters_put(token_filters, |
9840 | name_start, |
9841 | name_end - name_start); |
9842 | last_name_end = name_end + 1; |
9843 | name_start = NULL; |
9844 | name_end = NULL; |
9845 | break; |
9846 | default : |
9847 | if (!name_start) { |
9848 | name_start = current; |
9849 | } |
9850 | break; |
9851 | } |
9852 | current++; |
9853 | } |
9854 | |
9855 | break_loop: |
9856 | if (!name_start) { |
9857 | char message[MRN_BUFFER_SIZE]; |
9858 | sprintf(message, |
9859 | "empty token filter name: " |
9860 | "<%.*s|%.*s|%.*s>" , |
9861 | (int)(last_name_end - start), start, |
9862 | (int)(current - last_name_end), last_name_end, |
9863 | (int)(end - current), current); |
9864 | push_warning(ha_thd(), |
9865 | MRN_SEVERITY_WARNING, ER_UNSUPPORTED_EXTENSION, |
9866 | message); |
9867 | return false; |
9868 | } |
9869 | |
9870 | if (!name_end) { |
9871 | name_end = current; |
9872 | } |
9873 | find_token_filters_put(token_filters, |
9874 | name_start, |
9875 | name_end - name_start); |
9876 | |
9877 | return true; |
9878 | } |
9879 | |
9880 | int ha_mroonga::wrapper_get_record(uchar *buf, const uchar *key) |
9881 | { |
9882 | MRN_DBUG_ENTER_METHOD(); |
9883 | |
9884 | int error = 0; |
9885 | MRN_SET_WRAP_SHARE_KEY(share, table->s); |
9886 | MRN_SET_WRAP_TABLE_KEY(this, table); |
9887 | if (wrap_handler->inited == NONE) { |
9888 | #ifdef MRN_HANDLER_HAVE_HA_INDEX_READ_IDX_MAP |
9889 | error = wrap_handler->ha_index_read_idx_map(buf, |
9890 | share->wrap_primary_key, |
9891 | key, |
9892 | pk_keypart_map, |
9893 | HA_READ_KEY_EXACT); |
9894 | #else |
9895 | error = wrap_handler->index_read_idx_map(buf, |
9896 | share->wrap_primary_key, |
9897 | key, |
9898 | pk_keypart_map, |
9899 | HA_READ_KEY_EXACT); |
9900 | #endif |
9901 | } else { |
9902 | #ifdef MRN_HANDLER_HAVE_HA_INDEX_READ_MAP |
9903 | error = wrap_handler->ha_index_read_map(buf, |
9904 | key, |
9905 | pk_keypart_map, |
9906 | HA_READ_KEY_EXACT); |
9907 | #else |
9908 | error = wrap_handler->index_read_map(buf, |
9909 | key, |
9910 | pk_keypart_map, |
9911 | HA_READ_KEY_EXACT); |
9912 | #endif |
9913 | } |
9914 | MRN_SET_BASE_SHARE_KEY(share, table->s); |
9915 | MRN_SET_BASE_TABLE_KEY(this, table); |
9916 | |
9917 | DBUG_RETURN(error); |
9918 | } |
9919 | |
9920 | int ha_mroonga::wrapper_get_next_geo_record(uchar *buf) |
9921 | { |
9922 | MRN_DBUG_ENTER_METHOD(); |
9923 | int error = 0; |
9924 | mrn_change_encoding(ctx, NULL); |
9925 | do { |
9926 | GRN_BULK_REWIND(&key_buffer); |
9927 | grn_id found_record_id; |
9928 | grn_posting *posting; |
9929 | posting = grn_geo_cursor_next(ctx, cursor_geo); |
9930 | if (!posting) { |
9931 | error = HA_ERR_END_OF_FILE; |
9932 | clear_cursor_geo(); |
9933 | break; |
9934 | } |
9935 | found_record_id = posting->rid; |
9936 | grn_table_get_key(ctx, grn_table, found_record_id, |
9937 | GRN_TEXT_VALUE(&key_buffer), |
9938 | table->key_info->key_length); |
9939 | error = wrapper_get_record(buf, (const uchar *)GRN_TEXT_VALUE(&key_buffer)); |
9940 | } while (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND); |
9941 | DBUG_RETURN(error); |
9942 | } |
9943 | |
9944 | int ha_mroonga::storage_get_next_record(uchar *buf) |
9945 | { |
9946 | MRN_DBUG_ENTER_METHOD(); |
9947 | if (cursor_geo) { |
9948 | grn_posting *posting; |
9949 | posting = grn_geo_cursor_next(ctx, cursor_geo); |
9950 | if (posting) { |
9951 | record_id = posting->rid; |
9952 | } else { |
9953 | record_id = GRN_ID_NIL; |
9954 | } |
9955 | } else if (cursor) { |
9956 | record_id = grn_table_cursor_next(ctx, cursor); |
9957 | } else if (empty_value_records_cursor) { |
9958 | grn_id empty_value_record_id; |
9959 | empty_value_record_id = |
9960 | grn_table_cursor_next(ctx, empty_value_records_cursor); |
9961 | if (empty_value_record_id == GRN_ID_NIL) { |
9962 | record_id = GRN_ID_NIL; |
9963 | } else { |
9964 | grn_table_get_key(ctx, empty_value_records, empty_value_record_id, |
9965 | &record_id, sizeof(grn_id)); |
9966 | } |
9967 | } else { |
9968 | record_id = GRN_ID_NIL; |
9969 | } |
9970 | if (ctx->rc) { |
9971 | int error = ER_ERROR_ON_READ; |
9972 | my_message(error, ctx->errbuf, MYF(0)); |
9973 | DBUG_RETURN(error); |
9974 | } |
9975 | if (record_id == GRN_ID_NIL) { |
9976 | DBUG_PRINT("info" , ("mroonga: storage_get_next_record: end-of-file" )); |
9977 | table->status = STATUS_NOT_FOUND; |
9978 | DBUG_RETURN(HA_ERR_END_OF_FILE); |
9979 | } |
9980 | if (buf) { |
9981 | if (ignoring_no_key_columns) |
9982 | storage_store_fields_by_index(buf); |
9983 | else |
9984 | storage_store_fields(buf, record_id); |
9985 | if (cursor_geo && grn_source_column_geo) { |
9986 | int latitude, longitude; |
9987 | GRN_GEO_POINT_VALUE(&source_point, latitude, longitude); |
9988 | double latitude_in_degree = GRN_GEO_MSEC2DEGREE(latitude); |
9989 | double longitude_in_degree = GRN_GEO_MSEC2DEGREE(longitude); |
9990 | if (!((bottom_right_latitude_in_degree <= latitude_in_degree && |
9991 | latitude_in_degree <= top_left_latitude_in_degree) && |
9992 | (top_left_longitude_in_degree <= longitude_in_degree && |
9993 | longitude_in_degree <= bottom_right_longitude_in_degree))) { |
9994 | DBUG_PRINT("info" , |
9995 | ("mroonga: remove not contained geo point: " |
9996 | "<%g,%g>(<%d,%d>); key: <%g,%g>(<%d,%d>), <%g,%g>(<%d,%d>)" , |
9997 | latitude_in_degree, longitude_in_degree, |
9998 | latitude, longitude, |
9999 | top_left_latitude_in_degree, top_left_longitude_in_degree, |
10000 | GRN_GEO_DEGREE2MSEC(top_left_latitude_in_degree), |
10001 | GRN_GEO_DEGREE2MSEC(top_left_longitude_in_degree), |
10002 | bottom_right_latitude_in_degree, |
10003 | bottom_right_longitude_in_degree, |
10004 | GRN_GEO_DEGREE2MSEC(bottom_right_latitude_in_degree), |
10005 | GRN_GEO_DEGREE2MSEC(bottom_right_longitude_in_degree))); |
10006 | int error = storage_get_next_record(buf); |
10007 | DBUG_RETURN(error); |
10008 | } |
10009 | } |
10010 | } |
10011 | table->status = 0; |
10012 | DBUG_RETURN(0); |
10013 | } |
10014 | |
10015 | void ha_mroonga::geo_store_rectangle(const uchar *rectangle) |
10016 | { |
10017 | MRN_DBUG_ENTER_METHOD(); |
10018 | |
10019 | double locations[4]; |
10020 | for (int i = 0; i < 4; i++) { |
10021 | uchar reversed_value[8]; |
10022 | for (int j = 0; j < 8; j++) { |
10023 | reversed_value[j] = (rectangle + (8 * i))[7 - j]; |
10024 | } |
10025 | mi_float8get(locations[i], reversed_value); |
10026 | } |
10027 | top_left_longitude_in_degree = locations[0]; |
10028 | bottom_right_longitude_in_degree = locations[1]; |
10029 | bottom_right_latitude_in_degree = locations[2]; |
10030 | top_left_latitude_in_degree = locations[3]; |
10031 | int top_left_latitude = GRN_GEO_DEGREE2MSEC(top_left_latitude_in_degree); |
10032 | int top_left_longitude = GRN_GEO_DEGREE2MSEC(top_left_longitude_in_degree); |
10033 | int bottom_right_latitude = GRN_GEO_DEGREE2MSEC(bottom_right_latitude_in_degree); |
10034 | int bottom_right_longitude = GRN_GEO_DEGREE2MSEC(bottom_right_longitude_in_degree); |
10035 | GRN_GEO_POINT_SET(ctx, &top_left_point, |
10036 | top_left_latitude, top_left_longitude); |
10037 | GRN_GEO_POINT_SET(ctx, &bottom_right_point, |
10038 | bottom_right_latitude, bottom_right_longitude); |
10039 | |
10040 | DBUG_VOID_RETURN; |
10041 | } |
10042 | |
10043 | int ha_mroonga::generic_geo_open_cursor(const uchar *key, |
10044 | enum ha_rkey_function find_flag) |
10045 | { |
10046 | MRN_DBUG_ENTER_METHOD(); |
10047 | int error = 0; |
10048 | int flags = 0; |
10049 | if (find_flag & HA_READ_MBR_CONTAIN) { |
10050 | grn_obj *index = grn_index_columns[active_index]; |
10051 | geo_store_rectangle(key); |
10052 | cursor_geo = grn_geo_cursor_open_in_rectangle(ctx, |
10053 | index, |
10054 | &top_left_point, |
10055 | &bottom_right_point, |
10056 | 0, -1); |
10057 | if (cursor_geo) { |
10058 | if (grn_source_column_geo) { |
10059 | grn_obj_unlink(ctx, grn_source_column_geo); |
10060 | } |
10061 | grn_obj sources; |
10062 | GRN_OBJ_INIT(&sources, GRN_BULK, 0, GRN_ID_NIL); |
10063 | grn_obj_get_info(ctx, index, GRN_INFO_SOURCE, &sources); |
10064 | grn_source_column_geo = grn_ctx_at(ctx, GRN_RECORD_VALUE(&sources)); |
10065 | grn_obj_unlink(ctx, &sources); |
10066 | } |
10067 | } else { |
10068 | push_warning_unsupported_spatial_index_search(find_flag); |
10069 | cursor = grn_table_cursor_open(ctx, grn_table, NULL, 0, NULL, 0, |
10070 | 0, -1, flags); |
10071 | } |
10072 | if (ctx->rc) { |
10073 | error = ER_ERROR_ON_READ; |
10074 | my_message(error, ctx->errbuf, MYF(0)); |
10075 | } |
10076 | DBUG_RETURN(error); |
10077 | } |
10078 | |
10079 | bool ha_mroonga::is_dry_write() |
10080 | { |
10081 | MRN_DBUG_ENTER_METHOD(); |
10082 | bool dry_write_p = THDVAR(ha_thd(), dry_write); |
10083 | DBUG_RETURN(dry_write_p); |
10084 | } |
10085 | |
10086 | bool ha_mroonga::is_enable_optimization() |
10087 | { |
10088 | MRN_DBUG_ENTER_METHOD(); |
10089 | bool enable_optimization_p = THDVAR(ha_thd(), enable_optimization); |
10090 | DBUG_RETURN(enable_optimization_p); |
10091 | } |
10092 | |
10093 | bool ha_mroonga::should_normalize(Field *field) const |
10094 | { |
10095 | MRN_DBUG_ENTER_METHOD(); |
10096 | mrn::FieldNormalizer field_normalizer(ctx, ha_thd(), field); |
10097 | bool need_normalize_p = field_normalizer.should_normalize(); |
10098 | DBUG_RETURN(need_normalize_p); |
10099 | } |
10100 | |
10101 | void ha_mroonga::check_count_skip(key_part_map target_key_part_map) |
10102 | { |
10103 | MRN_DBUG_ENTER_METHOD(); |
10104 | |
10105 | if (!is_enable_optimization()) { |
10106 | GRN_LOG(ctx, GRN_LOG_DEBUG, |
10107 | "[mroonga][count-skip][false] optimization is disabled" ); |
10108 | count_skip = false; |
10109 | DBUG_VOID_RETURN; |
10110 | } |
10111 | |
10112 | if (thd_sql_command(ha_thd()) != SQLCOM_SELECT) { |
10113 | GRN_LOG(ctx, GRN_LOG_DEBUG, |
10114 | "[mroonga][count-skip][false] not SELECT" ); |
10115 | count_skip = false; |
10116 | DBUG_VOID_RETURN; |
10117 | } |
10118 | |
10119 | if (share->wrapper_mode && |
10120 | !(wrap_handler->ha_table_flags() & HA_NO_TRANSACTIONS)) { |
10121 | GRN_LOG(ctx, GRN_LOG_DEBUG, |
10122 | "[mroonga][count-skip][false] wrapped engine is transactional" ); |
10123 | count_skip = false; |
10124 | DBUG_VOID_RETURN; |
10125 | } |
10126 | |
10127 | st_select_lex *select_lex = table->pos_in_table_list->select_lex; |
10128 | KEY *key_info = NULL; |
10129 | if (active_index != MAX_KEY) { |
10130 | key_info = &(table->key_info[active_index]); |
10131 | } |
10132 | mrn::CountSkipChecker checker(ctx, |
10133 | table, |
10134 | select_lex, |
10135 | key_info, |
10136 | target_key_part_map, |
10137 | !share->wrapper_mode); |
10138 | if (checker.check()) { |
10139 | count_skip = true; |
10140 | mrn_count_skip++; |
10141 | DBUG_VOID_RETURN; |
10142 | } else { |
10143 | count_skip = false; |
10144 | DBUG_VOID_RETURN; |
10145 | } |
10146 | } |
10147 | |
10148 | bool ha_mroonga::is_grn_zero_column_value(grn_obj *column, grn_obj *value) |
10149 | { |
10150 | MRN_DBUG_ENTER_METHOD(); |
10151 | |
10152 | if (column->header.type != GRN_COLUMN_FIX_SIZE) { |
10153 | DBUG_RETURN(false); |
10154 | } |
10155 | |
10156 | char *bytes = GRN_BULK_HEAD(value); |
10157 | unsigned int size = GRN_BULK_VSIZE(value); |
10158 | for (unsigned int i = 0; i < size; ++i) { |
10159 | if (bytes[i] != '\0') { |
10160 | DBUG_RETURN(false); |
10161 | } |
10162 | } |
10163 | |
10164 | DBUG_RETURN(true); |
10165 | } |
10166 | |
10167 | bool ha_mroonga::is_primary_key_field(Field *field) const |
10168 | { |
10169 | MRN_DBUG_ENTER_METHOD(); |
10170 | |
10171 | if (table->s->primary_key == MAX_INDEXES) { |
10172 | DBUG_RETURN(false); |
10173 | } |
10174 | |
10175 | KEY *key_info = &(table->s->key_info[table->s->primary_key]); |
10176 | if (KEY_N_KEY_PARTS(key_info) != 1) { |
10177 | DBUG_RETURN(false); |
10178 | } |
10179 | |
10180 | if (strcmp(field->field_name.str, |
10181 | key_info->key_part[0].field->field_name.str) == 0) { |
10182 | DBUG_RETURN(true); |
10183 | } else { |
10184 | DBUG_RETURN(false); |
10185 | } |
10186 | } |
10187 | |
10188 | void ha_mroonga::check_fast_order_limit(grn_table_sort_key **sort_keys, |
10189 | int *n_sort_keys, |
10190 | longlong *limit) |
10191 | { |
10192 | MRN_DBUG_ENTER_METHOD(); |
10193 | |
10194 | if (!is_enable_optimization()) { |
10195 | DBUG_PRINT("info" , ("mroonga: fast order limit: optimization is disabled" )); |
10196 | fast_order_limit = false; |
10197 | DBUG_VOID_RETURN; |
10198 | } |
10199 | |
10200 | TABLE_LIST *table_list = table->pos_in_table_list; |
10201 | st_select_lex *select_lex = table_list->select_lex; |
10202 | SELECT_LEX_UNIT *unit = MRN_TABLE_LIST_GET_DERIVED(table_list); |
10203 | st_select_lex *first_select_lex; |
10204 | if (unit) |
10205 | { |
10206 | first_select_lex = unit->first_select(); |
10207 | } else { |
10208 | first_select_lex = select_lex; |
10209 | } |
10210 | DBUG_PRINT("info" , |
10211 | ("mroonga: first_select_lex->options=%llu" , |
10212 | first_select_lex ? MRN_SELECT_LEX_GET_ACTIVE_OPTIONS(first_select_lex) : 0)); |
10213 | |
10214 | if ( |
10215 | thd_sql_command(ha_thd()) == SQLCOM_SELECT && |
10216 | !select_lex->with_sum_func && |
10217 | !select_lex->group_list.elements && |
10218 | !MRN_SELECT_LEX_GET_HAVING_COND(select_lex) && |
10219 | select_lex->table_list.elements == 1 && |
10220 | select_lex->order_list.elements && |
10221 | select_lex->explicit_limit && |
10222 | select_lex->select_limit && |
10223 | select_lex->select_limit->val_int() > 0 |
10224 | ) { |
10225 | if (select_lex->offset_limit) { |
10226 | *limit = select_lex->offset_limit->val_int(); |
10227 | } else { |
10228 | *limit = 0; |
10229 | } |
10230 | *limit += select_lex->select_limit->val_int(); |
10231 | if (*limit > (longlong)INT_MAX) { |
10232 | DBUG_PRINT("info" , |
10233 | ("mroonga: fast_order_limit = false: " |
10234 | "too long limit: %lld <= %d is required" , |
10235 | *limit, INT_MAX)); |
10236 | fast_order_limit = false; |
10237 | DBUG_VOID_RETURN; |
10238 | } |
10239 | if (first_select_lex && |
10240 | (MRN_SELECT_LEX_GET_ACTIVE_OPTIONS(first_select_lex) & OPTION_FOUND_ROWS)) { |
10241 | DBUG_PRINT("info" , |
10242 | ("mroonga: fast_order_limit = false: " |
10243 | "SQL_CALC_FOUND_ROWS is specified" )); |
10244 | fast_order_limit = false; |
10245 | DBUG_VOID_RETURN; |
10246 | } |
10247 | bool is_storage_mode = !(share->wrapper_mode); |
10248 | Item *where = MRN_SELECT_LEX_GET_WHERE_COND(select_lex); |
10249 | const Item_func *match_against = NULL; |
10250 | if (where) { |
10251 | mrn::ConditionConverter converter(ctx, grn_table, is_storage_mode); |
10252 | if (!converter.is_convertable(where)) { |
10253 | DBUG_PRINT("info" , |
10254 | ("mroonga: fast_order_limit = false: " |
10255 | "not Groonga layer condition search" )); |
10256 | fast_order_limit = false; |
10257 | DBUG_VOID_RETURN; |
10258 | } |
10259 | unsigned int n_match_againsts = converter.count_match_against(where); |
10260 | if (n_match_againsts == 0) { |
10261 | DBUG_PRINT("info" , |
10262 | ("mroonga: fast_order_limit = false: " |
10263 | "Groonga layer condition but not fulltext search" )); |
10264 | fast_order_limit = false; |
10265 | DBUG_VOID_RETURN; |
10266 | } |
10267 | if (n_match_againsts > 1) { |
10268 | DBUG_PRINT("info" , |
10269 | ("mroonga: fast_order_limit = false: " |
10270 | "MATCH AGAINST must be only one" )); |
10271 | fast_order_limit = false; |
10272 | DBUG_VOID_RETURN; |
10273 | } |
10274 | } |
10275 | int n_max_sort_keys = select_lex->order_list.elements; |
10276 | *n_sort_keys = 0; |
10277 | size_t sort_keys_size = sizeof(grn_table_sort_key) * n_max_sort_keys; |
10278 | *sort_keys = (grn_table_sort_key *)mrn_my_malloc(sort_keys_size, |
10279 | MYF(MY_WME)); |
10280 | memset(*sort_keys, 0, sort_keys_size); |
10281 | ORDER *order; |
10282 | int i; |
10283 | mrn_change_encoding(ctx, system_charset_info); |
10284 | for (order = (ORDER *) select_lex->order_list.first, i = 0; |
10285 | order; |
10286 | order = order->next, i++) { |
10287 | Item *item = *order->item; |
10288 | if (item->type() == Item::FIELD_ITEM) |
10289 | { |
10290 | Field *field = static_cast<Item_field *>(item)->field; |
10291 | mrn::ColumnName column_name(field->field_name); |
10292 | |
10293 | if (should_normalize(field)) |
10294 | { |
10295 | DBUG_PRINT("info" , ("mroonga: fast_order_limit = false: " |
10296 | "sort by collated value isn't supported yet." )); |
10297 | fast_order_limit = false; |
10298 | my_free(*sort_keys); |
10299 | *sort_keys = NULL; |
10300 | *n_sort_keys = 0; |
10301 | DBUG_VOID_RETURN; |
10302 | } |
10303 | |
10304 | if (is_storage_mode) { |
10305 | (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys, |
10306 | column_name.c_str(), |
10307 | column_name.length()); |
10308 | } else { |
10309 | if (is_primary_key_field(field)) { |
10310 | (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys, |
10311 | MRN_COLUMN_NAME_KEY, |
10312 | strlen(MRN_COLUMN_NAME_KEY)); |
10313 | } else { |
10314 | DBUG_PRINT("info" , ("mroonga: fast_order_limit = false: " |
10315 | "sort by not primary key value " |
10316 | "isn't supported in wrapper mode." )); |
10317 | fast_order_limit = false; |
10318 | my_free(*sort_keys); |
10319 | *sort_keys = NULL; |
10320 | *n_sort_keys = 0; |
10321 | DBUG_VOID_RETURN; |
10322 | } |
10323 | } |
10324 | } else if (!match_against || match_against->eq(item, true)) { |
10325 | (*sort_keys)[i].key = grn_obj_column(ctx, matched_record_keys, |
10326 | MRN_COLUMN_NAME_SCORE, |
10327 | strlen(MRN_COLUMN_NAME_SCORE)); |
10328 | } else { |
10329 | DBUG_PRINT("info" , ("mroonga: fast_order_limit = false: " |
10330 | "sort by computed value isn't supported." )); |
10331 | fast_order_limit = false; |
10332 | my_free(*sort_keys); |
10333 | *sort_keys = NULL; |
10334 | *n_sort_keys = 0; |
10335 | DBUG_VOID_RETURN; |
10336 | } |
10337 | (*sort_keys)[i].offset = 0; |
10338 | if (MRN_ORDER_IS_ASC(order)) |
10339 | { |
10340 | (*sort_keys)[i].flags = GRN_TABLE_SORT_ASC; |
10341 | } else { |
10342 | (*sort_keys)[i].flags = GRN_TABLE_SORT_DESC; |
10343 | } |
10344 | (*n_sort_keys)++; |
10345 | } |
10346 | DBUG_PRINT("info" , ("mroonga: fast_order_limit = true" )); |
10347 | fast_order_limit = true; |
10348 | mrn_fast_order_limit++; |
10349 | DBUG_VOID_RETURN; |
10350 | } |
10351 | DBUG_PRINT("info" , ("mroonga: fast_order_limit = false" )); |
10352 | fast_order_limit = false; |
10353 | DBUG_VOID_RETURN; |
10354 | } |
10355 | |
10356 | int ha_mroonga::generic_store_bulk_fixed_size_string(Field *field, grn_obj *buf) |
10357 | { |
10358 | MRN_DBUG_ENTER_METHOD(); |
10359 | int error = 0; |
10360 | grn_obj_reinit(ctx, buf, GRN_DB_SHORT_TEXT, 0); |
10361 | GRN_TEXT_SET(ctx, buf, field->ptr, field->field_length); |
10362 | DBUG_RETURN(error); |
10363 | } |
10364 | |
10365 | int ha_mroonga::generic_store_bulk_variable_size_string(Field *field, |
10366 | grn_obj *buf) |
10367 | { |
10368 | MRN_DBUG_ENTER_METHOD(); |
10369 | int error = 0; |
10370 | String value; |
10371 | field->val_str(NULL, &value); |
10372 | grn_obj_reinit(ctx, buf, GRN_DB_SHORT_TEXT, 0); |
10373 | DBUG_PRINT("info" , ("mroonga: length=%" MRN_FORMAT_STRING_LENGTH, |
10374 | value.length())); |
10375 | DBUG_PRINT("info" , ("mroonga: value=%s" , value.c_ptr_safe())); |
10376 | GRN_TEXT_SET(ctx, buf, value.ptr(), value.length()); |
10377 | DBUG_RETURN(error); |
10378 | } |
10379 | |
10380 | int ha_mroonga::generic_store_bulk_integer(Field *field, grn_obj *buf) |
10381 | { |
10382 | MRN_DBUG_ENTER_METHOD(); |
10383 | int error = 0; |
10384 | long long value = field->val_int(); |
10385 | DBUG_PRINT("info" , ("mroonga: value=%lld" , value)); |
10386 | uint32 size = field->pack_length(); |
10387 | DBUG_PRINT("info" , ("mroonga: size=%u" , size)); |
10388 | Field_num *field_num = static_cast<Field_num *>(field); |
10389 | bool is_unsigned = field_num->unsigned_flag; |
10390 | DBUG_PRINT("info" , ("mroonga: is_unsigned=%s" , is_unsigned ? "true" : "false" )); |
10391 | switch (size) { |
10392 | case 1: |
10393 | if (is_unsigned) { |
10394 | grn_obj_reinit(ctx, buf, GRN_DB_UINT8, 0); |
10395 | GRN_UINT8_SET(ctx, buf, value); |
10396 | } else { |
10397 | grn_obj_reinit(ctx, buf, GRN_DB_INT8, 0); |
10398 | GRN_INT8_SET(ctx, buf, value); |
10399 | } |
10400 | break; |
10401 | case 2: |
10402 | if (is_unsigned) { |
10403 | grn_obj_reinit(ctx, buf, GRN_DB_UINT16, 0); |
10404 | GRN_UINT16_SET(ctx, buf, value); |
10405 | } else { |
10406 | grn_obj_reinit(ctx, buf, GRN_DB_INT16, 0); |
10407 | GRN_INT16_SET(ctx, buf, value); |
10408 | } |
10409 | break; |
10410 | case 3: |
10411 | case 4: |
10412 | if (is_unsigned) { |
10413 | grn_obj_reinit(ctx, buf, GRN_DB_UINT32, 0); |
10414 | GRN_UINT32_SET(ctx, buf, value); |
10415 | } else { |
10416 | grn_obj_reinit(ctx, buf, GRN_DB_INT32, 0); |
10417 | GRN_INT32_SET(ctx, buf, value); |
10418 | } |
10419 | break; |
10420 | case 8: |
10421 | if (is_unsigned) { |
10422 | grn_obj_reinit(ctx, buf, GRN_DB_UINT64, 0); |
10423 | GRN_UINT64_SET(ctx, buf, value); |
10424 | } else { |
10425 | grn_obj_reinit(ctx, buf, GRN_DB_INT64, 0); |
10426 | GRN_INT64_SET(ctx, buf, value); |
10427 | } |
10428 | break; |
10429 | default: |
10430 | // Why!? |
10431 | error = HA_ERR_UNSUPPORTED; |
10432 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
10433 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
10434 | "unknown integer value size: <%u>: " |
10435 | "available sizes: [1, 2, 3, 4, 8]" , |
10436 | size); |
10437 | push_warning(ha_thd(), MRN_SEVERITY_WARNING, |
10438 | error, error_message); |
10439 | break; |
10440 | } |
10441 | DBUG_RETURN(error); |
10442 | } |
10443 | |
10444 | int ha_mroonga::generic_store_bulk_unsigned_integer(Field *field, grn_obj *buf) |
10445 | { |
10446 | MRN_DBUG_ENTER_METHOD(); |
10447 | int error = 0; |
10448 | long long signed_value = field->val_int(); |
10449 | unsigned long long unsigned_value = *((unsigned long long *)(&signed_value)); |
10450 | uint32 size = field->pack_length(); |
10451 | switch (size) { |
10452 | case 1: |
10453 | grn_obj_reinit(ctx, buf, GRN_DB_UINT8, 0); |
10454 | GRN_UINT8_SET(ctx, buf, unsigned_value); |
10455 | break; |
10456 | case 2: |
10457 | grn_obj_reinit(ctx, buf, GRN_DB_UINT16, 0); |
10458 | GRN_UINT16_SET(ctx, buf, unsigned_value); |
10459 | break; |
10460 | case 3: |
10461 | case 4: |
10462 | grn_obj_reinit(ctx, buf, GRN_DB_UINT32, 0); |
10463 | GRN_UINT32_SET(ctx, buf, unsigned_value); |
10464 | break; |
10465 | case 8: |
10466 | grn_obj_reinit(ctx, buf, GRN_DB_UINT64, 0); |
10467 | GRN_UINT64_SET(ctx, buf, unsigned_value); |
10468 | break; |
10469 | default: |
10470 | // Why!? |
10471 | error = HA_ERR_UNSUPPORTED; |
10472 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
10473 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
10474 | "unknown unsigned integer value size: <%u>: " |
10475 | "available sizes: [1, 2, 3, 4, 8]" , |
10476 | size); |
10477 | push_warning(ha_thd(), MRN_SEVERITY_WARNING, |
10478 | error, error_message); |
10479 | break; |
10480 | } |
10481 | DBUG_RETURN(error); |
10482 | } |
10483 | |
10484 | int ha_mroonga::generic_store_bulk_float(Field *field, grn_obj *buf) |
10485 | { |
10486 | MRN_DBUG_ENTER_METHOD(); |
10487 | int error = 0; |
10488 | double value = field->val_real(); |
10489 | uint32 size = field->pack_length(); |
10490 | switch (size) { |
10491 | case 4: |
10492 | case 8: |
10493 | grn_obj_reinit(ctx, buf, GRN_DB_FLOAT, 0); |
10494 | GRN_FLOAT_SET(ctx, buf, value); |
10495 | break; |
10496 | default: |
10497 | // Why!? |
10498 | error = HA_ERR_UNSUPPORTED; |
10499 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
10500 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
10501 | "unknown float value size: <%u>: " |
10502 | "available sizes: [4, 8]" , |
10503 | size); |
10504 | push_warning(ha_thd(), MRN_SEVERITY_WARNING, |
10505 | error, error_message); |
10506 | break; |
10507 | } |
10508 | DBUG_RETURN(error); |
10509 | } |
10510 | |
10511 | long long int ha_mroonga::get_grn_time_from_timestamp_field(Field_timestamp *field) |
10512 | { |
10513 | MRN_DBUG_ENTER_METHOD(); |
10514 | long long int grn_time = 0; |
10515 | #ifdef MRN_TIMESTAMP_USE_TIMEVAL |
10516 | int warnings = 0; |
10517 | struct timeval time_value; |
10518 | if (field->get_timestamp(&time_value, &warnings)) { |
10519 | // XXX: Should we report warnings or MySQL does? |
10520 | } else { |
10521 | DBUG_PRINT("info" , ("mroonga: timeval tv_sec=%ld" , time_value.tv_sec)); |
10522 | grn_time = GRN_TIME_PACK(time_value.tv_sec, time_value.tv_usec); |
10523 | } |
10524 | #elif defined(MRN_TIMESTAMP_USE_MY_TIME_T) |
10525 | unsigned long int micro_seconds; |
10526 | my_time_t seconds = field->get_timestamp(µ_seconds); |
10527 | DBUG_PRINT("info" , ("mroonga: my_time_t seconds=%ld" , seconds)); |
10528 | grn_time = GRN_TIME_PACK(seconds, micro_seconds); |
10529 | #else |
10530 | my_bool is_null_value; |
10531 | long seconds = field->get_timestamp(&is_null_value); |
10532 | DBUG_PRINT("info" , ("mroonga: long seconds=%ld" , seconds)); |
10533 | grn_time = GRN_TIME_PACK(seconds, 0); |
10534 | #endif |
10535 | DBUG_RETURN(grn_time); |
10536 | } |
10537 | |
10538 | int ha_mroonga::generic_store_bulk_timestamp(Field *field, grn_obj *buf) |
10539 | { |
10540 | MRN_DBUG_ENTER_METHOD(); |
10541 | int error = 0; |
10542 | Field_timestamp *timestamp_field = (Field_timestamp *)field; |
10543 | long long int time = get_grn_time_from_timestamp_field(timestamp_field); |
10544 | grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); |
10545 | GRN_TIME_SET(ctx, buf, time); |
10546 | DBUG_RETURN(error); |
10547 | } |
10548 | |
10549 | int ha_mroonga::generic_store_bulk_date(Field *field, grn_obj *buf) |
10550 | { |
10551 | MRN_DBUG_ENTER_METHOD(); |
10552 | int error = 0; |
10553 | bool truncated = false; |
10554 | long long int date_value = field->val_int(); |
10555 | struct tm date; |
10556 | memset(&date, 0, sizeof(struct tm)); |
10557 | date.tm_year = date_value / 10000 % 10000 - mrn::TimeConverter::TM_YEAR_BASE; |
10558 | date.tm_mon = date_value / 100 % 100 - 1; |
10559 | date.tm_mday = date_value % 100; |
10560 | int usec = 0; |
10561 | mrn::TimeConverter time_converter; |
10562 | long long int time = time_converter.tm_to_grn_time(&date, usec, &truncated); |
10563 | if (truncated) { |
10564 | field->set_warning(MRN_SEVERITY_WARNING, |
10565 | WARN_DATA_TRUNCATED, 1); |
10566 | } |
10567 | grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); |
10568 | GRN_TIME_SET(ctx, buf, time); |
10569 | DBUG_RETURN(error); |
10570 | } |
10571 | |
10572 | int ha_mroonga::generic_store_bulk_time(Field *field, grn_obj *buf) |
10573 | { |
10574 | MRN_DBUG_ENTER_METHOD(); |
10575 | int error = 0; |
10576 | bool truncated = false; |
10577 | Field_time *time_field = (Field_time *)field; |
10578 | MYSQL_TIME mysql_time; |
10579 | time_field->get_time(&mysql_time); |
10580 | mrn::TimeConverter time_converter; |
10581 | long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, |
10582 | &truncated); |
10583 | if (truncated) { |
10584 | field->set_warning(MRN_SEVERITY_WARNING, |
10585 | WARN_DATA_TRUNCATED, 1); |
10586 | } |
10587 | grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); |
10588 | GRN_TIME_SET(ctx, buf, time); |
10589 | DBUG_RETURN(error); |
10590 | } |
10591 | |
10592 | int ha_mroonga::generic_store_bulk_datetime(Field *field, grn_obj *buf) |
10593 | { |
10594 | MRN_DBUG_ENTER_METHOD(); |
10595 | int error = 0; |
10596 | bool truncated = false; |
10597 | Field_datetime *datetime_field = (Field_datetime *)field; |
10598 | MYSQL_TIME mysql_time; |
10599 | datetime_field->get_time(&mysql_time); |
10600 | mrn::TimeConverter time_converter; |
10601 | long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, |
10602 | &truncated); |
10603 | if (truncated) { |
10604 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
10605 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
10606 | } |
10607 | field->set_warning(MRN_SEVERITY_WARNING, |
10608 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
10609 | 1); |
10610 | } |
10611 | grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); |
10612 | GRN_TIME_SET(ctx, buf, time); |
10613 | DBUG_RETURN(error); |
10614 | } |
10615 | |
10616 | int ha_mroonga::generic_store_bulk_year(Field *field, grn_obj *buf) |
10617 | { |
10618 | MRN_DBUG_ENTER_METHOD(); |
10619 | int error = 0; |
10620 | bool truncated = false; |
10621 | |
10622 | int year; |
10623 | if (field->field_length == 2) { |
10624 | year = static_cast<int>(field->val_int() + 2000); |
10625 | } else { |
10626 | year = static_cast<int>(field->val_int()); |
10627 | } |
10628 | |
10629 | DBUG_PRINT("info" , ("mroonga: year=%d" , year)); |
10630 | struct tm date; |
10631 | memset(&date, 0, sizeof(struct tm)); |
10632 | date.tm_year = year - mrn::TimeConverter::TM_YEAR_BASE; |
10633 | date.tm_mon = 0; |
10634 | date.tm_mday = 1; |
10635 | |
10636 | int usec = 0; |
10637 | mrn::TimeConverter time_converter; |
10638 | long long int time = time_converter.tm_to_grn_time(&date, usec, &truncated); |
10639 | if (truncated) { |
10640 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
10641 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
10642 | } |
10643 | field->set_warning(MRN_SEVERITY_WARNING, |
10644 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
10645 | 1); |
10646 | } |
10647 | grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); |
10648 | GRN_TIME_SET(ctx, buf, time); |
10649 | DBUG_RETURN(error); |
10650 | } |
10651 | |
10652 | #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 |
10653 | int ha_mroonga::generic_store_bulk_datetime2(Field *field, grn_obj *buf) |
10654 | { |
10655 | MRN_DBUG_ENTER_METHOD(); |
10656 | int error = 0; |
10657 | bool truncated = false; |
10658 | Field_datetimef *datetimef_field = (Field_datetimef *)field; |
10659 | MYSQL_TIME mysql_time; |
10660 | datetimef_field->get_time(&mysql_time); |
10661 | mrn::TimeConverter time_converter; |
10662 | long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, |
10663 | &truncated); |
10664 | if (truncated) { |
10665 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
10666 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
10667 | } |
10668 | field->set_warning(MRN_SEVERITY_WARNING, |
10669 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
10670 | 1); |
10671 | } |
10672 | grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); |
10673 | GRN_TIME_SET(ctx, buf, time); |
10674 | DBUG_RETURN(error); |
10675 | } |
10676 | #endif |
10677 | |
10678 | #ifdef MRN_HAVE_MYSQL_TYPE_TIME2 |
10679 | int ha_mroonga::generic_store_bulk_time2(Field *field, grn_obj *buf) |
10680 | { |
10681 | MRN_DBUG_ENTER_METHOD(); |
10682 | int error = 0; |
10683 | bool truncated = false; |
10684 | MYSQL_TIME mysql_time; |
10685 | field->get_time(&mysql_time); |
10686 | mrn::TimeConverter time_converter; |
10687 | long long int time = time_converter.mysql_time_to_grn_time(&mysql_time, |
10688 | &truncated); |
10689 | if (truncated) { |
10690 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
10691 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
10692 | } |
10693 | field->set_warning(MRN_SEVERITY_WARNING, |
10694 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
10695 | 1); |
10696 | } |
10697 | grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); |
10698 | GRN_TIME_SET(ctx, buf, time); |
10699 | DBUG_RETURN(error); |
10700 | } |
10701 | #endif |
10702 | |
10703 | int ha_mroonga::generic_store_bulk_new_date(Field *field, grn_obj *buf) |
10704 | { |
10705 | MRN_DBUG_ENTER_METHOD(); |
10706 | int error = 0; |
10707 | bool truncated = false; |
10708 | Field_newdate *newdate_field = (Field_newdate *)field; |
10709 | MYSQL_TIME mysql_date; |
10710 | newdate_field->get_time(&mysql_date); |
10711 | mrn::TimeConverter time_converter; |
10712 | long long int time = time_converter.mysql_time_to_grn_time(&mysql_date, |
10713 | &truncated); |
10714 | if (truncated) { |
10715 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
10716 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
10717 | } |
10718 | field->set_warning(MRN_SEVERITY_WARNING, |
10719 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
10720 | 1); |
10721 | } |
10722 | grn_obj_reinit(ctx, buf, GRN_DB_TIME, 0); |
10723 | GRN_TIME_SET(ctx, buf, time); |
10724 | DBUG_RETURN(error); |
10725 | } |
10726 | |
10727 | int ha_mroonga::generic_store_bulk_new_decimal(Field *field, grn_obj *buf) |
10728 | { |
10729 | MRN_DBUG_ENTER_METHOD(); |
10730 | int error = 0; |
10731 | String value; |
10732 | Field_new_decimal *new_decimal_field = (Field_new_decimal *)field; |
10733 | new_decimal_field->val_str(&value, NULL); |
10734 | grn_obj_reinit(ctx, buf, GRN_DB_SHORT_TEXT, 0); |
10735 | GRN_TEXT_SET(ctx, buf, value.ptr(), value.length()); |
10736 | DBUG_RETURN(error); |
10737 | } |
10738 | |
10739 | int ha_mroonga::generic_store_bulk_blob(Field *field, grn_obj *buf) |
10740 | { |
10741 | MRN_DBUG_ENTER_METHOD(); |
10742 | int error = 0; |
10743 | String buffer; |
10744 | Field_blob *blob = (Field_blob *)field; |
10745 | String *value = blob->val_str(0, &buffer); |
10746 | grn_obj_reinit(ctx, buf, GRN_DB_TEXT, 0); |
10747 | GRN_TEXT_SET(ctx, buf, value->ptr(), value->length()); |
10748 | DBUG_RETURN(error); |
10749 | } |
10750 | |
10751 | int ha_mroonga::generic_store_bulk_geometry(Field *field, grn_obj *buf) |
10752 | { |
10753 | MRN_DBUG_ENTER_METHOD(); |
10754 | int error = 0; |
10755 | #ifdef MRN_HAVE_SPATIAL |
10756 | String buffer; |
10757 | Field_geom *geometry = (Field_geom *)field; |
10758 | String *value = geometry->val_str(0, &buffer); |
10759 | const char *wkb = value->ptr(); |
10760 | int len = value->length(); |
10761 | error = mrn_set_geometry(ctx, buf, wkb, len); |
10762 | #endif |
10763 | DBUG_RETURN(error); |
10764 | } |
10765 | |
10766 | #ifdef MRN_HAVE_MYSQL_TYPE_JSON |
10767 | int ha_mroonga::generic_store_bulk_json(Field *field, grn_obj *buf) |
10768 | { |
10769 | MRN_DBUG_ENTER_METHOD(); |
10770 | int error = 0; |
10771 | String buffer; |
10772 | Field_json *json = static_cast<Field_json *>(field); |
10773 | String *value = json->val_str(&buffer, NULL); |
10774 | grn_obj_reinit(ctx, buf, GRN_DB_TEXT, 0); |
10775 | GRN_TEXT_SET(ctx, buf, value->ptr(), value->length()); |
10776 | DBUG_RETURN(error); |
10777 | } |
10778 | #endif |
10779 | |
10780 | int ha_mroonga::generic_store_bulk(Field *field, grn_obj *buf) |
10781 | { |
10782 | MRN_DBUG_ENTER_METHOD(); |
10783 | int error; |
10784 | error = mrn_change_encoding(ctx, field->charset()); |
10785 | if (error) |
10786 | return error; |
10787 | switch (field->real_type()) { |
10788 | case MYSQL_TYPE_DECIMAL: |
10789 | error = generic_store_bulk_variable_size_string(field, buf); |
10790 | break; |
10791 | case MYSQL_TYPE_TINY: |
10792 | case MYSQL_TYPE_SHORT: |
10793 | case MYSQL_TYPE_LONG: |
10794 | error = generic_store_bulk_integer(field, buf); |
10795 | break; |
10796 | case MYSQL_TYPE_FLOAT: |
10797 | case MYSQL_TYPE_DOUBLE: |
10798 | error = generic_store_bulk_float(field, buf); |
10799 | break; |
10800 | case MYSQL_TYPE_NULL: |
10801 | error = generic_store_bulk_unsigned_integer(field, buf); |
10802 | break; |
10803 | case MYSQL_TYPE_TIMESTAMP: |
10804 | error = generic_store_bulk_timestamp(field, buf); |
10805 | break; |
10806 | case MYSQL_TYPE_LONGLONG: |
10807 | case MYSQL_TYPE_INT24: |
10808 | error = generic_store_bulk_integer(field, buf); |
10809 | break; |
10810 | case MYSQL_TYPE_DATE: |
10811 | error = generic_store_bulk_date(field, buf); |
10812 | break; |
10813 | case MYSQL_TYPE_TIME: |
10814 | error = generic_store_bulk_time(field, buf); |
10815 | break; |
10816 | case MYSQL_TYPE_DATETIME: |
10817 | error = generic_store_bulk_datetime(field, buf); |
10818 | break; |
10819 | case MYSQL_TYPE_YEAR: |
10820 | error = generic_store_bulk_year(field, buf); |
10821 | break; |
10822 | case MYSQL_TYPE_NEWDATE: |
10823 | error = generic_store_bulk_new_date(field, buf); |
10824 | break; |
10825 | case MYSQL_TYPE_VARCHAR: |
10826 | error = generic_store_bulk_variable_size_string(field, buf); |
10827 | break; |
10828 | case MYSQL_TYPE_BIT: |
10829 | error = generic_store_bulk_unsigned_integer(field, buf); |
10830 | break; |
10831 | #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2 |
10832 | case MYSQL_TYPE_TIMESTAMP2: |
10833 | error = generic_store_bulk_timestamp(field, buf); |
10834 | break; |
10835 | #endif |
10836 | #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 |
10837 | case MYSQL_TYPE_DATETIME2: |
10838 | error = generic_store_bulk_datetime2(field, buf); |
10839 | break; |
10840 | #endif |
10841 | #ifdef MRN_HAVE_MYSQL_TYPE_TIME2 |
10842 | case MYSQL_TYPE_TIME2: |
10843 | error = generic_store_bulk_time2(field, buf); |
10844 | break; |
10845 | #endif |
10846 | case MYSQL_TYPE_NEWDECIMAL: |
10847 | error = generic_store_bulk_new_decimal(field, buf); |
10848 | break; |
10849 | case MYSQL_TYPE_ENUM: |
10850 | error = generic_store_bulk_unsigned_integer(field, buf); |
10851 | break; |
10852 | case MYSQL_TYPE_SET: |
10853 | error = generic_store_bulk_unsigned_integer(field, buf); |
10854 | break; |
10855 | case MYSQL_TYPE_TINY_BLOB: |
10856 | case MYSQL_TYPE_MEDIUM_BLOB: |
10857 | case MYSQL_TYPE_LONG_BLOB: |
10858 | case MYSQL_TYPE_BLOB: |
10859 | error = generic_store_bulk_blob(field, buf); |
10860 | break; |
10861 | case MYSQL_TYPE_VAR_STRING: |
10862 | error = generic_store_bulk_variable_size_string(field, buf); |
10863 | break; |
10864 | case MYSQL_TYPE_STRING: |
10865 | error = generic_store_bulk_fixed_size_string(field, buf); |
10866 | break; |
10867 | case MYSQL_TYPE_GEOMETRY: |
10868 | error = generic_store_bulk_geometry(field, buf); |
10869 | break; |
10870 | #ifdef MRN_HAVE_MYSQL_TYPE_JSON |
10871 | case MYSQL_TYPE_JSON: |
10872 | error = generic_store_bulk_json(field, buf); |
10873 | break; |
10874 | #endif |
10875 | default: |
10876 | error = HA_ERR_UNSUPPORTED; |
10877 | break; |
10878 | } |
10879 | DBUG_RETURN(error); |
10880 | } |
10881 | |
10882 | void ha_mroonga::storage_store_field_string(Field *field, |
10883 | const char *value, |
10884 | uint value_length) |
10885 | { |
10886 | MRN_DBUG_ENTER_METHOD(); |
10887 | field->store(value, value_length, field->charset()); |
10888 | DBUG_VOID_RETURN; |
10889 | } |
10890 | |
10891 | void ha_mroonga::storage_store_field_integer(Field *field, |
10892 | const char *value, |
10893 | uint value_length) |
10894 | { |
10895 | MRN_DBUG_ENTER_METHOD(); |
10896 | Field_num *field_num = static_cast<Field_num *>(field); |
10897 | bool is_unsigned = field_num->unsigned_flag; |
10898 | switch (value_length) { |
10899 | case 1: |
10900 | { |
10901 | if (is_unsigned) { |
10902 | unsigned char field_value; |
10903 | field_value = *((unsigned char *)value); |
10904 | field->store(field_value, is_unsigned); |
10905 | } else { |
10906 | signed char field_value; |
10907 | field_value = *((signed char *)value); |
10908 | field->store(field_value, is_unsigned); |
10909 | } |
10910 | break; |
10911 | } |
10912 | case 2: |
10913 | { |
10914 | if (is_unsigned) { |
10915 | unsigned short field_value; |
10916 | field_value = *((unsigned short *)value); |
10917 | field->store(field_value, is_unsigned); |
10918 | } else { |
10919 | short field_value; |
10920 | field_value = *((short *)value); |
10921 | field->store(field_value, is_unsigned); |
10922 | } |
10923 | break; |
10924 | } |
10925 | case 4: |
10926 | { |
10927 | if (is_unsigned) { |
10928 | unsigned int field_value; |
10929 | field_value = *((unsigned int *)value); |
10930 | field->store(field_value, is_unsigned); |
10931 | } else { |
10932 | int field_value; |
10933 | field_value = *((int *)value); |
10934 | field->store(field_value, is_unsigned); |
10935 | } |
10936 | break; |
10937 | } |
10938 | case 8: |
10939 | { |
10940 | if (is_unsigned) { |
10941 | unsigned long long int field_value; |
10942 | field_value = *((unsigned long long int *)value); |
10943 | DBUG_PRINT("info" , ("mroonga: field_value=%llu" , field_value)); |
10944 | field->store(field_value, is_unsigned); |
10945 | } else { |
10946 | long long int field_value; |
10947 | field_value = *((long long int *)value); |
10948 | field->store(field_value, is_unsigned); |
10949 | } |
10950 | break; |
10951 | } |
10952 | default: |
10953 | { |
10954 | // Why!? |
10955 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
10956 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
10957 | "unknown integer value size: <%d>: " |
10958 | "available sizes: [1, 2, 4, 8]" , |
10959 | value_length); |
10960 | push_warning(ha_thd(), MRN_SEVERITY_WARNING, |
10961 | HA_ERR_UNSUPPORTED, error_message); |
10962 | storage_store_field_string(field, value, value_length); |
10963 | break; |
10964 | } |
10965 | } |
10966 | DBUG_VOID_RETURN; |
10967 | } |
10968 | |
10969 | void ha_mroonga::storage_store_field_unsigned_integer(Field *field, |
10970 | const char *value, |
10971 | uint value_length) |
10972 | { |
10973 | MRN_DBUG_ENTER_METHOD(); |
10974 | switch (value_length) { |
10975 | case 1: |
10976 | { |
10977 | unsigned char field_value; |
10978 | field_value = *((unsigned char *)value); |
10979 | field->store(field_value, true); |
10980 | break; |
10981 | } |
10982 | case 2: |
10983 | { |
10984 | unsigned short field_value; |
10985 | field_value = *((unsigned short *)value); |
10986 | field->store(field_value, true); |
10987 | break; |
10988 | } |
10989 | case 4: |
10990 | { |
10991 | unsigned int field_value; |
10992 | field_value = *((unsigned int *)value); |
10993 | field->store(field_value, true); |
10994 | break; |
10995 | } |
10996 | case 8: |
10997 | { |
10998 | unsigned long long int field_value; |
10999 | field_value = *((unsigned long long int *)value); |
11000 | DBUG_PRINT("info" , ("mroonga: field_value=%llu" , field_value)); |
11001 | field->store(field_value, true); |
11002 | break; |
11003 | } |
11004 | default: |
11005 | { |
11006 | // Why!? |
11007 | char error_message[MRN_MESSAGE_BUFFER_SIZE]; |
11008 | snprintf(error_message, MRN_MESSAGE_BUFFER_SIZE, |
11009 | "unknown integer value size: <%d>: " |
11010 | "available sizes: [1, 2, 4, 8]" , |
11011 | value_length); |
11012 | push_warning(ha_thd(), MRN_SEVERITY_WARNING, |
11013 | HA_ERR_UNSUPPORTED, error_message); |
11014 | storage_store_field_string(field, value, value_length); |
11015 | break; |
11016 | } |
11017 | } |
11018 | DBUG_VOID_RETURN; |
11019 | } |
11020 | |
11021 | void ha_mroonga::storage_store_field_float(Field *field, |
11022 | const char *value, |
11023 | uint value_length) |
11024 | { |
11025 | MRN_DBUG_ENTER_METHOD(); |
11026 | double field_value; |
11027 | field_value = *((double *)value); |
11028 | field->store(field_value); |
11029 | DBUG_VOID_RETURN; |
11030 | } |
11031 | |
11032 | void ha_mroonga::storage_store_field_timestamp(Field *field, |
11033 | const char *value, |
11034 | uint value_length) |
11035 | { |
11036 | MRN_DBUG_ENTER_METHOD(); |
11037 | long long int time = *((long long int *)value); |
11038 | Field_timestamp *timestamp_field = (Field_timestamp *)field; |
11039 | #ifdef MRN_TIMESTAMP_USE_TIMEVAL |
11040 | struct timeval time_value; |
11041 | GRN_TIME_UNPACK(time, time_value.tv_sec, time_value.tv_usec); |
11042 | timestamp_field->store_timestamp(&time_value); |
11043 | #elif defined(MRN_TIMESTAMP_USE_MY_TIME_T) |
11044 | long long int sec, usec; |
11045 | GRN_TIME_UNPACK(time, sec, usec); |
11046 | timestamp_field->store_TIME(static_cast<int32>(sec), |
11047 | static_cast<int32>(usec)); |
11048 | #else |
11049 | int32 sec, usec __attribute__((unused)); |
11050 | GRN_TIME_UNPACK(time, sec, usec); |
11051 | timestamp_field->store_timestamp(sec); |
11052 | #endif |
11053 | DBUG_VOID_RETURN; |
11054 | } |
11055 | |
11056 | void ha_mroonga::storage_store_field_date(Field *field, |
11057 | const char *value, |
11058 | uint value_length) |
11059 | { |
11060 | MRN_DBUG_ENTER_METHOD(); |
11061 | long long int time = *((long long int *)value); |
11062 | long long int sec, usec __attribute__((unused)); |
11063 | GRN_TIME_UNPACK(time, sec, usec); |
11064 | struct tm date; |
11065 | time_t sec_t = static_cast<int32>(sec); |
11066 | gmtime_r(&sec_t, &date); |
11067 | long long int date_in_mysql = |
11068 | (date.tm_year + mrn::TimeConverter::TM_YEAR_BASE) * 10000 + |
11069 | (date.tm_mon + 1) * 100 + |
11070 | date.tm_mday; |
11071 | field->store(date_in_mysql, false); |
11072 | DBUG_VOID_RETURN; |
11073 | } |
11074 | |
11075 | void ha_mroonga::storage_store_field_time(Field *field, |
11076 | const char *value, |
11077 | uint value_length) |
11078 | { |
11079 | MRN_DBUG_ENTER_METHOD(); |
11080 | long long int time = *((long long int *)value); |
11081 | MYSQL_TIME mysql_time; |
11082 | memset(&mysql_time, 0, sizeof(MYSQL_TIME)); |
11083 | mysql_time.time_type = MYSQL_TIMESTAMP_TIME; |
11084 | mrn::TimeConverter time_converter; |
11085 | time_converter.grn_time_to_mysql_time(time, &mysql_time); |
11086 | #ifdef MRN_FIELD_STORE_TIME_NEED_TYPE |
11087 | Field_time *time_field = (Field_time *)field; |
11088 | time_field->store_time(&mysql_time, mysql_time.time_type); |
11089 | #else |
11090 | field->store_time(&mysql_time); |
11091 | #endif |
11092 | DBUG_VOID_RETURN; |
11093 | } |
11094 | |
11095 | void ha_mroonga::storage_store_field_datetime(Field *field, |
11096 | const char *value, |
11097 | uint value_length) |
11098 | { |
11099 | MRN_DBUG_ENTER_METHOD(); |
11100 | long long int time = *((long long int *)value); |
11101 | MYSQL_TIME mysql_datetime; |
11102 | memset(&mysql_datetime, 0, sizeof(MYSQL_TIME)); |
11103 | mysql_datetime.time_type = MYSQL_TIMESTAMP_DATETIME; |
11104 | mrn::TimeConverter time_converter; |
11105 | time_converter.grn_time_to_mysql_time(time, &mysql_datetime); |
11106 | #ifdef MRN_FIELD_STORE_TIME_NEED_TYPE |
11107 | Field_datetime *datetime_field = (Field_datetime *)field; |
11108 | datetime_field->store_time(&mysql_datetime, mysql_datetime.time_type); |
11109 | #else |
11110 | field->store_time(&mysql_datetime); |
11111 | #endif |
11112 | DBUG_VOID_RETURN; |
11113 | } |
11114 | |
11115 | void ha_mroonga::storage_store_field_year(Field *field, |
11116 | const char *value, |
11117 | uint value_length) |
11118 | { |
11119 | MRN_DBUG_ENTER_METHOD(); |
11120 | long long int time = *((long long int *)value); |
11121 | MYSQL_TIME mysql_time; |
11122 | memset(&mysql_time, 0, sizeof(MYSQL_TIME)); |
11123 | mysql_time.time_type = MYSQL_TIMESTAMP_DATE; |
11124 | mrn::TimeConverter time_converter; |
11125 | time_converter.grn_time_to_mysql_time(time, &mysql_time); |
11126 | DBUG_PRINT("info" , ("mroonga: stored %d" , mysql_time.year)); |
11127 | field->store(mysql_time.year, false); |
11128 | DBUG_VOID_RETURN; |
11129 | } |
11130 | |
11131 | void ha_mroonga::storage_store_field_new_date(Field *field, |
11132 | const char *value, |
11133 | uint value_length) |
11134 | { |
11135 | MRN_DBUG_ENTER_METHOD(); |
11136 | long long int time = *((long long int *)value); |
11137 | MYSQL_TIME mysql_date; |
11138 | memset(&mysql_date, 0, sizeof(MYSQL_TIME)); |
11139 | mysql_date.time_type = MYSQL_TIMESTAMP_DATE; |
11140 | mrn::TimeConverter time_converter; |
11141 | time_converter.grn_time_to_mysql_time(time, &mysql_date); |
11142 | #ifdef MRN_FIELD_STORE_TIME_NEED_TYPE |
11143 | Field_newdate *newdate_field = (Field_newdate *)field; |
11144 | newdate_field->store_time(&mysql_date, MYSQL_TIMESTAMP_DATE); |
11145 | #else |
11146 | field->store_time(&mysql_date); |
11147 | #endif |
11148 | DBUG_VOID_RETURN; |
11149 | } |
11150 | |
11151 | #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 |
11152 | void ha_mroonga::storage_store_field_datetime2(Field *field, |
11153 | const char *value, |
11154 | uint value_length) |
11155 | { |
11156 | MRN_DBUG_ENTER_METHOD(); |
11157 | long long int time = *((long long int *)value); |
11158 | MYSQL_TIME mysql_datetime; |
11159 | memset(&mysql_datetime, 0, sizeof(MYSQL_TIME)); |
11160 | mysql_datetime.time_type = MYSQL_TIMESTAMP_DATETIME; |
11161 | mrn::TimeConverter time_converter; |
11162 | time_converter.grn_time_to_mysql_time(time, &mysql_datetime); |
11163 | field->store_time(&mysql_datetime); |
11164 | DBUG_VOID_RETURN; |
11165 | } |
11166 | #endif |
11167 | |
11168 | #ifdef MRN_HAVE_MYSQL_TYPE_TIME2 |
11169 | void ha_mroonga::storage_store_field_time2(Field *field, |
11170 | const char *value, |
11171 | uint value_length) |
11172 | { |
11173 | MRN_DBUG_ENTER_METHOD(); |
11174 | long long int time = *((long long int *)value); |
11175 | |
11176 | MYSQL_TIME mysql_time; |
11177 | memset(&mysql_time, 0, sizeof(MYSQL_TIME)); |
11178 | mysql_time.time_type = MYSQL_TIMESTAMP_TIME; |
11179 | mrn::TimeConverter time_converter; |
11180 | time_converter.grn_time_to_mysql_time(time, &mysql_time); |
11181 | field->store_time(&mysql_time); |
11182 | DBUG_VOID_RETURN; |
11183 | } |
11184 | #endif |
11185 | |
11186 | void ha_mroonga::storage_store_field_blob(Field *field, |
11187 | const char *value, |
11188 | uint value_length) |
11189 | { |
11190 | MRN_DBUG_ENTER_METHOD(); |
11191 | Field_blob *blob = (Field_blob *)field; |
11192 | String *blob_buffer = &blob_buffers[field->field_index]; |
11193 | blob_buffer->length(0); |
11194 | blob_buffer->reserve(value_length); |
11195 | blob_buffer->q_append(value, value_length); |
11196 | blob->set_ptr((uint32) value_length, (uchar *) blob_buffer->ptr()); |
11197 | DBUG_VOID_RETURN; |
11198 | } |
11199 | |
11200 | void ha_mroonga::storage_store_field_geometry(Field *field, |
11201 | const char *value, |
11202 | uint value_length) |
11203 | { |
11204 | MRN_DBUG_ENTER_METHOD(); |
11205 | #ifdef MRN_HAVE_SPATIAL |
11206 | uchar wkb[SRID_SIZE + WKB_HEADER_SIZE + POINT_DATA_SIZE]; |
11207 | grn_geo_point *field_value = (grn_geo_point *)value; |
11208 | int latitude, longitude; |
11209 | latitude = field_value->latitude; |
11210 | longitude = field_value->longitude; |
11211 | if (grn_source_column_geo) { |
11212 | GRN_GEO_POINT_SET(ctx, &source_point, latitude, longitude); |
11213 | } |
11214 | memset(wkb, 0, SRID_SIZE); |
11215 | memset(wkb + SRID_SIZE, Geometry::wkb_ndr, 1); // wkb_ndr is meaningless. |
11216 | int4store(wkb + SRID_SIZE + 1, Geometry::wkb_point); |
11217 | double latitude_in_degree, longitude_in_degree; |
11218 | latitude_in_degree = GRN_GEO_MSEC2DEGREE(latitude); |
11219 | longitude_in_degree = GRN_GEO_MSEC2DEGREE(longitude); |
11220 | float8store(wkb + SRID_SIZE + WKB_HEADER_SIZE, |
11221 | longitude_in_degree); |
11222 | float8store(wkb + SRID_SIZE + WKB_HEADER_SIZE + SIZEOF_STORED_DOUBLE, |
11223 | latitude_in_degree); |
11224 | String *geometry_buffer = &blob_buffers[field->field_index]; |
11225 | geometry_buffer->length(0); |
11226 | uint wkb_length = sizeof(wkb) / sizeof(*wkb); |
11227 | Field_geom *geometry = (Field_geom *)field; |
11228 | geometry_buffer->reserve(wkb_length); |
11229 | geometry_buffer->q_append((const char *) wkb, wkb_length); |
11230 | geometry->set_ptr((uint32) wkb_length, (uchar *) geometry_buffer->ptr()); |
11231 | #endif |
11232 | DBUG_VOID_RETURN; |
11233 | } |
11234 | |
11235 | #ifdef MRN_HAVE_MYSQL_TYPE_JSON |
11236 | void ha_mroonga::storage_store_field_json(Field *field, |
11237 | const char *value, |
11238 | uint value_length) |
11239 | { |
11240 | MRN_DBUG_ENTER_METHOD(); |
11241 | Field_json *json = static_cast<Field_json *>(field); |
11242 | json->store(value, value_length, field->charset()); |
11243 | DBUG_VOID_RETURN; |
11244 | } |
11245 | #endif |
11246 | |
11247 | void ha_mroonga::storage_store_field(Field *field, |
11248 | const char *value, uint value_length) |
11249 | { |
11250 | field->set_notnull(); |
11251 | switch (field->real_type()) { |
11252 | case MYSQL_TYPE_DECIMAL: |
11253 | storage_store_field_string(field, value, value_length); |
11254 | break; |
11255 | case MYSQL_TYPE_TINY: |
11256 | case MYSQL_TYPE_SHORT: |
11257 | case MYSQL_TYPE_LONG: |
11258 | storage_store_field_integer(field, value, value_length); |
11259 | break; |
11260 | case MYSQL_TYPE_FLOAT: |
11261 | case MYSQL_TYPE_DOUBLE: |
11262 | storage_store_field_float(field, value, value_length); |
11263 | break; |
11264 | case MYSQL_TYPE_NULL: |
11265 | storage_store_field_unsigned_integer(field, value, value_length); |
11266 | break; |
11267 | case MYSQL_TYPE_TIMESTAMP: |
11268 | storage_store_field_timestamp(field, value, value_length); |
11269 | break; |
11270 | case MYSQL_TYPE_LONGLONG: |
11271 | case MYSQL_TYPE_INT24: |
11272 | storage_store_field_integer(field, value, value_length); |
11273 | break; |
11274 | case MYSQL_TYPE_DATE: |
11275 | storage_store_field_date(field, value, value_length); |
11276 | break; |
11277 | case MYSQL_TYPE_TIME: |
11278 | storage_store_field_time(field, value, value_length); |
11279 | break; |
11280 | case MYSQL_TYPE_DATETIME: |
11281 | storage_store_field_datetime(field, value, value_length); |
11282 | break; |
11283 | case MYSQL_TYPE_YEAR: |
11284 | storage_store_field_year(field, value, value_length); |
11285 | break; |
11286 | case MYSQL_TYPE_NEWDATE: |
11287 | storage_store_field_new_date(field, value, value_length); |
11288 | break; |
11289 | case MYSQL_TYPE_VARCHAR: |
11290 | storage_store_field_string(field, value, value_length); |
11291 | break; |
11292 | case MYSQL_TYPE_BIT: |
11293 | storage_store_field_unsigned_integer(field, value, value_length); |
11294 | break; |
11295 | #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2 |
11296 | case MYSQL_TYPE_TIMESTAMP2: |
11297 | storage_store_field_timestamp(field, value, value_length); |
11298 | break; |
11299 | #endif |
11300 | #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 |
11301 | case MYSQL_TYPE_DATETIME2: |
11302 | storage_store_field_datetime2(field, value, value_length); |
11303 | break; |
11304 | #endif |
11305 | #ifdef MRN_HAVE_MYSQL_TYPE_TIME2 |
11306 | case MYSQL_TYPE_TIME2: |
11307 | storage_store_field_time2(field, value, value_length); |
11308 | break; |
11309 | #endif |
11310 | case MYSQL_TYPE_NEWDECIMAL: |
11311 | storage_store_field_string(field, value, value_length); |
11312 | break; |
11313 | case MYSQL_TYPE_ENUM: |
11314 | case MYSQL_TYPE_SET: |
11315 | storage_store_field_unsigned_integer(field, value, value_length); |
11316 | break; |
11317 | case MYSQL_TYPE_TINY_BLOB: |
11318 | case MYSQL_TYPE_MEDIUM_BLOB: |
11319 | case MYSQL_TYPE_LONG_BLOB: |
11320 | case MYSQL_TYPE_BLOB: |
11321 | storage_store_field_blob(field, value, value_length); |
11322 | break; |
11323 | case MYSQL_TYPE_VAR_STRING: |
11324 | case MYSQL_TYPE_STRING: |
11325 | storage_store_field_string(field, value, value_length); |
11326 | break; |
11327 | case MYSQL_TYPE_GEOMETRY: |
11328 | storage_store_field_geometry(field, value, value_length); |
11329 | break; |
11330 | case MYSQL_TYPE_VARCHAR_COMPRESSED: |
11331 | case MYSQL_TYPE_BLOB_COMPRESSED: |
11332 | DBUG_ASSERT(0); |
11333 | #ifdef MRN_HAVE_MYSQL_TYPE_JSON |
11334 | case MYSQL_TYPE_JSON: |
11335 | storage_store_field_json(field, value, value_length); |
11336 | break; |
11337 | #endif |
11338 | } |
11339 | } |
11340 | |
11341 | void ha_mroonga::storage_store_field_column(Field *field, bool is_primary_key, |
11342 | int nth_column, grn_id record_id) |
11343 | { |
11344 | MRN_DBUG_ENTER_METHOD(); |
11345 | |
11346 | if (!grn_columns[nth_column]) { |
11347 | DBUG_VOID_RETURN; |
11348 | } |
11349 | |
11350 | grn_obj *column = grn_columns[nth_column]; |
11351 | grn_id range_id = grn_obj_get_range(ctx, column); |
11352 | grn_obj *range = grn_column_ranges[nth_column]; |
11353 | grn_obj *value = &new_value_buffer; |
11354 | |
11355 | if (mrn::grn::is_table(range)) { |
11356 | if (mrn::grn::is_vector_column(column)) { |
11357 | grn_obj_reinit(ctx, value, range_id, GRN_OBJ_VECTOR); |
11358 | grn_obj_get_value(ctx, column, record_id, value); |
11359 | |
11360 | grn_obj unvectored_value; |
11361 | GRN_TEXT_INIT(&unvectored_value, 0); |
11362 | int n_ids = GRN_BULK_VSIZE(value) / sizeof(grn_id); |
11363 | for (int i = 0; i < n_ids; i++) { |
11364 | grn_id id = GRN_RECORD_VALUE_AT(value, i); |
11365 | if (i > 0) { |
11366 | GRN_TEXT_PUTS(ctx, &unvectored_value, mrn_vector_column_delimiter); |
11367 | } |
11368 | char key[GRN_TABLE_MAX_KEY_SIZE]; |
11369 | int key_length; |
11370 | key_length = grn_table_get_key(ctx, range, id, |
11371 | &key, GRN_TABLE_MAX_KEY_SIZE); |
11372 | GRN_TEXT_PUT(ctx, &unvectored_value, key, key_length); |
11373 | } |
11374 | storage_store_field(field, |
11375 | GRN_TEXT_VALUE(&unvectored_value), |
11376 | GRN_TEXT_LEN(&unvectored_value)); |
11377 | GRN_OBJ_FIN(ctx, &unvectored_value); |
11378 | } else { |
11379 | grn_obj_reinit(ctx, value, range_id, 0); |
11380 | grn_obj_get_value(ctx, column, record_id, value); |
11381 | |
11382 | grn_id id = GRN_RECORD_VALUE(value); |
11383 | char key[GRN_TABLE_MAX_KEY_SIZE]; |
11384 | int key_length; |
11385 | key_length = grn_table_get_key(ctx, range, id, |
11386 | &key, GRN_TABLE_MAX_KEY_SIZE); |
11387 | storage_store_field(field, key, key_length); |
11388 | } |
11389 | } else { |
11390 | grn_obj_reinit(ctx, value, range_id, 0); |
11391 | grn_obj_get_value(ctx, column, record_id, value); |
11392 | if (is_primary_key && GRN_BULK_VSIZE(value) == 0) { |
11393 | char key[GRN_TABLE_MAX_KEY_SIZE]; |
11394 | int key_length; |
11395 | key_length = grn_table_get_key(ctx, grn_table, record_id, |
11396 | &key, GRN_TABLE_MAX_KEY_SIZE); |
11397 | storage_store_field(field, key, key_length); |
11398 | } else { |
11399 | storage_store_field(field, GRN_BULK_HEAD(value), GRN_BULK_VSIZE(value)); |
11400 | } |
11401 | } |
11402 | |
11403 | DBUG_VOID_RETURN; |
11404 | } |
11405 | |
11406 | void ha_mroonga::storage_store_fields(uchar *buf, grn_id record_id) |
11407 | { |
11408 | MRN_DBUG_ENTER_METHOD(); |
11409 | DBUG_PRINT("info" , ("mroonga: stored record ID: %d" , record_id)); |
11410 | |
11411 | my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(buf, table->record[0]); |
11412 | |
11413 | Field *primary_key_field = NULL; |
11414 | if (table->s->primary_key != MAX_INDEXES) { |
11415 | KEY *key_info = &(table->s->key_info[table->s->primary_key]); |
11416 | if (KEY_N_KEY_PARTS(key_info) == 1) { |
11417 | primary_key_field = key_info->key_part[0].field; |
11418 | } |
11419 | } |
11420 | |
11421 | int i; |
11422 | int n_columns = table->s->fields; |
11423 | for (i = 0; i < n_columns; i++) { |
11424 | Field *field = table->field[i]; |
11425 | |
11426 | if (bitmap_is_set(table->read_set, field->field_index) || |
11427 | bitmap_is_set(table->write_set, field->field_index)) { |
11428 | const char *column_name = field->field_name.str; |
11429 | |
11430 | if (ignoring_no_key_columns) { |
11431 | KEY *key_info = &(table->s->key_info[active_index]); |
11432 | if (strcmp(key_info->key_part[0].field->field_name.str, column_name)) { |
11433 | continue; |
11434 | } |
11435 | } |
11436 | |
11437 | mrn::DebugColumnAccess debug_column_access(table, table->write_set); |
11438 | DBUG_PRINT("info" , ("mroonga: store column %d(%d)" ,i,field->field_index)); |
11439 | field->move_field_offset(ptr_diff); |
11440 | if (strcmp(MRN_COLUMN_NAME_ID, column_name) == 0) { |
11441 | // for _id column |
11442 | field->set_notnull(); |
11443 | field->store((int)record_id); |
11444 | } else if (primary_key_field && |
11445 | strcmp(primary_key_field->field_name.str, column_name) == 0) { |
11446 | // for primary key column |
11447 | storage_store_field_column(field, true, i, record_id); |
11448 | } else { |
11449 | storage_store_field_column(field, false, i, record_id); |
11450 | } |
11451 | field->move_field_offset(-ptr_diff); |
11452 | } |
11453 | } |
11454 | |
11455 | DBUG_VOID_RETURN; |
11456 | } |
11457 | |
11458 | void ha_mroonga::storage_store_fields_for_prep_update(const uchar *old_data, |
11459 | const uchar *new_data, |
11460 | grn_id record_id) |
11461 | { |
11462 | MRN_DBUG_ENTER_METHOD(); |
11463 | DBUG_PRINT("info" , ("mroonga: stored record ID: %d" , record_id)); |
11464 | my_ptrdiff_t ptr_diff_old = PTR_BYTE_DIFF(old_data, table->record[0]); |
11465 | my_ptrdiff_t ptr_diff_new = 0; |
11466 | #ifdef MRN_RBR_UPDATE_NEED_ALL_COLUMNS |
11467 | if (!written_by_row_based_binlog) { |
11468 | if (check_written_by_row_based_binlog()) { |
11469 | written_by_row_based_binlog = 2; |
11470 | } else { |
11471 | written_by_row_based_binlog = 1; |
11472 | } |
11473 | } |
11474 | bool need_all_columns = |
11475 | (new_data && written_by_row_based_binlog == 2); |
11476 | #endif |
11477 | if (new_data) { |
11478 | ptr_diff_new = PTR_BYTE_DIFF(new_data, table->record[0]); |
11479 | } |
11480 | int i; |
11481 | int n_columns = table->s->fields; |
11482 | for (i = 0; i < n_columns; i++) { |
11483 | Field *field = table->field[i]; |
11484 | |
11485 | #ifdef MRN_SUPPORT_GENERATED_COLUMNS |
11486 | if (MRN_GENERATED_COLUMNS_FIELD_IS_VIRTUAL(field)) { |
11487 | continue; |
11488 | } |
11489 | #endif |
11490 | if ( |
11491 | !bitmap_is_set(table->read_set, field->field_index) && |
11492 | !bitmap_is_set(table->write_set, field->field_index) && |
11493 | #ifdef MRN_RBR_UPDATE_NEED_ALL_COLUMNS |
11494 | ( |
11495 | need_all_columns || |
11496 | #endif |
11497 | bitmap_is_set(&multiple_column_key_bitmap, field->field_index) |
11498 | #ifdef MRN_RBR_UPDATE_NEED_ALL_COLUMNS |
11499 | ) |
11500 | #endif |
11501 | ) { |
11502 | mrn::DebugColumnAccess debug_column_access(table, table->write_set); |
11503 | DBUG_PRINT("info" , ("mroonga: store column %d(%d)" ,i,field->field_index)); |
11504 | grn_obj value; |
11505 | GRN_OBJ_INIT(&value, GRN_BULK, 0, grn_obj_get_range(ctx, grn_columns[i])); |
11506 | grn_obj_get_value(ctx, grn_columns[i], record_id, &value); |
11507 | // old column |
11508 | field->move_field_offset(ptr_diff_old); |
11509 | storage_store_field(field, GRN_BULK_HEAD(&value), GRN_BULK_VSIZE(&value)); |
11510 | field->move_field_offset(-ptr_diff_old); |
11511 | if (new_data) { |
11512 | // new column |
11513 | field->move_field_offset(ptr_diff_new); |
11514 | storage_store_field(field, GRN_BULK_HEAD(&value), GRN_BULK_VSIZE(&value)); |
11515 | field->move_field_offset(-ptr_diff_new); |
11516 | } |
11517 | GRN_OBJ_FIN(ctx, &value); |
11518 | } |
11519 | } |
11520 | |
11521 | DBUG_VOID_RETURN; |
11522 | } |
11523 | |
11524 | void ha_mroonga::storage_store_fields_by_index(uchar *buf) |
11525 | { |
11526 | MRN_DBUG_ENTER_METHOD(); |
11527 | uint key_length; |
11528 | void *key; |
11529 | KEY *key_info = &table->key_info[active_index]; |
11530 | if (table->s->primary_key == active_index) |
11531 | key_length = grn_table_cursor_get_key(ctx, cursor, &key); |
11532 | else |
11533 | key_length = grn_table_cursor_get_key(ctx, index_table_cursor, &key); |
11534 | |
11535 | if (KEY_N_KEY_PARTS(key_info) == 1) { |
11536 | my_ptrdiff_t ptr_diff = PTR_BYTE_DIFF(buf, table->record[0]); |
11537 | Field *field = key_info->key_part->field; |
11538 | mrn::DebugColumnAccess debug_column_access(table, table->write_set); |
11539 | field->move_field_offset(ptr_diff); |
11540 | storage_store_field(field, (const char *)key, key_length); |
11541 | field->move_field_offset(-ptr_diff); |
11542 | } else { |
11543 | uchar enc_buf[MAX_KEY_LENGTH]; |
11544 | uint enc_len; |
11545 | mrn::MultipleColumnKeyCodec codec(ctx, ha_thd(), key_info); |
11546 | codec.decode(static_cast<uchar *>(key), key_length, enc_buf, &enc_len); |
11547 | key_restore(buf, enc_buf, key_info, enc_len); |
11548 | } |
11549 | DBUG_VOID_RETURN; |
11550 | } |
11551 | |
11552 | int ha_mroonga::storage_encode_key_normalize_min_sort_chars(Field *field, |
11553 | uchar *buf, |
11554 | uint size) |
11555 | { |
11556 | MRN_DBUG_ENTER_METHOD(); |
11557 | int error = 0; |
11558 | |
11559 | if (size == 0) { |
11560 | DBUG_RETURN(0); |
11561 | } |
11562 | if (!field->has_charset()) { |
11563 | DBUG_RETURN(0); |
11564 | } |
11565 | |
11566 | uint16 raw_min_sort_char = |
11567 | static_cast<uint16>(field->sort_charset()->min_sort_char); |
11568 | if (raw_min_sort_char <= UINT_MAX8) { |
11569 | uchar min_sort_char = static_cast<uchar>(raw_min_sort_char); |
11570 | for (uint i = size - 1; i > 0; --i) { |
11571 | if (buf[i] != min_sort_char) { |
11572 | break; |
11573 | } |
11574 | buf[i] = '\0'; |
11575 | } |
11576 | } |
11577 | |
11578 | DBUG_RETURN(error); |
11579 | } |
11580 | |
11581 | int ha_mroonga::storage_encode_key_fixed_size_string(Field *field, |
11582 | const uchar *key, |
11583 | uchar *buf, uint *size) |
11584 | { |
11585 | MRN_DBUG_ENTER_METHOD(); |
11586 | int error = 0; |
11587 | memcpy(buf, key, field->field_length); |
11588 | *size = field->field_length; |
11589 | DBUG_RETURN(error); |
11590 | } |
11591 | |
11592 | int ha_mroonga::storage_encode_key_variable_size_string(Field *field, |
11593 | const uchar *key, |
11594 | uchar *buf, uint *size) |
11595 | { |
11596 | MRN_DBUG_ENTER_METHOD(); |
11597 | int error = 0; |
11598 | *size = uint2korr(key); |
11599 | memcpy(buf, key + HA_KEY_BLOB_LENGTH, *size); |
11600 | storage_encode_key_normalize_min_sort_chars(field, buf, *size); |
11601 | DBUG_RETURN(error); |
11602 | } |
11603 | |
11604 | int ha_mroonga::storage_encode_key_timestamp(Field *field, const uchar *key, |
11605 | uchar *buf, uint *size) |
11606 | { |
11607 | MRN_DBUG_ENTER_METHOD(); |
11608 | int error = 0; |
11609 | bool truncated = false; |
11610 | long long int time; |
11611 | MYSQL_TIME mysql_time; |
11612 | #ifdef MRN_MARIADB_P |
11613 | if (field->decimals() == 0) { |
11614 | my_time_t my_time = sint4korr(key); |
11615 | mrn_my_tz_UTC->gmt_sec_to_TIME(&mysql_time, my_time); |
11616 | mysql_time.second_part = 0; |
11617 | } else { |
11618 | Field_timestamp_hires *timestamp_hires_field = |
11619 | (Field_timestamp_hires *)field; |
11620 | uint fuzzy_date = 0; |
11621 | uchar *ptr_backup = field->ptr; |
11622 | uchar *null_ptr_backup = field->null_ptr; |
11623 | TABLE *table_backup = field->table; |
11624 | field->ptr = (uchar *)key; |
11625 | field->null_ptr = (uchar *)(key - 1); |
11626 | field->table = table; |
11627 | timestamp_hires_field->get_date(&mysql_time, fuzzy_date); |
11628 | field->ptr = ptr_backup; |
11629 | field->null_ptr = null_ptr_backup; |
11630 | field->table = table_backup; |
11631 | } |
11632 | #else |
11633 | my_time_t my_time = uint4korr(key); |
11634 | mrn_my_tz_UTC->gmt_sec_to_TIME(&mysql_time, my_time); |
11635 | #endif |
11636 | mrn::TimeConverter time_converter; |
11637 | time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); |
11638 | if (truncated) { |
11639 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
11640 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
11641 | } |
11642 | field->set_warning(MRN_SEVERITY_WARNING, |
11643 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
11644 | 1); |
11645 | } |
11646 | memcpy(buf, &time, 8); |
11647 | *size = 8; |
11648 | DBUG_RETURN(error); |
11649 | } |
11650 | |
11651 | int ha_mroonga::storage_encode_key_time(Field *field, const uchar *key, |
11652 | uchar *buf, uint *size) |
11653 | { |
11654 | MRN_DBUG_ENTER_METHOD(); |
11655 | int error = 0; |
11656 | long long int time; |
11657 | #ifdef MRN_MARIADB_P |
11658 | MYSQL_TIME mysql_time; |
11659 | bool truncated = false; |
11660 | if (field->decimals() == 0) { |
11661 | long long int packed_time = sint3korr(key); |
11662 | mysql_time.neg = false; |
11663 | if (packed_time < 0) { |
11664 | mysql_time.neg = true; |
11665 | packed_time = -packed_time; |
11666 | } |
11667 | mysql_time.year = 0; |
11668 | mysql_time.month = 0; |
11669 | mysql_time.day = 0; |
11670 | mysql_time.hour = (int)(packed_time / 10000); |
11671 | long long int minute_part = packed_time - mysql_time.hour * 10000; |
11672 | mysql_time.minute = (int)(minute_part / 100); |
11673 | mysql_time.second = (int)(minute_part % 100); |
11674 | mysql_time.second_part = 0; |
11675 | mysql_time.time_type = MYSQL_TIMESTAMP_TIME; |
11676 | } else { |
11677 | Field_time_hires *time_hires_field = (Field_time_hires *)field; |
11678 | uint fuzzy_date = 0; |
11679 | uchar *ptr_backup = field->ptr; |
11680 | uchar *null_ptr_backup = field->null_ptr; |
11681 | field->ptr = (uchar *)key; |
11682 | field->null_ptr = (uchar *)(key - 1); |
11683 | time_hires_field->get_date(&mysql_time, fuzzy_date); |
11684 | field->ptr = ptr_backup; |
11685 | field->null_ptr = null_ptr_backup; |
11686 | } |
11687 | mrn::TimeConverter time_converter; |
11688 | time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); |
11689 | if (truncated) { |
11690 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
11691 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
11692 | } |
11693 | field->set_warning(MRN_SEVERITY_WARNING, |
11694 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
11695 | 1); |
11696 | } |
11697 | #else |
11698 | int mysql_time = (int)sint3korr(key); |
11699 | int sec = |
11700 | mysql_time / 10000 * 60 * 60 + |
11701 | mysql_time / 100 % 100 * 60 + |
11702 | mysql_time % 60; |
11703 | int usec = 0; |
11704 | time = GRN_TIME_PACK(sec, usec); |
11705 | #endif |
11706 | memcpy(buf, &time, 8); |
11707 | *size = 8; |
11708 | DBUG_RETURN(error); |
11709 | } |
11710 | |
11711 | int ha_mroonga::storage_encode_key_year(Field *field, const uchar *key, |
11712 | uchar *buf, uint *size) |
11713 | { |
11714 | MRN_DBUG_ENTER_METHOD(); |
11715 | int error = 0; |
11716 | bool truncated = false; |
11717 | int year = (int)key[0]; |
11718 | |
11719 | struct tm datetime; |
11720 | memset(&datetime, 0, sizeof(struct tm)); |
11721 | datetime.tm_year = year; |
11722 | datetime.tm_mon = 0; |
11723 | datetime.tm_mday = 1; |
11724 | int usec = 0; |
11725 | mrn::TimeConverter time_converter; |
11726 | long long int time = time_converter.tm_to_grn_time(&datetime, usec, |
11727 | &truncated); |
11728 | if (truncated) { |
11729 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
11730 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
11731 | } |
11732 | field->set_warning(MRN_SEVERITY_WARNING, |
11733 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
11734 | 1); |
11735 | } |
11736 | memcpy(buf, &time, 8); |
11737 | *size = 8; |
11738 | DBUG_RETURN(error); |
11739 | } |
11740 | |
11741 | int ha_mroonga::storage_encode_key_datetime(Field *field, const uchar *key, |
11742 | uchar *buf, uint *size) |
11743 | { |
11744 | MRN_DBUG_ENTER_METHOD(); |
11745 | int error = 0; |
11746 | bool truncated = false; |
11747 | long long int time; |
11748 | #ifdef MRN_MARIADB_P |
11749 | if (field->decimals() > 0) { |
11750 | Field_datetime_hires *datetime_hires_field = (Field_datetime_hires *)field; |
11751 | MYSQL_TIME mysql_time; |
11752 | uint fuzzy_date = 0; |
11753 | uchar *ptr_backup = field->ptr; |
11754 | uchar *null_ptr_backup = field->null_ptr; |
11755 | field->ptr = (uchar *)key; |
11756 | field->null_ptr = (uchar *)(key - 1); |
11757 | datetime_hires_field->get_date(&mysql_time, fuzzy_date); |
11758 | field->ptr = ptr_backup; |
11759 | field->null_ptr = null_ptr_backup; |
11760 | mrn::TimeConverter time_converter; |
11761 | time = time_converter.mysql_time_to_grn_time(&mysql_time, &truncated); |
11762 | } else |
11763 | #endif |
11764 | { |
11765 | long long int encoded_datetime = sint8korr(key); |
11766 | uint32 part1 = (uint32)(encoded_datetime / 1000000LL); |
11767 | uint32 part2 = (uint32)(encoded_datetime - |
11768 | (unsigned long long int)part1 * 1000000LL); |
11769 | struct tm date; |
11770 | memset(&date, 0, sizeof(struct tm)); |
11771 | date.tm_year = part1 / 10000 - mrn::TimeConverter::TM_YEAR_BASE; |
11772 | date.tm_mon = part1 / 100 % 100 - 1; |
11773 | date.tm_mday = part1 % 100; |
11774 | date.tm_hour = part2 / 10000; |
11775 | date.tm_min = part2 / 100 % 100; |
11776 | date.tm_sec = part2 % 100; |
11777 | int usec = 0; |
11778 | mrn::TimeConverter time_converter; |
11779 | time = time_converter.tm_to_grn_time(&date, usec, &truncated); |
11780 | } |
11781 | if (truncated) { |
11782 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
11783 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
11784 | } |
11785 | field->set_warning(MRN_SEVERITY_WARNING, |
11786 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
11787 | 1); |
11788 | } |
11789 | memcpy(buf, &time, 8); |
11790 | *size = 8; |
11791 | DBUG_RETURN(error); |
11792 | } |
11793 | |
11794 | #ifdef MRN_HAVE_MYSQL_TYPE_TIMESTAMP2 |
11795 | int ha_mroonga::storage_encode_key_timestamp2(Field *field, const uchar *key, |
11796 | uchar *buf, uint *size) |
11797 | { |
11798 | MRN_DBUG_ENTER_METHOD(); |
11799 | int error = 0; |
11800 | bool truncated = false; |
11801 | |
11802 | Field_timestampf *timestamp2_field = (Field_timestampf *)field; |
11803 | struct timeval tm; |
11804 | my_timestamp_from_binary(&tm, key, timestamp2_field->decimals()); |
11805 | MYSQL_TIME mysql_time; |
11806 | mrn_my_tz_UTC->gmt_sec_to_TIME(&mysql_time, (my_time_t)tm.tv_sec); |
11807 | mysql_time.second_part = tm.tv_usec; |
11808 | mrn::TimeConverter time_converter; |
11809 | long long int grn_time = time_converter.mysql_time_to_grn_time(&mysql_time, |
11810 | &truncated); |
11811 | if (truncated) { |
11812 | if (MRN_ABORT_ON_WARNING(ha_thd())) { |
11813 | error = MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()); |
11814 | } |
11815 | field->set_warning(MRN_SEVERITY_WARNING, |
11816 | MRN_ERROR_CODE_DATA_TRUNCATE(ha_thd()), |
11817 | 1); |
11818 | } |
11819 | memcpy(buf, &grn_time, 8); |
11820 | *size = 8; |
11821 | |
11822 | DBUG_RETURN(error); |
11823 | } |
11824 | #endif |
11825 | |
11826 | #ifdef MRN_HAVE_MYSQL_TYPE_DATETIME2 |
11827 | int 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 |
11858 | int 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 | |
11888 | int 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 | |
11907 | int 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 | |
11957 | int 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 | |
12095 | int 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 | |
12107 | int 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 | |
12138 | int 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 | |
12172 | int 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 | |
12202 | int 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 | |
12230 | int ha_mroonga::storage_reset() |
12231 | { |
12232 | MRN_DBUG_ENTER_METHOD(); |
12233 | int error; |
12234 | error = generic_reset(); |
12235 | DBUG_RETURN(error); |
12236 | } |
12237 | |
12238 | int 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 | |
12263 | handler *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 | |
12282 | handler *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 | |
12290 | handler *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 | |
12303 | uint8 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 | |
12315 | uint8 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 | |
12322 | uint8 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 |
12336 | ha_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 | |
12364 | ha_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 | |
12380 | ha_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 | |
12401 | ha_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 | |
12435 | ha_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 | |
12453 | ha_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 | |
12479 | int 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 | |
12503 | int 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 | |
12514 | int 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 | |
12531 | int 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 | |
12550 | int 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 | |
12557 | int 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 |
12570 | int 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 | |
12595 | int 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 | |
12607 | int 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 | |
12626 | int 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 | |
12645 | int 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 | |
12652 | int 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 |
12667 | void ha_mroonga::wrapper_start_bulk_insert(ha_rows rows, uint flags) |
12668 | #else |
12669 | void 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 |
12686 | void ha_mroonga::storage_start_bulk_insert(ha_rows rows, uint flags) |
12687 | #else |
12688 | void 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 |
12696 | void ha_mroonga::start_bulk_insert(ha_rows rows, uint flags) |
12697 | #else |
12698 | void 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 | |
12718 | int 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 | |
12730 | int ha_mroonga::storage_end_bulk_insert() |
12731 | { |
12732 | MRN_DBUG_ENTER_METHOD(); |
12733 | DBUG_RETURN(0); |
12734 | } |
12735 | |
12736 | int 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 | |
12749 | int 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 | |
12784 | int 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 | |
12831 | int 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 | |
12861 | int 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 | |
12874 | int 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 | |
12891 | int 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 | } |
12929 | err: |
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 | |
12939 | int 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 | |
12969 | int 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 | } |
13007 | err: |
13008 | DBUG_RETURN(error); |
13009 | } |
13010 | |
13011 | int 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 | |
13028 | double 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 | |
13040 | double ha_mroonga::storage_scan_time() |
13041 | { |
13042 | MRN_DBUG_ENTER_METHOD(); |
13043 | double time = handler::scan_time(); |
13044 | DBUG_RETURN(time); |
13045 | } |
13046 | |
13047 | double 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 | |
13060 | double 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 | |
13085 | double 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 | |
13092 | double 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 |
13106 | const 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 | |
13118 | const key_map *ha_mroonga::storage_keys_to_use_for_scanning() |
13119 | { |
13120 | MRN_DBUG_ENTER_METHOD(); |
13121 | DBUG_RETURN(&key_map_full); |
13122 | } |
13123 | |
13124 | const 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 | |
13138 | ha_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 | |
13150 | ha_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 | |
13157 | ha_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 | |
13170 | void 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 | |
13181 | void 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 | |
13197 | void 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 | |
13239 | int 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 | |
13269 | int 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 | |
13329 | int 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 | |
13405 | error_end: |
13406 | mrn_free_long_term_share(to_long_term_share); |
13407 | DBUG_RETURN(error); |
13408 | } |
13409 | |
13410 | #ifdef MRN_SUPPORT_FOREIGN_KEYS |
13411 | int 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 | |
13463 | int 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 | |
13526 | bool 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 | |
13538 | bool 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 | |
13546 | bool 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 | |
13559 | bool 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 | |
13575 | bool 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 | |
13587 | bool 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 | |
13602 | bool 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 | |
13609 | int 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 | |
13652 | int 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 | |
13688 | int 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 | |
13706 | int 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 | |
13742 | int 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 | |
13755 | int 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 | |
13833 | int 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 | |
13851 | int 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 | |
13930 | int 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 | |
13944 | int 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 | |
13956 | int 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 | |
13967 | int 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 | |
13980 | int 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 | |
14095 | int 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 | |
14139 | int 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 | |
14197 | int 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 | |
14212 | int 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 | |
14219 | int 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 | |
14233 | bool 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 | |
14245 | bool 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 | |
14254 | bool 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 | |
14267 | int 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 | |
14279 | int 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 | |
14285 | int 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 | |
14298 | int 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 | |
14304 | int 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 | |
14310 | int 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 | |
14323 | bool 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 | |
14339 | bool 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 | |
14350 | bool 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 | |
14363 | bool 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 | |
14376 | bool 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 | |
14390 | bool 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 | |
14410 | int 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 |
14487 | bool ha_mroonga::(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 | |
14504 | enum_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 | |
14633 | enum_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 | |
14660 | enum_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 | |
14676 | bool 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 | |
14720 | bool 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 | |
14728 | bool 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 | |
14742 | bool 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 | |
14910 | bool 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 | |
15045 | bool 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 | |
15072 | bool 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 | |
15275 | bool 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 | |
15325 | bool 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 | |
15383 | bool 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 | |
15440 | bool 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 | |
15454 | bool 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 | |
15482 | bool 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 | |
15491 | bool 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 | |
15508 | void 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 | |
15519 | void ha_mroonga::storage_notify_table_changed() |
15520 | { |
15521 | MRN_DBUG_ENTER_METHOD(); |
15522 | DBUG_VOID_RETURN; |
15523 | } |
15524 | |
15525 | void 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 |
15536 | alter_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 | |
15548 | alter_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 | |
15555 | alter_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 |
15569 | int ha_mroonga::wrapper_add_index(TABLE *table_arg, KEY *key_info, |
15570 | uint num_of_keys, handler_add_index **add) |
15571 | #else |
15572 | int 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 |
15709 | int ha_mroonga::storage_add_index(TABLE *table_arg, KEY *key_info, |
15710 | uint num_of_keys, handler_add_index **add) |
15711 | #else |
15712 | int 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 |
15822 | int 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 |
15836 | int 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 |
15852 | int 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 | |
15871 | int 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 | |
15881 | int 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 | |
15895 | int 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 | |
15934 | int 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 | |
15955 | int 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 | |
15969 | int 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 | |
15981 | int ha_mroonga::storage_final_drop_index(TABLE *table_arg) |
15982 | { |
15983 | MRN_DBUG_ENTER_METHOD(); |
15984 | DBUG_RETURN(0); |
15985 | } |
15986 | |
15987 | int 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 | |
16001 | int 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 | |
16013 | int 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 | |
16022 | int 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 | |
16035 | void 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 | |
16046 | void 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 | |
16053 | void 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 | |
16065 | void 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 | |
16081 | void 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 | |
16111 | void 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 | |
16133 | void 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 | |
16144 | void 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 | |
16151 | void 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 | |
16163 | void 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 | |
16174 | void ha_mroonga::storage_release_auto_increment() |
16175 | { |
16176 | MRN_DBUG_ENTER_METHOD(); |
16177 | DBUG_VOID_RETURN; |
16178 | } |
16179 | |
16180 | void 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 | |
16192 | int 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 | |
16203 | int 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 | |
16231 | int 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 |
16244 | int 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 | |
16256 | int 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 | |
16268 | int 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 | |
16282 | void 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 | |
16294 | bool 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 | |
16306 | bool 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 | |
16314 | bool 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 | |
16327 | void 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 | |
16338 | void 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 | |
16345 | void 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 | |
16357 | void 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 | |
16368 | void ha_mroonga::storage_unlock_row() |
16369 | { |
16370 | MRN_DBUG_ENTER_METHOD(); |
16371 | handler::unlock_row(); |
16372 | DBUG_VOID_RETURN; |
16373 | } |
16374 | |
16375 | void 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 | |
16387 | int 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 | |
16399 | int 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 | |
16407 | int 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 | |
16420 | void 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 | |
16432 | void 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 | |
16439 | void 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 | |
16452 | bool 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 | |
16464 | bool 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 | |
16471 | bool 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 | |
16484 | bool 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 | |
16496 | bool 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 | |
16503 | bool 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 | |
16516 | char *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 |
16529 | char *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 |
16634 | char *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 | |
16642 | char *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 |
16656 | char *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 | |
16669 | char *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 | |
16677 | char *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 | |
16691 | bool 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 | |
16703 | bool 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 | |
16710 | bool 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 | |
16723 | int 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 |
16737 | int 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 |
16845 | int 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 | |
16854 | int 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 | |
16868 | int 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 | |
16881 | int 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 | |
16889 | int 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 | |
16903 | uint 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 | |
16915 | uint 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 | |
16922 | uint 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 | |
16935 | void 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 | |
16946 | void 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 | |
16953 | void 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 | |
16965 | void 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 |
16977 | void 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 |
16984 | void 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 | |
16992 | void 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 |
17005 | bool 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 |
17041 | void 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 | |
17052 | void ha_mroonga::storage_unbind_psi() |
17053 | { |
17054 | MRN_DBUG_ENTER_METHOD(); |
17055 | DBUG_VOID_RETURN; |
17056 | } |
17057 | |
17058 | void 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 | |
17071 | void 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 | |
17082 | void ha_mroonga::storage_rebind_psi() |
17083 | { |
17084 | MRN_DBUG_ENTER_METHOD(); |
17085 | DBUG_VOID_RETURN; |
17086 | } |
17087 | |
17088 | void 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 | |
17102 | my_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 | |
17123 | my_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 | |
17139 | my_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 | |
17169 | namespace 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 | |