~drizzle-trunk/drizzle/development

« back to all changes in this revision

Viewing changes to server/sql_binlog.cc

Removed/replaced DBUG symbols and TRUE/FALSE

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
16
#include "mysql_priv.h"
 
17
#include "rpl_rli.h"
 
18
#include "base64.h"
 
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
 
 
31
void mysql_client_binlog_statement(THD* thd)
 
32
{
 
33
  size_t coded_len= thd->lex->comment.length + 1;
 
34
  size_t decoded_len= base64_needed_decoded_length(coded_len);
 
35
  assert(coded_len > 0);
 
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
  */
 
46
  my_bool have_fd_event= true;
 
47
  if (!thd->rli_fake)
 
48
  {
 
49
    thd->rli_fake= new Relay_log_info;
 
50
#ifdef HAVE_purify
 
51
    thd->rli_fake->is_fake= true;
 
52
#endif
 
53
    have_fd_event= false;
 
54
  }
 
55
  if (thd->rli_fake && !thd->rli_fake->relay_log.description_event_for_exec)
 
56
  {
 
57
    thd->rli_fake->relay_log.description_event_for_exec=
 
58
      new Format_description_log_event(4);
 
59
    have_fd_event= false;
 
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
  */
 
69
  if (!(thd->rli_fake &&
 
70
        thd->rli_fake->relay_log.description_event_for_exec &&
 
71
        buf))
 
72
  {
 
73
    my_error(ER_OUTOFMEMORY, MYF(0), 1);  /* needed 1 bytes */
 
74
    goto end;
 
75
  }
 
76
 
 
77
  thd->rli_fake->sql_thd= thd;
 
78
  thd->rli_fake->no_storage= true;
 
79
 
 
80
  for (char const *strptr= thd->lex->comment.str ;
 
81
       strptr < thd->lex->comment.str + thd->lex->comment.length ; )
 
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
 
 
94
    assert(bytes_decoded > 0);
 
95
    assert(endptr > strptr);
 
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
      */
 
119
      ulong event_len= uint4korr(bufptr + EVENT_LEN_OFFSET);
 
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)
 
135
          have_fd_event= true;
 
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,
 
145
                                    thd->rli_fake->relay_log.
 
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
 
 
161
      ev->thd= thd;
 
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
      */
 
170
#if !defined(MYSQL_CLIENT) && defined(HAVE_REPLICATION)
 
171
      if (apply_event_and_update_pos(ev, thd, thd->rli_fake, false))
 
172
      {
 
173
        /*
 
174
          TODO: Maybe a better error message since the BINLOG statement
 
175
          now contains several events.
 
176
        */
 
177
        my_error(ER_UNKNOWN_ERROR, MYF(0), "Error executing BINLOG statement");
 
178
        goto end;
 
179
      }
 
180
#endif
 
181
 
 
182
      /*
 
183
        Format_description_log_event should not be deleted because it
 
184
        will be used to read info about the relay log's format; it
 
185
        will be deleted when the SQL thread does not need it,
 
186
        i.e. when this thread terminates.
 
187
      */
 
188
      if (ev->get_type_code() != FORMAT_DESCRIPTION_EVENT)
 
189
        delete ev;
 
190
      ev= 0;
 
191
    }
 
192
  }
 
193
 
 
194
  my_ok(thd);
 
195
 
 
196
end:
 
197
  thd->rli_fake->clear_tables_to_lock();
 
198
  my_free(buf, MYF(MY_ALLOW_ZERO_PTR));
 
199
  return;
 
200
}