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 "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)
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"
35
#include "drizzled/session.h"
36
#include "drizzled/sql_base.h"
37
#include "drizzled/replicator.h"
38
#include "drizzled/lock.h"
39
#include "drizzled/item/int.h"
40
#include "drizzled/item/empty_string.h"
41
#include "drizzled/unireg.h" // for mysql_frm_type
42
#include "drizzled/field/timestamp.h"
43
#include "drizzled/serialize/table.pb.h"
41
47
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
61
60
const char *tx_isolation_names[] =
62
61
{ "READ-UNCOMMITTED", "READ-COMMITTED", "REPEATABLE-READ", "SERIALIZABLE",
64
64
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
65
tx_isolation_names, NULL};
65
tx_isolation_names, NULL};
67
67
static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
68
68
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
72
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
329
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
330
session->transaction. This structure has two members of type
331
Session_TRANS. These members correspond to the statement and
598
332
normal transactions respectively:
600
- thd->transaction.stmt contains a list of engines
334
- session->transaction.stmt contains a list of engines
601
335
that are participating in the given statement
602
- thd->transaction.all contains a list of engines that
336
- session->transaction.all contains a list of engines that
603
337
have participated in any of the statement transactions started
604
338
within the context of the normal transaction.
605
339
Each element of the list contains a pointer to the storage
606
340
engine, engine-specific transactional data, and engine-specific
607
341
transaction flags.
609
In autocommit mode thd->transaction.all is empty.
610
Instead, data of thd->transaction.stmt is
343
In autocommit mode session->transaction.all is empty.
344
Instead, data of session->transaction.stmt is
611
345
used to commit/rollback the normal transaction.
613
347
The list of registered engines has a few important properties:
750
484
---------------------------------------------------
752
486
DDLs and operations with non-transactional engines
753
do not "register" in thd->transaction lists, and thus do not
487
do not "register" in session->transaction lists, and thus do not
754
488
modify the transaction state. Besides, each DDL in
755
489
MySQL is prefixed with an implicit normal transaction commit
756
(a call to end_active_trans()), and thus leaves nothing
490
(a call to Session::endActiveTransaction()), and thus leaves nothing
758
492
However, as it has been pointed out with CREATE TABLE .. SELECT,
759
493
some DDL statements can start a *new* transaction.
797
531
times per transaction.
800
void trans_register_ha(THD *thd, bool all, handlerton *ht_arg)
534
void trans_register_ha(Session *session, bool all, handlerton *ht_arg)
536
Session_TRANS *trans;
803
537
Ha_trx_info *ha_info;
807
trans= &thd->transaction.all;
808
thd->server_status|= SERVER_STATUS_IN_TRANS;
541
trans= &session->transaction.all;
542
session->server_status|= SERVER_STATUS_IN_TRANS;
811
trans= &thd->transaction.stmt;
545
trans= &session->transaction.stmt;
813
ha_info= thd->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
547
ha_info= session->ha_data[ht_arg->slot].ha_info + static_cast<unsigned>(all);
815
549
if (ha_info->is_started())
816
550
return; /* already registered, return */
843
577
handlerton *ht= ha_info->ht();
844
status_var_increment(thd->status_var.ha_prepare_count);
578
status_var_increment(session->status_var.ha_prepare_count);
847
if ((err= ht->prepare(ht, thd, all)))
581
if ((err= ht->prepare(ht, session, all)))
849
583
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
850
ha_rollback_trans(thd, all);
584
ha_rollback_trans(session, all);
857
push_warning_printf(thd, DRIZZLE_ERROR::WARN_LEVEL_WARN,
591
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
858
592
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
859
593
ha_resolve_storage_engine_name(ht));
933
667
stored functions or triggers. So we simply do nothing now.
934
668
TODO: This should be fixed in later ( >= 5.1) releases.
936
int ha_commit_trans(THD *thd, bool all)
670
int ha_commit_trans(Session *session, bool all)
938
672
int error= 0, cookie= 0;
940
674
'all' means that this is either an explicit commit issued by
941
675
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;
677
Session_TRANS *trans= all ? &session->transaction.all : &session->transaction.stmt;
678
bool is_real_trans= all || session->transaction.all.ha_list == 0;
945
679
Ha_trx_info *ha_info= trans->ha_list;
946
my_xid xid= thd->transaction.xid_state.xid.get_my_xid();
949
682
We must not commit the normal transaction if a statement
951
684
flags will not get propagated to its normal transaction's
954
assert(thd->transaction.stmt.ha_list == NULL ||
955
trans == &thd->transaction.stmt);
687
assert(session->transaction.stmt.ha_list == NULL ||
688
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))
694
if (is_real_trans && wait_if_global_read_lock(session, 0, 0))
983
ha_rollback_trans(thd, all);
696
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);
700
must_2pc= ha_check_and_coalesce_trx_read_only(session, ha_info, all);
1000
702
if (!trans->no_2pc && must_2pc)
1014
716
Sic: we know that prepare() is not NULL since otherwise
1015
717
trans->no_2pc would have been set.
1017
if ((err= ht->prepare(ht, thd, all)))
719
if ((err= ht->prepare(ht, session, all)))
1019
721
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1022
status_var_increment(thd->status_var.ha_prepare_count);
724
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);
728
ha_rollback_trans(session, all);
1032
error=ha_commit_one_phase(thd, all) ? (cookie ? 2 : 1) : 0;
1034
tc_log->unlog(cookie, xid);
733
error=ha_commit_one_phase(session, all) ? (cookie ? 2 : 1) : 0;
1036
735
if (is_real_trans)
1037
start_waiting_global_read_lock(thd);
736
start_waiting_global_read_lock(session);
1057
756
handlerton *ht= ha_info->ht();
1058
if ((err= ht->commit(ht, thd, all)))
757
if ((err= ht->commit(ht, session, all)))
1060
759
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
1063
status_var_increment(thd->status_var.ha_commit_count);
762
status_var_increment(session->status_var.ha_commit_count);
1064
763
ha_info_next= ha_info->next();
1065
764
ha_info->reset(); /* keep it conveniently zero-filled */
1067
766
trans->ha_list= 0;
1068
767
trans->no_2pc=0;
1069
768
if (is_real_trans)
1070
thd->transaction.xid_state.xid.null();
769
session->transaction.xid_state.xid.null();
1073
thd->variables.tx_isolation=thd->session_tx_isolation;
1074
thd->transaction.cleanup();
772
session->variables.tx_isolation=session->session_tx_isolation;
773
session->transaction.cleanup();
1081
int ha_rollback_trans(THD *thd, bool all)
780
int ha_rollback_trans(Session *session, bool all)
1084
THD_TRANS *trans=all ? &thd->transaction.all : &thd->transaction.stmt;
783
Session_TRANS *trans=all ? &session->transaction.all : &session->transaction.stmt;
1085
784
Ha_trx_info *ha_info= trans->ha_list, *ha_info_next;
1086
bool is_real_trans=all || thd->transaction.all.ha_list == 0;
785
bool is_real_trans=all || session->transaction.all.ha_list == 0;
1089
788
We must not rollback the normal transaction if a statement
1090
789
transaction is pending.
1092
assert(thd->transaction.stmt.ha_list == NULL ||
1093
trans == &thd->transaction.stmt);
791
assert(session->transaction.stmt.ha_list == NULL ||
792
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
796
for (; ha_info; ha_info= ha_info_next)
1113
799
handlerton *ht= ha_info->ht();
1114
if ((err= ht->rollback(ht, thd, all)))
800
if ((err= ht->rollback(ht, session, all)))
1115
801
{ // cannot happen
1116
802
my_error(ER_ERROR_DURING_ROLLBACK, MYF(0), err);
1119
status_var_increment(thd->status_var.ha_rollback_count);
805
status_var_increment(session->status_var.ha_rollback_count);
1120
806
ha_info_next= ha_info->next();
1121
807
ha_info->reset(); /* keep it conveniently zero-filled */
1123
809
trans->ha_list= 0;
1124
810
trans->no_2pc=0;
1125
811
if (is_real_trans)
1126
thd->transaction.xid_state.xid.null();
812
session->transaction.xid_state.xid.null();
1129
thd->variables.tx_isolation=thd->session_tx_isolation;
1130
thd->transaction.cleanup();
815
session->variables.tx_isolation=session->session_tx_isolation;
816
session->transaction.cleanup();
1134
thd->transaction_rollback_request= false;
820
session->transaction_rollback_request= false;
1137
823
If a non-transactional table was updated, warn; don't warn if this is a
1161
846
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)
849
int ha_autocommit_or_rollback(Session *session, int error)
1166
if (thd->transaction.stmt.ha_list)
851
if (session->transaction.stmt.ha_list)
1170
if (ha_commit_trans(thd, 0))
855
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);
860
(void) ha_rollback_trans(session, 0);
861
if (session->transaction_rollback_request)
862
(void) ha_rollback(session);
1180
thd->variables.tx_isolation=thd->session_tx_isolation;
865
session->variables.tx_isolation=session->session_tx_isolation;
1325
1010
rollback all pending transactions, without risking inconsistent data
1328
assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
1013
assert(total_ha_2pc == 2); // only InnoDB and binlog
1329
1014
tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
1330
1015
info.dry_run=false;
1334
for (info.len= MAX_XID_LIST_SIZE ;
1019
for (info.len= MAX_XID_LIST_SIZE ;
1335
1020
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1337
info.list=(XID *)my_malloc(info.len*sizeof(XID), MYF(0));
1022
info.list=(XID *)malloc(info.len*sizeof(XID));
1339
1024
if (!info.list)
1341
sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1026
errmsg_printf(ERRMSG_LVL_ERROR, ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1345
plugin_foreach(NULL, xarecover_handlerton,
1030
plugin_foreach(NULL, xarecover_handlerton,
1346
1031
DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1348
1033
free((unsigned char*)info.list);
1349
1034
if (info.found_foreign_xids)
1350
sql_print_warning(_("Found %d prepared XA transactions"),
1351
info.found_foreign_xids);
1035
errmsg_printf(ERRMSG_LVL_WARN, _("Found %d prepared XA transactions"),
1036
info.found_foreign_xids);
1352
1037
if (info.dry_run && info.found_my_xids)
1354
sql_print_error(_("Found %d prepared transactions! It means that drizzled "
1039
errmsg_printf(ERRMSG_LVL_ERROR,
1040
_("Found %d prepared transactions! It means that drizzled "
1355
1041
"was not shut down properly last time and critical "
1356
1042
"recovery information (last binlog or %s file) was "
1357
1043
"manually deleted after a crash. You have to start "
1426
1112
performs another SQL query. In MySQL-4.1 this is even more important because
1427
1113
there a connection can have several SELECT queries open at the same time.
1429
@param thd the thread handle of the current connection
1115
@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)))
1120
static bool release_temporary_latches(Session *session, plugin_ref plugin,
1437
1123
handlerton *hton= plugin_data(plugin, handlerton *);
1439
1125
if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1440
hton->release_temporary_latches(hton, thd);
1126
hton->release_temporary_latches(hton, session);
1446
int ha_release_temporary_latches(THD *thd)
1132
int ha_release_temporary_latches(Session *session)
1448
plugin_foreach(thd, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1134
plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1454
int ha_rollback_to_savepoint(THD *thd, SAVEPOINT *sv)
1140
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1457
THD_TRANS *trans= (thd->in_sub_stmt ? &thd->transaction.stmt :
1458
&thd->transaction.all);
1143
Session_TRANS *trans= &session->transaction.all;
1459
1144
Ha_trx_info *ha_info, *ha_info_next;
1461
1146
trans->no_2pc=0;
1565
static bool snapshot_handlerton(THD *thd, plugin_ref plugin, void *arg)
1249
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
1567
1251
handlerton *hton= plugin_data(plugin, handlerton *);
1568
1252
if (hton->state == SHOW_OPTION_YES &&
1569
1253
hton->start_consistent_snapshot)
1571
hton->start_consistent_snapshot(hton, thd);
1255
hton->start_consistent_snapshot(hton, session);
1572
1256
*((bool *)arg)= false;
1577
int ha_start_consistent_snapshot(THD *thd)
1261
int ha_start_consistent_snapshot(Session *session)
1579
1263
bool warn= true;
1581
plugin_foreach(thd, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1265
plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1584
1268
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 "
1272
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1273
"This Drizzle server does not support any "
1590
1274
"consistent-read capable storage engine");
1595
static bool flush_handlerton(THD *thd __attribute__((unused)),
1279
static bool flush_handlerton(Session *,
1596
1280
plugin_ref plugin,
1597
void *arg __attribute__((unused)))
1599
1283
handlerton *hton= plugin_data(plugin, handlerton *);
1600
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1284
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1601
1285
hton->flush_logs(hton))
1649
1333
struct Ha_delete_table_error_handler: public Internal_error_handler
1336
Ha_delete_table_error_handler() : Internal_error_handler() {}
1652
1337
virtual bool handle_error(uint32_t sql_errno,
1653
1338
const char *message,
1654
1339
DRIZZLE_ERROR::enum_warning_level level,
1656
1341
char buff[DRIZZLE_ERRMSG_SIZE];
1661
1346
Ha_delete_table_error_handler::
1662
handle_error(uint32_t sql_errno __attribute__((unused)),
1347
handle_error(uint32_t ,
1663
1348
const char *message,
1664
DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1665
THD *thd __attribute__((unused)))
1349
DRIZZLE_ERROR::enum_warning_level ,
1667
1352
/* Grab the error message */
1668
strmake(buff, message, sizeof(buff)-1);
1353
strncpy(buff, message, sizeof(buff)-1);
1358
struct handlerton_delete_table_args {
1365
static bool deletetable_handlerton(Session *,
1369
struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
1371
Session *session= dtargs->session;
1372
const char *path= dtargs->path;
1375
char tmp_path[FN_REFLEN];
1377
if(dtargs->error!=ENOENT) /* already deleted table */
1380
handlerton *table_type= plugin_data(plugin, handlerton *);
1385
if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
1388
if ((file= table_type->create(table_type, NULL, session->mem_root)))
1393
path= check_lowercase_names(file, path, tmp_path);
1394
int error= file->ha_delete_table(path);
1398
dtargs->error= error;
1400
delete dtargs->file;
1674
1411
This should return ENOENT if the file doesn't exists.
1675
1412
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,
1414
int ha_delete_table(Session *session, const char *path,
1678
1415
const char *db, const char *alias, bool generate_warning)
1681
char tmp_path[FN_REFLEN];
1417
TABLE_SHARE dummy_share;
1683
1418
Table dummy_table;
1684
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,
1686
1429
memset(&dummy_table, 0, sizeof(dummy_table));
1687
1430
memset(&dummy_share, 0, sizeof(dummy_share));
1688
1431
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)
1433
if (dtargs.error && generate_warning)
1699
1436
Because file->print_error() use my_error() to generate the error message
1712
1449
dummy_share.table_name.length= strlen(alias);
1713
1450
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();
1454
handler *file= dtargs.file;
1455
file->change_table_ptr(&dummy_table, &dummy_share);
1457
session->push_internal_handler(&ha_delete_table_error_handler);
1458
file->print_error(dtargs.error, 0);
1460
session->pop_internal_handler();
1463
dtargs.error= -1; /* General form of fail. maybe bad FRM */
1723
1466
XXX: should we convert *all* errors to warnings here?
1724
1467
What if the error is fatal?
1726
push_warning(thd, DRIZZLE_ERROR::WARN_LEVEL_ERROR, error,
1469
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, dtargs.error,
1727
1470
ha_delete_table_error_handler.buff);
1476
return dtargs.error;
1733
1479
/****************************************************************************
1500
int handler::ha_index_init(uint32_t idx, bool sorted)
1503
assert(inited==NONE);
1504
if (!(result= index_init(idx, sorted)))
1510
int handler::ha_index_end()
1512
assert(inited==INDEX);
1515
return(index_end());
1518
int handler::ha_rnd_init(bool scan)
1521
assert(inited==NONE || (inited==RND && scan));
1522
inited= (result= rnd_init(scan)) ? NONE: RND;
1526
int handler::ha_rnd_end()
1528
assert(inited==RND);
1533
int handler::ha_index_or_rnd_end()
1535
return inited == INDEX ? ha_index_end() : inited == RND ? ha_rnd_end() : 0;
1538
handler::Table_flags handler::ha_table_flags() const
1540
return cached_table_flags;
1543
void handler::ha_start_bulk_insert(ha_rows rows)
1545
estimation_rows_to_insert= rows;
1546
start_bulk_insert(rows);
1549
int handler::ha_end_bulk_insert()
1551
estimation_rows_to_insert= 0;
1552
return end_bulk_insert();
1555
void handler::change_table_ptr(Table *table_arg, TABLE_SHARE *share)
1561
const key_map *handler::keys_to_use_for_scanning()
1563
return &key_map_empty;
1566
bool handler::has_transactions()
1568
return (ha_table_flags() & HA_NO_TRANSACTIONS) == 0;
1756
1571
void handler::ha_statistic_increment(ulong SSV::*offset) const
1758
1573
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;
1576
void **handler::ha_data(Session *session) const
1578
return session_ha_data(session, ht);
1581
Session *handler::ha_session(void) const
1583
assert(!table || !table->in_use || table->in_use == current_session);
1584
return (table && table->in_use) ? table->in_use : current_session;
1588
bool handler::is_fatal_error(int error, uint32_t flags)
1591
((flags & HA_CHECK_DUP_KEY) &&
1592
(error == HA_ERR_FOUND_DUPP_KEY ||
1593
error == HA_ERR_FOUND_DUPP_UNIQUE)))
1599
ha_rows handler::records() { return stats.records; }
1773
1602
Open database-handler.
1990
1819
start counting from the inserted value.
1992
1821
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
1822
with a value, session->next_insert_id is filled with the value to use for the
1994
1823
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
1824
session->insert_id_for_cur_row, if get_auto_increment() was called
1825
session->auto_inc_interval_for_cur_row is modified, if that interval is not
1826
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
2367
key if error because of duplicated keys
2595
2369
uint32_t handler::get_dup_key(int error)
2597
table->file->errkey = (uint) -1;
2371
table->file->errkey = (uint32_t) -1;
2598
2372
if (error == HA_ERR_FOUND_DUPP_KEY || error == HA_ERR_FOREIGN_DUPLICATE_KEY ||
2599
2373
error == HA_ERR_FOUND_DUPP_UNIQUE ||
2600
2374
error == HA_ERR_DROP_INDEX_FK)
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, (uint32_t) 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),
3037
if (table_proto_exists(path)==EEXIST)
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
build_table_filename(path, sizeof(path),
3046
db, name, ".dfe", 0);
3047
if(drizzle_read_table_proto(path, &table)==0)
3049
LEX_STRING engine_name= { (char*)table.engine().name().c_str(),
3050
strlen(table.engine().name().c_str()) };
3051
plugin_ref plugin= ha_resolve_by_name(session, &engine_name);
3053
args.hton= plugin_data(plugin,handlerton *);
3369
3061
return(args.err);
3440
3130
handler::multi_range_read_info_const(uint32_t keyno, RANGE_SEQ_IF *seq,
3441
3131
void *seq_init_param,
3442
uint32_t n_ranges_arg __attribute__((unused)),
3443
3133
uint32_t *bufsz, uint32_t *flags, COST_VECT *cost)
3445
3135
KEY_MULTI_RANGE range;
3446
3136
range_seq_t seq_it;
3447
3137
ha_rows rows, total_rows= 0;
3448
3138
uint32_t n_ranges=0;
3449
THD *thd= current_thd;
3139
Session *session= current_session;
3451
3141
/* Default MRR implementation doesn't need buffer */
3454
3144
seq_it= seq->init(seq_init_param, n_ranges, *flags);
3455
3145
while (!seq->next(seq_it, &range))
3457
if (unlikely(thd->killed != 0))
3147
if (unlikely(session->killed != 0))
3458
3148
return HA_POS_ERROR;
3461
3151
key_range *min_endp, *max_endp;
3551
3241
Initialize the MRR scan
3553
Initialize the MRR scan. This function may do heavyweight scan
3243
Initialize the MRR scan. This function may do heavyweight scan
3554
3244
initialization like row prefetching/sorting/etc (NOTE: but better not do
3555
3245
it here as we may not need it, e.g. if we never satisfy WHERE clause on
3556
3246
previous tables. For many implementations it would be natural to do such
3557
3247
initializations in the first multi_read_range_next() call)
3559
3249
mode is a combination of the following flags: HA_MRR_SORTED,
3560
HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3250
HA_MRR_INDEX_ONLY, HA_MRR_NO_ASSOCIATION
3562
3252
@param seq Range sequence to be traversed
3563
3253
@param seq_init_param First parameter for seq->init()
3698
3388
uint32_t keyno;
3699
3389
Item *pushed_cond= NULL;
3700
3390
handler *new_h2;
3701
keyno= h->active_index;
3391
keyno= h_in->active_index;
3702
3392
assert(h2 == NULL);
3703
3393
if (mode & HA_MRR_USE_DEFAULT_IMPL || mode & HA_MRR_SORTED)
3705
3395
use_default_impl= true;
3706
return(h->handler::multi_range_read_init(seq_funcs, seq_init_param,
3396
return(h_in->handler::multi_range_read_init(seq_funcs, seq_init_param,
3707
3397
n_ranges, mode, buf));
3709
3399
rowids_buf= buf->buffer;
3710
3400
//psergey-todo: don't add key_length as it is not needed anymore
3711
rowids_buf += key->key_length + h->ref_length;
3401
rowids_buf += key->key_length + h_in->ref_length;
3713
3403
is_mrr_assoc= !test(mode & HA_MRR_NO_ASSOCIATION);
3714
3404
rowids_buf_end= buf->buffer_end;
3716
elem_size= h->ref_length + (int)is_mrr_assoc * sizeof(void*);
3717
rowids_buf_last= rowids_buf +
3406
elem_size= h_in->ref_length + (int)is_mrr_assoc * sizeof(void*);
3407
rowids_buf_last= rowids_buf +
3718
3408
((rowids_buf_end - rowids_buf)/ elem_size)*
3720
3410
rowids_buf_end= rowids_buf_last;
3722
3412
/* 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))
3413
Session *session= current_session;
3414
if (!(new_h2= h_in->clone(session->mem_root)) ||
3415
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())
3421
if (keyno == h_in->pushed_idx_cond_keyno)
3422
pushed_cond= h_in->pushed_idx_cond;
3423
if (h_in->ha_index_end())
4016
3706
COST_VECT dsmrr_cost;
4018
THD *thd= current_thd;
4019
if ((thd->variables.optimizer_use_mrr == 2) ||
3708
Session *session= current_session;
3709
if ((session->variables.optimizer_use_mrr == 2) ||
4020
3710
(*flags & HA_MRR_INDEX_ONLY) || (*flags & HA_MRR_SORTED) ||
4021
(keyno == table->s->primary_key &&
4022
h->primary_key_is_clustered()) ||
3711
(keyno == table->s->primary_key &&
3712
h->primary_key_is_clustered()) ||
4023
3713
key_uses_partial_cols(keyno))
4025
3715
/* Use the default implementation */
4026
3716
*flags |= HA_MRR_USE_DEFAULT_IMPL;
4030
uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
3720
uint32_t add_len= table->key_info[keyno].key_length + h->ref_length;
4031
3721
*bufsz -= add_len;
4032
3722
if (get_disk_sweep_mrr_cost(keyno, rows, *flags, bufsz, &dsmrr_cost))
4034
3724
*bufsz += add_len;
4036
3726
bool force_dsmrr;
4038
3728
If @@optimizer_use_mrr==force, then set cost of DS-MRR to be minimum of
4039
3729
DS-MRR and Default implementations cost. This allows one to force use of
4040
3730
DS-MRR whenever it is applicable without affecting other cost-based
4043
if ((force_dsmrr= (thd->variables.optimizer_use_mrr == 1)) &&
3733
if ((force_dsmrr= (session->variables.optimizer_use_mrr == 1)) &&
4044
3734
dsmrr_cost.total_cost() > cost->total_cost())
4045
3735
dsmrr_cost= *cost;
4092
3782
return true; /* Buffer has not enough space for even 1 rowid */
4094
3784
/* Number of iterations we'll make with full buffer */
4095
n_full_steps= (uint)floor(rows2double(rows) / max_buff_entries);
4098
Get numbers of rows we'll be processing in
4099
- non-last sweep, with full buffer
3785
n_full_steps= (uint32_t)floor(rows2double(rows) / max_buff_entries);
3788
Get numbers of rows we'll be processing in
3789
- non-last sweep, with full buffer
4100
3790
- last iteration, with non-full buffer
4102
3792
rows_in_full_step= max_buff_entries;
4103
3793
rows_in_last_step= rows % max_buff_entries;
4105
3795
/* Adjust buffer size if we expect to use only part of the buffer */
4106
3796
if (n_full_steps)
4114
*buffer_size= cmax((ulong)*buffer_size,
4115
(size_t)(1.2*rows_in_last_step) * elem_size +
3804
*buffer_size= cmax((ulong)*buffer_size,
3805
(size_t)(1.2*rows_in_last_step) * elem_size +
4116
3806
h->ref_length + table->key_info[keynr].key_length);
4119
3809
COST_VECT last_step_cost;
4120
3810
get_sort_and_sweep_cost(table, rows_in_last_step, &last_step_cost);
4121
3811
cost->add(&last_step_cost);
4123
3813
if (n_full_steps != 0)
4124
3814
cost->mem_cost= *buffer_size;
4126
3816
cost->mem_cost= (double)rows_in_last_step * elem_size;
4128
3818
/* Total cost of all index accesses */
4129
3819
index_read_cost= h->index_only_read_time(keynr, (double)rows);
4130
3820
cost->add_io(index_read_cost, 1 /* Random seeks */);
4455
static bool stat_print(THD *thd, const char *type, uint32_t type_len,
4146
static bool stat_print(Session *session, const char *type, uint32_t type_len,
4456
4147
const char *file, uint32_t file_len,
4457
4148
const char *status, uint32_t status_len)
4459
Protocol *protocol= thd->protocol;
4150
Protocol *protocol= session->protocol;
4460
4151
protocol->prepare_for_resend();
4461
4152
protocol->store(type, type_len, system_charset_info);
4462
4153
protocol->store(file, file_len, system_charset_info);
4501
4192
- 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))
4195
static bool binlog_log_row(Table* table,
4196
const unsigned char *before_record,
4197
const unsigned char *after_record)
4200
Session *const session= table->in_use;
4202
if (table->no_replicate == false)
4205
error= replicator_session_init(session);
4207
switch (session->lex->sql_command)
4209
case SQLCOM_REPLACE:
4211
case SQLCOM_REPLACE_SELECT:
4212
case SQLCOM_INSERT_SELECT:
4213
case SQLCOM_CREATE_TABLE:
4214
error= replicator_write_row(session, table);
4218
case SQLCOM_UPDATE_MULTI:
4219
error= replicator_update_row(session, table, before_record, after_record);
4223
case SQLCOM_DELETE_MULTI:
4224
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.
4228
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)
4237
int handler::ha_external_lock(Session *session, int lock_type)
4612
4240
Whether this is lock or unlock, this should be true, and is to verify that
4652
4280
int handler::ha_write_row(unsigned char *buf)
4655
Log_func *log_func= Write_rows_log_event::binlog_row_logging_function;
4656
4283
DRIZZLE_INSERT_ROW_START();
4286
* If we have a timestamp column, update it to the current time
4288
* @TODO Technically, the below two lines can be take even further out of the
4289
* handler interface and into the fill_record() method.
4291
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
4292
table->timestamp_field->set_time();
4658
4294
mark_trx_read_write();
4660
4296
if (unlikely(error= write_row(buf)))
4662
if (unlikely(error= binlog_log_row(table, 0, buf, log_func)))
4663
return(error); /* purecov: inspected */
4299
if (unlikely(binlog_log_row(table, 0, buf)))
4300
return HA_ERR_RBR_LOGGING_FAILED; /* purecov: inspected */
4664
4302
DRIZZLE_INSERT_ROW_END();
4682
4319
if (unlikely(error= update_row(old_data, new_data)))
4684
if (unlikely(error= binlog_log_row(table, old_data, new_data, log_func)))
4322
if (unlikely(binlog_log_row(table, old_data, new_data)))
4323
return HA_ERR_RBR_LOGGING_FAILED;
4689
4328
int handler::ha_delete_row(const unsigned char *buf)
4692
Log_func *log_func= Delete_rows_log_event::binlog_row_logging_function;
4694
4332
mark_trx_read_write();
4696
4334
if (unlikely(error= delete_row(buf)))
4698
if (unlikely(error= binlog_log_row(table, buf, 0, log_func)))
4337
if (unlikely(binlog_log_row(table, buf, 0)))
4338
return HA_ERR_RBR_LOGGING_FAILED;