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