~drizzle-trunk/drizzle/development

1 by brian
clean slate
1
/* Copyright (C) 2005-2006 MySQL AB
2
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.
6
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.
11
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 */
15
243.1.17 by Jay Pipes
FINAL PHASE removal of mysql_priv.h (Bye, bye my friend.)
16
#include <drizzled/server_includes.h>
1 by brian
clean slate
17
#include "rpl_rli.h"
212.5.3 by Monty Taylor
Moved base64.h to mysys.
18
#include <mysys/base64.h>
1 by brian
clean slate
19
20
/**
21
  Execute a BINLOG statement
22
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.
29
*/
30
520.1.22 by Brian Aker
Second pass of thd cleanup
31
void mysql_client_binlog_statement(Session* session)
1 by brian
clean slate
32
{
520.1.22 by Brian Aker
Second pass of thd cleanup
33
  size_t coded_len= session->lex->comment.length + 1;
1 by brian
clean slate
34
  size_t decoded_len= base64_needed_decoded_length(coded_len);
51.1.49 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
35
  assert(coded_len > 0);
1 by brian
clean slate
36
37
  /*
38
    Allocation
39
  */
40
41
  /*
42
    If we do not have a Format_description_event, we create a dummy
43
    one here.  In this case, the first event we read must be a
44
    Format_description_event.
45
  */
199 by Brian Aker
my_bool...
46
  bool have_fd_event= true;
520.1.22 by Brian Aker
Second pass of thd cleanup
47
  if (!session->rli_fake)
1 by brian
clean slate
48
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
49
    session->rli_fake= new Relay_log_info;
1 by brian
clean slate
50
#ifdef HAVE_purify
520.1.22 by Brian Aker
Second pass of thd cleanup
51
    session->rli_fake->is_fake= true;
1 by brian
clean slate
52
#endif
51.1.49 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
53
    have_fd_event= false;
1 by brian
clean slate
54
  }
520.1.22 by Brian Aker
Second pass of thd cleanup
55
  if (session->rli_fake && !session->rli_fake->relay_log.description_event_for_exec)
1 by brian
clean slate
56
  {
520.1.22 by Brian Aker
Second pass of thd cleanup
57
    session->rli_fake->relay_log.description_event_for_exec=
1 by brian
clean slate
58
      new Format_description_log_event(4);
51.1.49 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
59
    have_fd_event= false;
1 by brian
clean slate
60
  }
61
62
  const char *error= 0;
63
  char *buf= (char *) my_malloc(decoded_len, MYF(MY_WME));
64
  Log_event *ev = 0;
65
66
  /*
67
    Out of memory check
68
  */
520.1.22 by Brian Aker
Second pass of thd cleanup
69
  if (!(session->rli_fake &&
70
        session->rli_fake->relay_log.description_event_for_exec &&
1 by brian
clean slate
71
        buf))
72
  {
73
    my_error(ER_OUTOFMEMORY, MYF(0), 1);  /* needed 1 bytes */
74
    goto end;
75
  }
76
520.1.22 by Brian Aker
Second pass of thd cleanup
77
  session->rli_fake->sql_session= session;
78
  session->rli_fake->no_storage= true;
1 by brian
clean slate
79
520.1.22 by Brian Aker
Second pass of thd cleanup
80
  for (char const *strptr= session->lex->comment.str ;
81
       strptr < session->lex->comment.str + session->lex->comment.length ; )
1 by brian
clean slate
82
  {
83
    char const *endptr= 0;
84
    int bytes_decoded= base64_decode(strptr, coded_len, buf, &endptr);
85
86
    if (bytes_decoded < 0)
87
    {
88
      my_error(ER_BASE64_DECODE_ERROR, MYF(0));
89
      goto end;
90
    }
91
    else if (bytes_decoded == 0)
92
      break; // If no bytes where read, the string contained only whitespace
93
51.1.49 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
94
    assert(bytes_decoded > 0);
95
    assert(endptr > strptr);
1 by brian
clean slate
96
    coded_len-= endptr - strptr;
97
    strptr= endptr;
98
99
    /*
100
      Now we have one or more events stored in the buffer. The size of
101
      the buffer is computed based on how much base64-encoded data
102
      there were, so there should be ample space for the data (maybe
103
      even too much, since a statement can consist of a considerable
104
      number of events).
105
106
      TODO: Switch to use a stream-based base64 encoder/decoder in
107
      order to be able to read exactly what is necessary.
108
    */
109
110
    /*
111
      Now we start to read events of the buffer, until there are no
112
      more.
113
    */
114
    for (char *bufptr= buf ; bytes_decoded > 0 ; )
115
    {
116
      /*
117
        Checking that the first event in the buffer is not truncated.
118
      */
307 by Brian Aker
Minor cleanups around ulong in kernel.
119
      uint32_t event_len= uint4korr(bufptr + EVENT_LEN_OFFSET);
1 by brian
clean slate
120
      if (bytes_decoded < EVENT_LEN_OFFSET || (uint) bytes_decoded < event_len)
121
      {
122
        my_error(ER_SYNTAX_ERROR, MYF(0));
123
        goto end;
124
      }
125
126
      /*
127
        If we have not seen any Format_description_event, then we must
128
        see one; it is the only statement that can be read in base64
129
        without a prior Format_description_event.
130
      */
131
      if (!have_fd_event)
132
      {
133
        int type = bufptr[EVENT_TYPE_OFFSET];
134
        if (type == FORMAT_DESCRIPTION_EVENT || type == START_EVENT_V3)
51.1.49 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
135
          have_fd_event= true;
1 by brian
clean slate
136
        else
137
        {
138
          my_error(ER_NO_FORMAT_DESCRIPTION_EVENT_BEFORE_BINLOG_STATEMENT,
139
                   MYF(0), Log_event::get_type_str((Log_event_type)type));
140
          goto end;
141
        }
142
      }
143
144
      ev= Log_event::read_log_event(bufptr, event_len, &error,
520.1.22 by Brian Aker
Second pass of thd cleanup
145
                                    session->rli_fake->relay_log.
1 by brian
clean slate
146
                                      description_event_for_exec);
147
148
      if (!ev)
149
      {
150
        /*
151
          This could actually be an out-of-memory, but it is more likely
152
          causes by a bad statement
153
        */
154
        my_error(ER_SYNTAX_ERROR, MYF(0));
155
        goto end;
156
      }
157
158
      bytes_decoded -= event_len;
159
      bufptr += event_len;
160
520.1.22 by Brian Aker
Second pass of thd cleanup
161
      ev->session= session;
1 by brian
clean slate
162
      /*
163
        We go directly to the application phase, since we don't need
164
        to check if the event shall be skipped or not.
165
166
        Neither do we have to update the log positions, since that is
167
        not used at all: the rli_fake instance is used only for error
168
        reporting.
169
      */
520.1.22 by Brian Aker
Second pass of thd cleanup
170
      if (apply_event_and_update_pos(ev, session, session->rli_fake, false))
1 by brian
clean slate
171
      {
172
        /*
173
          TODO: Maybe a better error message since the BINLOG statement
174
          now contains several events.
175
        */
176
        my_error(ER_UNKNOWN_ERROR, MYF(0), "Error executing BINLOG statement");
177
        goto end;
178
      }
179
180
      /*
181
        Format_description_log_event should not be deleted because it
182
        will be used to read info about the relay log's format; it
183
        will be deleted when the SQL thread does not need it,
184
        i.e. when this thread terminates.
185
      */
186
      if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
187
        delete ev;
188
      ev= 0;
189
    }
190
  }
191
520.1.22 by Brian Aker
Second pass of thd cleanup
192
  my_ok(session);
1 by brian
clean slate
193
194
end:
520.1.22 by Brian Aker
Second pass of thd cleanup
195
  session->rli_fake->clear_tables_to_lock();
477 by Monty Taylor
Removed my_free(). It turns out that it had been def'd to ignore the flags passed to it in the second arg anyway. Gotta love that.
196
  free(buf);
51.1.49 by Jay Pipes
Removed/replaced DBUG symbols and standardized TRUE/FALSE
197
  return;
1 by brian
clean slate
198
}