25 #include "rpl_handler.h"
26 #include "sql_cache.h"
28 #include "sql_table.h"
29 #include "sql_parse.h"
34 #include "rpl_filter.h"
35 #include <myisampack.h>
36 #include "transaction.h"
38 #include "probes_mysql.h"
44 #ifdef WITH_PARTITION_STORAGE_ENGINE
45 #include "ha_partition.h"
58 inline double log2(
double x)
60 return (log(x) / M_LN2);
73 #define BITMAP_STACKBUF_SIZE (128/8)
76 { HA_KEY_ALG_UNDEF, 0, {NullS, 0}, {NullS, 0},
true };
81 ulong total_ha_2pc= 0;
83 ulong savepoint_alloc_size= 0;
87 { C_STRING_WITH_LEN(
"INNOBASE") }, { C_STRING_WITH_LEN(
"INNODB") },
88 { C_STRING_WITH_LEN(
"NDB") }, { C_STRING_WITH_LEN(
"NDBCLUSTER") },
89 { C_STRING_WITH_LEN(
"HEAP") }, { C_STRING_WITH_LEN(
"MEMORY") },
90 { C_STRING_WITH_LEN(
"MERGE") }, { C_STRING_WITH_LEN(
"MRG_MYISAM") },
94 const char *ha_row_type[] = {
95 "",
"FIXED",
"DYNAMIC",
"COMPRESSED",
"REDUNDANT",
"COMPACT",
100 const char *tx_isolation_names[] =
101 {
"READ-UNCOMMITTED",
"READ-COMMITTED",
"REPEATABLE-READ",
"SERIALIZABLE",
103 TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,
"",
104 tx_isolation_names, NULL};
108 const char *ha_legacy_type_name(legacy_db_type legacy_type)
112 case DB_TYPE_UNKNOWN:
113 return "DB_TYPE_UNKNOWN";
114 case DB_TYPE_DIAB_ISAM:
115 return "DB_TYPE_DIAB_ISAM";
117 return "DB_TYPE_HASH";
119 return "DB_TYPE_MISAM";
121 return "DB_TYPE_PISAM";
122 case DB_TYPE_RMS_ISAM:
123 return "DB_TYPE_RMS_ISAM";
125 return "DB_TYPE_HEAP";
127 return "DB_TYPE_ISAM";
128 case DB_TYPE_MRG_ISAM:
129 return "DB_TYPE_MRG_ISAM";
131 return "DB_TYPE_MYISAM";
132 case DB_TYPE_MRG_MYISAM:
133 return "DB_TYPE_MRG_MYISAM";
134 case DB_TYPE_BERKELEY_DB:
135 return "DB_TYPE_BERKELEY_DB";
137 return "DB_TYPE_INNODB";
139 return "DB_TYPE_GEMINI";
140 case DB_TYPE_NDBCLUSTER:
141 return "DB_TYPE_NDBCLUSTER";
142 case DB_TYPE_EXAMPLE_DB:
143 return "DB_TYPE_EXAMPLE_DB";
144 case DB_TYPE_ARCHIVE_DB:
145 return "DB_TYPE_ARCHIVE_DB";
147 return "DB_TYPE_CSV_DB";
148 case DB_TYPE_FEDERATED_DB:
149 return "DB_TYPE_FEDERATED_DB";
150 case DB_TYPE_BLACKHOLE_DB:
151 return "DB_TYPE_BLACKHOLE_DB";
152 case DB_TYPE_PARTITION_DB:
153 return "DB_TYPE_PARTITION_DB";
155 return "DB_TYPE_BINLOG";
157 return "DB_TYPE_SOLID";
159 return "DB_TYPE_PBXT";
160 case DB_TYPE_TABLE_FUNCTION:
161 return "DB_TYPE_TABLE_FUNCTION";
162 case DB_TYPE_MEMCACHE:
163 return "DB_TYPE_MEMCACHE";
165 return "DB_TYPE_FALCON";
167 return "DB_TYPE_MARIA";
168 case DB_TYPE_PERFORMANCE_SCHEMA:
169 return "DB_TYPE_PERFORMANCE_SCHEMA";
171 return "DB_TYPE_DYNAMIC";
206 {(
const char *)NULL, (
const char *)NULL}
213 static const char **known_system_databases= NULL;
214 static const char **ha_known_system_databases();
217 static my_bool system_databases_handlerton(THD *unused,
plugin_ref plugin,
221 static my_bool check_engine_system_table_handlerton(THD *unused,
232 const char *table_name;
233 bool is_sql_layer_system_table;
234 legacy_db_type db_type;
236 enum enum_sys_tbl_chk_status
239 NOT_KNOWN_SYSTEM_TABLE,
249 SUPPORTED_SYSTEM_TABLE
256 if (thd->variables.table_plugin)
257 return thd->variables.table_plugin;
258 return my_plugin_lock(thd, &global_system_variables.table_plugin);
283 static plugin_ref ha_default_temp_plugin(THD *thd)
285 if (thd->variables.temp_table_plugin)
286 return thd->variables.temp_table_plugin;
287 return my_plugin_lock(thd, &global_system_variables.temp_table_plugin);
304 plugin_ref plugin= ha_default_temp_plugin(thd);
331 if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1,
332 (
const uchar *)name->str, name->length,
333 (
const uchar *)STRING_WITH_LEN(
"DEFAULT"), 0))
334 return is_temp_table ?
335 ha_default_plugin(thd) : ha_default_temp_plugin(thd);
337 if ((plugin= my_plugin_lock_by_name(thd, name, MYSQL_STORAGE_ENGINE_PLUGIN)))
340 if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
346 plugin_unlock(thd, plugin);
352 for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
354 if (!my_strnncoll(&my_charset_latin1,
355 (
const uchar *)name->str, name->length,
356 (
const uchar *)table_alias->str, table_alias->length))
358 name= table_alias + 1;
374 return my_plugin_lock(thd, plugin);
376 return my_plugin_lock(thd, &plugin);
383 handlerton *ha_resolve_by_legacy_type(THD *thd,
enum legacy_db_type db_type)
387 case DB_TYPE_DEFAULT:
390 if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
391 (plugin= ha_lock_engine(thd, installed_htons[db_type])))
394 case DB_TYPE_UNKNOWN:
404 bool no_substitute,
bool report_error)
406 handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
407 if (ha_storage_engine_is_enabled(hton))
414 const char *engine_name= ha_resolve_storage_engine_name(hton);
415 my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
420 (void) RUN_HOOK(transaction, after_rollback, (thd, FALSE));
422 switch (database_type) {
423 case DB_TYPE_MRG_ISAM:
424 return ha_resolve_by_legacy_type(thd, DB_TYPE_MRG_MYISAM);
437 DBUG_ENTER(
"get_new_handler");
438 DBUG_PRINT(
"enter", (
"alloc: 0x%lx", (
long) alloc));
440 if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
442 if ((file= db_type->create(db_type, share, alloc)))
455 #ifdef WITH_PARTITION_STORAGE_ENGINE
459 DBUG_ENTER(
"get_ha_partition");
460 if ((partition=
new ha_partition(partition_hton, part_info)))
462 if (partition->initialize_partition(current_thd->mem_root))
472 my_error(ER_OUTOFMEMORY, MYF(ME_FATALERROR),
475 DBUG_RETURN(((
handler*) partition));
480 static const char **handler_errmsgs;
483 static const char **get_handler_errmsgs()
485 return handler_errmsgs;
501 #define SETMSG(nr, msg) handler_errmsgs[(nr) - HA_ERR_FIRST]= (msg)
505 if (! (handler_errmsgs= (
const char**) my_malloc(HA_ERR_ERRORS *
sizeof(
char*),
506 MYF(MY_WME | MY_ZEROFILL))))
510 SETMSG(HA_ERR_KEY_NOT_FOUND, ER_DEFAULT(ER_KEY_NOT_FOUND));
511 SETMSG(HA_ERR_FOUND_DUPP_KEY, ER_DEFAULT(ER_DUP_KEY));
512 SETMSG(HA_ERR_RECORD_CHANGED,
"Update wich is recoverable");
513 SETMSG(HA_ERR_WRONG_INDEX,
"Wrong index given to function");
514 SETMSG(HA_ERR_CRASHED, ER_DEFAULT(ER_NOT_KEYFILE));
515 SETMSG(HA_ERR_WRONG_IN_RECORD, ER_DEFAULT(ER_CRASHED_ON_USAGE));
516 SETMSG(HA_ERR_OUT_OF_MEM,
"Table handler out of memory");
517 SETMSG(HA_ERR_NOT_A_TABLE,
"Incorrect file format '%.64s'");
518 SETMSG(HA_ERR_WRONG_COMMAND,
"Command not supported");
519 SETMSG(HA_ERR_OLD_FILE, ER_DEFAULT(ER_OLD_KEYFILE));
520 SETMSG(HA_ERR_NO_ACTIVE_RECORD,
"No record read in update");
521 SETMSG(HA_ERR_RECORD_DELETED,
"Intern record deleted");
522 SETMSG(HA_ERR_RECORD_FILE_FULL, ER_DEFAULT(ER_RECORD_FILE_FULL));
523 SETMSG(HA_ERR_INDEX_FILE_FULL,
"No more room in index file '%.64s'");
524 SETMSG(HA_ERR_END_OF_FILE,
"End in next/prev/first/last");
525 SETMSG(HA_ERR_UNSUPPORTED, ER_DEFAULT(ER_ILLEGAL_HA));
526 SETMSG(HA_ERR_TO_BIG_ROW,
"Too big row");
527 SETMSG(HA_WRONG_CREATE_OPTION,
"Wrong create option");
528 SETMSG(HA_ERR_FOUND_DUPP_UNIQUE, ER_DEFAULT(ER_DUP_UNIQUE));
529 SETMSG(HA_ERR_UNKNOWN_CHARSET,
"Can't open charset");
530 SETMSG(HA_ERR_WRONG_MRG_TABLE_DEF, ER_DEFAULT(ER_WRONG_MRG_TABLE));
531 SETMSG(HA_ERR_CRASHED_ON_REPAIR, ER_DEFAULT(ER_CRASHED_ON_REPAIR));
532 SETMSG(HA_ERR_CRASHED_ON_USAGE, ER_DEFAULT(ER_CRASHED_ON_USAGE));
533 SETMSG(HA_ERR_LOCK_WAIT_TIMEOUT, ER_DEFAULT(ER_LOCK_WAIT_TIMEOUT));
534 SETMSG(HA_ERR_LOCK_TABLE_FULL, ER_DEFAULT(ER_LOCK_TABLE_FULL));
535 SETMSG(HA_ERR_READ_ONLY_TRANSACTION, ER_DEFAULT(ER_READ_ONLY_TRANSACTION));
536 SETMSG(HA_ERR_LOCK_DEADLOCK, ER_DEFAULT(ER_LOCK_DEADLOCK));
537 SETMSG(HA_ERR_CANNOT_ADD_FOREIGN, ER_DEFAULT(ER_CANNOT_ADD_FOREIGN));
538 SETMSG(HA_ERR_NO_REFERENCED_ROW, ER_DEFAULT(ER_NO_REFERENCED_ROW_2));
539 SETMSG(HA_ERR_ROW_IS_REFERENCED, ER_DEFAULT(ER_ROW_IS_REFERENCED_2));
540 SETMSG(HA_ERR_NO_SAVEPOINT,
"No savepoint with that name");
541 SETMSG(HA_ERR_NON_UNIQUE_BLOCK_SIZE,
"Non unique key block size");
542 SETMSG(HA_ERR_NO_SUCH_TABLE,
"No such table: '%.64s'");
543 SETMSG(HA_ERR_TABLE_EXIST, ER_DEFAULT(ER_TABLE_EXISTS_ERROR));
544 SETMSG(HA_ERR_NO_CONNECTION,
"Could not connect to storage engine");
545 SETMSG(HA_ERR_TABLE_DEF_CHANGED, ER_DEFAULT(ER_TABLE_DEF_CHANGED));
546 SETMSG(HA_ERR_FOREIGN_DUPLICATE_KEY,
"FK constraint would lead to duplicate key");
547 SETMSG(HA_ERR_TABLE_NEEDS_UPGRADE, ER_DEFAULT(ER_TABLE_NEEDS_UPGRADE));
548 SETMSG(HA_ERR_TABLE_READONLY, ER_DEFAULT(ER_OPEN_AS_READONLY));
549 SETMSG(HA_ERR_AUTOINC_READ_FAILED, ER_DEFAULT(ER_AUTOINC_READ_FAILED));
550 SETMSG(HA_ERR_AUTOINC_ERANGE, ER_DEFAULT(ER_WARN_DATA_OUT_OF_RANGE));
551 SETMSG(HA_ERR_TOO_MANY_CONCURRENT_TRXS, ER_DEFAULT(ER_TOO_MANY_CONCURRENT_TRXS));
552 SETMSG(HA_ERR_INDEX_COL_TOO_LONG, ER_DEFAULT(ER_INDEX_COLUMN_TOO_LONG));
553 SETMSG(HA_ERR_INDEX_CORRUPT, ER_DEFAULT(ER_INDEX_CORRUPT));
554 SETMSG(HA_FTS_INVALID_DOCID,
"Invalid InnoDB FTS Doc ID");
555 SETMSG(HA_ERR_TABLE_IN_FK_CHECK, ER_DEFAULT(ER_TABLE_IN_FK_CHECK));
556 SETMSG(HA_ERR_TABLESPACE_EXISTS,
"Tablespace already exists");
557 SETMSG(HA_ERR_FTS_EXCEED_RESULT_CACHE_LIMIT,
"FTS query exceeds result cache limit");
560 return my_error_register(get_handler_errmsgs, HA_ERR_FIRST, HA_ERR_LAST);
572 static int ha_finish_errors(
void)
574 const char **errmsgs;
577 if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
587 DBUG_ENTER(
"ha_finalize_handlerton");
596 case SHOW_OPTION_DISABLED:
598 case SHOW_OPTION_YES:
599 if (installed_htons[hton->db_type] == hton)
600 installed_htons[hton->db_type]= NULL;
605 hton->panic(hton, HA_PANIC_CLOSE);
607 if (plugin->plugin->deinit)
613 DBUG_PRINT(
"info", (
"Deinitializing plugin: '%s'", plugin->name.str));
614 if (plugin->plugin->deinit(NULL))
616 DBUG_PRINT(
"warning", (
"Plugin '%s' deinit function returned error.",
626 if (hton->slot != HA_SLOT_UNDEF)
629 DBUG_ASSERT(hton2plugin[hton->slot] == plugin);
630 DBUG_ASSERT(hton->slot < MAX_HA);
631 hton2plugin[hton->slot]= NULL;
644 DBUG_ENTER(
"ha_initialize_handlerton");
645 DBUG_PRINT(
"plugin", (
"initialize plugin: '%s'", plugin->name.str));
648 MYF(MY_WME | MY_ZEROFILL));
652 sql_print_error(
"Unable to allocate memory for plugin '%s' handlerton.",
654 goto err_no_hton_memory;
657 hton->slot= HA_SLOT_UNDEF;
660 if (plugin->plugin->init && plugin->plugin->init(hton))
662 sql_print_error(
"Plugin '%s' init function returned error.",
671 DBUG_PRINT(
"info", (
"hton->state=%d", hton->state));
672 switch (hton->state) {
675 case SHOW_OPTION_YES:
680 if (hton->db_type <= DB_TYPE_UNKNOWN ||
681 hton->db_type >= DB_TYPE_DEFAULT ||
682 installed_htons[hton->db_type])
684 int idx= (int) DB_TYPE_FIRST_DYNAMIC;
686 while (idx < (
int) DB_TYPE_DEFAULT && installed_htons[idx])
689 if (idx == (
int) DB_TYPE_DEFAULT)
691 sql_print_warning(
"Too many storage engines!");
694 if (hton->db_type != DB_TYPE_UNKNOWN)
695 sql_print_warning(
"Storage engine '%s' has conflicting typecode. "
696 "Assigning value %d.", plugin->plugin->name, idx);
697 hton->db_type= (
enum legacy_db_type) idx;
705 DBUG_PRINT(
"plugin", (
"total_ha: %lu", total_ha));
706 for (fslot= 0; fslot < total_ha; fslot++)
708 if (!hton2plugin[fslot])
711 if (fslot < total_ha)
715 if (total_ha >= MAX_HA)
717 sql_print_error(
"Too many plugins loaded. Limit is %lu. "
718 "Failed on '%s'", (ulong) MAX_HA, plugin->name.str);
721 hton->slot= total_ha++;
723 installed_htons[hton->db_type]= hton;
724 tmp= hton->savepoint_offset;
725 hton->savepoint_offset= savepoint_alloc_size;
726 savepoint_alloc_size+= tmp;
727 hton2plugin[hton->slot]=plugin;
734 hton->state= SHOW_OPTION_DISABLED;
743 switch (hton->db_type) {
750 case DB_TYPE_PARTITION_DB:
751 partition_hton= hton;
764 if (plugin->plugin->deinit)
765 (void) plugin->plugin->deinit(NULL);
777 DBUG_ENTER(
"ha_init");
779 DBUG_ASSERT(total_ha < MAX_HA);
785 opt_using_transactions= total_ha>(ulong)opt_bin_log;
786 savepoint_alloc_size+=
sizeof(SAVEPOINT);
793 known_system_databases= ha_known_system_databases();
801 DBUG_ENTER(
"ha_end");
809 if (ha_finish_errors())
815 static my_bool dropdb_handlerton(THD *unused1,
plugin_ref plugin,
819 if (hton->state == SHOW_OPTION_YES && hton->drop_database)
820 hton->drop_database(hton, (
char *)path);
825 void ha_drop_database(
char* path)
827 plugin_foreach(NULL, dropdb_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, path);
831 static my_bool closecon_handlerton(THD *thd,
plugin_ref plugin,
839 if (hton->state == SHOW_OPTION_YES && thd_get_ha_data(thd, hton))
841 if (hton->close_connection)
842 hton->close_connection(hton, thd);
844 thd_set_ha_data(thd, hton, NULL);
856 plugin_foreach(thd, closecon_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, 0);
1168 Ha_trx_info *ha_info;
1169 DBUG_ENTER(
"trans_register_ha");
1170 DBUG_PRINT(
"enter",(
"%s", all ?
"all" :
"stmt"));
1174 trans= &thd->transaction.all;
1175 thd->server_status|= SERVER_STATUS_IN_TRANS;
1176 if (thd->tx_read_only)
1177 thd->server_status|= SERVER_STATUS_IN_TRANS_READONLY;
1178 DBUG_PRINT(
"info", (
"setting SERVER_STATUS_IN_TRANS"));
1181 trans= &thd->transaction.stmt;
1183 ha_info= thd->ha_data[ht_arg->slot].ha_info + (all ? 1 : 0);
1185 if (ha_info->is_started())
1188 ha_info->register_ha(trans, ht_arg);
1190 trans->no_2pc|=(ht_arg->prepare==0);
1191 if (thd->transaction.xid_state.xid.is_null())
1192 thd->transaction.xid_state.xid.set(thd->query_id);
1205 THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1206 Ha_trx_info *ha_info= trans->ha_list;
1207 DBUG_ENTER(
"ha_prepare");
1211 for (; ha_info; ha_info= ha_info->next())
1215 status_var_increment(thd->status_var.ha_prepare_count);
1218 if ((err= ht->prepare(ht, thd, all)))
1220 my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1221 ha_rollback_trans(thd, all);
1228 push_warning_printf(thd, Sql_condition::WARN_LEVEL_WARN,
1229 ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
1230 ha_resolve_storage_engine_name(ht));
1259 ha_check_and_coalesce_trx_read_only(THD *thd, Ha_trx_info *ha_list,
1263 unsigned rw_ha_count= 0;
1264 Ha_trx_info *ha_info;
1266 for (ha_info= ha_list; ha_info; ha_info= ha_info->next())
1268 if (ha_info->is_trx_read_write())
1273 Ha_trx_info *ha_info_all= &thd->ha_data[ha_info->ht()->slot].ha_info[1];
1274 DBUG_ASSERT(ha_info != ha_info_all);
1282 if (ha_info_all->is_started())
1283 ha_info_all->coalesce_trx_with(ha_info);
1285 else if (rw_ha_count > 1)
1326 THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
1334 bool is_real_trans= all || thd->transaction.all.ha_list == 0;
1335 Ha_trx_info *ha_info= trans->ha_list;
1336 DBUG_ENTER(
"ha_commit_trans");
1338 DBUG_PRINT(
"info", (
"all=%d thd->in_sub_stmt=%d ha_info=%p is_real_trans=%d",
1339 all, thd->in_sub_stmt, ha_info, is_real_trans));
1346 DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL ||
1347 trans == &thd->transaction.stmt);
1349 if (thd->in_sub_stmt)
1366 my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
1371 bool release_mdl=
false;
1378 DBUG_EXECUTE_IF(
"crash_commit_before", DBUG_SUICIDE(););
1382 thd->stmt_map.close_transient_cursors();
1384 rw_ha_count= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
1385 trans->rw_ha_count= rw_ha_count;
1387 rw_trans= is_real_trans && (rw_ha_count > 0);
1389 if (rw_trans && !ignore_global_read_lock)
1399 mdl_request.
init(MDL_key::COMMIT,
"",
"", MDL_INTENTION_EXCLUSIVE,
1402 DBUG_PRINT(
"debug", (
"Acquire MDL commit lock"));
1403 if (thd->mdl_context.acquire_lock(&mdl_request,
1404 thd->variables.lock_wait_timeout))
1406 ha_rollback_trans(thd, all);
1411 DEBUG_SYNC(thd,
"ha_commit_trans_after_acquire_commit_lock");
1416 !(thd->security_ctx->master_access & SUPER_ACL) &&
1419 my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--read-only");
1420 ha_rollback_trans(thd, all);
1425 if (!trans->no_2pc && (rw_ha_count > 1))
1426 error= tc_log->
prepare(thd, all);
1428 if (error || (error= tc_log->
commit(thd, all)))
1430 ha_rollback_trans(thd, all);
1434 DBUG_EXECUTE_IF(
"crash_commit_after", DBUG_SUICIDE(););
1436 if (release_mdl && mdl_request.
ticket)
1444 DBUG_PRINT(
"debug", (
"Releasing MDL commit lock"));
1445 thd->mdl_context.release_lock(mdl_request.
ticket);
1449 thd->transaction.cleanup();
1475 THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1476 Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1477 DBUG_ENTER(
"ha_commit_low");
1481 for (; ha_info; ha_info= ha_info_next)
1485 if ((err= ht->commit(ht, thd, all)))
1487 my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1490 status_var_increment(thd->status_var.ha_commit_count);
1491 ha_info_next= ha_info->next();
1496 trans->rw_ha_count= 0;
1499 #ifdef HAVE_QUERY_CACHE
1500 if (thd->transaction.changed_tables)
1501 query_cache.invalidate(thd->transaction.changed_tables);
1507 thd->transaction.cleanup();
1513 thd->transaction.flags.commit_low=
false;
1514 if (run_after_commit)
1518 (void) RUN_HOOK(transaction, after_commit, (thd, all));
1519 thd->transaction.flags.run_hooks=
false;
1525 int ha_rollback_low(THD *thd,
bool all)
1527 THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1528 Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1535 thd->stmt_map.close_transient_cursors();
1537 for (; ha_info; ha_info= ha_info_next)
1541 if ((err= ht->rollback(ht, thd, all)))
1543 my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1546 status_var_increment(thd->status_var.ha_rollback_count);
1547 ha_info_next= ha_info->next();
1552 trans->rw_ha_count= 0;
1559 if (all && thd->transaction_rollback_request &&
1560 thd->transaction.xid_state.xa_state != XA_NOTR)
1561 thd->transaction.xid_state.rm_error= thd->get_stmt_da()->sql_errno();
1563 (void) RUN_HOOK(transaction, after_rollback, (thd, all));
1568 int ha_rollback_trans(THD *thd,
bool all)
1572 THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1587 bool is_real_trans= all || thd->transaction.all.ha_list == NULL;
1588 DBUG_ENTER(
"ha_rollback_trans");
1594 DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL ||
1595 trans == &thd->transaction.stmt);
1597 if (thd->in_sub_stmt)
1607 my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
1616 thd->transaction.cleanup();
1618 thd->transaction_rollback_request= FALSE;
1637 thd->transaction.stmt.dbug_unsafe_rollback_flags(
"stmt");
1638 thd->transaction.all.dbug_unsafe_rollback_flags(
"all");
1640 if (is_real_trans && thd->transaction.all.cannot_safely_rollback() &&
1641 !thd->slave_thread && thd->killed != THD::KILL_CONNECTION)
1642 thd->transaction.push_unsafe_rollback_warnings(thd);
1652 static my_bool xacommit_handlerton(THD *unused1,
plugin_ref plugin,
1656 if (hton->state == SHOW_OPTION_YES && hton->recover)
1658 hton->commit_by_xid(hton, ((
struct xahton_st *)arg)->xid);
1664 static my_bool xarollback_handlerton(THD *unused1,
plugin_ref plugin,
1668 if (hton->state == SHOW_OPTION_YES && hton->recover)
1670 hton->rollback_by_xid(hton, ((
struct xahton_st *)arg)->xid);
1677 int ha_commit_or_rollback_by_xid(THD *thd,
XID *xid,
bool commit)
1683 plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
1684 MYSQL_STORAGE_ENGINE_PLUGIN, &xaop);
1697 static char* xid_to_str(
char *
buf,
XID *xid)
1704 uchar c=(uchar)xid->
data[i];
1706 bool is_next_dig= FALSE;
1707 if (i < XIDDATASIZE)
1709 char ch= xid->
data[i+1];
1710 is_next_dig= (ch >=
'0' && ch <=
'9');
1721 if (c < 32 || c > 126)
1729 if (c > 077 || is_next_dig)
1730 *s++=_dig_vec_lower[c >> 6];
1731 if (c > 007 || is_next_dig)
1732 *s++=_dig_vec_lower[(c >> 3) & 7];
1733 *s++=_dig_vec_lower[c & 7];
1737 if (c ==
'\'' || c ==
'\\')
1766 int len, found_foreign_xids, found_my_xids;
1772 static my_bool xarecover_handlerton(THD *unused,
plugin_ref plugin,
1779 if (hton->state == SHOW_OPTION_YES && hton->recover)
1781 while ((got= hton->recover(hton, info->list, info->len)) > 0 )
1783 sql_print_information(
"Found %d prepared transaction(s) in %s",
1784 got, ha_resolve_storage_engine_name(hton));
1785 for (
int i=0; i < got; i ++)
1787 my_xid x=info->list[
i].get_my_xid();
1791 char buf[XIDDATASIZE*4+6];
1792 sql_print_information(
"ignore xid %s", xid_to_str(buf, info->list+i));
1794 xid_cache_insert(info->list+i, XA_PREPARED);
1795 info->found_foreign_xids++;
1800 info->found_my_xids++;
1804 if (info->commit_list ?
1805 my_hash_search(info->commit_list, (uchar *)&x,
sizeof(x)) != 0 :
1806 tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
1809 char buf[XIDDATASIZE*4+6];
1810 sql_print_information(
"commit xid %s", xid_to_str(buf, info->list+i));
1812 hton->commit_by_xid(hton, info->list+i);
1817 char buf[XIDDATASIZE*4+6];
1818 sql_print_information(
"rollback xid %s",
1819 xid_to_str(buf, info->list+i));
1821 hton->rollback_by_xid(hton, info->list+i);
1824 if (got < info->len)
1831 int ha_recover(
HASH *commit_list)
1834 DBUG_ENTER(
"ha_recover");
1835 info.found_foreign_xids= info.found_my_xids= 0;
1836 info.commit_list= commit_list;
1837 info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
1841 DBUG_ASSERT(info.commit_list==0 || tc_heuristic_recover==0);
1843 DBUG_ASSERT(info.dry_run || total_ha_2pc>(ulong)opt_bin_log);
1845 if (total_ha_2pc <= (ulong)opt_bin_log)
1848 if (info.commit_list)
1849 sql_print_information(
"Starting crash recovery...");
1851 #ifndef WILL_BE_DELETED_LATER
1856 DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1);
1857 tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK;
1861 for (info.len= MAX_XID_LIST_SIZE ;
1862 info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1864 info.list=(
XID *)my_malloc(info.len*
sizeof(
XID), MYF(0));
1868 sql_print_error(ER(ER_OUTOFMEMORY),
1869 static_cast<int>(info.len*
sizeof(
XID)));
1873 plugin_foreach(NULL, xarecover_handlerton,
1874 MYSQL_STORAGE_ENGINE_PLUGIN, &info);
1877 if (info.found_foreign_xids)
1878 sql_print_warning(
"Found %d prepared XA transactions",
1879 info.found_foreign_xids);
1880 if (info.dry_run && info.found_my_xids)
1882 sql_print_error(
"Found %d prepared transactions! It means that mysqld was "
1883 "not shut down properly last time and critical recovery "
1884 "information (last binlog or %s file) was manually deleted "
1885 "after a crash. You have to start mysqld with "
1886 "--tc-heuristic-recover switch to commit or rollback "
1887 "pending transactions.",
1888 info.found_my_xids, opt_tc_log_file);
1891 if (info.commit_list)
1892 sql_print_information(
"Crash recovery finished.");
1910 DBUG_ENTER(
"mysql_xa_recover");
1912 field_list.push_back(
new Item_int(NAME_STRING(
"formatID"), 0, MY_INT32_NUM_DECIMAL_DIGITS));
1913 field_list.push_back(
new Item_int(NAME_STRING(
"gtrid_length"), 0, MY_INT32_NUM_DECIMAL_DIGITS));
1914 field_list.push_back(
new Item_int(NAME_STRING(
"bqual_length"), 0, MY_INT32_NUM_DECIMAL_DIGITS));
1918 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1922 while ((xs= (XID_STATE*) my_hash_element(&xid_cache, i++)))
1924 if (xs->xa_state==XA_PREPARED)
1926 protocol->prepare_for_resend();
1927 protocol->store_longlong((longlong)xs->xid.formatID, FALSE);
1928 protocol->store_longlong((longlong)xs->xid.gtrid_length, FALSE);
1929 protocol->store_longlong((longlong)xs->xid.bqual_length, FALSE);
1930 protocol->
store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
1932 if (protocol->write())
1974 for (info= thd->transaction.stmt.ha_list; info; info= info->next())
1977 if (hton && hton->release_temporary_latches)
1978 hton->release_temporary_latches(hton, thd);
1983 int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
1986 THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1987 &thd->transaction.all);
1988 Ha_trx_info *ha_info, *ha_info_next;
1990 DBUG_ENTER(
"ha_rollback_to_savepoint");
1993 trans->rw_ha_count= 0;
1998 for (ha_info= sv->ha_list; ha_info; ha_info= ha_info->next())
2003 DBUG_ASSERT(ht->savepoint_set != 0);
2004 if ((err= ht->savepoint_rollback(ht, thd,
2005 (uchar *)(sv+1)+ht->savepoint_offset)))
2007 my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
2010 status_var_increment(thd->status_var.ha_savepoint_rollback_count);
2011 trans->no_2pc|= ht->prepare == 0;
2017 for (ha_info= trans->ha_list; ha_info != sv->ha_list;
2018 ha_info= ha_info_next)
2022 if ((err= ht->rollback(ht, thd, !thd->in_sub_stmt)))
2024 my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
2027 status_var_increment(thd->status_var.ha_rollback_count);
2028 ha_info_next= ha_info->next();
2031 trans->ha_list= sv->ha_list;
2035 int ha_prepare_low(THD *thd,
bool all)
2038 THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
2039 Ha_trx_info *ha_info= trans->ha_list;
2040 DBUG_ENTER(
"ha_prepare_low");
2044 for (; ha_info && !error; ha_info= ha_info->next())
2053 if (!ha_info->is_trx_read_write())
2055 if ((err= ht->prepare(ht, thd, all)))
2057 my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
2060 status_var_increment(thd->status_var.ha_prepare_count);
2062 DBUG_EXECUTE_IF(
"crash_commit_after_prepare", DBUG_SUICIDE(););
2077 THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
2078 &thd->transaction.all);
2079 Ha_trx_info *ha_info= trans->ha_list;
2080 DBUG_ENTER(
"ha_savepoint");
2082 for (; ha_info; ha_info= ha_info->next())
2087 if (! ht->savepoint_set)
2089 my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0),
"SAVEPOINT");
2093 if ((err= ht->savepoint_set(ht, thd, (uchar *)(sv+1)+ht->savepoint_offset)))
2095 my_error(ER_GET_ERRNO, MYF(0), err);
2098 status_var_increment(thd->status_var.ha_savepoint_count);
2104 sv->ha_list= trans->ha_list;
2109 int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
2112 Ha_trx_info *ha_info= sv->ha_list;
2113 DBUG_ENTER(
"ha_release_savepoint");
2115 for (; ha_info; ha_info= ha_info->next())
2121 if (!ht->savepoint_release)
2123 if ((err= ht->savepoint_release(ht, thd,
2124 (uchar *)(sv+1) + ht->savepoint_offset)))
2126 my_error(ER_GET_ERRNO, MYF(0), err);
2134 static my_bool snapshot_handlerton(THD *thd,
plugin_ref plugin,
2138 if (hton->state == SHOW_OPTION_YES &&
2139 hton->start_consistent_snapshot)
2141 hton->start_consistent_snapshot(hton, thd);
2142 *((
bool *)arg)=
false;
2147 int ha_start_consistent_snapshot(THD *thd)
2151 plugin_foreach(thd, snapshot_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &warn);
2158 push_warning(thd, Sql_condition::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
2159 "This MySQL server does not support any "
2160 "consistent-read capable storage engine");
2165 static my_bool flush_handlerton(THD *thd,
plugin_ref plugin,
2169 if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
2170 hton->flush_logs(hton))
2178 if (db_type == NULL)
2180 if (plugin_foreach(NULL, flush_handlerton,
2181 MYSQL_STORAGE_ENGINE_PLUGIN, 0))
2186 if (db_type->state != SHOW_OPTION_YES ||
2187 (db_type->flush_logs && db_type->flush_logs(db_type)))
2220 if (lower_case_table_names != 2 || (file->
ha_table_flags() & HA_FILE_BASED))
2223 for (i= 0; i <= mysql_tmpdir_list.max; i++)
2225 if (is_prefix(path, mysql_tmpdir_list.list[i]))
2230 if (tmp_path != path)
2231 strmov(tmp_path, path);
2237 my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
2251 virtual bool handle_condition(THD *thd,
2253 const char* sqlstate,
2254 Sql_condition::enum_warning_level
level,
2257 char buff[MYSQL_ERRMSG_SIZE];
2262 Ha_delete_table_error_handler::
2263 handle_condition(THD *,
2266 Sql_condition::enum_warning_level,
2272 strmake(buff, msg,
sizeof(buff)-1);
2282 const char *db,
const char *alias,
bool generate_warning)
2285 char tmp_path[FN_REFLEN];
2289 DBUG_ENTER(
"ha_delete_table");
2291 memset(&dummy_table, 0,
sizeof(dummy_table));
2292 memset(&dummy_share, 0,
sizeof(dummy_share));
2293 dummy_table.s= &dummy_share;
2296 if (table_type == NULL ||
2297 ! (file=get_new_handler((
TABLE_SHARE*)0, thd->mem_root, table_type)))
2298 DBUG_RETURN(ENOENT);
2312 dummy_share.path.str= (
char*) path;
2313 dummy_share.path.length= strlen(path);
2314 dummy_share.db.str= (
char*) db;
2315 dummy_share.db.length= strlen(db);
2316 dummy_share.table_name.str= (
char*) alias;
2317 dummy_share.table_name.length= strlen(alias);
2318 dummy_table.alias= alias;
2320 file->change_table_ptr(&dummy_table, &dummy_share);
2322 thd->push_internal_handler(&ha_delete_table_error_handler);
2325 thd->pop_internal_handler();
2331 push_warning(thd, Sql_condition::WARN_LEVEL_WARN, error,
2332 ha_delete_table_error_handler.buff);
2336 #ifdef HAVE_PSI_TABLE_INTERFACE
2337 if (likely(error == 0))
2341 (temp_table, db, strlen(db), alias, strlen(alias));
2353 handler *new_handler= get_new_handler(table->s, mem_root, ht);
2357 if (new_handler->set_ha_share_ref(ha_share))
2365 if (!(new_handler->ref= (uchar*) alloc_root(mem_root,
2372 if (new_handler->
ha_open(table, name, table->db_stat,
2373 HA_OPEN_IGNORE_IF_LOCKED))
2385 void handler::ha_statistic_increment(ulonglong
SSV::*
offset)
const
2387 status_var_increment(table->in_use->status_var.*offset);
2390 void **handler::ha_data(THD *thd)
const
2392 return thd_ha_data(thd, ht);
2395 THD *handler::ha_thd(
void)
const
2397 DBUG_ASSERT(!table || !table->in_use || table->in_use == current_thd);
2398 return (table && table->in_use) ? table->in_use : current_thd;
2401 void handler::unbind_psi()
2403 #ifdef HAVE_PSI_TABLE_INTERFACE
2404 DBUG_ASSERT(m_lock_type == F_UNLCK);
2405 DBUG_ASSERT(inited == NONE);
2410 PSI_TABLE_CALL(unbind_table)(
m_psi);
2414 void handler::rebind_psi()
2416 #ifdef HAVE_PSI_TABLE_INTERFACE
2417 DBUG_ASSERT(m_lock_type == F_UNLCK);
2418 DBUG_ASSERT(inited == NONE);
2424 m_psi= PSI_TABLE_CALL(rebind_table)(share_psi,
this,
m_psi);
2430 return share->
m_psi;
2444 DBUG_ENTER(
"handler::ha_open");
2446 (
"name: %s db_type: %d db_stat: %d mode: %d lock_test: %d",
2447 name, ht->db_type, table_arg->db_stat, mode,
2451 DBUG_ASSERT(table->s == table_share);
2452 DBUG_ASSERT(m_lock_type == F_UNLCK);
2453 DBUG_PRINT(
"info", (
"old m_lock_type: %d F_UNLCK %d", m_lock_type, F_UNLCK));
2454 DBUG_ASSERT(alloc_root_inited(&table->
mem_root));
2456 if ((error=open(name,mode,test_if_locked)))
2458 if ((error == EACCES || error == EROFS) && mode == O_RDWR &&
2459 (table->db_stat & HA_TRY_READ_ONLY))
2461 table->db_stat|=HA_READ_ONLY;
2462 error=open(name,O_RDONLY,test_if_locked);
2468 DBUG_PRINT(
"error",(
"error: %d errno: %d",error,errno));
2472 DBUG_ASSERT(
m_psi == NULL);
2473 DBUG_ASSERT(table_share != NULL);
2474 #ifdef HAVE_PSI_TABLE_INTERFACE
2480 if (!(test_if_locked & HA_OPEN_NO_PSI_CALL))
2487 if (table->s->db_options_in_use & HA_OPTION_READ_ONLY_DATA)
2488 table->db_stat|=HA_READ_ONLY;
2489 (void)
extra(HA_EXTRA_NO_READCHECK);
2492 if (!ref && !(ref= (uchar*) alloc_root(&table->
mem_root,
2496 error=HA_ERR_OUT_OF_MEM;
2500 cached_table_flags= table_flags();
2512 DBUG_ENTER(
"handler::ha_close");
2513 #ifdef HAVE_PSI_TABLE_INTERFACE
2514 PSI_TABLE_CALL(close_table)(
m_psi);
2518 DBUG_ASSERT(
m_psi == NULL);
2519 DBUG_ASSERT(m_lock_type == F_UNLCK);
2520 DBUG_ASSERT(inited == NONE);
2521 DBUG_RETURN(close());
2538 DBUG_EXECUTE_IF(
"ha_index_init_fail",
return HA_ERR_TABLE_DEF_CHANGED;);
2540 DBUG_ENTER(
"ha_index_init");
2541 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2542 m_lock_type != F_UNLCK);
2543 DBUG_ASSERT(inited == NONE);
2544 if (!(result= index_init(idx, sorted)))
2547 DBUG_RETURN(result);
2561 DBUG_ENTER(
"ha_index_end");
2563 DBUG_ASSERT(table->open_by_handler ||
2564 table_share->tmp_table != NO_TMP_TABLE ||
2565 m_lock_type != F_UNLCK);
2566 DBUG_ASSERT(inited == INDEX);
2569 DBUG_RETURN(index_end());
2586 DBUG_EXECUTE_IF(
"ha_rnd_init_fail",
return HA_ERR_TABLE_DEF_CHANGED;);
2588 DBUG_ENTER(
"ha_rnd_init");
2589 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2590 m_lock_type != F_UNLCK);
2591 DBUG_ASSERT(inited == NONE || (inited == RND && scan));
2592 inited= (result= rnd_init(scan)) ? NONE : RND;
2594 DBUG_RETURN(result);
2608 DBUG_ENTER(
"ha_rnd_end");
2610 DBUG_ASSERT(table->open_by_handler ||
2611 table_share->tmp_table != NO_TMP_TABLE ||
2612 m_lock_type != F_UNLCK);
2613 DBUG_ASSERT(inited == RND);
2616 DBUG_RETURN(rnd_end());
2633 DBUG_ENTER(
"handler::ha_rnd_next");
2634 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2635 m_lock_type != F_UNLCK);
2636 DBUG_ASSERT(inited == RND);
2640 DBUG_RETURN(result);
2658 DBUG_ENTER(
"handler::ha_rnd_pos");
2659 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2660 m_lock_type != F_UNLCK);
2665 { result=
rnd_pos(buf, pos); })
2666 DBUG_RETURN(result);
2694 key_part_map keypart_map,
2695 enum ha_rkey_function find_flag)
2698 DBUG_ENTER(
"handler::ha_index_read_map");
2699 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2700 m_lock_type != F_UNLCK);
2701 DBUG_ASSERT(inited == INDEX);
2705 DBUG_RETURN(result);
2708 int handler::ha_index_read_last_map(uchar *buf,
const uchar *key,
2709 key_part_map keypart_map)
2712 DBUG_ENTER(
"handler::ha_index_read_last_map");
2713 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2714 m_lock_type != F_UNLCK);
2715 DBUG_ASSERT(inited == INDEX);
2719 DBUG_RETURN(result);
2730 key_part_map keypart_map,
2731 enum ha_rkey_function find_flag)
2734 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2735 m_lock_type != F_UNLCK);
2736 DBUG_ASSERT(end_range == NULL);
2758 DBUG_ENTER(
"handler::ha_index_next");
2759 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2760 m_lock_type != F_UNLCK);
2761 DBUG_ASSERT(inited == INDEX);
2765 DBUG_RETURN(result);
2783 DBUG_ENTER(
"handler::ha_index_prev");
2784 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2785 m_lock_type != F_UNLCK);
2786 DBUG_ASSERT(inited == INDEX);
2790 DBUG_RETURN(result);
2808 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2809 m_lock_type != F_UNLCK);
2810 DBUG_ASSERT(inited == INDEX);
2832 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2833 m_lock_type != F_UNLCK);
2834 DBUG_ASSERT(inited == INDEX);
2858 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2859 m_lock_type != F_UNLCK);
2860 DBUG_ASSERT(inited == INDEX);
2883 enum ha_rkey_function find_flag)
2886 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2887 m_lock_type != F_UNLCK);
2888 DBUG_ASSERT(inited == INDEX);
2891 { result= index_read(buf, key, key_len, find_flag); })
2912 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
2913 m_lock_type != F_UNLCK);
2914 DBUG_ASSERT(inited == INDEX);
2917 { result= index_read_last(buf, key, key_len); })
2931 DBUG_ENTER(
"handler::read_first_row");
2933 ha_statistic_increment(&SSV::ha_read_first_count);
2940 if (
stats.deleted < 10 || primary_key >= MAX_KEY ||
2941 !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
2945 while ((error=
rnd_next(buf)) == HA_ERR_RECORD_DELETED)
2981 const ulonglong save_nr= nr;
2983 if (variables->auto_increment_increment == 1)
2987 nr= (((nr+ variables->auto_increment_increment -
2988 variables->auto_increment_offset)) /
2989 (ulonglong) variables->auto_increment_increment);
2990 nr= (nr* (ulonglong) variables->auto_increment_increment +
2991 variables->auto_increment_offset);
2994 if (unlikely(nr <= save_nr))
2995 return ULONGLONG_MAX;
3001 void handler::adjust_next_insert_id_after_explicit_value(ulonglong nr)
3031 if (unlikely(nr < variables->auto_increment_offset))
3038 DBUG_PRINT(
"info",(
"auto_increment: nr: %lu cannot honour "
3039 "auto_increment_offset: %lu",
3040 (ulong) nr, variables->auto_increment_offset));
3043 if (variables->auto_increment_increment == 1)
3045 nr= (((nr - variables->auto_increment_offset)) /
3046 (ulonglong) variables->auto_increment_increment);
3047 return (nr * (ulonglong) variables->auto_increment_increment +
3048 variables->auto_increment_offset);
3127 #define AUTO_INC_DEFAULT_NB_ROWS 1 // Some prefer 1024 here
3128 #define AUTO_INC_DEFAULT_NB_MAX_BITS 16
3129 #define AUTO_INC_DEFAULT_NB_MAX ((1 << AUTO_INC_DEFAULT_NB_MAX_BITS) - 1)
3131 int handler::update_auto_increment()
3133 ulonglong nr, nb_reserved_values;
3135 THD *thd= table->in_use;
3137 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
3138 m_lock_type != F_UNLCK);
3139 DBUG_ENTER(
"handler::update_auto_increment");
3147 if ((nr=
table->next_number_field->val_int()) != 0 ||
3148 (
table->auto_increment_field_not_null &&
3149 thd->variables.sql_mode & MODE_NO_AUTO_VALUE_ON_ZERO))
3157 adjust_next_insert_id_after_explicit_value(nr);
3166 thd->auto_inc_intervals_forced.get_next();
3169 nr= forced->minimum();
3170 nb_reserved_values= forced->values();
3178 ulonglong nb_desired_values;
3193 nb_desired_values= estimation_rows_to_insert;
3195 (thd->lex->many_values.elements > 0))
3202 nb_desired_values= thd->lex->many_values.elements;
3211 set_if_smaller(nb_desired_values, AUTO_INC_DEFAULT_NB_MAX);
3214 nb_desired_values= AUTO_INC_DEFAULT_NB_MAX;
3218 variables->auto_increment_increment,
3219 nb_desired_values, &nr,
3220 &nb_reserved_values);
3221 if (nr == ULONGLONG_MAX)
3222 DBUG_RETURN(HA_ERR_AUTOINC_READ_FAILED);
3235 if (
table->s->next_number_keypart == 0)
3248 DBUG_PRINT(
"info",(
"auto_increment: special not-first-in-index"));
3252 if (unlikely(nr == ULONGLONG_MAX))
3253 DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
3255 DBUG_PRINT(
"info",(
"auto_increment: %lu", (ulong) nr));
3257 if (unlikely(
table->next_number_field->store((longlong) nr, TRUE)))
3262 if (thd->killed == THD::KILL_BAD_DATA)
3263 DBUG_RETURN(HA_ERR_AUTOINC_ERANGE);
3274 if (unlikely(
table->next_number_field->store((longlong) nr, TRUE)))
3275 nr=
table->next_number_field->val_int();
3280 variables->auto_increment_increment);
3283 if (mysql_bin_log.is_open() && !thd->is_current_stmt_binlog_format_row())
3286 variables->auto_increment_increment);
3322 DBUG_ENTER(
"column_bitmaps_signal");
3323 DBUG_PRINT(
"info", (
"read_set: 0x%lx write_set: 0x%lx", (
long)
table->read_set,
3324 (
long)
table->write_set));
3346 ulonglong nb_desired_values,
3347 ulonglong *first_value,
3348 ulonglong *nb_reserved_values)
3352 DBUG_ENTER(
"handler::get_auto_increment");
3354 (void)
extra(HA_EXTRA_KEYREAD);
3355 table->mark_columns_used_by_index_no_reset(
table->s->next_number_index,
3363 *first_value= ULONGLONG_MAX;
3367 if (
table->s->next_number_keypart == 0)
3375 *nb_reserved_values= ULONGLONG_MAX;
3379 uchar key[MAX_KEY_LENGTH];
3380 key_copy(key,
table->record[0],
3381 table->key_info +
table->s->next_number_index,
3382 table->s->next_number_key_offset);
3384 make_prev_keypart_map(
table->s->next_number_keypart),
3385 HA_READ_PREFIX_LAST);
3392 *nb_reserved_values= 1;
3397 if (error == HA_ERR_END_OF_FILE || error == HA_ERR_KEY_NOT_FOUND)
3409 nr= ((ulonglong)
table->next_number_field->
3410 val_int_offset(
table->s->rec_buff_length)+1);
3412 (void)
extra(HA_EXTRA_NO_KEYREAD);
3418 void handler::ha_release_auto_increment()
3420 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
3421 m_lock_type != F_UNLCK ||
3423 release_auto_increment();
3434 table->in_use->auto_inc_intervals_forced.empty();
3454 char key_buff[MAX_KEY_LENGTH];
3455 String str(key_buff,
sizeof(key_buff),system_charset_info);
3460 str.copy(
"", 0, system_charset_info);
3461 my_printf_error(ER_DUP_ENTRY, msg, errflag, str.c_ptr(),
"*UNKNOWN*");
3466 key_unpack(&str,table, key);
3467 uint max_length=MYSQL_ERRMSG_SIZE-(uint) strlen(msg);
3468 if (str.length() >= max_length)
3470 str.length(max_length-4);
3471 str.append(STRING_WITH_LEN(
"..."));
3473 my_printf_error(ER_DUP_ENTRY, msg, errflag, str.c_ptr_safe(), key->
name);
3502 DBUG_ENTER(
"handler::print_error");
3503 DBUG_PRINT(
"enter",(
"error: %d",error));
3505 int textno=ER_GET_ERRNO;
3508 textno=ER_OPEN_AS_READONLY;
3511 textno=ER_FILE_USED;
3515 char errbuf[MYSYS_STRERROR_SIZE];
3516 textno=ER_FILE_NOT_FOUND;
3517 my_error(textno, errflag, table_share->table_name.str,
3518 error, my_strerror(errbuf,
sizeof(errbuf), error));
3521 case HA_ERR_KEY_NOT_FOUND:
3522 case HA_ERR_NO_ACTIVE_RECORD:
3523 case HA_ERR_RECORD_DELETED:
3524 case HA_ERR_END_OF_FILE:
3525 textno=ER_KEY_NOT_FOUND;
3527 case HA_ERR_WRONG_MRG_TABLE_DEF:
3528 textno=ER_WRONG_MRG_TABLE;
3530 case HA_ERR_FOUND_DUPP_KEY:
3533 if ((
int) key_nr >= 0)
3536 key_nr == MAX_KEY ? NULL : &
table->key_info[key_nr],
3543 case HA_ERR_FOREIGN_DUPLICATE_KEY:
3545 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
3546 m_lock_type != F_UNLCK);
3548 char rec_buf[MAX_KEY_LENGTH];
3549 String rec(rec_buf,
sizeof(rec_buf), system_charset_info);
3556 key_unpack(&rec,
table, &
table->key_info[0]);
3558 char child_table_name[NAME_LEN + 1];
3559 char child_key_name[NAME_LEN + 1];
3561 child_key_name,
sizeof(child_key_name)))
3563 my_error(ER_FOREIGN_DUPLICATE_KEY_WITH_CHILD_INFO, errflag,
3564 table_share->table_name.str, rec.c_ptr_safe(),
3565 child_table_name, child_key_name);
3569 my_error(ER_FOREIGN_DUPLICATE_KEY_WITHOUT_CHILD_INFO, errflag,
3570 table_share->table_name.str, rec.c_ptr_safe());
3574 case HA_ERR_NULL_IN_SPATIAL:
3575 my_error(ER_CANT_CREATE_GEOMETRY_OBJECT, errflag);
3577 case HA_ERR_FOUND_DUPP_UNIQUE:
3578 textno=ER_DUP_UNIQUE;
3580 case HA_ERR_RECORD_CHANGED:
3581 textno=ER_CHECKREAD;
3583 case HA_ERR_CRASHED:
3584 textno=ER_NOT_KEYFILE;
3586 case HA_ERR_WRONG_IN_RECORD:
3587 textno= ER_CRASHED_ON_USAGE;
3589 case HA_ERR_CRASHED_ON_USAGE:
3590 textno=ER_CRASHED_ON_USAGE;
3592 case HA_ERR_NOT_A_TABLE:
3595 case HA_ERR_CRASHED_ON_REPAIR:
3596 textno=ER_CRASHED_ON_REPAIR;
3598 case HA_ERR_OUT_OF_MEM:
3599 textno=ER_OUT_OF_RESOURCES;
3601 case HA_ERR_WRONG_COMMAND:
3602 textno=ER_ILLEGAL_HA;
3604 case HA_ERR_OLD_FILE:
3605 textno=ER_OLD_KEYFILE;
3607 case HA_ERR_UNSUPPORTED:
3608 textno=ER_UNSUPPORTED_EXTENSION;
3610 case HA_ERR_RECORD_FILE_FULL:
3611 case HA_ERR_INDEX_FILE_FULL:
3613 textno=ER_RECORD_FILE_FULL;
3615 errflag|= ME_NOREFRESH;
3618 case HA_ERR_LOCK_WAIT_TIMEOUT:
3619 textno=ER_LOCK_WAIT_TIMEOUT;
3621 case HA_ERR_LOCK_TABLE_FULL:
3622 textno=ER_LOCK_TABLE_FULL;
3624 case HA_ERR_LOCK_DEADLOCK:
3625 textno=ER_LOCK_DEADLOCK;
3627 case HA_ERR_READ_ONLY_TRANSACTION:
3628 textno=ER_READ_ONLY_TRANSACTION;
3630 case HA_ERR_CANNOT_ADD_FOREIGN:
3631 textno=ER_CANNOT_ADD_FOREIGN;
3633 case HA_ERR_ROW_IS_REFERENCED:
3637 my_error(ER_ROW_IS_REFERENCED_2, errflag, str.c_ptr_safe());
3640 case HA_ERR_NO_REFERENCED_ROW:
3644 my_error(ER_NO_REFERENCED_ROW_2, errflag, str.c_ptr_safe());
3647 case HA_ERR_TABLE_DEF_CHANGED:
3648 textno=ER_TABLE_DEF_CHANGED;
3650 case HA_ERR_NO_SUCH_TABLE:
3651 my_error(ER_NO_SUCH_TABLE, errflag, table_share->db.str,
3652 table_share->table_name.str);
3654 case HA_ERR_RBR_LOGGING_FAILED:
3655 textno= ER_BINLOG_ROW_LOGGING_FAILED;
3657 case HA_ERR_DROP_INDEX_FK:
3659 const char *ptr=
"???";
3661 if ((
int) key_nr >= 0)
3662 ptr=
table->key_info[key_nr].name;
3663 my_error(ER_DROP_INDEX_FK, errflag, ptr);
3666 case HA_ERR_TABLE_NEEDS_UPGRADE:
3667 textno=ER_TABLE_NEEDS_UPGRADE;
3669 case HA_ERR_NO_PARTITION_FOUND:
3670 textno=ER_WRONG_PARTITION_NAME;
3672 case HA_ERR_TABLE_READONLY:
3673 textno= ER_OPEN_AS_READONLY;
3675 case HA_ERR_AUTOINC_READ_FAILED:
3676 textno= ER_AUTOINC_READ_FAILED;
3678 case HA_ERR_AUTOINC_ERANGE:
3679 textno= ER_WARN_DATA_OUT_OF_RANGE;
3681 case HA_ERR_TOO_MANY_CONCURRENT_TRXS:
3682 textno= ER_TOO_MANY_CONCURRENT_TRXS;
3684 case HA_ERR_INDEX_COL_TOO_LONG:
3685 textno= ER_INDEX_COLUMN_TOO_LONG;
3687 case HA_ERR_NOT_IN_LOCK_PARTITIONS:
3688 textno=ER_ROW_DOES_NOT_MATCH_GIVEN_PARTITION_SET;
3690 case HA_ERR_INDEX_CORRUPT:
3691 textno= ER_INDEX_CORRUPT;
3693 case HA_ERR_UNDO_REC_TOO_BIG:
3694 textno= ER_UNDO_RECORD_TOO_BIG;
3696 case HA_ERR_TABLE_IN_FK_CHECK:
3697 textno= ER_TABLE_IN_FK_CHECK;
3699 case HA_WRONG_CREATE_OPTION:
3700 textno= ER_ILLEGAL_HA;
3702 case HA_ERR_TOO_MANY_FIELDS:
3703 textno= ER_TOO_MANY_FIELDS;
3705 case HA_ERR_INNODB_READ_ONLY:
3706 textno= ER_INNODB_READ_ONLY;
3712 bool temporary= FALSE;
3715 if (!str.is_empty())
3719 my_error(ER_GET_TEMPORARY_ERRMSG, errflag, error, str.ptr(), engine);
3721 my_error(ER_GET_ERRMSG, errflag, error, str.ptr(), engine);
3724 my_error(ER_GET_ERRNO,errflag,error);
3728 if (textno != ER_FILE_NOT_FOUND)
3729 my_error(textno, errflag, table_share->table_name.str, error);
3760 ulong mysql_version=
table->s->mysql_version;
3762 if (mysql_version < 50124)
3765 KEY *key_end= key +
table->s->keys;
3766 for (; key < key_end; key++)
3770 for (; key_part < key_part_end; key_part++)
3772 if (!key_part->fieldnr)
3774 Field *field=
table->field[key_part->fieldnr - 1];
3775 uint cs_number= field->charset()->number;
3776 if ((mysql_version < 50048 &&
3784 cs_number == 26)) ||
3785 (mysql_version < 50124 &&
3788 return HA_ADMIN_NEEDS_UPGRADE;
3796 int handler::ha_check_for_upgrade(
HA_CHECK_OPT *check_opt)
3799 KEY *keyinfo, *keyend;
3802 if (!
table->s->mysql_version)
3805 keyinfo=
table->key_info;
3807 for (; keyinfo < keyend; keyinfo++)
3809 keypart= keyinfo->key_part;
3811 for (; keypart < keypartend; keypart++)
3813 if (!keypart->fieldnr)
3815 Field *field=
table->field[keypart->fieldnr-1];
3816 if (field->type() == MYSQL_TYPE_BLOB)
3818 if (check_opt->sql_flags & TT_FOR_UPGRADE)
3819 check_opt->flags= T_MEDIUM;
3820 return HA_ADMIN_NEEDS_CHECK;
3825 if (
table->s->frm_version != FRM_VER_TRUE_VARCHAR)
3826 return HA_ADMIN_NEEDS_ALTER;
3831 return check_for_upgrade(check_opt);
3835 int handler::check_old_types()
3839 for (field=
table->field; (*field); field++)
3841 if (
table->s->mysql_version == 0)
3844 if ((*field)->type() == MYSQL_TYPE_NEWDECIMAL)
3846 return HA_ADMIN_NEEDS_ALTER;
3848 if ((*field)->type() == MYSQL_TYPE_VAR_STRING)
3850 return HA_ADMIN_NEEDS_ALTER;
3853 if ((*field)->type() == MYSQL_TYPE_YEAR && (*field)->field_length == 2)
3854 return HA_ADMIN_NEEDS_ALTER;
3862 char path[FN_REFLEN];
3865 DBUG_ENTER(
"update_frm_version");
3873 if (table->s->mysql_version == MYSQL_VERSION_ID)
3876 strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
3879 path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
3883 int4store(version, MYSQL_VERSION_ID);
3888 table->s->mysql_version= MYSQL_VERSION_ID;
3893 DBUG_RETURN(result);
3904 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
3905 m_lock_type != F_UNLCK);
3906 DBUG_ENTER(
"handler::get_dup_key");
3907 table->file->errkey = (uint) -1;
3908 if (error == HA_ERR_FOUND_DUPP_KEY ||
3909 error == HA_ERR_FOUND_DUPP_UNIQUE || error == HA_ERR_NULL_IN_SPATIAL ||
3910 error == HA_ERR_DROP_INDEX_FK)
3911 table->file->info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
3912 DBUG_RETURN(table->file->errkey);
3935 int enoent_or_zero= ENOENT;
3936 char buff[FN_REFLEN];
3937 DBUG_ASSERT(m_lock_type == F_UNLCK);
3939 for (
const char **ext=
bas_ext(); *ext ; ext++)
3941 fn_format(buff, name,
"", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
3944 if (my_errno != ENOENT)
3952 saved_error= my_errno;
3957 error= enoent_or_zero;
3959 return saved_error ? saved_error : error;
3966 const char **ext, **start_ext;
3968 for (ext= start_ext; *ext ; ext++)
3970 if (rename_file_ext(from, to, *ext))
3972 if ((error=my_errno) != ENOENT)
3980 for (; ext >= start_ext; ext--)
3981 rename_file_ext(to, from, *ext);
3987 void handler::drop_table(
const char *name)
4012 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4013 m_lock_type != F_UNLCK);
4015 if ((table->s->mysql_version >= MYSQL_VERSION_ID) &&
4016 (check_opt->sql_flags & TT_FOR_UPGRADE))
4019 if (table->s->mysql_version < MYSQL_VERSION_ID)
4021 if ((error= check_old_types()))
4023 error= ha_check_for_upgrade(check_opt);
4024 if (error && (error != HA_ADMIN_NEEDS_CHECK))
4026 if (!error && (check_opt->sql_flags & TT_FOR_UPGRADE))
4029 if ((error= check(thd, check_opt)))
4032 if (table->file !=
this)
4034 return update_frm_version(table);
4044 handler::mark_trx_read_write()
4046 Ha_trx_info *ha_info= &ha_thd()->ha_data[ht->slot].ha_info[0];
4055 if (ha_info->is_started())
4057 DBUG_ASSERT(has_transactions());
4062 if (table_share == NULL || table_share->tmp_table == NO_TMP_TABLE)
4063 ha_info->set_trx_read_write();
4077 mark_trx_read_write();
4079 result= repair(thd, check_opt);
4080 DBUG_ASSERT(result == HA_ADMIN_NOT_IMPLEMENTED ||
4083 if (result == HA_ADMIN_OK)
4084 result= update_frm_version(table);
4099 DBUG_ENTER(
"handler::ha_start_bulk_insert");
4100 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4101 m_lock_type == F_WRLCK);
4102 estimation_rows_to_insert= rows;
4103 start_bulk_insert(rows);
4118 DBUG_ENTER(
"handler::ha_end_bulk_insert");
4119 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4120 m_lock_type == F_WRLCK);
4121 estimation_rows_to_insert= 0;
4122 DBUG_RETURN(end_bulk_insert());
4134 uint *dup_key_found)
4136 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4137 m_lock_type == F_WRLCK);
4138 mark_trx_read_write();
4153 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4154 m_lock_type == F_WRLCK);
4155 mark_trx_read_write();
4170 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4171 m_lock_type == F_WRLCK);
4172 mark_trx_read_write();
4187 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4188 m_lock_type == F_WRLCK);
4189 mark_trx_read_write();
4204 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4205 m_lock_type == F_WRLCK);
4206 mark_trx_read_write();
4208 return optimize(thd, check_opt);
4221 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4222 m_lock_type != F_UNLCK);
4223 mark_trx_read_write();
4225 return analyze(thd, check_opt);
4238 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4239 m_lock_type == F_UNLCK);
4240 mark_trx_read_write();
4242 return check_and_repair(thd);
4255 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4256 m_lock_type != F_UNLCK);
4257 mark_trx_read_write();
4259 return disable_indexes(mode);
4272 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4273 m_lock_type != F_UNLCK);
4274 mark_trx_read_write();
4276 return enable_indexes(mode);
4289 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4290 m_lock_type == F_WRLCK);
4291 mark_trx_read_write();
4293 return discard_or_import_tablespace(discard);
4300 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4301 m_lock_type != F_UNLCK);
4302 mark_trx_read_write();
4318 DBUG_ASSERT(ha_thd()->mdl_context.is_lock_owner(MDL_key::TABLE,
4320 table->s->table_name.str,
4333 enum_alter_inplace_result
4337 DBUG_ENTER(
"check_if_supported_alter");
4343 Alter_inplace_info::ALTER_COLUMN_NAME |
4344 Alter_inplace_info::ALTER_COLUMN_DEFAULT |
4345 Alter_inplace_info::CHANGE_CREATE_OPTION |
4346 Alter_inplace_info::ALTER_RENAME;
4349 if (ha_alter_info->
handler_flags & ~inplace_offline_operations)
4350 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
4361 if (create_info->used_fields & (HA_CREATE_USED_CHARSET |
4362 HA_CREATE_USED_DEFAULT_CHARSET |
4363 HA_CREATE_USED_PACK_KEYS |
4364 HA_CREATE_USED_MAX_ROWS) ||
4365 (table->s->row_type != create_info->
row_type))
4366 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
4370 IS_EQUAL_PACK_LENGTH : IS_EQUAL_YES;
4372 == COMPATIBLE_DATA_YES)
4373 DBUG_RETURN(HA_ALTER_INPLACE_EXCLUSIVE_LOCK);
4375 DBUG_RETURN(HA_ALTER_INPLACE_NOT_SUPPORTED);
4391 const char *try_instead)
4394 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED, MYF(0),
4395 not_supported, try_instead);
4397 my_error(ER_ALTER_OPERATION_NOT_SUPPORTED_REASON, MYF(0),
4411 DBUG_ASSERT(m_lock_type == F_UNLCK);
4412 mark_trx_read_write();
4427 DBUG_ASSERT(m_lock_type == F_UNLCK);
4428 mark_trx_read_write();
4443 DBUG_ASSERT(m_lock_type == F_UNLCK);
4444 mark_trx_read_write();
4446 return drop_table(name);
4459 DBUG_ASSERT(m_lock_type == F_UNLCK);
4460 mark_trx_read_write();
4462 return create(name, form, info);
4481 DBUG_ASSERT(m_lock_type == F_UNLCK ||
4482 (!old_name && strcmp(name, table_share->path.str)));
4483 mark_trx_read_write();
4485 return create_handler_files(name, old_name, action_flag, info);
4498 ulonglong *
const copied,
4499 ulonglong *
const deleted,
4500 const uchar *pack_frm_data,
4501 size_t pack_frm_len)
4507 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
4508 m_lock_type != F_UNLCK);
4509 mark_trx_read_write();
4511 return change_partitions(create_info, path, copied, deleted,
4512 pack_frm_data, pack_frm_len);
4525 DBUG_ASSERT(!table->db_stat);
4527 mark_trx_read_write();
4529 return drop_partitions(path);
4542 DBUG_ASSERT(!table->db_stat);
4543 mark_trx_read_write();
4545 return rename_partitions(path);
4560 DBUG_ENTER(
"ha_enable_transaction");
4561 DBUG_PRINT(
"enter", (
"on: %d", (
int) on));
4563 if ((thd->transaction.flags.enabled= on))
4572 error= trans_commit_implicit(thd);
4580 DBUG_ENTER(
"index_next_same");
4583 my_ptrdiff_t ptrdiff= buf - table->record[0];
4584 uchar *UNINIT_VAR(save_record_0);
4585 KEY *UNINIT_VAR(key_info);
4599 save_record_0= table->record[0];
4600 table->record[0]=
buf;
4601 key_info= table->key_info + active_index;
4602 key_part= key_info->key_part;
4603 key_part_end= key_part + key_info->user_defined_key_parts;
4604 for (; key_part < key_part_end; key_part++)
4606 DBUG_ASSERT(key_part->field);
4607 key_part->field->move_field_offset(ptrdiff);
4611 if (key_cmp_if_same(table, key, active_index, keylen))
4613 table->status=STATUS_NOT_FOUND;
4614 error=HA_ERR_END_OF_FILE;
4620 table->record[0]= save_record_0;
4621 for (key_part= key_info->key_part; key_part < key_part_end; key_part++)
4622 key_part->field->move_field_offset(-ptrdiff);
4632 info(HA_STATUS_CONST | HA_STATUS_TIME | HA_STATUS_VARIABLE |
4634 stat_info->records=
stats.records;
4635 stat_info->mean_rec_length=
stats.mean_rec_length;
4636 stat_info->data_file_length=
stats.data_file_length;
4637 stat_info->max_data_file_length=
stats.max_data_file_length;
4638 stat_info->index_file_length=
stats.index_file_length;
4639 stat_info->delete_length=
stats.delete_length;
4640 stat_info->create_time=
stats.create_time;
4641 stat_info->update_time=
stats.update_time;
4642 stat_info->check_time=
stats.check_time;
4643 stat_info->check_sum= 0;
4644 if (table_flags() & (ulong) HA_HAS_CHECKSUM)
4645 stat_info->check_sum= checksum();
4665 bool update_create_info,
4670 char name_buff[FN_REFLEN];
4673 bool saved_abort_on_warning;
4674 DBUG_ENTER(
"ha_create_table");
4675 #ifdef HAVE_PSI_TABLE_INTERFACE
4676 my_bool temp_table= (my_bool)is_temp_table ||
4678 (create_info->options & HA_LEX_CREATE_TMP_TABLE ? TRUE : FALSE);
4681 init_tmp_table_share(thd, &share, db, 0, table_name, path);
4682 if (open_table_def(thd, &share, 0))
4685 #ifdef HAVE_PSI_TABLE_INTERFACE
4686 share.
m_psi= PSI_TABLE_CALL(get_table_share)(temp_table, &share);
4689 if (open_table_from_share(thd, &share,
"", 0, (uint) READ_ALL, 0, &table,
4693 if (update_create_info)
4694 update_create_info_from_table(create_info, &table);
4698 saved_abort_on_warning = thd->abort_on_warning;
4699 thd->abort_on_warning =
false;
4700 error= table.file->
ha_create(name, &table, create_info);
4701 thd->abort_on_warning = saved_abort_on_warning;
4705 #ifdef HAVE_PSI_TABLE_INTERFACE
4707 (temp_table, db, strlen(db),
table_name, strlen(table_name));
4710 (void) closefrm(&table, 0);
4712 free_table_share(&share);
4713 DBUG_RETURN(error != 0);
4734 char path[FN_REFLEN + 1];
4738 DBUG_ENTER(
"ha_create_table_from_engine");
4739 DBUG_PRINT(
"enter", (
"name '%s'.'%s'", db, name));
4741 memset(&create_info, 0,
sizeof(create_info));
4742 if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
4753 build_table_filename(path,
sizeof(path) - 1, db, name,
"", 0);
4755 error= writefrm(path, frmblob, frmlen);
4760 init_tmp_table_share(thd, &share, db, 0, name, path);
4761 if (open_table_def(thd, &share, 0))
4766 #ifdef HAVE_PSI_TABLE_INTERFACE
4774 if (open_table_from_share(thd, &share,
"" ,0, 0, 0, &table, FALSE))
4776 free_table_share(&share);
4780 update_create_info_from_table(&create_info, &table);
4781 create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
4784 error=table.file->
ha_create(path, &table, &create_info);
4785 (void) closefrm(&table, 1);
4787 DBUG_RETURN(error != 0);
4806 uchar *frmblob= NULL;
4808 DBUG_ENTER(
"ha_check_if_table_exists");
4810 *exists= ! ha_discover(thd, db, name, &frmblob, &frmlen);
4845 DBUG_ENTER(
"ha_check_if_supported_system_table");
4847 bool is_system_database=
false;
4852 DBUG_ASSERT(known_system_databases != NULL);
4853 names= known_system_databases;
4854 while (names && *names)
4856 if (strcmp(*names, db) == 0)
4859 check_params.db= *names;
4860 is_system_database=
true;
4865 if (!is_system_database)
4869 systab= mysqld_system_tables;
4870 check_params.is_sql_layer_system_table=
false;
4871 while (systab && systab->db)
4873 if (systab->db == check_params.db &&
4874 strcmp(systab->tablename, table_name) == 0)
4876 check_params.is_sql_layer_system_table=
true;
4883 check_params.status= check_params.is_sql_layer_system_table ?
4884 st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE :
4885 st_sys_tbl_chk_params::NOT_KNOWN_SYSTEM_TABLE;
4886 check_params.db_type= hton->db_type;
4888 plugin_foreach(NULL, check_engine_system_table_handlerton,
4889 MYSQL_STORAGE_ENGINE_PLUGIN, &check_params);
4892 if (check_params.status == st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE)
4920 static my_bool check_engine_system_table_handlerton(THD *unused,
4928 if (check_params->status == st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE)
4934 if (hton->db_type == check_params->db_type)
4938 check_params->table_name,
4939 check_params->is_sql_layer_system_table))
4940 check_params->status= st_sys_tbl_chk_params::SUPPORTED_SYSTEM_TABLE;
4957 check_params->table_name,
4958 check_params->is_sql_layer_system_table))
4964 if (hton->db_type == check_params->db_type)
4966 check_params->status= st_sys_tbl_chk_params::SUPPORTED_SYSTEM_TABLE;
4970 check_params->status= st_sys_tbl_chk_params::KNOWN_SYSTEM_TABLE;
4983 const char** ha_known_system_databases(
void)
4985 list<const char*> found_databases;
4986 const char **databases, **database;
4989 found_databases.push_back((
char*) mysqld_system_database);
4992 plugin_foreach(NULL, system_databases_handlerton,
4993 MYSQL_STORAGE_ENGINE_PLUGIN, &found_databases);
4995 databases= (
const char **) my_once_alloc(
sizeof(
char *)*
4996 (found_databases.size()+1),
4997 MYF(MY_WME | MY_FAE));
4998 DBUG_ASSERT(databases != NULL);
5000 list<const char*>::iterator it;
5001 database= databases;
5002 for (it= found_databases.begin(); it != found_databases.end(); it++)
5015 static my_bool system_databases_handlerton(THD *unused,
plugin_ref plugin,
5018 list<const char*> *found_databases= (list<const char*> *) arg;
5026 found_databases->push_back(db);
5032 void st_ha_check_opt::init()
5034 flags= sql_flags= 0;
5053 DBUG_ENTER(
"ha_init_key_cache");
5055 if (!key_cache->key_cache_inited)
5058 size_t tmp_buff_size= (size_t) key_cache->param_buff_size;
5059 uint tmp_block_size= (uint) key_cache->param_block_size;
5060 uint division_limit= key_cache->param_division_limit;
5061 uint age_threshold= key_cache->param_age_threshold;
5063 DBUG_RETURN(!init_key_cache(key_cache,
5066 division_limit, age_threshold));
5077 DBUG_ENTER(
"ha_resize_key_cache");
5079 if (key_cache->key_cache_inited)
5082 size_t tmp_buff_size= (size_t) key_cache->param_buff_size;
5083 long tmp_block_size= (
long) key_cache->param_block_size;
5084 uint division_limit= key_cache->param_division_limit;
5085 uint age_threshold= key_cache->param_age_threshold;
5087 DBUG_RETURN(!resize_key_cache(key_cache, tmp_block_size,
5089 division_limit, age_threshold));
5100 if (key_cache->key_cache_inited)
5103 uint division_limit= key_cache->param_division_limit;
5104 uint age_threshold= key_cache->param_age_threshold;
5106 change_key_cache_param(key_cache, division_limit, age_threshold);
5117 mi_change_key_cache(old_key_cache, new_key_cache);
5140 static my_bool discover_handlerton(THD *thd,
plugin_ref plugin,
5145 if (hton->state == SHOW_OPTION_YES && hton->discover &&
5146 (!(hton->discover(hton, thd, vargs->db, vargs->name,
5154 int ha_discover(THD *thd,
const char *db,
const char *name,
5155 uchar **frmblob,
size_t *frmlen)
5158 DBUG_ENTER(
"ha_discover");
5159 DBUG_PRINT(
"enter", (
"db: %s, name: %s", db, name));
5165 if (plugin_foreach(thd, discover_handlerton,
5166 MYSQL_STORAGE_ENGINE_PLUGIN, &args))
5170 status_var_increment(thd->status_var.ha_discover_count);
5189 static my_bool find_files_handlerton(THD *thd,
plugin_ref plugin,
5196 if (hton->state == SHOW_OPTION_YES && hton->find_files)
5197 if (hton->find_files(hton, thd, vargs->db, vargs->path, vargs->wild,
5198 vargs->dir, vargs->files))
5205 ha_find_files(THD *thd,
const char *db,
const char *path,
5209 DBUG_ENTER(
"ha_find_files");
5210 DBUG_PRINT(
"enter", (
"db: '%s' path: '%s' wild: '%s' dir: %d",
5211 db, path, wild ? wild :
"NULL", dir));
5214 plugin_foreach(thd, find_files_handlerton,
5215 MYSQL_STORAGE_ENGINE_PLUGIN, &args);
5236 static my_bool table_exists_in_engine_handlerton(THD *thd,
plugin_ref plugin,
5242 int err= HA_ERR_NO_SUCH_TABLE;
5244 if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
5245 err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
5248 if (vargs->err == HA_ERR_TABLE_EXIST)
5254 int ha_table_exists_in_engine(THD* thd,
const char* db,
const char* name)
5256 DBUG_ENTER(
"ha_table_exists_in_engine");
5257 DBUG_PRINT(
"enter", (
"db: %s, name: %s", db, name));
5259 plugin_foreach(thd, table_exists_in_engine_handlerton,
5260 MYSQL_STORAGE_ENGINE_PLUGIN, &args);
5261 DBUG_PRINT(
"exit", (
"error: %d", args.err));
5262 DBUG_RETURN(args.err);
5275 static my_bool make_pushed_join_handlerton(THD *thd,
plugin_ref plugin,
5281 if (hton && hton->make_pushed_join)
5283 const int error= hton->make_pushed_join(hton, thd, vargs->plan);
5284 if (unlikely(error))
5295 DBUG_ENTER(
"ha_make_pushed_joins");
5297 plugin_foreach(thd, make_pushed_join_handlerton,
5298 MYSQL_STORAGE_ENGINE_PLUGIN, &args);
5299 DBUG_PRINT(
"exit", (
"error: %d", args.err));
5300 DBUG_RETURN(args.err);
5309 #define MAX_HTON_LIST_ST 63
5318 enum_binlog_func fn;
5325 static my_bool binlog_func_list(THD *thd,
plugin_ref plugin,
void *arg)
5329 if (hton->state == SHOW_OPTION_YES && hton->binlog_func)
5331 uint sz= hton_list->sz;
5332 if (sz == MAX_HTON_LIST_ST-1)
5337 hton_list->hton[sz]= hton;
5338 hton_list->sz= sz+1;
5343 static my_bool binlog_func_foreach(THD *thd,
binlog_func_st *bfn)
5349 plugin_foreach(thd, binlog_func_list,
5350 MYSQL_STORAGE_ENGINE_PLUGIN, &hton_list);
5352 for (i= 0, sz= hton_list.sz; i < sz ; i++)
5353 hton_list.hton[
i]->binlog_func(hton_list.hton[i], thd, bfn->fn, bfn->arg);
5357 #ifdef HAVE_NDB_BINLOG
5359 int ha_reset_logs(THD *thd)
5362 binlog_func_foreach(thd, &bfn);
5366 void ha_reset_slave(THD* thd)
5369 binlog_func_foreach(thd, &bfn);
5372 void ha_binlog_wait(THD* thd)
5375 binlog_func_foreach(thd, &bfn);
5378 int ha_binlog_index_purge_file(THD *thd,
const char *file)
5381 binlog_func_foreach(thd, &bfn);
5385 struct binlog_log_query_st
5387 enum_binlog_command binlog_command;
5394 static my_bool binlog_log_query_handlerton2(THD *thd,
5398 struct binlog_log_query_st *b= (
struct binlog_log_query_st*)args;
5399 if (hton->state == SHOW_OPTION_YES && hton->binlog_log_query)
5400 hton->binlog_log_query(hton, thd,
5409 static my_bool binlog_log_query_handlerton(THD *thd,
5413 return binlog_log_query_handlerton2(thd, plugin_data(plugin,
handlerton *), args);
5416 void ha_binlog_log_query(THD *thd,
handlerton *hton,
5417 enum_binlog_command binlog_command,
5418 const char *
query, uint query_length,
5421 struct binlog_log_query_st b;
5422 b.binlog_command= binlog_command;
5424 b.query_length= query_length;
5428 plugin_foreach(thd, binlog_log_query_handlerton,
5429 MYSQL_STORAGE_ENGINE_PLUGIN, &b);
5431 binlog_log_query_handlerton2(thd, hton, &b);
5435 int ha_binlog_end(THD* thd)
5438 binlog_func_foreach(thd, &bfn);
5466 uint keys_per_block= (
stats.block_size/2/
5469 read_time=((double) (records + keys_per_block-1) /
5470 (double) keys_per_block);
5497 for (; kp != kp_end; kp++)
5499 if (!kp->field->part_of_key.is_set(keyno))
5542 void *seq_init_param, uint n_ranges_arg,
5543 uint *bufsz, uint *
flags,
5548 ha_rows rows, total_rows= 0;
5550 THD *thd= current_thd;
5555 DBUG_EXECUTE_IF(
"bug13822652_2", thd->killed= THD::KILL_QUERY;);
5557 seq_it= seq->init(seq_init_param, n_ranges, *flags);
5558 while (!seq->next(seq_it, &range))
5560 if (unlikely(thd->killed != 0))
5561 return HA_POS_ERROR;
5565 if (range.range_flag & GEOM_FLAG)
5568 range.start_key.flag= (ha_rkey_function) (range.range_flag ^ GEOM_FLAG);
5569 min_endp= &range.start_key;
5574 min_endp= range.start_key.length? &range.start_key : NULL;
5575 max_endp= range.end_key.length? &range.end_key : NULL;
5597 int keyparts_used= 0;
5598 if ((range.range_flag & UNIQUE_RANGE) &&
5599 !(range.range_flag & NULL_RANGE))
5601 else if ((range.range_flag & EQ_RANGE) &&
5602 (range.range_flag & USE_INDEX_STATISTICS) &&
5603 (keyparts_used= my_count_bits(range.start_key.keypart_map)) &&
5604 table->key_info[keyno].
rec_per_key[keyparts_used-1] &&
5605 !(range.range_flag & NULL_RANGE))
5606 rows= table->key_info[keyno].
rec_per_key[keyparts_used-1];
5609 DBUG_EXECUTE_IF(
"crash_records_in_range", DBUG_SUICIDE(););
5610 DBUG_ASSERT(min_endp || max_endp);
5611 if (HA_POS_ERROR == (rows= this->records_in_range(keyno, min_endp,
5615 total_rows= HA_POS_ERROR;
5622 if (total_rows != HA_POS_ERROR)
5625 *
flags|= HA_MRR_USE_DEFAULT_IMPL;
5626 *
flags|= HA_MRR_SUPPORT_SORTED;
5628 DBUG_ASSERT(cost->is_zero());
5629 if ((*
flags & HA_MRR_INDEX_ONLY) && total_rows > 2)
5630 cost->add_io(index_only_read_time(keyno, total_rows) *
5633 cost->add_io(read_time(keyno, n_ranges, total_rows) *
5676 uint *bufsz, uint *
flags,
5681 *flags|= HA_MRR_USE_DEFAULT_IMPL;
5682 *flags|= HA_MRR_SUPPORT_SORTED;
5687 if (*flags & HA_MRR_INDEX_ONLY)
5742 DBUG_ENTER(
"handler::multi_range_read_init");
5743 mrr_iter= seq_funcs->init(seq_init_param, n_ranges, mode);
5744 mrr_funcs= *seq_funcs;
5745 mrr_is_output_sorted=
test(mode & HA_MRR_SORTED);
5746 mrr_have_range= FALSE;
5766 int result= HA_ERR_END_OF_FILE;
5768 DBUG_ENTER(
"handler::multi_range_read_next");
5770 if (!mrr_have_range)
5772 mrr_have_range= TRUE;
5779 if (mrr_cur_range.range_flag != (UNIQUE_RANGE | EQ_RANGE))
5783 if (result != HA_ERR_END_OF_FILE)
5794 while (!(range_res= mrr_funcs.next(mrr_iter, &mrr_cur_range)))
5798 &mrr_cur_range.start_key : 0,
5799 mrr_cur_range.end_key.keypart_map ?
5800 &mrr_cur_range.end_key : 0,
5801 test(mrr_cur_range.range_flag & EQ_RANGE),
5802 mrr_is_output_sorted);
5803 if (result != HA_ERR_END_OF_FILE)
5807 while ((result == HA_ERR_END_OF_FILE) && !range_res);
5809 *range_info= mrr_cur_range.ptr;
5810 DBUG_PRINT(
"exit",(
"handler::multi_range_read_next result %d", result));
5811 DBUG_RETURN(result);
5857 void *seq_init_param, uint n_ranges, uint
mode,
5862 DBUG_ENTER(
"DsMrr_impl::dsmrr_init");
5863 THD *thd= h_arg->table->in_use;
5871 mode & (HA_MRR_USE_DEFAULT_IMPL | HA_MRR_SORTED))
5873 use_default_impl= TRUE;
5874 retval= h->handler::multi_range_read_init(seq_funcs, seq_init_param,
5875 n_ranges, mode, buf);
5876 DBUG_RETURN(retval);
5891 DBUG_ASSERT(!h->pushed_idx_cond ||
5892 h->pushed_idx_cond_keyno == h->active_index ||
5893 h->pushed_idx_cond_keyno != table->s->primary_key ||
5894 (h2 && h->pushed_idx_cond_keyno == h2->active_index));
5896 rowids_buf= buf->buffer;
5898 is_mrr_assoc= !
test(mode & HA_MRR_NO_ASSOCIATION);
5901 status_var_increment(table->in_use->status_var.ha_multi_range_read_init_count);
5903 rowids_buf_end= buf->buffer_end;
5904 elem_size= h->
ref_length + (int)is_mrr_assoc *
sizeof(
void*);
5905 rowids_buf_last= rowids_buf +
5906 ((rowids_buf_end - rowids_buf)/ elem_size)*
5908 rowids_buf_end= rowids_buf_last;
5928 if (!(new_h2= h->clone(h->table->s->normalized_path.str, thd->mem_root)))
5937 if (h2->active_index == MAX_KEY)
5939 DBUG_ASSERT(h->active_index != MAX_KEY);
5940 const uint mrr_keyno= h->active_index;
5945 if ((retval= h2->extra(HA_EXTRA_KEYREAD)))
5952 if (mrr_keyno == h->pushed_idx_cond_keyno)
5975 DBUG_ASSERT(h->inited == handler::RND);
5976 DBUG_ASSERT(h->active_index == MAX_KEY ||
5977 h->active_index == table->s->primary_key);
5984 if (h->inited == handler::INDEX)
6002 DBUG_ASSERT(h->inited != handler::INDEX);
6003 DBUG_ASSERT(h->active_index == MAX_KEY ||
6004 h->active_index == table->s->primary_key);
6005 DBUG_ASSERT(h2->inited == handler::INDEX);
6006 DBUG_ASSERT(h2->active_index != MAX_KEY);
6007 DBUG_ASSERT(h->m_lock_type == h2->m_lock_type);
6009 if ((retval= h2->handler::multi_range_read_init(seq_funcs, seq_init_param,
6010 n_ranges, mode, buf)))
6021 buf->end_of_used_area= rowids_buf_last;
6027 if ((h->inited != handler::RND) &&
6028 ((h->inited==handler::INDEX? h->
ha_index_end(): FALSE) ||
6035 use_default_impl= FALSE;
6036 h->mrr_funcs= *seq_funcs;
6040 h2->ha_index_or_rnd_end();
6045 DBUG_ASSERT(retval != 0);
6046 DBUG_RETURN(retval);
6050 void DsMrr_impl::dsmrr_close()
6052 DBUG_ENTER(
"DsMrr_impl::dsmrr_close");
6055 if (h2 && h2->active_index != MAX_KEY)
6057 h2->ha_index_or_rnd_end();
6060 use_default_impl=
true;
6067 DBUG_ENTER(
"DsMrr_impl::reset");
6083 static int rowid_cmp(
void *h, uchar *a, uchar *b)
6085 return ((
handler*)h)->cmp_ref(a, b);
6110 DBUG_ENTER(
"DsMrr_impl::dsmrr_fill_buffer");
6111 DBUG_ASSERT(rowids_buf < rowids_buf_end);
6113 rowids_buf_cur= rowids_buf;
6114 while ((rowids_buf_cur < rowids_buf_end) &&
6115 !(res= h2->handler::multi_range_read_next(&range_info)))
6118 if (h2->mrr_funcs.skip_index_tuple &&
6119 h2->mrr_funcs.skip_index_tuple(h2->mrr_iter, curr_range->ptr))
6123 h2->position(table->record[0]);
6124 memcpy(rowids_buf_cur, h2->ref, h2->
ref_length);
6129 memcpy(rowids_buf_cur, &range_info,
sizeof(
void*));
6130 rowids_buf_cur +=
sizeof(
void*);
6134 if (res && res != HA_ERR_END_OF_FILE)
6136 dsmrr_eof=
test(res == HA_ERR_END_OF_FILE);
6139 uint elem_size= h->ref_length + (int)is_mrr_assoc *
sizeof(
void*);
6140 uint n_rowids= (rowids_buf_cur - rowids_buf) / elem_size;
6142 my_qsort2(rowids_buf, n_rowids, elem_size, (qsort2_cmp)rowid_cmp,
6144 rowids_buf_last= rowids_buf_cur;
6145 rowids_buf_cur= rowids_buf;
6154 int DsMrr_impl::dsmrr_next(
char **range_info)
6157 uchar *cur_range_info= 0;
6160 if (use_default_impl)
6161 return h->handler::multi_range_read_next(range_info);
6165 if (rowids_buf_cur == rowids_buf_last)
6169 res= HA_ERR_END_OF_FILE;
6179 if (rowids_buf_cur == rowids_buf_last)
6181 res= HA_ERR_END_OF_FILE;
6184 rowid= rowids_buf_cur;
6187 memcpy(&cur_range_info, rowids_buf_cur + h->ref_length,
sizeof(uchar*));
6189 rowids_buf_cur += h->ref_length +
sizeof(
void*) *
test(is_mrr_assoc);
6190 if (h2->mrr_funcs.skip_record &&
6191 h2->mrr_funcs.skip_record(h2->mrr_iter, (
char *) cur_range_info, rowid))
6193 res= h->rnd_pos(table->record[0], rowid);
6199 memcpy(range_info, rowid + h->ref_length,
sizeof(
void*));
6209 ha_rows DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows,
6213 uint def_flags= *
flags;
6214 uint def_bufsz= *bufsz;
6217 res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
6221 if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
6222 choose_mrr_impl(keyno, rows, flags, bufsz, cost))
6225 DBUG_PRINT(
"info", (
"Default MRR implementation choosen"));
6228 DBUG_ASSERT(*flags & HA_MRR_USE_DEFAULT_IMPL);
6233 DBUG_PRINT(
"info", (
"DS-MRR implementation choosen"));
6243 ha_rows DsMrr_impl::dsmrr_info_const(uint keyno,
RANGE_SEQ_IF *seq,
6244 void *seq_init_param, uint n_ranges,
6248 uint def_flags= *
flags;
6249 uint def_bufsz= *bufsz;
6251 rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
6252 n_ranges, &def_bufsz,
6254 if (rows == HA_POS_ERROR)
6266 if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
6267 choose_mrr_impl(keyno, rows, flags, bufsz, cost))
6269 DBUG_PRINT(
"info", (
"Default MRR implementation choosen"));
6272 DBUG_ASSERT(*flags & HA_MRR_USE_DEFAULT_IMPL);
6277 DBUG_PRINT(
"info", (
"DS-MRR implementation choosen"));
6306 bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
6310 THD *thd= current_thd;
6312 *flags & (HA_MRR_INDEX_ONLY | HA_MRR_SORTED) ||
6313 (keyno == table->s->primary_key && h->primary_key_is_clustered()) ||
6339 if (min_file_size == -1)
6342 min_file_size= 100 * 1024 * 1024;
6345 if (table->file->stats.data_file_length <
6346 static_cast<ulonglong>(min_file_size) ||
6352 if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
6370 *flags &= ~HA_MRR_USE_DEFAULT_IMPL;
6371 *flags &= ~HA_MRR_SUPPORT_SORTED;
6384 static void get_sort_and_sweep_cost(
TABLE *table, ha_rows nrows,
6402 bool DsMrr_impl::get_disk_sweep_mrr_cost(uint keynr, ha_rows rows, uint flags,
6406 ha_rows rows_in_last_step;
6408 double index_read_cost;
6410 const uint elem_size= h->ref_length +
6411 sizeof(
void*) * (!
test(flags & HA_MRR_NO_ASSOCIATION));
6412 const ha_rows max_buff_entries= *buffer_size / elem_size;
6414 if (!max_buff_entries)
6418 n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
6424 rows_in_last_step= rows % max_buff_entries;
6430 get_sort_and_sweep_cost(table, max_buff_entries, cost);
6443 const ha_rows keys_in_buffer=
6444 max<ha_rows>(
static_cast<ha_rows
>(1.2 * rows_in_last_step), 100);
6445 *buffer_size= min<ulong>(*buffer_size,
6446 static_cast<ulong
>(keys_in_buffer) * elem_size);
6450 get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
6451 (*cost)+= last_step_cost;
6461 index_read_cost= h->index_only_read_time(keynr, rows);
6505 const double ROWID_COMPARE_SORT_COST = 0.01;
6508 const double cpu_sort= nrows * log2(nrows) * ROWID_COMPARE_SORT_COST;
6560 DBUG_ENTER(
"get_sweep_read_cost");
6566 ceil(ulonglong2double(table->file->stats.data_file_length) / IO_SIZE);
6570 n_blocks * (1.0 - pow(1.0 - 1.0/n_blocks, rows2double(nrows)));
6571 if (busy_blocks < 1.0)
6574 DBUG_PRINT(
"info",(
"sweep: nblocks=%g, busy_blocks=%g", n_blocks,
6580 cost->
add_io(busy_blocks *
6581 (DISK_SEEK_BASE_COST +
6582 DISK_SEEK_PROP_COST * n_blocks / busy_blocks));
6584 DBUG_PRINT(
"info",(
"returning cost=%g", cost->
total_cost()));
6618 DBUG_ENTER(
"handler::read_range_first");
6620 eq_range= eq_range_arg;
6623 range_key_part= table->key_info[active_index].key_part;
6630 start_key->keypart_map,
6633 DBUG_RETURN((result == HA_ERR_KEY_NOT_FOUND)
6634 ? HA_ERR_END_OF_FILE
6648 DBUG_RETURN(HA_ERR_END_OF_FILE);
6669 DBUG_ENTER(
"handler::read_range_next");
6676 end_range->length));
6680 DBUG_RETURN(result);
6693 DBUG_RETURN(HA_ERR_END_OF_FILE);
6699 enum_range_scan_direction direction)
6703 save_end_range= *range;
6704 end_range= &save_end_range;
6705 range_key_part= table->key_info[active_index].key_part;
6706 key_compare_result_on_equal= ((range->flag == HA_READ_BEFORE_KEY) ? 1 :
6707 (range->flag == HA_READ_AFTER_KEY) ? -1 : 0);
6712 range_scan_direction= direction;
6734 if (!range || in_range_check_pushed_down)
6736 cmp= key_cmp(range_key_part, range->key, range->length);
6738 cmp= key_compare_result_on_equal;
6763 int handler::compare_key_icp(
const key_range *range)
const
6768 cmp= key_cmp(range_key_part, range->key, range->length);
6770 cmp= key_compare_result_on_equal;
6771 if (range_scan_direction == RANGE_SCAN_DESC)
6777 key_part_map keypart_map,
6778 enum ha_rkey_function find_flag)
6781 error= index_init(index, 0);
6785 error1= index_end();
6787 return error ? error : error1;
6801 static my_bool exts_handlerton(THD *unused,
plugin_ref plugin,
6807 if (hton->state == SHOW_OPTION_YES && hton->create &&
6808 (file= hton->create(hton, (
TABLE_SHARE*) 0, current_thd->mem_root)))
6811 const char **ext, *old_ext;
6813 for (ext= file->
bas_ext(); *ext; ext++)
6815 while ((old_ext= it++))
6817 if (!strcmp(old_ext, *ext))
6821 found_exts->push_back((
char *) *ext);
6833 known_extensions->name=
"known_exts";
6834 known_extensions->type_lengths= NULL;
6837 const char **ext, *old_ext;
6839 found_exts.push_back((
char*) TRG_EXT);
6840 found_exts.push_back((
char*) TRN_EXT);
6842 plugin_foreach(NULL, exts_handlerton,
6843 MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
6845 size_t arr_length=
sizeof(
char *)* (found_exts.elements+1);
6846 ext= (
const char **) sql_alloc(arr_length);
6848 DBUG_ASSERT(NULL != ext);
6849 known_extensions->count= found_exts.elements;
6850 known_extensions->type_names= ext;
6853 while ((old_ext= it++))
6856 return known_extensions;
6860 static bool stat_print(THD *thd,
const char *
type, uint type_len,
6861 const char *file, uint file_len,
6862 const char *status, uint status_len)
6865 protocol->prepare_for_resend();
6866 protocol->
store(type, type_len, system_charset_info);
6867 protocol->
store(file, file_len, system_charset_info);
6868 protocol->
store(status, status_len, system_charset_info);
6869 if (protocol->write())
6875 static my_bool showstat_handlerton(THD *thd,
plugin_ref plugin,
6878 enum ha_stat_type stat= *(
enum ha_stat_type *) arg;
6880 if (hton->state == SHOW_OPTION_YES && hton->show_status &&
6881 hton->show_status(hton, thd, stat_print, stat))
6886 bool ha_show_status(THD *thd,
handlerton *db_type,
enum ha_stat_type stat)
6897 Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
6900 if (db_type == NULL)
6902 result= plugin_foreach(thd, showstat_handlerton,
6903 MYSQL_STORAGE_ENGINE_PLUGIN, &stat);
6907 if (db_type->state != SHOW_OPTION_YES)
6909 const LEX_STRING *name=&hton2plugin[db_type->slot]->name;
6910 result= stat_print(thd, name->str, name->length,
6911 "", 0,
"DISABLED", 8) ? 1 : 0;
6914 result= db_type->show_status &&
6915 db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
6936 static bool check_table_binlog_row_based(THD *thd,
TABLE *table)
6938 if (table->s->cached_row_logging_check == -1)
6940 int const check(table->s->tmp_table == NO_TMP_TABLE &&
6942 binlog_filter->db_ok(table->s->db.str));
6943 table->s->cached_row_logging_check= check;
6946 DBUG_ASSERT(table->s->cached_row_logging_check == 0 ||
6947 table->s->cached_row_logging_check == 1);
6949 return (thd->is_current_stmt_binlog_format_row() &&
6950 table->s->cached_row_logging_check &&
6951 (thd->variables.option_bits & OPTION_BIN_LOG) &&
6952 mysql_bin_log.is_open());
6976 static int write_locked_table_maps(THD *thd)
6978 DBUG_ENTER(
"write_locked_table_maps");
6979 DBUG_PRINT(
"enter", (
"thd: 0x%lx thd->lock: 0x%lx "
6980 "thd->extra_lock: 0x%lx",
6981 (
long) thd, (
long) thd->lock, (
long) thd->extra_lock));
6983 DBUG_PRINT(
"debug", (
"get_binlog_table_maps(): %d", thd->get_binlog_table_maps()));
6985 if (thd->get_binlog_table_maps() == 0)
6988 locks[0]= thd->extra_lock;
6989 locks[1]= thd->lock;
6990 for (uint i= 0 ; i <
sizeof(locks)/
sizeof(*locks) ; ++
i )
6996 bool need_binlog_rows_query= thd->variables.binlog_rows_query_log_events;
6997 TABLE **
const end_ptr= lock->table + lock->table_count;
6998 for (
TABLE **table_ptr= lock->table ;
6999 table_ptr != end_ptr ;
7002 TABLE *
const table= *table_ptr;
7003 DBUG_PRINT(
"info", (
"Checking table %s", table->s->table_name.str));
7004 if (table->current_lock == F_WRLCK &&
7005 check_table_binlog_row_based(thd, table))
7020 bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
7021 table->file->has_transactions();
7022 int const error= thd->binlog_write_table_map(table, has_trans,
7023 need_binlog_rows_query);
7026 if (need_binlog_rows_query)
7027 need_binlog_rows_query= FALSE;
7032 if (unlikely(error))
7042 typedef bool Log_func(THD*,
TABLE*,
bool,
7043 const uchar*,
const uchar*);
7046 const uchar *before_record,
7047 const uchar *after_record,
7051 THD *
const thd= table->in_use;
7053 if (check_table_binlog_row_based(thd, table))
7055 DBUG_DUMP(
"read_set 10", (uchar*) table->read_set->bitmap,
7056 (table->s->fields + 7) / 8);
7063 if (likely(!(error= write_locked_table_maps(thd))))
7073 bool const has_trans= thd->lex->sql_command == SQLCOM_CREATE_TABLE ||
7074 table->file->has_transactions();
7076 (*log_func)(thd,
table, has_trans, before_record, after_record);
7079 return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
7085 DBUG_ENTER(
"handler::ha_external_lock");
7093 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
7094 ((lock_type != F_UNLCK && m_lock_type == F_UNLCK) ||
7095 lock_type == F_UNLCK));
7097 DBUG_ASSERT(inited == NONE || table->open_by_handler);
7099 if (MYSQL_HANDLER_RDLOCK_START_ENABLED() ||
7100 MYSQL_HANDLER_WRLOCK_START_ENABLED() ||
7101 MYSQL_HANDLER_UNLOCK_START_ENABLED())
7103 if (lock_type == F_RDLCK)
7105 MYSQL_HANDLER_RDLOCK_START(table_share->db.str,
7106 table_share->table_name.str);
7108 else if (lock_type == F_WRLCK)
7110 MYSQL_HANDLER_WRLOCK_START(table_share->db.str,
7111 table_share->table_name.str);
7113 else if (lock_type == F_UNLCK)
7115 MYSQL_HANDLER_UNLOCK_START(table_share->db.str,
7116 table_share->table_name.str);
7120 ha_statistic_increment(&SSV::ha_external_lock_count);
7123 { error= external_lock(thd, lock_type); })
7136 m_lock_type= lock_type;
7137 cached_table_flags= table_flags();
7140 if (MYSQL_HANDLER_RDLOCK_DONE_ENABLED() ||
7141 MYSQL_HANDLER_WRLOCK_DONE_ENABLED() ||
7142 MYSQL_HANDLER_UNLOCK_DONE_ENABLED())
7144 if (lock_type == F_RDLCK)
7146 MYSQL_HANDLER_RDLOCK_DONE(error);
7148 else if (lock_type == F_WRLCK)
7150 MYSQL_HANDLER_WRLOCK_DONE(error);
7152 else if (lock_type == F_UNLCK)
7154 MYSQL_HANDLER_UNLOCK_DONE(error);
7168 DBUG_ENTER(
"handler::ha_reset");
7170 DBUG_ASSERT((uchar*) table->def_read_set.bitmap +
7171 table->s->column_bitmap_size ==
7172 (uchar*) table->def_write_set.bitmap);
7173 DBUG_ASSERT(bitmap_is_set_all(&table->s->all_set));
7176 DBUG_ASSERT(inited == NONE);
7178 free_io_cache(table);
7180 table->default_column_bitmaps();
7186 const int retval= reset();
7187 DBUG_RETURN(retval);
7191 int handler::ha_write_row(uchar *buf)
7194 Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
7195 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
7196 m_lock_type == F_WRLCK);
7198 DBUG_ENTER(
"handler::ha_write_row");
7199 DBUG_EXECUTE_IF(
"inject_error_ha_write_row",
7200 DBUG_RETURN(HA_ERR_INTERNAL_ERROR); );
7202 MYSQL_INSERT_ROW_START(table_share->db.str, table_share->table_name.str);
7203 mark_trx_read_write();
7206 { error= write_row(buf); })
7208 MYSQL_INSERT_ROW_DONE(error);
7209 if (unlikely(error))
7215 DEBUG_SYNC_C(
"ha_write_row_end");
7220 int handler::ha_update_row(
const uchar *old_data, uchar *new_data)
7223 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
7224 m_lock_type == F_WRLCK);
7225 Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
7231 DBUG_ASSERT(new_data == table->record[0]);
7232 DBUG_ASSERT(old_data == table->record[1]);
7234 MYSQL_UPDATE_ROW_START(table_share->db.str, table_share->table_name.str);
7235 mark_trx_read_write();
7238 { error= update_row(old_data, new_data);})
7240 MYSQL_UPDATE_ROW_DONE(error);
7241 if (unlikely(error))
7243 if (unlikely(error=
binlog_log_row(table, old_data, new_data, log_func)))
7248 int handler::ha_delete_row(
const uchar *buf)
7251 DBUG_ASSERT(table_share->tmp_table != NO_TMP_TABLE ||
7252 m_lock_type == F_WRLCK);
7253 Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
7257 DBUG_ASSERT(buf == table->record[0] ||
7258 buf == table->record[1]);
7259 DBUG_EXECUTE_IF(
"inject_error_ha_delete_row",
7260 return HA_ERR_INTERNAL_ERROR; );
7262 MYSQL_DELETE_ROW_START(table_share->db.str, table_share->table_name.str);
7263 mark_trx_read_write();
7266 { error= delete_row(buf);})
7268 MYSQL_DELETE_ROW_DONE(error);
7269 if (unlikely(error))
7286 table->use_all_columns();
7303 DBUG_ENTER(
"handler::get_ha_share_ptr");
7304 DBUG_ASSERT(ha_share && table_share);
7307 if (table_share->tmp_table == NO_TMP_TABLE)
7311 DBUG_RETURN(*ha_share);
7326 DBUG_ENTER(
"handler::set_ha_share_ptr");
7327 DBUG_ASSERT(ha_share);
7329 if (table_share->tmp_table == NO_TMP_TABLE)
7333 *ha_share= arg_ha_share;
7344 DBUG_ASSERT(table_share);
7345 if (table_share->tmp_table == NO_TMP_TABLE)
7356 DBUG_ASSERT(table_share);
7357 if (table_share->tmp_table == NO_TMP_TABLE)
7368 DBUG_ENTER(
"signal_log_not_needed");
7369 DBUG_PRINT(
"enter", (
"logfile '%s'", log_file));
7373 #ifdef TRANS_LOG_MGM_EXAMPLE_CODE
7380 int example_of_iterator_using_for_logs_cleanup(
handlerton *hton)
7387 if (!hton->create_iterator)
7390 if ((*hton->create_iterator)(hton, HA_TRANSACTLOG_ITERATOR, &iterator) !=
7396 while((*iterator.next)(&iterator, (
void*)&data) == 0)
7398 printf(
"%s\n", data.filename.str);
7399 if (data.status == HA_LOG_STATUS_FREE &&
7401 data.filename.str, MYF(MY_WME)))
7406 (*iterator.destroy)(&iterator);
7418 #define fl_dir FN_ROOTDIR
7426 enum log_status fl_get_log_status(
char *log)
7430 return HA_LOG_STATUS_INUSE;
7431 return HA_LOG_STATUS_NOSUCHLOG;
7438 enum log_status *statuses;
7445 void *iterator_object)
7447 struct fl_buff *buff= (
struct fl_buff *)iterator->buffer;
7450 if (buff->current >= buff->entries)
7452 data->filename= buff->names[buff->current];
7453 data->status= buff->statuses[buff->current];
7461 my_free(iterator->buffer);
7468 enum handler_create_iterator_result
7472 struct fl_buff *buff;
7479 iterator->buffer= 0;
7481 if (!(dirp = my_dir(fl_dir, MYF(0))))
7483 return HA_ITERATOR_ERROR;
7485 if ((ptr= (uchar*)my_malloc(ALIGN_SIZE(
sizeof(fl_buff)) +
7487 sizeof(
enum log_status) +
7489 (uint) dirp->number_off_files),
7492 return HA_ITERATOR_ERROR;
7494 buff= (
struct fl_buff *)ptr;
7495 buff->entries= buff->current= 0;
7496 ptr= ptr + (ALIGN_SIZE(
sizeof(fl_buff)));
7498 ptr= ptr + ((ALIGN_SIZE(
sizeof(
LEX_STRING)) *
7499 (uint) dirp->number_off_files));
7500 buff->statuses= (
enum log_status *)(ptr);
7501 name_ptr= (
char *)(ptr + (
sizeof(
enum log_status) *
7502 (uint) dirp->number_off_files));
7503 for (i=0 ; i < (uint) dirp->number_off_files ; i++)
7506 file= dirp->dir_entry +
i;
7507 if ((file->name[0] ==
'.' &&
7508 ((file->name[1] ==
'.' && file->name[2] ==
'\0') ||
7509 file->name[1] ==
'\0')))
7511 if ((st= fl_get_log_status(file->name)) == HA_LOG_STATUS_NOSUCHLOG)
7513 name_ptr= strxnmov(buff->names[buff->entries].str= name_ptr,
7514 FN_REFLEN, fl_dir, file->name, NullS);
7515 buff->names[buff->entries].length= (name_ptr -
7516 buff->names[buff->entries].str);
7517 buff->statuses[buff->entries]= st;
7521 iterator->buffer= buff;
7522 iterator->next= &fl_log_iterator_next;
7523 iterator->destroy= &fl_log_iterator_destroy;
7524 return HA_ITERATOR_OK;
7529 enum handler_create_iterator_result
7530 fl_create_iterator(
enum handler_iterator_type type,
7534 case HA_TRANSACTLOG_ITERATOR:
7535 return fl_log_iterator_buffer_init(iterator);
7537 return HA_ITERATOR_UNSUPPORTED;