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 185 static void free_annotate_event() 186 { 187 if (annotate_event) 188 { 189 delete annotate_event; 190 annotate_event= 0; 191 } 192 } 193 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 225 void keep_annotate_event(Annotate_rows_log_event* event) 226 { 227 free_annotate_event(); 228 annotate_event= event; 229 } 230 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 */ 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: 307 Load_log_processor() {} 308 ~Load_log_processor() {} 309 310 int init() 311 { 312 return my_init_dynamic_array(&file_names, sizeof(File_name_record), 313 100, 100, MYF(0)); 314 } 315 316 void init_by_dir_name(const char *dir) 317 { 318 target_dir_name_len= (convert_dirname(target_dir_name, dir, NullS) - 319 target_dir_name); 320 } 321 void init_by_cur_dir() 322 { 323 if (my_getwd(target_dir_name,sizeof(target_dir_name),MYF(MY_WME))) 324 exit(1); 325 target_dir_name_len= strlen(target_dir_name); 326 } 327 void destroy() 328 { 329 File_name_record *ptr= (File_name_record *)file_names.buffer; 330 File_name_record *end= ptr + file_names.elements; 331 for (; ptr < end; ptr++) 332 { 333 if (ptr->fname) 334 { 335 my_free(ptr->fname); 336 delete ptr->event; 337 bzero((char *)ptr, sizeof(File_name_record)); 338 } 339 } 340 341 delete_dynamic(&file_names); 342 } 343 344 /** 345 Obtain Create_file event for LOAD DATA statement by its file_id 346 and remove it from this Load_log_processor's list of events. 347 348 Checks whether we have already seen a Create_file_log_event with 349 the given file_id. If yes, returns a pointer to the event and 350 removes the event from array describing active temporary files. 351 From this moment, the caller is responsible for freeing the memory 352 occupied by the event. 353 354 @param[in] file_id File id identifying LOAD DATA statement. 355 356 @return Pointer to Create_file_log_event, or NULL if we have not 357 seen any Create_file_log_event with this file_id. 358 */ 359 Create_file_log_event *grab_event(uint file_id) 360 { 361 File_name_record *ptr; 362 Create_file_log_event *res; 363 364 if (file_id >= file_names.elements) 365 return 0; 366 ptr= dynamic_element(&file_names, file_id, File_name_record*); 367 if ((res= ptr->event)) 368 bzero((char *)ptr, sizeof(File_name_record)); 369 return res; 370 } 371 372 /** 373 Obtain file name of temporary file for LOAD DATA statement by its 374 file_id and remove it from this Load_log_processor's list of events. 375 376 @param[in] file_id Identifier for the LOAD DATA statement. 377 378 Checks whether we have already seen Begin_load_query event for 379 this file_id. If yes, returns the file name of the corresponding 380 temporary file and removes the filename from the array of active 381 temporary files. From this moment, the caller is responsible for 382 freeing the memory occupied by this name. 383 384 @return String with the name of the temporary file, or NULL if we 385 have not seen any Begin_load_query_event with this file_id. 386 */ 387 char *grab_fname(uint file_id) 388 { 389 File_name_record *ptr; 390 char *res= 0; 391 392 if (file_id >= file_names.elements) 393 return 0; 394 ptr= dynamic_element(&file_names, file_id, File_name_record*); 395 if (!ptr->event) 396 { 397 res= ptr->fname; 398 bzero((char *)ptr, sizeof(File_name_record)); 399 } 400 return res; 401 } 402 Exit_status process(Create_file_log_event *ce); 403 Exit_status process(Begin_load_query_log_event *ce); 404 Exit_status process(Append_block_log_event *ae); 405 File prepare_new_file_for_old_format(Load_log_event *le, char *filename); 406 Exit_status load_old_format_file(NET* net, const char *server_fname, 407 uint server_fname_len, File file); 408 Exit_status process_first_event(const char *bname, size_t blen, 409 const uchar *block, 410 size_t block_len, uint file_id, 411 Create_file_log_event *ce); 412 }; 413 414 415 /** 416 Creates and opens a new temporary file in the directory specified by previous call to init_by_dir_name() or init_by_cur_dir(). 417 418 @param[in] le The basename of the created file will start with the 419 basename of the file pointed to by this Load_log_event. 420 421 @param[out] filename Buffer to save the filename in. 422 423 @return File handle >= 0 on success, -1 on error. 424 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 */ 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 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 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 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 */ 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 */ 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 */ 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 */ 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 */ 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 */ 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 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 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 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 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 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 */ 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 */ 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 */ 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 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 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 */ 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 */ 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 */ 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 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 3234 uint e_key_get_latest_version_func(uint) { return 1; } 3235 uint e_key_get_func(uint, uint, uchar*, uint*) { return 1; } 3236 uint e_ctx_size_func(uint, uint) { return 1; } 3237 int e_ctx_init_func(void *, const uchar*, uint, const uchar*, uint, 3238 int, uint, uint) { return 1; } 3239 int e_ctx_update_func(void *, const uchar*, uint, uchar*, uint*) { return 1; } 3240 int e_ctx_finish_func(void *, uchar*, uint*) { return 1; } 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