1
/* Copyright (C) 2005-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., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */
16
#include "mysql_priv.h"
21
Execute a BINLOG statement
23
To execute the BINLOG command properly the server needs to know
24
which format the BINLOG command's event is in. Therefore, the first
25
BINLOG statement seen must be a base64 encoding of the
26
Format_description_log_event, as outputted by mysqlbinlog. This
27
Format_description_log_event is cached in
28
rli->description_event_for_exec.
31
void mysql_client_binlog_statement(THD* thd)
33
DBUG_ENTER("mysql_client_binlog_statement");
34
DBUG_PRINT("info",("binlog base64: '%*s'",
35
(int) (thd->lex->comment.length < 2048 ?
36
thd->lex->comment.length : 2048),
37
thd->lex->comment.str));
39
size_t coded_len= thd->lex->comment.length + 1;
40
size_t decoded_len= base64_needed_decoded_length(coded_len);
41
DBUG_ASSERT(coded_len > 0);
48
If we do not have a Format_description_event, we create a dummy
49
one here. In this case, the first event we read must be a
50
Format_description_event.
52
my_bool have_fd_event= TRUE;
55
thd->rli_fake= new Relay_log_info;
57
thd->rli_fake->is_fake= TRUE;
61
if (thd->rli_fake && !thd->rli_fake->relay_log.description_event_for_exec)
63
thd->rli_fake->relay_log.description_event_for_exec=
64
new Format_description_log_event(4);
69
char *buf= (char *) my_malloc(decoded_len, MYF(MY_WME));
75
if (!(thd->rli_fake &&
76
thd->rli_fake->relay_log.description_event_for_exec &&
79
my_error(ER_OUTOFMEMORY, MYF(0), 1); /* needed 1 bytes */
83
thd->rli_fake->sql_thd= thd;
84
thd->rli_fake->no_storage= TRUE;
86
for (char const *strptr= thd->lex->comment.str ;
87
strptr < thd->lex->comment.str + thd->lex->comment.length ; )
89
char const *endptr= 0;
90
int bytes_decoded= base64_decode(strptr, coded_len, buf, &endptr);
94
This debug printout should not be used for valgrind builds
95
since it will read from unassigned memory.
98
("bytes_decoded: %d strptr: 0x%lx endptr: 0x%lx ('%c':%d)",
99
bytes_decoded, (long) strptr, (long) endptr, *endptr,
103
if (bytes_decoded < 0)
105
my_error(ER_BASE64_DECODE_ERROR, MYF(0));
108
else if (bytes_decoded == 0)
109
break; // If no bytes where read, the string contained only whitespace
111
DBUG_ASSERT(bytes_decoded > 0);
112
DBUG_ASSERT(endptr > strptr);
113
coded_len-= endptr - strptr;
117
Now we have one or more events stored in the buffer. The size of
118
the buffer is computed based on how much base64-encoded data
119
there were, so there should be ample space for the data (maybe
120
even too much, since a statement can consist of a considerable
123
TODO: Switch to use a stream-based base64 encoder/decoder in
124
order to be able to read exactly what is necessary.
127
DBUG_PRINT("info",("binlog base64 decoded_len: %lu bytes_decoded: %d",
128
(ulong) decoded_len, bytes_decoded));
131
Now we start to read events of the buffer, until there are no
134
for (char *bufptr= buf ; bytes_decoded > 0 ; )
137
Checking that the first event in the buffer is not truncated.
139
ulong event_len= uint4korr(bufptr + EVENT_LEN_OFFSET);
140
DBUG_PRINT("info", ("event_len=%lu, bytes_decoded=%d",
141
event_len, bytes_decoded));
142
if (bytes_decoded < EVENT_LEN_OFFSET || (uint) bytes_decoded < event_len)
144
my_error(ER_SYNTAX_ERROR, MYF(0));
149
If we have not seen any Format_description_event, then we must
150
see one; it is the only statement that can be read in base64
151
without a prior Format_description_event.
155
int type = bufptr[EVENT_TYPE_OFFSET];
156
if (type == FORMAT_DESCRIPTION_EVENT || type == START_EVENT_V3)
160
my_error(ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT,
161
MYF(0), Log_event::get_type_str((Log_event_type)type));
166
ev= Log_event::read_log_event(bufptr, event_len, &error,
167
thd->rli_fake->relay_log.
168
description_event_for_exec);
170
DBUG_PRINT("info",("binlog base64 err=%s", error));
174
This could actually be an out-of-memory, but it is more likely
175
causes by a bad statement
177
my_error(ER_SYNTAX_ERROR, MYF(0));
181
bytes_decoded -= event_len;
184
DBUG_PRINT("info",("ev->get_type_code()=%d", ev->get_type_code()));
187
This debug printout should not be used for valgrind builds
188
since it will read from unassigned memory.
190
DBUG_PRINT("info",("bufptr+EVENT_TYPE_OFFSET: 0x%lx",
191
(long) (bufptr+EVENT_TYPE_OFFSET)));
192
DBUG_PRINT("info", ("bytes_decoded: %d bufptr: 0x%lx buf[EVENT_LEN_OFFSET]: %lu",
193
bytes_decoded, (long) bufptr,
194
(ulong) uint4korr(bufptr+EVENT_LEN_OFFSET)));
198
We go directly to the application phase, since we don't need
199
to check if the event shall be skipped or not.
201
Neither do we have to update the log positions, since that is
202
not used at all: the rli_fake instance is used only for error
205
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
206
if (apply_event_and_update_pos(ev, thd, thd->rli_fake, FALSE))
209
TODO: Maybe a better error message since the BINLOG statement
210
now contains several events.
212
my_error(ER_UNKNOWN_ERROR, MYF(0), "Error executing BINLOG statement");
218
Format_description_log_event should not be deleted because it
219
will be used to read info about the relay log's format; it
220
will be deleted when the SQL thread does not need it,
221
i.e. when this thread terminates.
223
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
230
DBUG_PRINT("info",("binlog base64 execution finished successfully"));
234
thd->rli_fake->clear_tables_to_lock();
235
my_free(buf, MYF(MY_ALLOW_ZERO_PTR));