|
2 | 2 | import time
|
3 | 3 | import unittest
|
4 | 4 |
|
| 5 | +from pymysqlreplication.json_binary import JsonDiff, JsonDiffOperation |
5 | 6 | from pymysqlreplication.tests import base
|
6 | 7 | from pymysqlreplication import BinLogStreamReader
|
7 | 8 | from pymysqlreplication.gtid import GtidSet, Gtid
|
|
22 | 23 | "TestRowsQueryLogEvents",
|
23 | 24 | "TestOptionalMetaData",
|
24 | 25 | "TestColumnValueNoneSources",
|
| 26 | + "TestJsonPartialUpdate", |
25 | 27 | ]
|
26 | 28 |
|
27 | 29 |
|
@@ -1838,6 +1840,182 @@ def test_get_none_invalid(self):
|
1838 | 1840 | self.assertEqual(after_none_sources["col4"], "empty set")
|
1839 | 1841 |
|
1840 | 1842 |
|
| 1843 | +class TestJsonPartialUpdate(base.PyMySQLReplicationTestCase): |
| 1844 | + def setUp(self): |
| 1845 | + super(TestJsonPartialUpdate, self).setUp() |
| 1846 | + self.stream.close() |
| 1847 | + self.stream = BinLogStreamReader( |
| 1848 | + self.database, |
| 1849 | + server_id=1024, |
| 1850 | + only_events=(PartialUpdateRowsEvent,), |
| 1851 | + ) |
| 1852 | + if not self.isMySQL8014AndMore(): |
| 1853 | + self.skipTest("Mysql version is under 8.0.14 - pass TestJsonPartialUpdate") |
| 1854 | + self.execute("SET SESSION binlog_row_image = 'FULL';") |
| 1855 | + self.execute("SET SESSION binlog_row_value_options = 'PARTIAL_JSON';") |
| 1856 | + |
| 1857 | + def test_json_partial_update(self): |
| 1858 | + create_query = "CREATE TABLE test_json_v2 (id INT, c JSON,PRIMARY KEY (id)) ;" |
| 1859 | + column_add_query = "ALTER TABLE test_json_v2 ADD COLUMN d JSON DEFAULT NULL, ADD COLUMN e JSON DEFAULT NULL;" |
| 1860 | + insert_query = """INSERT INTO test_json_v2 VALUES (101,'{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}', '{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}','{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}');""" |
| 1861 | + |
| 1862 | + update_query1 = """UPDATE test_json_v2 SET c = JSON_SET(c, '$.ab', '["ab_updatedccc"]') WHERE id = 101;""" |
| 1863 | + # update_query2 = """UPDATE test_json_v2 SET d = JSON_SET(d, '$.ab', '["ab_updatedddd"]') WHERE id = 101;""" |
| 1864 | + # update_query3 = """UPDATE test_json_v2 SET e = JSON_SET(e, '$.ab', '["ab_updatedeee"]'), c=NULL WHERE id = 101;""" |
| 1865 | + # update_query4 = """UPDATE test_json_v2 SET d = JSON_SET(d, '$.ab', '["ab_ddd"]'), e = json_set(e, '$.ab', '["ab_eee"]') WHERE id = 101;""" |
| 1866 | + |
| 1867 | + self.execute(create_query) |
| 1868 | + self.execute(column_add_query) |
| 1869 | + self.execute(insert_query) |
| 1870 | + self.execute(update_query1) |
| 1871 | + |
| 1872 | + self.execute("COMMIT;") |
| 1873 | + event = self.stream.fetchone() |
| 1874 | + |
| 1875 | + if event.table_map[event.table_id].column_name_flag: |
| 1876 | + self.assertEqual( |
| 1877 | + event.rows[0]["before_values"]["c"], |
| 1878 | + { |
| 1879 | + b"a": b"aaaaaaaaaaaaa", |
| 1880 | + b"c": b"ccccccccccccccc", |
| 1881 | + b"ab": [b"abababababababa", b"babababababab"], |
| 1882 | + }, |
| 1883 | + ), |
| 1884 | + after_value_c: JsonDiff = event.rows[0]["after_values"]["c"] |
| 1885 | + self.assertEqual(after_value_c.op, JsonDiffOperation.Replace) |
| 1886 | + self.assertEqual(after_value_c.path, b"$.ab") |
| 1887 | + self.assertEqual(after_value_c.value, b'["ab_updatedccc"]') |
| 1888 | + |
| 1889 | + after_none_sources = event.rows[0].get("after_none_sources") |
| 1890 | + self.assertEqual(after_none_sources["d"], NONE_SOURCE.JSON_PARTIAL_UPDATE) |
| 1891 | + self.assertEqual(after_none_sources["e"], NONE_SOURCE.JSON_PARTIAL_UPDATE) |
| 1892 | + |
| 1893 | + def test_json_partial_update_column_value_none(self): |
| 1894 | + drop_table_if_exists_query = "DROP TABLE IF EXISTS test_json_v2;" |
| 1895 | + create_query = "CREATE TABLE test_json_v2 (id INT, c JSON,PRIMARY KEY (id)) ;" |
| 1896 | + column_add_query = "ALTER TABLE test_json_v2 ADD COLUMN d JSON DEFAULT NULL, ADD COLUMN e JSON DEFAULT NULL;" |
| 1897 | + insert_query = """INSERT INTO test_json_v2 VALUES (101,'{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}', |
| 1898 | + '{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}', |
| 1899 | + '{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}');""" |
| 1900 | + |
| 1901 | + update_query = """UPDATE test_json_v2 SET e = JSON_SET(e, '$.ab', '["ab_updatedeee"]'), c=NULL WHERE id = 101;""" |
| 1902 | + |
| 1903 | + self.execute(drop_table_if_exists_query) |
| 1904 | + self.execute(create_query) |
| 1905 | + self.execute(column_add_query) |
| 1906 | + self.execute(insert_query) |
| 1907 | + self.execute(update_query) |
| 1908 | + |
| 1909 | + self.execute("COMMIT;") |
| 1910 | + event = self.stream.fetchone() |
| 1911 | + |
| 1912 | + if event.table_map[event.table_id].column_name_flag: |
| 1913 | + self.assertEqual( |
| 1914 | + event.rows[0]["before_values"]["e"], |
| 1915 | + { |
| 1916 | + b"a": b"aaaaaaaaaaaaa", |
| 1917 | + b"c": b"ccccccccccccccc", |
| 1918 | + b"ab": [b"abababababababa", b"babababababab"], |
| 1919 | + }, |
| 1920 | + ), |
| 1921 | + after_value_e: JsonDiff = event.rows[0]["after_values"]["e"] |
| 1922 | + self.assertEqual(after_value_e.op, JsonDiffOperation.Replace) |
| 1923 | + self.assertEqual(after_value_e.path, b"$.ab") |
| 1924 | + self.assertEqual(after_value_e.value, b'["ab_updatedeee"]') |
| 1925 | + |
| 1926 | + after_none_sources = event.rows[0].get("after_none_sources") |
| 1927 | + self.assertEqual(after_none_sources["c"], NONE_SOURCE.NULL) |
| 1928 | + self.assertEqual(after_none_sources["d"], NONE_SOURCE.JSON_PARTIAL_UPDATE) |
| 1929 | + |
| 1930 | + def test_json_partial_update_json_remove(self): |
| 1931 | + drop_table_if_exists_query = "DROP TABLE IF EXISTS test_json_v2;" |
| 1932 | + create_query = "CREATE TABLE test_json_v2 (id INT, c JSON,PRIMARY KEY (id)) ;" |
| 1933 | + column_add_query = "ALTER TABLE test_json_v2 ADD COLUMN d JSON DEFAULT NULL, ADD COLUMN e JSON DEFAULT NULL;" |
| 1934 | + insert_query = """INSERT INTO test_json_v2 VALUES (101,'{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}', |
| 1935 | + '{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}', |
| 1936 | + '{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}');""" |
| 1937 | + |
| 1938 | + update_query = ( |
| 1939 | + """UPDATE test_json_v2 SET e = JSON_REMOVE(e, '$.ab') WHERE id = 101;""" |
| 1940 | + ) |
| 1941 | + |
| 1942 | + self.execute(drop_table_if_exists_query) |
| 1943 | + self.execute(create_query) |
| 1944 | + self.execute(column_add_query) |
| 1945 | + self.execute(insert_query) |
| 1946 | + self.execute(update_query) |
| 1947 | + |
| 1948 | + self.execute("COMMIT;") |
| 1949 | + event = self.stream.fetchone() |
| 1950 | + |
| 1951 | + if event.table_map[event.table_id].column_name_flag: |
| 1952 | + self.assertEqual( |
| 1953 | + event.rows[0]["before_values"]["e"], |
| 1954 | + { |
| 1955 | + b"a": b"aaaaaaaaaaaaa", |
| 1956 | + b"c": b"ccccccccccccccc", |
| 1957 | + b"ab": [b"abababababababa", b"babababababab"], |
| 1958 | + }, |
| 1959 | + ), |
| 1960 | + after_value_e: JsonDiff = event.rows[0]["after_values"]["e"] |
| 1961 | + self.assertEqual(after_value_e.op, JsonDiffOperation.Remove) |
| 1962 | + self.assertEqual(after_value_e.path, b"$.ab") |
| 1963 | + self.assertEqual(after_value_e.value, None) |
| 1964 | + |
| 1965 | + after_none_sources = event.rows[0].get("after_none_sources") |
| 1966 | + self.assertEqual(after_none_sources["c"], NONE_SOURCE.JSON_PARTIAL_UPDATE) |
| 1967 | + self.assertEqual(after_none_sources["d"], NONE_SOURCE.JSON_PARTIAL_UPDATE) |
| 1968 | + |
| 1969 | + def test_json_partial_update_two_column(self): |
| 1970 | + drop_table_if_exists_query = "DROP TABLE IF EXISTS test_json_v2;" |
| 1971 | + create_query = "CREATE TABLE test_json_v2 (id INT, c JSON,PRIMARY KEY (id)) ;" |
| 1972 | + column_add_query = "ALTER TABLE test_json_v2 ADD COLUMN d JSON DEFAULT NULL, ADD COLUMN e JSON DEFAULT NULL;" |
| 1973 | + insert_query = """INSERT INTO test_json_v2 VALUES (101,'{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}', |
| 1974 | + '{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}', |
| 1975 | + '{"a":"aaaaaaaaaaaaa", "c":"ccccccccccccccc", "ab":["abababababababa", "babababababab"]}');""" |
| 1976 | + |
| 1977 | + update_query = """UPDATE test_json_v2 SET d = JSON_SET(d, '$.ab', '["ab_ddd"]'), e = JSON_REMOVE(e, '$.ab') WHERE id = 101;""" |
| 1978 | + |
| 1979 | + self.execute(drop_table_if_exists_query) |
| 1980 | + self.execute(create_query) |
| 1981 | + self.execute(column_add_query) |
| 1982 | + self.execute(insert_query) |
| 1983 | + self.execute(update_query) |
| 1984 | + |
| 1985 | + self.execute("COMMIT;") |
| 1986 | + event = self.stream.fetchone() |
| 1987 | + |
| 1988 | + if event.table_map[event.table_id].column_name_flag: |
| 1989 | + self.assertEqual( |
| 1990 | + event.rows[0]["before_values"]["d"], |
| 1991 | + { |
| 1992 | + b"a": b"aaaaaaaaaaaaa", |
| 1993 | + b"c": b"ccccccccccccccc", |
| 1994 | + b"ab": [b"abababababababa", b"babababababab"], |
| 1995 | + }, |
| 1996 | + ), |
| 1997 | + self.assertEqual( |
| 1998 | + event.rows[0]["before_values"]["e"], |
| 1999 | + { |
| 2000 | + b"a": b"aaaaaaaaaaaaa", |
| 2001 | + b"c": b"ccccccccccccccc", |
| 2002 | + b"ab": [b"abababababababa", b"babababababab"], |
| 2003 | + }, |
| 2004 | + ), |
| 2005 | + after_value_d: JsonDiff = event.rows[0]["after_values"]["d"] |
| 2006 | + self.assertEqual(after_value_d.op, JsonDiffOperation.Replace) |
| 2007 | + self.assertEqual(after_value_d.path, b"$.ab") |
| 2008 | + self.assertEqual(after_value_d.value, b'["ab_ddd"]') |
| 2009 | + |
| 2010 | + after_value_e: JsonDiff = event.rows[0]["after_values"]["e"] |
| 2011 | + self.assertEqual(after_value_e.op, JsonDiffOperation.Remove) |
| 2012 | + self.assertEqual(after_value_e.path, b"$.ab") |
| 2013 | + self.assertEqual(after_value_e.value, None) |
| 2014 | + |
| 2015 | + after_none_sources = event.rows[0].get("after_none_sources") |
| 2016 | + self.assertEqual(after_none_sources["c"], NONE_SOURCE.JSON_PARTIAL_UPDATE) |
| 2017 | + |
| 2018 | + |
1841 | 2019 | if __name__ == "__main__":
|
1842 | 2020 | import unittest
|
1843 | 2021 |
|
|
0 commit comments