canal icon indicating copy to clipboard operation
canal copied to clipboard

LogBuffer 解析 Decimal 数据未补齐末尾0的精度问题

Open F-ca7 opened this issue 1 year ago • 1 comments

复现方式:

// 字段类型 decimal(64, 16)
public static void main(String[] args) {
    byte[] bytes = new byte[] {-128, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
    LogBuffer logBuffer = new LogBuffer(bytes, 0, bytes.length);
    BigDecimal decimal = logBuffer.getDecimal(64, 16);
    System.out.println(decimal.toPlainString());
}

预期输出:"0.0000000000000000" (16个0)

实际输出:"0.000000000" (9个0)

错误原因:解析最后一段小数的时候,没有补齐0至原始数据类型定义的小数精度

https://github.com/alibaba/canal/blob/66483ef83fd9736ea587353674dfbd29d447b11e/dbsync/src/main/java/com/taobao/tddl/dbsync/binlog/LogBuffer.java#L1546

修复方案:补齐指定scale后的0

for (int i = pos - mark; i < frac; i++) {
    buf[pos++] = ('0');
}

MySQL 源码中最后也有补齐0的操作:

// Append padding if a fixed precision was specified.
for (int i = 0; i < fill; ++i) *to++ = '0';

F-ca7 avatar Oct 30 '24 13:10 F-ca7

可以考虑提交一个PR给我

agapple avatar Dec 17 '24 09:12 agapple