22
22
import java .io .IOException ;
23
23
import java .io .Serializable ;
24
24
import java .math .BigDecimal ;
25
- import java .sql .Time ;
26
25
import java .util .BitSet ;
27
26
import java .util .Calendar ;
28
27
import java .util .Map ;
@@ -69,6 +68,8 @@ public abstract class AbstractRowsEventDataDeserializer<T extends EventData> imp
69
68
70
69
private static final int DIG_PER_DEC = 9 ;
71
70
private static final int [] DIG_TO_BYTES = {0 , 1 , 1 , 2 , 2 , 3 , 3 , 4 , 4 , 4 };
71
+ private static final long TIMEF_OFS = 0x800000000000L ;
72
+ private static final long TIMEF_INT_OFS = 0x800000 ;
72
73
73
74
private final Map <Long , TableMapEventData > tableMapEventByTableId ;
74
75
@@ -77,6 +78,7 @@ public abstract class AbstractRowsEventDataDeserializer<T extends EventData> imp
77
78
private boolean microsecondsPrecision ;
78
79
private boolean deserializeCharAndBinaryAsByteArray ;
79
80
private boolean deserializeIntegerAsByteArray ;
81
+ private boolean deserializeWithNewTimeV2 ;
80
82
81
83
public AbstractRowsEventDataDeserializer (Map <Long , TableMapEventData > tableMapEventByTableId ) {
82
84
this .tableMapEventByTableId = tableMapEventByTableId ;
@@ -103,6 +105,10 @@ void setDeserializeIntegerAsByteArray(boolean deserializeIntegerAsByteArray) {
103
105
this .deserializeIntegerAsByteArray = deserializeIntegerAsByteArray ;
104
106
}
105
107
108
+ void setDeserializeWithNewTimeV2 (boolean deserializeWithNewTimeV2 ) {
109
+ this .deserializeWithNewTimeV2 = deserializeWithNewTimeV2 ;
110
+ }
111
+
106
112
protected Serializable [] deserializeRow (long tableId , BitSet includedColumns , ByteArrayInputStream inputStream )
107
113
throws IOException {
108
114
TableMapEventData tableMapEvent = tableMapEventByTableId .get (tableId );
@@ -173,7 +179,11 @@ protected Serializable deserializeCell(ColumnType type, int meta, int length, By
173
179
case TIME :
174
180
return deserializeTime (inputStream );
175
181
case TIME_V2 :
176
- return deserializeTimeV2 (meta , inputStream );
182
+ if (deserializeWithNewTimeV2 ) {
183
+ return deserializeTimeV2New (meta , inputStream );
184
+ } else {
185
+ return deserializeTimeV2 (meta , inputStream );
186
+ }
177
187
case TIMESTAMP :
178
188
return deserializeTimestamp (inputStream );
179
189
case TIMESTAMP_V2 :
@@ -317,6 +327,63 @@ protected Serializable deserializeTimeV2(int meta, ByteArrayInputStream inputStr
317
327
return timestamp != null ? convertLongTimestamptWithFSP (timestamp , fsp ) : null ;
318
328
}
319
329
330
+ protected Serializable deserializeTimeV2New (int meta , ByteArrayInputStream inputStream ) throws IOException {
331
+ long result ;
332
+ long intPart ;
333
+ long fracPart ;
334
+
335
+ switch (meta ) {
336
+ case 1 : case 2 :
337
+ intPart = bigEndianLong (inputStream .read (3 ), 0 , 3 ) - TIMEF_INT_OFS ;
338
+ fracPart = bigEndianLong (inputStream .read (1 ), 0 , 1 );
339
+
340
+ if (intPart < 0 && fracPart != 0 ) {
341
+ /*
342
+ Negative values are stored with reverse fractional part order,
343
+ for binary sort compatibility.
344
+
345
+ Disk value intpart fracPart Time value Memory value
346
+ 800000.00 0 0 00:00:00.00 0000000000.000000
347
+ 7FFFFF.FF -1 255 -00:00:00.01 FFFFFFFFFF.FFD8F0
348
+ 7FFFFF.9D -1 99 -00:00:00.99 FFFFFFFFFF.F0E4D0
349
+ 7FFFFF.00 -1 0 -00:00:01.00 FFFFFFFFFF.000000
350
+ 7FFFFE.FF -1 255 -00:00:01.01 FFFFFFFFFE.FFD8F0
351
+ 7FFFFE.F6 -2 246 -00:00:01.10 FFFFFFFFFE.FE7960
352
+
353
+ Formula to convert fractional part from disk format
354
+ (now stored in "fracPart" variable) to absolute value: "0x100 - fracPart".
355
+ To reconstruct in-memory value, we shift
356
+ to the next integer value and then substruct fractional part.
357
+ */
358
+ intPart ++; /* Shift to the next integer value */
359
+ fracPart -= 0x100 ; /* -(0x100 - fracPart) */
360
+ }
361
+ result = (intPart << 24 ) + (fracPart * 10000 );
362
+ break ;
363
+ case 3 : case 4 :
364
+ intPart = bigEndianLong (inputStream .read (3 ), 0 , 3 ) - TIMEF_INT_OFS ;
365
+ fracPart = bigEndianLong (inputStream .read (2 ), 0 , 2 );
366
+ if (intPart < 0 && fracPart != 0 ) {
367
+ /*
368
+ Fix reverse fractional part order: "0x10000 - fracPart".
369
+ See comments for FSP=1 and FSP=2 above.
370
+ */
371
+ intPart ++; /* Shift to the next integer value */
372
+ fracPart -= 0x10000 ; /* -(0x10000-fracPart) */
373
+ }
374
+ result = (intPart << 24 ) + (fracPart * 100 );
375
+ break ;
376
+ case 5 : case 6 :
377
+ result = bigEndianLong (inputStream .read (6 ), 0 , 6 ) - TIMEF_OFS ;
378
+ break ;
379
+ default :
380
+ intPart = bigEndianLong (inputStream .read (3 ), 0 , 3 ) - TIMEF_INT_OFS ;
381
+ result = intPart << 24 ;
382
+ }
383
+
384
+ return result ;
385
+ }
386
+
320
387
protected Serializable deserializeTimestamp (ByteArrayInputStream inputStream ) throws IOException {
321
388
long timestamp = inputStream .readLong (4 ) * 1000 ;
322
389
if (deserializeDateAndTimeAsLong ) {
0 commit comments