23
19
Handler-calling-functions
26
#include "drizzled/server_includes.h"
27
#include "mysys/hash.h"
28
#include "drizzled/error.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/probes.h"
31
#include "drizzled/sql_parse.h"
32
#include "drizzled/cost_vect.h"
33
#include "drizzled/session.h"
34
#include "drizzled/sql_base.h"
35
#include "drizzled/transaction_services.h"
36
#include "drizzled/lock.h"
37
#include "drizzled/item/int.h"
38
#include "drizzled/item/empty_string.h"
39
#include "drizzled/unireg.h" // for mysql_frm_type
40
#include "drizzled/field/timestamp.h"
41
#include "drizzled/message/table.pb.h"
45
extern drizzled::TransactionServices transaction_services;
47
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
49
/* number of entries in storage_engines[] */
51
/* number of storage engines (from storage_engines[]) that support 2pc */
52
uint32_t total_ha_2pc= 0;
22
#ifdef USE_PRAGMA_IMPLEMENTATION
23
#pragma implementation // gcc: Class implementation
26
#include "mysql_priv.h"
27
#include "rpl_filter.h"
28
#include <myisampack.h>
32
While we have legacy_db_type, we have this array to
33
check for dups and to find handlerton from legacy_db_type.
34
Remove when legacy_db_type is finally gone
36
st_plugin_int *hton2plugin[MAX_HA];
38
static handlerton *installed_htons[128];
40
#define BITMAP_STACKBUF_SIZE (128/8)
42
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0}, {NullS,0} };
44
/* number of entries in handlertons[] */
46
/* number of storage engines (from handlertons[]) that support 2pc */
47
ulong total_ha_2pc= 0;
53
48
/* size of savepoint storage area (see ha_init) */
54
uint32_t savepoint_alloc_size= 0;
49
ulong savepoint_alloc_size= 0;
51
static const LEX_STRING sys_table_aliases[]=
53
{ C_STRING_WITH_LEN("INNOBASE") }, { C_STRING_WITH_LEN("INNODB") },
54
{ C_STRING_WITH_LEN("HEAP") }, { C_STRING_WITH_LEN("MEMORY") },
56
58
const char *ha_row_type[] = {
57
59
"", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
60
62
const char *tx_isolation_names[] =
61
63
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
64
65
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
tx_isolation_names, NULL};
66
tx_isolation_names, NULL};
68
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
69
uint known_extensions_id= 0;
73
static plugin_ref ha_default_plugin(THD *thd)
75
if (thd->variables.table_plugin)
76
return thd->variables.table_plugin;
77
return my_plugin_lock(thd, &global_system_variables.table_plugin);
82
Return the default storage engine handlerton for thread
84
@param ha_default_handlerton(thd)
85
@param thd current thread
90
handlerton *ha_default_handlerton(THD *thd)
92
plugin_ref plugin= ha_default_plugin(thd);
94
handlerton *hton= plugin_data(plugin, handlerton*);
101
Return the storage engine handlerton for the supplied name
103
@param thd current thread
104
@param name name of storage engine
107
pointer to storage engine plugin handle
109
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
111
const LEX_STRING *table_alias;
115
/* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
116
if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1,
117
(const uchar *)name->str, name->length,
118
(const uchar *)STRING_WITH_LEN("DEFAULT"), 0))
119
return ha_default_plugin(thd);
121
if ((plugin= my_plugin_lock_by_name(thd, name, MYSQL_STORAGE_ENGINE_PLUGIN)))
123
handlerton *hton= plugin_data(plugin, handlerton *);
124
if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
128
unlocking plugin immediately after locking is relatively low cost.
130
plugin_unlock(thd, plugin);
134
We check for the historical aliases.
136
for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
138
if (!my_strnncoll(&my_charset_latin1,
139
(const uchar *)name->str, name->length,
140
(const uchar *)table_alias->str, table_alias->length))
142
name= table_alias + 1;
151
plugin_ref ha_lock_engine(THD *thd, handlerton *hton)
155
st_plugin_int **plugin= hton2plugin + hton->slot;
158
return my_plugin_lock(thd, plugin);
160
return my_plugin_lock(thd, &plugin);
167
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
171
case DB_TYPE_DEFAULT:
172
return ha_default_handlerton(thd);
174
if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
175
(plugin= ha_lock_engine(thd, installed_htons[db_type])))
176
return plugin_data(plugin, handlerton*);
178
case DB_TYPE_UNKNOWN:
185
Use other database handler if databasehandler is not compiled in.
187
handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
188
bool no_substitute, bool report_error)
190
handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
191
if (ha_storage_engine_is_enabled(hton))
198
const char *engine_name= ha_resolve_storage_engine_name(hton);
199
my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
204
switch (database_type) {
206
return ha_resolve_by_legacy_type(thd, DB_TYPE_HASH);
211
return ha_default_handlerton(thd);
215
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
219
DBUG_ENTER("get_new_handler");
220
DBUG_PRINT("enter", ("alloc: 0x%lx", (long) alloc));
222
if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
224
if ((file= db_type->create(db_type, share, alloc)))
229
Try the default table type
230
Here the call to current_thd() is ok as we call this function a lot of
231
times but we enter this branch very seldom.
233
DBUG_RETURN(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
148
317
/* Allocate a pointer array for the error message strings. */
149
318
if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
151
free((unsigned char*) errmsgs);
320
my_free((uchar*) errmsgs, MYF(0));
325
int ha_finalize_handlerton(st_plugin_int *plugin)
327
handlerton *hton= (handlerton *)plugin->data;
328
DBUG_ENTER("ha_finalize_handlerton");
333
case SHOW_OPTION_DISABLED:
335
case SHOW_OPTION_YES:
336
if (installed_htons[hton->db_type] == hton)
337
installed_htons[hton->db_type]= NULL;
342
hton->panic(hton, HA_PANIC_CLOSE);
344
if (plugin->plugin->deinit)
347
Today we have no defined/special behavior for uninstalling
350
DBUG_PRINT("info", ("Deinitializing plugin: '%s'", plugin->name.str));
351
if (plugin->plugin->deinit(NULL))
353
DBUG_PRINT("warning", ("Plugin '%s' deinit function returned error.",
358
my_free((uchar*)hton, MYF(0));
364
int ha_initialize_handlerton(st_plugin_int *plugin)
367
DBUG_ENTER("ha_initialize_handlerton");
368
DBUG_PRINT("plugin", ("initialize plugin: '%s'", plugin->name.str));
370
hton= (handlerton *)my_malloc(sizeof(handlerton),
371
MYF(MY_WME | MY_ZEROFILL));
373
FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
375
This was detected after adding get_backup_engine member to handlerton
376
structure. Apparently get_backup_engine was not NULL even though it was
379
bzero(hton, sizeof(hton));
380
/* Historical Requirement */
381
plugin->data= hton; // shortcut for the future
382
if (plugin->plugin->init)
384
if (plugin->plugin->init(hton))
386
sql_print_error("Plugin '%s' init function returned error.",
393
the switch below and hton->state should be removed when
394
command-line options for plugins will be implemented
396
switch (hton->state) {
399
case SHOW_OPTION_YES:
402
/* now check the db_type for conflict */
403
if (hton->db_type <= DB_TYPE_UNKNOWN ||
404
hton->db_type >= DB_TYPE_DEFAULT ||
405
installed_htons[hton->db_type])
407
int idx= (int) DB_TYPE_FIRST_DYNAMIC;
409
while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
412
if (idx == (int) DB_TYPE_DEFAULT)
414
sql_print_warning("Too many storage engines!");
417
if (hton->db_type != DB_TYPE_UNKNOWN)
418
sql_print_warning("Storage engine '%s' has conflicting typecode. "
419
"Assigning value %d.", plugin->plugin->name, idx);
420
hton->db_type= (enum legacy_db_type) idx;
422
installed_htons[hton->db_type]= hton;
423
tmp= hton->savepoint_offset;
424
hton->savepoint_offset= savepoint_alloc_size;
425
savepoint_alloc_size+= tmp;
426
hton->slot= total_ha++;
427
hton2plugin[hton->slot]=plugin;
434
hton->state= SHOW_OPTION_DISABLED;
439
This is entirely for legacy. We will create a new "disk based" hton and a
440
"memory" hton which will be configurable longterm. We should be able to
441
remove partition and myisammrg.
443
switch (hton->db_type) {
462
DBUG_ENTER("ha_init");
159
assert(total_ha < MAX_HA);
464
DBUG_ASSERT(total_ha < MAX_HA);
161
466
Check if there is a transaction-capable storage engine besides the
162
467
binary log (which is considered a transaction-capable storage engine in
163
468
counting total_ha)
470
opt_using_transactions= total_ha>(ulong)opt_bin_log;
165
471
savepoint_alloc_size+= sizeof(SAVEPOINT);
478
DBUG_ENTER("ha_end");
174
482
This should be eventualy based on the graceful shutdown flag.
175
483
So if flag is equal to HA_PANIC_CLOSE, the deallocate
489
835
times per transaction.
492
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
838
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
494
Session_TRANS *trans;
495
841
Ha_trx_info *ha_info;
842
DBUG_ENTER("trans_register_ha");
843
DBUG_PRINT("enter",("%s", all ? "all" : "stmt"));
499
trans= &session->transaction.all;
500
session->server_status|= SERVER_STATUS_IN_TRANS;
847
trans= &thd->transaction.all;
848
thd->server_status|= SERVER_STATUS_IN_TRANS;
503
trans= &session->transaction.stmt;
851
trans= &thd->transaction.stmt;
505
ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
853
ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
507
855
if (ha_info->is_started())
508
return; /* already registered, return */
510
ha_info->register_ha(trans, engine);
512
trans->no_2pc|= not engine->has_2pc();
513
if (session->transaction.xid_state.xid.is_null())
514
session->transaction.xid_state.xid.set(session->query_id);
856
DBUG_VOID_RETURN; /* already registered, return */
858
ha_info->register_ha(trans, ht_arg);
860
trans->no_2pc|=(ht_arg->prepare==0);
861
if (thd->transaction.xid_state.xid.is_null())
862
thd->transaction.xid_state.xid.set(thd->query_id);
871
1 error, transaction was rolled back
873
int ha_prepare(THD *thd)
876
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
877
Ha_trx_info *ha_info= trans->ha_list;
878
DBUG_ENTER("ha_prepare");
881
for (; ha_info; ha_info= ha_info->next())
884
handlerton *ht= ha_info->ht();
885
status_var_increment(thd->status_var.ha_prepare_count);
888
if ((err= ht->prepare(ht, thd, all)))
890
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
891
ha_rollback_trans(thd, all);
898
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
899
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
900
ha_resolve_storage_engine_name(ht));
633
1056
Sic: we know that prepare() is not NULL since otherwise
634
1057
trans->no_2pc would have been set.
636
if ((err= engine->prepare(session, all)))
1059
if ((err= ht->prepare(ht, thd, all)))
638
1061
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
641
status_var_increment(session->status_var.ha_prepare_count);
1064
status_var_increment(thd->status_var.ha_prepare_count);
1066
DBUG_EXECUTE_IF("crash_commit_after_prepare", abort(););
1067
if (error || (is_real_trans && xid &&
1068
(error= !(cookie= tc_log->log_xid(thd, xid)))))
645
ha_rollback_trans(session, all);
1070
ha_rollback_trans(thd, all);
1074
DBUG_EXECUTE_IF("crash_commit_after_log", abort(););
650
error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1076
error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1077
DBUG_EXECUTE_IF("crash_commit_before_unlog", abort(););
1079
tc_log->unlog(cookie, xid);
1080
DBUG_EXECUTE_IF("crash_commit_after", abort(););
652
1082
if (is_real_trans)
653
start_waiting_global_read_lock(session);
1083
start_waiting_global_read_lock(thd);
660
1090
This function does not care about global read lock. A caller should.
662
int ha_commit_one_phase(Session *session, bool all)
1092
int ha_commit_one_phase(THD *thd, bool all)
665
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
666
bool is_real_trans=all || session->transaction.all.ha_list == 0;
1095
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1096
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
667
1097
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1098
DBUG_ENTER("ha_commit_one_phase");
670
1101
for (; ha_info; ha_info= ha_info_next)
673
StorageEngine *engine= ha_info->engine();
674
if ((err= engine->commit(session, all)))
1104
handlerton *ht= ha_info->ht();
1105
if ((err= ht->commit(ht, thd, all)))
676
1107
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
679
status_var_increment(session->status_var.ha_commit_count);
1110
status_var_increment(thd->status_var.ha_commit_count);
680
1111
ha_info_next= ha_info->next();
681
1112
ha_info->reset(); /* keep it conveniently zero-filled */
683
1114
trans->ha_list= 0;
684
1115
trans->no_2pc=0;
685
1116
if (is_real_trans)
686
session->transaction.xid_state.xid.null();
1117
thd->transaction.xid_state.xid.null();
689
session->variables.tx_isolation=session->session_tx_isolation;
690
session->transaction.cleanup();
1120
thd->variables.tx_isolation=thd->session_tx_isolation;
1121
thd->transaction.cleanup();
697
int ha_rollback_trans(Session *session, bool all)
1128
int ha_rollback_trans(THD *thd, bool all)
700
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1131
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
701
1132
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
702
bool is_real_trans=all || session->transaction.all.ha_list == 0;
1133
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
1134
DBUG_ENTER("ha_rollback_trans");
705
1137
We must not rollback the normal transaction if a statement
706
1138
transaction is pending.
708
assert(session->transaction.stmt.ha_list == NULL ||
709
trans == &session->transaction.stmt);
1140
DBUG_ASSERT(thd->transaction.stmt.ha_list == NULL ||
1141
trans == &thd->transaction.stmt);
1143
if (thd->in_sub_stmt)
1146
If we are inside stored function or trigger we should not commit or
1147
rollback current statement transaction. See comment in ha_commit_trans()
1148
call for more information.
1153
my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
713
1158
for (; ha_info; ha_info= ha_info_next)
716
StorageEngine *engine= ha_info->engine();
717
if ((err= engine->rollback(session, all)))
1161
handlerton *ht= ha_info->ht();
1162
if ((err= ht->rollback(ht, thd, all)))
718
1163
{ // cannot happen
719
1164
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
722
status_var_increment(session->status_var.ha_rollback_count);
1167
status_var_increment(thd->status_var.ha_rollback_count);
723
1168
ha_info_next= ha_info->next();
724
1169
ha_info->reset(); /* keep it conveniently zero-filled */
726
1171
trans->ha_list= 0;
727
1172
trans->no_2pc=0;
728
1173
if (is_real_trans)
729
session->transaction.xid_state.xid.null();
1174
thd->transaction.xid_state.xid.null();
732
session->variables.tx_isolation=session->session_tx_isolation;
733
session->transaction.cleanup();
1177
thd->variables.tx_isolation=thd->session_tx_isolation;
1178
thd->transaction.cleanup();
737
session->transaction_rollback_request= false;
1182
thd->transaction_rollback_request= FALSE;
740
1185
If a non-transactional table was updated, warn; don't warn if this is a
763
1209
the user has used LOCK TABLES then that mechanism does not know to do the
766
int ha_autocommit_or_rollback(Session *session, int error)
1212
int ha_autocommit_or_rollback(THD *thd, int error)
768
if (session->transaction.stmt.ha_list)
1214
DBUG_ENTER("ha_autocommit_or_rollback");
1215
if (thd->transaction.stmt.ha_list)
772
if (ha_commit_trans(session, 0))
1219
if (ha_commit_trans(thd, 0))
1224
(void) ha_rollback_trans(thd, 0);
1225
if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1226
(void) ha_rollback(thd);
1229
thd->variables.tx_isolation=thd->session_tx_isolation;
1240
static my_bool xacommit_handlerton(THD *unused1, plugin_ref plugin,
1243
handlerton *hton= plugin_data(plugin, handlerton *);
1244
if (hton->state == SHOW_OPTION_YES && hton->recover)
1246
hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
1247
((struct xahton_st *)arg)->result= 0;
1252
static my_bool xarollback_handlerton(THD *unused1, plugin_ref plugin,
1255
handlerton *hton= plugin_data(plugin, handlerton *);
1256
if (hton->state == SHOW_OPTION_YES && hton->recover)
1258
hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
1259
((struct xahton_st *)arg)->result= 0;
1265
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
1267
struct xahton_st xaop;
1271
plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
1272
MYSQL_STORAGE_ENGINE_PLUGIN, &xaop);
1281
This does not need to be multi-byte safe or anything
1283
static char* xid_to_str(char *buf, XID *xid)
1288
for (i=0; i < xid->gtrid_length+xid->bqual_length; i++)
1290
uchar c=(uchar)xid->data[i];
1291
/* is_next_dig is set if next character is a number */
1292
bool is_next_dig= FALSE;
1293
if (i < XIDDATASIZE)
1295
char ch= xid->data[i+1];
1296
is_next_dig= (ch >= '0' && ch <='9');
1298
if (i == xid->gtrid_length)
1301
if (xid->bqual_length)
1307
if (c < 32 || c > 126)
1311
If next character is a number, write current character with
1312
3 octal numbers to ensure that the next number is not seen
1313
as part of the octal number
1315
if (c > 077 || is_next_dig)
1316
*s++=_dig_vec_lower[c >> 6];
1317
if (c > 007 || is_next_dig)
1318
*s++=_dig_vec_lower[(c >> 3) & 7];
1319
*s++=_dig_vec_lower[c & 7];
777
(void) ha_rollback_trans(session, 0);
778
if (session->transaction_rollback_request)
779
(void) ha_rollback(session);
782
session->variables.tx_isolation=session->session_tx_isolation;
1323
if (c == '\'' || c == '\\')
1335
recover() step of xa.
1338
there are three modes of operation:
1339
- automatic recover after a crash
1340
in this case commit_list != 0, tc_heuristic_recover==0
1341
all xids from commit_list are committed, others are rolled back
1342
- manual (heuristic) recover
1343
in this case commit_list==0, tc_heuristic_recover != 0
1344
DBA has explicitly specified that all prepared transactions should
1345
be committed (or rolled back).
1346
- no recovery (MySQL did not detect a crash)
1347
in this case commit_list==0, tc_heuristic_recover == 0
1348
there should be no prepared transactions in this case.
1352
int len, found_foreign_xids, found_my_xids;
1358
static my_bool xarecover_handlerton(THD *unused, plugin_ref plugin,
1361
handlerton *hton= plugin_data(plugin, handlerton *);
1362
struct xarecover_st *info= (struct xarecover_st *) arg;
1365
if (hton->state == SHOW_OPTION_YES && hton->recover)
1367
while ((got= hton->recover(hton, info->list, info->len)) > 0 )
1369
sql_print_information("Found %d prepared transaction(s) in %s",
1370
got, ha_resolve_storage_engine_name(hton));
1371
for (int i=0; i < got; i ++)
1373
my_xid x=info->list[i].get_my_xid();
1374
if (!x) // not "mine" - that is generated by external TM
1377
char buf[XIDDATASIZE*4+6]; // see xid_to_str
1378
sql_print_information("ignore xid %s", xid_to_str(buf, info->list+i));
1380
xid_cache_insert(info->list+i, XA_PREPARED);
1381
info->found_foreign_xids++;
1386
info->found_my_xids++;
1390
if (info->commit_list ?
1391
hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
1392
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
1395
char buf[XIDDATASIZE*4+6]; // see xid_to_str
1396
sql_print_information("commit xid %s", xid_to_str(buf, info->list+i));
1398
hton->commit_by_xid(hton, info->list+i);
1403
char buf[XIDDATASIZE*4+6]; // see xid_to_str
1404
sql_print_information("rollback xid %s",
1405
xid_to_str(buf, info->list+i));
1407
hton->rollback_by_xid(hton, info->list+i);
1410
if (got < info->len)
1417
int ha_recover(HASH *commit_list)
1419
struct xarecover_st info;
1420
DBUG_ENTER("ha_recover");
1421
info.found_foreign_xids= info.found_my_xids= 0;
1422
info.commit_list= commit_list;
1423
info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
1426
/* commit_list and tc_heuristic_recover cannot be set both */
1427
DBUG_ASSERT(info.commit_list==0 || tc_heuristic_recover==0);
1428
/* if either is set, total_ha_2pc must be set too */
1429
DBUG_ASSERT(info.dry_run || total_ha_2pc>(ulong)opt_bin_log);
1431
if (total_ha_2pc <= (ulong)opt_bin_log)
1434
if (info.commit_list)
1435
sql_print_information("Starting crash recovery...");
1438
#ifndef WILL_BE_DELETED_LATER
1441
for now, only InnoDB supports 2pc. It means we can always safely
1442
rollback all pending transactions, without risking inconsistent data
1445
DBUG_ASSERT(total_ha_2pc == (ulong) opt_bin_log+1); // only InnoDB and binlog
1446
tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
1451
for (info.len= MAX_XID_LIST_SIZE ;
1452
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1454
info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
1458
sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1462
plugin_foreach(NULL, xarecover_handlerton,
1463
MYSQL_STORAGE_ENGINE_PLUGIN, &info);
1465
my_free((uchar*)info.list, MYF(0));
1466
if (info.found_foreign_xids)
1467
sql_print_warning("Found %d prepared XA transactions",
1468
info.found_foreign_xids);
1469
if (info.dry_run && info.found_my_xids)
1471
sql_print_error("Found %d prepared transactions! It means that mysqld was "
1472
"not shut down properly last time and critical recovery "
1473
"information (last binlog or %s file) was manually deleted "
1474
"after a crash. You have to start mysqld with "
1475
"--tc-heuristic-recover switch to commit or rollback "
1476
"pending transactions.",
1477
info.found_my_xids, opt_tc_log_file);
1480
if (info.commit_list)
1481
sql_print_information("Crash recovery finished.");
792
1486
return the list of XID's to a client, the same way SHOW commands do.
796
1490
so mysql_xa_recover does not filter XID's to ensure uniqueness.
797
1491
It can be easily fixed later, if necessary.
799
bool mysql_xa_recover(Session *session)
1493
bool mysql_xa_recover(THD *thd)
801
1495
List<Item> field_list;
802
Protocol *protocol= session->protocol;
1496
Protocol *protocol= thd->protocol;
1499
DBUG_ENTER("mysql_xa_recover");
806
1501
field_list.push_back(new Item_int("formatID", 0, MY_INT32_NUM_DECIMAL_DIGITS));
807
1502
field_list.push_back(new Item_int("gtrid_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
808
1503
field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
809
1504
field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
811
if (protocol->sendFields(&field_list,
812
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1506
if (protocol->send_fields(&field_list,
1507
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
815
1510
pthread_mutex_lock(&LOCK_xid_cache);
816
1511
while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
818
1513
if (xs->xa_state==XA_PREPARED)
820
protocol->prepareForResend();
821
protocol->store((int64_t)xs->xid.formatID);
822
protocol->store((int64_t)xs->xid.gtrid_length);
823
protocol->store((int64_t)xs->xid.bqual_length);
824
protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length);
1515
protocol->prepare_for_resend();
1516
protocol->store_longlong((longlong)xs->xid.formatID, FALSE);
1517
protocol->store_longlong((longlong)xs->xid.gtrid_length, FALSE);
1518
protocol->store_longlong((longlong)xs->xid.bqual_length, FALSE);
1519
protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
825
1521
if (protocol->write())
827
1523
pthread_mutex_unlock(&LOCK_xid_cache);
833
1529
pthread_mutex_unlock(&LOCK_xid_cache);
1536
This function should be called when MySQL sends rows of a SELECT result set
1537
or the EOF mark to the client. It releases a possible adaptive hash index
1538
S-latch held by thd in InnoDB and also releases a possible InnoDB query
1539
FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
1540
keep them over several calls of the InnoDB handler interface when a join
1541
is executed. But when we let the control to pass to the client they have
1542
to be released because if the application program uses mysql_use_result(),
1543
it may deadlock on the S-latch if the application on another connection
1544
performs another SQL query. In MySQL-4.1 this is even more important because
1545
there a connection can have several SELECT queries open at the same time.
1547
@param thd the thread handle of the current connection
1552
static my_bool release_temporary_latches(THD *thd, plugin_ref plugin,
1555
handlerton *hton= plugin_data(plugin, handlerton *);
1557
if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1558
hton->release_temporary_latches(hton, thd);
1564
int ha_release_temporary_latches(THD *thd)
1566
plugin_foreach(thd, release_temporary_latches, MYSQL_STORAGE_ENGINE_PLUGIN,
839
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1572
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
842
Session_TRANS *trans= &session->transaction.all;
1575
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1576
&thd->transaction.all);
843
1577
Ha_trx_info *ha_info, *ha_info_next;
1579
DBUG_ENTER("ha_rollback_to_savepoint");
845
1581
trans->no_2pc=0;
847
1583
rolling back to savepoint in all storage engines that were part of the
889
1626
section "4.33.4 SQL-statements and transaction states",
890
1627
SAVEPOINT is *not* transaction-initiating SQL-statement
892
int ha_savepoint(Session *session, SAVEPOINT *sv)
1629
int ha_savepoint(THD *thd, SAVEPOINT *sv)
895
Session_TRANS *trans= &session->transaction.all;
1632
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1633
&thd->transaction.all);
896
1634
Ha_trx_info *ha_info= trans->ha_list;
1635
DBUG_ENTER("ha_savepoint");
897
1636
for (; ha_info; ha_info= ha_info->next())
900
StorageEngine *engine= ha_info->engine();
902
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
903
if (! engine->savepoint_set)
1639
handlerton *ht= ha_info->ht();
1641
if (! ht->savepoint_set)
905
1643
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
910
if ((err= engine->savepoint_set(session, (void *)(sv+1))))
1647
if ((err= ht->savepoint_set(ht, thd, (uchar *)(sv+1)+ht->savepoint_offset)))
911
1648
{ // cannot happen
912
1649
my_error(ER_GET_ERRNO, MYF(0), err);
915
status_var_increment(session->status_var.ha_savepoint_count);
1652
status_var_increment(thd->status_var.ha_savepoint_count);
918
1655
Remember the list of registered storage engines. All new
919
1656
engines are prepended to the beginning of the list.
921
1658
sv->ha_list= trans->ha_list;
925
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1662
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
928
1665
Ha_trx_info *ha_info= sv->ha_list;
1666
DBUG_ENTER("ha_release_savepoint");
930
1668
for (; ha_info; ha_info= ha_info->next())
933
StorageEngine *engine= ha_info->engine();
1671
handlerton *ht= ha_info->ht();
934
1672
/* Savepoint life time is enclosed into transaction life time. */
936
if ((err= engine->savepoint_release(session,
1674
if (!ht->savepoint_release)
1676
if ((err= ht->savepoint_release(ht, thd,
1677
(uchar *)(sv+1) + ht->savepoint_offset)))
938
1678
{ // cannot happen
939
1679
my_error(ER_GET_ERRNO, MYF(0), err);
1687
static my_bool snapshot_handlerton(THD *thd, plugin_ref plugin,
1690
handlerton *hton= plugin_data(plugin, handlerton *);
1691
if (hton->state == SHOW_OPTION_YES &&
1692
hton->start_consistent_snapshot)
1694
hton->start_consistent_snapshot(hton, thd);
1695
*((bool *)arg)= false;
1700
int ha_start_consistent_snapshot(THD *thd)
1704
plugin_foreach(thd, snapshot_handlerton, MYSQL_STORAGE_ENGINE_PLUGIN, &warn);
1707
Same idea as when one wants to CREATE TABLE in one engine which does not
1711
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1712
"This MySQL server does not support any "
1713
"consistent-read capable storage engine");
1718
static my_bool flush_handlerton(THD *thd, plugin_ref plugin,
1721
handlerton *hton= plugin_data(plugin, handlerton *);
1722
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1723
hton->flush_logs(hton))
1729
bool ha_flush_logs(handlerton *db_type)
1731
if (db_type == NULL)
1733
if (plugin_foreach(NULL, flush_handlerton,
1734
MYSQL_STORAGE_ENGINE_PLUGIN, 0))
1739
if (db_type->state != SHOW_OPTION_YES ||
1740
(db_type->flush_logs && db_type->flush_logs(db_type)))
1746
static const char *check_lowercase_names(handler *file, const char *path,
1749
if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
1752
/* Ensure that table handler get path in lower case */
1753
if (tmp_path != path)
1754
strmov(tmp_path, path);
1757
we only should turn into lowercase database/table part
1758
so start the process after homedirectory
1760
my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
1766
An interceptor to hijack the text of the error message without
1767
setting an error in the thread. We need the text to present it
1768
in the form of a warning to the user.
1771
struct Ha_delete_table_error_handler: public Internal_error_handler
1774
virtual bool handle_error(uint sql_errno,
1775
const char *message,
1776
MYSQL_ERROR::enum_warning_level level,
1778
char buff[MYSQL_ERRMSG_SIZE];
1783
Ha_delete_table_error_handler::
1784
handle_error(uint sql_errno,
1785
const char *message,
1786
MYSQL_ERROR::enum_warning_level level,
1789
/* Grab the error message */
1790
strmake(buff, message, sizeof(buff)-1);
1796
This should return ENOENT if the file doesn't exists.
1797
The .frm file will be deleted only if we return 0 or ENOENT
1799
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
1800
const char *db, const char *alias, bool generate_warning)
1803
char tmp_path[FN_REFLEN];
1806
TABLE_SHARE dummy_share;
1807
DBUG_ENTER("ha_delete_table");
1809
bzero((char*) &dummy_table, sizeof(dummy_table));
1810
bzero((char*) &dummy_share, sizeof(dummy_share));
1811
dummy_table.s= &dummy_share;
1813
/* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
1814
if (table_type == NULL ||
1815
! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
1816
DBUG_RETURN(ENOENT);
1818
path= check_lowercase_names(file, path, tmp_path);
1819
if ((error= file->ha_delete_table(path)) && generate_warning)
1822
Because file->print_error() use my_error() to generate the error message
1823
we use an internal error handler to intercept it and store the text
1824
in a temporary buffer. Later the message will be presented to user
1827
Ha_delete_table_error_handler ha_delete_table_error_handler;
1829
/* Fill up strucutures that print_error may need */
1830
dummy_share.path.str= (char*) path;
1831
dummy_share.path.length= strlen(path);
1832
dummy_share.db.str= (char*) db;
1833
dummy_share.db.length= strlen(db);
1834
dummy_share.table_name.str= (char*) alias;
1835
dummy_share.table_name.length= strlen(alias);
1836
dummy_table.alias= alias;
1838
file->change_table_ptr(&dummy_table, &dummy_share);
1840
thd->push_internal_handler(&ha_delete_table_error_handler);
1841
file->print_error(error, 0);
1843
thd->pop_internal_handler();
1846
XXX: should we convert *all* errors to warnings here?
1847
What if the error is fatal?
1849
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_ERROR, error,
1850
ha_delete_table_error_handler.buff);
950
1856
/****************************************************************************
951
1857
** General handler functions
952
1858
****************************************************************************/
953
handler::~handler(void)
955
assert(locked == false);
956
/* TODO: assert(inited == NONE); */
960
1859
handler *handler::clone(MEM_ROOT *mem_root)
962
1861
handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
964
1863
Allocate handler->ref here because otherwise ha_open will allocate it
965
on this->table->mem_root and we will not be able to reclaim that memory
1864
on this->table->mem_root and we will not be able to reclaim that memory
966
1865
when the clone handler object is destroyed.
968
if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1867
if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
970
1869
if (new_handler && !new_handler->ha_open(table,
971
1870
table->s->normalized_path.str,
973
1872
HA_OPEN_IGNORE_IF_LOCKED))
974
1873
return new_handler;
978
int handler::ha_index_init(uint32_t idx, bool sorted)
981
assert(inited == NONE);
982
if (!(result= index_init(idx, sorted)))
988
int handler::ha_index_end()
990
assert(inited==INDEX);
996
int handler::ha_rnd_init(bool scan)
999
assert(inited==NONE || (inited==RND && scan));
1000
inited= (result= rnd_init(scan)) ? NONE: RND;
1005
int handler::ha_rnd_end()
1007
assert(inited==RND);
1012
int handler::ha_index_or_rnd_end()
1014
return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1017
handler::Table_flags handler::ha_table_flags() const
1019
return cached_table_flags;
1022
void handler::ha_start_bulk_insert(ha_rows rows)
1024
estimation_rows_to_insert= rows;
1025
start_bulk_insert(rows);
1028
int handler::ha_end_bulk_insert()
1030
estimation_rows_to_insert= 0;
1031
return end_bulk_insert();
1034
void handler::change_table_ptr(Table *table_arg, TableShare *share)
1040
const key_map *handler::keys_to_use_for_scanning()
1042
return &key_map_empty;
1045
bool handler::has_transactions()
1047
return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1050
1879
void handler::ha_statistic_increment(ulong SSV::*offset) const
1052
1881
status_var_increment(table->in_use->status_var.*offset);
1055
void **handler::ha_data(Session *session) const
1057
return session_ha_data(session, engine);
1060
Session *handler::ha_session(void) const
1062
assert(!table || !table->in_use || table->in_use == current_session);
1063
return (table && table->in_use) ? table->in_use : current_session;
1067
bool handler::is_fatal_error(int error, uint32_t flags)
1070
((flags & HA_CHECK_DUP_KEY) &&
1071
(error == HA_ERR_FOUND_DUPP_KEY ||
1072
error == HA_ERR_FOUND_DUPP_UNIQUE)))
1078
ha_rows handler::records() { return stats.records; }
1884
void **handler::ha_data(THD *thd) const
1886
return thd_ha_data(thd, ht);
1889
THD *handler::ha_thd(void) const
1891
DBUG_ASSERT(!table || !table->in_use || table->in_use == current_thd);
1892
return (table && table->in_use) ? table->in_use : current_thd;
1897
Get tablespace name from handler
1898
Returns the tablespace name associated
1899
with the table or NULL if not defined
1902
char* handler::get_tablespace_name()
1904
return table->s->tablespace;
1081
1908
Open database-handler.
2709
static bool update_frm_version(TABLE *table)
2711
char path[FN_REFLEN];
2714
DBUG_ENTER("update_frm_version");
2717
No need to update frm version in case table was created or checked
2718
by server with the same version. This also ensures that we do not
2719
update frm version for temporary tables as this code doesn't support
2722
if (table->s->mysql_version == MYSQL_VERSION_ID)
2725
strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
2727
if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
2730
char *key= table->s->table_cache_key.str;
2731
uint key_length= table->s->table_cache_key.length;
2733
HASH_SEARCH_STATE state;
2735
int4store(version, MYSQL_VERSION_ID);
2737
if ((result= my_pwrite(file,(uchar*) version,4,51L,MYF_RW)))
2740
for (entry=(TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state);
2742
entry= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state))
2743
entry->s->mysql_version= MYSQL_VERSION_ID;
2747
VOID(my_close(file,MYF(MY_WME)));
2748
DBUG_RETURN(result);
1802
2755
key if error because of duplicated keys
1804
uint32_t handler::get_dup_key(int error)
2757
uint handler::get_dup_key(int error)
1806
table->file->errkey = (uint32_t) -1;
2759
DBUG_ENTER("handler::get_dup_key");
2760
table->file->errkey = (uint) -1;
1807
2761
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
1808
2762
error == HA_ERR_FOUND_DUPP_UNIQUE ||
1809
2763
error == HA_ERR_DROP_INDEX_FK)
1810
2764
info(HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK);
1811
return(table->file->errkey);
2765
DBUG_RETURN(table->file->errkey);
2770
Delete all files with extension from bas_ext().
2772
@param name Base name of table
2775
We assume that the handler may return more extensions than
2776
was actually used for the file.
2779
0 If we successfully deleted at least one file from base_ext and
2780
didn't get any other errors than ENOENT
2784
int handler::delete_table(const char *name)
2787
int enoent_or_zero= ENOENT; // Error if no file was deleted
2788
char buff[FN_REFLEN];
2790
for (const char **ext=bas_ext(); *ext ; ext++)
2792
fn_format(buff, name, "", *ext, MY_UNPACK_FILENAME|MY_APPEND_EXT);
2793
if (my_delete_with_symlink(buff, MYF(0)))
2795
if ((error= my_errno) != ENOENT)
2799
enoent_or_zero= 0; // No error for ENOENT
2800
error= enoent_or_zero;
2806
int handler::rename_table(const char * from, const char * to)
2809
for (const char **ext= bas_ext(); *ext ; ext++)
2811
if (rename_file_ext(from, to, *ext))
2813
if ((error=my_errno) != ENOENT)
1814
2822
void handler::drop_table(const char *name)
1817
engine->deleteTable(ha_session(), name);
1822
2830
Performs checks upon the table.
1824
@param session thread doing CHECK Table operation
2832
@param thd thread doing CHECK TABLE operation
1825
2833
@param check_opt options from the parser
2100
3226
** Some general functions that isn't in the handler class
2101
3227
****************************************************************************/
3230
Initiates table-file and calls appropriate database-creator.
3237
int ha_create_table(THD *thd, const char *path,
3238
const char *db, const char *table_name,
3239
HA_CREATE_INFO *create_info,
3240
bool update_create_info)
3244
char name_buff[FN_REFLEN];
3247
DBUG_ENTER("ha_create_table");
3249
init_tmp_table_share(thd, &share, db, 0, table_name, path);
3250
if (open_table_def(thd, &share, 0) ||
3251
open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
3255
if (update_create_info)
3256
update_create_info_from_table(create_info, &table);
3258
name= check_lowercase_names(table.file, share.path.str, name_buff);
3260
error= table.file->ha_create(name, &table, create_info);
3261
VOID(closefrm(&table, 0));
3264
strxmov(name_buff, db, ".", table_name, NullS);
3265
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
3268
free_table_share(&share);
3269
DBUG_RETURN(error != 0);
3273
Try to discover table from engine.
3276
If found, write the frm file to disk.
3279
-1 Table did not exists
3283
> 0 Error, table existed but could not be created
3285
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
3290
char path[FN_REFLEN];
3291
HA_CREATE_INFO create_info;
3294
DBUG_ENTER("ha_create_table_from_engine");
3295
DBUG_PRINT("enter", ("name '%s'.'%s'", db, name));
3297
bzero((uchar*) &create_info,sizeof(create_info));
3298
if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
3300
/* Table could not be discovered and thus not created */
3305
Table exists in handler and could be discovered
3306
frmblob and frmlen are set, write the frm to disk
3309
build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
3310
// Save the frm file
3311
error= writefrm(path, frmblob, frmlen);
3312
my_free(frmblob, MYF(0));
3316
init_tmp_table_share(thd, &share, db, 0, name, path);
3317
if (open_table_def(thd, &share, 0))
3321
if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
3323
free_table_share(&share);
3327
update_create_info_from_table(&create_info, &table);
3328
create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
3330
check_lowercase_names(table.file, path, path);
3331
error=table.file->ha_create(path, &table, &create_info);
3332
VOID(closefrm(&table, 1));
3334
DBUG_RETURN(error != 0);
2104
3337
void st_ha_check_opt::init()
3339
flags= sql_flags= 0;
3340
sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
3438
Try to discover one table from handler(s).
3441
-1 Table did not exists
3443
0 OK. In this case *frmblob and *frmlen are set
3445
>0 error. frmblob and frmlen may not be set
3447
struct st_discover_args
3455
static my_bool discover_handlerton(THD *thd, plugin_ref plugin,
3458
st_discover_args *vargs= (st_discover_args *)arg;
3459
handlerton *hton= plugin_data(plugin, handlerton *);
3460
if (hton->state == SHOW_OPTION_YES && hton->discover &&
3461
(!(hton->discover(hton, thd, vargs->db, vargs->name,
3469
int ha_discover(THD *thd, const char *db, const char *name,
3470
uchar **frmblob, size_t *frmlen)
3472
int error= -1; // Table does not exist in any handler
3473
DBUG_ENTER("ha_discover");
3474
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
3475
st_discover_args args= {db, name, frmblob, frmlen};
3477
if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
3480
if (plugin_foreach(thd, discover_handlerton,
3481
MYSQL_STORAGE_ENGINE_PLUGIN, &args))
3485
status_var_increment(thd->status_var.ha_discover_count);
3491
Call this function in order to give the handler the possiblity
3492
to ask engine if there are any new tables that should be written to disk
3493
or any dropped tables that need to be removed from disk
3495
struct st_find_files_args
3501
List<LEX_STRING> *files;
3505
Ask handler if the table exists in engine.
3507
HA_ERR_NO_SUCH_TABLE Table does not exist
3509
HA_ERR_TABLE_EXIST Table exists
3513
struct st_table_exists_in_engine_args
3520
static my_bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
3523
st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
3524
handlerton *hton= plugin_data(plugin, handlerton *);
3526
int err= HA_ERR_NO_SUCH_TABLE;
3528
if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3529
err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
3532
if (vargs->err == HA_ERR_TABLE_EXIST)
3538
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
3540
DBUG_ENTER("ha_table_exists_in_engine");
3541
DBUG_PRINT("enter", ("db: %s, name: %s", db, name));
3542
st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3543
plugin_foreach(thd, table_exists_in_engine_handlerton,
3544
MYSQL_STORAGE_ENGINE_PLUGIN, &args);
3545
DBUG_PRINT("exit", ("error: %d", args.err));
3546
DBUG_RETURN(args.err);
2202
3550
Calculate cost of 'index only' scan for given index and number of records
2204
3552
@param keynr Index number
2517
3868
@retval other Error
2520
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
3871
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
2521
3872
RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
2522
uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3873
uint n_ranges, uint mode, HANDLER_BUFFER *buf)
2526
3877
Item *pushed_cond= NULL;
2527
3878
handler *new_h2;
2528
keyno= h_in->active_index;
3879
DBUG_ENTER("DsMrr_impl::dsmrr_init");
3880
keyno= h->active_index;
3881
DBUG_ASSERT(h2 == NULL);
2530
3882
if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
2532
use_default_impl= true;
2533
return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3884
use_default_impl= TRUE;
3885
DBUG_RETURN(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
2534
3886
n_ranges, mode, buf));
2536
3888
rowids_buf= buf->buffer;
2537
3889
//psergey-todo: don't add key_length as it is not needed anymore
2538
rowids_buf += key->key_length + h_in->ref_length;
3890
rowids_buf += key->key_length + h->ref_length;
2540
3892
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
2541
3893
rowids_buf_end= buf->buffer_end;
2543
elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
2544
rowids_buf_last= rowids_buf +
3895
elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3896
rowids_buf_last= rowids_buf +
2545
3897
((rowids_buf_end - rowids_buf)/ elem_size)*
2547
3899
rowids_buf_end= rowids_buf_last;
2549
3901
/* Create a separate handler object to do rndpos() calls. */
2550
Session *session= current_session;
2551
if (!(new_h2= h_in->clone(session->mem_root)) ||
2552
new_h2->ha_external_lock(session, F_RDLCK))
3902
THD *thd= current_thd;
3903
if (!(new_h2= h->clone(thd->mem_root)) ||
3904
new_h2->ha_external_lock(thd, F_RDLCK))
2558
if (keyno == h_in->pushed_idx_cond_keyno)
2559
pushed_cond= h_in->pushed_idx_cond;
2560
if (h_in->ha_index_end())
3910
if (keyno == h->pushed_idx_cond_keyno)
3911
pushed_cond= h->pushed_idx_cond;
3912
if (h->ha_index_end())
2832
4194
OUT If DS-MRR is choosen, cost of DS-MRR scan
2833
4195
else the value is not modified
2835
@retval true Default MRR implementation should be used
2836
@retval false DS-MRR implementation should be used
4197
@retval TRUE Default MRR implementation should be used
4198
@retval FALSE DS-MRR implementation should be used
2839
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
2840
uint32_t *bufsz, COST_VECT *cost)
4201
bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
4202
uint *bufsz, COST_VECT *cost)
2842
4204
COST_VECT dsmrr_cost;
2844
Session *session= current_session;
2845
if ((session->variables.optimizer_use_mrr == 2) ||
4206
THD *thd= current_thd;
4207
if ((thd->variables.optimizer_use_mrr == 2) ||
2846
4208
(*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
2847
(keyno == table->s->primary_key &&
2848
h->primary_key_is_clustered()) ||
4209
(keyno == table->s->primary_key &&
4210
h->primary_key_is_clustered()) ||
2849
4211
key_uses_partial_cols(keyno))
2851
4213
/* Use the default implementation */
2852
4214
*flags |= HA_MRR_USE_DEFAULT_IMPL;
2856
uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4218
uint add_len= table->key_info[keyno].key_length + h->ref_length;
2857
4219
*bufsz -= add_len;
2858
4220
if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
2860
4222
*bufsz += add_len;
2862
4224
bool force_dsmrr;
2864
4226
If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
2865
4227
DS-MRR and Default implementations cost. This allows one to force use of
2866
4228
DS-MRR whenever it is applicable without affecting other cost-based
2869
if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4231
if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
2870
4232
dsmrr_cost.total_cost() > cost->total_cost())
2871
4233
dsmrr_cost= *cost;
3212
static bool stat_print(Session *session, const char *type, uint32_t type_len,
3213
const char *file, uint32_t file_len,
3214
const char *status, uint32_t status_len)
3216
Protocol *protocol= session->protocol;
3217
protocol->prepareForResend();
3218
protocol->store(type, type_len);
3219
protocol->store(file, file_len);
3220
protocol->store(status, status_len);
4582
Returns a list of all known extensions.
4584
No mutexes, worst case race is a minor surplus memory allocation
4585
We have to recreate the extension map if mysqld is restarted (for example
4589
pointer pointer to TYPELIB structure
4591
static my_bool exts_handlerton(THD *unused, plugin_ref plugin,
4594
List<char> *found_exts= (List<char> *) arg;
4595
handlerton *hton= plugin_data(plugin, handlerton *);
4597
if (hton->state == SHOW_OPTION_YES && hton->create &&
4598
(file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
4600
List_iterator_fast<char> it(*found_exts);
4601
const char **ext, *old_ext;
4603
for (ext= file->bas_ext(); *ext; ext++)
4605
while ((old_ext= it++))
4607
if (!strcmp(old_ext, *ext))
4611
found_exts->push_back((char *) *ext);
4620
TYPELIB *ha_known_exts(void)
4622
if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
4624
List<char> found_exts;
4625
const char **ext, *old_ext;
4627
known_extensions_id= mysys_usage_id;
4629
plugin_foreach(NULL, exts_handlerton,
4630
MYSQL_STORAGE_ENGINE_PLUGIN, &found_exts);
4632
ext= (const char **) my_once_alloc(sizeof(char *)*
4633
(found_exts.elements+1),
4634
MYF(MY_WME | MY_FAE));
4636
DBUG_ASSERT(ext != 0);
4637
known_extensions.count= found_exts.elements;
4638
known_extensions.type_names= ext;
4640
List_iterator_fast<char> it(found_exts);
4641
while ((old_ext= it++))
4645
return &known_extensions;
4649
static bool stat_print(THD *thd, const char *type, uint type_len,
4650
const char *file, uint file_len,
4651
const char *status, uint status_len)
4653
Protocol *protocol= thd->protocol;
4654
protocol->prepare_for_resend();
4655
protocol->store(type, type_len, system_charset_info);
4656
protocol->store(file, file_len, system_charset_info);
4657
protocol->store(status, status_len, system_charset_info);
3221
4658
if (protocol->write())
3226
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
4663
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
3228
4665
List<Item> field_list;
3229
Protocol *protocol= session->protocol;
4666
Protocol *protocol= thd->protocol;
3232
4669
field_list.push_back(new Item_empty_string("Type",10));
3233
4670
field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
3234
4671
field_list.push_back(new Item_empty_string("Status",10));
3236
if (protocol->sendFields(&field_list,
3237
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
4673
if (protocol->send_fields(&field_list,
4674
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
3240
result= engine->show_status(session, stat_print, stat) ? 1 : 0;
4677
result= db_type->show_status &&
4678
db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
3257
4695
- table is not mysql.event
3260
static bool log_row_for_replication(Table* table,
3261
const unsigned char *before_record,
3262
const unsigned char *after_record)
3264
Session *const session= table->in_use;
3266
switch (session->lex->sql_command)
3268
case SQLCOM_REPLACE:
3270
case SQLCOM_REPLACE_SELECT:
3271
case SQLCOM_INSERT_SELECT:
3272
case SQLCOM_CREATE_TABLE:
3273
transaction_services.insertRecord(session, table);
3277
case SQLCOM_UPDATE_MULTI:
3278
transaction_services.updateRecord(session, table, before_record, after_record);
3282
case SQLCOM_DELETE_MULTI:
3283
transaction_services.deleteRecord(session, table);
4698
static bool check_table_binlog_row_based(THD *thd, TABLE *table)
4700
if (table->s->cached_row_logging_check == -1)
4702
int const check(table->s->tmp_table == NO_TMP_TABLE &&
4703
binlog_filter->db_ok(table->s->db.str));
4704
table->s->cached_row_logging_check= check;
4707
DBUG_ASSERT(table->s->cached_row_logging_check == 0 ||
4708
table->s->cached_row_logging_check == 1);
4710
return (thd->current_stmt_binlog_row_based &&
4711
table->s->cached_row_logging_check &&
4712
(thd->options & OPTION_BIN_LOG) &&
4713
mysql_bin_log.is_open());
4718
Write table maps for all (manually or automatically) locked tables
4721
This function will generate and write table maps for all tables
4722
that are locked by the thread 'thd'. Either manually locked
4723
(stored in THD::locked_tables) and automatically locked (stored
4724
in THD::lock) are considered.
4726
@param thd Pointer to THD structure
4729
@retval 1 Failed to write all table maps
4736
static int write_locked_table_maps(THD *thd)
4738
DBUG_ENTER("write_locked_table_maps");
4739
DBUG_PRINT("enter", ("thd: 0x%lx thd->lock: 0x%lx thd->locked_tables: 0x%lx "
4740
"thd->extra_lock: 0x%lx",
4741
(long) thd, (long) thd->lock,
4742
(long) thd->locked_tables, (long) thd->extra_lock));
4744
if (thd->get_binlog_table_maps() == 0)
4746
MYSQL_LOCK *locks[3];
4747
locks[0]= thd->extra_lock;
4748
locks[1]= thd->lock;
4749
locks[2]= thd->locked_tables;
4750
for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4752
MYSQL_LOCK const *const lock= locks[i];
4756
TABLE **const end_ptr= lock->table + lock->table_count;
4757
for (TABLE **table_ptr= lock->table ;
4758
table_ptr != end_ptr ;
4761
TABLE *const table= *table_ptr;
4762
DBUG_PRINT("info", ("Checking table %s", table->s->table_name.str));
4763
if (table->current_lock == F_WRLCK &&
4764
check_table_binlog_row_based(thd, table))
4766
int const has_trans= table->file->has_transactions();
4767
int const error= thd->binlog_write_table_map(table, has_trans);
4769
If an error occurs, it is the responsibility of the caller to
4770
roll back the transaction.
4772
if (unlikely(error))
4782
typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
4784
static int binlog_log_row(TABLE* table,
4785
const uchar *before_record,
4786
const uchar *after_record,
4789
if (table->no_replicate)
4792
THD *const thd= table->in_use;
4794
if (check_table_binlog_row_based(thd, table))
4796
DBUG_DUMP("read_set 10", (uchar*) table->read_set->bitmap,
4797
(table->s->fields + 7) / 8);
3287
For everything else we ignore the event (since it just involves a temp table)
4799
If there are no table maps written to the binary log, this is
4800
the first row handled in this statement. In that case, we need
4801
to write table maps for all locked tables to the binary log.
4803
if (likely(!(error= write_locked_table_maps(thd))))
4805
bool const has_trans= table->file->has_transactions();
4806
error= (*log_func)(thd, table, has_trans, before_record, after_record);
3293
return false; //error;
4809
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
3296
int handler::ha_external_lock(Session *session, int lock_type)
4812
int handler::ha_external_lock(THD *thd, int lock_type)
4814
DBUG_ENTER("handler::ha_external_lock");
3299
4816
Whether this is lock or unlock, this should be true, and is to verify that
3300
4817
if get_auto_increment() was called (thus may have reserved intervals or
3301
4818
taken a table lock), ha_release_auto_increment() was too.
3303
assert(next_insert_id == 0);
4820
DBUG_ASSERT(next_insert_id == 0);
3306
4823
We cache the table flags if the locking succeeded. Otherwise, we
3307
4824
keep them as they were when they were fetched in ha_open().
3309
DRIZZLE_EXTERNAL_LOCK(lock_type);
4826
MYSQL_EXTERNAL_LOCK(lock_type);
3311
int error= external_lock(session, lock_type);
4828
int error= external_lock(thd, lock_type);
3312
4829
if (error == 0)
3313
4830
cached_table_flags= table_flags();
3321
4838
int handler::ha_reset()
4840
DBUG_ENTER("ha_reset");
3323
4841
/* Check that we have called all proper deallocation functions */
3324
assert((unsigned char*) table->def_read_set.bitmap +
4842
DBUG_ASSERT((uchar*) table->def_read_set.bitmap +
3325
4843
table->s->column_bitmap_size ==
3326
(unsigned char*) table->def_write_set.bitmap);
3327
assert(bitmap_is_set_all(&table->s->all_set));
3328
assert(table->key_read == 0);
4844
(uchar*) table->def_write_set.bitmap);
4845
DBUG_ASSERT(bitmap_is_set_all(&table->s->all_set));
4846
DBUG_ASSERT(table->key_read == 0);
3329
4847
/* ensure that ha_index_end / ha_rnd_end has been called */
3330
assert(inited == NONE);
4848
DBUG_ASSERT(inited == NONE);
3331
4849
/* Free cache used by filesort */
3332
4850
free_io_cache(table);
3333
4851
/* reset the bitmaps to point to defaults */
3334
4852
table->default_column_bitmaps();
4853
DBUG_RETURN(reset());
3339
int handler::ha_write_row(unsigned char *buf)
4857
int handler::ha_write_row(uchar *buf)
3342
DRIZZLE_INSERT_ROW_START();
3345
* If we have a timestamp column, update it to the current time
3347
* @TODO Technically, the below two lines can be take even further out of the
3348
* handler interface and into the fill_record() method.
3350
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
3351
table->timestamp_field->set_time();
4860
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4861
DBUG_ENTER("handler::ha_write_row");
4862
MYSQL_INSERT_ROW_START();
3353
4864
mark_trx_read_write();
3355
4866
if (unlikely(error= write_row(buf)))
3358
if (unlikely(log_row_for_replication(table, 0, buf)))
3359
return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
3361
DRIZZLE_INSERT_ROW_END();
4868
if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4869
DBUG_RETURN(error); /* purecov: inspected */
4870
MYSQL_INSERT_ROW_END();
3366
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4875
int handler::ha_update_row(const uchar *old_data, uchar *new_data)
4878
Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
3371
4881
Some storage engines require that the new record is in record[0]
3372
4882
(and the old record is in record[1]).
3374
assert(new_data == table->record[0]);
4884
DBUG_ASSERT(new_data == table->record[0]);
3376
4886
mark_trx_read_write();
3378
4888
if (unlikely(error= update_row(old_data, new_data)))
3381
if (unlikely(log_row_for_replication(table, old_data, new_data)))
3382
return HA_ERR_RBR_LOGGING_FAILED;
4890
if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
3387
int handler::ha_delete_row(const unsigned char *buf)
4895
int handler::ha_delete_row(const uchar *buf)
4898
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
3391
4900
mark_trx_read_write();
3393
4902
if (unlikely(error= delete_row(buf)))
3396
if (unlikely(log_row_for_replication(table, buf, 0)))
3397
return HA_ERR_RBR_LOGGING_FAILED;
4904
if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4913
use_hidden_primary_key() is called in case of an update/delete when
4914
(table_flags() and HA_PRIMARY_KEY_REQUIRED_FOR_DELETE) is defined
4915
but we don't have a primary key
4917
void handler::use_hidden_primary_key()
4919
/* fallback to use all columns in the table to identify row */
4920
table->use_all_columns();