1 /*
2 Copyright (c) 2000, 2014, Oracle and/or its affiliates.
3 Copyright (c) 2009, 2020, MariaDB
4
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; version 2 of the License.
8
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1335 USA
17 */
18
19 /*
20
21 TODO: print the catalog (some USE catalog.db ????).
22
23 Standalone program to read a MySQL binary log (or relay log).
24
25 Should be able to read any file of these categories, even with
26 --start-position.
27 An important fact: the Format_desc event of the log is at most the 3rd event
28 of the log; if it is the 3rd then there is this combination:
29 Format_desc_of_slave, Rotate_of_master, Format_desc_of_master.
30 */
31
32 #define MYSQL_CLIENT
33 #undef MYSQL_SERVER
34 #define TABLE TABLE_CLIENT
35 /* This hack is here to avoid adding COMPRESSED data types to libmariadb. */
36 #define MYSQL_TYPE_TIME2 MYSQL_TYPE_TIME2,MYSQL_TYPE_BLOB_COMPRESSED=140,MYSQL_TYPE_VARCHAR_COMPRESSED=141
37 #include "client_priv.h"
38 #undef MYSQL_TYPE_TIME2
39 #include <my_time.h>
40 #include <sslopt-vars.h>
41 /* That one is necessary for defines of OPTION_NO_FOREIGN_KEY_CHECKS etc */
42 #include "sql_priv.h"
43 #include "sql_basic_types.h"
44 #include <atomic>
45 #include "log_event.h"
46 #include "compat56.h"
47 #include "sql_common.h"
48 #include "my_dir.h"
49 #include <welcome_copyright_notice.h> // ORACLE_WELCOME_COPYRIGHT_NOTICE
50 #include "sql_string.h" // needed for Rpl_filter
51 #include "sql_list.h" // needed for Rpl_filter
52 #include "rpl_filter.h"
53
54 #include "mysqld.h"
55
56 #include <algorithm>
57
58 #define my_net_write ma_net_write
59 #define net_flush ma_net_flush
60 #define cli_safe_read mysql_net_read_packet
61 #define my_net_read ma_net_read
62 extern "C" unsigned char *mysql_net_store_length(unsigned char *packet, size_t length);
63 #define net_store_length mysql_net_store_length
64
65 Rpl_filter *binlog_filter= 0;
66
67 #define BIN_LOG_HEADER_SIZE 4
68 #define PROBE_HEADER_LEN (EVENT_LEN_OFFSET+4)
69
70 /* Needed for Rpl_filter */
71 CHARSET_INFO* system_charset_info= &my_charset_utf8_general_ci;
72
73 /* Needed for Flashback */
74 DYNAMIC_ARRAY binlog_events; // Storing the events output string
75 DYNAMIC_ARRAY events_in_stmt; // Storing the events that in one statement
76 String stop_event_string; // Storing the STOP_EVENT output string
77
78 char server_version[SERVER_VERSION_LENGTH];
79 ulong server_id = 0;
80
81 // needed by net_serv.c
82 ulong bytes_sent = 0L, bytes_received = 0L;
83 ulong mysqld_net_retry_count = 10L;
84 ulong open_files_limit;
85 ulong opt_binlog_rows_event_max_size;
86 ulonglong test_flags = 0;
87 ulong opt_binlog_rows_event_max_encoded_size= MAX_MAX_ALLOWED_PACKET;
88 static uint opt_protocol= 0;
89 static FILE *result_file;
90 static char *result_file_name= 0;
91 static const char *output_prefix= "";
92
93 #ifndef DBUG_OFF
94 static const char *default_dbug_option = "d:t:o,/tmp/mysqlbinlog.trace";
95 const char *current_dbug_option= default_dbug_option;
96 #endif
97 static const char *load_groups[]=
98 { "mysqlbinlog", "mariadb-binlog", "client", "client-server", "client-mariadb",
99 0 };
100
101 static void error(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
102 static void warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2);
103
104 static bool one_database=0, one_table=0, to_last_remote_log= 0, disable_log_bin= 0;
105 static bool opt_hexdump= 0, opt_version= 0;
106 const char *base64_output_mode_names[]=
107 {"NEVER", "AUTO", "ALWAYS", "UNSPEC", "DECODE-ROWS", NullS};
108 TYPELIB base64_output_mode_typelib=
109 { array_elements(base64_output_mode_names) - 1, "",
110 base64_output_mode_names, NULL };
111 static enum_base64_output_mode opt_base64_output_mode= BASE64_OUTPUT_UNSPEC;
112 static char *opt_base64_output_mode_str= NullS;
113 static char* database= 0;
114 static char* table= 0;
115 static my_bool force_opt= 0, short_form= 0, remote_opt= 0;
116 static my_bool print_row_count= 0, print_row_event_positions= 0;
117 static my_bool print_row_count_used= 0, print_row_event_positions_used= 0;
118 static my_bool debug_info_flag, debug_check_flag;
119 static my_bool force_if_open_opt= 1;
120 static my_bool opt_raw_mode= 0, opt_stop_never= 0;
121 static ulong opt_stop_never_slave_server_id= 0;
122 static my_bool opt_verify_binlog_checksum= 1;
123 static ulonglong offset = 0;
124 static char* host = 0;
125 static int port= 0;
126 static uint my_end_arg;
127 static const char* sock= 0;
128 static char *opt_plugindir= 0, *opt_default_auth= 0;
129
130 static char* user = 0;
131 static char* pass = 0;
132 static char *charset= 0;
133
134 static uint verbose= 0;
135
136 static ulonglong start_position, stop_position;
137 #define start_position_mot ((my_off_t)start_position)
138 #define stop_position_mot ((my_off_t)stop_position)
139
140 static char *start_datetime_str, *stop_datetime_str;
141 static my_time_t start_datetime= 0, stop_datetime= MY_TIME_T_MAX;
142 static ulonglong rec_count= 0;
143 static MYSQL* mysql = NULL;
144 static const char* dirname_for_local_load= 0;
145 static bool opt_skip_annotate_row_events= 0;
146
147 static my_bool opt_flashback;
148 #ifdef WHEN_FLASHBACK_REVIEW_READY
149 static my_bool opt_flashback_review;
150 static char *flashback_review_dbname, *flashback_review_tablename;
151 #endif
152
153 /**
154 Pointer to the Format_description_log_event of the currently active binlog.
155
156 This will be changed each time a new Format_description_log_event is
157 found in the binlog. It is finally destroyed at program termination.
158 */
159 static Format_description_log_event* glob_description_event= NULL;
160
161 /**
162 Exit status for functions in this file.
163 */
164 enum Exit_status {
165 /** No error occurred and execution should continue. */
166 OK_CONTINUE= 0,
167 /** An error occurred and execution should stop. */
168 ERROR_STOP,
169 /** No error occurred but execution should stop. */
170 OK_STOP,
171 /** No error occurred - end of file reached. */
172 OK_EOF,
173 };
174
175 /**
176 Pointer to the last read Annotate_rows_log_event. Having read an
177 Annotate_rows event, we should not print it immediatedly because all
178 subsequent rbr events can be filtered away, and have to keep it for a while.
179 Also because of that when reading a remote Annotate event we have to keep
180 its binary log representation in a separately allocated buffer.
181 */
182 static Annotate_rows_log_event *annotate_event= NULL;
183
free_annotate_event()184 static void free_annotate_event()
185 {
186 if (annotate_event)
187 {
188 delete annotate_event;
189 annotate_event= 0;
190 }
191 }
192
read_remote_annotate_event(uchar * net_buf,ulong event_len,const char ** error_msg)193 Log_event* read_remote_annotate_event(uchar* net_buf, ulong event_len,
194 const char **error_msg)
195 {
196 uchar *event_buf;
197 Log_event* event;
198
199 if (!(event_buf= (uchar*) my_malloc(event_len + 1, MYF(MY_WME))))
200 {
201 error("Out of memory");
202 return 0;
203 }
204
205 memcpy(event_buf, net_buf, event_len);
206 event_buf[event_len]= 0;
207
208 if (!(event= Log_event::read_log_event((const char*) event_buf, event_len,
209 error_msg, glob_description_event,
210 opt_verify_binlog_checksum)))
211 {
212 my_free(event_buf);
213 return 0;
214 }
215 /*
216 Ensure the event->temp_buf is pointing to the allocated buffer.
217 (TRUE = free temp_buf on the event deletion)
218 */
219 event->register_temp_buf((char*)event_buf, TRUE);
220
221 return event;
222 }
223
keep_annotate_event(Annotate_rows_log_event * event)224 void keep_annotate_event(Annotate_rows_log_event* event)
225 {
226 free_annotate_event();
227 annotate_event= event;
228 }
229
print_annotate_event(PRINT_EVENT_INFO * print_event_info)230 bool print_annotate_event(PRINT_EVENT_INFO *print_event_info)
231 {
232 bool error= 0;
233 if (annotate_event)
234 {
235 annotate_event->print(result_file, print_event_info);
236 free_annotate_event();
237 }
238 return error;
239 }
240
241 static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *, const char*);
242 static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *, const char*);
243 static Exit_status dump_log_entries(const char* logname);
244 static Exit_status safe_connect();
245
246
247 class Load_log_processor
248 {
249 char target_dir_name[FN_REFLEN];
250 size_t target_dir_name_len;
251
252 /*
253 When we see first event corresponding to some LOAD DATA statement in
254 binlog, we create temporary file to store data to be loaded.
255 We add name of this file to file_names array using its file_id as index.
256 If we have Create_file event (i.e. we have binary log in pre-5.0.3
257 format) we also store save event object to be able which is needed to
258 emit LOAD DATA statement when we will meet Exec_load_data event.
259 If we have Begin_load_query event we simply store 0 in
260 File_name_record::event field.
261 */
262 struct File_name_record
263 {
264 char *fname;
265 Create_file_log_event *event;
266 };
267 /*
268 @todo Should be a map (e.g., a hash map), not an array. With the
269 present implementation, the number of elements in this array is
270 about the number of files loaded since the server started, which
271 may be big after a few years. We should be able to use existing
272 library data structures for this. /Sven
273 */
274 DYNAMIC_ARRAY file_names;
275
276 /**
277 Looks for a non-existing filename by adding a numerical suffix to
278 the given base name, creates the generated file, and returns the
279 filename by modifying the filename argument.
280
281 @param[in,out] filename Base filename
282
283 @param[in,out] file_name_end Pointer to last character of
284 filename. The numerical suffix will be written to this position.
285 Note that there must be a least five bytes of allocated memory
286 after file_name_end.
287
288 @retval -1 Error (can't find new filename).
289 @retval >=0 Found file.
290 */
create_unique_file(char * filename,char * file_name_end)291 File create_unique_file(char *filename, char *file_name_end)
292 {
293 File res;
294 /* If we have to try more than 1000 times, something is seriously wrong */
295 for (uint version= 0; version<1000; version++)
296 {
297 sprintf(file_name_end,"-%x",version);
298 if ((res= my_create(filename,0,
299 O_CREAT|O_EXCL|O_BINARY|O_WRONLY,MYF(0)))!=-1)
300 return res;
301 }
302 return -1;
303 }
304
305 public:
Load_log_processor()306 Load_log_processor() {}
~Load_log_processor()307 ~Load_log_processor() {}
308
init()309 int init()
310 {
311 return my_init_dynamic_array(&file_names, sizeof(File_name_record),
312 100, 100, MYF(0));
313 }
314
init_by_dir_name(const char * dir)315 void init_by_dir_name(const char *dir)
316 {
317 target_dir_name_len= (convert_dirname(target_dir_name, dir, NullS) -
318 target_dir_name);
319 }
init_by_cur_dir()320 void init_by_cur_dir()
321 {
322 if (my_getwd(target_dir_name,sizeof(target_dir_name),MYF(MY_WME)))
323 exit(1);
324 target_dir_name_len= strlen(target_dir_name);
325 }
destroy()326 void destroy()
327 {
328 File_name_record *ptr= (File_name_record *)file_names.buffer;
329 File_name_record *end= ptr + file_names.elements;
330 for (; ptr < end; ptr++)
331 {
332 if (ptr->fname)
333 {
334 my_free(ptr->fname);
335 delete ptr->event;
336 bzero((char *)ptr, sizeof(File_name_record));
337 }
338 }
339
340 delete_dynamic(&file_names);
341 }
342
343 /**
344 Obtain Create_file event for LOAD DATA statement by its file_id
345 and remove it from this Load_log_processor's list of events.
346
347 Checks whether we have already seen a Create_file_log_event with
348 the given file_id. If yes, returns a pointer to the event and
349 removes the event from array describing active temporary files.
350 From this moment, the caller is responsible for freeing the memory
351 occupied by the event.
352
353 @param[in] file_id File id identifying LOAD DATA statement.
354
355 @return Pointer to Create_file_log_event, or NULL if we have not
356 seen any Create_file_log_event with this file_id.
357 */
grab_event(uint file_id)358 Create_file_log_event *grab_event(uint file_id)
359 {
360 File_name_record *ptr;
361 Create_file_log_event *res;
362
363 if (file_id >= file_names.elements)
364 return 0;
365 ptr= dynamic_element(&file_names, file_id, File_name_record*);
366 if ((res= ptr->event))
367 bzero((char *)ptr, sizeof(File_name_record));
368 return res;
369 }
370
371 /**
372 Obtain file name of temporary file for LOAD DATA statement by its
373 file_id and remove it from this Load_log_processor's list of events.
374
375 @param[in] file_id Identifier for the LOAD DATA statement.
376
377 Checks whether we have already seen Begin_load_query event for
378 this file_id. If yes, returns the file name of the corresponding
379 temporary file and removes the filename from the array of active
380 temporary files. From this moment, the caller is responsible for
381 freeing the memory occupied by this name.
382
383 @return String with the name of the temporary file, or NULL if we
384 have not seen any Begin_load_query_event with this file_id.
385 */
grab_fname(uint file_id)386 char *grab_fname(uint file_id)
387 {
388 File_name_record *ptr;
389 char *res= 0;
390
391 if (file_id >= file_names.elements)
392 return 0;
393 ptr= dynamic_element(&file_names, file_id, File_name_record*);
394 if (!ptr->event)
395 {
396 res= ptr->fname;
397 bzero((char *)ptr, sizeof(File_name_record));
398 }
399 return res;
400 }
401 Exit_status process(Create_file_log_event *ce);
402 Exit_status process(Begin_load_query_log_event *ce);
403 Exit_status process(Append_block_log_event *ae);
404 File prepare_new_file_for_old_format(Load_log_event *le, char *filename);
405 Exit_status load_old_format_file(NET* net, const char *server_fname,
406 uint server_fname_len, File file);
407 Exit_status process_first_event(const char *bname, size_t blen,
408 const uchar *block,
409 size_t block_len, uint file_id,
410 Create_file_log_event *ce);
411 };
412
413
414 /**
415 Creates and opens a new temporary file in the directory specified by previous call to init_by_dir_name() or init_by_cur_dir().
416
417 @param[in] le The basename of the created file will start with the
418 basename of the file pointed to by this Load_log_event.
419
420 @param[out] filename Buffer to save the filename in.
421
422 @return File handle >= 0 on success, -1 on error.
423 */
prepare_new_file_for_old_format(Load_log_event * le,char * filename)424 File Load_log_processor::prepare_new_file_for_old_format(Load_log_event *le,
425 char *filename)
426 {
427 size_t len;
428 char *tail;
429 File file;
430
431 fn_format(filename, le->fname, target_dir_name, "", MY_REPLACE_DIR);
432 len= strlen(filename);
433 tail= filename + len;
434
435 if ((file= create_unique_file(filename,tail)) < 0)
436 {
437 error("Could not construct local filename %s.",filename);
438 return -1;
439 }
440
441 le->set_fname_outside_temp_buf(filename,len+strlen(tail));
442
443 return file;
444 }
445
446
447 /**
448 Reads a file from a server and saves it locally.
449
450 @param[in,out] net The server to read from.
451
452 @param[in] server_fname The name of the file that the server should
453 read.
454
455 @param[in] server_fname_len The length of server_fname.
456
457 @param[in,out] file The file to write to.
458
459 @retval ERROR_STOP An error occurred - the program should terminate.
460 @retval OK_CONTINUE No error, the program should continue.
461 */
load_old_format_file(NET * net,const char * server_fname,uint server_fname_len,File file)462 Exit_status Load_log_processor::load_old_format_file(NET* net,
463 const char*server_fname,
464 uint server_fname_len,
465 File file)
466 {
467 uchar buf[FN_REFLEN+1];
468 buf[0] = 0;
469 memcpy(buf + 1, server_fname, server_fname_len + 1);
470 if (my_net_write(net, buf, server_fname_len +2) || net_flush(net))
471 {
472 error("Failed requesting the remote dump of %s.", server_fname);
473 return ERROR_STOP;
474 }
475
476 for (;;)
477 {
478 ulong packet_len = my_net_read(net);
479 if (packet_len == 0)
480 {
481 if (my_net_write(net, (uchar*) "", 0) || net_flush(net))
482 {
483 error("Failed sending the ack packet.");
484 return ERROR_STOP;
485 }
486 /*
487 we just need to send something, as the server will read but
488 not examine the packet - this is because mysql_load() sends
489 an OK when it is done
490 */
491 break;
492 }
493 else if (packet_len == packet_error)
494 {
495 error("Failed reading a packet during the dump of %s.", server_fname);
496 return ERROR_STOP;
497 }
498
499 if (packet_len > UINT_MAX)
500 {
501 error("Illegal length of packet read from net.");
502 return ERROR_STOP;
503 }
504 if (my_write(file, (uchar*) net->read_pos,
505 (uint) packet_len, MYF(MY_WME|MY_NABP)))
506 return ERROR_STOP;
507 }
508
509 return OK_CONTINUE;
510 }
511
512
513 /**
514 Process the first event in the sequence of events representing a
515 LOAD DATA statement.
516
517 Creates a temporary file to be used in LOAD DATA and writes first
518 block of data to it. Registers its file name (and optional
519 Create_file event) in the array of active temporary files.
520
521 @param bname Base name for temporary file to be created.
522 @param blen Base name length.
523 @param block First block of data to be loaded.
524 @param block_len First block length.
525 @param file_id Identifies the LOAD DATA statement.
526 @param ce Pointer to Create_file event object if we are processing
527 this type of event.
528
529 @retval ERROR_STOP An error occurred - the program should terminate.
530 @retval OK_CONTINUE No error, the program should continue.
531 */
process_first_event(const char * bname,size_t blen,const uchar * block,size_t block_len,uint file_id,Create_file_log_event * ce)532 Exit_status Load_log_processor::process_first_event(const char *bname,
533 size_t blen,
534 const uchar *block,
535 size_t block_len,
536 uint file_id,
537 Create_file_log_event *ce)
538 {
539 size_t full_len= target_dir_name_len + blen + 9 + 9 + 1;
540 Exit_status retval= OK_CONTINUE;
541 char *fname, *ptr;
542 File file;
543 File_name_record rec;
544 DBUG_ENTER("Load_log_processor::process_first_event");
545
546 if (!(fname= (char*) my_malloc(full_len,MYF(MY_WME))))
547 {
548 error("Out of memory.");
549 delete ce;
550 DBUG_RETURN(ERROR_STOP);
551 }
552
553 memcpy(fname, target_dir_name, target_dir_name_len);
554 ptr= fname + target_dir_name_len;
555 memcpy(ptr,bname,blen);
556 ptr+= blen;
557 ptr+= sprintf(ptr, "-%x", file_id);
558
559 if ((file= create_unique_file(fname,ptr)) < 0)
560 {
561 error("Could not construct local filename %s%s.",
562 target_dir_name,bname);
563 my_free(fname);
564 delete ce;
565 DBUG_RETURN(ERROR_STOP);
566 }
567
568 rec.fname= fname;
569 rec.event= ce;
570
571 /*
572 fname is freed in process_event()
573 after Execute_load_query_log_event or Execute_load_log_event
574 will have been processed, otherwise in Load_log_processor::destroy()
575 */
576 if (set_dynamic(&file_names, (uchar*)&rec, file_id))
577 {
578 error("Out of memory.");
579 my_free(fname);
580 delete ce;
581 DBUG_RETURN(ERROR_STOP);
582 }
583
584 if (ce)
585 ce->set_fname_outside_temp_buf(fname, strlen(fname));
586
587 if (my_write(file, (uchar*)block, block_len, MYF(MY_WME|MY_NABP)))
588 {
589 error("Failed writing to file.");
590 retval= ERROR_STOP;
591 }
592 if (my_close(file, MYF(MY_WME)))
593 {
594 error("Failed closing file.");
595 retval= ERROR_STOP;
596 }
597 DBUG_RETURN(retval);
598 }
599
600
601 /**
602 Process the given Create_file_log_event.
603
604 @see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
605
606 @param ce Create_file_log_event to process.
607
608 @retval ERROR_STOP An error occurred - the program should terminate.
609 @retval OK_CONTINUE No error, the program should continue.
610 */
process(Create_file_log_event * ce)611 Exit_status Load_log_processor::process(Create_file_log_event *ce)
612 {
613 const char *bname= ce->fname + dirname_length(ce->fname);
614 size_t blen= ce->fname_len - (bname-ce->fname);
615
616 return process_first_event(bname, blen, ce->block, ce->block_len,
617 ce->file_id, ce);
618 }
619
620
621 /**
622 Process the given Begin_load_query_log_event.
623
624 @see Load_log_processor::process_first_event(const char*,uint,const char*,uint,uint,Create_file_log_event*)
625
626 @param ce Begin_load_query_log_event to process.
627
628 @retval ERROR_STOP An error occurred - the program should terminate.
629 @retval OK_CONTINUE No error, the program should continue.
630 */
process(Begin_load_query_log_event * blqe)631 Exit_status Load_log_processor::process(Begin_load_query_log_event *blqe)
632 {
633 return process_first_event("SQL_LOAD_MB", 11, blqe->block, blqe->block_len,
634 blqe->file_id, 0);
635 }
636
637
638 /**
639 Process the given Append_block_log_event.
640
641 Appends the chunk of the file contents specified by the event to the
642 file created by a previous Begin_load_query_log_event or
643 Create_file_log_event.
644
645 If the file_id for the event does not correspond to any file
646 previously registered through a Begin_load_query_log_event or
647 Create_file_log_event, this member function will print a warning and
648 return OK_CONTINUE. It is safe to return OK_CONTINUE, because no
649 query will be written for this event. We should not print an error
650 and fail, since the missing file_id could be because a (valid)
651 --start-position has been specified after the Begin/Create event but
652 before this Append event.
653
654 @param ae Append_block_log_event to process.
655
656 @retval ERROR_STOP An error occurred - the program should terminate.
657
658 @retval OK_CONTINUE No error, the program should continue.
659 */
process(Append_block_log_event * ae)660 Exit_status Load_log_processor::process(Append_block_log_event *ae)
661 {
662 DBUG_ENTER("Load_log_processor::process");
663 const char* fname= ((ae->file_id < file_names.elements) ?
664 dynamic_element(&file_names, ae->file_id,
665 File_name_record*)->fname : 0);
666
667 if (fname)
668 {
669 File file;
670 Exit_status retval= OK_CONTINUE;
671 if (((file= my_open(fname,
672 O_APPEND|O_BINARY|O_WRONLY,MYF(MY_WME))) < 0))
673 {
674 error("Failed opening file %s", fname);
675 DBUG_RETURN(ERROR_STOP);
676 }
677 if (my_write(file,(uchar*)ae->block,ae->block_len,MYF(MY_WME|MY_NABP)))
678 {
679 error("Failed writing to file %s", fname);
680 retval= ERROR_STOP;
681 }
682 if (my_close(file,MYF(MY_WME)))
683 {
684 error("Failed closing file %s", fname);
685 retval= ERROR_STOP;
686 }
687 DBUG_RETURN(retval);
688 }
689
690 /*
691 There is no Create_file event (a bad binlog or a big
692 --start-position). Assuming it's a big --start-position, we just do
693 nothing and print a warning.
694 */
695 warning("Ignoring Append_block as there is no "
696 "Create_file event for file_id: %u", ae->file_id);
697 DBUG_RETURN(OK_CONTINUE);
698 }
699
700
701 static Load_log_processor load_processor;
702
703
704 /**
705 Replace windows-style backslashes by forward slashes so it can be
706 consumed by the mysql client, which requires Unix path.
707
708 @todo This is only useful under windows, so may be ifdef'ed out on
709 other systems. /Sven
710
711 @todo If a Create_file_log_event contains a filename with a
712 backslash (valid under unix), then we have problems under windows.
713 /Sven
714
715 @param[in,out] fname Filename to modify. The filename is modified
716 in-place.
717 */
convert_path_to_forward_slashes(char * fname)718 static void convert_path_to_forward_slashes(char *fname)
719 {
720 while (*fname)
721 {
722 if (*fname == '\\')
723 *fname= '/';
724 fname++;
725 }
726 }
727
728
729 /**
730 Indicates whether the given database should be filtered out,
731 according to the --database=X option.
732
733 @param log_dbname Name of database.
734
735 @return nonzero if the database with the given name should be
736 filtered out, 0 otherwise.
737 */
shall_skip_database(const char * log_dbname)738 static bool shall_skip_database(const char *log_dbname)
739 {
740 return one_database &&
741 (log_dbname != NULL) &&
742 strcmp(log_dbname, database);
743 }
744
745
746 /**
747 Print "use <db>" statement when current db is to be changed.
748
749 We have to control emitting USE statements according to rewrite-db options.
750 We have to do it here (see process_event() below) and to suppress
751 producing USE statements by corresponding log event print-functions.
752 */
753
754 static void
print_use_stmt(PRINT_EVENT_INFO * pinfo,const Query_log_event * ev)755 print_use_stmt(PRINT_EVENT_INFO* pinfo, const Query_log_event *ev)
756 {
757 const char* db= ev->db;
758 const size_t db_len= ev->db_len;
759
760 // pinfo->db is the current db.
761 // If current db is the same as required db, do nothing.
762 if ((ev->flags & LOG_EVENT_SUPPRESS_USE_F) || !db ||
763 !memcmp(pinfo->db, db, db_len + 1))
764 return;
765
766 // Current db and required db are different.
767 // Check for rewrite rule for required db. (Note that in a rewrite rule
768 // neither db_from nor db_to part can be empty).
769 size_t len_to= 0;
770 const char *db_to= binlog_filter->get_rewrite_db(db, &len_to);
771
772 // If there is no rewrite rule for db (in this case len_to is left = 0),
773 // printing of the corresponding USE statement is left for log event
774 // print-function.
775 if (!len_to)
776 return;
777
778 // In case of rewrite rule print USE statement for db_to
779 my_fprintf(result_file, "use %`s%s\n", db_to, pinfo->delimiter);
780
781 // Copy the *original* db to pinfo to suppress emitting
782 // of USE stmts by log_event print-functions.
783 memcpy(pinfo->db, db, db_len + 1);
784 }
785
786
787 /**
788 Print "SET skip_replication=..." statement when needed.
789
790 Not all servers support this (only MariaDB from some version on). So we
791 mark the SET to only execute from the version of MariaDB that supports it,
792 and also only output it if we actually see events with the flag set, to not
793 get spurious errors on MySQL@Oracle servers of higher version that do not
794 support the flag.
795
796 So we start out assuming @@skip_replication is 0, and only output a SET
797 statement when it changes.
798 */
799 static void
print_skip_replication_statement(PRINT_EVENT_INFO * pinfo,const Log_event * ev)800 print_skip_replication_statement(PRINT_EVENT_INFO *pinfo, const Log_event *ev)
801 {
802 bool cur_val;
803
804 cur_val= (ev->flags & LOG_EVENT_SKIP_REPLICATION_F) != 0;
805 if (cur_val == pinfo->skip_replication)
806 return; /* Not changed. */
807 fprintf(result_file, "/*!50521 SET skip_replication=%d*/%s\n",
808 cur_val, pinfo->delimiter);
809 pinfo->skip_replication= cur_val;
810 }
811
812 /**
813 Indicates whether the given table should be filtered out,
814 according to the --table=X option.
815
816 @param log_tblname Name of table.
817
818 @return nonzero if the table with the given name should be
819 filtered out, 0 otherwise.
820 */
shall_skip_table(const char * log_tblname)821 static bool shall_skip_table(const char *log_tblname)
822 {
823 return one_table &&
824 (log_tblname != NULL) &&
825 strcmp(log_tblname, table);
826 }
827
828
829 /**
830 Prints the given event in base64 format.
831
832 The header is printed to the head cache and the body is printed to
833 the body cache of the print_event_info structure. This allows all
834 base64 events corresponding to the same statement to be joined into
835 one BINLOG statement.
836
837 @param[in] ev Log_event to print.
838 @param[in,out] result_file FILE to which the output will be written.
839 @param[in,out] print_event_info Parameters and context state
840 determining how to print.
841
842 @retval ERROR_STOP An error occurred - the program should terminate.
843 @retval OK_CONTINUE No error, the program should continue.
844 */
845 static Exit_status
write_event_header_and_base64(Log_event * ev,FILE * result_file,PRINT_EVENT_INFO * print_event_info)846 write_event_header_and_base64(Log_event *ev, FILE *result_file,
847 PRINT_EVENT_INFO *print_event_info)
848 {
849 IO_CACHE *head= &print_event_info->head_cache;
850 IO_CACHE *body= &print_event_info->body_cache;
851 DBUG_ENTER("write_event_header_and_base64");
852
853 /* Write header and base64 output to cache */
854 if (ev->print_header(head, print_event_info, FALSE))
855 DBUG_RETURN(ERROR_STOP);
856
857 DBUG_ASSERT(print_event_info->base64_output_mode == BASE64_OUTPUT_ALWAYS);
858
859 if (ev->print_base64(body, print_event_info,
860 print_event_info->base64_output_mode !=
861 BASE64_OUTPUT_DECODE_ROWS))
862 DBUG_RETURN(ERROR_STOP);
863
864 /* Read data from cache and write to result file */
865 if (copy_event_cache_to_file_and_reinit(head, result_file) ||
866 copy_event_cache_to_file_and_reinit(body, result_file))
867 {
868 error("Error writing event to file.");
869 DBUG_RETURN(ERROR_STOP);
870 }
871 DBUG_RETURN(OK_CONTINUE);
872 }
873
874
print_base64(PRINT_EVENT_INFO * print_event_info,Log_event * ev)875 static bool print_base64(PRINT_EVENT_INFO *print_event_info, Log_event *ev)
876 {
877 /*
878 These events must be printed in base64 format, if printed.
879 base64 format requires a FD event to be safe, so if no FD
880 event has been printed, we give an error. Except if user
881 passed --short-form, because --short-form disables printing
882 row events.
883 */
884
885 if (!print_event_info->printed_fd_event && !short_form &&
886 opt_base64_output_mode != BASE64_OUTPUT_DECODE_ROWS &&
887 opt_base64_output_mode != BASE64_OUTPUT_NEVER)
888 {
889 const char* type_str= ev->get_type_str();
890 error("malformed binlog: it does not contain any "
891 "Format_description_log_event. Found a %s event, which "
892 "is not safe to process without a "
893 "Format_description_log_event.",
894 type_str);
895 return 1;
896 }
897
898 return ev->print(result_file, print_event_info);
899 }
900
901
print_row_event(PRINT_EVENT_INFO * print_event_info,Log_event * ev,ulonglong table_id,bool is_stmt_end)902 static bool print_row_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
903 ulonglong table_id, bool is_stmt_end)
904 {
905 Table_map_log_event *ignored_map=
906 print_event_info->m_table_map_ignored.get_table(table_id);
907 bool skip_event= (ignored_map != NULL);
908 char ll_buff[21];
909 bool result= 0;
910
911 if (opt_flashback)
912 {
913 Rows_log_event *e= (Rows_log_event*) ev;
914 // The last Row_log_event will be the first event in Flashback
915 if (is_stmt_end)
916 e->clear_flags(Rows_log_event::STMT_END_F);
917 // The first Row_log_event will be the last event in Flashback
918 if (events_in_stmt.elements == 0)
919 e->set_flags(Rows_log_event::STMT_END_F);
920 // Update the temp_buf
921 e->update_flags();
922
923 if (insert_dynamic(&events_in_stmt, (uchar *) &ev))
924 {
925 error("Out of memory: can't allocate memory to store the flashback events.");
926 exit(1);
927 }
928 }
929
930 /*
931 end of statement check:
932 i) destroy/free ignored maps
933 ii) if skip event
934 a) since we are skipping the last event,
935 append END-MARKER(') to body cache (if required)
936
937 b) flush cache now
938 */
939 if (is_stmt_end)
940 {
941 /*
942 Now is safe to clear ignored map (clear_tables will also
943 delete original table map events stored in the map).
944 */
945 if (print_event_info->m_table_map_ignored.count() > 0)
946 print_event_info->m_table_map_ignored.clear_tables();
947
948 /*
949 If there is a kept Annotate event and all corresponding
950 rbr-events were filtered away, the Annotate event was not
951 freed and it is just the time to do it.
952 */
953 free_annotate_event();
954
955 /*
956 One needs to take into account an event that gets
957 filtered but was last event in the statement. If this is
958 the case, previous rows events that were written into
959 IO_CACHEs still need to be copied from cache to
960 result_file (as it would happen in ev->print(...) if
961 event was not skipped).
962 */
963 if (skip_event)
964 {
965 // append END-MARKER(') with delimiter
966 IO_CACHE *const body_cache= &print_event_info->body_cache;
967 if (my_b_tell(body_cache))
968 my_b_printf(body_cache, "'%s\n", print_event_info->delimiter);
969
970 // flush cache
971 if ((copy_event_cache_to_file_and_reinit(&print_event_info->head_cache,
972 result_file) ||
973 copy_event_cache_to_file_and_reinit(&print_event_info->body_cache,
974 result_file) ||
975 copy_event_cache_to_file_and_reinit(&print_event_info->tail_cache,
976 result_file)))
977 return 1;
978 }
979 }
980
981 /* skip the event check */
982 if (skip_event)
983 return 0;
984
985 if (!opt_flashback)
986 result= print_base64(print_event_info, ev);
987 else
988 {
989 if (is_stmt_end)
990 {
991 Log_event *e= NULL;
992
993 // Print the row_event from the last one to the first one
994 for (uint i= events_in_stmt.elements; i > 0; --i)
995 {
996 e= *(dynamic_element(&events_in_stmt, i - 1, Log_event**));
997 result= result || print_base64(print_event_info, e);
998 }
999 // Copy all output into the Log_event
1000 ev->output_buf.copy(e->output_buf);
1001 // Delete Log_event
1002 for (uint i= 0; i < events_in_stmt.elements-1; ++i)
1003 {
1004 e= *(dynamic_element(&events_in_stmt, i, Log_event**));
1005 delete e;
1006 }
1007 reset_dynamic(&events_in_stmt);
1008 }
1009 }
1010
1011 if (is_stmt_end && !result)
1012 {
1013 if (print_event_info->print_row_count)
1014 fprintf(result_file, "# Number of rows: %s\n",
1015 llstr(print_event_info->row_events, ll_buff));
1016 print_event_info->row_events= 0;
1017 }
1018 return result;
1019 }
1020
1021
1022 /**
1023 Print the given event, and either delete it or delegate the deletion
1024 to someone else.
1025
1026 The deletion may be delegated in two cases: (1) the event is a
1027 Format_description_log_event, and is saved in
1028 glob_description_event; (2) the event is a Create_file_log_event,
1029 and is saved in load_processor.
1030
1031 @param[in,out] print_event_info Parameters and context state
1032 determining how to print.
1033 @param[in] ev Log_event to process.
1034 @param[in] pos Offset from beginning of binlog file.
1035 @param[in] logname Name of input binlog.
1036
1037 @retval ERROR_STOP An error occurred - the program should terminate.
1038 @retval OK_CONTINUE No error, the program should continue.
1039 @retval OK_STOP No error, but the end of the specified range of
1040 events to process has been reached and the program should terminate.
1041 */
process_event(PRINT_EVENT_INFO * print_event_info,Log_event * ev,my_off_t pos,const char * logname)1042 Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev,
1043 my_off_t pos, const char *logname)
1044 {
1045 char ll_buff[21];
1046 Log_event_type ev_type= ev->get_type_code();
1047 my_bool destroy_evt= TRUE;
1048 DBUG_ENTER("process_event");
1049 Exit_status retval= OK_CONTINUE;
1050 IO_CACHE *const head= &print_event_info->head_cache;
1051
1052 /* Bypass flashback settings to event */
1053 ev->is_flashback= opt_flashback;
1054 #ifdef WHEN_FLASHBACK_REVIEW_READY
1055 ev->need_flashback_review= opt_flashback_review;
1056 #endif
1057
1058 /*
1059 Format events are not concerned by --offset and such, we always need to
1060 read them to be able to process the wanted events.
1061 */
1062 if (((rec_count >= offset) &&
1063 (ev->when >= start_datetime)) ||
1064 (ev_type == FORMAT_DESCRIPTION_EVENT))
1065 {
1066 if (ev_type != FORMAT_DESCRIPTION_EVENT)
1067 {
1068 /*
1069 We have found an event after start_datetime, from now on print
1070 everything (in case the binlog has timestamps increasing and
1071 decreasing, we do this to avoid cutting the middle).
1072 */
1073 start_datetime= 0;
1074 offset= 0; // print everything and protect against cycling rec_count
1075 /*
1076 Skip events according to the --server-id flag. However, don't
1077 skip format_description or rotate events, because they they
1078 are really "global" events that are relevant for the entire
1079 binlog, even if they have a server_id. Also, we have to read
1080 the format_description event so that we can parse subsequent
1081 events.
1082 */
1083 if (ev_type != ROTATE_EVENT &&
1084 server_id && (server_id != ev->server_id))
1085 goto end;
1086 }
1087 if ((ev->when >= stop_datetime)
1088 || (pos >= stop_position_mot))
1089 {
1090 /* end the program */
1091 retval= OK_STOP;
1092 goto end;
1093 }
1094 if (print_row_event_positions)
1095 fprintf(result_file, "# at %s\n",llstr(pos,ll_buff));
1096
1097 if (!opt_hexdump)
1098 print_event_info->hexdump_from= 0; /* Disabled */
1099 else
1100 print_event_info->hexdump_from= pos;
1101
1102 print_event_info->base64_output_mode= opt_base64_output_mode;
1103
1104 DBUG_PRINT("debug", ("event_type: %s", ev->get_type_str()));
1105
1106 switch (ev_type) {
1107 case QUERY_EVENT:
1108 case QUERY_COMPRESSED_EVENT:
1109 {
1110 Query_log_event *qe= (Query_log_event*)ev;
1111 if (!qe->is_trans_keyword())
1112 {
1113 if (shall_skip_database(qe->db))
1114 goto end;
1115 }
1116 else
1117 {
1118 /*
1119 In case the event for one of these statements is obtained
1120 from binary log 5.0, make it compatible with 5.1
1121 */
1122 qe->flags|= LOG_EVENT_SUPPRESS_USE_F;
1123 }
1124 print_use_stmt(print_event_info, qe);
1125 if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
1126 {
1127 if ((retval= write_event_header_and_base64(ev, result_file,
1128 print_event_info)) !=
1129 OK_CONTINUE)
1130 goto end;
1131 }
1132 else
1133 {
1134 print_skip_replication_statement(print_event_info, ev);
1135 if (ev->print(result_file, print_event_info))
1136 goto err;
1137 }
1138 if (head->error == -1)
1139 goto err;
1140 break;
1141 }
1142
1143 case CREATE_FILE_EVENT:
1144 {
1145 Create_file_log_event* ce= (Create_file_log_event*)ev;
1146 /*
1147 We test if this event has to be ignored. If yes, we don't save
1148 this event; this will have the good side-effect of ignoring all
1149 related Append_block and Exec_load.
1150 Note that Load event from 3.23 is not tested.
1151 */
1152 if (shall_skip_database(ce->db))
1153 goto end; // Next event
1154 /*
1155 We print the event, but with a leading '#': this is just to inform
1156 the user of the original command; the command we want to execute
1157 will be a derivation of this original command (we will change the
1158 filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT'
1159 below.
1160 */
1161 if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
1162 {
1163 if ((retval= write_event_header_and_base64(ce, result_file,
1164 print_event_info)) !=
1165 OK_CONTINUE)
1166 goto end;
1167 }
1168 else
1169 {
1170 print_skip_replication_statement(print_event_info, ev);
1171 if (ce->print(result_file, print_event_info, TRUE))
1172 goto err;
1173 }
1174 // If this binlog is not 3.23 ; why this test??
1175 if (glob_description_event->binlog_version >= 3)
1176 {
1177 /*
1178 transfer the responsibility for destroying the event to
1179 load_processor
1180 */
1181 ev= NULL;
1182 if ((retval= load_processor.process(ce)) != OK_CONTINUE)
1183 goto end;
1184 }
1185 break;
1186 }
1187
1188 case APPEND_BLOCK_EVENT:
1189 /*
1190 Append_block_log_events can safely print themselves even if
1191 the subsequent call load_processor.process fails, because the
1192 output of Append_block_log_event::print is only a comment.
1193 */
1194 if (ev->print(result_file, print_event_info))
1195 goto err;
1196 if ((retval= load_processor.process((Append_block_log_event*) ev)) !=
1197 OK_CONTINUE)
1198 goto end;
1199 break;
1200
1201 case EXEC_LOAD_EVENT:
1202 {
1203 if (ev->print(result_file, print_event_info))
1204 goto err;
1205 Execute_load_log_event *exv= (Execute_load_log_event*)ev;
1206 Create_file_log_event *ce= load_processor.grab_event(exv->file_id);
1207 /*
1208 if ce is 0, it probably means that we have not seen the Create_file
1209 event (a bad binlog, or most probably --start-position is after the
1210 Create_file event). Print a warning comment.
1211 */
1212 if (ce)
1213 {
1214 bool error;
1215 /*
1216 We must not convert earlier, since the file is used by
1217 my_open() in Load_log_processor::append().
1218 */
1219 convert_path_to_forward_slashes((char*) ce->fname);
1220 error= ce->print(result_file, print_event_info, TRUE);
1221 my_free((void*)ce->fname);
1222 delete ce;
1223 if (error)
1224 goto err;
1225 }
1226 else
1227 warning("Ignoring Execute_load_log_event as there is no "
1228 "Create_file event for file_id: %u", exv->file_id);
1229 break;
1230 }
1231 case FORMAT_DESCRIPTION_EVENT:
1232 delete glob_description_event;
1233 glob_description_event= (Format_description_log_event*) ev;
1234 destroy_evt= 0;
1235 print_event_info->common_header_len=
1236 glob_description_event->common_header_len;
1237 if (ev->print(result_file, print_event_info))
1238 goto err;
1239 if (!remote_opt)
1240 {
1241 ev->free_temp_buf(); // free memory allocated in dump_local_log_entries
1242 }
1243 else
1244 {
1245 /*
1246 disassociate but not free dump_remote_log_entries time memory
1247 */
1248 ev->temp_buf= 0;
1249 }
1250 /*
1251 We don't want this event to be deleted now, so let's hide it (I
1252 (Guilhem) should later see if this triggers a non-serious Valgrind
1253 error). Not serious error, because we will free description_event
1254 later.
1255 */
1256 ev= 0;
1257 if (!force_if_open_opt &&
1258 (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F))
1259 {
1260 error("Attempting to dump binlog '%s', which was not closed properly. "
1261 "Most probably, mysqld is still writing it, or it crashed. "
1262 "Rerun with --force-if-open to ignore this problem.", logname);
1263 DBUG_RETURN(ERROR_STOP);
1264 }
1265 break;
1266 case BEGIN_LOAD_QUERY_EVENT:
1267 if (ev->print(result_file, print_event_info))
1268 goto err;
1269 if ((retval= load_processor.process((Begin_load_query_log_event*) ev)) !=
1270 OK_CONTINUE)
1271 goto end;
1272 break;
1273 case EXECUTE_LOAD_QUERY_EVENT:
1274 {
1275 Execute_load_query_log_event *exlq= (Execute_load_query_log_event*)ev;
1276 char *fname= load_processor.grab_fname(exlq->file_id);
1277
1278 if (!shall_skip_database(exlq->db))
1279 {
1280 print_use_stmt(print_event_info, exlq);
1281 if (fname)
1282 {
1283 convert_path_to_forward_slashes(fname);
1284 print_skip_replication_statement(print_event_info, ev);
1285 if (exlq->print(result_file, print_event_info, fname))
1286 {
1287 my_free(fname);
1288 goto err;
1289 }
1290 }
1291 else
1292 warning("Ignoring Execute_load_query since there is no "
1293 "Begin_load_query event for file_id: %u", exlq->file_id);
1294 }
1295 my_free(fname);
1296 break;
1297 }
1298 case ANNOTATE_ROWS_EVENT:
1299 if (!opt_skip_annotate_row_events)
1300 {
1301 /*
1302 We don't print Annotate event just now because all subsequent
1303 rbr-events can be filtered away. Instead we'll keep the event
1304 till it will be printed together with the first not filtered
1305 away Table map or the last rbr will be processed.
1306 */
1307 keep_annotate_event((Annotate_rows_log_event*) ev);
1308 destroy_evt= FALSE;
1309 }
1310 break;
1311 case TABLE_MAP_EVENT:
1312 {
1313 Table_map_log_event *map= ((Table_map_log_event *)ev);
1314 if (shall_skip_database(map->get_db_name()) ||
1315 shall_skip_table(map->get_table_name()))
1316 {
1317 print_event_info->m_table_map_ignored.set_table(map->get_table_id(), map);
1318 destroy_evt= FALSE;
1319 goto end;
1320 }
1321 #ifdef WHEN_FLASHBACK_REVIEW_READY
1322 /* Create review table for Flashback */
1323 if (opt_flashback_review)
1324 {
1325 // Check if the table was already created?
1326 Table_map_log_event *exist_table;
1327 exist_table= print_event_info->m_table_map.get_table(map->get_table_id());
1328
1329 if (!exist_table)
1330 {
1331
1332 MYSQL *conn;
1333 MYSQL_RES *res;
1334 MYSQL_ROW row;
1335 char tmp_sql[8096];
1336 int tmp_sql_offset;
1337
1338 conn = mysql_init(NULL);
1339 if (!mysql_real_connect(conn, host, user, pass,
1340 map->get_db_name(), port, sock, 0))
1341 {
1342 fprintf(stderr, "%s\n", mysql_error(conn));
1343 exit(1);
1344 }
1345
1346 if (mysql_query(conn, "SET group_concat_max_len=10000;"))
1347 {
1348 fprintf(stderr, "%s\n", mysql_error(conn));
1349 exit(1);
1350 }
1351
1352 memset(tmp_sql, 0, sizeof(tmp_sql));
1353 sprintf(tmp_sql, " "
1354 "SELECT Group_concat(cols) "
1355 "FROM (SELECT 'op_type char(1)' cols "
1356 " UNION ALL "
1357 " SELECT Concat('`', column_name, '_old` ', column_type, ' ', "
1358 " IF(character_set_name IS NOT NULL, "
1359 " Concat('character set ', character_set_name, ' '), ' '), "
1360 " IF(collation_name IS NOT NULL, "
1361 " Concat('collate ', collation_name, ' '), ' ')) cols "
1362 " FROM information_schema.columns "
1363 " WHERE table_schema = '%s' "
1364 " AND table_name = '%s' "
1365 " UNION ALL "
1366 " SELECT Concat('`', column_name, '_new` ', column_type, ' ', "
1367 " IF(character_set_name IS NOT NULL, "
1368 " Concat('character set ', character_set_name, ' '), ' '), "
1369 " IF(collation_name IS NOT NULL, "
1370 " Concat('collate ', collation_name, ' '), ' ')) cols "
1371 " FROM information_schema.columns "
1372 " WHERE table_schema = '%s' "
1373 " AND table_name = '%s') tmp;",
1374 map->get_db_name(), map->get_table_name(),
1375 map->get_db_name(), map->get_table_name());
1376
1377 if (mysql_query(conn, tmp_sql))
1378 {
1379 fprintf(stderr, "%s\n", mysql_error(conn));
1380 exit(1);
1381 }
1382 res = mysql_use_result(conn);
1383 if ((row = mysql_fetch_row(res)) != NULL) // only one row
1384 {
1385 if (flashback_review_dbname)
1386 {
1387 ev->set_flashback_review_dbname(flashback_review_dbname);
1388 }
1389 else
1390 {
1391 ev->set_flashback_review_dbname(map->get_db_name());
1392 }
1393 if (flashback_review_tablename)
1394 {
1395 ev->set_flashback_review_tablename(flashback_review_tablename);
1396 }
1397 else
1398 {
1399 memset(tmp_sql, 0, sizeof(tmp_sql));
1400 sprintf(tmp_sql, "__%s", map->get_table_name());
1401 ev->set_flashback_review_tablename(tmp_sql);
1402 }
1403 memset(tmp_sql, 0, sizeof(tmp_sql));
1404 tmp_sql_offset= sprintf(tmp_sql, "CREATE TABLE IF NOT EXISTS");
1405 tmp_sql_offset+= sprintf(tmp_sql + tmp_sql_offset, " `%s`.`%s` (%s) %s",
1406 ev->get_flashback_review_dbname(),
1407 ev->get_flashback_review_tablename(),
1408 row[0],
1409 print_event_info->delimiter);
1410 }
1411 fprintf(result_file, "%s\n", tmp_sql);
1412 mysql_free_result(res);
1413 mysql_close(conn);
1414 }
1415 else
1416 {
1417 char tmp_str[128];
1418
1419 if (flashback_review_dbname)
1420 ev->set_flashback_review_dbname(flashback_review_dbname);
1421 else
1422 ev->set_flashback_review_dbname(map->get_db_name());
1423
1424 if (flashback_review_tablename)
1425 ev->set_flashback_review_tablename(flashback_review_tablename);
1426 else
1427 {
1428 memset(tmp_str, 0, sizeof(tmp_str));
1429 sprintf(tmp_str, "__%s", map->get_table_name());
1430 ev->set_flashback_review_tablename(tmp_str);
1431 }
1432 }
1433 }
1434 #endif
1435
1436 /*
1437 The Table map is to be printed, so it's just the time when we may
1438 print the kept Annotate event (if there is any).
1439 print_annotate_event() also deletes the kept Annotate event.
1440 */
1441 if (print_annotate_event(print_event_info))
1442 goto err;
1443
1444 size_t len_to= 0;
1445 const char* db_to= binlog_filter->get_rewrite_db(map->get_db_name(), &len_to);
1446 if (len_to && map->rewrite_db(db_to, len_to, glob_description_event))
1447 {
1448 error("Could not rewrite database name");
1449 goto err;
1450 }
1451 if (print_base64(print_event_info, ev))
1452 goto err;
1453 if (opt_flashback)
1454 reset_dynamic(&events_in_stmt);
1455 break;
1456 }
1457 case WRITE_ROWS_EVENT:
1458 case DELETE_ROWS_EVENT:
1459 case UPDATE_ROWS_EVENT:
1460 case WRITE_ROWS_EVENT_V1:
1461 case UPDATE_ROWS_EVENT_V1:
1462 case DELETE_ROWS_EVENT_V1:
1463 case WRITE_ROWS_COMPRESSED_EVENT:
1464 case DELETE_ROWS_COMPRESSED_EVENT:
1465 case UPDATE_ROWS_COMPRESSED_EVENT:
1466 case WRITE_ROWS_COMPRESSED_EVENT_V1:
1467 case UPDATE_ROWS_COMPRESSED_EVENT_V1:
1468 case DELETE_ROWS_COMPRESSED_EVENT_V1:
1469 {
1470 Rows_log_event *e= (Rows_log_event*) ev;
1471 bool is_stmt_end= e->get_flags(Rows_log_event::STMT_END_F);
1472 if (!print_event_info->found_row_event)
1473 {
1474 print_event_info->found_row_event= 1;
1475 print_event_info->row_events= 0;
1476 }
1477 if (print_row_event(print_event_info, ev, e->get_table_id(),
1478 e->get_flags(Rows_log_event::STMT_END_F)))
1479 goto err;
1480 DBUG_PRINT("info", ("is_stmt_end: %d", (int) is_stmt_end));
1481 if (is_stmt_end)
1482 print_event_info->found_row_event= 0;
1483 else if (opt_flashback)
1484 destroy_evt= FALSE;
1485 break;
1486 }
1487 case PRE_GA_WRITE_ROWS_EVENT:
1488 case PRE_GA_DELETE_ROWS_EVENT:
1489 case PRE_GA_UPDATE_ROWS_EVENT:
1490 {
1491 Old_rows_log_event *e= (Old_rows_log_event*) ev;
1492 bool is_stmt_end= e->get_flags(Rows_log_event::STMT_END_F);
1493 if (print_row_event(print_event_info, ev, e->get_table_id(),
1494 e->get_flags(Old_rows_log_event::STMT_END_F)))
1495 goto err;
1496 DBUG_PRINT("info", ("is_stmt_end: %d", (int) is_stmt_end));
1497 if (!is_stmt_end && opt_flashback)
1498 destroy_evt= FALSE;
1499 break;
1500 }
1501 case START_ENCRYPTION_EVENT:
1502 glob_description_event->start_decryption((Start_encryption_log_event*)ev);
1503 /* fall through */
1504 default:
1505 print_skip_replication_statement(print_event_info, ev);
1506 if (ev->print(result_file, print_event_info))
1507 goto err;
1508 }
1509 }
1510
1511 goto end;
1512
1513 err:
1514 retval= ERROR_STOP;
1515 end:
1516 rec_count++;
1517
1518 DBUG_PRINT("info", ("end event processing"));
1519 /*
1520 Destroy the log_event object.
1521 MariaDB MWL#36: mainline does this:
1522 If reading from a remote host,
1523 set the temp_buf to NULL so that memory isn't freed twice.
1524 We no longer do that, we use Rpl_filter::event_owns_temp_buf instead.
1525 */
1526 if (ev)
1527 {
1528 /* Holding event output if needed */
1529 if (!ev->output_buf.is_empty())
1530 {
1531 LEX_STRING tmp_str;
1532
1533 tmp_str.length= ev->output_buf.length();
1534 tmp_str.str= ev->output_buf.release();
1535
1536 if (opt_flashback)
1537 {
1538 if (ev_type == STOP_EVENT)
1539 stop_event_string.reset(tmp_str.str, tmp_str.length, tmp_str.length,
1540 &my_charset_bin);
1541 else
1542 {
1543 if (insert_dynamic(&binlog_events, (uchar *) &tmp_str))
1544 {
1545 error("Out of memory: can't allocate memory to store the flashback events.");
1546 exit(1);
1547 }
1548 }
1549 }
1550 else
1551 {
1552 my_fwrite(result_file, (const uchar *) tmp_str.str, tmp_str.length,
1553 MYF(MY_NABP));
1554 fflush(result_file);
1555 my_free(tmp_str.str);
1556 }
1557 }
1558
1559 if (destroy_evt) /* destroy it later if not set (ignored table map) */
1560 delete ev;
1561 }
1562 DBUG_PRINT("exit",("return: %d", retval));
1563 DBUG_RETURN(retval);
1564 }
1565
1566
1567 static struct my_option my_options[] =
1568 {
1569 {"help", '?', "Display this help and exit.",
1570 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1571 {"base64-output", OPT_BASE64_OUTPUT_MODE,
1572 /* 'unspec' is not mentioned because it is just a placeholder. */
1573 "Determine when the output statements should be base64-encoded BINLOG "
1574 "statements: 'never' doesn't print binlog row events and should not be "
1575 "used when directing output to a MariaDB master; "
1576 "'decode-rows' decodes row events into commented SQL statements if the "
1577 "--verbose option is also given; "
1578 "'auto' prints base64 only when necessary (i.e., for row-based events and "
1579 "format description events); "
1580 "'always' prints base64 whenever possible. "
1581 "--base64-output with no 'name' argument is equivalent to "
1582 "--base64-output=always and is also deprecated. If no "
1583 "--base64-output[=name] option is given at all, the default is 'auto'.",
1584 &opt_base64_output_mode_str, &opt_base64_output_mode_str,
1585 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1586 /*
1587 mysqlbinlog needs charsets knowledge, to be able to convert a charset
1588 number found in binlog to a charset name (to be able to print things
1589 like this:
1590 SET @`a`:=_cp850 0x4DFC6C6C6572 COLLATE `cp850_general_ci`;
1591 */
1592 {"character-sets-dir", OPT_CHARSETS_DIR,
1593 "Directory for character set files.", &charsets_dir,
1594 &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1595 {"database", 'd', "List entries for just this database (local log only).",
1596 &database, &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
1597 0, 0, 0, 0, 0, 0},
1598 #ifndef DBUG_OFF
1599 {"debug", '#', "Output debug log.", ¤t_dbug_option,
1600 ¤t_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1601 #endif
1602 {"debug-check", OPT_DEBUG_CHECK, "Check memory and open file usage at exit .",
1603 &debug_check_flag, &debug_check_flag, 0,
1604 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1605 {"debug-info", OPT_DEBUG_INFO, "Print some debug info at exit.",
1606 &debug_info_flag, &debug_info_flag,
1607 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1608 {"default_auth", OPT_DEFAULT_AUTH,
1609 "Default authentication client-side plugin to use.",
1610 &opt_default_auth, &opt_default_auth, 0,
1611 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1612 {"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
1613 "enabled --to-last-log and are sending the output to the same MariaDB server. "
1614 "This way you could avoid an endless loop. You would also like to use it "
1615 "when restoring after a crash to avoid duplication of the statements you "
1616 "already have. NOTE: you will need a SUPER privilege to use this option.",
1617 &disable_log_bin, &disable_log_bin, 0, GET_BOOL,
1618 NO_ARG, 0, 0, 0, 0, 0, 0},
1619 {"flashback", 'B', "Flashback feature can rollback you committed data to a special time point.",
1620 #ifdef WHEN_FLASHBACK_REVIEW_READY
1621 "before Flashback feature writing a row, original row can insert to review-dbname.review-tablename,"
1622 "and mysqlbinlog will login mysql by user(-u) and password(-p) and host(-h).",
1623 #endif
1624 &opt_flashback, &opt_flashback, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1625 0, 0},
1626 {"force-if-open", 'F', "Force if binlog was not closed properly.",
1627 &force_if_open_opt, &force_if_open_opt, 0, GET_BOOL, NO_ARG,
1628 1, 0, 0, 0, 0, 0},
1629 {"force-read", 'f', "Force reading unknown binlog events.",
1630 &force_opt, &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1631 0, 0},
1632 {"hexdump", 'H', "Augment output with hexadecimal and ASCII event dump.",
1633 &opt_hexdump, &opt_hexdump, 0, GET_BOOL, NO_ARG,
1634 0, 0, 0, 0, 0, 0},
1635 {"host", 'h', "Get the binlog from server.", &host, &host,
1636 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1637 {"local-load", 'l', "Prepare local temporary files for LOAD DATA INFILE in the specified directory.",
1638 &dirname_for_local_load, &dirname_for_local_load, 0,
1639 GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1640 {"offset", 'o', "Skip the first N entries.", &offset, &offset,
1641 0, GET_ULL, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1642 {"password", 'p', "Password to connect to remote server.",
1643 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
1644 {"plugin_dir", OPT_PLUGIN_DIR, "Directory for client-side plugins.",
1645 &opt_plugindir, &opt_plugindir, 0,
1646 GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1647 {"port", 'P', "Port number to use for connection or 0 for default to, in "
1648 "order of preference, my.cnf, $MYSQL_TCP_PORT, "
1649 #if MYSQL_PORT_DEFAULT == 0
1650 "/etc/services, "
1651 #endif
1652 "built-in default (" STRINGIFY_ARG(MYSQL_PORT) ").",
1653 &port, &port, 0, GET_INT, REQUIRED_ARG,
1654 0, 0, 0, 0, 0, 0},
1655 {"protocol", OPT_MYSQL_PROTOCOL,
1656 "The protocol to use for connection (tcp, socket, pipe).",
1657 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1658 {"read-from-remote-server", 'R', "Read binary logs from a MariaDB server.",
1659 &remote_opt, &remote_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1660 0, 0},
1661 {"raw", 0, "Requires -R. Output raw binlog data instead of SQL "
1662 "statements. Output files named after server logs.",
1663 &opt_raw_mode, &opt_raw_mode, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1664 0, 0},
1665 {"result-file", 'r', "Direct output to a given file. With --raw this is a "
1666 "prefix for the file names.",
1667 &result_file_name, &result_file_name, 0, GET_STR, REQUIRED_ARG,
1668 0, 0, 0, 0, 0, 0},
1669 #ifdef WHEN_FLASHBACK_REVIEW_READY
1670 {"review", opt_flashback_review, "Print review sql in output file.",
1671 &opt_flashback_review, &opt_flashback_review, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1672 0, 0},
1673 {"review-dbname", opt_flashback_flashback_review_dbname,
1674 "Writing flashback original row data into this db",
1675 &flashback_review_dbname, &flashback_review_dbname,
1676 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1677 {"review-tablename", opt_flashback_flashback_review_tablename,
1678 "Writing flashback original row data into this table",
1679 &flashback_review_tablename, &flashback_review_tablename,
1680 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1681 #endif
1682 {"print-row-count", OPT_PRINT_ROW_COUNT,
1683 "Print row counts for each row events",
1684 &print_row_count, &print_row_count, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0,
1685 0, 0},
1686 {"print-row-event-positions", OPT_PRINT_ROW_EVENT_POSITIONS,
1687 "Print row event positions",
1688 &print_row_event_positions, &print_row_event_positions, 0, GET_BOOL,
1689 NO_ARG, 1, 0, 0, 0, 0, 0},
1690 {"server-id", 0,
1691 "Extract only binlog entries created by the server having the given id.",
1692 &server_id, &server_id, 0, GET_ULONG,
1693 REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1694 {"set-charset", OPT_SET_CHARSET,
1695 "Add 'SET NAMES character_set' to the output.", &charset,
1696 &charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1697 {"short-form", 's', "Just show regular queries: no extra info, no "
1698 "row-based events and no row counts. This is mainly for testing only, "
1699 "and should not be used to feed to the MariaDB server. "
1700 "If you want to just suppress base64-output, you can instead "
1701 "use --base64-output=never",
1702 &short_form, &short_form, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
1703 0, 0},
1704 {"socket", 'S', "The socket file to use for connection.",
1705 &sock, &sock, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
1706 0, 0},
1707 #include <sslopt-longopts.h>
1708 {"start-datetime", OPT_START_DATETIME,
1709 "Start reading the binlog at first event having a datetime equal or "
1710 "posterior to the argument; the argument must be a date and time "
1711 "in the local time zone, in any format accepted by the MariaDB server "
1712 "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1713 "(you should probably use quotes for your shell to set it properly).",
1714 &start_datetime_str, &start_datetime_str,
1715 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1716 {"start-position", 'j',
1717 "Start reading the binlog at position N. Applies to the first binlog "
1718 "passed on the command line.",
1719 &start_position, &start_position, 0, GET_ULL,
1720 REQUIRED_ARG, BIN_LOG_HEADER_SIZE, BIN_LOG_HEADER_SIZE,
1721 /*
1722 COM_BINLOG_DUMP accepts only 4 bytes for the position
1723 so remote log reading has lower limit.
1724 */
1725 (ulonglong)(0xffffffffffffffffULL), 0, 0, 0},
1726 {"stop-datetime", OPT_STOP_DATETIME,
1727 "Stop reading the binlog at first event having a datetime equal or "
1728 "posterior to the argument; the argument must be a date and time "
1729 "in the local time zone, in any format accepted by the MariaDB server "
1730 "for DATETIME and TIMESTAMP types, for example: 2004-12-25 11:25:56 "
1731 "(you should probably use quotes for your shell to set it properly).",
1732 &stop_datetime_str, &stop_datetime_str,
1733 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1734 {"stop-never", 0, "Wait for more data from the server "
1735 "instead of stopping at the end of the last log. Implies --to-last-log.",
1736 &opt_stop_never, &opt_stop_never, 0,
1737 GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1738 {"stop-never-slave-server-id", 0,
1739 "The slave server_id used for --read-from-remote-server --stop-never.",
1740 &opt_stop_never_slave_server_id, &opt_stop_never_slave_server_id, 0,
1741 GET_ULONG, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1742 {"stop-position", OPT_STOP_POSITION,
1743 "Stop reading the binlog at position N. Applies to the last binlog "
1744 "passed on the command line.",
1745 &stop_position, &stop_position, 0, GET_ULL,
1746 REQUIRED_ARG, (longlong)(~(my_off_t)0), BIN_LOG_HEADER_SIZE,
1747 (ulonglong)(~(my_off_t)0), 0, 0, 0},
1748 {"table", 'T', "List entries for just this table (local log only).",
1749 &table, &table, 0, GET_STR_ALLOC, REQUIRED_ARG,
1750 0, 0, 0, 0, 0, 0},
1751 {"to-last-log", 't', "Requires -R. Will not stop at the end of the \
1752 requested binlog but rather continue printing until the end of the last \
1753 binlog of the MariaDB server. If you send the output to the same MariaDB server, \
1754 that may lead to an endless loop.",
1755 &to_last_remote_log, &to_last_remote_log, 0, GET_BOOL,
1756 NO_ARG, 0, 0, 0, 0, 0, 0},
1757 {"user", 'u', "Connect to the remote server as username.",
1758 &user, &user, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0,
1759 0, 0},
1760 {"verbose", 'v', "Reconstruct SQL statements out of row events. "
1761 "-v -v adds comments on column data types.",
1762 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
1763 {"version", 'V', "Print version and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
1764 0, 0, 0, 0, 0},
1765 {"open_files_limit", OPT_OPEN_FILES_LIMIT,
1766 "Used to reserve file descriptors for use by this program.",
1767 &open_files_limit, &open_files_limit, 0, GET_ULONG,
1768 REQUIRED_ARG, MY_NFILE, 8, OS_FILE_LIMIT, 0, 1, 0},
1769 {"binlog-row-event-max-size", 0,
1770 "The maximum size of a row-based binary log event in bytes. Rows will be "
1771 "grouped into events smaller than this size if possible. "
1772 "This value must be a multiple of 256.",
1773 &opt_binlog_rows_event_max_size, &opt_binlog_rows_event_max_size, 0,
1774 GET_ULONG, REQUIRED_ARG, UINT_MAX, 256, ULONG_MAX, 0, 256, 0},
1775 #ifndef DBUG_OFF
1776 {"debug-binlog-row-event-max-encoded-size", 0,
1777 "The maximum size of base64-encoded rows-event in one BINLOG pseudo-query "
1778 "instance. When the computed actual size exceeds the limit "
1779 "the BINLOG's argument string is fragmented in two.",
1780 &opt_binlog_rows_event_max_encoded_size,
1781 &opt_binlog_rows_event_max_encoded_size, 0,
1782 GET_ULONG, REQUIRED_ARG, UINT_MAX/4, 256, ULONG_MAX, 0, 256, 0},
1783 #endif
1784 {"verify-binlog-checksum", 'c', "Verify checksum binlog events.",
1785 (uchar**) &opt_verify_binlog_checksum, (uchar**) &opt_verify_binlog_checksum,
1786 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1787 {"rewrite-db", OPT_REWRITE_DB,
1788 "Updates to a database with a different name than the original. \
1789 Example: rewrite-db='from->to'.",
1790 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
1791 {"skip-annotate-row-events", OPT_SKIP_ANNOTATE_ROWS_EVENTS,
1792 "Don't print Annotate_rows events stored in the binary log.",
1793 (uchar**) &opt_skip_annotate_row_events,
1794 (uchar**) &opt_skip_annotate_row_events,
1795 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
1796 {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
1797 };
1798
1799
1800 /**
1801 Auxiliary function used by error() and warning().
1802
1803 Prints the given text (normally "WARNING: " or "ERROR: "), followed
1804 by the given vprintf-style string, followed by a newline.
1805
1806 @param format Printf-style format string.
1807 @param args List of arguments for the format string.
1808 @param msg Text to print before the string.
1809 */
error_or_warning(const char * format,va_list args,const char * msg)1810 static void error_or_warning(const char *format, va_list args, const char *msg)
1811 {
1812 if (result_file)
1813 fflush(result_file);
1814 fprintf(stderr, "%s: ", msg);
1815 vfprintf(stderr, format, args);
1816 fprintf(stderr, "\n");
1817 fflush(stderr);
1818 }
1819
1820 /**
1821 Prints a message to stderr, prefixed with the text "ERROR: " and
1822 suffixed with a newline.
1823
1824 @param format Printf-style format string, followed by printf
1825 varargs.
1826 */
error(const char * format,...)1827 static void error(const char *format,...)
1828 {
1829 va_list args;
1830 va_start(args, format);
1831 error_or_warning(format, args, "ERROR");
1832 va_end(args);
1833 }
1834
1835
1836 /**
1837 This function is used in log_event.cc to report errors.
1838
1839 @param format Printf-style format string, followed by printf
1840 varargs.
1841 */
sql_print_error(const char * format,...)1842 static void sql_print_error(const char *format,...)
1843 {
1844 va_list args;
1845 va_start(args, format);
1846 error_or_warning(format, args, "ERROR");
1847 va_end(args);
1848 }
1849
1850 /**
1851 Prints a message to stderr, prefixed with the text "WARNING: " and
1852 suffixed with a newline.
1853
1854 @param format Printf-style format string, followed by printf
1855 varargs.
1856 */
warning(const char * format,...)1857 static void warning(const char *format,...)
1858 {
1859 va_list args;
1860 va_start(args, format);
1861 error_or_warning(format, args, "WARNING");
1862 va_end(args);
1863 }
1864
1865 /**
1866 Frees memory for global variables in this file.
1867 */
cleanup()1868 static void cleanup()
1869 {
1870 DBUG_ENTER("cleanup");
1871 my_free(pass);
1872 my_free(database);
1873 my_free(table);
1874 my_free(host);
1875 my_free(user);
1876 my_free(const_cast<char*>(dirname_for_local_load));
1877 my_free(start_datetime_str);
1878 my_free(stop_datetime_str);
1879
1880 delete binlog_filter;
1881 delete glob_description_event;
1882 if (mysql)
1883 mysql_close(mysql);
1884 DBUG_VOID_RETURN;
1885 }
1886
1887
print_version()1888 static void print_version()
1889 {
1890 printf("%s Ver 3.4 for %s at %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
1891 }
1892
1893
usage()1894 static void usage()
1895 {
1896 print_version();
1897 puts(ORACLE_WELCOME_COPYRIGHT_NOTICE("2000"));
1898 printf("\
1899 Dumps a MariaDB binary log in a format usable for viewing or for piping to\n\
1900 the mysql command line client.\n\n");
1901 printf("Usage: %s [options] log-files\n", my_progname);
1902 print_defaults("my",load_groups);
1903 puts("");
1904 my_print_help(my_options);
1905 my_print_variables(my_options);
1906 }
1907
1908
convert_str_to_timestamp(const char * str)1909 static my_time_t convert_str_to_timestamp(const char* str)
1910 {
1911 MYSQL_TIME_STATUS status;
1912 MYSQL_TIME l_time;
1913 long dummy_my_timezone;
1914 uint dummy_in_dst_time_gap;
1915
1916 /* We require a total specification (date AND time) */
1917 if (str_to_datetime_or_date(str, (uint) strlen(str), &l_time, 0, &status) ||
1918 l_time.time_type != MYSQL_TIMESTAMP_DATETIME || status.warnings)
1919 {
1920 error("Incorrect date and time argument: %s", str);
1921 exit(1);
1922 }
1923 /*
1924 Note that Feb 30th, Apr 31st cause no error messages and are mapped to
1925 the next existing day, like in mysqld. Maybe this could be changed when
1926 mysqld is changed too (with its "strict" mode?).
1927 */
1928 return
1929 my_system_gmt_sec(&l_time, &dummy_my_timezone, &dummy_in_dst_time_gap);
1930 }
1931
1932
1933 extern "C" my_bool
get_one_option(int optid,const struct my_option * opt,char * argument)1934 get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
1935 char *argument)
1936 {
1937 bool tty_password=0;
1938 switch (optid) {
1939 #ifndef DBUG_OFF
1940 case '#':
1941 if (!argument)
1942 argument= (char*) default_dbug_option;
1943 current_dbug_option= argument;
1944 DBUG_PUSH(argument);
1945 break;
1946 #endif
1947 #include <sslopt-case.h>
1948 case 'B':
1949 opt_flashback= 1;
1950 break;
1951 case 'd':
1952 one_database = 1;
1953 break;
1954 case 'p':
1955 if (argument == disabled_my_option)
1956 argument= (char*) ""; // Don't require password
1957 if (argument)
1958 {
1959 my_free(pass);
1960 char *start=argument;
1961 pass= my_strdup(argument,MYF(MY_FAE));
1962 while (*argument) *argument++= 'x'; /* Destroy argument */
1963 if (*start)
1964 start[1]=0; /* Cut length of argument */
1965 }
1966 else
1967 tty_password=1;
1968 break;
1969 case 'R':
1970 remote_opt= 1;
1971 break;
1972 case 'T':
1973 one_table= 1;
1974 break;
1975 case OPT_MYSQL_PROTOCOL:
1976 if ((opt_protocol= find_type_with_warning(argument, &sql_protocol_typelib,
1977 opt->name)) <= 0)
1978 {
1979 sf_leaking_memory= 1; /* no memory leak reports here */
1980 exit(1);
1981 }
1982 break;
1983 #ifdef WHEN_FLASHBACK_REVIEW_READY
1984 case opt_flashback_review:
1985 opt_flashback_review= 1;
1986 break;
1987 #endif
1988 case OPT_START_DATETIME:
1989 start_datetime= convert_str_to_timestamp(start_datetime_str);
1990 break;
1991 case OPT_STOP_DATETIME:
1992 stop_datetime= convert_str_to_timestamp(stop_datetime_str);
1993 break;
1994 case OPT_BASE64_OUTPUT_MODE:
1995 if (argument == NULL)
1996 opt_base64_output_mode= BASE64_OUTPUT_ALWAYS;
1997 else
1998 {
1999 int val;
2000
2001 if ((val= find_type_with_warning(argument, &base64_output_mode_typelib,
2002 opt->name)) <= 0)
2003 {
2004 sf_leaking_memory= 1; /* no memory leak reports here */
2005 exit(1);
2006 }
2007 opt_base64_output_mode= (enum_base64_output_mode) (val - 1);
2008 }
2009 break;
2010 case OPT_REWRITE_DB: // db_from->db_to
2011 {
2012 /* See also handling of OPT_REPLICATE_REWRITE_DB in sql/mysqld.cc */
2013 char* ptr;
2014 char* key= argument; // db-from
2015 char* val; // db-to
2016
2017 // Where key begins
2018 while (*key && my_isspace(&my_charset_latin1, *key))
2019 key++;
2020
2021 // Where val begins
2022 if (!(ptr= strstr(argument, "->")))
2023 {
2024 sql_print_error("Bad syntax in rewrite-db: missing '->'!\n");
2025 return 1;
2026 }
2027 val= ptr + 2;
2028 while (*val && my_isspace(&my_charset_latin1, *val))
2029 val++;
2030
2031 // Write \0 and skip blanks at the end of key
2032 *ptr-- = 0;
2033 while (my_isspace(&my_charset_latin1, *ptr) && ptr > argument)
2034 *ptr-- = 0;
2035
2036 if (!*key)
2037 {
2038 sql_print_error("Bad syntax in rewrite-db: empty db-from!\n");
2039 return 1;
2040 }
2041
2042 // Skip blanks at the end of val
2043 ptr= val;
2044 while (*ptr && !my_isspace(&my_charset_latin1, *ptr))
2045 ptr++;
2046 *ptr= 0;
2047
2048 if (!*val)
2049 {
2050 sql_print_error("Bad syntax in rewrite-db: empty db-to!\n");
2051 return 1;
2052 }
2053
2054 binlog_filter->add_db_rewrite(key, val);
2055 break;
2056 }
2057 case OPT_PRINT_ROW_COUNT:
2058 print_row_count_used= 1;
2059 break;
2060 case OPT_PRINT_ROW_EVENT_POSITIONS:
2061 print_row_event_positions_used= 1;
2062 break;
2063 case 'v':
2064 if (argument == disabled_my_option)
2065 verbose= 0;
2066 else
2067 verbose++;
2068 break;
2069 case 'V':
2070 print_version();
2071 opt_version= 1;
2072 break;
2073 case '?':
2074 usage();
2075 opt_version= 1;
2076 break;
2077 }
2078 if (tty_password)
2079 pass= get_tty_password(NullS);
2080
2081 return 0;
2082 }
2083
2084
parse_args(int * argc,char *** argv)2085 static int parse_args(int *argc, char*** argv)
2086 {
2087 int ho_error;
2088
2089 if ((ho_error=handle_options(argc, argv, my_options, get_one_option)))
2090 exit(ho_error);
2091 if (debug_info_flag)
2092 my_end_arg= MY_CHECK_ERROR | MY_GIVE_INFO;
2093 else if (debug_check_flag)
2094 my_end_arg= MY_CHECK_ERROR;
2095 if (start_position > UINT_MAX32 && remote_opt)
2096 {
2097 /* Here we just emulate old behaviour of option limit handling */
2098 fprintf(stderr, "Warning: option 'start-position': unsigned value %llu "
2099 "adjusted to 4294967295 (limitation of the client-server protocol)",
2100 start_position);
2101 start_position= UINT_MAX32;
2102 }
2103 return 0;
2104 }
2105
2106
2107 /**
2108 Create and initialize the global mysql object, and connect to the
2109 server.
2110
2111 @retval ERROR_STOP An error occurred - the program should terminate.
2112 @retval OK_CONTINUE No error, the program should continue.
2113 */
safe_connect()2114 static Exit_status safe_connect()
2115 {
2116 my_bool reconnect= 1;
2117 /* Close any old connections to MySQL */
2118 if (mysql)
2119 mysql_close(mysql);
2120
2121 mysql= mysql_init(NULL);
2122
2123 if (!mysql)
2124 {
2125 error("Failed on mysql_init.");
2126 return ERROR_STOP;
2127 }
2128
2129 #ifdef HAVE_OPENSSL
2130 if (opt_use_ssl)
2131 {
2132 mysql_ssl_set(mysql, opt_ssl_key, opt_ssl_cert, opt_ssl_ca,
2133 opt_ssl_capath, opt_ssl_cipher);
2134 mysql_options(mysql, MYSQL_OPT_SSL_CRL, opt_ssl_crl);
2135 mysql_options(mysql, MYSQL_OPT_SSL_CRLPATH, opt_ssl_crlpath);
2136 mysql_options(mysql, MARIADB_OPT_TLS_VERSION, opt_tls_version);
2137 }
2138 mysql_options(mysql,MYSQL_OPT_SSL_VERIFY_SERVER_CERT,
2139 (char*)&opt_ssl_verify_server_cert);
2140 #endif /*HAVE_OPENSSL*/
2141
2142 if (opt_plugindir && *opt_plugindir)
2143 mysql_options(mysql, MYSQL_PLUGIN_DIR, opt_plugindir);
2144
2145 if (opt_default_auth && *opt_default_auth)
2146 mysql_options(mysql, MYSQL_DEFAULT_AUTH, opt_default_auth);
2147
2148 if (opt_protocol)
2149 mysql_options(mysql, MYSQL_OPT_PROTOCOL, (char*) &opt_protocol);
2150 mysql_options(mysql, MYSQL_OPT_CONNECT_ATTR_RESET, 0);
2151 mysql_options4(mysql, MYSQL_OPT_CONNECT_ATTR_ADD,
2152 "program_name", "mysqlbinlog");
2153 if (!mysql_real_connect(mysql, host, user, pass, 0, port, sock, 0))
2154 {
2155 error("Failed on connect: %s", mysql_error(mysql));
2156 return ERROR_STOP;
2157 }
2158 mysql_options(mysql, MYSQL_OPT_RECONNECT, &reconnect);
2159 return OK_CONTINUE;
2160 }
2161
2162
2163 /**
2164 High-level function for dumping a named binlog.
2165
2166 This function calls dump_remote_log_entries() or
2167 dump_local_log_entries() to do the job.
2168
2169 @param[in] logname Name of input binlog.
2170
2171 @retval ERROR_STOP An error occurred - the program should terminate.
2172 @retval OK_CONTINUE No error, the program should continue.
2173 @retval OK_STOP No error, but the end of the specified range of
2174 events to process has been reached and the program should terminate.
2175 */
dump_log_entries(const char * logname)2176 static Exit_status dump_log_entries(const char* logname)
2177 {
2178 Exit_status rc;
2179 PRINT_EVENT_INFO print_event_info;
2180
2181 if (!print_event_info.init_ok())
2182 return ERROR_STOP;
2183 /*
2184 Set safe delimiter, to dump things
2185 like CREATE PROCEDURE safely
2186 */
2187 if (!opt_raw_mode)
2188 fprintf(result_file, "DELIMITER /*!*/;\n");
2189 strmov(print_event_info.delimiter, "/*!*/;");
2190
2191 if (short_form)
2192 {
2193 if (!print_row_event_positions_used)
2194 print_row_event_positions= 0;
2195 if (!print_row_count_used)
2196 print_row_count = 0;
2197 }
2198 if (opt_flashback)
2199 {
2200 if (!print_row_event_positions_used)
2201 print_row_event_positions= 0;
2202 }
2203
2204 print_event_info.verbose= short_form ? 0 : verbose;
2205 print_event_info.short_form= short_form;
2206 print_event_info.print_row_count= print_row_count;
2207 print_event_info.file= result_file;
2208 fflush(result_file);
2209 rc= (remote_opt ? dump_remote_log_entries(&print_event_info, logname) :
2210 dump_local_log_entries(&print_event_info, logname));
2211
2212 if (rc == ERROR_STOP)
2213 return rc;
2214
2215 /* Set delimiter back to semicolon */
2216 if (!opt_raw_mode && !opt_flashback)
2217 fprintf(result_file, "DELIMITER ;\n");
2218 strmov(print_event_info.delimiter, ";");
2219 return rc;
2220 }
2221
2222
2223 /**
2224 When reading a remote binlog, this function is used to grab the
2225 Format_description_log_event in the beginning of the stream.
2226
2227 This is not as smart as check_header() (used for local log); it will
2228 not work for a binlog which mixes format. TODO: fix this.
2229
2230 @retval ERROR_STOP An error occurred - the program should terminate.
2231 @retval OK_CONTINUE No error, the program should continue.
2232 */
check_master_version()2233 static Exit_status check_master_version()
2234 {
2235 MYSQL_RES* res = 0;
2236 MYSQL_ROW row;
2237 uint version;
2238
2239 if (mysql_query(mysql, "SELECT VERSION()") ||
2240 !(res = mysql_store_result(mysql)))
2241 {
2242 error("Could not find server version: "
2243 "Query failed when checking master version: %s", mysql_error(mysql));
2244 return ERROR_STOP;
2245 }
2246 if (!(row = mysql_fetch_row(res)))
2247 {
2248 error("Could not find server version: "
2249 "Master returned no rows for SELECT VERSION().");
2250 goto err;
2251 }
2252
2253 if (!(version = atoi(row[0])))
2254 {
2255 error("Could not find server version: "
2256 "Master reported NULL for the version.");
2257 goto err;
2258 }
2259 /*
2260 Make a notice to the server that this client
2261 is checksum-aware. It does not need the first fake Rotate
2262 necessary checksummed.
2263 That preference is specified below.
2264 */
2265 if (mysql_query(mysql, "SET @master_binlog_checksum='NONE'"))
2266 {
2267 error("Could not notify master about checksum awareness."
2268 "Master returned '%s'", mysql_error(mysql));
2269 goto err;
2270 }
2271
2272 /*
2273 Announce our capabilities to the server, so it will send us all the events
2274 that we know about.
2275 */
2276 if (mysql_query(mysql, "SET @mariadb_slave_capability="
2277 STRINGIFY_ARG(MARIA_SLAVE_CAPABILITY_MINE)))
2278 {
2279 error("Could not inform master about capability. Master returned '%s'",
2280 mysql_error(mysql));
2281 goto err;
2282 }
2283
2284 delete glob_description_event;
2285 glob_description_event= NULL;
2286
2287 switch (version) {
2288 case 3:
2289 glob_description_event= new Format_description_log_event(1);
2290 break;
2291 case 4:
2292 glob_description_event= new Format_description_log_event(3);
2293 break;
2294 case 5:
2295 case 10:
2296 /*
2297 The server is soon going to send us its Format_description log
2298 event, unless it is a 5.0 server with 3.23 or 4.0 binlogs.
2299 So we first assume that this is 4.0 (which is enough to read the
2300 Format_desc event if one comes).
2301 */
2302 glob_description_event= new Format_description_log_event(3);
2303 break;
2304 default:
2305 error("Could not find server version: "
2306 "Master reported unrecognized MariaDB version '%s'.", row[0]);
2307 goto err;
2308 }
2309 if (!glob_description_event || !glob_description_event->is_valid())
2310 {
2311 error("Failed creating Format_description_log_event; out of memory?");
2312 goto err;
2313 }
2314
2315 mysql_free_result(res);
2316 return OK_CONTINUE;
2317
2318 err:
2319 mysql_free_result(res);
2320 return ERROR_STOP;
2321 }
2322
2323
handle_event_text_mode(PRINT_EVENT_INFO * print_event_info,ulong * len,const char * logname,uint logname_len,my_off_t old_off)2324 static Exit_status handle_event_text_mode(PRINT_EVENT_INFO *print_event_info,
2325 ulong *len,
2326 const char* logname,
2327 uint logname_len, my_off_t old_off)
2328 {
2329 const char *error_msg;
2330 Log_event *ev;
2331 NET *net= &mysql->net;
2332 DBUG_ENTER("handle_event_text_mode");
2333
2334 if (net->read_pos[5] == ANNOTATE_ROWS_EVENT)
2335 {
2336 if (!(ev= read_remote_annotate_event(net->read_pos + 1, *len - 1,
2337 &error_msg)))
2338 {
2339 error("Could not construct annotate event object: %s", error_msg);
2340 DBUG_RETURN(ERROR_STOP);
2341 }
2342 }
2343 else
2344 {
2345 if (!(ev= Log_event::read_log_event((const char*) net->read_pos + 1 ,
2346 *len - 1, &error_msg,
2347 glob_description_event,
2348 opt_verify_binlog_checksum)))
2349 {
2350 error("Could not construct log event object: %s", error_msg);
2351 DBUG_RETURN(ERROR_STOP);
2352 }
2353 /*
2354 If reading from a remote host, ensure the temp_buf for the
2355 Log_event class is pointing to the incoming stream.
2356 */
2357 ev->register_temp_buf((char *) net->read_pos + 1, FALSE);
2358 }
2359
2360 Log_event_type type= ev->get_type_code();
2361 if (glob_description_event->binlog_version >= 3 ||
2362 (type != LOAD_EVENT && type != CREATE_FILE_EVENT))
2363 {
2364 /*
2365 If this is a Rotate event, maybe it's the end of the requested binlog;
2366 in this case we are done (stop transfer).
2367 This is suitable for binlogs, not relay logs (but for now we don't read
2368 relay logs remotely because the server is not able to do that). If one
2369 day we read relay logs remotely, then we will have a problem with the
2370 detection below: relay logs contain Rotate events which are about the
2371 binlogs, so which would trigger the end-detection below.
2372 */
2373 if (type == ROTATE_EVENT)
2374 {
2375 Rotate_log_event *rev= (Rotate_log_event *)ev;
2376 /*
2377 If this is a fake Rotate event, and not about our log, we can stop
2378 transfer. If this a real Rotate event (so it's not about our log,
2379 it's in our log describing the next log), we print it (because it's
2380 part of our log) and then we will stop when we receive the fake one
2381 soon.
2382 */
2383 if (rev->when == 0)
2384 {
2385 *len= 1; // fake Rotate, so don't increment old_off
2386 if (!to_last_remote_log)
2387 {
2388 if ((rev->ident_len != logname_len) ||
2389 memcmp(rev->new_log_ident, logname, logname_len))
2390 {
2391 delete ev;
2392 DBUG_RETURN(OK_EOF);
2393 }
2394 /*
2395 Otherwise, this is a fake Rotate for our log, at the very
2396 beginning for sure. Skip it, because it was not in the original
2397 log. If we are running with to_last_remote_log, we print it,
2398 because it serves as a useful marker between binlogs then.
2399 */
2400 delete ev;
2401 DBUG_RETURN(OK_CONTINUE);
2402 }
2403 }
2404 }
2405 else if (type == FORMAT_DESCRIPTION_EVENT)
2406 {
2407 /*
2408 This could be an fake Format_description_log_event that server
2409 (5.0+) automatically sends to a slave on connect, before sending
2410 a first event at the requested position. If this is the case,
2411 don't increment old_off. Real Format_description_log_event always
2412 starts from BIN_LOG_HEADER_SIZE position.
2413 */
2414 if (old_off != BIN_LOG_HEADER_SIZE)
2415 *len= 1; // fake event, don't increment old_off
2416 }
2417 Exit_status retval= process_event(print_event_info, ev, old_off, logname);
2418 if (retval != OK_CONTINUE)
2419 DBUG_RETURN(retval);
2420 }
2421 else
2422 {
2423 Load_log_event *le= (Load_log_event*)ev;
2424 const char *old_fname= le->fname;
2425 uint old_len= le->fname_len;
2426 File file;
2427 Exit_status retval;
2428 char fname[FN_REFLEN+1];
2429
2430 if ((file= load_processor.prepare_new_file_for_old_format(le,fname)) < 0)
2431 {
2432 DBUG_RETURN(ERROR_STOP);
2433 }
2434
2435 retval= process_event(print_event_info, ev, old_off, logname);
2436 if (retval != OK_CONTINUE)
2437 {
2438 my_close(file,MYF(MY_WME));
2439 DBUG_RETURN(retval);
2440 }
2441 retval= load_processor.load_old_format_file(net,old_fname,old_len,file);
2442 my_close(file,MYF(MY_WME));
2443 if (retval != OK_CONTINUE)
2444 DBUG_RETURN(retval);
2445 }
2446
2447 DBUG_RETURN(OK_CONTINUE);
2448 }
2449
2450
2451 static char out_file_name[FN_REFLEN + 1];
2452
handle_event_raw_mode(PRINT_EVENT_INFO * print_event_info,ulong * len,const char * logname,uint logname_len)2453 static Exit_status handle_event_raw_mode(PRINT_EVENT_INFO *print_event_info,
2454 ulong *len,
2455 const char* logname, uint logname_len)
2456 {
2457 const char *error_msg;
2458 const unsigned char *read_pos= mysql->net.read_pos + 1;
2459 Log_event_type type;
2460 DBUG_ENTER("handle_event_raw_mode");
2461 DBUG_ASSERT(opt_raw_mode && remote_opt);
2462
2463 type= (Log_event_type) read_pos[EVENT_TYPE_OFFSET];
2464
2465 if (type == HEARTBEAT_LOG_EVENT)
2466 DBUG_RETURN(OK_CONTINUE);
2467
2468 if (type == ROTATE_EVENT || type == FORMAT_DESCRIPTION_EVENT)
2469 {
2470 Log_event *ev;
2471 if (!(ev= Log_event::read_log_event((const char*) read_pos ,
2472 *len - 1, &error_msg,
2473 glob_description_event,
2474 opt_verify_binlog_checksum)))
2475 {
2476 error("Could not construct %s event object: %s",
2477 type == ROTATE_EVENT ? "rotate" : "format description", error_msg);
2478 DBUG_RETURN(ERROR_STOP);
2479 }
2480 /*
2481 If reading from a remote host, ensure the temp_buf for the
2482 Log_event class is pointing to the incoming stream.
2483 */
2484 ev->register_temp_buf((char *) read_pos, FALSE);
2485
2486 if (type == ROTATE_EVENT)
2487 {
2488 Exit_status ret_val= OK_CONTINUE;
2489 Rotate_log_event *rev= (Rotate_log_event *)ev;
2490 char *pe= strmake(out_file_name, output_prefix, sizeof(out_file_name)-1);
2491 strmake(pe, rev->new_log_ident, sizeof(out_file_name) - (pe-out_file_name));
2492
2493 /*
2494 If this is a fake Rotate event, and not about our log, we can stop
2495 transfer. If this a real Rotate event (so it's not about our log,
2496 it's in our log describing the next log), we print it (because it's
2497 part of our log) and then we will stop when we receive the fake one
2498 soon.
2499 */
2500 if (rev->when == 0)
2501 {
2502 if (!to_last_remote_log)
2503 {
2504 if ((rev->ident_len != logname_len) ||
2505 memcmp(rev->new_log_ident, logname, logname_len))
2506 {
2507 ret_val= OK_EOF;
2508 }
2509 /*
2510 Otherwise, this is a fake Rotate for our log, at the very
2511 beginning for sure. Skip it, because it was not in the original
2512 log. If we are running with to_last_remote_log, we print it,
2513 because it serves as a useful marker between binlogs then.
2514 */
2515 }
2516 *len= 1; // fake Rotate, so don't increment old_off
2517 ev->temp_buf= 0;
2518 delete ev;
2519 DBUG_RETURN(ret_val);
2520 }
2521 ev->temp_buf= 0;
2522 delete ev;
2523 }
2524 else /* if (type == FORMAT_DESCRIPTION_EVENT) */
2525 {
2526 DBUG_ASSERT(type == FORMAT_DESCRIPTION_EVENT);
2527
2528 if (result_file)
2529 my_fclose(result_file, MYF(0));
2530
2531 if (!(result_file= my_fopen(out_file_name,
2532 O_WRONLY | O_BINARY, MYF(MY_WME))))
2533 {
2534 error("Could not create output log file: %s", out_file_name);
2535 DBUG_RETURN(ERROR_STOP);
2536 }
2537 /* TODO - add write error simulation here */
2538
2539 if (my_fwrite(result_file, (const uchar *) BINLOG_MAGIC,
2540 BIN_LOG_HEADER_SIZE, MYF(MY_NABP)))
2541 {
2542 error("Could not write into log file '%s'", out_file_name);
2543 DBUG_RETURN(ERROR_STOP);
2544 }
2545 print_event_info->file= result_file;
2546
2547 delete glob_description_event;
2548 glob_description_event= (Format_description_log_event*) ev;
2549 print_event_info->common_header_len=
2550 glob_description_event->common_header_len;
2551 ev->temp_buf= 0;
2552 /* We do not want to delete the event here. */
2553 }
2554 }
2555
2556 if (my_fwrite(result_file, read_pos, *len - 1, MYF(MY_NABP)))
2557 {
2558 error("Could not write into log file '%s'", out_file_name);
2559 DBUG_RETURN(ERROR_STOP);
2560 }
2561
2562 DBUG_RETURN(OK_CONTINUE);
2563 }
2564
2565
2566 /**
2567 Requests binlog dump from a remote server and prints the events it
2568 receives.
2569
2570 @param[in,out] print_event_info Parameters and context state
2571 determining how to print.
2572 @param[in] logname Name of input binlog.
2573
2574 @retval ERROR_STOP An error occurred - the program should terminate.
2575 @retval OK_CONTINUE No error, the program should continue.
2576 @retval OK_STOP No error, but the end of the specified range of
2577 events to process has been reached and the program should terminate.
2578 */
dump_remote_log_entries(PRINT_EVENT_INFO * print_event_info,const char * logname)2579 static Exit_status dump_remote_log_entries(PRINT_EVENT_INFO *print_event_info,
2580 const char* logname)
2581
2582 {
2583 uchar buf[128];
2584 ulong len;
2585 uint logname_len;
2586 NET* net;
2587 my_off_t old_off= start_position_mot;
2588 Exit_status retval= OK_CONTINUE;
2589 short binlog_flags = 0;
2590 ulong slave_id;
2591 DBUG_ENTER("dump_remote_log_entries");
2592
2593 /*
2594 Even if we already read one binlog (case of >=2 binlogs on command line),
2595 we cannot re-use the same connection as before, because it is now dead
2596 (COM_BINLOG_DUMP kills the thread when it finishes).
2597 */
2598 if ((retval= safe_connect()) != OK_CONTINUE)
2599 DBUG_RETURN(retval);
2600 net= &mysql->net;
2601
2602 if ((retval= check_master_version()) != OK_CONTINUE)
2603 DBUG_RETURN(retval);
2604
2605 /*
2606 COM_BINLOG_DUMP accepts only 4 bytes for the position, so we are forced to
2607 cast to uint32.
2608 */
2609 DBUG_ASSERT(start_position <= UINT_MAX32);
2610 int4store(buf, (uint32)start_position);
2611 if (!opt_skip_annotate_row_events)
2612 binlog_flags|= BINLOG_SEND_ANNOTATE_ROWS_EVENT;
2613 if (!opt_stop_never)
2614 binlog_flags|= BINLOG_DUMP_NON_BLOCK;
2615
2616 int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
2617
2618 size_t tlen = strlen(logname);
2619 if (tlen > sizeof(buf) - 10)
2620 {
2621 error("Log name too long.");
2622 DBUG_RETURN(ERROR_STOP);
2623 }
2624 logname_len = (uint) tlen;
2625 if (opt_stop_never)
2626 {
2627 DBUG_ASSERT(to_last_remote_log);
2628 slave_id= (opt_stop_never_slave_server_id == 0) ?
2629 1 : opt_stop_never_slave_server_id;
2630 }
2631 else
2632 slave_id= 0;
2633 int4store(buf + 6, slave_id);
2634 memcpy(buf + 10, logname, logname_len);
2635 if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
2636 {
2637 error("Got fatal error sending the log dump command.");
2638 DBUG_RETURN(ERROR_STOP);
2639 }
2640
2641 for (;;)
2642 {
2643 len= cli_safe_read(mysql);
2644 if (len == packet_error)
2645 {
2646 error("Got error reading packet from server: %s", mysql_error(mysql));
2647 DBUG_RETURN(ERROR_STOP);
2648 }
2649 if (len < 8 && net->read_pos[0] == 254)
2650 break; // end of data
2651 DBUG_PRINT("info",( "len: %lu net->read_pos[5]: %d\n",
2652 len, net->read_pos[5]));
2653 if (opt_raw_mode)
2654 {
2655 retval= handle_event_raw_mode(print_event_info, &len,
2656 logname, logname_len);
2657 }
2658 else
2659 {
2660 retval= handle_event_text_mode(print_event_info, &len,
2661 logname, logname_len, old_off);
2662 }
2663 if (retval != OK_CONTINUE)
2664 {
2665 if (retval == OK_EOF)
2666 break;
2667 DBUG_RETURN(retval);
2668 }
2669
2670 /*
2671 Let's adjust offset for remote log as for local log to produce
2672 similar text and to have --stop-position to work identically.
2673 */
2674 old_off+= len-1;
2675 }
2676
2677 DBUG_RETURN(OK_CONTINUE);
2678 }
2679
2680
2681 /**
2682 Reads the @c Format_description_log_event from the beginning of a
2683 local input file.
2684
2685 The @c Format_description_log_event is only read if it is outside
2686 the range specified with @c --start-position; otherwise, it will be
2687 seen later. If this is an old binlog, a fake @c
2688 Format_description_event is created. This also prints a @c
2689 Format_description_log_event to the output, unless we reach the
2690 --start-position range. In this case, it is assumed that a @c
2691 Format_description_log_event will be found when reading events the
2692 usual way.
2693
2694 @param file The file to which a @c Format_description_log_event will
2695 be printed.
2696
2697 @param[in,out] print_event_info Parameters and context state
2698 determining how to print.
2699
2700 @param[in] logname Name of input binlog.
2701
2702 @retval ERROR_STOP An error occurred - the program should terminate.
2703 @retval OK_CONTINUE No error, the program should continue.
2704 @retval OK_STOP No error, but the end of the specified range of
2705 events to process has been reached and the program should terminate.
2706 */
check_header(IO_CACHE * file,PRINT_EVENT_INFO * print_event_info,const char * logname)2707 static Exit_status check_header(IO_CACHE* file,
2708 PRINT_EVENT_INFO *print_event_info,
2709 const char* logname)
2710 {
2711 uchar header[BIN_LOG_HEADER_SIZE];
2712 uchar buf[PROBE_HEADER_LEN];
2713 my_off_t tmp_pos, pos;
2714 MY_STAT my_file_stat;
2715
2716 delete glob_description_event;
2717 if (!(glob_description_event= new Format_description_log_event(3)))
2718 {
2719 error("Failed creating Format_description_log_event; out of memory?");
2720 return ERROR_STOP;
2721 }
2722
2723 pos= my_b_tell(file);
2724
2725 /* fstat the file to check if the file is a regular file. */
2726 if (my_fstat(file->file, &my_file_stat, MYF(0)) == -1)
2727 {
2728 error("Unable to stat the file.");
2729 return ERROR_STOP;
2730 }
2731 if ((my_file_stat.st_mode & S_IFMT) == S_IFREG)
2732 my_b_seek(file, (my_off_t)0);
2733
2734 if (my_b_read(file, header, sizeof(header)))
2735 {
2736 error("Failed reading header; probably an empty file.");
2737 return ERROR_STOP;
2738 }
2739 if (memcmp(header, BINLOG_MAGIC, sizeof(header)))
2740 {
2741 error("File is not a binary log file.");
2742 return ERROR_STOP;
2743 }
2744
2745 /*
2746 Imagine we are running with --start-position=1000. We still need
2747 to know the binlog format's. So we still need to find, if there is
2748 one, the Format_desc event, or to know if this is a 3.23
2749 binlog. So we need to first read the first events of the log,
2750 those around offset 4. Even if we are reading a 3.23 binlog from
2751 the start (no --start-position): we need to know the header length
2752 (which is 13 in 3.23, 19 in 4.x) to be able to successfully print
2753 the first event (Start_log_event_v3). So even in this case, we
2754 need to "probe" the first bytes of the log *before* we do a real
2755 read_log_event(). Because read_log_event() needs to know the
2756 header's length to work fine.
2757 */
2758 for(;;)
2759 {
2760 tmp_pos= my_b_tell(file); /* should be 4 the first time */
2761 if (my_b_read(file, buf, sizeof(buf)))
2762 {
2763 if (file->error)
2764 {
2765 error("Could not read entry at offset %llu: "
2766 "Error in log format or read error.", (ulonglong)tmp_pos);
2767 return ERROR_STOP;
2768 }
2769 /*
2770 Otherwise this is just EOF : this log currently contains 0-2
2771 events. Maybe it's going to be filled in the next
2772 milliseconds; then we are going to have a problem if this a
2773 3.23 log (imagine we are locally reading a 3.23 binlog which
2774 is being written presently): we won't know it in
2775 read_log_event() and will fail(). Similar problems could
2776 happen with hot relay logs if --start-position is used (but a
2777 --start-position which is posterior to the current size of the log).
2778 These are rare problems anyway (reading a hot log + when we
2779 read the first events there are not all there yet + when we
2780 read a bit later there are more events + using a strange
2781 --start-position).
2782 */
2783 break;
2784 }
2785 else
2786 {
2787 DBUG_PRINT("info",("buf[EVENT_TYPE_OFFSET=%d]=%d",
2788 EVENT_TYPE_OFFSET, buf[EVENT_TYPE_OFFSET]));
2789 /* always test for a Start_v3, even if no --start-position */
2790 if (buf[EVENT_TYPE_OFFSET] == START_EVENT_V3)
2791 {
2792 /* This is 3.23 or 4.x */
2793 if (uint4korr(buf + EVENT_LEN_OFFSET) <
2794 (LOG_EVENT_MINIMAL_HEADER_LEN + START_V3_HEADER_LEN))
2795 {
2796 /* This is 3.23 (format 1) */
2797 delete glob_description_event;
2798 if (!(glob_description_event= new Format_description_log_event(1)))
2799 {
2800 error("Failed creating Format_description_log_event; "
2801 "out of memory?");
2802 return ERROR_STOP;
2803 }
2804 }
2805 break;
2806 }
2807 else if (tmp_pos >= start_position)
2808 break;
2809 else if (buf[EVENT_TYPE_OFFSET] == FORMAT_DESCRIPTION_EVENT)
2810 {
2811 /* This is 5.0 */
2812 Format_description_log_event *new_description_event;
2813 my_b_seek(file, tmp_pos); /* seek back to event's start */
2814 if (!(new_description_event= (Format_description_log_event*)
2815 Log_event::read_log_event(file, glob_description_event,
2816 opt_verify_binlog_checksum)))
2817 /* EOF can't be hit here normally, so it's a real error */
2818 {
2819 error("Could not read a Format_description_log_event event at "
2820 "offset %llu; this could be a log format error or read error.",
2821 (ulonglong)tmp_pos);
2822 return ERROR_STOP;
2823 }
2824 if (opt_base64_output_mode == BASE64_OUTPUT_AUTO
2825 || opt_base64_output_mode == BASE64_OUTPUT_ALWAYS)
2826 {
2827 /*
2828 process_event will delete *description_event and set it to
2829 the new one, so we should not do it ourselves in this
2830 case.
2831 */
2832 Exit_status retval= process_event(print_event_info,
2833 new_description_event, tmp_pos,
2834 logname);
2835 if (retval != OK_CONTINUE)
2836 return retval;
2837 }
2838 else
2839 {
2840 delete glob_description_event;
2841 glob_description_event= new_description_event;
2842 }
2843 DBUG_PRINT("info",("Setting description_event"));
2844 }
2845 else if (buf[EVENT_TYPE_OFFSET] == ROTATE_EVENT)
2846 {
2847 Log_event *ev;
2848 my_b_seek(file, tmp_pos); /* seek back to event's start */
2849 if (!(ev= Log_event::read_log_event(file, glob_description_event,
2850 opt_verify_binlog_checksum)))
2851 {
2852 /* EOF can't be hit here normally, so it's a real error */
2853 error("Could not read a Rotate_log_event event at offset %llu;"
2854 " this could be a log format error or read error.",
2855 (ulonglong)tmp_pos);
2856 return ERROR_STOP;
2857 }
2858 delete ev;
2859 }
2860 else
2861 break;
2862 }
2863 }
2864 my_b_seek(file, pos);
2865 return OK_CONTINUE;
2866 }
2867
2868
2869 /**
2870 Reads a local binlog and prints the events it sees.
2871
2872 @param[in] logname Name of input binlog.
2873
2874 @param[in,out] print_event_info Parameters and context state
2875 determining how to print.
2876
2877 @retval ERROR_STOP An error occurred - the program should terminate.
2878 @retval OK_CONTINUE No error, the program should continue.
2879 @retval OK_STOP No error, but the end of the specified range of
2880 events to process has been reached and the program should terminate.
2881 */
dump_local_log_entries(PRINT_EVENT_INFO * print_event_info,const char * logname)2882 static Exit_status dump_local_log_entries(PRINT_EVENT_INFO *print_event_info,
2883 const char* logname)
2884 {
2885 File fd = -1;
2886 IO_CACHE cache,*file= &cache;
2887 uchar tmp_buff[BIN_LOG_HEADER_SIZE];
2888 Exit_status retval= OK_CONTINUE;
2889
2890 if (logname && strcmp(logname, "-") != 0)
2891 {
2892 /* read from normal file */
2893 if ((fd = my_open(logname, O_RDONLY | O_BINARY, MYF(MY_WME))) < 0)
2894 return ERROR_STOP;
2895 if (init_io_cache(file, fd, 0, READ_CACHE, start_position_mot, 0,
2896 MYF(MY_WME | MY_NABP)))
2897 {
2898 my_close(fd, MYF(MY_WME));
2899 return ERROR_STOP;
2900 }
2901 if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
2902 goto end;
2903 }
2904 else
2905 {
2906 /* read from stdin */
2907 /*
2908 Windows opens stdin in text mode by default. Certain characters
2909 such as CTRL-Z are interpreted as events and the read() method
2910 will stop. CTRL-Z is the EOF marker in Windows. to get past this
2911 you have to open stdin in binary mode. Setmode() is used to set
2912 stdin in binary mode. Errors on setting this mode result in
2913 halting the function and printing an error message to stderr.
2914 */
2915 #if defined (__WIN__) || defined(_WIN64)
2916 if (_setmode(fileno(stdin), O_BINARY) == -1)
2917 {
2918 error("Could not set binary mode on stdin.");
2919 return ERROR_STOP;
2920 }
2921 #endif
2922 if (init_io_cache(file, my_fileno(stdin), 0, READ_CACHE, (my_off_t) 0,
2923 0, MYF(MY_WME | MY_NABP | MY_DONT_CHECK_FILESIZE)))
2924 {
2925 error("Failed to init IO cache.");
2926 return ERROR_STOP;
2927 }
2928 if ((retval= check_header(file, print_event_info, logname)) != OK_CONTINUE)
2929 goto end;
2930 if (start_position)
2931 {
2932 /* skip 'start_position' characters from stdin */
2933 uchar buff[IO_SIZE];
2934 my_off_t length,tmp;
2935 for (length= start_position_mot ; length > 0 ; length-=tmp)
2936 {
2937 tmp= MY_MIN(length,sizeof(buff));
2938 if (my_b_read(file, buff, (uint) tmp))
2939 {
2940 error("Failed reading from file.");
2941 goto err;
2942 }
2943 }
2944 }
2945 }
2946
2947 if (!glob_description_event || !glob_description_event->is_valid())
2948 {
2949 error("Invalid Format_description log event; could be out of memory.");
2950 goto err;
2951 }
2952
2953 if (!start_position && my_b_read(file, tmp_buff, BIN_LOG_HEADER_SIZE))
2954 {
2955 error("Failed reading from file.");
2956 goto err;
2957 }
2958 for (;;)
2959 {
2960 char llbuff[21];
2961 my_off_t old_off = my_b_tell(file);
2962
2963 Log_event* ev = Log_event::read_log_event(file, glob_description_event,
2964 opt_verify_binlog_checksum);
2965 if (!ev)
2966 {
2967 /*
2968 if binlog wasn't closed properly ("in use" flag is set) don't complain
2969 about a corruption, but treat it as EOF and move to the next binlog.
2970 */
2971 if (glob_description_event->flags & LOG_EVENT_BINLOG_IN_USE_F)
2972 file->error= 0;
2973 else if (file->error)
2974 {
2975 error("Could not read entry at offset %s: "
2976 "Error in log format or read error.",
2977 llstr(old_off,llbuff));
2978 goto err;
2979 }
2980 // file->error == 0 means EOF, that's OK, we break in this case
2981 goto end;
2982 }
2983 if ((retval= process_event(print_event_info, ev, old_off, logname)) !=
2984 OK_CONTINUE)
2985 goto end;
2986 }
2987
2988 /* NOTREACHED */
2989
2990 err:
2991 retval= ERROR_STOP;
2992
2993 end:
2994 if (fd >= 0)
2995 my_close(fd, MYF(MY_WME));
2996 /*
2997 Since the end_io_cache() writes to the
2998 file errors may happen.
2999 */
3000 if (end_io_cache(file))
3001 retval= ERROR_STOP;
3002
3003 return retval;
3004 }
3005
3006
main(int argc,char ** argv)3007 int main(int argc, char** argv)
3008 {
3009 char **defaults_argv;
3010 Exit_status retval= OK_CONTINUE;
3011 ulonglong save_stop_position;
3012 MY_INIT(argv[0]);
3013 DBUG_ENTER("main");
3014 DBUG_PROCESS(argv[0]);
3015
3016 my_init_time(); // for time functions
3017 tzset(); // set tzname
3018
3019 load_defaults_or_exit("my", load_groups, &argc, &argv);
3020 defaults_argv= argv;
3021
3022 if (!(binlog_filter= new Rpl_filter))
3023 {
3024 error("Failed to create Rpl_filter");
3025 goto err;
3026 }
3027
3028 parse_args(&argc, (char***)&argv);
3029
3030 if (!argc || opt_version)
3031 {
3032 if (!opt_version)
3033 {
3034 usage();
3035 retval= ERROR_STOP;
3036 }
3037 goto err;
3038 }
3039
3040 if (opt_base64_output_mode == BASE64_OUTPUT_UNSPEC)
3041 opt_base64_output_mode= BASE64_OUTPUT_AUTO;
3042
3043 my_set_max_open_files(open_files_limit);
3044
3045 if (opt_flashback)
3046 {
3047 my_init_dynamic_array(&binlog_events, sizeof(LEX_STRING), 1024, 1024,
3048 MYF(0));
3049 my_init_dynamic_array(&events_in_stmt, sizeof(Rows_log_event*), 1024, 1024,
3050 MYF(0));
3051 }
3052 if (opt_stop_never)
3053 to_last_remote_log= TRUE;
3054
3055 if (opt_raw_mode)
3056 {
3057 if (!remote_opt)
3058 {
3059 error("The --raw mode only works with --read-from-remote-server");
3060 exit(1);
3061 }
3062 if (one_database)
3063 warning("The --database option is ignored in raw mode");
3064
3065 if (stop_position != (ulonglong)(~(my_off_t)0))
3066 warning("The --stop-position option is ignored in raw mode");
3067
3068 if (stop_datetime != MY_TIME_T_MAX)
3069 warning("The --stop-datetime option is ignored in raw mode");
3070 result_file= 0;
3071 if (result_file_name)
3072 output_prefix= result_file_name;
3073 }
3074 else
3075 {
3076 if (result_file_name)
3077 {
3078 if (!(result_file= my_fopen(result_file_name,
3079 O_WRONLY | O_BINARY, MYF(MY_WME))))
3080 {
3081 error("Could not create log file '%s'", result_file_name);
3082 exit(1);
3083 }
3084 }
3085 else
3086 result_file= stdout;
3087 }
3088
3089 MY_TMPDIR tmpdir;
3090 tmpdir.list= 0;
3091 if (!dirname_for_local_load)
3092 {
3093 if (init_tmpdir(&tmpdir, 0))
3094 {
3095 retval= ERROR_STOP;
3096 goto err;
3097 }
3098 dirname_for_local_load= my_strdup(my_tmpdir(&tmpdir), MY_WME);
3099 }
3100
3101 if (load_processor.init())
3102 {
3103 retval= ERROR_STOP;
3104 goto err;
3105 }
3106 if (dirname_for_local_load)
3107 load_processor.init_by_dir_name(dirname_for_local_load);
3108 else
3109 load_processor.init_by_cur_dir();
3110
3111 if (!opt_raw_mode)
3112 {
3113 fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=1*/;\n");
3114
3115 fprintf(result_file,
3116 "/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
3117
3118 if (disable_log_bin)
3119 fprintf(result_file,
3120 "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
3121
3122 /*
3123 In mysqlbinlog|mysql, don't want mysql to be disconnected after each
3124 transaction (which would be the case with GLOBAL.COMPLETION_TYPE==2).
3125 */
3126 fprintf(result_file,
3127 "/*!50003 SET @OLD_COMPLETION_TYPE=@@COMPLETION_TYPE,"
3128 "COMPLETION_TYPE=0*/;\n");
3129
3130 if (charset)
3131 fprintf(result_file,
3132 "\n/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;"
3133 "\n/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;"
3134 "\n/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;"
3135 "\n/*!40101 SET NAMES %s */;\n", charset);
3136 }
3137
3138 for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
3139 (--argc >= 0) ; )
3140 {
3141 if (argc == 0) // last log, --stop-position applies
3142 stop_position= save_stop_position;
3143 if ((retval= dump_log_entries(*argv++)) != OK_CONTINUE)
3144 break;
3145
3146 // For next log, --start-position does not apply
3147 start_position= BIN_LOG_HEADER_SIZE;
3148 }
3149
3150 /*
3151 If enable flashback, need to print the events from the end to the
3152 beginning
3153 */
3154 if (opt_flashback && retval != ERROR_STOP)
3155 {
3156 for (uint i= binlog_events.elements; i > 0; --i)
3157 {
3158 LEX_STRING *event_str= dynamic_element(&binlog_events, i - 1,
3159 LEX_STRING*);
3160 fprintf(result_file, "%s", event_str->str);
3161 my_free(event_str->str);
3162 }
3163 fprintf(result_file, "COMMIT\n/*!*/;\n");
3164 delete_dynamic(&binlog_events);
3165 delete_dynamic(&events_in_stmt);
3166 }
3167
3168 /* Set delimiter back to semicolon */
3169 if (retval != ERROR_STOP)
3170 {
3171 if (!stop_event_string.is_empty())
3172 fprintf(result_file, "%s", stop_event_string.ptr());
3173 if (!opt_raw_mode && opt_flashback)
3174 fprintf(result_file, "DELIMITER ;\n");
3175 }
3176
3177 if (retval != ERROR_STOP && !opt_raw_mode)
3178 {
3179 /*
3180 Issue a ROLLBACK in case the last printed binlog was crashed and had half
3181 of transaction.
3182 */
3183 fprintf(result_file,
3184 "# End of log file\nROLLBACK /* added by mysqlbinlog */;\n"
3185 "/*!50003 SET COMPLETION_TYPE=@OLD_COMPLETION_TYPE*/;\n");
3186 if (disable_log_bin)
3187 fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
3188
3189 if (charset)
3190 fprintf(result_file,
3191 "/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;\n"
3192 "/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;\n"
3193 "/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;\n");
3194
3195 fprintf(result_file, "/*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/;\n");
3196 }
3197
3198 if (tmpdir.list)
3199 free_tmpdir(&tmpdir);
3200 if (result_file && result_file != stdout)
3201 my_fclose(result_file, MYF(0));
3202 cleanup();
3203 free_annotate_event();
3204 free_defaults(defaults_argv);
3205 my_free_open_file_info();
3206 load_processor.destroy();
3207 mysql_server_end();
3208 /* We cannot free DBUG, it is used in global destructors after exit(). */
3209 my_end(my_end_arg | MY_DONT_FREE_DBUG);
3210
3211 exit(retval == ERROR_STOP ? 1 : 0);
3212 /* Keep compilers happy. */
3213 DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
3214
3215 err:
3216 cleanup();
3217 free_defaults(defaults_argv);
3218 my_end(my_end_arg);
3219 exit(retval == ERROR_STOP ? 1 : 0);
3220 DBUG_RETURN(retval == ERROR_STOP ? 1 : 0);
3221 }
3222
e_key_get_latest_version_func(uint)3223 uint e_key_get_latest_version_func(uint) { return 1; }
e_key_get_func(uint,uint,uchar *,uint *)3224 uint e_key_get_func(uint, uint, uchar*, uint*) { return 1; }
e_ctx_size_func(uint,uint)3225 uint e_ctx_size_func(uint, uint) { return 1; }
e_ctx_init_func(void *,const uchar *,uint,const uchar *,uint,int,uint,uint)3226 int e_ctx_init_func(void *, const uchar*, uint, const uchar*, uint,
3227 int, uint, uint) { return 1; }
e_ctx_update_func(void *,const uchar *,uint,uchar *,uint *)3228 int e_ctx_update_func(void *, const uchar*, uint, uchar*, uint*) { return 1; }
e_ctx_finish_func(void *,uchar *,uint *)3229 int e_ctx_finish_func(void *, uchar*, uint*) { return 1; }
e_encrypted_length_func(uint,uint,uint)3230 uint e_encrypted_length_func(uint, uint, uint) { return 1; }
3231
3232 struct encryption_service_st encryption_handler=
3233 {
3234 e_key_get_latest_version_func,
3235 e_key_get_func,
3236 e_ctx_size_func,
3237 e_ctx_init_func,
3238 e_ctx_update_func,
3239 e_ctx_finish_func,
3240 e_encrypted_length_func
3241 };
3242
3243 /*
3244 We must include this here as it's compiled with different options for
3245 the server
3246 */
3247
3248 #include "rpl_tblmap.cc"
3249 #undef TABLE
3250 #include "my_decimal.h"
3251 #include "decimal.c"
3252 #include "my_decimal.cc"
3253 #include "../sql-common/my_time.c"
3254 #include "password.c"
3255 #include "log_event.cc"
3256 #include "log_event_old.cc"
3257 #include "rpl_utility.cc"
3258 #include "sql_string.cc"
3259 #include "sql_list.cc"
3260 #include "rpl_filter.cc"
3261 #include "compat56.cc"
3262