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