Fractional part < 100000 microseconds was printed without leading zeros,
causing such timestamps to be applied incorrectly in mariadb-binlog | mysql

Signed-off-by: Kristian Nielsen <kniel...@knielsen-hq.org>
---
 mysql-test/main/mysqlbinlog.result | 26 ++++++++++++++++++++++++
 mysql-test/main/mysqlbinlog.test   | 32 ++++++++++++++++++++++++++++++
 sql/log_event_client.cc            |  7 +++++--
 3 files changed, 63 insertions(+), 2 deletions(-)

diff --git a/mysql-test/main/mysqlbinlog.result 
b/mysql-test/main/mysqlbinlog.result
index c6d9ef97229..76ded3d31f8 100644
--- a/mysql-test/main/mysqlbinlog.result
+++ b/mysql-test/main/mysqlbinlog.result
@@ -1286,3 +1286,29 @@ ERROR: Bad syntax in rewrite-db: empty FROM db
 
 ERROR: Bad syntax in rewrite-db: empty FROM db
 
+#
+# MDEV-31761: Timestamp is written into binary log incorrectly
+#
+SET SESSION binlog_format= MIXED;
+RESET MASTER;
+CREATE TABLE t (a INT,
+b TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE CURRENT_TIMESTAMP(6));
+set SESSION timestamp= 1689978980.012345;
+INSERT INTO t (a) VALUES (1);
+SELECT * from t;
+a      b
+1      2023-07-22 00:36:20.012345
+FLUSH BINARY LOGS;
+SET SESSION timestamp= 1689978980.567890;
+SET SESSION binlog_format= ROW;
+UPDATE t SET a = 2;
+FLUSH BINARY LOGS;
+SET SESSION binlog_format= STATEMENT;
+DROP TABLE t;
+SELECT * FROM t;
+a      b
+1      2023-07-22 00:36:20.012345
+SELECT * FROM t;
+a      b
+2      2023-07-22 00:36:20.567890
+DROP TABLE t;
diff --git a/mysql-test/main/mysqlbinlog.test b/mysql-test/main/mysqlbinlog.test
index 22a85393a35..1747d55d29d 100644
--- a/mysql-test/main/mysqlbinlog.test
+++ b/mysql-test/main/mysqlbinlog.test
@@ -637,3 +637,35 @@ FLUSH LOGS;
 --exec $MYSQL_BINLOG --rewrite-db=" ->" --short-form 
$MYSQLD_DATADIR/master-bin.000001 2>&1
 
 --exec $MYSQL_BINLOG --rewrite-db=" test -> foo " --short-form 
$MYSQLD_DATADIR/master-bin.000001 > /dev/null 2> 
$MYSQLTEST_VARDIR/tmp/mysqlbinlog.warn
+
+
+--echo #
+--echo # MDEV-31761: Timestamp is written into binary log incorrectly
+--echo #
+
+SET SESSION binlog_format= MIXED;
+
+RESET MASTER;
+CREATE TABLE t (a INT,
+                b TIMESTAMP(6) DEFAULT CURRENT_TIMESTAMP(6) ON UPDATE 
CURRENT_TIMESTAMP(6));
+set SESSION timestamp= 1689978980.012345;
+INSERT INTO t (a) VALUES (1);
+SELECT * from t;
+FLUSH BINARY LOGS;
+SET SESSION timestamp= 1689978980.567890;
+SET SESSION binlog_format= ROW;
+UPDATE t SET a = 2;
+FLUSH BINARY LOGS;
+SET SESSION binlog_format= STATEMENT;
+
+# Replay to see that timestamps are applied correctly.
+# The bug was that leading zeros on the fractional part were not included in
+# the mysqlbinlog output, so 1689978980.012345 was applied as 1689978980.12345.
+
+DROP TABLE t;
+--let $datadir= `select @@datadir`
+--exec $MYSQL_BINLOG $datadir/master-bin.000001 | $MYSQL test
+SELECT * FROM t;
+--exec $MYSQL_BINLOG $datadir/master-bin.000002 | $MYSQL test
+SELECT * FROM t;
+DROP TABLE t;
diff --git a/sql/log_event_client.cc b/sql/log_event_client.cc
index 11fabbbca39..720cc5ab611 100644
--- a/sql/log_event_client.cc
+++ b/sql/log_event_client.cc
@@ -1851,8 +1851,11 @@ bool Query_log_event::print_query_header(IO_CACHE* file,
   end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10);
   if (when_sec_part && when_sec_part <= TIME_MAX_SECOND_PART)
   {
-    *end++= '.';
-    end=int10_to_str(when_sec_part, end, 10);
+    char buff2[1 + 6 + 1];
+    /* Ensure values < 100000 are printed with leading zeros, MDEV-31761. */
+    snprintf(buff2, sizeof(buff2), ".%06lu", when_sec_part);
+    DBUG_ASSERT(strlen(buff2) == 1 + 6);
+    end= strmov(end, buff2);
   }
   end= strmov(end, print_event_info->delimiter);
   *end++='\n';
-- 
2.39.5

_______________________________________________
commits mailing list -- commits@lists.mariadb.org
To unsubscribe send an email to commits-le...@lists.mariadb.org

Reply via email to