diff --git a/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/LogBuffer.java b/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/LogBuffer.java index 408eaa4e..de4a7969 100644 --- a/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/LogBuffer.java +++ b/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/LogBuffer.java @@ -16,6 +16,8 @@ import java.util.BitSet; */ public class LogBuffer { + static final BigDecimal DECIMAL_ZERO_1_SCALE = BigDecimal.valueOf(0, 1); + static final BigDecimal DECIMAL_ONE_1_SCALE = BigDecimal.valueOf(10, 1); protected byte[] buffer; protected int origin, limit; @@ -1263,6 +1265,15 @@ public class LogBuffer { throw new IllegalArgumentException("limit excceed: " + (position + binSize - origin)); } + if (precision <= 20 && intg <= 18 && frac <= 9) { + // use compact BigDecimal + BigDecimal compactDecimal = getBigDecimalCompact(precision, scale, intg, frac, intg0x); + if (compactDecimal != null) { + position += binSize; + return compactDecimal; + } + } + BigDecimal decimal = getDecimal0(position, intg, frac, // NL intg0, frac0, @@ -1272,6 +1283,162 @@ public class LogBuffer { return decimal; } + /** + * use compact BigDecimal + */ + private BigDecimal getBigDecimalCompact(int precision, int scale, int intg, int frac, int intg0x) { + if (precision > 20 || intg > 18 && frac > 9) { + return null; + } + + BigDecimal compactDecimal = null; + long longValue = 0; + int small = 0; + int pos = position; + byte b0 = buffer[position]; + final int mask = ((b0 & 0x80) == 0x80) ? 0 : -1; + b0 ^= 0x80; + + switch (intg0x) { + case 0: + if (intg == 0) { + longValue = 0; + } else { + longValue = (b0 << 24) + | ((0xff & buffer[pos + 1]) << 16) + | ((0xff & buffer[pos + 2]) << 8) + | (0xff & buffer[pos + 3]); + longValue ^= mask; + pos += 4; + } + break; + case 1: + case 2: + longValue = b0; + longValue ^= mask; + pos += 1; + break; + case 3: + case 4: + longValue = (b0 << 8) | (0xff & buffer[pos + 1]); + longValue ^= mask; + pos += 2; + break; + case 5: + case 6: + longValue = (b0 << 16) | ((0xff & buffer[pos + 1]) << 8) | (0xff & buffer[pos + 2]); + longValue ^= mask; + pos += 3; + break; + case 7: + case 8: + longValue = (b0 << 24) + | ((0xff & buffer[pos + 1]) << 16) + | ((0xff & buffer[pos + 2]) << 8) + | (0xff & buffer[pos + 3]); + longValue ^= mask; + pos += 4; + break; + default: + break; + } + + if (intg > 9) { + int value = getInt32BE(buffer, pos); + value ^= mask; + longValue *= 1_000_000_000; + longValue += value; + pos += 4; + } + + int power = 1; + if (pos != position) { + b0 = buffer[pos]; + } + switch (frac) { + case 0: + small = 0; + break; + case 1: + case 2: + power = frac == 1 ? 10 : 100; + small = b0; + small ^= mask; + break; + case 3: + case 4: + power = frac == 3 ? 1_000 : 10_000; + small = (b0 << 8) | (0xff & buffer[pos + 1]); + small ^= mask; + break; + case 5: + case 6: + power = frac == 5 ? 100_000 : 1_000_000; + small = (b0 << 16) | ((0xff & buffer[pos + 1]) << 8) | (0xff & buffer[pos + 2]); + small ^= mask; + break; + case 7: + case 8: + case 9: + power = frac == 7 ? 10_000_000 : frac == 8 ? 100_000_000 : 1_000_000_000; + small = (b0 << 24) + | ((0xff & buffer[pos + 1]) << 16) + | ((0xff & buffer[pos + 2]) << 8) + | (0xff & buffer[pos + 3]); + small ^= mask; + break; + default: + break; + } + + if (small == 0) { + if (frac == 0) { + if (mask != 0) { + longValue = -longValue; + } + compactDecimal = BigDecimal.valueOf(longValue, 0); + } else if (longValue == 0) { + if (scale < 9) { + compactDecimal = DECIMAL_ZERO_1_SCALE; + } else { + compactDecimal = BigDecimal.valueOf(longValue, scale); + } + } else { + if (scale < 9) { + long unscaleValue = longValue * 10; + if (unscaleValue >= longValue) { + if (mask != 0) { + unscaleValue = -unscaleValue; + } + if (unscaleValue == 10) { + compactDecimal = DECIMAL_ONE_1_SCALE; + } else { + compactDecimal = BigDecimal.valueOf(unscaleValue, 1); + } + } + } else { + long unscaleValue = longValue * power; + if (unscaleValue >= longValue) { + if (mask != 0) { + unscaleValue = -unscaleValue; + } + compactDecimal = BigDecimal.valueOf(unscaleValue, scale); + } + } + } + } else { + long unscaleValue = longValue * power + small; + if (unscaleValue >= longValue) { + if (mask != 0) { + unscaleValue = -unscaleValue; + } + compactDecimal = BigDecimal.valueOf(unscaleValue, scale); + } + } + + return compactDecimal; + } + /** * Return big decimal from buffer. * @@ -1445,8 +1612,9 @@ public class LogBuffer { } d_copy[begin] ^= 0x80; /* restore sign */ - String decimal = String.valueOf(buf, 0, pos); - return new BigDecimal(decimal); + // String decimal = String.valueOf(buf, 0, pos); + // return new BigDecimal(decimal); + return new BigDecimal(buf, 0, pos); } /**