From e3f8276dace389e8bb5346346f9ba95aa6e9c2c5 Mon Sep 17 00:00:00 2001 From: Jan Grodowski Date: Fri, 24 Jan 2025 07:59:49 +0100 Subject: [PATCH 1/2] Use 64 bit size when formatting FloatWithTrailingZero Caused errors with moves that involve double precision numbers in JSON blobs. Co-authored-by: Merve Taner --- test/integration/types_test.rb | 12 ++++++++---- .../go-mysql-org/go-mysql/replication/json_binary.go | 4 ++-- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/test/integration/types_test.rb b/test/integration/types_test.rb index 86f8cfa3..1b718d40 100644 --- a/test/integration/types_test.rb +++ b/test/integration/types_test.rb @@ -3,6 +3,7 @@ class TypesTest < GhostferryTestCase JSON_OBJ = '{"data": {"quote": "\\\'", "value": [1, 12.13]}}' JSON_OBJ_WITH_TRAILING_ZERO = '{"data": {"float": 32.0}}' + JSON_OBJ_LAT_LONG = '{ "lat": 43.72437629996218, "long": -79.45382688031805 }' EMPTY_JSON = '{}' JSON_ARRAY = '[\"test_data\", \"test_data_2\"]' JSON_NULL = 'null' @@ -199,7 +200,7 @@ def test_json_data_update loop do sleep 0.1 res = target_db.query("SELECT COUNT(*) AS cnt FROM #{DEFAULT_FULL_TABLE_NAME}") - if res.first["cnt"] == 11 + if res.first["cnt"] == 12 source_db.query("UPDATE #{DEFAULT_FULL_TABLE_NAME} SET data = '#{EMPTY_JSON}' WHERE id = 1") source_db.query("UPDATE #{DEFAULT_FULL_TABLE_NAME} SET data = '#{JSON_ARRAY}' WHERE id = 2") source_db.query("UPDATE #{DEFAULT_FULL_TABLE_NAME} SET data = NULL WHERE id = 3") @@ -210,7 +211,8 @@ def test_json_data_update source_db.query("UPDATE #{DEFAULT_FULL_TABLE_NAME} SET data = '#{JSON_FLOATING_POINT_WITH_ZERO_FRACTIONAL_PART}' WHERE id = 8") source_db.query("UPDATE #{DEFAULT_FULL_TABLE_NAME} SET data = '#{JSON_FLOATING_POINT_WITH_NON_ZERO_FRACTIONAL_PART}' WHERE id = 9") source_db.query("UPDATE #{DEFAULT_FULL_TABLE_NAME} SET data = '#{JSON_NUMBER}' WHERE id = 10") - source_db.query("UPDATE #{DEFAULT_FULL_TABLE_NAME} SET data = '#{JSON_OBJ}' WHERE id = 11") + source_db.query("UPDATE #{DEFAULT_FULL_TABLE_NAME} SET data = '#{JSON_OBJ_LAT_LONG}' WHERE id = 11") + source_db.query("UPDATE #{DEFAULT_FULL_TABLE_NAME} SET data = '#{JSON_OBJ}' WHERE id = 12") break end @@ -225,7 +227,7 @@ def test_json_data_update refute timedout, "failed due to time out while waiting for the 4 insert binlogs to be written to the target" res = target_db.query("SELECT COUNT(*) AS cnt FROM #{DEFAULT_FULL_TABLE_NAME}") - assert_equal 11, res.first["cnt"] + assert_equal 12, res.first["cnt"] expected = [ {"id"=>1, "data"=>"{}"}, @@ -238,7 +240,8 @@ def test_json_data_update {"id"=>8, "data"=>format_float_based_on_mysql_version("52.0")}, {"id"=>9, "data"=>"52.13"}, {"id" => 10, "data" => "42"}, - {"id" => 11, "data" => "{\"data\": {\"quote\": \"'\", \"value\": [1, 12.13]}}"}, + {"id" => 11, "data" => "{\"lat\": 43.72437629996218, \"long\": -79.45382688031805}"}, + {"id" => 12, "data" => "{\"data\": {\"quote\": \"'\", \"value\": [1, 12.13]}}"}, ] res = target_db.query("SELECT * FROM #{DEFAULT_FULL_TABLE_NAME} ORDER BY id ASC") @@ -423,6 +426,7 @@ def insert_json_on_source source_db.query("INSERT INTO #{DEFAULT_FULL_TABLE_NAME} (data) VALUES ('#{JSON_FLOATING_POINT_WITH_NON_ZERO_FRACTIONAL_PART}')") source_db.query("INSERT INTO #{DEFAULT_FULL_TABLE_NAME} (data) VALUES ('#{JSON_FLOATING_POINT_WITH_ZERO_FRACTIONAL_PART}')") source_db.query("INSERT INTO #{DEFAULT_FULL_TABLE_NAME} (data) VALUES ('#{JSON_OBJ_WITH_TRAILING_ZERO}')") + source_db.query("INSERT INTO #{DEFAULT_FULL_TABLE_NAME} (data) VALUES ('#{JSON_OBJ_LAT_LONG}')") end def execute_copy_data_in_fixed_size_binary_column(column_size:, inserted_data:, expected_inserted_data:, updated_data:) diff --git a/vendor/github.com/go-mysql-org/go-mysql/replication/json_binary.go b/vendor/github.com/go-mysql-org/go-mysql/replication/json_binary.go index e8d87256..3f1f993f 100644 --- a/vendor/github.com/go-mysql-org/go-mysql/replication/json_binary.go +++ b/vendor/github.com/go-mysql-org/go-mysql/replication/json_binary.go @@ -49,10 +49,10 @@ type FloatWithTrailingZero float64 func (f FloatWithTrailingZero) MarshalJSON() ([]byte, error) { if float64(f) == float64(int(f)) { - return []byte(strconv.FormatFloat(float64(f), 'f', 1, 32)), nil + return []byte(strconv.FormatFloat(float64(f), 'f', 1, 64)), nil } - return []byte(strconv.FormatFloat(float64(f), 'f', -1, 32)), nil + return []byte(strconv.FormatFloat(float64(f), 'f', -1, 64)), nil } func jsonbGetOffsetSize(isSmall bool) int { From 7daba759cba3e850562f5cf7d1f5b1641753e672 Mon Sep 17 00:00:00 2001 From: Jan Grodowski Date: Fri, 24 Jan 2025 08:24:48 +0100 Subject: [PATCH 2/2] update test_types to account for the extra insert Co-authored-by: Merve Taner --- test/integration/types_test.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/test/integration/types_test.rb b/test/integration/types_test.rb index 1b718d40..4545e75b 100644 --- a/test/integration/types_test.rb +++ b/test/integration/types_test.rb @@ -107,7 +107,7 @@ def test_json_data_insert # with a JSON column is broken on 5.7. # See: https://bugs.mysql.com/bug.php?id=87847 res = target_db.query("SELECT COUNT(*) AS cnt FROM #{DEFAULT_FULL_TABLE_NAME}") - assert_equal 22, res.first["cnt"] + assert_equal 24, res.first["cnt"] expected = [ {"id"=>1, "data"=>"{\"data\": {\"quote\": \"'\", \"value\": [1, 12.13]}}"}, @@ -120,7 +120,8 @@ def test_json_data_insert {"id"=>8, "data"=>"42"}, {"id"=>9, "data"=>"52.13"}, {"id" => 10, "data" => format_float_based_on_mysql_version("52.0")}, - {"id" => 11, "data" => "{\"data\": {\"float\": #{format_float_based_on_mysql_version("32.0")}}}"} + {"id" => 11, "data" => "{\"data\": {\"float\": #{format_float_based_on_mysql_version("32.0")}}}"}, + {"id" => 12, "data" => "{\"lat\": 43.72437629996218, \"long\": -79.45382688031805}"} ] expected_length = expected.length @@ -158,8 +159,8 @@ def test_json_data_delete loop do sleep 0.1 res = target_db.query("SELECT COUNT(*) AS cnt FROM #{DEFAULT_FULL_TABLE_NAME}") - if res.first["cnt"] == 11 - 1.upto(11) do |i| + if res.first["cnt"] == 12 + 1.upto(12) do |i| source_db.query("DELETE FROM #{DEFAULT_FULL_TABLE_NAME} WHERE id = #{i}") end break