@@ -107,30 +107,27 @@ protected Serializable[] deserializeRow(long tableId, BitSet includedColumns, By
107107 return result ;
108108 }
109109
110- private Serializable deserializeCell (ColumnType type , int meta , int length , ByteArrayInputStream inputStream )
110+ protected Serializable deserializeCell (ColumnType type , int meta , int length , ByteArrayInputStream inputStream )
111111 throws IOException {
112112 switch (type ) {
113113 case BIT :
114- int bitSetLength = (meta >> 8 ) * 8 + (meta & 0xFF );
115- return inputStream .readBitSet (bitSetLength , false );
114+ return deserializeBit (meta , inputStream );
116115 case TINY :
117- return ( int ) (( byte ) inputStream . readInteger ( 1 ) );
116+ return deserializeTiny ( inputStream );
118117 case SHORT :
119- return ( int ) (( short ) inputStream . readInteger ( 2 ) );
118+ return deserializeShort ( inputStream );
120119 case INT24 :
121- return (inputStream . readInteger ( 3 ) << 8 ) >> 8 ;
120+ return deserializeInt24 (inputStream ) ;
122121 case LONG :
123- return inputStream . readInteger ( 4 );
122+ return deserializeLong ( inputStream );
124123 case LONGLONG :
125- return inputStream . readLong ( 8 );
124+ return deserializeLongLong ( inputStream );
126125 case FLOAT :
127- return Float . intBitsToFloat (inputStream . readInteger ( 4 ) );
126+ return deserializeFloat (inputStream );
128127 case DOUBLE :
129- return Double . longBitsToDouble (inputStream . readLong ( 8 ) );
128+ return deserializeDouble (inputStream );
130129 case NEWDECIMAL :
131- int precision = meta & 0xFF , scale = meta >> 8 ,
132- decimalLength = determineDecimalLength (precision , scale );
133- return toDecimal (precision , scale , inputStream .read (decimalLength ));
130+ return deserializeNewDecimal (meta , inputStream );
134131 case DATE :
135132 return deserializeDate (inputStream );
136133 case TIME :
@@ -146,27 +143,64 @@ private Serializable deserializeCell(ColumnType type, int meta, int length, Byte
146143 case DATETIME_V2 :
147144 return deserializeDatetimeV2 (meta , inputStream );
148145 case YEAR :
149- return 1900 + inputStream .readInteger (1 );
150- case STRING :
151- int stringLength = length < 256 ? inputStream .readInteger (1 ) : inputStream .readInteger (2 );
152- return inputStream .readString (stringLength );
153- case VARCHAR :
154- case VAR_STRING :
155- int varcharLength = meta < 256 ? inputStream .readInteger (1 ) : inputStream .readInteger (2 );
156- return inputStream .readString (varcharLength );
146+ return deserializeYear (inputStream );
147+ case STRING : // CHAR or BINARY
148+ return deserializeString (length , inputStream );
149+ case VARCHAR : case VAR_STRING : // VARCHAR or VARBINARY
150+ return deserializeVarString (meta , inputStream );
157151 case BLOB :
158- int blobLength = inputStream .readInteger (meta );
159- return inputStream .read (blobLength );
152+ return deserializeBlob (meta , inputStream );
160153 case ENUM :
161- return inputStream . readInteger (length );
154+ return deserializeEnum (length , inputStream );
162155 case SET :
163- return inputStream . readLong (length );
156+ return deserializeSet (length , inputStream );
164157 default :
165158 throw new IOException ("Unsupported type " + type );
166159 }
167160 }
168161
169- private java .sql .Date deserializeDate (ByteArrayInputStream inputStream ) throws IOException {
162+ protected Serializable deserializeBit (int meta , ByteArrayInputStream inputStream ) throws IOException {
163+ int bitSetLength = (meta >> 8 ) * 8 + (meta & 0xFF );
164+ return inputStream .readBitSet (bitSetLength , false );
165+ }
166+
167+ protected Serializable deserializeTiny (ByteArrayInputStream inputStream ) throws IOException {
168+ return (int ) ((byte ) inputStream .readInteger (1 ));
169+ }
170+
171+ protected Serializable deserializeShort (ByteArrayInputStream inputStream ) throws IOException {
172+ return (int ) ((short ) inputStream .readInteger (2 ));
173+ }
174+
175+ protected Serializable deserializeInt24 (ByteArrayInputStream inputStream ) throws IOException {
176+ return (inputStream .readInteger (3 ) << 8 ) >> 8 ;
177+ }
178+
179+ protected Serializable deserializeLong (ByteArrayInputStream inputStream ) throws IOException {
180+ return inputStream .readInteger (4 );
181+ }
182+
183+ protected Serializable deserializeLongLong (ByteArrayInputStream inputStream ) throws IOException {
184+ return inputStream .readLong (8 );
185+ }
186+
187+ protected Serializable deserializeFloat (ByteArrayInputStream inputStream ) throws IOException {
188+ return Float .intBitsToFloat (inputStream .readInteger (4 ));
189+ }
190+
191+ protected Serializable deserializeDouble (ByteArrayInputStream inputStream ) throws IOException {
192+ return Double .longBitsToDouble (inputStream .readLong (8 ));
193+ }
194+
195+ protected Serializable deserializeNewDecimal (int meta , ByteArrayInputStream inputStream ) throws IOException {
196+ int precision = meta & 0xFF , scale = meta >> 8 , x = precision - scale ;
197+ int ipd = x / DIG_PER_DEC , fpd = scale / DIG_PER_DEC ;
198+ int decimalLength = (ipd << 2 ) + DIG_TO_BYTES [x - ipd * DIG_PER_DEC ] +
199+ (fpd << 2 ) + DIG_TO_BYTES [scale - fpd * DIG_PER_DEC ];
200+ return asBigDecimal (precision , scale , inputStream .read (decimalLength ));
201+ }
202+
203+ protected Serializable deserializeDate (ByteArrayInputStream inputStream ) throws IOException {
170204 int value = inputStream .readInteger (3 );
171205 int day = value % 32 ;
172206 value >>>= 5 ;
@@ -180,7 +214,7 @@ private java.sql.Date deserializeDate(ByteArrayInputStream inputStream) throws I
180214 return new java .sql .Date (cal .getTimeInMillis ());
181215 }
182216
183- private static java . sql . Time deserializeTime (ByteArrayInputStream inputStream ) throws IOException {
217+ protected Serializable deserializeTime (ByteArrayInputStream inputStream ) throws IOException {
184218 int value = inputStream .readInteger (3 );
185219 int [] split = split (value , 100 , 3 );
186220 Calendar c = Calendar .getInstance ();
@@ -191,7 +225,7 @@ private static java.sql.Time deserializeTime(ByteArrayInputStream inputStream) t
191225 return new java .sql .Time (c .getTimeInMillis ());
192226 }
193227
194- private java . sql . Time deserializeTimeV2 (int meta , ByteArrayInputStream inputStream ) throws IOException {
228+ protected Serializable deserializeTimeV2 (int meta , ByteArrayInputStream inputStream ) throws IOException {
195229 /*
196230 in big endian:
197231
@@ -210,25 +244,25 @@ private java.sql.Time deserializeTimeV2(int meta, ByteArrayInputStream inputStre
210244 c .set (Calendar .HOUR_OF_DAY , extractBits (time , 2 , 10 , 24 ));
211245 c .set (Calendar .MINUTE , extractBits (time , 12 , 6 , 24 ));
212246 c .set (Calendar .SECOND , extractBits (time , 18 , 6 , 24 ));
213- c .set (Calendar .MILLISECOND , getFractionalSeconds (meta , inputStream ));
247+ c .set (Calendar .MILLISECOND , deserializeFractionalSeconds (meta , inputStream ));
214248 return new java .sql .Time (c .getTimeInMillis ());
215249 }
216250
217- private java . sql . Timestamp deserializeTimestamp (ByteArrayInputStream inputStream ) throws IOException {
251+ protected Serializable deserializeTimestamp (ByteArrayInputStream inputStream ) throws IOException {
218252 long value = inputStream .readLong (4 );
219253 return new java .sql .Timestamp (value * 1000L );
220254 }
221255
222- private java . sql . Timestamp deserializeTimestampV2 (int meta , ByteArrayInputStream inputStream ) throws IOException {
256+ protected Serializable deserializeTimestampV2 (int meta , ByteArrayInputStream inputStream ) throws IOException {
223257 // big endian
224258 long timestamp = bigEndianLong (inputStream .read (4 ), 0 , 4 );
225259 Calendar c = Calendar .getInstance ();
226260 c .setTimeInMillis (timestamp * 1000 );
227- c .set (Calendar .MILLISECOND , getFractionalSeconds (meta , inputStream ));
261+ c .set (Calendar .MILLISECOND , deserializeFractionalSeconds (meta , inputStream ));
228262 return new java .sql .Timestamp (c .getTimeInMillis ());
229263 }
230264
231- private java . util . Date deserializeDatetime (ByteArrayInputStream inputStream ) throws IOException {
265+ protected Serializable deserializeDatetime (ByteArrayInputStream inputStream ) throws IOException {
232266 long value = inputStream .readLong (8 );
233267 int [] split = split (value , 100 , 6 );
234268 Calendar c = Calendar .getInstance ();
@@ -242,7 +276,7 @@ private java.util.Date deserializeDatetime(ByteArrayInputStream inputStream) thr
242276 return c .getTime ();
243277 }
244278
245- private java . util . Date deserializeDatetimeV2 (int meta , ByteArrayInputStream inputStream ) throws IOException {
279+ protected Serializable deserializeDatetimeV2 (int meta , ByteArrayInputStream inputStream ) throws IOException {
246280 /*
247281 in big endian:
248282
@@ -265,11 +299,40 @@ private java.util.Date deserializeDatetimeV2(int meta, ByteArrayInputStream inpu
265299 c .set (Calendar .HOUR_OF_DAY , extractBits (datetime , 23 , 5 , 40 ));
266300 c .set (Calendar .MINUTE , extractBits (datetime , 28 , 6 , 40 ));
267301 c .set (Calendar .SECOND , extractBits (datetime , 34 , 6 , 40 ));
268- c .set (Calendar .MILLISECOND , getFractionalSeconds (meta , inputStream ));
302+ c .set (Calendar .MILLISECOND , deserializeFractionalSeconds (meta , inputStream ));
269303 return c .getTime ();
270304 }
271305
272- private int getFractionalSeconds (int meta , ByteArrayInputStream inputStream ) throws IOException {
306+ protected Serializable deserializeYear (ByteArrayInputStream inputStream ) throws IOException {
307+ return 1900 + inputStream .readInteger (1 );
308+ }
309+
310+ protected Serializable deserializeString (int length , ByteArrayInputStream inputStream ) throws IOException {
311+ // charset is not present in the binary log (meaning there is no way to distinguish between CHAR / BINARY)
312+ // as a result - return byte[] instead of an actual String
313+ int stringLength = length < 256 ? inputStream .readInteger (1 ) : inputStream .readInteger (2 );
314+ return inputStream .readString (stringLength );
315+ }
316+
317+ protected Serializable deserializeVarString (int meta , ByteArrayInputStream inputStream ) throws IOException {
318+ int varcharLength = meta < 256 ? inputStream .readInteger (1 ) : inputStream .readInteger (2 );
319+ return inputStream .readString (varcharLength );
320+ }
321+
322+ protected Serializable deserializeBlob (int meta , ByteArrayInputStream inputStream ) throws IOException {
323+ int blobLength = inputStream .readInteger (meta );
324+ return inputStream .read (blobLength );
325+ }
326+
327+ protected Serializable deserializeEnum (int length , ByteArrayInputStream inputStream ) throws IOException {
328+ return inputStream .readInteger (length );
329+ }
330+
331+ protected Serializable deserializeSet (int length , ByteArrayInputStream inputStream ) throws IOException {
332+ return inputStream .readLong (length );
333+ }
334+
335+ protected int deserializeFractionalSeconds (int meta , ByteArrayInputStream inputStream ) throws IOException {
273336 int length = (meta + 1 ) / 2 ;
274337 if (length > 0 ) {
275338 long fraction = bigEndianLong (inputStream .read (length ), 0 , length );
@@ -301,19 +364,10 @@ private static int[] split(long value, int divider, int length) {
301364 return result ;
302365 }
303366
304- private static int determineDecimalLength (int precision , int scale ) {
305- int x = precision - scale ;
306- int ipDigits = x / DIG_PER_DEC ;
307- int fpDigits = scale / DIG_PER_DEC ;
308- int ipDigitsX = x - ipDigits * DIG_PER_DEC ;
309- int fpDigitsX = scale - fpDigits * DIG_PER_DEC ;
310- return (ipDigits << 2 ) + DIG_TO_BYTES [ipDigitsX ] + (fpDigits << 2 ) + DIG_TO_BYTES [fpDigitsX ];
311- }
312-
313367 /**
314368 * see mysql/strings/decimal.c
315369 */
316- private static BigDecimal toDecimal (int precision , int scale , byte [] value ) {
370+ private static BigDecimal asBigDecimal (int precision , int scale , byte [] value ) {
317371 boolean positive = (value [0 ] & 0x80 ) == 0x80 ;
318372 value [0 ] ^= 0x80 ;
319373 if (!positive ) {
0 commit comments