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
#include "drizzled/server_includes.h"
27
#include "libdrizzleclient/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
43
#include "drizzled/field/timestamp.h"
44
#include "drizzled/serialize/table.pb.h"
46
#if defined(CMATH_NAMESPACE)
47
using namespace CMATH_NAMESPACE;
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
51
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
61
64
const char *tx_isolation_names[] =
62
65
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
64
68
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
tx_isolation_names, NULL};
69
tx_isolation_names, NULL};
67
71
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
68
72
uint32_t 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_utf8_general_ci.coll->strnncoll(&my_charset_utf8_general_ci,
116
(const unsigned char *)name->str, name->length,
117
(const unsigned char *)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_utf8_general_ci,
138
(const unsigned char *)name->str, name->length,
139
(const unsigned char *)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
return ha_default_handlerton(thd);
203
handler *get_new_handler(TABLE_SHARE *share, MEM_ROOT *alloc,
208
if (db_type && db_type->state == SHOW_OPTION_YES && db_type->create)
210
if ((file= db_type->create(db_type, share, alloc)))
215
Try the default table type
216
Here the call to current_thd() is ok as we call this function a lot of
217
times but we enter this branch very seldom.
219
return(get_new_handler(share, alloc, ha_default_handlerton(current_thd)));
224
76
Register handler error messages for use with my_error().
311
int ha_finalize_handlerton(st_plugin_int *plugin)
313
handlerton *hton= (handlerton *)plugin->data;
318
case SHOW_OPTION_DISABLED:
320
case SHOW_OPTION_YES:
321
if (installed_htons[hton->db_type] == hton)
322
installed_htons[hton->db_type]= NULL;
326
if (hton && plugin->plugin->deinit)
327
(void)plugin->plugin->deinit(hton);
329
free((unsigned char*)hton);
335
int ha_initialize_handlerton(st_plugin_int *plugin)
339
hton= (handlerton *)my_malloc(sizeof(handlerton),
340
MYF(MY_WME | MY_ZEROFILL));
342
FIXME: the MY_ZEROFILL flag above doesn't zero all the bytes.
344
This was detected after adding get_backup_engine member to handlerton
345
structure. Apparently get_backup_engine was not NULL even though it was
348
memset(hton, 0, sizeof(hton));
349
/* Historical Requirement */
350
plugin->data= hton; // shortcut for the future
351
if (plugin->plugin->init)
353
if (plugin->plugin->init(hton))
355
sql_print_error(_("Plugin '%s' init function returned error."),
362
the switch below and hton->state should be removed when
363
command-line options for plugins will be implemented
365
switch (hton->state) {
368
case SHOW_OPTION_YES:
371
/* now check the db_type for conflict */
372
if (hton->db_type <= DB_TYPE_UNKNOWN ||
373
hton->db_type >= DB_TYPE_DEFAULT ||
374
installed_htons[hton->db_type])
376
int idx= (int) DB_TYPE_FIRST_DYNAMIC;
378
while (idx < (int) DB_TYPE_DEFAULT && installed_htons[idx])
381
if (idx == (int) DB_TYPE_DEFAULT)
383
sql_print_warning(_("Too many storage engines!"));
386
if (hton->db_type != DB_TYPE_UNKNOWN)
387
sql_print_warning(_("Storage engine '%s' has conflicting typecode. "
388
"Assigning value %d."), plugin->plugin->name, idx);
389
hton->db_type= (enum legacy_db_type) idx;
391
installed_htons[hton->db_type]= hton;
392
tmp= hton->savepoint_offset;
393
hton->savepoint_offset= savepoint_alloc_size;
394
savepoint_alloc_size+= tmp;
395
hton->slot= total_ha++;
396
hton2plugin[hton->slot]=plugin;
403
hton->state= SHOW_OPTION_DISABLED;
408
This is entirely for legacy. We will create a new "disk based" hton and a
409
"memory" hton which will be configurable longterm. We should be able to
410
remove partition and myisammrg.
412
if (strcmp(plugin->plugin->name, "MEMORY") == 0)
415
if (strcmp(plugin->plugin->name, "MyISAM") == 0)
595
334
The server stores its transaction-related data in
596
thd->transaction. This structure has two members of type
597
THD_TRANS. These members correspond to the statement and
335
session->transaction. This structure has two members of type
336
Session_TRANS. These members correspond to the statement and
598
337
normal transactions respectively:
600
- thd->transaction.stmt contains a list of engines
339
- session->transaction.stmt contains a list of engines
601
340
that are participating in the given statement
602
- thd->transaction.all contains a list of engines that
341
- session->transaction.all contains a list of engines that
603
342
have participated in any of the statement transactions started
604
343
within the context of the normal transaction.
605
344
Each element of the list contains a pointer to the storage
606
345
engine, engine-specific transactional data, and engine-specific
607
346
transaction flags.
609
In autocommit mode thd->transaction.all is empty.
610
Instead, data of thd->transaction.stmt is
348
In autocommit mode session->transaction.all is empty.
349
Instead, data of session->transaction.stmt is
611
350
used to commit/rollback the normal transaction.
613
352
The list of registered engines has a few important properties:
797
536
times per transaction.
800
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
539
void trans_register_ha(Session *session, bool all, handlerton *ht_arg)
541
Session_TRANS *trans;
803
542
Ha_trx_info *ha_info;
807
trans= &thd->transaction.all;
808
thd->server_status|= SERVER_STATUS_IN_TRANS;
546
trans= &session->transaction.all;
547
session->server_status|= SERVER_STATUS_IN_TRANS;
811
trans= &thd->transaction.stmt;
550
trans= &session->transaction.stmt;
813
ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
552
ha_info= session->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
815
554
if (ha_info->is_started())
816
555
return; /* already registered, return */
843
582
handlerton *ht= ha_info->ht();
844
status_var_increment(thd->status_var.ha_prepare_count);
583
status_var_increment(session->status_var.ha_prepare_count);
847
if ((err= ht->prepare(ht, thd, all)))
586
if ((err= ht->prepare(ht, session, all)))
849
588
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
850
ha_rollback_trans(thd, all);
589
ha_rollback_trans(session, all);
857
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
596
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
858
597
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
859
598
ha_resolve_storage_engine_name(ht));
933
672
stored functions or triggers. So we simply do nothing now.
934
673
TODO: This should be fixed in later ( >= 5.1) releases.
936
int ha_commit_trans(THD *thd, bool all)
675
int ha_commit_trans(Session *session, bool all)
938
677
int error= 0, cookie= 0;
940
679
'all' means that this is either an explicit commit issued by
941
680
user, or an implicit commit issued by a DDL.
943
THD_TRANS *trans= all ? &thd->transaction.all : &thd->transaction.stmt;
944
bool is_real_trans= all || thd->transaction.all.ha_list == 0;
682
Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
683
bool is_real_trans= all || session->transaction.all.ha_list == 0;
945
684
Ha_trx_info *ha_info= trans->ha_list;
946
my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
949
687
We must not commit the normal transaction if a statement
951
689
flags will not get propagated to its normal transaction's
954
assert(thd->transaction.stmt.ha_list == NULL ||
955
trans == &thd->transaction.stmt);
692
assert(session->transaction.stmt.ha_list == NULL ||
693
trans == &session->transaction.stmt);
957
if (thd->in_sub_stmt)
960
Since we don't support nested statement transactions in 5.0,
961
we can't commit or rollback stmt transactions while we are inside
962
stored functions or triggers. So we simply do nothing now.
963
TODO: This should be fixed in later ( >= 5.1) releases.
968
We assume that all statements which commit or rollback main transaction
969
are prohibited inside of stored functions or triggers. So they should
970
bail out with error even before ha_commit_trans() call. To be 100% safe
971
let us throw error in non-debug builds.
974
my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
981
if (is_real_trans && wait_if_global_read_lock(thd, 0, 0))
699
if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
983
ha_rollback_trans(thd, all);
701
ha_rollback_trans(session, all);
989
&& ! thd->slave_thread
992
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
993
ha_rollback_trans(thd, all);
998
must_2pc= ha_check_and_coalesce_trx_read_only(thd, ha_info, all);
705
must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
1000
707
if (!trans->no_2pc && must_2pc)
1014
721
Sic: we know that prepare() is not NULL since otherwise
1015
722
trans->no_2pc would have been set.
1017
if ((err= ht->prepare(ht, thd, all)))
724
if ((err= ht->prepare(ht, session, all)))
1019
726
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1022
status_var_increment(thd->status_var.ha_prepare_count);
729
status_var_increment(session->status_var.ha_prepare_count);
1024
if (error || (is_real_trans && xid &&
1025
(error= !(cookie= tc_log->log_xid(thd, xid)))))
1027
ha_rollback_trans(thd, all);
733
ha_rollback_trans(session, all);
1032
error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1034
tc_log->unlog(cookie, xid);
738
error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1036
740
if (is_real_trans)
1037
start_waiting_global_read_lock(thd);
741
start_waiting_global_read_lock(session);
1057
761
handlerton *ht= ha_info->ht();
1058
if ((err= ht->commit(ht, thd, all)))
762
if ((err= ht->commit(ht, session, all)))
1060
764
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1063
status_var_increment(thd->status_var.ha_commit_count);
767
status_var_increment(session->status_var.ha_commit_count);
1064
768
ha_info_next= ha_info->next();
1065
769
ha_info->reset(); /* keep it conveniently zero-filled */
1067
771
trans->ha_list= 0;
1068
772
trans->no_2pc=0;
1069
773
if (is_real_trans)
1070
thd->transaction.xid_state.xid.null();
774
session->transaction.xid_state.xid.null();
1073
thd->variables.tx_isolation=thd->session_tx_isolation;
1074
thd->transaction.cleanup();
777
session->variables.tx_isolation=session->session_tx_isolation;
778
session->transaction.cleanup();
1081
int ha_rollback_trans(THD *thd, bool all)
785
int ha_rollback_trans(Session *session, bool all)
1084
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
788
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1085
789
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1086
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
790
bool is_real_trans=all || session->transaction.all.ha_list == 0;
1089
793
We must not rollback the normal transaction if a statement
1090
794
transaction is pending.
1092
assert(thd->transaction.stmt.ha_list == NULL ||
1093
trans == &thd->transaction.stmt);
796
assert(session->transaction.stmt.ha_list == NULL ||
797
trans == &session->transaction.stmt);
1095
if (thd->in_sub_stmt)
1098
If we are inside stored function or trigger we should not commit or
1099
rollback current statement transaction. See comment in ha_commit_trans()
1100
call for more information.
1105
my_error(ER_COMMIT_NOT_ALLOWED_IN_SF_OR_TRG, MYF(0));
1110
801
for (; ha_info; ha_info= ha_info_next)
1113
804
handlerton *ht= ha_info->ht();
1114
if ((err= ht->rollback(ht, thd, all)))
805
if ((err= ht->rollback(ht, session, all)))
1115
806
{ // cannot happen
1116
807
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1119
status_var_increment(thd->status_var.ha_rollback_count);
810
status_var_increment(session->status_var.ha_rollback_count);
1120
811
ha_info_next= ha_info->next();
1121
812
ha_info->reset(); /* keep it conveniently zero-filled */
1123
814
trans->ha_list= 0;
1124
815
trans->no_2pc=0;
1125
816
if (is_real_trans)
1126
thd->transaction.xid_state.xid.null();
817
session->transaction.xid_state.xid.null();
1129
thd->variables.tx_isolation=thd->session_tx_isolation;
1130
thd->transaction.cleanup();
820
session->variables.tx_isolation=session->session_tx_isolation;
821
session->transaction.cleanup();
1134
thd->transaction_rollback_request= false;
825
session->transaction_rollback_request= false;
1137
828
If a non-transactional table was updated, warn; don't warn if this is a
1161
851
the user has used LOCK TABLES then that mechanism does not know to do the
1164
int ha_autocommit_or_rollback(THD *thd, int error)
854
int ha_autocommit_or_rollback(Session *session, int error)
1166
if (thd->transaction.stmt.ha_list)
856
if (session->transaction.stmt.ha_list)
1170
if (ha_commit_trans(thd, 0))
860
if (ha_commit_trans(session, 0))
1175
(void) ha_rollback_trans(thd, 0);
1176
if (thd->transaction_rollback_request && !thd->in_sub_stmt)
1177
(void) ha_rollback(thd);
865
(void) ha_rollback_trans(session, 0);
866
if (session->transaction_rollback_request)
867
(void) ha_rollback(session);
1180
thd->variables.tx_isolation=thd->session_tx_isolation;
870
session->variables.tx_isolation=session->session_tx_isolation;
1334
for (info.len= MAX_XID_LIST_SIZE ;
1024
for (info.len= MAX_XID_LIST_SIZE ;
1335
1025
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1337
info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
1027
info.list=(XID *)malloc(info.len*sizeof(XID));
1339
1029
if (!info.list)
1341
sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1031
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1345
plugin_foreach(NULL, xarecover_handlerton,
1035
plugin_foreach(NULL, xarecover_handlerton,
1346
1036
DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1348
1038
free((unsigned char*)info.list);
1349
1039
if (info.found_foreign_xids)
1350
sql_print_warning(_("Found %d prepared XA transactions"),
1351
info.found_foreign_xids);
1040
errmsg_printf(ERRMSG_LVL_WARN, _("Found %d prepared XA transactions"),
1041
info.found_foreign_xids);
1352
1042
if (info.dry_run && info.found_my_xids)
1354
sql_print_error(_("Found %d prepared transactions! It means that drizzled "
1044
errmsg_printf(ERRMSG_LVL_ERROR,
1045
_("Found %d prepared transactions! It means that drizzled "
1355
1046
"was not shut down properly last time and critical "
1356
1047
"recovery information (last binlog or %s file) was "
1357
1048
"manually deleted after a crash. You have to start "
1426
1117
performs another SQL query. In MySQL-4.1 this is even more important because
1427
1118
there a connection can have several SELECT queries open at the same time.
1429
@param thd the thread handle of the current connection
1120
@param session the thread handle of the current connection
1434
static bool release_temporary_latches(THD *thd, plugin_ref plugin,
1435
void *unused __attribute__((unused)))
1125
static bool release_temporary_latches(Session *session, plugin_ref plugin,
1437
1128
handlerton *hton= plugin_data(plugin, handlerton *);
1439
1130
if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1440
hton->release_temporary_latches(hton, thd);
1131
hton->release_temporary_latches(hton, session);
1446
int ha_release_temporary_latches(THD *thd)
1137
int ha_release_temporary_latches(Session *session)
1448
plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1139
plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1454
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
1145
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1457
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1458
&thd->transaction.all);
1148
Session_TRANS *trans= &session->transaction.all;
1459
1149
Ha_trx_info *ha_info, *ha_info_next;
1461
1151
trans->no_2pc=0;
1565
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
1254
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
1567
1256
handlerton *hton= plugin_data(plugin, handlerton *);
1568
1257
if (hton->state == SHOW_OPTION_YES &&
1569
1258
hton->start_consistent_snapshot)
1571
hton->start_consistent_snapshot(hton, thd);
1260
hton->start_consistent_snapshot(hton, session);
1572
1261
*((bool *)arg)= false;
1577
int ha_start_consistent_snapshot(THD *thd)
1266
int ha_start_consistent_snapshot(Session *session)
1579
1268
bool warn= true;
1581
plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1270
plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1584
1273
Same idea as when one wants to CREATE TABLE in one engine which does not
1588
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1589
"This MySQL server does not support any "
1277
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1278
"This Drizzle server does not support any "
1590
1279
"consistent-read capable storage engine");
1595
static bool flush_handlerton(THD *thd __attribute__((unused)),
1284
static bool flush_handlerton(Session *,
1596
1285
plugin_ref plugin,
1597
void *arg __attribute__((unused)))
1599
1288
handlerton *hton= plugin_data(plugin, handlerton *);
1600
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1289
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1601
1290
hton->flush_logs(hton))
1652
1341
virtual bool handle_error(uint32_t sql_errno,
1653
1342
const char *message,
1654
1343
DRIZZLE_ERROR::enum_warning_level level,
1656
1345
char buff[DRIZZLE_ERRMSG_SIZE];
1661
1350
Ha_delete_table_error_handler::
1662
handle_error(uint32_t sql_errno __attribute__((unused)),
1351
handle_error(uint32_t ,
1663
1352
const char *message,
1664
DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1665
THD *thd __attribute__((unused)))
1353
DRIZZLE_ERROR::enum_warning_level ,
1667
1356
/* Grab the error message */
1668
strmake(buff, message, sizeof(buff)-1);
1357
strncpy(buff, message, sizeof(buff)-1);
1362
struct handlerton_delete_table_args {
1369
static bool deletetable_handlerton(Session *,
1373
struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
1375
Session *session= dtargs->session;
1376
const char *path= dtargs->path;
1379
char tmp_path[FN_REFLEN];
1381
if(dtargs->error!=ENOENT) /* already deleted table */
1384
handlerton *table_type= plugin_data(plugin, handlerton *);
1389
if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
1392
if ((file= table_type->create(table_type, NULL, session->mem_root)))
1397
path= check_lowercase_names(file, path, tmp_path);
1398
int error= file->ha_delete_table(path);
1402
dtargs->error= error;
1404
delete dtargs->file;
1674
1413
This should return ENOENT if the file doesn't exists.
1675
1414
The .frm file will be deleted only if we return 0 or ENOENT
1677
int ha_delete_table(THD *thd, handlerton *table_type, const char *path,
1416
int ha_delete_table(Session *session, const char *path,
1678
1417
const char *db, const char *alias, bool generate_warning)
1681
char tmp_path[FN_REFLEN];
1419
TABLE_SHARE dummy_share;
1683
1420
Table dummy_table;
1684
TABLE_SHARE dummy_share;
1422
struct handlerton_delete_table_args dtargs;
1423
dtargs.error= ENOENT;
1424
dtargs.session= session;
1428
plugin_foreach(NULL, deletetable_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1686
1431
memset(&dummy_table, 0, sizeof(dummy_table));
1687
1432
memset(&dummy_share, 0, sizeof(dummy_share));
1688
1433
dummy_table.s= &dummy_share;
1690
/* DB_TYPE_UNKNOWN is used in ALTER Table when renaming only .frm files */
1691
if (table_type == NULL ||
1692
! (file=get_new_handler((TABLE_SHARE*)0, thd->mem_root, table_type)))
1695
path= check_lowercase_names(file, path, tmp_path);
1696
if ((error= file->ha_delete_table(path)) && generate_warning)
1435
if (dtargs.error && generate_warning)
1699
1438
Because file->print_error() use my_error() to generate the error message
1712
1451
dummy_share.table_name.length= strlen(alias);
1713
1452
dummy_table.alias= alias;
1715
file->change_table_ptr(&dummy_table, &dummy_share);
1717
thd->push_internal_handler(&ha_delete_table_error_handler);
1718
file->print_error(error, 0);
1720
thd->pop_internal_handler();
1456
handler *file= dtargs.file;
1457
file->change_table_ptr(&dummy_table, &dummy_share);
1459
session->push_internal_handler(&ha_delete_table_error_handler);
1460
file->print_error(dtargs.error, 0);
1462
session->pop_internal_handler();
1465
dtargs.error= -1; /* General form of fail. maybe bad FRM */
1723
1468
XXX: should we convert *all* errors to warnings here?
1724
1469
What if the error is fatal?
1726
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
1471
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, dtargs.error,
1727
1472
ha_delete_table_error_handler.buff);
1478
return dtargs.error;
1733
1481
/****************************************************************************
1502
int handler::ha_index_init(uint32_t idx, bool sorted)
1505
assert(inited==NONE);
1506
if (!(result= index_init(idx, sorted)))
1512
int handler::ha_index_end()
1514
assert(inited==INDEX);
1517
return(index_end());
1520
int handler::ha_rnd_init(bool scan)
1523
assert(inited==NONE || (inited==RND && scan));
1524
inited= (result= rnd_init(scan)) ? NONE: RND;
1528
int handler::ha_rnd_end()
1530
assert(inited==RND);
1535
int handler::ha_index_or_rnd_end()
1537
return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1540
handler::Table_flags handler::ha_table_flags() const
1542
return cached_table_flags;
1545
void handler::ha_start_bulk_insert(ha_rows rows)
1547
estimation_rows_to_insert= rows;
1548
start_bulk_insert(rows);
1551
int handler::ha_end_bulk_insert()
1553
estimation_rows_to_insert= 0;
1554
return end_bulk_insert();
1557
void handler::change_table_ptr(Table *table_arg, TABLE_SHARE *share)
1563
const key_map *handler::keys_to_use_for_scanning()
1565
return &key_map_empty;
1568
bool handler::has_transactions()
1570
return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1756
1573
void handler::ha_statistic_increment(ulong SSV::*offset) const
1758
1575
status_var_increment(table->in_use->status_var.*offset);
1761
void **handler::ha_data(THD *thd) const
1763
return thd_ha_data(thd, ht);
1766
THD *handler::ha_thd(void) const
1768
assert(!table || !table->in_use || table->in_use == current_thd);
1769
return (table && table->in_use) ? table->in_use : current_thd;
1578
void **handler::ha_data(Session *session) const
1580
return session_ha_data(session, ht);
1583
Session *handler::ha_session(void) const
1585
assert(!table || !table->in_use || table->in_use == current_session);
1586
return (table && table->in_use) ? table->in_use : current_session;
1590
bool handler::is_fatal_error(int error, uint32_t flags)
1593
((flags & HA_CHECK_DUP_KEY) &&
1594
(error == HA_ERR_FOUND_DUPP_KEY ||
1595
error == HA_ERR_FOUND_DUPP_UNIQUE)))
1601
ha_rows handler::records() { return stats.records; }
1773
1604
Open database-handler.
1990
1821
start counting from the inserted value.
1992
1823
This function's "outputs" are: the table's auto_increment field is filled
1993
with a value, thd->next_insert_id is filled with the value to use for the
1824
with a value, session->next_insert_id is filled with the value to use for the
1994
1825
next row, if a value was autogenerated for the current row it is stored in
1995
thd->insert_id_for_cur_row, if get_auto_increment() was called
1996
thd->auto_inc_interval_for_cur_row is modified, if that interval is not
1997
present in thd->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
1826
session->insert_id_for_cur_row, if get_auto_increment() was called
1827
session->auto_inc_interval_for_cur_row is modified, if that interval is not
1828
present in session->auto_inc_intervals_in_cur_stmt_for_binlog it is added to
2545
static bool update_frm_version(Table *table)
2547
char path[FN_REFLEN];
2552
No need to update frm version in case table was created or checked
2553
by server with the same version. This also ensures that we do not
2554
update frm version for temporary tables as this code doesn't support
2557
if (table->s->mysql_version == DRIZZLE_VERSION_ID)
2560
strxmov(path, table->s->normalized_path.str, reg_ext, NULL);
2562
if ((file= my_open(path, O_RDWR|O_BINARY, MYF(MY_WME))) >= 0)
2564
unsigned char version[4];
2565
char *key= table->s->table_cache_key.str;
2566
uint32_t key_length= table->s->table_cache_key.length;
2568
HASH_SEARCH_STATE state;
2570
int4store(version, DRIZZLE_VERSION_ID);
2572
if (pwrite(file, (unsigned char*)version, 4, 51L) == 0)
2578
for (entry=(Table*) hash_first(&open_cache,(unsigned char*) key,key_length, &state);
2580
entry= (Table*) hash_next(&open_cache,(unsigned char*) key,key_length, &state))
2581
entry->s->mysql_version= DRIZZLE_VERSION_ID;
2585
my_close(file,MYF(MY_WME));
2593
2369
key if error because of duplicated keys
3078
2847
char name_buff[FN_REFLEN];
3079
2848
const char *name;
3080
2849
TABLE_SHARE share;
3082
init_tmp_table_share(thd, &share, db, 0, table_name, path);
3083
if (open_table_def(thd, &share, 0) ||
3084
open_table_from_share(thd, &share, "", 0, (uint) READ_ALL, 0, &table,
2851
init_tmp_table_share(session, &share, db, 0, table_name, path);
2852
if (open_table_def(session, &share, 0) ||
2853
open_table_from_share(session, &share, "", 0, (uint) READ_ALL, 0, &table,
3102
2871
return(error != 0);
3106
Try to discover table from engine.
3109
If found, write the frm file to disk.
3112
-1 Table did not exists
3116
> 0 Error, table existed but could not be created
3118
int ha_create_table_from_engine(THD* thd, const char *db, const char *name)
3121
unsigned char *frmblob;
3123
char path[FN_REFLEN];
3124
HA_CREATE_INFO create_info;
3128
memset(&create_info, 0, sizeof(create_info));
3129
if ((error= ha_discover(thd, db, name, &frmblob, &frmlen)))
3131
/* Table could not be discovered and thus not created */
3136
Table exists in handler and could be discovered
3137
frmblob and frmlen are set, write the frm to disk
3140
build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
3141
// Save the frm file
3142
error= writefrm(path, frmblob, frmlen);
3147
init_tmp_table_share(thd, &share, db, 0, name, path);
3148
if (open_table_def(thd, &share, 0))
3152
if (open_table_from_share(thd, &share, "" ,0, 0, 0, &table, OTM_OPEN))
3154
free_table_share(&share);
3158
table.updateCreateInfo(&create_info);
3159
create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
3161
check_lowercase_names(table.file, path, path);
3162
error=table.file->ha_create(path, &table, &create_info);
3163
closefrm(&table, 1);
3168
2874
void st_ha_check_opt::init()
3170
flags= sql_flags= 0;
3171
sort_buffer_size = current_thd->variables.myisam_sort_buff_size;
3266
Try to discover one table from handler(s).
3269
-1 Table did not exists
3271
0 OK. In this case *frmblob and *frmlen are set
3273
>0 error. frmblob and frmlen may not be set
3275
struct st_discover_args
3279
unsigned char **frmblob;
3283
static bool discover_handlerton(THD *thd, plugin_ref plugin,
3286
st_discover_args *vargs= (st_discover_args *)arg;
3287
handlerton *hton= plugin_data(plugin, handlerton *);
3288
if (hton->state == SHOW_OPTION_YES && hton->discover &&
3289
(!(hton->discover(hton, thd, vargs->db, vargs->name,
3297
int ha_discover(THD *thd, const char *db, const char *name,
3298
unsigned char **frmblob, size_t *frmlen)
3300
int error= -1; // Table does not exist in any handler
3301
st_discover_args args= {db, name, frmblob, frmlen};
3303
if (is_prefix(name,tmp_file_prefix)) /* skip temporary tables */
3306
if (plugin_foreach(thd, discover_handlerton,
3307
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
3311
status_var_increment(thd->status_var.ha_discover_count);
3317
2971
Call this function in order to give the handler the possiblity
3318
2972
to ask engine if there are any new tables that should be written to disk
3352
3007
int err= HA_ERR_NO_SUCH_TABLE;
3354
3009
if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3355
err = hton->table_exists_in_engine(hton, thd, vargs->db, vargs->name);
3010
err = hton->table_exists_in_engine(hton, session, vargs->db, vargs->name);
3357
3012
vargs->err = err;
3358
3013
if (vargs->err == HA_ERR_TABLE_EXIST)
3364
int ha_table_exists_in_engine(THD* thd, const char* db, const char* name)
3022
int ha_table_exists_in_engine(Session* session,
3023
const char* db, const char* name,
3366
st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3367
plugin_foreach(thd, table_exists_in_engine_handlerton,
3026
st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE, NULL};
3027
plugin_foreach(session, table_exists_in_engine_handlerton,
3368
3028
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
3030
if(args.err==HA_ERR_NO_SUCH_TABLE)
3032
/* Default way of knowing if a table exists. (checking .frm exists) */
3034
char path[FN_REFLEN];
3035
build_table_filename(path, sizeof(path),
3036
db, name, ".dfe", 0);
3037
if (!access(path, F_OK))
3038
args.err= HA_ERR_TABLE_EXIST;
3040
args.err= HA_ERR_NO_SUCH_TABLE;
3042
if(args.err==HA_ERR_TABLE_EXIST)
3044
drizzle::Table table;
3045
if(drizzle_read_table_proto(path, &table)==0)
3047
LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
3048
strlen(table.engine().name().c_str()) };
3049
plugin_ref plugin= ha_resolve_by_name(session, &engine_name);
3051
args.hton= plugin_data(plugin,handlerton *);
3369
3059
return(args.err);
3440
3128
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3441
3129
void *seq_init_param,
3442
uint32_t n_ranges_arg __attribute__((unused)),
3443
3131
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3445
3133
KEY_MULTI_RANGE range;
3446
3134
range_seq_t seq_it;
3447
3135
ha_rows rows, total_rows= 0;
3448
3136
uint32_t n_ranges=0;
3449
THD *thd= current_thd;
3137
Session *session= current_session;
3451
3139
/* Default MRR implementation doesn't need buffer */
3454
3142
seq_it= seq->init(seq_init_param, n_ranges, *flags);
3455
3143
while (!seq->next(seq_it, &range))
3457
if (unlikely(thd->killed != 0))
3145
if (unlikely(session->killed != 0))
3458
3146
return HA_POS_ERROR;
3461
3149
key_range *min_endp, *max_endp;
3551
3239
Initialize the MRR scan
3553
Initialize the MRR scan. This function may do heavyweight scan
3241
Initialize the MRR scan. This function may do heavyweight scan
3554
3242
initialization like row prefetching/sorting/etc (NOTE: but better not do
3555
3243
it here as we may not need it, e.g. if we never satisfy WHERE clause on
3556
3244
previous tables. For many implementations it would be natural to do such
3557
3245
initializations in the first multi_read_range_next() call)
3559
3247
mode is a combination of the following flags: HA_MRR_SORTED,
3560
HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3248
HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3562
3250
@param seq Range sequence to be traversed
3563
3251
@param seq_init_param First parameter for seq->init()
3698
3386
uint32_t keyno;
3699
3387
Item *pushed_cond= NULL;
3700
3388
handler *new_h2;
3701
keyno= h->active_index;
3389
keyno= h_in->active_index;
3702
3390
assert(h2 == NULL);
3703
3391
if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3705
3393
use_default_impl= true;
3706
return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
3394
return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3707
3395
n_ranges, mode, buf));
3709
3397
rowids_buf= buf->buffer;
3710
3398
//psergey-todo: don't add key_length as it is not needed anymore
3711
rowids_buf += key->key_length + h->ref_length;
3399
rowids_buf += key->key_length + h_in->ref_length;
3713
3401
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3714
3402
rowids_buf_end= buf->buffer_end;
3716
elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3717
rowids_buf_last= rowids_buf +
3404
elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
3405
rowids_buf_last= rowids_buf +
3718
3406
((rowids_buf_end - rowids_buf)/ elem_size)*
3720
3408
rowids_buf_end= rowids_buf_last;
3722
3410
/* Create a separate handler object to do rndpos() calls. */
3723
THD *thd= current_thd;
3724
if (!(new_h2= h->clone(thd->mem_root)) ||
3725
new_h2->ha_external_lock(thd, F_RDLCK))
3411
Session *session= current_session;
3412
if (!(new_h2= h_in->clone(session->mem_root)) ||
3413
new_h2->ha_external_lock(session, F_RDLCK))
3731
if (keyno == h->pushed_idx_cond_keyno)
3732
pushed_cond= h->pushed_idx_cond;
3733
if (h->ha_index_end())
3419
if (keyno == h_in->pushed_idx_cond_keyno)
3420
pushed_cond= h_in->pushed_idx_cond;
3421
if (h_in->ha_index_end())
4016
3704
COST_VECT dsmrr_cost;
4018
THD *thd= current_thd;
4019
if ((thd->variables.optimizer_use_mrr == 2) ||
3706
Session *session= current_session;
3707
if ((session->variables.optimizer_use_mrr == 2) ||
4020
3708
(*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4021
(keyno == table->s->primary_key &&
4022
h->primary_key_is_clustered()) ||
3709
(keyno == table->s->primary_key &&
3710
h->primary_key_is_clustered()) ||
4023
3711
key_uses_partial_cols(keyno))
4025
3713
/* Use the default implementation */
4026
3714
*flags |= HA_MRR_USE_DEFAULT_IMPL;
4030
uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
3718
uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4031
3719
*bufsz -= add_len;
4032
3720
if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4034
3722
*bufsz += add_len;
4036
3724
bool force_dsmrr;
4038
3726
If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4039
3727
DS-MRR and Default implementations cost. This allows one to force use of
4040
3728
DS-MRR whenever it is applicable without affecting other cost-based
4043
if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
3731
if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4044
3732
dsmrr_cost.total_cost() > cost->total_cost())
4045
3733
dsmrr_cost= *cost;
4114
*buffer_size= cmax((ulong)*buffer_size,
4115
(size_t)(1.2*rows_in_last_step) * elem_size +
3802
*buffer_size= cmax((ulong)*buffer_size,
3803
(size_t)(1.2*rows_in_last_step) * elem_size +
4116
3804
h->ref_length + table->key_info[keynr].key_length);
4119
3807
COST_VECT last_step_cost;
4120
3808
get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
4121
3809
cost->add(&last_step_cost);
4123
3811
if (n_full_steps != 0)
4124
3812
cost->mem_cost= *buffer_size;
4126
3814
cost->mem_cost= (double)rows_in_last_step * elem_size;
4128
3816
/* Total cost of all index accesses */
4129
3817
index_read_cost= h->index_only_read_time(keynr, (double)rows);
4130
3818
cost->add_io(index_read_cost, 1 /* Random seeks */);
4455
static bool stat_print(THD *thd, const char *type, uint32_t type_len,
4144
static bool stat_print(Session *session, const char *type, uint32_t type_len,
4456
4145
const char *file, uint32_t file_len,
4457
4146
const char *status, uint32_t status_len)
4459
Protocol *protocol= thd->protocol;
4148
Protocol *protocol= session->protocol;
4460
4149
protocol->prepare_for_resend();
4461
4150
protocol->store(type, type_len, system_charset_info);
4462
4151
protocol->store(file, file_len, system_charset_info);
4501
4190
- table is not mysql.event
4504
static bool check_table_binlog_row_based(THD *thd, Table *table)
4506
if (table->s->cached_row_logging_check == -1)
4508
int const check(table->s->tmp_table == NO_TMP_TABLE &&
4509
binlog_filter->db_ok(table->s->db.str));
4510
table->s->cached_row_logging_check= check;
4513
assert(table->s->cached_row_logging_check == 0 ||
4514
table->s->cached_row_logging_check == 1);
4516
return (thd->current_stmt_binlog_row_based &&
4517
table->s->cached_row_logging_check &&
4518
(thd->options & OPTION_BIN_LOG) &&
4519
mysql_bin_log.is_open());
4524
Write table maps for all (manually or automatically) locked tables
4527
This function will generate and write table maps for all tables
4528
that are locked by the thread 'thd'. Either manually locked
4529
(stored in THD::locked_tables) and automatically locked (stored
4530
in THD::lock) are considered.
4532
@param thd Pointer to THD structure
4535
@retval 1 Failed to write all table maps
4542
static int write_locked_table_maps(THD *thd)
4544
if (thd->get_binlog_table_maps() == 0)
4546
DRIZZLE_LOCK *locks[3];
4547
locks[0]= thd->extra_lock;
4548
locks[1]= thd->lock;
4549
locks[2]= thd->locked_tables;
4550
for (uint32_t i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4552
DRIZZLE_LOCK const *const lock= locks[i];
4556
Table **const end_ptr= lock->table + lock->table_count;
4557
for (Table **table_ptr= lock->table ;
4558
table_ptr != end_ptr ;
4561
Table *const table= *table_ptr;
4562
if (table->current_lock == F_WRLCK &&
4563
check_table_binlog_row_based(thd, table))
4565
int const has_trans= table->file->has_transactions();
4566
int const error= thd->binlog_write_table_map(table, has_trans);
4568
If an error occurs, it is the responsibility of the caller to
4569
roll back the transaction.
4571
if (unlikely(error))
4581
typedef bool Log_func(THD*, Table*, bool, const unsigned char*, const unsigned char*);
4583
static int binlog_log_row(Table* table,
4584
const unsigned char *before_record,
4585
const unsigned char *after_record,
4588
if (table->no_replicate)
4591
THD *const thd= table->in_use;
4593
if (check_table_binlog_row_based(thd, table))
4193
static bool binlog_log_row(Table* table,
4194
const unsigned char *before_record,
4195
const unsigned char *after_record)
4198
Session *const session= table->in_use;
4200
if (table->no_replicate == false)
4203
error= replicator_session_init(session);
4205
switch (session->lex->sql_command)
4207
case SQLCOM_REPLACE:
4209
case SQLCOM_REPLACE_SELECT:
4210
case SQLCOM_INSERT_SELECT:
4211
case SQLCOM_CREATE_TABLE:
4212
error= replicator_write_row(session, table);
4216
case SQLCOM_UPDATE_MULTI:
4217
error= replicator_update_row(session, table, before_record, after_record);
4221
case SQLCOM_DELETE_MULTI:
4222
error= replicator_delete_row(session, table);
4596
If there are no table maps written to the binary log, this is
4597
the first row handled in this statement. In that case, we need
4598
to write table maps for all locked tables to the binary log.
4226
For everything else we ignore the event (since it just involves a temp table)
4600
if (likely(!(error= write_locked_table_maps(thd))))
4602
bool const has_trans= table->file->has_transactions();
4603
error= (*log_func)(thd, table, has_trans, before_record, after_record);
4606
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
4609
int handler::ha_external_lock(THD *thd, int lock_type)
4235
int handler::ha_external_lock(Session *session, int lock_type)
4612
4238
Whether this is lock or unlock, this should be true, and is to verify that
4652
4278
int handler::ha_write_row(unsigned char *buf)
4655
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4656
4281
DRIZZLE_INSERT_ROW_START();
4284
* If we have a timestamp column, update it to the current time
4286
* @TODO Technically, the below two lines can be take even further out of the
4287
* handler interface and into the fill_record() method.
4289
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
4290
table->timestamp_field->set_time();
4658
4292
mark_trx_read_write();
4660
4294
if (unlikely(error= write_row(buf)))
4662
if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4663
return(error); /* purecov: inspected */
4297
if (unlikely(binlog_log_row(table, 0, buf)))
4298
return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
4664
4300
DRIZZLE_INSERT_ROW_END();
4682
4317
if (unlikely(error= update_row(old_data, new_data)))
4684
if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4320
if (unlikely(binlog_log_row(table, old_data, new_data)))
4321
return HA_ERR_RBR_LOGGING_FAILED;
4689
4326
int handler::ha_delete_row(const unsigned char *buf)
4692
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4694
4330
mark_trx_read_write();
4696
4332
if (unlikely(error= delete_row(buf)))
4698
if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4335
if (unlikely(binlog_log_row(table, buf, 0)))
4336
return HA_ERR_RBR_LOGGING_FAILED;