1
/* Copyright (C) 2000-2004 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 */
17
#ifndef DRIZZLE_CLIENT
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
20
#include <drizzled/server_includes.h>
22
#include "rpl_filter.h"
23
#include "rpl_utility.h"
24
#include "rpl_record.h"
21
#include <drizzled/log_event.h>
22
#include <drizzled/replication/rli.h>
23
#include <drizzled/replication/mi.h>
24
#include <libdrizzle/libdrizzle.h>
25
#include <mysys/hash.h>
26
#include <drizzled/replication/utility.h>
27
#include <drizzled/replication/record.h>
25
28
#include <mysys/my_dir.h>
26
#include <drizzled/drizzled_error_messages.h>
29
#include <drizzled/error.h>
30
#include <libdrizzle/pack.h>
31
#include <drizzled/sql_parse.h>
32
#include <drizzled/sql_base.h>
33
#include <drizzled/sql_load.h>
34
#include <drizzled/item/return_int.h>
35
#include <drizzled/item/empty_string.h>
28
#endif /* !DRIZZLE_CLIENT */
30
40
#include <mysys/base64.h>
31
41
#include <mysys/my_bitmap.h>
33
#define log_cs &my_charset_latin1
35
#define FLAGSTR(V,F) ((V)&(F)?#F" ":"")
39
Size of buffer for printing a double in format %.<PREC>g
41
optional '-' + optional zero + '.' + PREC digits + 'e' + sign +
42
exponent digits + '\0'
44
#define FMT_G_BUFSIZE(PREC) (3 + (PREC) + 5 + 1)
47
#if !defined(DRIZZLE_CLIENT) && defined(HAVE_REPLICATION)
43
#include <drizzled/gettext.h>
44
#include <libdrizzle/libdrizzle.h>
45
#include <drizzled/error.h>
46
#include <drizzled/query_id.h>
47
#include <drizzled/tztime.h>
48
#include <drizzled/slave.h>
49
#include <drizzled/lock.h>
48
53
static const char *HA_ERR(int i)
1139
1042
if (!ev || !ev->is_valid())
1142
#ifdef DRIZZLE_CLIENT
1143
if (!force_opt) /* then mysqlbinlog dies */
1145
*error= "Found invalid event in binary log";
1148
ev= new Unknown_log_event(buf, description_event);
1150
1045
*error= "Found invalid event in binary log";
1157
#ifdef DRIZZLE_CLIENT
1160
Log_event::print_header()
1163
void Log_event::print_header(IO_CACHE* file,
1164
PRINT_EVENT_INFO* print_event_info,
1165
bool is_more __attribute__((unused)))
1168
my_off_t hexdump_from= print_event_info->hexdump_from;
1170
my_b_printf(file, "#");
1171
print_timestamp(file);
1172
my_b_printf(file, " server id %d end_log_pos %s ", server_id,
1173
llstr(log_pos,llbuff));
1175
/* mysqlbinlog --hexdump */
1176
if (print_event_info->hexdump_from)
1178
my_b_printf(file, "\n");
1179
uchar *ptr= (uchar*)temp_buf;
1181
uint4korr(ptr + EVENT_LEN_OFFSET) - LOG_EVENT_MINIMAL_HEADER_LEN;
1184
/* Header len * 4 >= header len * (2 chars + space + extra space) */
1185
char *h, hex_string[LOG_EVENT_MINIMAL_HEADER_LEN*4]= {0};
1186
char *c, char_string[16+1]= {0};
1188
/* Pretty-print event common header if header is exactly 19 bytes */
1189
if (print_event_info->common_header_len == LOG_EVENT_MINIMAL_HEADER_LEN)
1191
char emit_buf[256]; // Enough for storing one line
1192
my_b_printf(file, "# Position Timestamp Type Master ID "
1193
"Size Master Pos Flags \n");
1194
int const bytes_written=
1195
snprintf(emit_buf, sizeof(emit_buf),
1196
"# %8.8lx %02x %02x %02x %02x %02x "
1197
"%02x %02x %02x %02x %02x %02x %02x %02x "
1198
"%02x %02x %02x %02x %02x %02x\n",
1199
(unsigned long) hexdump_from,
1200
ptr[0], ptr[1], ptr[2], ptr[3], ptr[4], ptr[5], ptr[6],
1201
ptr[7], ptr[8], ptr[9], ptr[10], ptr[11], ptr[12], ptr[13],
1202
ptr[14], ptr[15], ptr[16], ptr[17], ptr[18]);
1203
assert(bytes_written >= 0);
1204
assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1205
my_b_write(file, (uchar*) emit_buf, bytes_written);
1206
ptr += LOG_EVENT_MINIMAL_HEADER_LEN;
1207
hexdump_from += LOG_EVENT_MINIMAL_HEADER_LEN;
1210
/* Rest of event (without common header) */
1211
for (i= 0, c= char_string, h=hex_string;
1215
snprintf(h, 4, "%02x ", *ptr);
1218
*c++= my_isalnum(&my_charset_bin, *ptr) ? *ptr : '.';
1223
my_b_printf() does not support full printf() formats, so we
1224
have to do it this way.
1226
TODO: Rewrite my_b_printf() to support full printf() syntax.
1229
int const bytes_written=
1230
snprintf(emit_buf, sizeof(emit_buf),
1231
"# %8.8lx %-48.48s |%16s|\n",
1232
(unsigned long) (hexdump_from + (i & 0xfffffff0)),
1233
hex_string, char_string);
1234
assert(bytes_written >= 0);
1235
assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1236
my_b_write(file, (uchar*) emit_buf, bytes_written);
1242
else if (i % 8 == 7) *h++ = ' ';
1249
int const bytes_written=
1250
snprintf(emit_buf, sizeof(emit_buf),
1251
"# %8.8lx %-48.48s |%s|\n",
1252
(unsigned long) (hexdump_from + (i & 0xfffffff0)),
1253
hex_string, char_string);
1254
assert(bytes_written >= 0);
1255
assert(static_cast<size_t>(bytes_written) < sizeof(emit_buf));
1256
my_b_write(file, (uchar*) emit_buf, bytes_written);
1259
need a # to prefix the rest of printouts for example those of
1260
Rows_log_event::print_helper().
1262
my_b_write(file, reinterpret_cast<const uchar*>("# "), 2);
1268
void Log_event::print_base64(IO_CACHE* file,
1269
PRINT_EVENT_INFO* print_event_info,
1272
const uchar *ptr= (const uchar *)temp_buf;
1273
uint32_t size= uint4korr(ptr + EVENT_LEN_OFFSET);
1275
size_t const tmp_str_sz= base64_needed_encoded_length((int) size);
1276
char *const tmp_str= (char *) my_malloc(tmp_str_sz, MYF(MY_WME));
1278
fprintf(stderr, "\nError: Out of memory. "
1279
"Could not print correct binlog event.\n");
1283
if (base64_encode(ptr, (size_t) size, tmp_str))
1288
if (my_b_tell(file) == 0)
1289
my_b_printf(file, "\nBINLOG '\n");
1291
my_b_printf(file, "%s\n", tmp_str);
1294
my_b_printf(file, "'%s\n", print_event_info->delimiter);
1296
my_free(tmp_str, MYF(0));
1302
Log_event::print_timestamp()
1305
void Log_event::print_timestamp(IO_CACHE* file, time_t* ts)
1310
#ifdef DRIZZLE_SERVER // This is always false
1312
localtime_r(ts,(res= &tm_tmp));
1317
my_b_printf(file,"%02d%02d%02d %2d:%02d:%02d",
1327
#endif /* DRIZZLE_CLIENT */
1330
#if !defined(DRIZZLE_CLIENT) && defined(HAVE_REPLICATION)
1331
1051
inline Log_event::enum_skip_reason
1332
1052
Log_event::continue_group(Relay_log_info *rli)
1588
1238
Query_log_event::Query_log_event()
1589
thd_arg - thread handle
1239
session_arg - thread handle
1590
1240
query_arg - array of char representing the query
1591
1241
query_length - size of the `query_arg' array
1592
1242
using_trans - there is a modified transactional table
1593
1243
suppress_use - suppress the generation of 'USE' statements
1594
killed_status_arg - an optional with default to THD::KILLED_NO_VALUE
1244
killed_status_arg - an optional with default to Session::KILLED_NO_VALUE
1595
1245
if the value is different from the default, the arg
1596
is set to the current thd->killed value.
1597
A caller might need to masquerade thd->killed with
1246
is set to the current session->killed value.
1247
A caller might need to masquerade session->killed with
1248
Session::NOT_KILLED.
1600
1250
Creates an event for binlogging
1601
1251
The value for local `killed_status' can be supplied by caller.
1603
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
1604
ulong query_length, bool using_trans,
1606
THD::killed_state killed_status_arg)
1608
(thd_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F :
1610
(suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0),
1612
data_buf(0), query(query_arg), catalog(thd_arg->catalog),
1613
db(thd_arg->db), q_len((uint32_t) query_length),
1614
thread_id(thd_arg->thread_id),
1615
/* save the original thread id; we already know the server id */
1616
slave_proxy_id(thd_arg->variables.pseudo_thread_id),
1617
flags2_inited(1), sql_mode_inited(1), charset_inited(1),
1619
auto_increment_increment(thd_arg->variables.auto_increment_increment),
1620
auto_increment_offset(thd_arg->variables.auto_increment_offset),
1621
lc_time_names_number(thd_arg->variables.lc_time_names->number),
1253
Query_log_event::Query_log_event(Session* session_arg, const char* query_arg,
1254
ulong query_length, bool using_trans,
1256
Session::killed_state killed_status_arg)
1257
:Log_event(session_arg,
1258
(session_arg->thread_specific_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0) |
1259
(suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0),
1261
data_buf(0), query(query_arg), catalog(session_arg->catalog),
1262
db(session_arg->db), q_len((uint32_t) query_length),
1263
thread_id(session_arg->thread_id),
1264
/* save the original thread id; we already know the server id */
1265
slave_proxy_id(session_arg->variables.pseudo_thread_id),
1266
flags2_inited(1), sql_mode_inited(1), charset_inited(1),
1268
auto_increment_increment(session_arg->variables.auto_increment_increment),
1269
auto_increment_offset(session_arg->variables.auto_increment_offset),
1270
lc_time_names_number(session_arg->variables.lc_time_names->number),
1622
1271
charset_database_number(0)
1624
1273
time_t end_time;
1626
if (killed_status_arg == THD::KILLED_NO_VALUE)
1627
killed_status_arg= thd_arg->killed;
1275
if (killed_status_arg == Session::KILLED_NO_VALUE)
1276
killed_status_arg= session_arg->killed;
1630
(killed_status_arg == THD::NOT_KILLED) ?
1631
(thd_arg->is_error() ? thd_arg->main_da.sql_errno() : 0) :
1632
(thd_arg->killed_errno());
1279
(killed_status_arg == Session::NOT_KILLED) ?
1280
(session_arg->is_error() ? session_arg->main_da.sql_errno() : 0) :
1281
(session_arg->killed_errno());
1634
1283
time(&end_time);
1635
exec_time = (ulong) (end_time - thd_arg->start_time);
1284
exec_time = (ulong) (end_time - session_arg->start_time);
1637
1286
@todo this means that if we have no catalog, then it is replicated
1638
1287
as an existing catalog of length zero. is that safe? /sven
1640
1289
catalog_len = (catalog) ? (uint32_t) strlen(catalog) : 0;
1641
1290
/* status_vars_len is set just before writing the event */
1642
1291
db_len = (db) ? (uint32_t) strlen(db) : 0;
1643
if (thd_arg->variables.collation_database != thd_arg->db_charset)
1644
charset_database_number= thd_arg->variables.collation_database->number;
1292
if (session_arg->variables.collation_database != session_arg->db_charset)
1293
charset_database_number= session_arg->variables.collation_database->number;
1647
1296
If we don't use flags2 for anything else than options contained in
1648
thd_arg->options, it would be more efficient to flags2=thd_arg->options
1297
session_arg->options, it would be more efficient to flags2=session_arg->options
1649
1298
(OPTIONS_WRITTEN_TO_BIN_LOG would be used only at reading time).
1650
1299
But it's likely that we don't want to use 32 bits for 3 bits; in the future
1651
1300
we will probably want to reclaim the 29 bits. So we need the &.
1653
flags2= (uint32_t) (thd_arg->options & OPTIONS_WRITTEN_TO_BIN_LOG);
1654
assert(thd_arg->variables.character_set_client->number < 256*256);
1655
assert(thd_arg->variables.collation_connection->number < 256*256);
1656
assert(thd_arg->variables.collation_server->number < 256*256);
1657
assert(thd_arg->variables.character_set_client->mbminlen == 1);
1658
int2store(charset, thd_arg->variables.character_set_client->number);
1659
int2store(charset+2, thd_arg->variables.collation_connection->number);
1660
int2store(charset+4, thd_arg->variables.collation_server->number);
1661
if (thd_arg->time_zone_used)
1664
Note that our event becomes dependent on the Time_zone object
1665
representing the time zone. Fortunately such objects are never deleted
1666
or changed during mysqld's lifetime.
1668
time_zone_len= thd_arg->variables.time_zone->get_name()->length();
1669
time_zone_str= thd_arg->variables.time_zone->get_name()->ptr();
1674
#endif /* DRIZZLE_CLIENT */
1677
/* 2 utility functions for the next method */
1680
Read a string with length from memory.
1682
This function reads the string-with-length stored at
1683
<code>src</code> and extract the length into <code>*len</code> and
1684
a pointer to the start of the string into <code>*dst</code>. The
1685
string can then be copied using <code>memcpy()</code> with the
1686
number of bytes given in <code>*len</code>.
1688
@param src Pointer to variable holding a pointer to the memory to
1689
read the string from.
1690
@param dst Pointer to variable holding a pointer where the actual
1691
string starts. Starting from this position, the string
1692
can be copied using @c memcpy().
1693
@param len Pointer to variable where the length will be stored.
1694
@param end One-past-the-end of the memory where the string is
1697
@return Zero if the entire string can be copied successfully,
1698
@c UINT_MAX if the length could not be read from memory
1699
(that is, if <code>*src >= end</code>), otherwise the
1700
number of bytes that are missing to read the full
1701
string, which happends <code>*dst + *len >= end</code>.
1704
get_str_len_and_pointer(const Log_event::Byte **src,
1707
const Log_event::Byte *end)
1710
return -1; // Will be UINT_MAX in two-complement arithmetics
1714
if (*src + length >= end)
1715
return *src + length - end + 1; // Number of bytes missing
1716
*dst= (char *)*src + 1; // Will be copied later
1723
static void copy_str_and_move(const char **src,
1724
Log_event::Byte **dst,
1302
flags2= (uint32_t) (session_arg->options & OPTIONS_WRITTEN_TO_BIN_LOG);
1303
assert(session_arg->variables.collation_server->number < 256*256);
1304
int2store(charset+4, session_arg->variables.collation_server->number);
1308
static void copy_str_and_move(const char **src,
1309
Log_event::Byte **dst,
1727
1312
memcpy(*dst, *src, len);
1728
1313
*src= (const char *)*dst;
1934
#ifdef DRIZZLE_CLIENT
1936
Query_log_event::print().
1939
print the catalog ??
1941
void Query_log_event::print_query_header(IO_CACHE* file,
1942
PRINT_EVENT_INFO* print_event_info)
1944
// TODO: print the catalog ??
1945
char buff[40],*end; // Enough for SET TIMESTAMP
1946
bool different_db= 1;
1949
if (!print_event_info->short_form)
1951
print_header(file, print_event_info, false);
1952
my_b_printf(file, "\t%s\tthread_id=%lu\texec_time=%lu\terror_code=%d\n",
1953
get_type_str(), (ulong) thread_id, (ulong) exec_time,
1957
if (!(flags & LOG_EVENT_SUPPRESS_USE_F) && db)
1959
if ((different_db= memcmp(print_event_info->db, db, db_len + 1)))
1960
memcpy(print_event_info->db, db, db_len + 1);
1961
if (db[0] && different_db)
1962
my_b_printf(file, "use %s%s\n", db, print_event_info->delimiter);
1965
end=int10_to_str((long) when, stpcpy(buff,"SET TIMESTAMP="),10);
1966
end= stpcpy(end, print_event_info->delimiter);
1968
my_b_write(file, (uchar*) buff, (uint) (end-buff));
1969
if ((!print_event_info->thread_id_printed ||
1970
((flags & LOG_EVENT_THREAD_SPECIFIC_F) &&
1971
thread_id != print_event_info->thread_id)))
1973
// If --short-form, print deterministic value instead of pseudo_thread_id.
1974
my_b_printf(file,"SET @@session.pseudo_thread_id=%lu%s\n",
1975
short_form ? 999999999 : (ulong)thread_id,
1976
print_event_info->delimiter);
1977
print_event_info->thread_id= thread_id;
1978
print_event_info->thread_id_printed= 1;
1982
If flags2_inited==0, this is an event from 3.23 or 4.0; nothing to
1983
print (remember we don't produce mixed relay logs so there cannot be
1984
5.0 events before that one so there is nothing to reset).
1986
if (likely(flags2_inited)) /* likely as this will mainly read 5.0 logs */
1988
/* tmp is a bitmask of bits which have changed. */
1989
if (likely(print_event_info->flags2_inited))
1990
/* All bits which have changed */
1991
tmp= (print_event_info->flags2) ^ flags2;
1992
else /* that's the first Query event we read */
1994
print_event_info->flags2_inited= 1;
1995
tmp= ~((uint32_t)0); /* all bits have changed */
1998
if (unlikely(tmp)) /* some bits have changed */
2001
my_b_printf(file, "SET ");
2002
print_set_option(file, tmp, OPTION_NO_FOREIGN_KEY_CHECKS, ~flags2,
2003
"@@session.foreign_key_checks", &need_comma);
2004
print_set_option(file, tmp, OPTION_AUTO_IS_NULL, flags2,
2005
"@@session.sql_auto_is_null", &need_comma);
2006
print_set_option(file, tmp, OPTION_RELAXED_UNIQUE_CHECKS, ~flags2,
2007
"@@session.unique_checks", &need_comma);
2008
my_b_printf(file,"%s\n", print_event_info->delimiter);
2009
print_event_info->flags2= flags2;
2014
Now the session variables;
2015
it's more efficient to pass SQL_MODE as a number instead of a
2016
comma-separated list.
2017
FOREIGN_KEY_CHECKS, SQL_AUTO_IS_NULL, UNIQUE_CHECKS are session-only
2018
variables (they have no global version; they're not listed in
2019
sql_class.h), The tests below work for pure binlogs or pure relay
2020
logs. Won't work for mixed relay logs but we don't create mixed
2021
relay logs (that is, there is no relay log with a format change
2022
except within the 3 first events, which mysqlbinlog handles
2023
gracefully). So this code should always be good.
2026
if (print_event_info->auto_increment_increment != auto_increment_increment ||
2027
print_event_info->auto_increment_offset != auto_increment_offset)
2029
my_b_printf(file,"SET @@session.auto_increment_increment=%lu, @@session.auto_increment_offset=%lu%s\n",
2030
auto_increment_increment,auto_increment_offset,
2031
print_event_info->delimiter);
2032
print_event_info->auto_increment_increment= auto_increment_increment;
2033
print_event_info->auto_increment_offset= auto_increment_offset;
2036
/* TODO: print the catalog when we feature SET CATALOG */
2038
if (likely(charset_inited) &&
2039
(unlikely(!print_event_info->charset_inited ||
2040
memcmp(print_event_info->charset, charset, 6))))
2042
const CHARSET_INFO * const cs_info= get_charset(uint2korr(charset), MYF(MY_WME));
2045
/* for mysql client */
2046
my_b_printf(file, "/*!\\C %s */%s\n",
2047
cs_info->csname, print_event_info->delimiter);
2049
my_b_printf(file,"SET "
2050
"@@session.character_set_client=%d,"
2051
"@@session.collation_connection=%d,"
2052
"@@session.collation_server=%d"
2055
uint2korr(charset+2),
2056
uint2korr(charset+4),
2057
print_event_info->delimiter);
2058
memcpy(print_event_info->charset, charset, 6);
2059
print_event_info->charset_inited= 1;
2063
if (memcmp(print_event_info->time_zone_str, time_zone_str, time_zone_len+1))
2065
my_b_printf(file,"SET @@session.time_zone='%s'%s\n",
2066
time_zone_str, print_event_info->delimiter);
2067
memcpy(print_event_info->time_zone_str, time_zone_str, time_zone_len+1);
2070
if (lc_time_names_number != print_event_info->lc_time_names_number)
2072
my_b_printf(file, "SET @@session.lc_time_names=%d%s\n",
2073
lc_time_names_number, print_event_info->delimiter);
2074
print_event_info->lc_time_names_number= lc_time_names_number;
2076
if (charset_database_number != print_event_info->charset_database_number)
2078
if (charset_database_number)
2079
my_b_printf(file, "SET @@session.collation_database=%d%s\n",
2080
charset_database_number, print_event_info->delimiter);
2082
my_b_printf(file, "SET @@session.collation_database=DEFAULT%s\n",
2083
print_event_info->delimiter);
2084
print_event_info->charset_database_number= charset_database_number;
2089
void Query_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
2091
Write_on_release_cache cache(&print_event_info->head_cache, file);
2093
print_query_header(&cache, print_event_info);
2094
my_b_write(&cache, (uchar*) query, q_len);
2095
my_b_printf(&cache, "\n%s\n", print_event_info->delimiter);
2097
#endif /* DRIZZLE_CLIENT */
2101
1473
Query_log_event::do_apply_event()
2104
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
2106
1475
int Query_log_event::do_apply_event(Relay_log_info const *rli)
2108
1477
return do_apply_event(rli, query, q_len);
2170
1537
::do_apply_event(), then the companion SET also have so
2171
1538
we don't need to reset_one_shot_variables().
2173
if (rpl_filter->db_ok(thd->db))
2175
thd->set_time((time_t)when);
2176
thd->query_length= q_len_arg;
2177
thd->query= (char*)query_arg;
2178
VOID(pthread_mutex_lock(&LOCK_thread_count));
2179
thd->query_id = next_query_id();
2180
VOID(pthread_mutex_unlock(&LOCK_thread_count));
2181
thd->variables.pseudo_thread_id= thread_id; // for temp tables
1542
session->set_time((time_t)when);
1543
session->query_length= q_len_arg;
1544
session->query= (char*)query_arg;
1545
session->query_id= query_id.next();
1546
session->variables.pseudo_thread_id= thread_id; // for temp tables
2183
1548
if (ignored_error_code((expected_error= error_code)) ||
2184
!check_expected_error(thd,rli,expected_error))
1549
!check_expected_error(session,rli,expected_error))
2186
1551
if (flags2_inited)
2188
all bits of thd->options which are 1 in OPTIONS_WRITTEN_TO_BIN_LOG
1553
all bits of session->options which are 1 in OPTIONS_WRITTEN_TO_BIN_LOG
2189
1554
must take their value from flags2.
2191
thd->options= flags2|(thd->options & ~OPTIONS_WRITTEN_TO_BIN_LOG);
2193
else, we are in a 3.23/4.0 binlog; we previously received a
2194
Rotate_log_event which reset thd->options and sql_mode etc, so
2199
if (rli->cached_charset_compare(charset))
2201
/* Verify that we support the charsets found in the event. */
2202
if (!(thd->variables.character_set_client=
2203
get_charset(uint2korr(charset), MYF(MY_WME))) ||
2204
!(thd->variables.collation_connection=
2205
get_charset(uint2korr(charset+2), MYF(MY_WME))) ||
2206
!(thd->variables.collation_server=
2207
get_charset(uint2korr(charset+4), MYF(MY_WME))))
2210
We updated the thd->variables with nonsensical values (0). Let's
2211
set them to something safe (i.e. which avoids crash), and we'll
2212
stop with EE_UNKNOWN_CHARSET in compare_errors (unless set to
2215
set_slave_thread_default_charset(thd, rli);
2216
goto compare_errors;
2218
thd->update_charset(); // for the charset change to take effect
1556
session->options= flags2|(session->options & ~OPTIONS_WRITTEN_TO_BIN_LOG);
2221
1557
if (time_zone_len)
2223
1559
String tmp(time_zone_str, time_zone_len, &my_charset_bin);
2224
if (!(thd->variables.time_zone= my_tz_find(thd, &tmp)))
1560
if (!(session->variables.time_zone= my_tz_find(session, &tmp)))
2226
1562
my_error(ER_UNKNOWN_TIME_ZONE, MYF(0), tmp.c_ptr());
2227
thd->variables.time_zone= global_system_variables.time_zone;
1563
session->variables.time_zone= global_system_variables.time_zone;
2228
1564
goto compare_errors;
2231
1567
if (lc_time_names_number)
2233
if (!(thd->variables.lc_time_names=
1569
if (!(session->variables.lc_time_names=
2234
1570
my_locale_by_number(lc_time_names_number)))
2236
1572
my_printf_error(ER_UNKNOWN_ERROR,
2237
1573
"Unknown locale: '%d'", MYF(0), lc_time_names_number);
2238
thd->variables.lc_time_names= &my_locale_en_US;
1574
session->variables.lc_time_names= &my_locale_en_US;
2239
1575
goto compare_errors;
2243
thd->variables.lc_time_names= &my_locale_en_US;
1579
session->variables.lc_time_names= &my_locale_en_US;
2244
1580
if (charset_database_number)
2246
1582
const CHARSET_INFO *cs;
2270
1606
we exit gracefully; otherwise we warn about the bad error and tell DBA
2271
1607
to check/fix it.
2273
if (mysql_test_parse_for_slave(thd, thd->query, thd->query_length))
2274
clear_all_errors(thd, const_cast<Relay_log_info*>(rli)); /* Can ignore query */
1609
if (mysql_test_parse_for_slave(session, session->query, session->query_length))
1610
clear_all_errors(session, const_cast<Relay_log_info*>(rli)); /* Can ignore query */
2277
rli->report(ERROR_LEVEL, expected_error,
2279
Query partially completed on the master (error on master: %d) \
2280
and was aborted. There is a chance that your master is inconsistent at this \
2281
point. If you are sure that your master is ok, run this query manually on the \
2282
slave and then restart the slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; \
2283
START SLAVE; . Query: '%s'", expected_error, thd->query);
2284
thd->is_slave_error= 1;
1613
rli->report(ERROR_LEVEL, expected_error,
1614
_("Query partially completed on the master "
1615
"(error on master: %d) and was aborted. There is a "
1616
"chance that your master is inconsistent at this "
1617
"point. If you are sure that your master is ok, run "
1618
"this query manually on the slave and then restart the "
1619
"slave with SET GLOBAL SQL_SLAVE_SKIP_COUNTER=1; "
1620
"START SLAVE; . Query: '%s'"),
1621
expected_error, session->query);
1622
session->is_slave_error= 1;
2289
/* If the query was not ignored, it is printed to the general log */
2290
if (!thd->is_error() || thd->main_da.sql_errno() != ER_SLAVE_IGNORED_TABLE)
2291
general_log_write(thd, COM_QUERY, thd->query, thd->query_length);
2293
1627
compare_errors:
2296
1630
If we expected a non-zero error code, and we don't get the same error
2297
1631
code, and none of them should be ignored.
2299
actual_error= thd->is_error() ? thd->main_da.sql_errno() : 0;
1633
actual_error= session->is_error() ? session->main_da.sql_errno() : 0;
2300
1634
if ((expected_error != actual_error) &&
2302
!ignored_error_code(actual_error) &&
2303
!ignored_error_code(expected_error))
1636
!ignored_error_code(actual_error) &&
1637
!ignored_error_code(expected_error))
2305
1639
rli->report(ERROR_LEVEL, 0,
2307
Query caused different errors on master and slave. \
2308
Error on master: '%s' (%d), Error on slave: '%s' (%d). \
2309
Default database: '%s'. Query: '%s'",
2310
ER_SAFE(expected_error),
2312
actual_error ? thd->main_da.message() : "no error",
2314
print_slave_db_safe(db), query_arg);
2315
thd->is_slave_error= 1;
1640
_("Query caused differenxt errors on master and slave.\n"
1641
"Error on master: '%s' (%d), Error on slave: '%s' (%d).\n"
1642
"Default database: '%s'. Query: '%s'"),
1645
actual_error ? session->main_da.message() : _("no error"),
1647
print_slave_db_safe(db), query_arg);
1648
session->is_slave_error= 1;
2318
If we get the same error code as expected, or they should be ignored.
1651
If we get the same error code as expected, or they should be ignored.
2320
1653
else if (expected_error == actual_error ||
2321
1654
ignored_error_code(actual_error))
2323
clear_all_errors(thd, const_cast<Relay_log_info*>(rli));
2324
thd->killed= THD::NOT_KILLED;
1656
clear_all_errors(session, const_cast<Relay_log_info*>(rli));
1657
session->killed= Session::NOT_KILLED;
2327
1660
Other cases: mostly we expected no error and get one.
2329
else if (thd->is_slave_error || thd->is_fatal_error)
1662
else if (session->is_slave_error || session->is_fatal_error)
2331
1664
rli->report(ERROR_LEVEL, actual_error,
2332
"Error '%s' on query. Default database: '%s'. Query: '%s'",
2333
(actual_error ? thd->main_da.message() :
2334
"unexpected success or fatal error"),
2335
print_slave_db_safe(thd->db), query_arg);
2336
thd->is_slave_error= 1;
1665
_("Error '%s' on query. Default database: '%s'. Query: '%s'"),
1666
(actual_error ? session->main_da.message() :
1667
_("unexpected success or fatal error")),
1668
print_slave_db_safe(session->db), query_arg);
1669
session->is_slave_error= 1;
2418
1731
if (strcmp("BEGIN", query) == 0)
2420
thd->options|= OPTION_BEGIN;
1733
session->options|= OPTION_BEGIN;
2421
1734
return(Log_event::continue_group(rli));
2424
1737
if (strcmp("COMMIT", query) == 0 || strcmp("ROLLBACK", query) == 0)
2426
thd->options&= ~OPTION_BEGIN;
1739
session->options&= ~OPTION_BEGIN;
2427
1740
return(Log_event::EVENT_SKIP_COUNT);
2430
1743
return(Log_event::do_shall_skip(rli));
2436
1747
/**************************************************************************
2437
1748
Start_log_event_v3 methods
2438
1749
**************************************************************************/
2440
#ifndef DRIZZLE_CLIENT
2441
1751
Start_log_event_v3::Start_log_event_v3()
2442
1752
:Log_event(), created(0), binlog_version(BINLOG_VERSION),
2443
1753
artificial_event(0), dont_set_created(0)
2445
1755
memcpy(server_version, ::server_version, ST_SERVER_VER_LEN);
2450
1759
Start_log_event_v3::pack_info()
2453
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
2454
1762
void Start_log_event_v3::pack_info(Protocol *protocol)
2456
1764
char buf[12 + ST_SERVER_VER_LEN + 14 + 22], *pos;
2457
pos= stpcpy(buf, "Server ver: ");
2458
pos= stpcpy(pos, server_version);
2459
pos= stpcpy(pos, ", Binlog ver: ");
1765
pos= strcpy(buf, "Server ver: ")+12;
1766
pos= strcpy(pos, server_version)+strlen(server_version);
1767
pos= strcpy(pos, ", Binlog ver: ")+14;
2460
1768
pos= int10_to_str(binlog_version, pos, 10);
2461
1769
protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
2467
Start_log_event_v3::print()
2470
#ifdef DRIZZLE_CLIENT
2471
void Start_log_event_v3::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
2473
Write_on_release_cache cache(&print_event_info->head_cache, file,
2474
Write_on_release_cache::FLUSH_F);
2476
if (!print_event_info->short_form)
2478
print_header(&cache, print_event_info, false);
2479
my_b_printf(&cache, "\tStart: binlog v %d, server v %s created ",
2480
binlog_version, server_version);
2481
print_timestamp(&cache);
2483
my_b_printf(&cache," at startup");
2484
my_b_printf(&cache, "\n");
2485
if (flags & LOG_EVENT_BINLOG_IN_USE_F)
2486
my_b_printf(&cache, "# Warning: this binlog was not closed properly. "
2487
"Most probably mysqld crashed writing it.\n");
2489
if (!artificial_event && created)
2491
#ifdef WHEN_WE_HAVE_THE_RESET_CONNECTION_SQL_COMMAND
2493
This is for mysqlbinlog: like in replication, we want to delete the stale
2494
tmp files left by an unclean shutdown of mysqld (temporary tables)
2495
and rollback unfinished transaction.
2496
Probably this can be done with RESET CONNECTION (syntax to be defined).
2498
my_b_printf(&cache,"RESET CONNECTION%s\n", print_event_info->delimiter);
2500
my_b_printf(&cache,"ROLLBACK%s\n", print_event_info->delimiter);
2504
print_event_info->base64_output_mode != BASE64_OUTPUT_NEVER &&
2505
!print_event_info->short_form)
2507
my_b_printf(&cache, "BINLOG '\n");
2508
print_base64(&cache, print_event_info, false);
2509
print_event_info->printed_fd_event= true;
2513
#endif /* DRIZZLE_CLIENT */
2516
1774
Start_log_event_v3::Start_log_event_v3()
3049
2254
if (need_db && db && db_len)
3051
pos= stpcpy(pos, "use `");
2256
pos= strcpy(pos, "use `")+5;
3052
2257
memcpy(pos, db, db_len);
3053
pos= stpcpy(pos+db_len, "`; ");
2258
pos= strcpy(pos+db_len, "`; ")+3;
3056
pos= stpcpy(pos, "LOAD DATA ");
2261
pos= strcpy(pos, "LOAD DATA ")+10;
3059
2264
*fn_start= pos;
3061
2266
if (check_fname_outside_temp_buf())
3062
pos= stpcpy(pos, "LOCAL ");
3063
pos= stpcpy(pos, "INFILE '");
2267
pos= strcpy(pos, "LOCAL ")+6;
2268
pos= strcpy(pos, "INFILE '")+8;
3064
2269
memcpy(pos, fname, fname_len);
3065
pos= stpcpy(pos+fname_len, "' ");
2270
pos= strcpy(pos+fname_len, "' ")+2;
3067
2272
if (sql_ex.opt_flags & REPLACE_FLAG)
3068
pos= stpcpy(pos, " REPLACE ");
2273
pos= strcpy(pos, " REPLACE ")+9;
3069
2274
else if (sql_ex.opt_flags & IGNORE_FLAG)
3070
pos= stpcpy(pos, " IGNORE ");
2275
pos= strcpy(pos, " IGNORE ")+8;
3072
pos= stpcpy(pos ,"INTO");
2277
pos= strcpy(pos ,"INTO")+4;
3077
pos= stpcpy(pos ," TABLE `");
2282
pos= strcpy(pos ," Table `")+8;
3078
2283
memcpy(pos, table_name, table_name_len);
3079
2284
pos+= table_name_len;
3081
2286
/* We have to create all optinal fields as the default is not empty */
3082
pos= stpcpy(pos, "` FIELDS TERMINATED BY ");
2287
pos= strcpy(pos, "` FIELDS TERMINATED BY ")+23;
3083
2288
pos= pretty_print_str(pos, sql_ex.field_term, sql_ex.field_term_len);
3084
2289
if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG)
3085
pos= stpcpy(pos, " OPTIONALLY ");
3086
pos= stpcpy(pos, " ENCLOSED BY ");
2290
pos= strcpy(pos, " OPTIONALLY ")+12;
2291
pos= strcpy(pos, " ENCLOSED BY ")+13;
3087
2292
pos= pretty_print_str(pos, sql_ex.enclosed, sql_ex.enclosed_len);
3089
pos= stpcpy(pos, " ESCAPED BY ");
2294
pos= strcpy(pos, " ESCAPED BY ")+12;
3090
2295
pos= pretty_print_str(pos, sql_ex.escaped, sql_ex.escaped_len);
3092
pos= stpcpy(pos, " LINES TERMINATED BY ");
2297
pos= strcpy(pos, " LINES TERMINATED BY ")+21;
3093
2298
pos= pretty_print_str(pos, sql_ex.line_term, sql_ex.line_term_len);
3094
2299
if (sql_ex.line_start_len)
3096
pos= stpcpy(pos, " STARTING BY ");
2301
pos= strcpy(pos, " STARTING BY ")+13;
3097
2302
pos= pretty_print_str(pos, sql_ex.line_start, sql_ex.line_start_len);
3100
2305
if ((long) skip_lines > 0)
3102
pos= stpcpy(pos, " IGNORE ");
2307
pos= strcpy(pos, " IGNORE ")+8;
3103
2308
pos= int64_t10_to_str((int64_t) skip_lines, pos, 10);
3104
pos= stpcpy(pos," LINES ");
2309
pos= strcpy(pos," LINES ")+7;
3107
2312
if (num_fields)
3110
2315
const char *field= fields;
3111
pos= stpcpy(pos, " (");
2316
pos= strcpy(pos, " (")+2;
3112
2317
for (i = 0; i < num_fields; i++)
3346
Load_log_event::print()
3349
#ifdef DRIZZLE_CLIENT
3350
void Load_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
3352
print(file, print_event_info, 0);
3356
void Load_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info,
3359
Write_on_release_cache cache(&print_event_info->head_cache, file_arg);
3361
if (!print_event_info->short_form)
3363
print_header(&cache, print_event_info, false);
3364
my_b_printf(&cache, "\tQuery\tthread_id=%ld\texec_time=%ld\n",
3365
thread_id, exec_time);
3368
bool different_db= 1;
3372
If the database is different from the one of the previous statement, we
3373
need to print the "use" command, and we update the last_db.
3374
But if commented, the "use" is going to be commented so we should not
3377
if ((different_db= memcmp(print_event_info->db, db, db_len + 1)) &&
3379
memcpy(print_event_info->db, db, db_len + 1);
3382
if (db && db[0] && different_db)
3383
my_b_printf(&cache, "%suse %s%s\n",
3384
commented ? "# " : "",
3385
db, print_event_info->delimiter);
3387
if (flags & LOG_EVENT_THREAD_SPECIFIC_F)
3388
my_b_printf(&cache,"%sSET @@session.pseudo_thread_id=%lu%s\n",
3389
commented ? "# " : "", (ulong)thread_id,
3390
print_event_info->delimiter);
3391
my_b_printf(&cache, "%sLOAD DATA ",
3392
commented ? "# " : "");
3393
if (check_fname_outside_temp_buf())
3394
my_b_printf(&cache, "LOCAL ");
3395
my_b_printf(&cache, "INFILE '%-*s' ", fname_len, fname);
3397
if (sql_ex.opt_flags & REPLACE_FLAG)
3398
my_b_printf(&cache," REPLACE ");
3399
else if (sql_ex.opt_flags & IGNORE_FLAG)
3400
my_b_printf(&cache," IGNORE ");
3402
my_b_printf(&cache, "INTO TABLE `%s`", table_name);
3403
my_b_printf(&cache, " FIELDS TERMINATED BY ");
3404
pretty_print_str(&cache, sql_ex.field_term, sql_ex.field_term_len);
3406
if (sql_ex.opt_flags & OPT_ENCLOSED_FLAG)
3407
my_b_printf(&cache," OPTIONALLY ");
3408
my_b_printf(&cache, " ENCLOSED BY ");
3409
pretty_print_str(&cache, sql_ex.enclosed, sql_ex.enclosed_len);
3411
my_b_printf(&cache, " ESCAPED BY ");
3412
pretty_print_str(&cache, sql_ex.escaped, sql_ex.escaped_len);
3414
my_b_printf(&cache," LINES TERMINATED BY ");
3415
pretty_print_str(&cache, sql_ex.line_term, sql_ex.line_term_len);
3418
if (sql_ex.line_start)
3420
my_b_printf(&cache," STARTING BY ");
3421
pretty_print_str(&cache, sql_ex.line_start, sql_ex.line_start_len);
3423
if ((long) skip_lines > 0)
3424
my_b_printf(&cache, " IGNORE %ld LINES", (long) skip_lines);
3429
const char* field = fields;
3430
my_b_printf(&cache, " (");
3431
for (i = 0; i < num_fields; i++)
3434
my_b_printf(&cache, ",");
3435
my_b_printf(&cache, field);
3437
field += field_lens[i] + 1;
3439
my_b_printf(&cache, ")");
3442
my_b_printf(&cache, "%s\n", print_event_info->delimiter);
3445
#endif /* DRIZZLE_CLIENT */
3447
#ifndef DRIZZLE_CLIENT
3450
2547
Load_log_event::set_fields()
3453
This function can not use the member variable
2550
This function can not use the member variable
3454
2551
for the database, since LOAD DATA INFILE on the slave
3455
2552
can be for a different database than the current one.
3456
2553
This is the reason for the affected_db argument to this method.
3459
void Load_log_event::set_fields(const char* affected_db,
2556
void Load_log_event::set_fields(const char* affected_db,
3460
2557
List<Item> &field_list,
3461
2558
Name_resolution_context *context)
3464
2561
const char* field = fields;
3465
2562
for (i= 0; i < num_fields; i++)
3948
3001
return Log_event::EVENT_SKIP_NOT; // To keep compiler happy
3954
/**************************************************************************
3955
Intvar_log_event methods
3956
**************************************************************************/
3959
Intvar_log_event::pack_info()
3962
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
3963
void Intvar_log_event::pack_info(Protocol *protocol)
3965
char buf[256], *pos;
3966
pos= strmake(buf, get_var_type_name(), sizeof(buf)-23);
3968
pos= int64_t10_to_str(val, pos, -10);
3969
protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
3975
Intvar_log_event::Intvar_log_event()
3978
Intvar_log_event::Intvar_log_event(const char* buf,
3979
const Format_description_log_event* description_event)
3980
:Log_event(buf, description_event)
3982
buf+= description_event->common_header_len;
3983
type= buf[I_TYPE_OFFSET];
3984
val= uint8korr(buf+I_VAL_OFFSET);
3989
Intvar_log_event::get_var_type_name()
3992
const char* Intvar_log_event::get_var_type_name()
3995
case LAST_INSERT_ID_EVENT: return "LAST_INSERT_ID";
3996
case INSERT_ID_EVENT: return "INSERT_ID";
3997
default: /* impossible */ return "UNKNOWN";
4003
Intvar_log_event::write()
4006
#ifndef DRIZZLE_CLIENT
4007
bool Intvar_log_event::write(IO_CACHE* file)
4010
buf[I_TYPE_OFFSET]= (uchar) type;
4011
int8store(buf + I_VAL_OFFSET, val);
4012
return (write_header(file, sizeof(buf)) ||
4013
my_b_safe_write(file, buf, sizeof(buf)));
4019
Intvar_log_event::print()
4022
#ifdef DRIZZLE_CLIENT
4023
void Intvar_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
4027
Write_on_release_cache cache(&print_event_info->head_cache, file,
4028
Write_on_release_cache::FLUSH_F);
4030
if (!print_event_info->short_form)
4032
print_header(&cache, print_event_info, false);
4033
my_b_printf(&cache, "\tIntvar\n");
4036
my_b_printf(&cache, "SET ");
4038
case LAST_INSERT_ID_EVENT:
4039
msg="LAST_INSERT_ID";
4041
case INSERT_ID_EVENT:
4044
case INVALID_INT_EVENT:
4045
default: // cannot happen
4049
my_b_printf(&cache, "%s=%s%s\n",
4050
msg, llstr(val,llbuff), print_event_info->delimiter);
4056
Intvar_log_event::do_apply_event()
4059
#if defined(HAVE_REPLICATION)&& !defined(DRIZZLE_CLIENT)
4060
int Intvar_log_event::do_apply_event(Relay_log_info const *rli)
4063
We are now in a statement until the associated query log event has
4066
const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
4069
case LAST_INSERT_ID_EVENT:
4070
thd->stmt_depends_on_first_successful_insert_id_in_prev_stmt= 1;
4071
thd->first_successful_insert_id_in_prev_stmt= val;
4073
case INSERT_ID_EVENT:
4074
thd->force_one_auto_inc_interval(val);
4080
int Intvar_log_event::do_update_pos(Relay_log_info *rli)
4082
rli->inc_event_relay_log_pos();
4087
Log_event::enum_skip_reason
4088
Intvar_log_event::do_shall_skip(Relay_log_info *rli)
4091
It is a common error to set the slave skip counter to 1 instead of
4092
2 when recovering from an insert which used a auto increment,
4093
rand, or user var. Therefore, if the slave skip counter is 1, we
4094
just say that this event should be skipped by ignoring it, meaning
4095
that we do not change the value of the slave skip counter since it
4096
will be decreased by the following insert event.
4098
return continue_group(rli);
4104
/**************************************************************************
4105
Rand_log_event methods
4106
**************************************************************************/
4108
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
4109
void Rand_log_event::pack_info(Protocol *protocol)
4111
char buf1[256], *pos;
4112
pos= stpcpy(buf1,"rand_seed1=");
4113
pos= int10_to_str((long) seed1, pos, 10);
4114
pos= stpcpy(pos, ",rand_seed2=");
4115
pos= int10_to_str((long) seed2, pos, 10);
4116
protocol->store(buf1, (uint) (pos-buf1), &my_charset_bin);
4121
Rand_log_event::Rand_log_event(const char* buf,
4122
const Format_description_log_event* description_event)
4123
:Log_event(buf, description_event)
4125
buf+= description_event->common_header_len;
4126
seed1= uint8korr(buf+RAND_SEED1_OFFSET);
4127
seed2= uint8korr(buf+RAND_SEED2_OFFSET);
4131
#ifndef DRIZZLE_CLIENT
4132
bool Rand_log_event::write(IO_CACHE* file)
4135
int8store(buf + RAND_SEED1_OFFSET, seed1);
4136
int8store(buf + RAND_SEED2_OFFSET, seed2);
4137
return (write_header(file, sizeof(buf)) ||
4138
my_b_safe_write(file, buf, sizeof(buf)));
4143
#ifdef DRIZZLE_CLIENT
4144
void Rand_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
4146
Write_on_release_cache cache(&print_event_info->head_cache, file,
4147
Write_on_release_cache::FLUSH_F);
4149
char llbuff[22],llbuff2[22];
4150
if (!print_event_info->short_form)
4152
print_header(&cache, print_event_info, false);
4153
my_b_printf(&cache, "\tRand\n");
4155
my_b_printf(&cache, "SET @@RAND_SEED1=%s, @@RAND_SEED2=%s%s\n",
4156
llstr(seed1, llbuff),llstr(seed2, llbuff2),
4157
print_event_info->delimiter);
4159
#endif /* DRIZZLE_CLIENT */
4162
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
4163
int Rand_log_event::do_apply_event(Relay_log_info const *rli)
4166
We are now in a statement until the associated query log event has
4169
const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
4171
thd->rand.seed1= (ulong) seed1;
4172
thd->rand.seed2= (ulong) seed2;
4176
int Rand_log_event::do_update_pos(Relay_log_info *rli)
4178
rli->inc_event_relay_log_pos();
4183
Log_event::enum_skip_reason
4184
Rand_log_event::do_shall_skip(Relay_log_info *rli)
4187
It is a common error to set the slave skip counter to 1 instead of
4188
2 when recovering from an insert which used a auto increment,
4189
rand, or user var. Therefore, if the slave skip counter is 1, we
4190
just say that this event should be skipped by ignoring it, meaning
4191
that we do not change the value of the slave skip counter since it
4192
will be decreased by the following insert event.
4194
return continue_group(rli);
4197
#endif /* !DRIZZLE_CLIENT */
4200
3005
/**************************************************************************
4201
3006
Xid_log_event methods
4202
3007
**************************************************************************/
4204
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
4205
3009
void Xid_log_event::pack_info(Protocol *protocol)
4207
3011
char buf[128], *pos;
4208
pos= stpcpy(buf, "COMMIT /* xid=");
3012
pos= strcpy(buf, "COMMIT /* xid=")+14;
4209
3013
pos= int64_t10_to_str(xid, pos, 10);
4210
pos= stpcpy(pos, " */");
3014
pos= strcpy(pos, " */")+3;
4211
3015
protocol->store(buf, (uint) (pos-buf), &my_charset_bin);
4217
3020
It's ok not to use int8store here,
4218
as long as xid_t::set(uint64_t) and
4219
xid_t::get_my_xid doesn't do it either.
3021
as long as XID::set(uint64_t) and
3022
XID::get_my_xid doesn't do it either.
4220
3023
We don't care about actual values of xids as long as
4221
3024
identical numbers compare identically
4234
#ifndef DRIZZLE_CLIENT
4235
3037
bool Xid_log_event::write(IO_CACHE* file)
4237
3039
return write_header(file, sizeof(xid)) ||
4238
my_b_safe_write(file, (uchar*) &xid, sizeof(xid));
4243
#ifdef DRIZZLE_CLIENT
4244
void Xid_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
4246
Write_on_release_cache cache(&print_event_info->head_cache, file,
4247
Write_on_release_cache::FLUSH_F);
4249
if (!print_event_info->short_form)
4252
int64_t10_to_str(xid, buf, 10);
4254
print_header(&cache, print_event_info, false);
4255
my_b_printf(&cache, "\tXid = %s\n", buf);
4257
my_b_printf(&cache, "COMMIT%s\n", print_event_info->delimiter);
4259
#endif /* DRIZZLE_CLIENT */
4262
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
4263
int Xid_log_event::do_apply_event(Relay_log_info const *rli __attribute__((unused)))
4265
/* For a slave Xid_log_event is COMMIT */
4266
general_log_print(thd, COM_QUERY,
4267
"COMMIT /* implicit, from Xid_log_event */");
4268
return end_trans(thd, COMMIT);
3040
my_b_safe_write(file, (unsigned char*) &xid, sizeof(xid));
3044
int Xid_log_event::do_apply_event(const Relay_log_info *)
3046
return end_trans(session, COMMIT);
4271
3049
Log_event::enum_skip_reason
4272
3050
Xid_log_event::do_shall_skip(Relay_log_info *rli)
4274
3052
if (rli->slave_skip_counter > 0) {
4275
thd->options&= ~OPTION_BEGIN;
3053
session->options&= ~OPTION_BEGIN;
4276
3054
return(Log_event::EVENT_SKIP_COUNT);
4278
3056
return(Log_event::do_shall_skip(rli));
4280
#endif /* !DRIZZLE_CLIENT */
4283
/**************************************************************************
4284
User_var_log_event methods
4285
**************************************************************************/
4287
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
4288
void User_var_log_event::pack_info(Protocol* protocol)
4291
uint val_offset= 4 + name_len;
4292
uint event_len= val_offset;
4296
if (!(buf= (char*) my_malloc(val_offset + 5, MYF(MY_WME))))
4298
stpcpy(buf + val_offset, "NULL");
4299
event_len= val_offset + 4;
4306
float8get(real_val, val);
4307
if (!(buf= (char*) my_malloc(val_offset + MY_GCVT_MAX_FIELD_WIDTH + 1,
4310
event_len+= my_gcvt(real_val, MY_GCVT_ARG_DOUBLE, MY_GCVT_MAX_FIELD_WIDTH,
4311
buf + val_offset, NULL);
4314
if (!(buf= (char*) my_malloc(val_offset + 22, MYF(MY_WME))))
4316
event_len= int64_t10_to_str(uint8korr(val), buf + val_offset,-10)-buf;
4318
case DECIMAL_RESULT:
4320
if (!(buf= (char*) my_malloc(val_offset + DECIMAL_MAX_STR_LENGTH,
4323
String str(buf+val_offset, DECIMAL_MAX_STR_LENGTH, &my_charset_bin);
4325
binary2my_decimal(E_DEC_FATAL_ERROR, (uchar*) (val+2), &dec, val[0],
4327
my_decimal2string(E_DEC_FATAL_ERROR, &dec, 0, 0, 0, &str);
4328
event_len= str.length() + val_offset;
4332
/* 15 is for 'COLLATE' and other chars */
4333
buf= (char*) my_malloc(event_len+val_len*2+1+2*MY_CS_NAME_SIZE+15,
4335
const CHARSET_INFO *cs;
4338
if (!(cs= get_charset(charset_number, MYF(0))))
4340
stpcpy(buf+val_offset, "???");
4345
char *p= strxmov(buf + val_offset, "_", cs->csname, " ", NullS);
4346
p= str_to_hex(p, val, val_len);
4347
p= strxmov(p, " COLLATE ", cs->name, NullS);
4359
memcpy(buf+2, name, name_len);
4360
buf[2+name_len]= '`';
4361
buf[3+name_len]= '=';
4362
protocol->store(buf, event_len, &my_charset_bin);
4363
my_free(buf, MYF(0));
4365
#endif /* !DRIZZLE_CLIENT */
4368
User_var_log_event::
4369
User_var_log_event(const char* buf,
4370
const Format_description_log_event* description_event)
4371
:Log_event(buf, description_event)
4373
buf+= description_event->common_header_len;
4374
name_len= uint4korr(buf);
4375
name= (char *) buf + UV_NAME_LEN_SIZE;
4376
buf+= UV_NAME_LEN_SIZE + name_len;
4377
is_null= (bool) *buf;
4380
type= STRING_RESULT;
4381
charset_number= my_charset_bin.number;
4387
type= (Item_result) buf[UV_VAL_IS_NULL];
4388
charset_number= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE);
4389
val_len= uint4korr(buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
4390
UV_CHARSET_NUMBER_SIZE);
4391
val= (char *) (buf + UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
4392
UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE);
4397
#ifndef DRIZZLE_CLIENT
4398
bool User_var_log_event::write(IO_CACHE* file)
4400
char buf[UV_NAME_LEN_SIZE];
4401
char buf1[UV_VAL_IS_NULL + UV_VAL_TYPE_SIZE +
4402
UV_CHARSET_NUMBER_SIZE + UV_VAL_LEN_SIZE];
4403
uchar buf2[(8 > DECIMAL_MAX_FIELD_SIZE + 2) ? 8 : DECIMAL_MAX_FIELD_SIZE +2], *pos= buf2;
4407
int4store(buf, name_len);
4409
if ((buf1[0]= is_null))
4412
val_len= 0; // Length of 'pos'
4417
int4store(buf1 + 2, charset_number);
4421
float8store(buf2, *(double*) val);
4424
int8store(buf2, *(int64_t*) val);
4426
case DECIMAL_RESULT:
4428
my_decimal *dec= (my_decimal *)val;
4429
dec->fix_buffer_pointer();
4430
buf2[0]= (char)(dec->intg + dec->frac);
4431
buf2[1]= (char)dec->frac;
4432
decimal2bin((decimal_t*)val, buf2+2, buf2[0], buf2[1]);
4433
val_len= decimal_bin_size(buf2[0], buf2[1]) + 2;
4444
int4store(buf1 + 2 + UV_CHARSET_NUMBER_SIZE, val_len);
4448
/* Length of the whole event */
4449
event_length= sizeof(buf)+ name_len + buf1_length + val_len;
4451
return (write_header(file, event_length) ||
4452
my_b_safe_write(file, (uchar*) buf, sizeof(buf)) ||
4453
my_b_safe_write(file, (uchar*) name, name_len) ||
4454
my_b_safe_write(file, (uchar*) buf1, buf1_length) ||
4455
my_b_safe_write(file, pos, val_len));
4461
User_var_log_event::print()
4464
#ifdef DRIZZLE_CLIENT
4465
void User_var_log_event::print(FILE* file, PRINT_EVENT_INFO* print_event_info)
4467
Write_on_release_cache cache(&print_event_info->head_cache, file,
4468
Write_on_release_cache::FLUSH_F);
4470
if (!print_event_info->short_form)
4472
print_header(&cache, print_event_info, false);
4473
my_b_printf(&cache, "\tUser_var\n");
4476
my_b_printf(&cache, "SET @`");
4477
my_b_write(&cache, (uchar*) name, (uint) (name_len));
4478
my_b_printf(&cache, "`");
4482
my_b_printf(&cache, ":=NULL%s\n", print_event_info->delimiter);
4489
char real_buf[FMT_G_BUFSIZE(14)];
4490
float8get(real_val, val);
4491
sprintf(real_buf, "%.14g", real_val);
4492
my_b_printf(&cache, ":=%s%s\n", real_buf, print_event_info->delimiter);
4496
int64_t10_to_str(uint8korr(val), int_buf, -10);
4497
my_b_printf(&cache, ":=%s%s\n", int_buf, print_event_info->delimiter);
4499
case DECIMAL_RESULT:
4502
int str_len= sizeof(str_buf) - 1;
4503
int precision= (int)val[0];
4504
int scale= (int)val[1];
4505
decimal_digit_t dec_buf[10];
4510
bin2decimal((uchar*) val+2, &dec, precision, scale);
4511
decimal2string(&dec, str_buf, &str_len, 0, 0, 0);
4512
str_buf[str_len]= 0;
4513
my_b_printf(&cache, ":=%s%s\n", str_buf, print_event_info->delimiter);
4519
Let's express the string in hex. That's the most robust way. If we
4520
print it in character form instead, we need to escape it with
4521
character_set_client which we don't know (we will know it in 5.0, but
4522
in 4.1 we don't know it easily when we are printing
4523
User_var_log_event). Explanation why we would need to bother with
4524
character_set_client (quoting Bar):
4525
> Note, the parser doesn't switch to another unescaping mode after
4526
> it has met a character set introducer.
4527
> For example, if an SJIS client says something like:
4528
> SET @a= _ucs2 \0a\0b'
4529
> the string constant is still unescaped according to SJIS, not
4530
> according to UCS2.
4533
const CHARSET_INFO *cs;
4535
if (!(hex_str= (char *)my_alloca(2*val_len+1+2))) // 2 hex digits / byte
4536
break; // no error, as we are 'void'
4537
str_to_hex(hex_str, val, val_len);
4539
For proper behaviour when mysqlbinlog|mysql, we need to explicitely
4540
specify the variable's collation. It will however cause problems when
4541
people want to mysqlbinlog|mysql into another server not supporting the
4542
character set. But there's not much to do about this and it's unlikely.
4544
if (!(cs= get_charset(charset_number, MYF(0))))
4546
Generate an unusable command (=> syntax error) is probably the best
4547
thing we can do here.
4549
my_b_printf(&cache, ":=???%s\n", print_event_info->delimiter);
4551
my_b_printf(&cache, ":=_%s %s COLLATE `%s`%s\n",
4552
cs->csname, hex_str, cs->name,
4553
print_event_info->delimiter);
4568
User_var_log_event::do_apply_event()
4571
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
4572
int User_var_log_event::do_apply_event(Relay_log_info const *rli)
4575
const CHARSET_INFO *charset;
4576
if (!(charset= get_charset(charset_number, MYF(MY_WME))))
4578
LEX_STRING user_var_name;
4579
user_var_name.str= name;
4580
user_var_name.length= name_len;
4585
We are now in a statement until the associated query log event has
4588
const_cast<Relay_log_info*>(rli)->set_flag(Relay_log_info::IN_STMT);
4592
it= new Item_null();
4598
float8get(real_val, val);
4599
it= new Item_float(real_val, 0);
4600
val= (char*) &real_val; // Pointer to value in native format
4604
int_val= (int64_t) uint8korr(val);
4605
it= new Item_int(int_val);
4606
val= (char*) &int_val; // Pointer to value in native format
4609
case DECIMAL_RESULT:
4611
Item_decimal *dec= new Item_decimal((uchar*) val+2, val[0], val[1]);
4613
val= (char *)dec->val_decimal(NULL);
4614
val_len= sizeof(my_decimal);
4618
it= new Item_string(val, val_len, charset);
4626
Item_func_set_user_var e(user_var_name, it);
4628
Item_func_set_user_var can't substitute something else on its place =>
4629
0 can be passed as last argument (reference on item)
4631
e.fix_fields(thd, 0);
4633
A variable can just be considered as a table with
4634
a single record and with a single column. Thus, like
4635
a column value, it could always have IMPLICIT derivation.
4637
e.update_hash(val, val_len, type, charset, DERIVATION_IMPLICIT, 0);
4638
free_root(thd->mem_root,0);
4643
int User_var_log_event::do_update_pos(Relay_log_info *rli)
4645
rli->inc_event_relay_log_pos();
4649
Log_event::enum_skip_reason
4650
User_var_log_event::do_shall_skip(Relay_log_info *rli)
4653
It is a common error to set the slave skip counter to 1 instead
4654
of 2 when recovering from an insert which used a auto increment,
4655
rand, or user var. Therefore, if the slave skip counter is 1, we
4656
just say that this event should be skipped by ignoring it, meaning
4657
that we do not change the value of the slave skip counter since it
4658
will be decreased by the following insert event.
4660
return continue_group(rli);
4662
#endif /* !DRIZZLE_CLIENT */
4665
3060
/**************************************************************************
4666
3061
Slave_log_event methods
4667
3062
**************************************************************************/
4669
#ifdef HAVE_REPLICATION
4670
#ifdef DRIZZLE_CLIENT
4671
void Unknown_log_event::print(FILE* file_arg, PRINT_EVENT_INFO* print_event_info)
4673
Write_on_release_cache cache(&print_event_info->head_cache, file_arg);
4675
if (print_event_info->short_form)
4677
print_header(&cache, print_event_info, false);
4678
my_b_printf(&cache, "\n# %s", "Unknown event\n");
4682
#ifndef DRIZZLE_CLIENT
4683
3064
void Slave_log_event::pack_info(Protocol *protocol)
4685
char buf[256+HOSTNAME_LENGTH], *pos;
4686
pos= stpcpy(buf, "host=");
4687
pos= stpncpy(pos, master_host, HOSTNAME_LENGTH);
4688
pos= stpcpy(pos, ",port=");
4689
pos= int10_to_str((long) master_port, pos, 10);
4690
pos= stpcpy(pos, ",log=");
4691
pos= stpcpy(pos, master_log);
4692
pos= stpcpy(pos, ",pos=");
4693
pos= int64_t10_to_str(master_pos, pos, 10);
4694
protocol->store(buf, pos-buf, &my_charset_bin);
3066
ostringstream stream;
3067
stream << "host=" << master_host << ",port=" << master_port;
3068
stream << ",log=" << master_log << ",pos=" << master_pos;
3070
protocol->store(stream.str().c_str(), stream.str().length(),
4696
#endif /* !DRIZZLE_CLIENT */
4699
#ifndef DRIZZLE_CLIENT
4702
3077
re-write this better without holding both locks at the same time
4704
Slave_log_event::Slave_log_event(THD* thd_arg,
3079
Slave_log_event::Slave_log_event(Session* session_arg,
4705
3080
Relay_log_info* rli)
4706
:Log_event(thd_arg, 0, 0) , mem_pool(0), master_host(0)
3081
:Log_event(session_arg, 0, 0) , mem_pool(0), master_host(0)
4708
3083
if (!rli->inited) // QQ When can this happen ?
5653
#ifndef DRIZZLE_CLIENT
5655
3835
Execute_load_query_log_event::write_post_header_for_derived(IO_CACHE* file)
5657
uchar buf[EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN];
3837
unsigned char buf[EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN];
5658
3838
int4store(buf, file_id);
5659
3839
int4store(buf + 4, fn_pos_start);
5660
3840
int4store(buf + 4 + 4, fn_pos_end);
5661
*(buf + 4 + 4 + 4)= (uchar) dup_handling;
3841
*(buf + 4 + 4 + 4)= (unsigned char) dup_handling;
5662
3842
return my_b_safe_write(file, buf, EXECUTE_LOAD_QUERY_EXTRA_HEADER_LEN);
5667
#ifdef DRIZZLE_CLIENT
5668
void Execute_load_query_log_event::print(FILE* file,
5669
PRINT_EVENT_INFO* print_event_info)
5671
print(file, print_event_info, 0);
5675
Prints the query as LOAD DATA LOCAL and with rewritten filename.
5677
void Execute_load_query_log_event::print(FILE* file,
5678
PRINT_EVENT_INFO* print_event_info,
5679
const char *local_fname)
5681
Write_on_release_cache cache(&print_event_info->head_cache, file);
5683
print_query_header(&cache, print_event_info);
5687
my_b_write(&cache, (uchar*) query, fn_pos_start);
5688
my_b_printf(&cache, " LOCAL INFILE \'");
5689
my_b_printf(&cache, local_fname);
5690
my_b_printf(&cache, "\'");
5691
if (dup_handling == LOAD_DUP_REPLACE)
5692
my_b_printf(&cache, " REPLACE");
5693
my_b_printf(&cache, " INTO");
5694
my_b_write(&cache, (uchar*) query + fn_pos_end, q_len-fn_pos_end);
5695
my_b_printf(&cache, "\n%s\n", print_event_info->delimiter);
5699
my_b_write(&cache, (uchar*) query, q_len);
5700
my_b_printf(&cache, "\n%s\n", print_event_info->delimiter);
5703
if (!print_event_info->short_form)
5704
my_b_printf(&cache, "# file_id: %d \n", file_id);
5709
#if defined(HAVE_REPLICATION) && !defined(DRIZZLE_CLIENT)
5710
3846
void Execute_load_query_log_event::pack_info(Protocol *protocol)
5712
3848
char *buf, *pos;
5713
if (!(buf= (char*) my_malloc(9 + db_len + q_len + 10 + 21, MYF(MY_WME))))
3849
if (!(buf= (char*) malloc(9 + db_len + q_len + 10 + 21)))
5716
3852
if (db && db_len)
5718
pos= stpcpy(buf, "use `");
3854
pos= strcpy(buf, "use `")+5;
5719
3855
memcpy(pos, db, db_len);
5720
pos= stpcpy(pos+db_len, "`; ");
3856
pos= strcpy(pos+db_len, "`; ")+3;
5722
3858
if (query && q_len)
5724
3860
memcpy(pos, query, q_len);
5727
pos= stpcpy(pos, " ;file_id=");
3863
pos= strcpy(pos, " ;file_id=")+10;
5728
3864
pos= int10_to_str((long) file_id, pos, 10);
5729
3865
protocol->store(buf, pos-buf, &my_charset_bin);
5730
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
6169
4281
if (get_flags(NO_FOREIGN_KEY_CHECKS_F))
6170
thd->options|= OPTION_NO_FOREIGN_KEY_CHECKS;
4282
session->options|= OPTION_NO_FOREIGN_KEY_CHECKS;
6172
thd->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
4284
session->options&= ~OPTION_NO_FOREIGN_KEY_CHECKS;
6174
4286
if (get_flags(RELAXED_UNIQUE_CHECKS_F))
6175
thd->options|= OPTION_RELAXED_UNIQUE_CHECKS;
4287
session->options|= OPTION_RELAXED_UNIQUE_CHECKS;
6177
thd->options&= ~OPTION_RELAXED_UNIQUE_CHECKS;
4289
session->options&= ~OPTION_RELAXED_UNIQUE_CHECKS;
6178
4290
/* A small test to verify that objects have consistent types */
6179
assert(sizeof(thd->options) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
6182
while ((error= lock_tables(thd, rli->tables_to_lock,
4291
assert(sizeof(session->options) == sizeof(OPTION_RELAXED_UNIQUE_CHECKS));
4294
while ((error= lock_tables(session, rli->tables_to_lock,
6183
4295
rli->tables_to_lock_count, &need_reopen)))
6185
4297
if (!need_reopen)
6187
if (thd->is_slave_error || thd->is_fatal_error)
4299
if (session->is_slave_error || session->is_fatal_error)
6190
4302
Error reporting borrowed from Query_log_event with many excessive
6191
4303
simplifications (we don't honour --slave-skip-errors)
6193
uint actual_error= thd->main_da.sql_errno();
4305
uint32_t actual_error= session->main_da.sql_errno();
6194
4306
rli->report(ERROR_LEVEL, actual_error,
6195
"Error '%s' in %s event: when locking tables",
6196
(actual_error ? thd->main_da.message():
6197
"unexpected success or fatal error"),
4307
_("Error '%s' in %s event: when locking tables"),
4309
? session->main_da.message()
4310
: _("unexpected success or fatal error")),
6198
4311
get_type_str());
6199
thd->is_fatal_error= 1;
4312
session->is_fatal_error= 1;
6203
4316
rli->report(ERROR_LEVEL, error,
6204
"Error in %s event: when locking tables",
4317
_("Error in %s event: when locking tables"),
6205
4318
get_type_str());
6207
4320
const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
6212
So we need to reopen the tables.
6214
We need to flush the pending RBR event, since it keeps a
6215
pointer to an open table.
6217
ALTERNATIVE SOLUTION (not implemented): Extract a pointer to
6218
the pending RBR event and reset the table pointer after the
6219
tables has been reopened.
6221
NOTE: For this new scheme there should be no pending event:
6222
need to add code to assert that is the case.
6224
thd->binlog_flush_pending_rows_event(false);
6225
TABLE_LIST *tables= rli->tables_to_lock;
6226
close_tables_for_reopen(thd, &tables);
6228
uint tables_count= rli->tables_to_lock_count;
6229
if ((error= open_tables(thd, &tables, &tables_count, 0)))
4324
TableList *tables= rli->tables_to_lock;
4325
close_tables_for_reopen(session, &tables);
4327
uint32_t tables_count= rli->tables_to_lock_count;
4328
if ((error= open_tables(session, &tables, &tables_count, 0)))
6231
if (thd->is_slave_error || thd->is_fatal_error)
4330
if (session->is_slave_error || session->is_fatal_error)
6234
4333
Error reporting borrowed from Query_log_event with many excessive
6235
4334
simplifications (we don't honour --slave-skip-errors)
6237
uint actual_error= thd->main_da.sql_errno();
4336
uint32_t actual_error= session->main_da.sql_errno();
6238
4337
rli->report(ERROR_LEVEL, actual_error,
6239
"Error '%s' on reopening tables",
6240
(actual_error ? thd->main_da.message() :
6241
"unexpected success or fatal error"));
6242
thd->is_slave_error= 1;
4338
_("Error '%s' on reopening tables"),
4340
? session->main_da.message()
4341
: _("unexpected success or fatal error")));
4342
session->is_slave_error= 1;
6244
4344
const_cast<Relay_log_info*>(rli)->clear_tables_to_lock();
6692
4748
@page How replication of field metadata works.
6694
When a table map is created, the master first calls
6695
Table_map_log_event::save_field_metadata() which calculates how many
6696
values will be in the field metadata. Only those fields that require the
6697
extra data are added. The method also loops through all of the fields in
4750
When a table map is created, the master first calls
4751
Table_map_log_event::save_field_metadata() which calculates how many
4752
values will be in the field metadata. Only those fields that require the
4753
extra data are added. The method also loops through all of the fields in
6698
4754
the table calling the method Field::save_field_metadata() which returns the
6699
4755
values for the field that will be saved in the metadata and replicated to
6700
4756
the slave. Once all fields have been processed, the table map is written to
6701
4757
the binlog adding the size of the field metadata and the field metadata to
6702
4758
the end of the body of the table map.
6704
When a table map is read on the slave, the field metadata is read from the
6705
table map and passed to the table_def class constructor which saves the
6706
field metadata from the table map into an array based on the type of the
6707
field. Field metadata values not present (those fields that do not use extra
6708
data) in the table map are initialized as zero (0). The array size is the
4760
When a table map is read on the slave, the field metadata is read from the
4761
table map and passed to the table_def class constructor which saves the
4762
field metadata from the table map into an array based on the type of the
4763
field. Field metadata values not present (those fields that do not use extra
4764
data) in the table map are initialized as zero (0). The array size is the
6709
4765
same as the columns for the table on the slave.
6711
Additionally, values saved for field metadata on the master are saved as a
6712
string of bytes (uchar) in the binlog. A field may require 1 or more bytes
6713
to store the information. In cases where values require multiple bytes
6714
(e.g. values > 255), the endian-safe methods are used to properly encode
4767
Additionally, values saved for field metadata on the master are saved as a
4768
string of bytes (unsigned char) in the binlog. A field may require 1 or more bytes
4769
to store the information. In cases where values require multiple bytes
4770
(e.g. values > 255), the endian-safe methods are used to properly encode
6715
4771
the values on the master and decode them on the slave. When the field
6716
4772
metadata values are captured on the slave, they are stored in an array of
6717
4773
type uint16_t. This allows the least number of casts to prevent casting bugs
6718
4774
when the field metadata is used in comparisons of field attributes. When
6719
4775
the field metadata is used for calculating addresses in pointer math, the
6720
type used is uint32_t.
4776
type used is uint32_t.
6723
#if !defined(DRIZZLE_CLIENT)
6725
4780
Save the field metadata based on the real_type of the field.
6726
4781
The metadata saved depends on the type of the field. Some fields
6727
4782
store a single byte for pack_length() while others store two bytes
6728
4783
for field_length (max length).
6733
4788
We may want to consider changing the encoding of the information.
6734
Currently, the code attempts to minimize the number of bytes written to
6735
the tablemap. There are at least two other alternatives; 1) using
4789
Currently, the code attempts to minimize the number of bytes written to
4790
the tablemap. There are at least two other alternatives; 1) using
6736
4791
net_store_length() to store the data allowing it to choose the number of
6737
bytes that are appropriate thereby making the code much easier to
4792
bytes that are appropriate thereby making the code much easier to
6738
4793
maintain (only 1 place to change the encoding), or 2) use a fixed number
6739
4794
of bytes for each field. The problem with option 1 is that net_store_length()
6740
4795
will use one byte if the value < 251, but 3 bytes if it is > 250. Thus,