19
23
Handler-calling-functions
22
#ifdef USE_PRAGMA_IMPLEMENTATION
23
#pragma implementation // gcc: Class implementation
26
#include <drizzled/server_includes.h>
27
#include "rpl_filter.h"
28
#include <drizzled/drizzled_error_messages.h>
31
While we have legacy_db_type, we have this array to
32
check for dups and to find handlerton from legacy_db_type.
33
Remove when legacy_db_type is finally gone
35
st_plugin_int *hton2plugin[MAX_HA];
37
static handlerton *installed_htons[128];
39
#define BITMAP_STACKBUF_SIZE (128/8)
41
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NullS,0}, {NullS,0} };
43
/* number of entries in handlertons[] */
26
#include "drizzled/server_includes.h"
27
#include "mysys/hash.h"
28
#include "drizzled/error.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/data_home.h"
31
#include "drizzled/probes.h"
32
#include "drizzled/sql_parse.h"
33
#include "drizzled/cost_vect.h"
34
#include "drizzled/session.h"
35
#include "drizzled/sql_base.h"
36
#include "drizzled/transaction_services.h"
37
#include "drizzled/lock.h"
38
#include "drizzled/item/int.h"
39
#include "drizzled/item/empty_string.h"
40
#include "drizzled/unireg.h" // for mysql_frm_type
41
#include "drizzled/field/timestamp.h"
42
#include "drizzled/message/table.pb.h"
46
extern drizzled::TransactionServices transaction_services;
48
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
50
/* number of entries in storage_engines[] */
44
51
uint32_t total_ha= 0;
45
/* number of storage engines (from handlertons[]) that support 2pc */
52
/* number of storage engines (from storage_engines[]) that support 2pc */
46
53
uint32_t total_ha_2pc= 0;
47
54
/* size of savepoint storage area (see ha_init) */
48
55
uint32_t savepoint_alloc_size= 0;
50
static const LEX_STRING sys_table_aliases[]=
52
{ C_STRING_WITH_LEN("INNOBASE") }, { C_STRING_WITH_LEN("INNODB") },
53
{ C_STRING_WITH_LEN("HEAP") }, { C_STRING_WITH_LEN("MEMORY") },
57
57
const char *ha_row_type[] = {
58
58
"", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
61
61
const char *tx_isolation_names[] =
62
62
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
64
65
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
tx_isolation_names, NULL};
67
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
68
uint known_extensions_id= 0;
72
static plugin_ref ha_default_plugin(THD *thd)
74
if (thd->variables.table_plugin)
75
return thd->variables.table_plugin;
76
return my_plugin_lock(thd, &global_system_variables.table_plugin);
81
Return the default storage engine handlerton for thread
83
@param ha_default_handlerton(thd)
84
@param thd current thread
89
handlerton *ha_default_handlerton(THD *thd)
91
plugin_ref plugin= ha_default_plugin(thd);
93
handlerton *hton= plugin_data(plugin, handlerton*);
100
Return the storage engine handlerton for the supplied name
102
@param thd current thread
103
@param name name of storage engine
106
pointer to storage engine plugin handle
108
plugin_ref ha_resolve_by_name(THD *thd, const LEX_STRING *name)
110
const LEX_STRING *table_alias;
114
/* my_strnncoll is a macro and gcc doesn't do early expansion of macro */
115
if (thd && !my_charset_latin1.coll->strnncoll(&my_charset_latin1,
116
(const uchar *)name->str, name->length,
117
(const uchar *)STRING_WITH_LEN("DEFAULT"), 0))
118
return ha_default_plugin(thd);
120
if ((plugin= my_plugin_lock_by_name(thd, name, DRIZZLE_STORAGE_ENGINE_PLUGIN)))
122
handlerton *hton= plugin_data(plugin, handlerton *);
123
if (!(hton->flags & HTON_NOT_USER_SELECTABLE))
127
unlocking plugin immediately after locking is relatively low cost.
129
plugin_unlock(thd, plugin);
133
We check for the historical aliases.
135
for (table_alias= sys_table_aliases; table_alias->str; table_alias+= 2)
137
if (!my_strnncoll(&my_charset_latin1,
138
(const uchar *)name->str, name->length,
139
(const uchar *)table_alias->str, table_alias->length))
141
name= table_alias + 1;
150
plugin_ref ha_lock_engine(THD *thd, handlerton *hton)
154
st_plugin_int **plugin= hton2plugin + hton->slot;
156
return my_plugin_lock(thd, &plugin);
162
handlerton *ha_resolve_by_legacy_type(THD *thd, enum legacy_db_type db_type)
166
case DB_TYPE_DEFAULT:
167
return ha_default_handlerton(thd);
169
if (db_type > DB_TYPE_UNKNOWN && db_type < DB_TYPE_DEFAULT &&
170
(plugin= ha_lock_engine(thd, installed_htons[db_type])))
171
return plugin_data(plugin, handlerton*);
173
case DB_TYPE_UNKNOWN:
180
Use other database handler if databasehandler is not compiled in.
182
handlerton *ha_checktype(THD *thd, enum legacy_db_type database_type,
183
bool no_substitute, bool report_error)
185
handlerton *hton= ha_resolve_by_legacy_type(thd, database_type);
186
if (ha_storage_engine_is_enabled(hton))
193
const char *engine_name= ha_resolve_storage_engine_name(hton);
194
my_error(ER_FEATURE_DISABLED,MYF(0),engine_name,engine_name);
199
switch (database_type) {
201
return ha_resolve_by_legacy_type(thd, DB_TYPE_HASH);
206
return ha_default_handlerton(thd);
210
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
215
if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
217
if ((file= db_type->create(db_type, share, alloc)))
222
Try the default table type
223
Here the call to current_thd() is ok as we call this function a lot of
224
times but we enter this branch very seldom.
226
return(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
66
tx_isolation_names, NULL};
310
149
/* Allocate a pointer array for the error message strings. */
311
150
if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
313
my_free((uchar*) errmsgs, MYF(0));
152
free((unsigned char*) errmsgs);
318
int ha_finalize_handlerton(st_plugin_int *plugin)
320
handlerton *hton= (handlerton *)plugin->data;
325
case SHOW_OPTION_DISABLED:
327
case SHOW_OPTION_YES:
328
if (installed_htons[hton->db_type] == hton)
329
installed_htons[hton->db_type]= NULL;
333
if (hton && plugin->plugin->deinit)
334
(void)plugin->plugin->deinit(hton);
336
my_free((uchar*)hton, MYF(0));
342
int ha_initialize_handlerton(st_plugin_int *plugin)
346
hton= (handlerton *)my_malloc(sizeof(handlerton),
347
MYF(MY_WME | MY_ZEROFILL));
349
FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
351
This was detected after adding get_backup_engine member to handlerton
352
structure. Apparently get_backup_engine was not NULL even though it was
355
memset(hton, 0, sizeof(hton));
356
/* Historical Requirement */
357
plugin->data= hton; // shortcut for the future
358
if (plugin->plugin->init)
360
if (plugin->plugin->init(hton))
362
sql_print_error("Plugin '%s' init function returned error.",
369
the switch below and hton->state should be removed when
370
command-line options for plugins will be implemented
372
switch (hton->state) {
375
case SHOW_OPTION_YES:
378
/* now check the db_type for conflict */
379
if (hton->db_type <= DB_TYPE_UNKNOWN ||
380
hton->db_type >= DB_TYPE_DEFAULT ||
381
installed_htons[hton->db_type])
383
int idx= (int) DB_TYPE_FIRST_DYNAMIC;
385
while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
388
if (idx == (int) DB_TYPE_DEFAULT)
390
sql_print_warning("Too many storage engines!");
393
if (hton->db_type != DB_TYPE_UNKNOWN)
394
sql_print_warning("Storage engine '%s' has conflicting typecode. "
395
"Assigning value %d.", plugin->plugin->name, idx);
396
hton->db_type= (enum legacy_db_type) idx;
398
installed_htons[hton->db_type]= hton;
399
tmp= hton->savepoint_offset;
400
hton->savepoint_offset= savepoint_alloc_size;
401
savepoint_alloc_size+= tmp;
402
hton->slot= total_ha++;
403
hton2plugin[hton->slot]=plugin;
410
hton->state= SHOW_OPTION_DISABLED;
415
This is entirely for legacy. We will create a new "disk based" hton and a
416
"memory" hton which will be configurable longterm. We should be able to
417
remove partition and myisammrg.
419
switch (hton->db_type) {
809
490
times per transaction.
812
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
493
void trans_register_ha(Session *session, bool all, StorageEngine *engine)
495
Session_TRANS *trans;
815
496
Ha_trx_info *ha_info;
819
trans= &thd->transaction.all;
820
thd->server_status|= SERVER_STATUS_IN_TRANS;
500
trans= &session->transaction.all;
501
session->server_status|= SERVER_STATUS_IN_TRANS;
823
trans= &thd->transaction.stmt;
504
trans= &session->transaction.stmt;
825
ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
506
ha_info= session->ha_data[engine->getSlot()].ha_info + static_cast<unsigned>(all);
827
508
if (ha_info->is_started())
828
509
return; /* already registered, return */
830
ha_info->register_ha(trans, ht_arg);
832
trans->no_2pc|=(ht_arg->prepare==0);
833
if (thd->transaction.xid_state.xid.is_null())
834
thd->transaction.xid_state.xid.set(thd->query_id);
843
1 error, transaction was rolled back
845
int ha_prepare(THD *thd)
848
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
849
Ha_trx_info *ha_info= trans->ha_list;
852
for (; ha_info; ha_info= ha_info->next())
855
handlerton *ht= ha_info->ht();
856
status_var_increment(thd->status_var.ha_prepare_count);
859
if ((err= ht->prepare(ht, thd, all)))
861
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
862
ha_rollback_trans(thd, all);
869
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
870
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
871
ha_resolve_storage_engine_name(ht));
511
ha_info->register_ha(trans, engine);
513
trans->no_2pc|= not engine->has_2pc();
514
if (session->transaction.xid_state.xid.is_null())
515
session->transaction.xid_state.xid.set(session->query_id);
963
602
flags will not get propagated to its normal transaction's
966
assert(thd->transaction.stmt.ha_list == NULL ||
967
trans == &thd->transaction.stmt);
605
assert(session->transaction.stmt.ha_list == NULL ||
606
trans == &session->transaction.stmt);
969
if (thd->in_sub_stmt)
972
Since we don't support nested statement transactions in 5.0,
973
we can't commit or rollback stmt transactions while we are inside
974
stored functions or triggers. So we simply do nothing now.
975
TODO: This should be fixed in later ( >= 5.1) releases.
980
We assume that all statements which commit or rollback main transaction
981
are prohibited inside of stored functions or triggers. So they should
982
bail out with error even before ha_commit_trans() call. To be 100% safe
983
let us throw error in non-debug builds.
986
my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
993
if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
995
ha_rollback_trans(thd, all);
1001
&& ! thd->slave_thread
1004
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
1005
ha_rollback_trans(thd, all);
1010
must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
612
if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
614
ha_rollback_trans(session, all);
618
must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
1012
620
if (!trans->no_2pc && must_2pc)
1014
622
for (; ha_info && !error; ha_info= ha_info->next())
1017
handlerton *ht= ha_info->ht();
625
StorageEngine *engine= ha_info->engine();
1019
627
Do not call two-phase commit if this particular
1020
628
transaction is read-only. This allows for simpler
1026
634
Sic: we know that prepare() is not NULL since otherwise
1027
635
trans->no_2pc would have been set.
1029
if ((err= ht->prepare(ht, thd, all)))
637
if ((err= engine->prepare(session, all)))
1031
639
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1034
status_var_increment(thd->status_var.ha_prepare_count);
642
status_var_increment(session->status_var.ha_prepare_count);
1036
if (error || (is_real_trans && xid &&
1037
(error= !(cookie= tc_log->log_xid(thd, xid)))))
1039
ha_rollback_trans(thd, all);
646
ha_rollback_trans(session, all);
1044
error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1046
tc_log->unlog(cookie, xid);
651
error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1048
653
if (is_real_trans)
1049
start_waiting_global_read_lock(thd);
654
start_waiting_global_read_lock(session);
1056
661
This function does not care about global read lock. A caller should.
1058
int ha_commit_one_phase(THD *thd, bool all)
663
int ha_commit_one_phase(Session *session, bool all)
1061
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
1062
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
666
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
667
bool is_real_trans=all || session->transaction.all.ha_list == 0;
1063
668
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1066
671
for (; ha_info; ha_info= ha_info_next)
1069
handlerton *ht= ha_info->ht();
1070
if ((err= ht->commit(ht, thd, all)))
674
StorageEngine *engine= ha_info->engine();
675
if ((err= engine->commit(session, all)))
1072
677
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1075
status_var_increment(thd->status_var.ha_commit_count);
680
status_var_increment(session->status_var.ha_commit_count);
1076
681
ha_info_next= ha_info->next();
1077
682
ha_info->reset(); /* keep it conveniently zero-filled */
1079
684
trans->ha_list= 0;
1080
685
trans->no_2pc=0;
1081
686
if (is_real_trans)
1082
thd->transaction.xid_state.xid.null();
687
session->transaction.xid_state.xid.null();
1085
thd->variables.tx_isolation=thd->session_tx_isolation;
1086
thd->transaction.cleanup();
690
session->variables.tx_isolation=session->session_tx_isolation;
691
session->transaction.cleanup();
1093
int ha_rollback_trans(THD *thd, bool all)
698
int ha_rollback_trans(Session *session, bool all)
1096
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
701
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1097
702
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1098
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
703
bool is_real_trans=all || session->transaction.all.ha_list == 0;
1101
706
We must not rollback the normal transaction if a statement
1102
707
transaction is pending.
1104
assert(thd->transaction.stmt.ha_list == NULL ||
1105
trans == &thd->transaction.stmt);
709
assert(session->transaction.stmt.ha_list == NULL ||
710
trans == &session->transaction.stmt);
1107
if (thd->in_sub_stmt)
1110
If we are inside stored function or trigger we should not commit or
1111
rollback current statement transaction. See comment in ha_commit_trans()
1112
call for more information.
1117
my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
1122
714
for (; ha_info; ha_info= ha_info_next)
1125
handlerton *ht= ha_info->ht();
1126
if ((err= ht->rollback(ht, thd, all)))
717
StorageEngine *engine= ha_info->engine();
718
if ((err= engine->rollback(session, all)))
1127
719
{ // cannot happen
1128
720
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1131
status_var_increment(thd->status_var.ha_rollback_count);
723
status_var_increment(session->status_var.ha_rollback_count);
1132
724
ha_info_next= ha_info->next();
1133
725
ha_info->reset(); /* keep it conveniently zero-filled */
1135
727
trans->ha_list= 0;
1136
728
trans->no_2pc=0;
1137
729
if (is_real_trans)
1138
thd->transaction.xid_state.xid.null();
730
session->transaction.xid_state.xid.null();
1141
thd->variables.tx_isolation=thd->session_tx_isolation;
1142
thd->transaction.cleanup();
733
session->variables.tx_isolation=session->session_tx_isolation;
734
session->transaction.cleanup();
1146
thd->transaction_rollback_request= false;
738
session->transaction_rollback_request= false;
1149
741
If a non-transactional table was updated, warn; don't warn if this is a
1173
764
the user has used LOCK TABLES then that mechanism does not know to do the
1176
int ha_autocommit_or_rollback(THD *thd, int error)
767
int ha_autocommit_or_rollback(Session *session, int error)
1178
if (thd->transaction.stmt.ha_list)
769
if (session->transaction.stmt.ha_list)
1182
if (ha_commit_trans(thd, 0))
1187
(void) ha_rollback_trans(thd, 0);
1188
if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1189
(void) ha_rollback(thd);
1192
thd->variables.tx_isolation=thd->session_tx_isolation;
1203
static bool xacommit_handlerton(THD *unused1 __attribute__((unused)),
1207
handlerton *hton= plugin_data(plugin, handlerton *);
1208
if (hton->state == SHOW_OPTION_YES && hton->recover)
1210
hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
1211
((struct xahton_st *)arg)->result= 0;
1216
static bool xarollback_handlerton(THD *unused1 __attribute__((unused)),
1220
handlerton *hton= plugin_data(plugin, handlerton *);
1221
if (hton->state == SHOW_OPTION_YES && hton->recover)
1223
hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
1224
((struct xahton_st *)arg)->result= 0;
1230
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
1232
struct xahton_st xaop;
1236
plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
1237
DRIZZLE_STORAGE_ENGINE_PLUGIN, &xaop);
1243
recover() step of xa.
1246
there are three modes of operation:
1247
- automatic recover after a crash
1248
in this case commit_list != 0, tc_heuristic_recover==0
1249
all xids from commit_list are committed, others are rolled back
1250
- manual (heuristic) recover
1251
in this case commit_list==0, tc_heuristic_recover != 0
1252
DBA has explicitly specified that all prepared transactions should
1253
be committed (or rolled back).
1254
- no recovery (MySQL did not detect a crash)
1255
in this case commit_list==0, tc_heuristic_recover == 0
1256
there should be no prepared transactions in this case.
1260
int len, found_foreign_xids, found_my_xids;
1266
static bool xarecover_handlerton(THD *unused __attribute__((unused)),
1270
handlerton *hton= plugin_data(plugin, handlerton *);
1271
struct xarecover_st *info= (struct xarecover_st *) arg;
1274
if (hton->state == SHOW_OPTION_YES && hton->recover)
1276
while ((got= hton->recover(hton, info->list, info->len)) > 0 )
1278
sql_print_information("Found %d prepared transaction(s) in %s",
1279
got, ha_resolve_storage_engine_name(hton));
1280
for (int i=0; i < got; i ++)
1282
my_xid x=info->list[i].get_my_xid();
1283
if (!x) // not "mine" - that is generated by external TM
1285
xid_cache_insert(info->list+i, XA_PREPARED);
1286
info->found_foreign_xids++;
1291
info->found_my_xids++;
1295
if (info->commit_list ?
1296
hash_search(info->commit_list, (uchar *)&x, sizeof(x)) != 0 :
1297
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
1299
hton->commit_by_xid(hton, info->list+i);
1303
hton->rollback_by_xid(hton, info->list+i);
1306
if (got < info->len)
1313
int ha_recover(HASH *commit_list)
1315
struct xarecover_st info;
1316
info.found_foreign_xids= info.found_my_xids= 0;
1317
info.commit_list= commit_list;
1318
info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
1321
/* commit_list and tc_heuristic_recover cannot be set both */
1322
assert(info.commit_list==0 || tc_heuristic_recover==0);
1323
/* if either is set, total_ha_2pc must be set too */
1324
assert(info.dry_run || total_ha_2pc>(uint32_t)opt_bin_log);
1326
if (total_ha_2pc <= (uint32_t)opt_bin_log)
1329
if (info.commit_list)
1330
sql_print_information("Starting crash recovery...");
1333
#ifndef WILL_BE_DELETED_LATER
1336
for now, only InnoDB supports 2pc. It means we can always safely
1337
rollback all pending transactions, without risking inconsistent data
1340
assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
1341
tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
1346
for (info.len= MAX_XID_LIST_SIZE ;
1347
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1349
info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
1353
sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1357
plugin_foreach(NULL, xarecover_handlerton,
1358
DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1360
my_free((uchar*)info.list, MYF(0));
1361
if (info.found_foreign_xids)
1362
sql_print_warning("Found %d prepared XA transactions",
1363
info.found_foreign_xids);
1364
if (info.dry_run && info.found_my_xids)
1366
sql_print_error("Found %d prepared transactions! It means that mysqld was "
1367
"not shut down properly last time and critical recovery "
1368
"information (last binlog or %s file) was manually deleted "
1369
"after a crash. You have to start mysqld with "
1370
"--tc-heuristic-recover switch to commit or rollback "
1371
"pending transactions.",
1372
info.found_my_xids, opt_tc_log_file);
1375
if (info.commit_list)
1376
sql_print_information("Crash recovery finished.");
773
if (ha_commit_trans(session, 0))
778
(void) ha_rollback_trans(session, 0);
779
if (session->transaction_rollback_request)
780
(void) ha_rollback(session);
783
session->variables.tx_isolation=session->session_tx_isolation;
1381
793
return the list of XID's to a client, the same way SHOW commands do.
1397
809
field_list.push_back(new Item_int("bqual_length", 0, MY_INT32_NUM_DECIMAL_DIGITS));
1398
810
field_list.push_back(new Item_empty_string("data",XIDDATASIZE));
1400
if (protocol->send_fields(&field_list,
1401
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
812
if (protocol->sendFields(&field_list,
813
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
1404
816
pthread_mutex_lock(&LOCK_xid_cache);
1405
817
while ((xs= (XID_STATE*)hash_element(&xid_cache, i++)))
1407
819
if (xs->xa_state==XA_PREPARED)
1409
protocol->prepare_for_resend();
1410
protocol->store_int64_t((int64_t)xs->xid.formatID, false);
1411
protocol->store_int64_t((int64_t)xs->xid.gtrid_length, false);
1412
protocol->store_int64_t((int64_t)xs->xid.bqual_length, false);
1413
protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length,
821
protocol->prepareForResend();
822
protocol->store((int64_t)xs->xid.formatID);
823
protocol->store((int64_t)xs->xid.gtrid_length);
824
protocol->store((int64_t)xs->xid.bqual_length);
825
protocol->store(xs->xid.data, xs->xid.gtrid_length+xs->xid.bqual_length);
1415
826
if (protocol->write())
1417
828
pthread_mutex_unlock(&LOCK_xid_cache);
1423
834
pthread_mutex_unlock(&LOCK_xid_cache);
1430
This function should be called when MySQL sends rows of a SELECT result set
1431
or the EOF mark to the client. It releases a possible adaptive hash index
1432
S-latch held by thd in InnoDB and also releases a possible InnoDB query
1433
FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a thd to
1434
keep them over several calls of the InnoDB handler interface when a join
1435
is executed. But when we let the control to pass to the client they have
1436
to be released because if the application program uses mysql_use_result(),
1437
it may deadlock on the S-latch if the application on another connection
1438
performs another SQL query. In MySQL-4.1 this is even more important because
1439
there a connection can have several SELECT queries open at the same time.
1441
@param thd the thread handle of the current connection
1446
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
1447
void *unused __attribute__((unused)))
1449
handlerton *hton= plugin_data(plugin, handlerton *);
1451
if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1452
hton->release_temporary_latches(hton, thd);
1458
int ha_release_temporary_latches(THD *thd)
1460
plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1466
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
840
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1469
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1470
&thd->transaction.all);
843
Session_TRANS *trans= &session->transaction.all;
1471
844
Ha_trx_info *ha_info, *ha_info_next;
1473
846
trans->no_2pc=0;
1518
890
section "4.33.4 SQL-statements and transaction states",
1519
891
SAVEPOINT is *not* transaction-initiating SQL-statement
1521
int ha_savepoint(THD *thd, SAVEPOINT *sv)
893
int ha_savepoint(Session *session, SAVEPOINT *sv)
1524
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1525
&thd->transaction.all);
896
Session_TRANS *trans= &session->transaction.all;
1526
897
Ha_trx_info *ha_info= trans->ha_list;
1527
898
for (; ha_info; ha_info= ha_info->next())
1530
handlerton *ht= ha_info->ht();
1532
if (! ht->savepoint_set)
901
StorageEngine *engine= ha_info->engine();
903
#ifdef NOT_IMPLEMENTED /*- TODO (examine this againt the original code base) */
904
if (! engine->savepoint_set)
1534
906
my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "SAVEPOINT");
1538
if ((err= ht->savepoint_set(ht, thd, (uchar *)(sv+1)+ht->savepoint_offset)))
911
if ((err= engine->savepoint_set(session, (void *)(sv+1))))
1539
912
{ // cannot happen
1540
913
my_error(ER_GET_ERRNO, MYF(0), err);
1543
status_var_increment(thd->status_var.ha_savepoint_count);
916
status_var_increment(session->status_var.ha_savepoint_count);
1546
919
Remember the list of registered storage engines. All new
1547
920
engines are prepended to the beginning of the list.
1549
922
sv->ha_list= trans->ha_list;
1553
int ha_release_savepoint(THD *thd, SAVEPOINT *sv)
926
int ha_release_savepoint(Session *session, SAVEPOINT *sv)
1556
929
Ha_trx_info *ha_info= sv->ha_list;
1558
931
for (; ha_info; ha_info= ha_info->next())
1561
handlerton *ht= ha_info->ht();
934
StorageEngine *engine= ha_info->engine();
1562
935
/* Savepoint life time is enclosed into transaction life time. */
1564
if (!ht->savepoint_release)
1566
if ((err= ht->savepoint_release(ht, thd,
1567
(uchar *)(sv+1) + ht->savepoint_offset)))
937
if ((err= engine->savepoint_release(session,
1568
939
{ // cannot happen
1569
940
my_error(ER_GET_ERRNO, MYF(0), err);
1577
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
1579
handlerton *hton= plugin_data(plugin, handlerton *);
1580
if (hton->state == SHOW_OPTION_YES &&
1581
hton->start_consistent_snapshot)
1583
hton->start_consistent_snapshot(hton, thd);
1584
*((bool *)arg)= false;
1589
int ha_start_consistent_snapshot(THD *thd)
1593
plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1596
Same idea as when one wants to CREATE TABLE in one engine which does not
1600
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1601
"This MySQL server does not support any "
1602
"consistent-read capable storage engine");
1607
static bool flush_handlerton(THD *thd __attribute__((unused)),
1609
void *arg __attribute__((unused)))
1611
handlerton *hton= plugin_data(plugin, handlerton *);
1612
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1613
hton->flush_logs(hton))
1619
bool ha_flush_logs(handlerton *db_type)
1621
if (db_type == NULL)
1623
if (plugin_foreach(NULL, flush_handlerton,
1624
DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
1629
if (db_type->state != SHOW_OPTION_YES ||
1630
(db_type->flush_logs && db_type->flush_logs(db_type)))
1636
static const char *check_lowercase_names(handler *file, const char *path,
1639
if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
1642
/* Ensure that table handler get path in lower case */
1643
if (tmp_path != path)
1644
stpcpy(tmp_path, path);
1647
we only should turn into lowercase database/table part
1648
so start the process after homedirectory
1650
my_casedn_str(files_charset_info, tmp_path + mysql_data_home_len);
1656
An interceptor to hijack the text of the error message without
1657
setting an error in the thread. We need the text to present it
1658
in the form of a warning to the user.
1661
struct Ha_delete_table_error_handler: public Internal_error_handler
1664
virtual bool handle_error(uint sql_errno,
1665
const char *message,
1666
DRIZZLE_ERROR::enum_warning_level level,
1668
char buff[DRIZZLE_ERRMSG_SIZE];
1673
Ha_delete_table_error_handler::
1674
handle_error(uint sql_errno __attribute__((unused)),
1675
const char *message,
1676
DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1677
THD *thd __attribute__((unused)))
1679
/* Grab the error message */
1680
strmake(buff, message, sizeof(buff)-1);
1686
This should return ENOENT if the file doesn't exists.
1687
The .frm file will be deleted only if we return 0 or ENOENT
1689
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
1690
const char *db, const char *alias, bool generate_warning)
1693
char tmp_path[FN_REFLEN];
1696
TABLE_SHARE dummy_share;
1698
memset(&dummy_table, 0, sizeof(dummy_table));
1699
memset(&dummy_share, 0, sizeof(dummy_share));
1700
dummy_table.s= &dummy_share;
1702
/* DB_TYPE_UNKNOWN is used in ALTER TABLE when renaming only .frm files */
1703
if (table_type == NULL ||
1704
! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
1707
path= check_lowercase_names(file, path, tmp_path);
1708
if ((error= file->ha_delete_table(path)) && generate_warning)
1711
Because file->print_error() use my_error() to generate the error message
1712
we use an internal error handler to intercept it and store the text
1713
in a temporary buffer. Later the message will be presented to user
1716
Ha_delete_table_error_handler ha_delete_table_error_handler;
1718
/* Fill up strucutures that print_error may need */
1719
dummy_share.path.str= (char*) path;
1720
dummy_share.path.length= strlen(path);
1721
dummy_share.db.str= (char*) db;
1722
dummy_share.db.length= strlen(db);
1723
dummy_share.table_name.str= (char*) alias;
1724
dummy_share.table_name.length= strlen(alias);
1725
dummy_table.alias= alias;
1727
file->change_table_ptr(&dummy_table, &dummy_share);
1729
thd->push_internal_handler(&ha_delete_table_error_handler);
1730
file->print_error(error, 0);
1732
thd->pop_internal_handler();
1735
XXX: should we convert *all* errors to warnings here?
1736
What if the error is fatal?
1738
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
1739
ha_delete_table_error_handler.buff);
1745
951
/****************************************************************************
1746
952
** General handler functions
1747
953
****************************************************************************/
954
handler::~handler(void)
956
assert(locked == false);
957
/* TODO: assert(inited == NONE); */
1748
961
handler *handler::clone(MEM_ROOT *mem_root)
1750
963
handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1752
965
Allocate handler->ref here because otherwise ha_open will allocate it
1753
on this->table->mem_root and we will not be able to reclaim that memory
966
on this->table->mem_root and we will not be able to reclaim that memory
1754
967
when the clone handler object is destroyed.
1756
if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
969
if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1758
971
if (new_handler && !new_handler->ha_open(table,
1759
972
table->s->normalized_path.str,
1761
974
HA_OPEN_IGNORE_IF_LOCKED))
1762
975
return new_handler;
979
int handler::ha_index_init(uint32_t idx, bool sorted)
982
assert(inited == NONE);
983
if (!(result= index_init(idx, sorted)))
989
int handler::ha_index_end()
991
assert(inited==INDEX);
997
int handler::ha_rnd_init(bool scan)
1000
assert(inited==NONE || (inited==RND && scan));
1001
inited= (result= rnd_init(scan)) ? NONE: RND;
1006
int handler::ha_rnd_end()
1008
assert(inited==RND);
1013
int handler::ha_index_or_rnd_end()
1015
return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1018
handler::Table_flags handler::ha_table_flags() const
1020
return cached_table_flags;
1023
void handler::ha_start_bulk_insert(ha_rows rows)
1025
estimation_rows_to_insert= rows;
1026
start_bulk_insert(rows);
1029
int handler::ha_end_bulk_insert()
1031
estimation_rows_to_insert= 0;
1032
return end_bulk_insert();
1035
void handler::change_table_ptr(Table *table_arg, TableShare *share)
1041
const key_map *handler::keys_to_use_for_scanning()
1043
return &key_map_empty;
1046
bool handler::has_transactions()
1048
return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1768
1051
void handler::ha_statistic_increment(ulong SSV::*offset) const
1770
1053
status_var_increment(table->in_use->status_var.*offset);
1773
void **handler::ha_data(THD *thd) const
1775
return thd_ha_data(thd, ht);
1778
THD *handler::ha_thd(void) const
1780
assert(!table || !table->in_use || table->in_use == current_thd);
1781
return (table && table->in_use) ? table->in_use : current_thd;
1056
void **handler::ha_data(Session *session) const
1058
return session_ha_data(session, engine);
1061
Session *handler::ha_session(void) const
1063
assert(!table || !table->in_use || table->in_use == current_session);
1064
return (table && table->in_use) ? table->in_use : current_session;
1068
bool handler::is_fatal_error(int error, uint32_t flags)
1071
((flags & HA_CHECK_DUP_KEY) &&
1072
(error == HA_ERR_FOUND_DUPP_KEY ||
1073
error == HA_ERR_FOUND_DUPP_UNIQUE)))
1079
ha_rows handler::records() { return stats.records; }
1785
1082
Open database-handler.
2510
1787
Returns true if this is a temporary error
2512
bool handler::get_error_message(int error __attribute__((unused)),
2513
String* buf __attribute__((unused)))
1789
bool handler::get_error_message(int , String* )
2519
int handler::ha_check_for_upgrade(HA_CHECK_OPT *check_opt)
2521
KEY *keyinfo, *keyend;
2522
KEY_PART_INFO *keypart, *keypartend;
2524
if (!table->s->mysql_version)
2526
/* check for blob-in-key error */
2527
keyinfo= table->key_info;
2528
keyend= table->key_info + table->s->keys;
2529
for (; keyinfo < keyend; keyinfo++)
2531
keypart= keyinfo->key_part;
2532
keypartend= keypart + keyinfo->key_parts;
2533
for (; keypart < keypartend; keypart++)
2535
if (!keypart->fieldnr)
2537
Field *field= table->field[keypart->fieldnr-1];
2538
if (field->type() == DRIZZLE_TYPE_BLOB)
2540
if (check_opt->sql_flags & TT_FOR_UPGRADE)
2541
check_opt->flags= T_MEDIUM;
2542
return HA_ADMIN_NEEDS_CHECK;
2547
return check_for_upgrade(check_opt);
2551
1795
/* Code left, but Drizzle has no legacy yet (while MySQL did) */
2552
1796
int handler::check_old_types()
2558
static bool update_frm_version(TABLE *table)
2560
char path[FN_REFLEN];
2565
No need to update frm version in case table was created or checked
2566
by server with the same version. This also ensures that we do not
2567
update frm version for temporary tables as this code doesn't support
2570
if (table->s->mysql_version == DRIZZLE_VERSION_ID)
2573
strxmov(path, table->s->normalized_path.str, reg_ext, NullS);
2575
if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
2578
char *key= table->s->table_cache_key.str;
2579
uint key_length= table->s->table_cache_key.length;
2581
HASH_SEARCH_STATE state;
2583
int4store(version, DRIZZLE_VERSION_ID);
2585
if (pwrite(file, (uchar*)version, 4, 51L) == 0)
2591
for (entry=(TABLE*) hash_first(&open_cache,(uchar*) key,key_length, &state);
2593
entry= (TABLE*) hash_next(&open_cache,(uchar*) key,key_length, &state))
2594
entry->s->mysql_version= DRIZZLE_VERSION_ID;
2598
VOID(my_close(file,MYF(MY_WME)));
2606
1803
key if error because of duplicated keys
2608
uint handler::get_dup_key(int error)
1805
uint32_t handler::get_dup_key(int error)
2610
table->file->errkey = (uint) -1;
1807
table->file->errkey = (uint32_t) -1;
2611
1808
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2612
1809
error == HA_ERR_FOUND_DUPP_UNIQUE ||
2613
1810
error == HA_ERR_DROP_INDEX_FK)
3073
2101
** Some general functions that isn't in the handler class
3074
2102
****************************************************************************/
3077
Initiates table-file and calls appropriate database-creator.
3084
int ha_create_table(THD *thd, const char *path,
3085
const char *db, const char *table_name,
3086
HA_CREATE_INFO *create_info,
3087
bool update_create_info)
3091
char name_buff[FN_REFLEN];
3095
init_tmp_table_share(thd, &share, db, 0, table_name, path);
3096
if (open_table_def(thd, &share, 0) ||
3097
open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
3101
if (update_create_info)
3102
update_create_info_from_table(create_info, &table);
3104
name= check_lowercase_names(table.file, share.path.str, name_buff);
3106
error= table.file->ha_create(name, &table, create_info);
3107
VOID(closefrm(&table, 0));
3110
strxmov(name_buff, db, ".", table_name, NullS);
3111
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
3114
free_table_share(&share);
3119
Try to discover table from engine.
3122
If found, write the frm file to disk.
3125
-1 Table did not exists
3129
> 0 Error, table existed but could not be created
3131
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
3136
char path[FN_REFLEN];
3137
HA_CREATE_INFO create_info;
3141
memset(&create_info, 0, sizeof(create_info));
3142
if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
3144
/* Table could not be discovered and thus not created */
3149
Table exists in handler and could be discovered
3150
frmblob and frmlen are set, write the frm to disk
3153
build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
3154
// Save the frm file
3155
error= writefrm(path, frmblob, frmlen);
3156
my_free(frmblob, MYF(0));
3160
init_tmp_table_share(thd, &share, db, 0, name, path);
3161
if (open_table_def(thd, &share, 0))
3165
if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
3167
free_table_share(&share);
3171
update_create_info_from_table(&create_info, &table);
3172
create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
3174
check_lowercase_names(table.file, path, path);
3175
error=table.file->ha_create(path, &table, &create_info);
3176
VOID(closefrm(&table, 1));
3181
2105
void st_ha_check_opt::init()
3183
flags= sql_flags= 0;
3184
sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
3279
Try to discover one table from handler(s).
3282
-1 Table did not exists
3284
0 OK. In this case *frmblob and *frmlen are set
3286
>0 error. frmblob and frmlen may not be set
3288
struct st_discover_args
3296
static bool discover_handlerton(THD *thd, plugin_ref plugin,
3299
st_discover_args *vargs= (st_discover_args *)arg;
3300
handlerton *hton= plugin_data(plugin, handlerton *);
3301
if (hton->state == SHOW_OPTION_YES && hton->discover &&
3302
(!(hton->discover(hton, thd, vargs->db, vargs->name,
3310
int ha_discover(THD *thd, const char *db, const char *name,
3311
uchar **frmblob, size_t *frmlen)
3313
int error= -1; // Table does not exist in any handler
3314
st_discover_args args= {db, name, frmblob, frmlen};
3316
if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
3319
if (plugin_foreach(thd, discover_handlerton,
3320
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
3324
status_var_increment(thd->status_var.ha_discover_count);
3330
Call this function in order to give the handler the possiblity
3331
to ask engine if there are any new tables that should be written to disk
3332
or any dropped tables that need to be removed from disk
3334
struct st_find_files_args
3340
List<LEX_STRING> *files;
3344
Ask handler if the table exists in engine.
3346
HA_ERR_NO_SUCH_TABLE Table does not exist
3348
HA_ERR_TABLE_EXIST Table exists
3352
struct st_table_exists_in_engine_args
3359
static bool table_exists_in_engine_handlerton(THD *thd, plugin_ref plugin,
3362
st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
3363
handlerton *hton= plugin_data(plugin, handlerton *);
3365
int err= HA_ERR_NO_SUCH_TABLE;
3367
if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3368
err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
3371
if (vargs->err == HA_ERR_TABLE_EXIST)
3377
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
3379
st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3380
plugin_foreach(thd, table_exists_in_engine_handlerton,
3381
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
3386
2203
Calculate cost of 'index only' scan for given index and number of records
3388
2205
@param keynr Index number
3703
2518
@retval other Error
3706
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
2521
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
3707
2522
RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3708
uint n_ranges, uint mode, HANDLER_BUFFER *buf)
2523
uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3712
2527
Item *pushed_cond= NULL;
3713
2528
handler *new_h2;
3714
keyno= h->active_index;
2529
keyno= h_in->active_index;
3715
2530
assert(h2 == NULL);
3716
2531
if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3718
2533
use_default_impl= true;
3719
return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
2534
return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3720
2535
n_ranges, mode, buf));
3722
2537
rowids_buf= buf->buffer;
3723
2538
//psergey-todo: don't add key_length as it is not needed anymore
3724
rowids_buf += key->key_length + h->ref_length;
2539
rowids_buf += key->key_length + h_in->ref_length;
3726
2541
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3727
2542
rowids_buf_end= buf->buffer_end;
3729
elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3730
rowids_buf_last= rowids_buf +
2544
elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
2545
rowids_buf_last= rowids_buf +
3731
2546
((rowids_buf_end - rowids_buf)/ elem_size)*
3733
2548
rowids_buf_end= rowids_buf_last;
3735
2550
/* Create a separate handler object to do rndpos() calls. */
3736
THD *thd= current_thd;
3737
if (!(new_h2= h->clone(thd->mem_root)) ||
3738
new_h2->ha_external_lock(thd, F_RDLCK))
2551
Session *session= current_session;
2552
if (!(new_h2= h_in->clone(session->mem_root)) ||
2553
new_h2->ha_external_lock(session, F_RDLCK))
3744
if (keyno == h->pushed_idx_cond_keyno)
3745
pushed_cond= h->pushed_idx_cond;
3746
if (h->ha_index_end())
2559
if (keyno == h_in->pushed_idx_cond_keyno)
2560
pushed_cond= h_in->pushed_idx_cond;
2561
if (h_in->ha_index_end())
4400
Returns a list of all known extensions.
4402
No mutexes, worst case race is a minor surplus memory allocation
4403
We have to recreate the extension map if mysqld is restarted (for example
4407
pointer pointer to TYPELIB structure
4409
static bool exts_handlerton(THD *unused __attribute__((unused)),
4413
List<char> *found_exts= (List<char> *) arg;
4414
handlerton *hton= plugin_data(plugin, handlerton *);
4416
if (hton->state == SHOW_OPTION_YES && hton->create &&
4417
(file= hton->create(hton, (TABLE_SHARE*) 0, current_thd->mem_root)))
4419
List_iterator_fast<char> it(*found_exts);
4420
const char **ext, *old_ext;
4422
for (ext= file->bas_ext(); *ext; ext++)
4424
while ((old_ext= it++))
4426
if (!strcmp(old_ext, *ext))
4430
found_exts->push_back((char *) *ext);
4439
TYPELIB *ha_known_exts(void)
4441
if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
4443
List<char> found_exts;
4444
const char **ext, *old_ext;
4446
known_extensions_id= mysys_usage_id;
4448
plugin_foreach(NULL, exts_handlerton,
4449
DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
4451
ext= (const char **) my_once_alloc(sizeof(char *)*
4452
(found_exts.elements+1),
4453
MYF(MY_WME | MY_FAE));
4456
known_extensions.count= found_exts.elements;
4457
known_extensions.type_names= ext;
4459
List_iterator_fast<char> it(found_exts);
4460
while ((old_ext= it++))
4464
return &known_extensions;
4468
static bool stat_print(THD *thd, const char *type, uint type_len,
4469
const char *file, uint file_len,
4470
const char *status, uint status_len)
4472
Protocol *protocol= thd->protocol;
4473
protocol->prepare_for_resend();
4474
protocol->store(type, type_len, system_charset_info);
4475
protocol->store(file, file_len, system_charset_info);
4476
protocol->store(status, status_len, system_charset_info);
3213
static bool stat_print(Session *session, const char *type, uint32_t type_len,
3214
const char *file, uint32_t file_len,
3215
const char *status, uint32_t status_len)
3217
Protocol *protocol= session->protocol;
3218
protocol->prepareForResend();
3219
protocol->store(type, type_len);
3220
protocol->store(file, file_len);
3221
protocol->store(status, status_len);
4477
3222
if (protocol->write())
4482
bool ha_show_status(THD *thd, handlerton *db_type, enum ha_stat_type stat)
3227
bool ha_show_status(Session *session, StorageEngine *engine, enum ha_stat_type stat)
4484
3229
List<Item> field_list;
4485
Protocol *protocol= thd->protocol;
3230
Protocol *protocol= session->protocol;
4488
3233
field_list.push_back(new Item_empty_string("Type",10));
4489
3234
field_list.push_back(new Item_empty_string("Name",FN_REFLEN));
4490
3235
field_list.push_back(new Item_empty_string("Status",10));
4492
if (protocol->send_fields(&field_list,
4493
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
3237
if (protocol->sendFields(&field_list,
3238
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
4496
result= db_type->show_status &&
4497
db_type->show_status(db_type, thd, stat_print, stat) ? 1 : 0;
3241
result= engine->show_status(session, stat_print, stat) ? 1 : 0;
4514
3258
- table is not mysql.event
4517
static bool check_table_binlog_row_based(THD *thd, TABLE *table)
4519
if (table->s->cached_row_logging_check == -1)
4521
int const check(table->s->tmp_table == NO_TMP_TABLE &&
4522
binlog_filter->db_ok(table->s->db.str));
4523
table->s->cached_row_logging_check= check;
4526
assert(table->s->cached_row_logging_check == 0 ||
4527
table->s->cached_row_logging_check == 1);
4529
return (thd->current_stmt_binlog_row_based &&
4530
table->s->cached_row_logging_check &&
4531
(thd->options & OPTION_BIN_LOG) &&
4532
mysql_bin_log.is_open());
4537
Write table maps for all (manually or automatically) locked tables
4540
This function will generate and write table maps for all tables
4541
that are locked by the thread 'thd'. Either manually locked
4542
(stored in THD::locked_tables) and automatically locked (stored
4543
in THD::lock) are considered.
4545
@param thd Pointer to THD structure
4548
@retval 1 Failed to write all table maps
4555
static int write_locked_table_maps(THD *thd)
4557
if (thd->get_binlog_table_maps() == 0)
4559
DRIZZLE_LOCK *locks[3];
4560
locks[0]= thd->extra_lock;
4561
locks[1]= thd->lock;
4562
locks[2]= thd->locked_tables;
4563
for (uint i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4565
DRIZZLE_LOCK const *const lock= locks[i];
4569
TABLE **const end_ptr= lock->table + lock->table_count;
4570
for (TABLE **table_ptr= lock->table ;
4571
table_ptr != end_ptr ;
4574
TABLE *const table= *table_ptr;
4575
if (table->current_lock == F_WRLCK &&
4576
check_table_binlog_row_based(thd, table))
4578
int const has_trans= table->file->has_transactions();
4579
int const error= thd->binlog_write_table_map(table, has_trans);
4581
If an error occurs, it is the responsibility of the caller to
4582
roll back the transaction.
4584
if (unlikely(error))
4594
typedef bool Log_func(THD*, TABLE*, bool, const uchar*, const uchar*);
4596
static int binlog_log_row(TABLE* table,
4597
const uchar *before_record,
4598
const uchar *after_record,
4601
if (table->no_replicate)
4604
THD *const thd= table->in_use;
4606
if (check_table_binlog_row_based(thd, table))
3261
static bool log_row_for_replication(Table* table,
3262
const unsigned char *before_record,
3263
const unsigned char *after_record)
3265
Session *const session= table->in_use;
3267
switch (session->lex->sql_command)
3269
case SQLCOM_REPLACE:
3271
case SQLCOM_REPLACE_SELECT:
3272
case SQLCOM_INSERT_SELECT:
3273
case SQLCOM_CREATE_TABLE:
3274
transaction_services.insertRecord(session, table);
3278
case SQLCOM_UPDATE_MULTI:
3279
transaction_services.updateRecord(session, table, before_record, after_record);
3283
case SQLCOM_DELETE_MULTI:
3284
transaction_services.deleteRecord(session, table);
4609
If there are no table maps written to the binary log, this is
4610
the first row handled in this statement. In that case, we need
4611
to write table maps for all locked tables to the binary log.
3288
For everything else we ignore the event (since it just involves a temp table)
4613
if (likely(!(error= write_locked_table_maps(thd))))
4615
bool const has_trans= table->file->has_transactions();
4616
error= (*log_func)(thd, table, has_trans, before_record, after_record);
4619
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
3294
return false; //error;
4622
int handler::ha_external_lock(THD *thd, int lock_type)
3297
int handler::ha_external_lock(Session *session, int lock_type)
4625
3300
Whether this is lock or unlock, this should be true, and is to verify that