Skip to content

Commit cb37436

Browse files
committed
Merge branch 'main' of github.com:23-OSSCA-python-mysql-replication/python-mysql-replication into feature/categorize-none-column
2 parents 154bf88 + a4e59d6 commit cb37436

29 files changed

+114
-84
lines changed

.github/workflows/pytest.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -13,14 +13,14 @@ jobs:
1313
- {name: 'Pypy 3.9', python: 'pypy-3.9'}
1414
name: ${{ matrix.name }}
1515
runs-on: ubuntu-latest
16-
timeout-minutes: 2
16+
timeout-minutes: 3
1717

1818
steps:
1919
- name: Check out code
20-
uses: actions/checkout@v2
20+
uses: actions/checkout@v4
2121

2222
- name: Setup Python
23-
uses: actions/setup-python@v2
23+
uses: actions/setup-python@v4
2424
with:
2525
python-version: ${{ matrix.python }}
2626

README.md

+2
Original file line numberDiff line numberDiff line change
@@ -65,6 +65,8 @@ Featured
6565

6666
[Near Zero Downtime Migration from MySQL to DynamoDB](https://aws.amazon.com/ko/blogs/big-data/near-zero-downtime-migration-from-mysql-to-dynamodb/) (by YongSeong Lee, Amazon Web Services)
6767

68+
[Enable change data capture on Amazon RDS for MySQL applications that are using XA transactions](https://aws.amazon.com/ko/blogs/database/enable-change-data-capture-on-amazon-rds-for-mysql-applications-that-are-using-xa-transactions/) (by Baruch Assif, Amazon Web Services)
69+
6870
Projects using this library
6971
===========================
7072

docker-compose-test.yml

+13-1
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,15 @@ services:
3737
networks:
3838
- default
3939

40+
percona-8.0:
41+
<<: *mysql
42+
image: percona:8.0
43+
platform: linux/amd64
44+
ports:
45+
- "3309:3306"
46+
networks:
47+
- default
48+
4049
mariadb-10.6:
4150
<<: *mariadb
4251
image: mariadb:10.6
@@ -61,6 +70,8 @@ services:
6170
MYSQL_5_7: percona-5.7
6271
MYSQL_5_7_CTL: percona-5.7-ctl
6372
MYSQL_5_7_CTL_PORT: 3306
73+
MYSQL_8_0: percona-8.0
74+
MYSQL_8_0_PORT: 3306
6475
MARIADB_10_6: mariadb-10.6
6576
MARIADB_10_6_PORT: 3306
6677

@@ -72,7 +83,7 @@ services:
7283
7384
while :
7485
do
75-
if mysql -h percona-5.7 --user=root --execute "SELECT version();" 2>&1 >/dev/null && mysql -h percona-5.7-ctl --user=root --execute "SELECT version();" 2>&1 >/dev/null; then
86+
if mysql -h percona-5.7 --user=root --execute "SELECT version();" 2>&1 >/dev/null && mysql -h percona-5.7-ctl --user=root --execute "SELECT version();" 2>&1 >/dev/null && mysql -h percona-8.0 --user=root --execute "SELECT version();" 2>&1 >/dev/null; then
7687
break
7788
fi
7889
sleep 1
@@ -87,6 +98,7 @@ services:
8798
depends_on:
8899
- percona-5.7
89100
- percona-5.7-ctl
101+
- percona-8.0
90102

91103
networks:
92104
default:

docker-compose.yml

+6
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,12 @@ services:
3333
ports:
3434
- "3307:3306"
3535

36+
percona-8.0:
37+
<<: *mysql
38+
image: percona:8.0
39+
ports:
40+
- "3309:3306"
41+
3642
mariadb-10.6:
3743
<<: *mariadb
3844
image: mariadb:10.6

docs/conf.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
#
31
# Python MySQL Replication documentation build configuration file, created by
42
# sphinx-quickstart on Sun Sep 30 15:04:27 2012.
53
#

examples/dump_events.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env python
2-
# -*- coding: utf-8 -*-
32

43
#
54
# Dump all replication events from a remote mysql server

examples/logstash/mysql_to_logstash.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env python
2-
# -*- coding: utf-8 -*-
32

43
#
54
# Output logstash events to the console from MySQL replication stream

examples/redis_cache.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
#!/usr/bin/env python
2-
# -*- coding: utf-8 -*-
32

43
#
54
# Update a redis server cache when an evenement is trigger

pymysqlreplication/_compat.py

-1
This file was deleted.

pymysqlreplication/binlogstream.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
import struct
42
import logging
53
from distutils.version import LooseVersion

pymysqlreplication/bitmap.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
bitCountInByte = [
42
0,
53
1,

pymysqlreplication/column.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
import struct
42

53
from .constants import FIELD_TYPE

pymysqlreplication/constants/BINLOG.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
UNKNOWN_EVENT = 0x00
42
START_EVENT_V3 = 0x01
53
QUERY_EVENT = 0x02

pymysqlreplication/constants/FIELD_TYPE.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
# Original code from PyMySQL
42
# Copyright (c) 2010 PyMySQL contributors
53
#
-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
from .BINLOG import *
42
from .FIELD_TYPE import *
53
from .STATUS_VAR_KEY import *

pymysqlreplication/event.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
import binascii
42
import struct
53
import datetime

pymysqlreplication/gtid.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
import re
42
import struct
53
import binascii

pymysqlreplication/packet.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
import struct
42

53
from pymysqlreplication import constants, event, row_event

pymysqlreplication/row_event.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
31
import struct
42
import decimal
53
import datetime

pymysqlreplication/table.py

-3
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
3-
41
class Table(object):
52
def __init__(
63
self, table_id, schema, table, columns, primary_key=None, column_name_flag=False

pymysqlreplication/tests/__init__.py

+1-6
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,7 @@
1-
# -*- coding: utf-8 -*-
2-
31
from pymysqlreplication.tests.test_basic import *
42
from pymysqlreplication.tests.test_data_type import *
53
from pymysqlreplication.tests.test_data_objects import *
4+
import unittest
65

76
if __name__ == "__main__":
8-
if sys.version_info < (2, 7):
9-
import unittest2 as unittest
10-
else:
11-
import unittest
127
unittest.main()

pymysqlreplication/tests/base.py

+29-8
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,8 @@
1-
# -*- coding: utf-8 -*-
2-
31
import pymysql
42
import copy
53
from pymysqlreplication import BinLogStreamReader
64
import os
7-
import sys
8-
9-
if sys.version_info < (2, 7):
10-
import unittest2 as unittest
11-
else:
12-
import unittest
5+
import unittest
136

147
base = unittest.TestCase
158

@@ -160,3 +153,31 @@ def bin_log_basename(self):
160153
bin_log_basename = cursor.fetchone()[0]
161154
bin_log_basename = bin_log_basename.split("/")[-1]
162155
return bin_log_basename
156+
157+
158+
class PyMySQLReplicationVersion8TestCase(PyMySQLReplicationTestCase):
159+
def setUp(self):
160+
super().setUp()
161+
# default
162+
self.database = {
163+
"host": os.environ.get("MYSQL_8_0") or "localhost",
164+
"user": "root",
165+
"passwd": "",
166+
"port": int(os.environ.get("MYSQL_8_0_PORT") or 3309),
167+
"use_unicode": True,
168+
"charset": "utf8",
169+
"db": "pymysqlreplication_test",
170+
}
171+
172+
self.conn_control = None
173+
db = copy.copy(self.database)
174+
db["db"] = None
175+
self.connect_conn_control(db)
176+
self.execute("DROP DATABASE IF EXISTS pymysqlreplication_test")
177+
self.execute("CREATE DATABASE pymysqlreplication_test")
178+
db = copy.copy(self.database)
179+
self.connect_conn_control(db)
180+
self.stream = None
181+
self.resetBinLog()
182+
self.isMySQL80AndMore()
183+
self.__is_mariaDB = None

pymysqlreplication/tests/benchmark.py

-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,3 @@
1-
# -*- coding: utf-8 -*-
2-
#
31
# This is a sample script in order to make benchmark
42
# on library speed.
53
#

pymysqlreplication/tests/test_abnormal.py

-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,3 @@
1-
# -*- coding: utf-8 -*-
21
"""Test abnormal conditions, such as caused by a MySQL crash
32
"""
43
import os.path

pymysqlreplication/tests/test_basic.py

+6-13
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,9 @@
1-
# -*- coding: utf-8 -*-
21
import copy
32
import io
43
import os
5-
import sys
64
import time
7-
85
import pymysql
9-
10-
if sys.version_info < (2, 7):
11-
import unittest2 as unittest
12-
else:
13-
import unittest
6+
import unittest
147

158
from pymysqlreplication.tests import base
169
from pymysqlreplication import BinLogStreamReader
@@ -1479,7 +1472,7 @@ def test_query_event_latin1(self):
14791472
assert event.query == r"CREATE TABLE test_latin1_\xd6\xc6\xdb (a INT)"
14801473

14811474

1482-
class TestOptionalMetaData(base.PyMySQLReplicationTestCase):
1475+
class TestOptionalMetaData(base.PyMySQLReplicationVersion8TestCase):
14831476
def setUp(self):
14841477
super(TestOptionalMetaData, self).setUp()
14851478
self.stream.close()
@@ -1704,7 +1697,7 @@ def test_sync_drop_table_map_event_table_schema(self):
17041697

17051698
event = self.stream.fetchone()
17061699
self.assertIsInstance(event, TableMapEvent)
1707-
self.assertEqual(event.table_obj.data["columns"][0].name, "name")
1700+
self.assertEqual(event.table_obj.data["columns"][0].name, None)
17081701
self.assertEqual(len(column_schemas), 0)
17091702

17101703
def test_sync_column_drop_event_table_schema(self):
@@ -1735,9 +1728,9 @@ def test_sync_column_drop_event_table_schema(self):
17351728
self.assertEqual(len(event.table_obj.data["columns"]), 3)
17361729
self.assertEqual(column_schemas[0][0], "drop_column1")
17371730
self.assertEqual(column_schemas[1][0], "drop_column3")
1738-
self.assertEqual(event.table_obj.data["columns"][0].name, "drop_column1")
1739-
self.assertEqual(event.table_obj.data["columns"][1].name, "drop_column2")
1740-
self.assertEqual(event.table_obj.data["columns"][2].name, "drop_column3")
1731+
self.assertEqual(event.table_obj.data["columns"][0].name, None)
1732+
self.assertEqual(event.table_obj.data["columns"][1].name, None)
1733+
self.assertEqual(event.table_obj.data["columns"][2].name, None)
17411734

17421735
def tearDown(self):
17431736
self.execute("SET GLOBAL binlog_row_metadata='MINIMAL';")

pymysqlreplication/tests/test_data_objects.py

+1-7
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,4 @@
1-
import sys
2-
3-
if sys.version_info < (2, 7):
4-
import unittest2 as unittest
5-
else:
6-
import unittest
7-
1+
import unittest
82
from pymysqlreplication.column import Column
93
from pymysqlreplication.table import Table
104
from pymysqlreplication.event import GtidEvent

pymysqlreplication/tests/test_data_type.py

+47-13
Original file line numberDiff line numberDiff line change
@@ -1,32 +1,22 @@
1-
# -*- coding: utf-8 -*-
2-
31
import copy
42
import platform
5-
import sys
63
import json
7-
84
from pymysqlreplication import BinLogStreamReader
9-
10-
if sys.version_info < (2, 7):
11-
import unittest2 as unittest
12-
else:
13-
import unittest
5+
import unittest
146

157
from decimal import Decimal
168

179
from pymysqlreplication.tests import base
1810
from pymysqlreplication.constants.BINLOG import *
1911
from pymysqlreplication.row_event import *
2012
from pymysqlreplication.event import *
21-
from pymysqlreplication._compat import text_type
2213

23-
24-
__all__ = ["TestDataType"]
14+
__all__ = ["TestDataType", "TestDataTypeVersion8"]
2515

2616

2717
def to_binary_dict(d):
2818
def encode_value(v):
29-
if isinstance(v, text_type):
19+
if isinstance(v, str):
3020
return v.encode()
3121
if isinstance(v, list):
3222
return [encode_value(x) for x in v]
@@ -954,5 +944,49 @@ def test_varbinary(self):
954944
self.assertEqual(event.rows[0]["values"]["b"], b"\xff\x01\x00\x00")
955945

956946

947+
class TestDataTypeVersion8(base.PyMySQLReplicationVersion8TestCase):
948+
def ignoredEvents(self):
949+
return [GtidEvent, PreviousGtidsEvent]
950+
951+
def create_and_insert_value(self, create_query, insert_query):
952+
self.execute(create_query)
953+
self.execute(insert_query)
954+
self.execute("COMMIT")
955+
956+
self.assertIsInstance(self.stream.fetchone(), RotateEvent)
957+
self.assertIsInstance(self.stream.fetchone(), FormatDescriptionEvent)
958+
# QueryEvent for the Create Table
959+
self.assertIsInstance(self.stream.fetchone(), QueryEvent)
960+
961+
# QueryEvent for the BEGIN
962+
self.assertIsInstance(self.stream.fetchone(), QueryEvent)
963+
964+
self.assertIsInstance(self.stream.fetchone(), TableMapEvent)
965+
966+
event = self.stream.fetchone()
967+
if self.isMySQL56AndMore():
968+
self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V2)
969+
else:
970+
self.assertEqual(event.event_type, WRITE_ROWS_EVENT_V1)
971+
self.assertIsInstance(event, WriteRowsEvent)
972+
return event
973+
974+
def test_partition_id(self):
975+
if not self.isMySQL80AndMore():
976+
self.skipTest("Not supported in this version of MySQL")
977+
create_query = "CREATE TABLE test (id INTEGER) \
978+
PARTITION BY RANGE (id) ( \
979+
PARTITION p0 VALUES LESS THAN (1), \
980+
PARTITION p1 VALUES LESS THAN (2), \
981+
PARTITION p2 VALUES LESS THAN (3), \
982+
PARTITION p3 VALUES LESS THAN (4), \
983+
PARTITION p4 VALUES LESS THAN (5) \
984+
)"
985+
insert_query = "INSERT INTO test (id) VALUES(3)"
986+
event = self.create_and_insert_value(create_query, insert_query)
987+
self.assertEqual(event.extra_data_type, 1)
988+
self.assertEqual(event.partition_id, 3)
989+
990+
957991
if __name__ == "__main__":
958992
unittest.main()

0 commit comments

Comments
 (0)