23
23
Handler-calling-functions
26
#include "drizzled/server_includes.h"
27
#include "mysys/hash.h"
28
#include "drizzled/error.h"
29
#include "drizzled/gettext.h"
30
#include "drizzled/data_home.h"
31
#include "drizzled/probes.h"
32
#include "drizzled/sql_parse.h"
33
#include "drizzled/cost_vect.h"
34
#include "drizzled/session.h"
35
#include "drizzled/sql_base.h"
36
#include "drizzled/replicator.h"
37
#include "drizzled/lock.h"
38
#include "drizzled/item/int.h"
39
#include "drizzled/item/empty_string.h"
40
#include "drizzled/unireg.h" // for mysql_frm_type
41
#include "drizzled/field/timestamp.h"
42
#include "drizzled/serialize/table.pb.h"
26
#include <drizzled/server_includes.h>
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>
39
#if defined(CMATH_NAMESPACE)
40
using namespace CMATH_NAMESPACE;
44
extern HASH open_cache;
46
46
KEY_CREATE_INFO default_key_create_info= { HA_KEY_ALG_UNDEF, 0, {NULL,0}, {NULL,0} };
48
/* number of entries in storage_engines[] */
48
/* number of entries in handlertons[] */
49
49
uint32_t total_ha= 0;
50
/* number of storage engines (from storage_engines[]) that support 2pc */
50
/* number of storage engines (from handlertons[]) that support 2pc */
51
51
uint32_t total_ha_2pc= 0;
52
52
/* size of savepoint storage area (see ha_init) */
53
53
uint32_t savepoint_alloc_size= 0;
187
static bool dropdb_handlerton(Session *unused1 __attribute__((unused)),
191
handlerton *hton= plugin_data(plugin, handlerton *);
192
if (hton->state == SHOW_OPTION_YES && hton->drop_database)
193
hton->drop_database(hton, (char *)path);
198
void ha_drop_database(char* path)
200
plugin_foreach(NULL, dropdb_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, path);
204
static bool closecon_handlerton(Session *session, plugin_ref plugin,
205
void *unused __attribute__((unused)))
207
handlerton *hton= plugin_data(plugin, handlerton *);
209
there's no need to rollback here as all transactions must
210
be rolled back already
212
if (hton->state == SHOW_OPTION_YES && hton->close_connection &&
213
session_get_ha_data(session, hton))
214
hton->close_connection(hton, session);
221
don't bother to rollback here, it's done already
223
void ha_close_connection(Session* session)
225
plugin_foreach(session, closecon_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, 0);
185
228
/* ========================================================================
186
229
======================= TRANSACTIONS ===================================*/
531
574
for (; ha_info; ha_info= ha_info->next())
534
StorageEngine *engine= ha_info->engine();
577
handlerton *ht= ha_info->ht();
535
578
status_var_increment(session->status_var.ha_prepare_count);
536
if ((err= engine->prepare(session, all)))
538
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
539
ha_rollback_trans(session, all);
581
if ((err= ht->prepare(ht, session, all)))
583
my_error(ER_ERROR_DURING_COMMIT, MYF(0), err);
584
ha_rollback_trans(session, all);
545
591
push_warning_printf(session, DRIZZLE_ERROR::WARN_LEVEL_WARN,
546
592
ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA),
547
engine->getName().c_str());
593
ha_resolve_storage_engine_name(ht));
892
static bool xacommit_handlerton(Session *unused1 __attribute__((unused)),
896
handlerton *hton= plugin_data(plugin, handlerton *);
897
if (hton->state == SHOW_OPTION_YES && hton->recover)
899
hton->commit_by_xid(hton, ((struct xahton_st *)arg)->xid);
900
((struct xahton_st *)arg)->result= 0;
905
static bool xarollback_handlerton(Session *unused1 __attribute__((unused)),
909
handlerton *hton= plugin_data(plugin, handlerton *);
910
if (hton->state == SHOW_OPTION_YES && hton->recover)
912
hton->rollback_by_xid(hton, ((struct xahton_st *)arg)->xid);
913
((struct xahton_st *)arg)->result= 0;
919
int ha_commit_or_rollback_by_xid(XID *xid, bool commit)
921
struct xahton_st xaop;
925
plugin_foreach(NULL, commit ? xacommit_handlerton : xarollback_handlerton,
926
DRIZZLE_STORAGE_ENGINE_PLUGIN, &xaop);
932
recover() step of xa.
935
there are three modes of operation:
936
- automatic recover after a crash
937
in this case commit_list != 0, tc_heuristic_recover==0
938
all xids from commit_list are committed, others are rolled back
939
- manual (heuristic) recover
940
in this case commit_list==0, tc_heuristic_recover != 0
941
DBA has explicitly specified that all prepared transactions should
942
be committed (or rolled back).
943
- no recovery (MySQL did not detect a crash)
944
in this case commit_list==0, tc_heuristic_recover == 0
945
there should be no prepared transactions in this case.
949
int len, found_foreign_xids, found_my_xids;
955
static bool xarecover_handlerton(Session *unused __attribute__((unused)),
959
handlerton *hton= plugin_data(plugin, handlerton *);
960
struct xarecover_st *info= (struct xarecover_st *) arg;
963
if (hton->state == SHOW_OPTION_YES && hton->recover)
965
while ((got= hton->recover(hton, info->list, info->len)) > 0 )
967
sql_print_information(_("Found %d prepared transaction(s) in %s"),
968
got, ha_resolve_storage_engine_name(hton));
969
for (int i=0; i < got; i ++)
971
my_xid x=info->list[i].get_my_xid();
972
if (!x) // not "mine" - that is generated by external TM
974
xid_cache_insert(info->list+i, XA_PREPARED);
975
info->found_foreign_xids++;
980
info->found_my_xids++;
984
if (info->commit_list ?
985
hash_search(info->commit_list, (unsigned char *)&x, sizeof(x)) != 0 :
986
tc_heuristic_recover == TC_HEURISTIC_RECOVER_COMMIT)
988
hton->commit_by_xid(hton, info->list+i);
992
hton->rollback_by_xid(hton, info->list+i);
1002
int ha_recover(HASH *commit_list)
1004
struct xarecover_st info;
1005
info.found_foreign_xids= info.found_my_xids= 0;
1006
info.commit_list= commit_list;
1007
info.dry_run= (info.commit_list==0 && tc_heuristic_recover==0);
1010
/* commit_list and tc_heuristic_recover cannot be set both */
1011
assert(info.commit_list==0 || tc_heuristic_recover==0);
1012
/* if either is set, total_ha_2pc must be set too */
1013
assert(info.dry_run || total_ha_2pc>(uint32_t)opt_bin_log);
1015
if (total_ha_2pc <= (uint32_t)opt_bin_log)
1018
if (info.commit_list)
1019
sql_print_information(_("Starting crash recovery..."));
1022
#ifndef WILL_BE_DELETED_LATER
1025
for now, only InnoDB supports 2pc. It means we can always safely
1026
rollback all pending transactions, without risking inconsistent data
1029
assert(total_ha_2pc == (uint32_t) opt_bin_log+1); // only InnoDB and binlog
1030
tc_heuristic_recover= TC_HEURISTIC_RECOVER_ROLLBACK; // forcing ROLLBACK
1035
for (info.len= MAX_XID_LIST_SIZE ;
1036
info.list==0 && info.len > MIN_XID_LIST_SIZE; info.len/=2)
1038
info.list=(XID *)malloc(info.len*sizeof(XID));
1042
sql_print_error(ER(ER_OUTOFMEMORY), info.len*sizeof(XID));
1046
plugin_foreach(NULL, xarecover_handlerton,
1047
DRIZZLE_STORAGE_ENGINE_PLUGIN, &info);
1049
free((unsigned char*)info.list);
1050
if (info.found_foreign_xids)
1051
sql_print_warning(_("Found %d prepared XA transactions"),
1052
info.found_foreign_xids);
1053
if (info.dry_run && info.found_my_xids)
1055
sql_print_error(_("Found %d prepared transactions! It means that drizzled "
1056
"was not shut down properly last time and critical "
1057
"recovery information (last binlog or %s file) was "
1058
"manually deleted after a crash. You have to start "
1059
"drizzled with the --tc-heuristic-recover switch to "
1060
"commit or rollback pending transactions."),
1061
info.found_my_xids, opt_tc_log_file);
1064
if (info.commit_list)
1065
sql_print_information(_("Crash recovery finished."));
828
1070
return the list of XID's to a client, the same way SHOW commands do.
870
1112
pthread_mutex_unlock(&LOCK_xid_cache);
1119
This function should be called when MySQL sends rows of a SELECT result set
1120
or the EOF mark to the client. It releases a possible adaptive hash index
1121
S-latch held by session in InnoDB and also releases a possible InnoDB query
1122
FIFO ticket to enter InnoDB. To save CPU time, InnoDB allows a session to
1123
keep them over several calls of the InnoDB handler interface when a join
1124
is executed. But when we let the control to pass to the client they have
1125
to be released because if the application program uses mysql_use_result(),
1126
it may deadlock on the S-latch if the application on another connection
1127
performs another SQL query. In MySQL-4.1 this is even more important because
1128
there a connection can have several SELECT queries open at the same time.
1130
@param session the thread handle of the current connection
1135
static bool release_temporary_latches(Session *session, plugin_ref plugin,
1136
void *unused __attribute__((unused)))
1138
handlerton *hton= plugin_data(plugin, handlerton *);
1140
if (hton->state == SHOW_OPTION_YES && hton->release_temporary_latches)
1141
hton->release_temporary_latches(hton, session);
1147
int ha_release_temporary_latches(Session *session)
1149
plugin_foreach(session, release_temporary_latches, DRIZZLE_STORAGE_ENGINE_PLUGIN,
876
1155
int ha_rollback_to_savepoint(Session *session, SAVEPOINT *sv)
1264
static bool snapshot_handlerton(Session *session, plugin_ref plugin, void *arg)
1266
handlerton *hton= plugin_data(plugin, handlerton *);
1267
if (hton->state == SHOW_OPTION_YES &&
1268
hton->start_consistent_snapshot)
1270
hton->start_consistent_snapshot(hton, session);
1271
*((bool *)arg)= false;
1276
int ha_start_consistent_snapshot(Session *session)
1280
plugin_foreach(session, snapshot_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN, &warn);
1283
Same idea as when one wants to CREATE TABLE in one engine which does not
1287
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
1288
"This MySQL server does not support any "
1289
"consistent-read capable storage engine");
1294
static bool flush_handlerton(Session *session __attribute__((unused)),
1296
void *arg __attribute__((unused)))
1298
handlerton *hton= plugin_data(plugin, handlerton *);
1299
if (hton->state == SHOW_OPTION_YES && hton->flush_logs &&
1300
hton->flush_logs(hton))
1306
bool ha_flush_logs(handlerton *db_type)
1308
if (db_type == NULL)
1310
if (plugin_foreach(NULL, flush_handlerton,
1311
DRIZZLE_STORAGE_ENGINE_PLUGIN, 0))
1316
if (db_type->state != SHOW_OPTION_YES ||
1317
(db_type->flush_logs && db_type->flush_logs(db_type)))
1323
static const char *check_lowercase_names(handler *file, const char *path,
1326
if (lower_case_table_names != 2 || (file->ha_table_flags() & HA_FILE_BASED))
1329
/* Ensure that table handler get path in lower case */
1330
if (tmp_path != path)
1331
strcpy(tmp_path, path);
1334
we only should turn into lowercase database/table part
1335
so start the process after homedirectory
1337
my_casedn_str(files_charset_info, tmp_path + drizzle_data_home_len);
1343
An interceptor to hijack the text of the error message without
1344
setting an error in the thread. We need the text to present it
1345
in the form of a warning to the user.
1348
struct Ha_delete_table_error_handler: public Internal_error_handler
1351
virtual bool handle_error(uint32_t sql_errno,
1352
const char *message,
1353
DRIZZLE_ERROR::enum_warning_level level,
1355
char buff[DRIZZLE_ERRMSG_SIZE];
1360
Ha_delete_table_error_handler::
1361
handle_error(uint32_t sql_errno __attribute__((unused)),
1362
const char *message,
1363
DRIZZLE_ERROR::enum_warning_level level __attribute__((unused)),
1364
Session *session __attribute__((unused)))
1366
/* Grab the error message */
1367
strncpy(buff, message, sizeof(buff)-1);
1372
struct handlerton_delete_table_args {
1379
static bool deletetable_handlerton(Session *unused1 __attribute__((unused)),
1383
struct handlerton_delete_table_args *dtargs= (struct handlerton_delete_table_args *) args;
1385
Session *session= dtargs->session;
1386
const char *path= dtargs->path;
1389
char tmp_path[FN_REFLEN];
1391
if(dtargs->error!=ENOENT) /* already deleted table */
1394
handlerton *table_type= plugin_data(plugin, handlerton *);
1399
if(!(table_type->state == SHOW_OPTION_YES && table_type->create))
1402
if ((file= table_type->create(table_type, NULL, session->mem_root)))
1407
path= check_lowercase_names(file, path, tmp_path);
1408
int error= file->ha_delete_table(path);
1412
dtargs->error= error;
1414
delete dtargs->file;
1423
This should return ENOENT if the file doesn't exists.
1424
The .frm file will be deleted only if we return 0 or ENOENT
1426
int ha_delete_table(Session *session, const char *path,
1427
const char *db, const char *alias, bool generate_warning)
1429
TABLE_SHARE dummy_share;
1432
struct handlerton_delete_table_args dtargs;
1433
dtargs.error= ENOENT;
1434
dtargs.session= session;
1438
plugin_foreach(NULL, deletetable_handlerton, DRIZZLE_STORAGE_ENGINE_PLUGIN,
1441
memset(&dummy_table, 0, sizeof(dummy_table));
1442
memset(&dummy_share, 0, sizeof(dummy_share));
1443
dummy_table.s= &dummy_share;
1445
if (dtargs.error && generate_warning)
1448
Because file->print_error() use my_error() to generate the error message
1449
we use an internal error handler to intercept it and store the text
1450
in a temporary buffer. Later the message will be presented to user
1453
Ha_delete_table_error_handler ha_delete_table_error_handler;
1455
/* Fill up strucutures that print_error may need */
1456
dummy_share.path.str= (char*) path;
1457
dummy_share.path.length= strlen(path);
1458
dummy_share.db.str= (char*) db;
1459
dummy_share.db.length= strlen(db);
1460
dummy_share.table_name.str= (char*) alias;
1461
dummy_share.table_name.length= strlen(alias);
1462
dummy_table.alias= alias;
1464
handler *file= dtargs.file;
1465
file->change_table_ptr(&dummy_table, &dummy_share);
1467
session->push_internal_handler(&ha_delete_table_error_handler);
1468
file->print_error(dtargs.error, 0);
1470
session->pop_internal_handler();
1473
XXX: should we convert *all* errors to warnings here?
1474
What if the error is fatal?
1476
push_warning(session, DRIZZLE_ERROR::WARN_LEVEL_ERROR, dtargs.error,
1477
ha_delete_table_error_handler.buff);
1483
return dtargs.error;
985
1486
/****************************************************************************
986
1487
** General handler functions
1800
2302
temporary= get_error_message(error, &str);
1801
2303
if (!str.is_empty())
1803
const char* engine_name= table_type();
1805
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(),
1808
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine_name);
2305
const char* engine= table_type();
2307
my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
2309
my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
1812
my_error(ER_GET_ERRNO,errflag,error);
2312
my_error(ER_GET_ERRNO,errflag,error);
2338
2844
** Some general functions that isn't in the handler class
2339
2845
****************************************************************************/
2848
Initiates table-file and calls appropriate database-creator.
2855
int ha_create_table(Session *session, const char *path,
2856
const char *db, const char *table_name,
2857
HA_CREATE_INFO *create_info,
2858
bool update_create_info)
2862
char name_buff[FN_REFLEN];
2866
init_tmp_table_share(session, &share, db, 0, table_name, path);
2867
if (open_table_def(session, &share, 0) ||
2868
open_table_from_share(session, &share, "", 0, (uint) READ_ALL, 0, &table,
2872
if (update_create_info)
2873
table.updateCreateInfo(create_info);
2875
name= check_lowercase_names(table.file, share.path.str, name_buff);
2877
error= table.file->ha_create(name, &table, create_info);
2878
closefrm(&table, 0);
2881
strxmov(name_buff, db, ".", table_name, NULL);
2882
my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name_buff, error);
2885
free_table_share(&share);
2890
Try to discover table from engine.
2893
If found, write the frm file to disk.
2896
-1 Table did not exists
2900
> 0 Error, table existed but could not be created
2902
int ha_create_table_from_engine(Session* session, const char *db, const char *name)
2905
unsigned char *frmblob;
2907
char path[FN_REFLEN];
2908
HA_CREATE_INFO create_info;
2912
memset(&create_info, 0, sizeof(create_info));
2913
if ((error= ha_discover(session, db, name, &frmblob, &frmlen)))
2915
/* Table could not be discovered and thus not created */
2920
Table exists in handler and could be discovered
2921
frmblob and frmlen are set, write the frm to disk
2924
build_table_filename(path, FN_REFLEN-1, db, name, "", 0);
2925
// Save the frm file
2926
error= writefrm(path, frmblob, frmlen);
2931
init_tmp_table_share(session, &share, db, 0, name, path);
2932
if (open_table_def(session, &share, 0))
2936
if (open_table_from_share(session, &share, "" ,0, 0, 0, &table, OTM_OPEN))
2938
free_table_share(&share);
2942
table.updateCreateInfo(&create_info);
2943
create_info.table_options|= HA_OPTION_CREATE_FROM_ENGINE;
2945
check_lowercase_names(table.file, path, path);
2946
error=table.file->ha_create(path, &table, &create_info);
2947
closefrm(&table, 1);
2342
2952
void st_ha_check_opt::init()
2954
flags= sql_flags= 0;
2955
sort_buffer_size = current_session->variables.myisam_sort_buff_size;
3050
Try to discover one table from handler(s).
3053
-1 Table did not exists
3055
0 OK. In this case *frmblob and *frmlen are set
3057
>0 error. frmblob and frmlen may not be set
3059
struct st_discover_args
3063
unsigned char **frmblob;
3067
static bool discover_handlerton(Session *session, plugin_ref plugin,
3070
st_discover_args *vargs= (st_discover_args *)arg;
3071
handlerton *hton= plugin_data(plugin, handlerton *);
3072
if (hton->state == SHOW_OPTION_YES && hton->discover &&
3073
(!(hton->discover(hton, session, vargs->db, vargs->name,
3081
int ha_discover(Session *session, const char *db, const char *name,
3082
unsigned char **frmblob, size_t *frmlen)
3084
int error= -1; // Table does not exist in any handler
3085
st_discover_args args= {db, name, frmblob, frmlen};
3087
if (is_prefix(name, TMP_FILE_PREFIX)) /* skip temporary tables */
3090
if (plugin_foreach(session, discover_handlerton,
3091
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args))
3095
status_var_increment(session->status_var.ha_discover_count);
3101
Call this function in order to give the handler the possiblity
3102
to ask engine if there are any new tables that should be written to disk
3103
or any dropped tables that need to be removed from disk
3105
struct st_find_files_args
3111
List<LEX_STRING> *files;
3115
Ask handler if the table exists in engine.
3117
HA_ERR_NO_SUCH_TABLE Table does not exist
3119
HA_ERR_TABLE_EXIST Table exists
3123
struct st_table_exists_in_engine_args
3130
static bool table_exists_in_engine_handlerton(Session *session, plugin_ref plugin,
3133
st_table_exists_in_engine_args *vargs= (st_table_exists_in_engine_args *)arg;
3134
handlerton *hton= plugin_data(plugin, handlerton *);
3136
int err= HA_ERR_NO_SUCH_TABLE;
3138
if (hton->state == SHOW_OPTION_YES && hton->table_exists_in_engine)
3139
err = hton->table_exists_in_engine(hton, session, vargs->db, vargs->name);
3142
if (vargs->err == HA_ERR_TABLE_EXIST)
3148
int ha_table_exists_in_engine(Session* session, const char* db, const char* name)
3150
st_table_exists_in_engine_args args= {db, name, HA_ERR_NO_SUCH_TABLE};
3151
plugin_foreach(session, table_exists_in_engine_handlerton,
3152
DRIZZLE_STORAGE_ENGINE_PLUGIN, &args);
2440
3157
Calculate cost of 'index only' scan for given index and number of records
2442
3159
@param keynr Index number
4172
Returns a list of all known extensions.
4174
No mutexes, worst case race is a minor surplus memory allocation
4175
We have to recreate the extension map if mysqld is restarted (for example
4179
pointer pointer to TYPELIB structure
4181
static bool exts_handlerton(Session *unused __attribute__((unused)),
4185
List<char> *found_exts= (List<char> *) arg;
4186
handlerton *hton= plugin_data(plugin, handlerton *);
4188
if (hton->state == SHOW_OPTION_YES && hton->create &&
4189
(file= hton->create(hton, (TABLE_SHARE*) 0, current_session->mem_root)))
4191
List_iterator_fast<char> it(*found_exts);
4192
const char **ext, *old_ext;
4194
for (ext= file->bas_ext(); *ext; ext++)
4196
while ((old_ext= it++))
4198
if (!strcmp(old_ext, *ext))
4202
found_exts->push_back((char *) *ext);
4211
TYPELIB *ha_known_exts(void)
4213
if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
4215
List<char> found_exts;
4216
const char **ext, *old_ext;
4218
known_extensions_id= mysys_usage_id;
4220
plugin_foreach(NULL, exts_handlerton,
4221
DRIZZLE_STORAGE_ENGINE_PLUGIN, &found_exts);
4223
ext= (const char **) my_once_alloc(sizeof(char *)*
4224
(found_exts.elements+1),
4225
MYF(MY_WME | MY_FAE));
4228
known_extensions.count= found_exts.elements;
4229
known_extensions.type_names= ext;
4231
List_iterator_fast<char> it(found_exts);
4232
while ((old_ext= it++))
4236
return &known_extensions;
3452
4240
static bool stat_print(Session *session, const char *type, uint32_t type_len,
3453
4241
const char *file, uint32_t file_len,
3454
4242
const char *status, uint32_t status_len)
3497
4286
- table is not mysql.event
3500
static bool binlog_log_row(Table* table,
3501
const unsigned char *before_record,
3502
const unsigned char *after_record)
4289
static bool check_table_binlog_row_based(Session *session, Table *table)
4291
if (table->s->cached_row_logging_check == -1)
4293
int const check(table->s->tmp_table == NO_TMP_TABLE);
4294
table->s->cached_row_logging_check= check;
4297
assert(table->s->cached_row_logging_check == 0 ||
4298
table->s->cached_row_logging_check == 1);
4300
return (table->s->cached_row_logging_check &&
4301
(session->options & OPTION_BIN_LOG) &&
4302
drizzle_bin_log.is_open());
4307
Write table maps for all (manually or automatically) locked tables
4310
This function will generate and write table maps for all tables
4311
that are locked by the thread 'session'. Either manually locked
4312
(stored in Session::locked_tables) and automatically locked (stored
4313
in Session::lock) are considered.
4315
@param session Pointer to Session structure
4318
@retval 1 Failed to write all table maps
4322
Session::locked_tables
4325
static int write_locked_table_maps(Session *session)
4327
if (session->get_binlog_table_maps() == 0)
4329
DRIZZLE_LOCK *locks[3];
4330
locks[0]= session->extra_lock;
4331
locks[1]= session->lock;
4332
locks[2]= session->locked_tables;
4333
for (uint32_t i= 0 ; i < sizeof(locks)/sizeof(*locks) ; ++i )
4335
DRIZZLE_LOCK const *const lock= locks[i];
4339
Table **const end_ptr= lock->table + lock->table_count;
4340
for (Table **table_ptr= lock->table ;
4341
table_ptr != end_ptr ;
4344
Table *const table= *table_ptr;
4345
if (table->current_lock == F_WRLCK &&
4346
check_table_binlog_row_based(session, table))
4348
int const has_trans= table->file->has_transactions();
4349
int const error= session->binlog_write_table_map(table, has_trans);
4351
If an error occurs, it is the responsibility of the caller to
4352
roll back the transaction.
4354
if (unlikely(error))
4364
typedef bool Log_func(Session*, Table*, bool, const unsigned char*, const unsigned char*);
4366
static int binlog_log_row(Table* table,
4367
const unsigned char *before_record,
4368
const unsigned char *after_record,
4371
if (table->no_replicate)
3505
4375
Session *const session= table->in_use;
3507
if (table->no_replicate == false)
3510
error= replicator_session_init(session);
3512
switch (session->lex->sql_command)
4377
if (check_table_binlog_row_based(session, table))
3514
case SQLCOM_REPLACE:
3516
case SQLCOM_REPLACE_SELECT:
3517
case SQLCOM_INSERT_SELECT:
3518
case SQLCOM_CREATE_TABLE:
3519
error= replicator_write_row(session, table);
3523
case SQLCOM_UPDATE_MULTI:
3524
error= replicator_update_row(session, table, before_record, after_record);
3528
case SQLCOM_DELETE_MULTI:
3529
error= replicator_delete_row(session, table);
3533
For everything else we ignore the event (since it just involves a temp table)
4380
If there are no table maps written to the binary log, this is
4381
the first row handled in this statement. In that case, we need
4382
to write table maps for all locked tables to the binary log.
4384
if (likely(!(error= write_locked_table_maps(session))))
4386
bool const has_trans= table->file->has_transactions();
4387
error= (*log_func)(session, table, has_trans, before_record, after_record);
4391
return error ? HA_ERR_RBR_LOGGING_FAILED : 0;
3542
4394
int handler::ha_external_lock(Session *session, int lock_type)