26
26
import java .util .LinkedHashMap ;
27
27
import java .util .List ;
28
28
import java .util .Map ;
29
+ import java .util .logging .Level ;
30
+ import java .util .logging .Logger ;
29
31
30
32
/**
31
33
* @author <a href="mailto:[email protected] ">Ahmed Abdul Hamid</a>
32
34
*/
33
35
public class TableMapEventMetadataDeserializer {
34
36
35
- public TableMapEventMetadata deserialize (ByteArrayInputStream inputStream , int nIntColumns ) throws IOException {
37
+ private final Logger logger = Logger .getLogger (getClass ().getName ());
38
+
39
+ public TableMapEventMetadata deserialize (ByteArrayInputStream inputStream , int nColumns , int nNumericColumns ) throws IOException {
36
40
int remainingBytes = inputStream .available ();
37
41
if (remainingBytes <= 0 ) {
38
42
return null ;
@@ -41,15 +45,27 @@ public TableMapEventMetadata deserialize(ByteArrayInputStream inputStream, int n
41
45
TableMapEventMetadata result = new TableMapEventMetadata ();
42
46
43
47
for (; remainingBytes > 0 ; inputStream .enterBlock (remainingBytes )) {
44
- MetadataFieldType fieldType = MetadataFieldType .byCode (inputStream .readInteger (1 ));
48
+ int code = inputStream .readInteger (1 );
49
+
50
+ MetadataFieldType fieldType = MetadataFieldType .byCode (code );
51
+
52
+ if (fieldType == null )
53
+ throw new IOException ("Unsupported table metadata field type " + code );
54
+
55
+ //for some reasons, the UNKNOWN_METADATA_FIELD_TYPE will mess up the stream
56
+ if (inputStream .available () == 0 ) {
57
+ logger .warning ("Stream is empty so cannot read field length for field type: " + fieldType );
58
+ return result ;
59
+ }
60
+
45
61
int fieldLength = inputStream .readPackedInteger ();
46
62
47
63
remainingBytes = inputStream .available ();
48
64
inputStream .enterBlock (fieldLength );
49
65
50
66
switch (fieldType ) {
51
67
case SIGNEDNESS :
52
- result .setSignedness (readSignedness (inputStream , nIntColumns ));
68
+ result .setSignedness (readBooleanList (inputStream , nNumericColumns ));
53
69
break ;
54
70
case DEFAULT_CHARSET :
55
71
result .setDefaultCharset (readDefaultCharset (inputStream ));
@@ -81,16 +97,22 @@ public TableMapEventMetadata deserialize(ByteArrayInputStream inputStream, int n
81
97
case ENUM_AND_SET_COLUMN_CHARSET :
82
98
result .setEnumAndSetColumnCharsets (readIntegers (inputStream ));
83
99
break ;
100
+ case VISIBILITY :
101
+ result .setVisibility (readBooleanList (inputStream , nColumns ));
102
+ break ;
103
+ case UNKNOWN_METADATA_FIELD_TYPE :
104
+ logger .warning ("Received metadata field of unknown type" );
105
+ break ;
84
106
default :
85
107
inputStream .enterBlock (remainingBytes );
86
- throw new IOException ("Unsupported table metadata field type " + fieldType );
108
+ throw new IOException ("Unsupported table metadata field type " + code );
87
109
}
88
110
remainingBytes -= fieldLength ;
89
111
}
90
112
return result ;
91
113
}
92
114
93
- private static BitSet readSignedness (ByteArrayInputStream inputStream , int length ) throws IOException {
115
+ private static BitSet readBooleanList (ByteArrayInputStream inputStream , int length ) throws IOException {
94
116
BitSet result = new BitSet ();
95
117
// according to MySQL internals the amount of storage required for N columns is INT((N+7)/8) bytes
96
118
byte [] bytes = inputStream .read ((length + 7 ) >> 3 );
@@ -162,7 +184,9 @@ private enum MetadataFieldType {
162
184
SIMPLE_PRIMARY_KEY (8 ), // The primary key without any prefix
163
185
PRIMARY_KEY_WITH_PREFIX (9 ), // The primary key with some prefix
164
186
ENUM_AND_SET_DEFAULT_CHARSET (10 ), // Charsets of ENUM and SET columns
165
- ENUM_AND_SET_COLUMN_CHARSET (11 ); // Charsets of ENUM and SET columns
187
+ ENUM_AND_SET_COLUMN_CHARSET (11 ), // Charsets of ENUM and SET columns
188
+ VISIBILITY (12 ), // Column visibility (8.0.23 and newer)
189
+ UNKNOWN_METADATA_FIELD_TYPE (128 ); // Returned from MySQL 8.0 in some cases
166
190
167
191
private final int code ;
168
192
0 commit comments