From 81402c131875c5fc2c3c4078bc12770304a48861 Mon Sep 17 00:00:00 2001 From: Brandon Nesterenko Date: Wed, 12 May 2021 11:46:58 -0600 Subject: [PATCH] MDEV-25222: mysqlbinlog --base64-output wrong option default drops BINLOG from output Problem: ======= The ALWAYS option of the mariadb-binlog --base64-output flag formats its output incorrectly. This option is deprecated, and MySQL 8.0 has removed it entirely. Solution: ======== Adhere to MySQL and remove this option from MariaDB. Behavioral Changes: ================== Use Case: ./mariadb-binlog --base64-output Previous Behavior: Sets base64-output mode to always New Behavior: Error message indicating incomplete argument Use Case: ./mariadb-binlog --base64-output=always Previous Behavior: Sets base64-output mode to always New Behavior: Error message indicating invalid argument value Reviewed By: ========== Andrei Elkin: --- client/mysqlbinlog.cc | 111 +++++------------------------ man/mysqlbinlog.1 | 18 +---- mysql-test/main/mysqlbinlog.result | 15 +++- mysql-test/main/mysqlbinlog.test | 32 ++++++--- sql/log_event.h | 5 +- 5 files changed, 57 insertions(+), 124 deletions(-) diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc index fd31ab6694e..b262cd9d7c9 100644 --- a/client/mysqlbinlog.cc +++ b/client/mysqlbinlog.cc @@ -112,7 +112,7 @@ static void warning(const char *format, ...) ATTRIBUTE_FORMAT(printf, 1, 2); static bool one_database=0, one_table=0, to_last_remote_log= 0, disable_log_bin= 0; static bool opt_hexdump= 0, opt_version= 0; const char *base64_output_mode_names[]= -{"NEVER", "AUTO", "ALWAYS", "UNSPEC", "DECODE-ROWS", NullS}; +{"NEVER", "AUTO", "UNSPEC", "DECODE-ROWS", NullS}; TYPELIB base64_output_mode_typelib= { array_elements(base64_output_mode_names) - 1, "", base64_output_mode_names, NULL }; @@ -834,53 +834,6 @@ static bool shall_skip_table(const char *log_tblname) strcmp(log_tblname, table); } - -/** - Prints the given event in base64 format. - - The header is printed to the head cache and the body is printed to - the body cache of the print_event_info structure. This allows all - base64 events corresponding to the same statement to be joined into - one BINLOG statement. - - @param[in] ev Log_event to print. - @param[in,out] result_file FILE to which the output will be written. - @param[in,out] print_event_info Parameters and context state - determining how to print. - - @retval ERROR_STOP An error occurred - the program should terminate. - @retval OK_CONTINUE No error, the program should continue. -*/ -static Exit_status -write_event_header_and_base64(Log_event *ev, FILE *result_file, - PRINT_EVENT_INFO *print_event_info) -{ - IO_CACHE *head= &print_event_info->head_cache; - IO_CACHE *body= &print_event_info->body_cache; - DBUG_ENTER("write_event_header_and_base64"); - - /* Write header and base64 output to cache */ - if (ev->print_header(head, print_event_info, FALSE)) - DBUG_RETURN(ERROR_STOP); - - DBUG_ASSERT(print_event_info->base64_output_mode == BASE64_OUTPUT_ALWAYS); - - if (ev->print_base64(body, print_event_info, - print_event_info->base64_output_mode != - BASE64_OUTPUT_DECODE_ROWS)) - DBUG_RETURN(ERROR_STOP); - - /* Read data from cache and write to result file */ - if (copy_event_cache_to_file_and_reinit(head, result_file) || - copy_event_cache_to_file_and_reinit(body, result_file)) - { - error("Error writing event to file."); - DBUG_RETURN(ERROR_STOP); - } - DBUG_RETURN(OK_CONTINUE); -} - - static bool print_base64(PRINT_EVENT_INFO *print_event_info, Log_event *ev) { /* @@ -1132,19 +1085,9 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, qe->flags|= LOG_EVENT_SUPPRESS_USE_F; } print_use_stmt(print_event_info, qe); - if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS) - { - if ((retval= write_event_header_and_base64(ev, result_file, - print_event_info)) != - OK_CONTINUE) - goto end; - } - else - { - print_skip_replication_statement(print_event_info, ev); - if (ev->print(result_file, print_event_info)) - goto err; - } + print_skip_replication_statement(print_event_info, ev); + if (ev->print(result_file, print_event_info)) + goto err; if (head->error == -1) goto err; break; @@ -1168,19 +1111,9 @@ Exit_status process_event(PRINT_EVENT_INFO *print_event_info, Log_event *ev, filename and use LOCAL), prepared in the 'case EXEC_LOAD_EVENT' below. */ - if (opt_base64_output_mode == BASE64_OUTPUT_ALWAYS) - { - if ((retval= write_event_header_and_base64(ce, result_file, - print_event_info)) != - OK_CONTINUE) - goto end; - } - else - { - print_skip_replication_statement(print_event_info, ev); - if (ce->print(result_file, print_event_info, TRUE)) - goto err; - } + print_skip_replication_statement(print_event_info, ev); + if (ce->print(result_file, print_event_info, TRUE)) + goto err; // If this binlog is not 3.23 ; why this test?? if (glob_description_event->binlog_version >= 3) { @@ -1587,12 +1520,10 @@ static struct my_option my_options[] = "--verbose option is also given; " "'auto' prints base64 only when necessary (i.e., for row-based events and " "format description events); " - "'always' prints base64 whenever possible. " - "--base64-output with no 'name' argument is equivalent to " - "--base64-output=always and is also deprecated. If no " - "--base64-output[=name] option is given at all, the default is 'auto'.", + "If no --base64-output=name option is given at all, the default is " + "'auto'.", &opt_base64_output_mode_str, &opt_base64_output_mode_str, - 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0}, + 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0}, /* mysqlbinlog needs charsets knowledge, to be able to convert a charset number found in binlog to a charset name (to be able to print things @@ -2024,20 +1955,15 @@ get_one_option(const struct my_option *opt, const char *argument, const char *) stop_datetime= convert_str_to_timestamp(stop_datetime_str); break; case OPT_BASE64_OUTPUT_MODE: - if (argument == NULL) - opt_base64_output_mode= BASE64_OUTPUT_ALWAYS; - else - { - int val; + int val; - if ((val= find_type_with_warning(argument, &base64_output_mode_typelib, - opt->name)) <= 0) - { - sf_leaking_memory= 1; /* no memory leak reports here */ - die(); - } - opt_base64_output_mode= (enum_base64_output_mode) (val - 1); + if ((val= find_type_with_warning(argument, &base64_output_mode_typelib, + opt->name)) <= 0) + { + sf_leaking_memory= 1; /* no memory leak reports here */ + die(); } + opt_base64_output_mode= (enum_base64_output_mode)(val - 1); break; case OPT_REWRITE_DB: // db_from->db_to { @@ -2855,8 +2781,7 @@ static Exit_status check_header(IO_CACHE* file, (ulonglong)tmp_pos); return ERROR_STOP; } - if (opt_base64_output_mode == BASE64_OUTPUT_AUTO - || opt_base64_output_mode == BASE64_OUTPUT_ALWAYS) + if (opt_base64_output_mode == BASE64_OUTPUT_AUTO) { /* process_event will delete *description_event and set it to diff --git a/man/mysqlbinlog.1 b/man/mysqlbinlog.1 index c475f8a9887..42eb1b38272 100644 --- a/man/mysqlbinlog.1 +++ b/man/mysqlbinlog.1 @@ -141,7 +141,7 @@ Display a help message and exit\&. .\} .\" mysqlbinlog: base64-output option .\" base64-output option: mysqlbinlog -\fB\-\-base64\-output[=\fR\fB\fIvalue\fR\fR\fB]\fR +\fB\-\-base64\-output=\fR\fB\fIvalue\fR\fR\fB\fR .sp This option determines when events should be displayed encoded as base\-64 strings using BINLOG @@ -192,22 +192,6 @@ to re\-execute binary log file contents\&. The other option values are intended .sp -1 .IP \(bu 2.3 .\} -ALWAYS -displays -BINLOG -statements whenever possible\&. This is the implied value if the option is given as -\fB\-\-base64\-output\fR -without a value\&. Both ALWAYS and not giving a value are deprecated. -.RE -.sp -.RS 4 -.ie n \{\ -\h'-04'\(bu\h'+03'\c -.\} -.el \{\ -.sp -1 -.IP \(bu 2.3 -.\} NEVER causes BINLOG diff --git a/mysql-test/main/mysqlbinlog.result b/mysql-test/main/mysqlbinlog.result index 8e12ecdf8c1..83cc2ef510a 100644 --- a/mysql-test/main/mysqlbinlog.result +++ b/mysql-test/main/mysqlbinlog.result @@ -878,8 +878,19 @@ ROLLBACK /* added by mysqlbinlog */; /*!50530 SET @@SESSION.PSEUDO_SLAVE_MODE=0*/; End of 5.0 tests End of 5.1 tests -# Expect deprecation warning. -# Expect deprecation warning again. +# +# Expect error for invalid --base64-output argument value. +# MYSQL_BINLOG std_data/master-bin.000001 --base64-output=always 2>&1 +Unknown option to base64-output: always +Alternatives are: 'NEVER','AUTO','UNSPEC','DECODE-ROWS' +# +# Expect error for incomplete --base64-output argument. +# MYSQL_BINLOG std_data/master-bin.000001 --base64-output 2>&1 +mysqlbinlog: option '--base64-output' requires an argument +# +# Ensure --base64-output=auto outputs the same result as unspecified +# MYSQL_BINLOG -v MYSQLD_DATADIR/master-bin.000001 > MYSQLTEST_VARDIR/tmp/mysqlbinlog_nob64spec.out +# MYSQL_BINLOG --base64-output=auto -v MYSQLD_DATADIR/master-bin.000001 > MYSQLTEST_VARDIR/tmp/mysqlbinlog_b64auto.out RESET MASTER; CREATE DATABASE test1; USE test1; diff --git a/mysql-test/main/mysqlbinlog.test b/mysql-test/main/mysqlbinlog.test index 79b745e1645..c8a141404d0 100644 --- a/mysql-test/main/mysqlbinlog.test +++ b/mysql-test/main/mysqlbinlog.test @@ -521,18 +521,32 @@ remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn.empty; remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn; # -# WL#5625: Deprecate mysqlbinlog options --base64-output=always and --base64-output +# MDEV-25222: Remove mysqlbinlog options --base64-output=always and --base64-output # ---echo # Expect deprecation warning. ---exec $MYSQL_BINLOG --base64-output=always std_data/master-bin.000001 > /dev/null 2> $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn ---cat_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn +--echo # +--echo # Expect error for invalid --base64-output argument value. +--echo # MYSQL_BINLOG std_data/master-bin.000001 --base64-output=always 2>&1 +--error 1 +--exec $MYSQL_BINLOG std_data/master-bin.000001 --base64-output=always 2>&1 ---echo # Expect deprecation warning again. ---exec $MYSQL_BINLOG --base64-output std_data/master-bin.000001 > /dev/null 2> $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn ---cat_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn +--echo # +--echo # Expect error for incomplete --base64-output argument. +--echo # MYSQL_BINLOG std_data/master-bin.000001 --base64-output 2>&1 +# The error produces the absolute path of the mysqlbinlog executable, remove it. +--replace_regex /.*mysqlbinlog.*:/mysqlbinlog:/i +--error 1 +--exec $MYSQL_BINLOG std_data/master-bin.000001 --base64-output 2>&1 + +--echo # +--echo # Ensure --base64-output=auto outputs the same result as unspecified +--echo # MYSQL_BINLOG -v MYSQLD_DATADIR/master-bin.000001 > MYSQLTEST_VARDIR/tmp/mysqlbinlog_nob64spec.out +--exec $MYSQL_BINLOG -v $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_nob64spec.out +--echo # MYSQL_BINLOG --base64-output=auto -v MYSQLD_DATADIR/master-bin.000001 > MYSQLTEST_VARDIR/tmp/mysqlbinlog_b64auto.out +--exec $MYSQL_BINLOG --base64-output=auto -v $MYSQLD_DATADIR/master-bin.000001 > $MYSQLTEST_VARDIR/tmp/mysqlbinlog_b64auto.out +--diff_files $MYSQLTEST_VARDIR/tmp/mysqlbinlog_nob64spec.out $MYSQLTEST_VARDIR/tmp/mysqlbinlog_b64auto.out +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_nob64spec.out +--remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog_b64auto.out -# Clean up this part of the test. ---remove_file $MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn # BUG#50914 # This test verifies if the approach of the mysqlbinlog prints diff --git a/sql/log_event.h b/sql/log_event.h index 3e08653a211..6a224b7b6a1 100644 --- a/sql/log_event.h +++ b/sql/log_event.h @@ -822,9 +822,8 @@ bool copy_event_cache_to_file_and_reinit(IO_CACHE *cache, FILE *file); enum enum_base64_output_mode { BASE64_OUTPUT_NEVER= 0, BASE64_OUTPUT_AUTO= 1, - BASE64_OUTPUT_ALWAYS= 2, - BASE64_OUTPUT_UNSPEC= 3, - BASE64_OUTPUT_DECODE_ROWS= 4, + BASE64_OUTPUT_UNSPEC= 2, + BASE64_OUTPUT_DECODE_ROWS= 3, /* insert new output modes here */ BASE64_OUTPUT_MODE_COUNT };