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 <drizzled/server_includes.h>
17
#include <drizzled/replication/rli.h>
18
#include <drizzled/replication/binlog.h>
19
#include <mysys/base64.h>
20
#include <drizzled/error.h>
21
#include <drizzled/slave.h>
22
#include <drizzled/session.h>
25
Execute a BINLOG statement
27
To execute the BINLOG command properly the server needs to know
28
which format the BINLOG command's event is in. Therefore, the first
29
BINLOG statement seen must be a base64 encoding of the
30
Format_description_log_event, as outputted by mysqlbinlog. This
31
Format_description_log_event is cached in
32
rli->description_event_for_exec.
35
void mysql_client_binlog_statement(Session* session)
37
size_t coded_len= session->lex->comment.length + 1;
38
size_t decoded_len= base64_needed_decoded_length(coded_len);
39
assert(coded_len > 0);
46
If we do not have a Format_description_event, we create a dummy
47
one here. In this case, the first event we read must be a
48
Format_description_event.
50
bool have_fd_event= true;
51
if (!session->rli_fake)
53
session->rli_fake= new Relay_log_info;
55
session->rli_fake->is_fake= true;
59
if (session->rli_fake && !session->rli_fake->relay_log.description_event_for_exec)
61
session->rli_fake->relay_log.description_event_for_exec=
62
new Format_description_log_event(4);
67
char *buf= (char *) malloc(decoded_len);
73
if (!(session->rli_fake &&
74
session->rli_fake->relay_log.description_event_for_exec &&
77
my_error(ER_OUTOFMEMORY, MYF(0), 1); /* needed 1 bytes */
81
session->rli_fake->sql_session= session;
82
session->rli_fake->no_storage= true;
84
for (char const *strptr= session->lex->comment.str ;
85
strptr < session->lex->comment.str + session->lex->comment.length ; )
87
char const *endptr= 0;
88
int bytes_decoded= base64_decode(strptr, coded_len, buf, &endptr);
90
if (bytes_decoded < 0)
92
my_error(ER_BASE64_DECODE_ERROR, MYF(0));
95
else if (bytes_decoded == 0)
96
break; // If no bytes where read, the string contained only whitespace
98
assert(bytes_decoded > 0);
99
assert(endptr > strptr);
100
coded_len-= endptr - strptr;
104
Now we have one or more events stored in the buffer. The size of
105
the buffer is computed based on how much base64-encoded data
106
there were, so there should be ample space for the data (maybe
107
even too much, since a statement can consist of a considerable
110
TODO: Switch to use a stream-based base64 encoder/decoder in
111
order to be able to read exactly what is necessary.
115
Now we start to read events of the buffer, until there are no
118
for (char *bufptr= buf ; bytes_decoded > 0 ; )
121
Checking that the first event in the buffer is not truncated.
123
uint32_t event_len= uint4korr(bufptr + EVENT_LEN_OFFSET);
124
if (bytes_decoded < EVENT_LEN_OFFSET || (uint) bytes_decoded < event_len)
126
my_error(ER_SYNTAX_ERROR, MYF(0));
131
If we have not seen any Format_description_event, then we must
132
see one; it is the only statement that can be read in base64
133
without a prior Format_description_event.
137
int type = bufptr[EVENT_TYPE_OFFSET];
138
if (type == FORMAT_DESCRIPTION_EVENT || type == START_EVENT_V3)
142
my_error(ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT,
143
MYF(0), Log_event::get_type_str((Log_event_type)type));
148
ev= Log_event::read_log_event(bufptr, event_len, &error,
149
session->rli_fake->relay_log.
150
description_event_for_exec);
155
This could actually be an out-of-memory, but it is more likely
156
causes by a bad statement
158
my_error(ER_SYNTAX_ERROR, MYF(0));
162
bytes_decoded -= event_len;
165
ev->session= session;
167
We go directly to the application phase, since we don't need
168
to check if the event shall be skipped or not.
170
Neither do we have to update the log positions, since that is
171
not used at all: the rli_fake instance is used only for error
174
if (apply_event_and_update_pos(ev, session, session->rli_fake, false))
177
TODO: Maybe a better error message since the BINLOG statement
178
now contains several events.
180
my_error(ER_UNKNOWN_ERROR, MYF(0), "Error executing BINLOG statement");
185
Format_description_log_event should not be deleted because it
186
will be used to read info about the relay log's format; it
187
will be deleted when the SQL thread does not need it,
188
i.e. when this thread terminates.
190
if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
199
session->rli_fake->clear_tables_to_lock();