1
/* Copyright (C) 2000-2006 MySQL AB
3
This program is free software; you can redistribute it and/or modify
4
it under the terms of the GNU General Public License as published by
5
the Free Software Foundation; version 2 of the License.
7
This program is distributed in the hope that it will be useful,
8
but WITHOUT ANY WARRANTY; without even the implied warranty of
9
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10
GNU General Public License for more details.
12
You should have received a copy of the GNU General Public License
13
along with this program; if not, write to the Free Software
14
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
1
/* -*- mode: c++; c-basic-offset: 2; indent-tabs-mode: nil; -*-
2
* vim:expandtab:shiftwidth=2:tabstop=2:smarttab:
4
* Copyright (C) 2008 Sun Microsystems
6
* This program is free software; you can redistribute it and/or modify
7
* it under the terms of the GNU General Public License as published by
8
* the Free Software Foundation; version 2 of the License.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19
23
Handler-calling-functions
22
#ifdef USE_PRAGMA_IMPLEMENTATION
23
#pragma implementation // gcc: Class implementation
26
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} };
27
#include <libdrizzle/libdrizzle.h>
28
#include <mysys/hash.h>
29
#include <drizzled/error.h>
30
#include <drizzled/gettext.h>
31
#include <drizzled/data_home.h>
32
#include <drizzled/probes.h>
33
#include <drizzled/sql_parse.h>
34
#include <drizzled/cost_vect.h>
36
#include <drizzled/session.h>
37
#include <drizzled/sql_base.h>
38
#include <drizzled/replicator.h>
39
#include <drizzled/lock.h>
40
#include <drizzled/item/int.h>
41
#include <drizzled/item/empty_string.h>
42
#include <drizzled/unireg.h> // for mysql_frm_type
44
#if defined(CMATH_NAMESPACE)
45
using namespace CMATH_NAMESPACE;
49
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
43
51
/* number of entries in handlertons[] */
44
52
uint32_t total_ha= 0;
47
55
/* size of savepoint storage area (see ha_init) */
48
56
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
58
const char *ha_row_type[] = {
58
59
"", "FIXED", "DYNAMIC", "COMPRESSED", "REDUNDANT", "COMPACT", "PAGE", "?","?","?"
61
62
const char *tx_isolation_names[] =
62
63
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
64
66
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
tx_isolation_names, NULL};
67
tx_isolation_names, NULL};
67
69
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)));
70
uint32_t known_extensions_id= 0;
310
153
/* Allocate a pointer array for the error message strings. */
311
154
if (! (errmsgs= my_error_unregister(HA_ERR_FIRST, HA_ERR_LAST)))
313
my_free((uchar*) errmsgs, MYF(0));
156
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) {
607
332
The server stores its transaction-related data in
608
thd->transaction. This structure has two members of type
609
THD_TRANS. These members correspond to the statement and
333
session->transaction. This structure has two members of type
334
Session_TRANS. These members correspond to the statement and
610
335
normal transactions respectively:
612
- thd->transaction.stmt contains a list of engines
337
- session->transaction.stmt contains a list of engines
613
338
that are participating in the given statement
614
- thd->transaction.all contains a list of engines that
339
- session->transaction.all contains a list of engines that
615
340
have participated in any of the statement transactions started
616
341
within the context of the normal transaction.
617
342
Each element of the list contains a pointer to the storage
618
343
engine, engine-specific transactional data, and engine-specific
619
344
transaction flags.
621
In autocommit mode thd->transaction.all is empty.
622
Instead, data of thd->transaction.stmt is
346
In autocommit mode session->transaction.all is empty.
347
Instead, data of session->transaction.stmt is
623
348
used to commit/rollback the normal transaction.
625
350
The list of registered engines has a few important properties:
855
580
handlerton *ht= ha_info->ht();
856
status_var_increment(thd->status_var.ha_prepare_count);
581
status_var_increment(session->status_var.ha_prepare_count);
859
if ((err= ht->prepare(ht, thd, all)))
584
if ((err= ht->prepare(ht, session, all)))
861
586
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
862
ha_rollback_trans(thd, all);
587
ha_rollback_trans(session, all);
869
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
594
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
870
595
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
871
596
ha_resolve_storage_engine_name(ht));
963
687
flags will not get propagated to its normal transaction's
966
assert(thd->transaction.stmt.ha_list == NULL ||
967
trans == &thd->transaction.stmt);
690
assert(session->transaction.stmt.ha_list == NULL ||
691
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))
697
if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
995
ha_rollback_trans(thd, all);
699
ha_rollback_trans(session, 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);
703
must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
1012
705
if (!trans->no_2pc && must_2pc)
1026
719
Sic: we know that prepare() is not NULL since otherwise
1027
720
trans->no_2pc would have been set.
1029
if ((err= ht->prepare(ht, thd, all)))
722
if ((err= ht->prepare(ht, session, all)))
1031
724
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1034
status_var_increment(thd->status_var.ha_prepare_count);
727
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);
731
ha_rollback_trans(session, all);
1044
error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1046
tc_log->unlog(cookie, xid);
736
error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1048
738
if (is_real_trans)
1049
start_waiting_global_read_lock(thd);
739
start_waiting_global_read_lock(session);
1069
759
handlerton *ht= ha_info->ht();
1070
if ((err= ht->commit(ht, thd, all)))
760
if ((err= ht->commit(ht, session, all)))
1072
762
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1075
status_var_increment(thd->status_var.ha_commit_count);
765
status_var_increment(session->status_var.ha_commit_count);
1076
766
ha_info_next= ha_info->next();
1077
767
ha_info->reset(); /* keep it conveniently zero-filled */
1079
769
trans->ha_list= 0;
1080
770
trans->no_2pc=0;
1081
771
if (is_real_trans)
1082
thd->transaction.xid_state.xid.null();
772
session->transaction.xid_state.xid.null();
1085
thd->variables.tx_isolation=thd->session_tx_isolation;
1086
thd->transaction.cleanup();
775
session->variables.tx_isolation=session->session_tx_isolation;
776
session->transaction.cleanup();
1093
int ha_rollback_trans(THD *thd, bool all)
783
int ha_rollback_trans(Session *session, bool all)
1096
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
786
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1097
787
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1098
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
788
bool is_real_trans=all || session->transaction.all.ha_list == 0;
1101
791
We must not rollback the normal transaction if a statement
1102
792
transaction is pending.
1104
assert(thd->transaction.stmt.ha_list == NULL ||
1105
trans == &thd->transaction.stmt);
794
assert(session->transaction.stmt.ha_list == NULL ||
795
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
799
for (; ha_info; ha_info= ha_info_next)
1125
802
handlerton *ht= ha_info->ht();
1126
if ((err= ht->rollback(ht, thd, all)))
803
if ((err= ht->rollback(ht, session, all)))
1127
804
{ // cannot happen
1128
805
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1131
status_var_increment(thd->status_var.ha_rollback_count);
808
status_var_increment(session->status_var.ha_rollback_count);
1132
809
ha_info_next= ha_info->next();
1133
810
ha_info->reset(); /* keep it conveniently zero-filled */
1135
812
trans->ha_list= 0;
1136
813
trans->no_2pc=0;
1137
814
if (is_real_trans)
1138
thd->transaction.xid_state.xid.null();
815
session->transaction.xid_state.xid.null();
1141
thd->variables.tx_isolation=thd->session_tx_isolation;
1142
thd->transaction.cleanup();
818
session->variables.tx_isolation=session->session_tx_isolation;
819
session->transaction.cleanup();
1146
thd->transaction_rollback_request= false;
823
session->transaction_rollback_request= false;
1149
826
If a non-transactional table was updated, warn; don't warn if this is a
1173
849
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)
852
int ha_autocommit_or_rollback(Session *session, int error)
1178
if (thd->transaction.stmt.ha_list)
854
if (session->transaction.stmt.ha_list)
1182
if (ha_commit_trans(thd, 0))
858
if (ha_commit_trans(session, 0))
1187
(void) ha_rollback_trans(thd, 0);
1188
if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1189
(void) ha_rollback(thd);
863
(void) ha_rollback_trans(session, 0);
864
if (session->transaction_rollback_request)
865
(void) ha_rollback(session);
1192
thd->variables.tx_isolation=thd->session_tx_isolation;
868
session->variables.tx_isolation=session->session_tx_isolation;
1346
for (info.len= MAX_XID_LIST_SIZE ;
1022
for (info.len= MAX_XID_LIST_SIZE ;
1347
1023
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1349
info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
1025
info.list=(XID *)malloc(info.len*sizeof(XID));
1351
1027
if (!info.list)
1353
sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1029
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1357
plugin_foreach(NULL, xarecover_handlerton,
1033
plugin_foreach(NULL, xarecover_handlerton,
1358
1034
DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1360
my_free((uchar*)info.list, MYF(0));
1036
free((unsigned char*)info.list);
1361
1037
if (info.found_foreign_xids)
1362
sql_print_warning("Found %d prepared XA transactions",
1363
info.found_foreign_xids);
1038
errmsg_printf(ERRMSG_LVL_WARN, _("Found %d prepared XA transactions"),
1039
info.found_foreign_xids);
1364
1040
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.",
1042
errmsg_printf(ERRMSG_LVL_ERROR,
1043
_("Found %d prepared transactions! It means that drizzled "
1044
"was not shut down properly last time and critical "
1045
"recovery information (last binlog or %s file) was "
1046
"manually deleted after a crash. You have to start "
1047
"drizzled with the --tc-heuristic-recover switch to "
1048
"commit or rollback pending transactions."),
1372
1049
info.found_my_xids, opt_tc_log_file);
1375
1052
if (info.commit_list)
1376
sql_print_information("Crash recovery finished.");
1053
errmsg_printf(ERRMSG_LVL_INFO, _("Crash recovery finished."));
1438
1115
performs another SQL query. In MySQL-4.1 this is even more important because
1439
1116
there a connection can have several SELECT queries open at the same time.
1441
@param thd the thread handle of the current connection
1118
@param session the thread handle of the current connection
1446
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
1447
void *unused __attribute__((unused)))
1123
static bool release_temporary_latches(Session *session, plugin_ref plugin,
1449
1126
handlerton *hton= plugin_data(plugin, handlerton *);
1451
1128
if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1452
hton->release_temporary_latches(hton, thd);
1129
hton->release_temporary_latches(hton, session);
1458
int ha_release_temporary_latches(THD *thd)
1135
int ha_release_temporary_latches(Session *session)
1460
plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1137
plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1466
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
1143
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1469
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1470
&thd->transaction.all);
1146
Session_TRANS *trans= &session->transaction.all;
1471
1147
Ha_trx_info *ha_info, *ha_info_next;
1473
1149
trans->no_2pc=0;
1577
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
1252
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
1579
1254
handlerton *hton= plugin_data(plugin, handlerton *);
1580
1255
if (hton->state == SHOW_OPTION_YES &&
1581
1256
hton->start_consistent_snapshot)
1583
hton->start_consistent_snapshot(hton, thd);
1258
hton->start_consistent_snapshot(hton, session);
1584
1259
*((bool *)arg)= false;
1589
int ha_start_consistent_snapshot(THD *thd)
1264
int ha_start_consistent_snapshot(Session *session)
1591
1266
bool warn= true;
1593
plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1268
plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1596
1271
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 "
1275
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1276
"This Drizzle server does not support any "
1602
1277
"consistent-read capable storage engine");
1607
static bool flush_handlerton(THD *thd __attribute__((unused)),
1282
static bool flush_handlerton(Session *,
1608
1283
plugin_ref plugin,
1609
void *arg __attribute__((unused)))
1611
1286
handlerton *hton= plugin_data(plugin, handlerton *);
1612
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1287
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1613
1288
hton->flush_logs(hton))
1661
1336
struct Ha_delete_table_error_handler: public Internal_error_handler
1664
virtual bool handle_error(uint sql_errno,
1339
virtual bool handle_error(uint32_t sql_errno,
1665
1340
const char *message,
1666
1341
DRIZZLE_ERROR::enum_warning_level level,
1668
1343
char buff[DRIZZLE_ERRMSG_SIZE];
1673
1348
Ha_delete_table_error_handler::
1674
handle_error(uint sql_errno __attribute__((unused)),
1349
handle_error(uint32_t ,
1675
1350
const char *message,
1676
DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1677
THD *thd __attribute__((unused)))
1351
DRIZZLE_ERROR::enum_warning_level ,
1679
1354
/* Grab the error message */
1680
strmake(buff, message, sizeof(buff)-1);
1355
strncpy(buff, message, sizeof(buff)-1);
1360
struct handlerton_delete_table_args {
1367
static bool deletetable_handlerton(Session *,
1371
struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
1373
Session *session= dtargs->session;
1374
const char *path= dtargs->path;
1377
char tmp_path[FN_REFLEN];
1379
if(dtargs->error!=ENOENT) /* already deleted table */
1382
handlerton *table_type= plugin_data(plugin, handlerton *);
1387
if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
1390
if ((file= table_type->create(table_type, NULL, session->mem_root)))
1395
path= check_lowercase_names(file, path, tmp_path);
1396
int error= file->ha_delete_table(path);
1400
dtargs->error= error;
1402
delete dtargs->file;
1686
1411
This should return ENOENT if the file doesn't exists.
1687
1412
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,
1414
int ha_delete_table(Session *session, const char *path,
1690
1415
const char *db, const char *alias, bool generate_warning)
1693
char tmp_path[FN_REFLEN];
1696
1417
TABLE_SHARE dummy_share;
1420
struct handlerton_delete_table_args dtargs;
1421
dtargs.error= ENOENT;
1422
dtargs.session= session;
1426
plugin_foreach(NULL, deletetable_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1698
1429
memset(&dummy_table, 0, sizeof(dummy_table));
1699
1430
memset(&dummy_share, 0, sizeof(dummy_share));
1700
1431
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)
1433
if (dtargs.error && generate_warning)
1711
1436
Because file->print_error() use my_error() to generate the error message
1724
1449
dummy_share.table_name.length= strlen(alias);
1725
1450
dummy_table.alias= alias;
1452
handler *file= dtargs.file;
1727
1453
file->change_table_ptr(&dummy_table, &dummy_share);
1729
thd->push_internal_handler(&ha_delete_table_error_handler);
1730
file->print_error(error, 0);
1455
session->push_internal_handler(&ha_delete_table_error_handler);
1456
file->print_error(dtargs.error, 0);
1732
thd->pop_internal_handler();
1458
session->pop_internal_handler();
1735
1461
XXX: should we convert *all* errors to warnings here?
1736
1462
What if the error is fatal?
1738
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
1464
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, dtargs.error,
1739
1465
ha_delete_table_error_handler.buff);
1471
return dtargs.error;
1745
1474
/****************************************************************************
1750
1479
handler *new_handler= get_new_handler(table->s, mem_root, table->s->db_type());
1752
1481
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
1482
on this->table->mem_root and we will not be able to reclaim that memory
1754
1483
when the clone handler object is destroyed.
1756
if (!(new_handler->ref= (uchar*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1485
if (!(new_handler->ref= (unsigned char*) alloc_root(mem_root, ALIGN_SIZE(ref_length)*2)))
1758
1487
if (new_handler && !new_handler->ha_open(table,
1759
1488
table->s->normalized_path.str,
1761
1490
HA_OPEN_IGNORE_IF_LOCKED))
1762
1491
return new_handler;
1495
int handler::ha_index_init(uint32_t idx, bool sorted)
1498
assert(inited==NONE);
1499
if (!(result= index_init(idx, sorted)))
1505
int handler::ha_index_end()
1507
assert(inited==INDEX);
1510
return(index_end());
1513
int handler::ha_rnd_init(bool scan)
1516
assert(inited==NONE || (inited==RND && scan));
1517
inited= (result= rnd_init(scan)) ? NONE: RND;
1521
int handler::ha_rnd_end()
1523
assert(inited==RND);
1528
int handler::ha_index_or_rnd_end()
1530
return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1533
handler::Table_flags handler::ha_table_flags() const
1535
return cached_table_flags;
1538
void handler::ha_start_bulk_insert(ha_rows rows)
1540
estimation_rows_to_insert= rows;
1541
start_bulk_insert(rows);
1544
int handler::ha_end_bulk_insert()
1546
estimation_rows_to_insert= 0;
1547
return end_bulk_insert();
1550
void handler::change_table_ptr(Table *table_arg, TABLE_SHARE *share)
1556
const key_map *handler::keys_to_use_for_scanning()
1558
return &key_map_empty;
1561
bool handler::has_transactions()
1563
return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1768
1566
void handler::ha_statistic_increment(ulong SSV::*offset) const
1770
1568
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;
1571
void **handler::ha_data(Session *session) const
1573
return session_ha_data(session, ht);
1576
Session *handler::ha_session(void) const
1578
assert(!table || !table->in_use || table->in_use == current_session);
1579
return (table && table->in_use) ? table->in_use : current_session;
1583
bool handler::is_fatal_error(int error, uint32_t flags)
1586
((flags & HA_CHECK_DUP_KEY) &&
1587
(error == HA_ERR_FOUND_DUPP_KEY ||
1588
error == HA_ERR_FOUND_DUPP_UNIQUE)))
1594
ha_rows handler::records() { return stats.records; }
1785
1597
Open database-handler.
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
2362
key if error because of duplicated keys
2608
uint handler::get_dup_key(int error)
2364
uint32_t handler::get_dup_key(int error)
2610
2366
table->file->errkey = (uint) -1;
2611
2367
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2986
2735
handler::ha_create_handler_files(const char *name, const char *old_name,
2987
int action_flag, HA_CREATE_INFO *info)
2736
int action_flag, HA_CREATE_INFO *create_info)
2989
2738
mark_trx_read_write();
2991
return create_handler_files(name, old_name, action_flag, info);
2740
return create_handler_files(name, old_name, action_flag, create_info);
2996
2745
Tell the storage engine that it is allowed to "disable transaction" in the
2997
2746
handler. It is a hint that ACID is not required - it is used in NDB for
2998
ALTER TABLE, for example, when data are copied to temporary table.
2747
ALTER Table, for example, when data are copied to temporary table.
2999
2748
A storage engine may treat this hint any way it likes. NDB for example
3000
2749
starts to commit every now and then automatically.
3001
2750
This hint can be safely ignored.
3003
int ha_enable_transaction(THD *thd, bool on)
2752
int ha_enable_transaction(Session *session, bool on)
3007
if ((thd->transaction.on= on))
2756
if ((session->transaction.on= on))
3010
2759
Now all storage engines should have transaction handling enabled.
3012
2761
is an optimization hint that storage engine is free to ignore.
3013
2762
So, let's commit an open transaction (if any) now.
3015
if (!(error= ha_commit_trans(thd, 0)))
3016
error= end_trans(thd, COMMIT);
2764
if (!(error= ha_commit_trans(session, 0)))
2765
error= end_trans(session, COMMIT);
3021
int handler::index_next_same(uchar *buf, const uchar *key, uint keylen)
2770
int handler::index_next_same(unsigned char *buf, const unsigned char *key, uint32_t keylen)
3024
2773
if (!(error=index_next(buf)))
3026
2775
my_ptrdiff_t ptrdiff= buf - table->record[0];
3027
uchar *save_record_0= NULL;
2776
unsigned char *save_record_0= NULL;
3028
2777
KEY *key_info= NULL;
3029
2778
KEY_PART_INFO *key_part;
3030
2779
KEY_PART_INFO *key_part_end= NULL;
3084
int ha_create_table(THD *thd, const char *path,
2833
int ha_create_table(Session *session, const char *path,
3085
2834
const char *db, const char *table_name,
3086
2835
HA_CREATE_INFO *create_info,
3087
2836
bool update_create_info)
3091
2840
char name_buff[FN_REFLEN];
3092
2841
const char *name;
3093
2842
TABLE_SHARE share;
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,
2844
init_tmp_table_share(session, &share, db, 0, table_name, path);
2845
if (open_table_def(session, &share, 0) ||
2846
open_table_from_share(session, &share, "", 0, (uint) READ_ALL, 0, &table,
3101
2850
if (update_create_info)
3102
update_create_info_from_table(create_info, &table);
2851
table.updateCreateInfo(create_info);
3104
2853
name= check_lowercase_names(table.file, share.path.str, name_buff);
3106
2855
error= table.file->ha_create(name, &table, create_info);
3107
VOID(closefrm(&table, 0));
2856
table.closefrm(false);
3110
strxmov(name_buff, db, ".", table_name, NullS);
2859
sprintf(name_buff,"%s.%s",db,table_name);
3111
2860
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
3115
2864
return(error != 0);
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
2867
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
2964
Call this function in order to give the handler the possiblity
3331
2965
to ask engine if there are any new tables that should be written to disk
3365
3000
int err= HA_ERR_NO_SUCH_TABLE;
3367
3002
if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3368
err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
3003
err = hton->table_exists_in_engine(hton, session, vargs->db, vargs->name);
3370
3005
vargs->err = err;
3371
3006
if (vargs->err == HA_ERR_TABLE_EXIST)
3377
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
3015
int ha_table_exists_in_engine(Session* session,
3016
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,
3019
st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE, NULL};
3020
plugin_foreach(session, table_exists_in_engine_handlerton,
3381
3021
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
3023
if(args.err==HA_ERR_NO_SUCH_TABLE)
3025
/* Default way of knowing if a table exists. (checking .frm exists) */
3027
char path[FN_REFLEN];
3028
build_table_filename(path, sizeof(path),
3029
db, name, ".frm", 0);
3030
if (!access(path, F_OK))
3031
args.err= HA_ERR_TABLE_EXIST;
3033
args.err= HA_ERR_NO_SUCH_TABLE;
3035
enum legacy_db_type table_type;
3036
if(args.err==HA_ERR_TABLE_EXIST && mysql_frm_type(path, &table_type)==0)
3038
args.hton= ha_resolve_by_legacy_type(session, table_type);
3382
3045
return(args.err);
3453
handler::multi_range_read_info_const(uint keyno, RANGE_SEQ_IF *seq,
3114
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3454
3115
void *seq_init_param,
3455
uint n_ranges_arg __attribute__((unused)),
3456
uint *bufsz, uint *flags, COST_VECT *cost)
3117
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3458
3119
KEY_MULTI_RANGE range;
3459
3120
range_seq_t seq_it;
3460
3121
ha_rows rows, total_rows= 0;
3462
THD *thd= current_thd;
3122
uint32_t n_ranges=0;
3123
Session *session= current_session;
3464
3125
/* Default MRR implementation doesn't need buffer */
3467
3128
seq_it= seq->init(seq_init_param, n_ranges, *flags);
3468
3129
while (!seq->next(seq_it, &range))
3470
if (unlikely(thd->killed != 0))
3131
if (unlikely(session->killed != 0))
3471
3132
return HA_POS_ERROR;
3474
3135
key_range *min_endp, *max_endp;
3703
3364
@retval other Error
3706
int DsMrr_impl::dsmrr_init(handler *h, KEY *key,
3367
int DsMrr_impl::dsmrr_init(handler *h_in, KEY *key,
3707
3368
RANGE_SEQ_IF *seq_funcs, void *seq_init_param,
3708
uint n_ranges, uint mode, HANDLER_BUFFER *buf)
3369
uint32_t n_ranges, uint32_t mode, HANDLER_BUFFER *buf)
3712
3373
Item *pushed_cond= NULL;
3713
3374
handler *new_h2;
3714
keyno= h->active_index;
3375
keyno= h_in->active_index;
3715
3376
assert(h2 == NULL);
3716
3377
if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3718
3379
use_default_impl= true;
3719
return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
3380
return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3720
3381
n_ranges, mode, buf));
3722
3383
rowids_buf= buf->buffer;
3723
3384
//psergey-todo: don't add key_length as it is not needed anymore
3724
rowids_buf += key->key_length + h->ref_length;
3385
rowids_buf += key->key_length + h_in->ref_length;
3726
3387
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3727
3388
rowids_buf_end= buf->buffer_end;
3729
elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3730
rowids_buf_last= rowids_buf +
3390
elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
3391
rowids_buf_last= rowids_buf +
3731
3392
((rowids_buf_end - rowids_buf)/ elem_size)*
3733
3394
rowids_buf_end= rowids_buf_last;
3735
3396
/* 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))
3397
Session *session= current_session;
3398
if (!(new_h2= h_in->clone(session->mem_root)) ||
3399
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())
3405
if (keyno == h_in->pushed_idx_cond_keyno)
3406
pushed_cond= h_in->pushed_idx_cond;
3407
if (h_in->ha_index_end())
3907
3568
DS-MRR implementation: multi_range_read_info() function
3909
int DsMrr_impl::dsmrr_info(uint keyno, uint n_ranges, uint rows, uint *bufsz,
3910
uint *flags, COST_VECT *cost)
3570
int DsMrr_impl::dsmrr_info(uint32_t keyno, uint32_t n_ranges, uint32_t rows, uint32_t *bufsz,
3571
uint32_t *flags, COST_VECT *cost)
3913
uint def_flags= *flags;
3914
uint def_bufsz= *bufsz;
3574
uint32_t def_flags= *flags;
3575
uint32_t def_bufsz= *bufsz;
3916
3577
/* Get cost/flags/mem_usage of default MRR implementation */
3917
3578
res= h->handler::multi_range_read_info(keyno, n_ranges, rows, &def_bufsz,
3918
3579
&def_flags, cost);
3921
if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
3582
if ((*flags & HA_MRR_USE_DEFAULT_IMPL) ||
3922
3583
choose_mrr_impl(keyno, rows, &def_flags, &def_bufsz, cost))
3924
3585
/* Default implementation is choosen */
3933
3594
DS-MRR Implementation: multi_range_read_info_const() function
3936
ha_rows DsMrr_impl::dsmrr_info_const(uint keyno, RANGE_SEQ_IF *seq,
3937
void *seq_init_param, uint n_ranges,
3938
uint *bufsz, uint *flags, COST_VECT *cost)
3597
ha_rows DsMrr_impl::dsmrr_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3598
void *seq_init_param, uint32_t n_ranges,
3599
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3941
uint def_flags= *flags;
3942
uint def_bufsz= *bufsz;
3602
uint32_t def_flags= *flags;
3603
uint32_t def_bufsz= *bufsz;
3943
3604
/* Get cost/flags/mem_usage of default MRR implementation */
3944
3605
rows= h->handler::multi_range_read_info_const(keyno, seq, seq_init_param,
3945
n_ranges, &def_bufsz,
3606
n_ranges, &def_bufsz,
3946
3607
&def_flags, cost);
3947
3608
if (rows == HA_POS_ERROR)
4023
3684
@retval false DS-MRR implementation should be used
4026
bool DsMrr_impl::choose_mrr_impl(uint keyno, ha_rows rows, uint *flags,
4027
uint *bufsz, COST_VECT *cost)
3687
bool DsMrr_impl::choose_mrr_impl(uint32_t keyno, ha_rows rows, uint32_t *flags,
3688
uint32_t *bufsz, COST_VECT *cost)
4029
3690
COST_VECT dsmrr_cost;
4031
THD *thd= current_thd;
4032
if ((thd->variables.optimizer_use_mrr == 2) ||
3692
Session *session= current_session;
3693
if ((session->variables.optimizer_use_mrr == 2) ||
4033
3694
(*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4034
(keyno == table->s->primary_key &&
4035
h->primary_key_is_clustered()) ||
3695
(keyno == table->s->primary_key &&
3696
h->primary_key_is_clustered()) ||
4036
3697
key_uses_partial_cols(keyno))
4038
3699
/* Use the default implementation */
4039
3700
*flags |= HA_MRR_USE_DEFAULT_IMPL;
4043
uint add_len= table->key_info[keyno].key_length + h->ref_length;
3704
uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4044
3705
*bufsz -= add_len;
4045
3706
if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4047
3708
*bufsz += add_len;
4049
3710
bool force_dsmrr;
4051
3712
If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4052
3713
DS-MRR and Default implementations cost. This allows one to force use of
4053
3714
DS-MRR whenever it is applicable without affecting other cost-based
4056
if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
3717
if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4057
3718
dsmrr_cost.total_cost() > cost->total_cost())
4058
3719
dsmrr_cost= *cost;
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)
4130
static bool stat_print(Session *session, const char *type, uint32_t type_len,
4131
const char *file, uint32_t file_len,
4132
const char *status, uint32_t status_len)
4472
Protocol *protocol= thd->protocol;
4134
Protocol *protocol= session->protocol;
4473
4135
protocol->prepare_for_resend();
4474
4136
protocol->store(type, type_len, system_charset_info);
4475
4137
protocol->store(file, file_len, system_charset_info);
4514
4176
- 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))
4179
static bool binlog_log_row(Table* table,
4180
const unsigned char *before_record,
4181
const unsigned char *after_record)
4184
Session *const session= table->in_use;
4186
if (table->no_replicate == false)
4189
error= replicator_session_init(session);
4191
switch (session->lex->sql_command)
4193
case SQLCOM_REPLACE:
4195
case SQLCOM_REPLACE_SELECT:
4196
case SQLCOM_INSERT_SELECT:
4197
case SQLCOM_CREATE_TABLE:
4198
error= replicator_write_row(session, table);
4202
case SQLCOM_UPDATE_MULTI:
4203
error= replicator_update_row(session, table, before_record, after_record);
4207
case SQLCOM_DELETE_MULTI:
4208
error= replicator_delete_row(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.
4212
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;
4622
int handler::ha_external_lock(THD *thd, int lock_type)
4221
int handler::ha_external_lock(Session *session, int lock_type)
4625
4224
Whether this is lock or unlock, this should be true, and is to verify that
4665
int handler::ha_write_row(uchar *buf)
4264
int handler::ha_write_row(unsigned char *buf)
4668
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4669
4267
DRIZZLE_INSERT_ROW_START();
4671
4269
mark_trx_read_write();
4673
4271
if (unlikely(error= write_row(buf)))
4675
if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4676
return(error); /* purecov: inspected */
4274
if (unlikely(binlog_log_row(table, 0, buf)))
4275
return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
4677
4277
DRIZZLE_INSERT_ROW_END();
4682
int handler::ha_update_row(const uchar *old_data, uchar *new_data)
4282
int handler::ha_update_row(const unsigned char *old_data, unsigned char *new_data)
4685
Log_func *log_func= Update_rows_log_event::binlog_row_logging_function;
4688
4287
Some storage engines require that the new record is in record[0]
4695
4294
if (unlikely(error= update_row(old_data, new_data)))
4697
if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4297
if (unlikely(binlog_log_row(table, old_data, new_data)))
4298
return HA_ERR_RBR_LOGGING_FAILED;
4702
int handler::ha_delete_row(const uchar *buf)
4303
int handler::ha_delete_row(const unsigned char *buf)
4705
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4707
4307
mark_trx_read_write();
4709
4309
if (unlikely(error= delete_row(buf)))
4711
if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4312
if (unlikely(binlog_log_row(table, buf, 0)))
4313
return HA_ERR_RBR_LOGGING_FAILED;