Skip to content

Commit 652fa9a

Browse files
committedSep 24, 2023
- fix bug when long json string type
- change json array type format - add Json testcases add update Json testcase add test datetime,decimal,time cases
1 parent 401fb87 commit 652fa9a

File tree

4 files changed

+48
-28
lines changed

4 files changed

+48
-28
lines changed
 

‎pymysqlreplication/packet.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -133,7 +133,7 @@ def parse_json_object_or_array(bytes, is_small, is_object):
133133
return None
134134
values[i] = parse_json(json_type, bytes[value_offset:])
135135
if not is_object:
136-
return values
136+
return list(values.values())
137137
out = {}
138138
for i in range(count):
139139
out[keys[i]] = values[i]

‎pymysqlreplication/tests/test_basic.py

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -596,6 +596,33 @@ def create_binlog_packet_wrapper(pkt):
596596
self.assertEqual(binlog_event.event._is_event_valid, True)
597597
self.assertNotEqual(wrong_event.event._is_event_valid, True)
598598

599+
def test_json_update(self):
600+
self.stream.close()
601+
self.stream = BinLogStreamReader(
602+
self.database, server_id=1024, only_events=[UpdateRowsEvent]
603+
)
604+
create_query = (
605+
"CREATE TABLE setting_table( id SERIAL AUTO_INCREMENT, setting JSON);"
606+
)
607+
insert_query = """INSERT INTO setting_table (setting) VALUES ('{"btn": true, "model": false}');"""
608+
609+
update_query = """ UPDATE setting_table
610+
SET setting = JSON_REMOVE(setting, '$.model')
611+
WHERE id=1;
612+
"""
613+
self.execute(create_query)
614+
self.execute(insert_query)
615+
self.execute(update_query)
616+
self.execute("COMMIT;")
617+
event = self.stream.fetchone()
618+
619+
if event.table_map[event.table_id].column_name_flag:
620+
self.assertEqual(
621+
event.rows[0]["before_values"]["setting"],
622+
{b"btn": True, b"model": False},
623+
),
624+
self.assertEqual(event.rows[0]["after_values"]["setting"], {b"btn": True}),
625+
599626

600627
class TestMultipleRowBinLogStreamReader(base.PyMySQLReplicationTestCase):
601628
def setUp(self):

‎pymysqlreplication/tests/test_data_type.py

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -588,8 +588,6 @@ def test_geometry(self):
588588
)
589589

590590
def test_json(self):
591-
if not self.isMySQL57():
592-
self.skipTest("Json is only supported in mysql 5.7")
593591
create_query = "CREATE TABLE test (id int, value json);"
594592
insert_query = """INSERT INTO test (id, value) VALUES (1, '{"my_key": "my_val", "my_key2": "my_val2"}');"""
595593
event = self.create_and_insert_value(create_query, insert_query)
@@ -600,8 +598,6 @@ def test_json(self):
600598
)
601599

602600
def test_json_array(self):
603-
if not self.isMySQL57():
604-
self.skipTest("Json is only supported in mysql 5.7")
605601
create_query = "CREATE TABLE test (id int, value json);"
606602
insert_query = (
607603
"""INSERT INTO test (id, value) VALUES (1, '["my_val", "my_val2"]');"""
@@ -611,8 +607,6 @@ def test_json_array(self):
611607
self.assertEqual(event.rows[0]["values"]["value"], [b"my_val", b"my_val2"])
612608

613609
def test_json_large(self):
614-
if not self.isMySQL57():
615-
self.skipTest("Json is only supported in mysql 5.7")
616610
data = dict(
617611
[("foooo%i" % i, "baaaaar%i" % i) for i in range(2560)]
618612
) # Make it large enough to reach 2^16 length
@@ -626,8 +620,6 @@ def test_json_large(self):
626620

627621
def test_json_large_array(self):
628622
"Test json array larger than 64k bytes"
629-
if not self.isMySQL57():
630-
self.skipTest("Json is only supported in mysql 5.7")
631623
create_query = "CREATE TABLE test (id int, value json);"
632624
large_array = dict(my_key=[i for i in range(100000)])
633625
insert_query = "INSERT INTO test (id, value) VALUES (1, '%s');" % (
@@ -640,8 +632,6 @@ def test_json_large_array(self):
640632
)
641633

642634
def test_json_large_with_literal(self):
643-
if not self.isMySQL57():
644-
self.skipTest("Json is only supported in mysql 5.7")
645635
data = dict(
646636
[("foooo%i" % i, "baaaaar%i" % i) for i in range(2560)], literal=True
647637
) # Make it large with literal
@@ -654,9 +644,6 @@ def test_json_large_with_literal(self):
654644
self.assertEqual(event.rows[0]["values"]["value"], to_binary_dict(data))
655645

656646
def test_json_types(self):
657-
if not self.isMySQL57():
658-
self.skipTest("Json is only supported in mysql 5.7")
659-
660647
types = [
661648
True,
662649
False,
@@ -685,9 +672,6 @@ def test_json_types(self):
685672
self.setUp()
686673

687674
def test_json_basic(self):
688-
if not self.isMySQL57():
689-
self.skipTest("Json is only supported in mysql 5.7")
690-
691675
types = [
692676
True,
693677
False,
@@ -714,8 +698,6 @@ def test_json_basic(self):
714698
self.setUp()
715699

716700
def test_json_unicode(self):
717-
if not self.isMySQL57():
718-
self.skipTest("Json is only supported in mysql 5.7")
719701
create_query = "CREATE TABLE test (id int, value json);"
720702
insert_query = """INSERT INTO test (id, value) VALUES (1, '{"miam": "🍔"}');"""
721703
event = self.create_and_insert_value(create_query, insert_query)
@@ -725,8 +707,6 @@ def test_json_unicode(self):
725707
)
726708

727709
def test_json_long_string(self):
728-
if not self.isMySQL57():
729-
self.skipTest("Json is only supported in mysql 5.7")
730710
create_query = "CREATE TABLE test (id int, value json);"
731711
# The string length needs to be larger than what can fit in a single byte.
732712
string_value = "super_long_string" * 100
@@ -735,12 +715,31 @@ def test_json_long_string(self):
735715
% (string_value,)
736716
)
737717
event = self.create_and_insert_value(create_query, insert_query)
718+
print(event.rows[0])
738719
if event.table_map[event.table_id].column_name_flag:
739720
self.assertEqual(
740721
event.rows[0]["values"]["value"],
741722
to_binary_dict({"my_key": string_value}),
742723
)
743724

725+
def test_json_deciaml_time_datetime(self):
726+
create_query = """CREATE TABLE json_deciaml_time_datetime_test (
727+
id INT PRIMARY KEY AUTO_INCREMENT,
728+
json_data JSON
729+
);"""
730+
insert_query = """
731+
INSERT INTO json_deciaml_time_datetime_test (json_data) VALUES (JSON_OBJECT('time_key', CAST('18:54:12' AS TIME), 'datetime_key', CAST('2023-09-24 18:54:12' AS DATETIME) ,'decimal', CAST('99.99' AS DECIMAL(10, 2))));"""
732+
event = self.create_and_insert_value(create_query, insert_query)
733+
if event.table_map[event.table_id].column_name_flag:
734+
self.assertEqual(
735+
event.rows[0]["values"]["json_data"],
736+
{
737+
b"decimal": Decimal("99.99"),
738+
b"time_key": datetime.time(18, 54, 12),
739+
b"datetime_key": datetime.datetime(2023, 9, 24, 18, 54, 12),
740+
},
741+
)
742+
744743
def test_null(self):
745744
create_query = "CREATE TABLE test ( \
746745
test TINYINT NULL DEFAULT NULL, \

‎pymysqlreplication/util/bytes.py

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -27,18 +27,15 @@ def decode_variable_length(data: bytes):
2727
max_count = 5
2828
if len(data) < max_count:
2929
max_count = len(data)
30-
3130
pos = 0
3231
length = 0
3332
for _ in range(max_count):
3433
v = data[pos]
3534
length |= (v & 0x7F) << (7 * pos)
36-
35+
pos += 1
3736
if v & 0x80 == 0:
3837
if length > sys.maxsize - 1:
3938
return 0, 0
40-
41-
pos += 1
4239
return int(length), pos
4340

4441
return 0, 0
@@ -103,11 +100,8 @@ def decode_time(data: bytes):
103100
if v == 0:
104101
return datetime.time(hour=0, minute=0, second=0)
105102

106-
sign = ""
107103
if v < 0:
108-
sign = "-"
109104
v = -v
110-
111105
int_part = v >> 24
112106
hour = (int_part >> 12) % (1 << 10)
113107
min = (int_part >> 6) % (1 << 6)

0 commit comments

Comments
 (0)
Please sign in to comment.