Skip to content

Commit 7b75aef

Browse files
committed
Fix mysql8 signedness decoding
The table metadata only contains signedness bits for integer columns. So in the case where there's 12 columns but only 1 integer column, mysql will use just one byte. Our calculation was saying there should be 2 bytes, and thus our buffer overruneth.
1 parent 8ca7a94 commit 7b75aef

File tree

4 files changed

+38
-4
lines changed

4 files changed

+38
-4
lines changed

pom.xml

+1-1
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@
6565
<dependency>
6666
<groupId>mysql</groupId>
6767
<artifactId>mysql-connector-java</artifactId>
68-
<version>5.1.21</version>
68+
<version>8.0.15</version>
6969
<scope>test</scope>
7070
</dependency>
7171
</dependencies>

src/main/java/com/github/shyiko/mysql/binlog/event/deserialization/TableMapEventDataDeserializer.java

+19-1
Original file line numberDiff line numberDiff line change
@@ -46,13 +46,31 @@ public TableMapEventData deserialize(ByteArrayInputStream inputStream) throws IO
4646
if (metadataLength > 0) {
4747
metadata = metadataDeserializer.deserialize(
4848
new ByteArrayInputStream(inputStream.read(metadataLength)),
49-
numberOfColumns
49+
numericColumnCount(eventData.getColumnTypes())
5050
);
5151
}
5252
eventData.setEventMetadata(metadata);
5353
return eventData;
5454
}
5555

56+
private int numericColumnCount(byte[] types) {
57+
int count = 0;
58+
for ( int i = 0 ; i < types.length; i++) {
59+
switch ( ColumnType.byCode(types[i] & 0xff)) {
60+
case TINY:
61+
case SHORT:
62+
case INT24:
63+
case LONG:
64+
case LONGLONG:
65+
case NEWDECIMAL:
66+
case FLOAT:
67+
case DOUBLE:
68+
count++;
69+
}
70+
}
71+
return count;
72+
}
73+
5674
private int[] readMetadata(ByteArrayInputStream inputStream, byte[] columnTypes) throws IOException {
5775
int[] metadata = new int[columnTypes.length];
5876
for (int i = 0; i < columnTypes.length; i++) {

src/main/java/com/github/shyiko/mysql/binlog/event/deserialization/TableMapEventMetadataDeserializer.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
*/
3333
public class TableMapEventMetadataDeserializer {
3434

35-
public TableMapEventMetadata deserialize(ByteArrayInputStream inputStream, int numberOfColumns) throws IOException {
35+
public TableMapEventMetadata deserialize(ByteArrayInputStream inputStream, int numberOfIntegerColumns) throws IOException {
3636
int remainingBytes = inputStream.available();
3737
if (remainingBytes <= 0) {
3838
return null;
@@ -49,7 +49,7 @@ public TableMapEventMetadata deserialize(ByteArrayInputStream inputStream, int n
4949

5050
switch (fieldType) {
5151
case SIGNEDNESS:
52-
result.setSignedness(readSignedness(inputStream, numberOfColumns));
52+
result.setSignedness(readSignedness(inputStream, numberOfIntegerColumns));
5353
break;
5454
case DEFAULT_CHARSET:
5555
result.setDefaultCharset(readDefaultCharset(inputStream));

src/test/java/com/github/shyiko/mysql/binlog/BinaryLogClientIntegrationTest.java

+16
Original file line numberDiff line numberDiff line change
@@ -990,6 +990,22 @@ public void execute(Statement statement) throws SQLException {
990990
}
991991
}
992992

993+
@Test
994+
public void testMysql8TableMetadata() throws Exception {
995+
master.execute("create table test_metameta ( " +
996+
"a date, b date, c date, d date, e date, f date, g date, " +
997+
"h date, i date, j int)");
998+
master.execute("insert into test_metameta set j = 5");
999+
1000+
final BinaryLogClient binaryLogClient = new BinaryLogClient(
1001+
master.hostname, master.port, master.username, master.password
1002+
);
1003+
binaryLogClient.registerEventListener(eventListener);
1004+
binaryLogClient.connect(DEFAULT_TIMEOUT);
1005+
1006+
eventListener.waitFor(WriteRowsEventData.class, 1, DEFAULT_TIMEOUT);
1007+
}
1008+
9931009
@AfterMethod
9941010
public void afterEachTest() throws Exception {
9951011
final CountDownLatch latch = new CountDownLatch(1);

0 commit comments

Comments
 (0)