Describe the bug, including details regarding any error messages, version, and platform.
We have an existing passing test case to write a parquet numeric array and read it back. After upgrading parquet-java from 1.17.1 to 1.18.0, the test failed because of the read mismatch.
For example:
# what we write via a parquet writer
{"12345678901234567890.123456789012345678", "12345678901234567890.123456789012345678"},
{"22.2345", "22.2345"},
# what we read from a parquet reader
row 0: 12345678901234567890.123456789012345678 12345678901234567890.123456789012345678
row 1: 12345678901234567890.123456789012345678 22.234500000000000000 <- the first record is wrong
I can reproduce this issue with the following test code:
importorg.apache.hadoop.conf.Configuration;
importorg.apache.hadoop.fs.Path;
importorg.apache.parquet.example.data.Group;
importorg.apache.parquet.example.data.simple.SimpleGroupFactory;
importorg.apache.parquet.hadoop.ParquetWriter;
importorg.apache.parquet.hadoop.example.ExampleParquetWriter;
importorg.apache.parquet.hadoop.example.GroupWriteSupport;
importorg.apache.parquet.hadoop.metadata.CompressionCodecName;
importorg.apache.parquet.io.api.Binary;
importorg.apache.parquet.schema.MessageType;
importorg.apache.parquet.schema.MessageTypeParser;
importorg.apache.parquet.hadoop.ParquetReader;
importorg.apache.parquet.hadoop.example.GroupReadSupport;
importjava.math.BigDecimal;
importjava.math.BigInteger;
importjava.util.Arrays;
publicclassRepro {
publicstaticvoidmain(String[] args) throwsException {
StringschemaStr = "message test {\n" +
" optional group numeric_array (LIST) {\n" +
" repeated group list {\n" +
" optional fixed_len_byte_array(16) element (DECIMAL(38,18));\n" +
" }\n" +
" }\n" +
"}";
MessageTypeschema = MessageTypeParser.parseMessageType(schemaStr);
Configurationconf = newConfiguration();
GroupWriteSupport.setSchema(schema, conf);
Pathpath = newPath("file:///tmp/parquet-repro/out.parquet");
path.getFileSystem(conf).delete(path, false);
// 2 rows, 2 elements per row -- this is the minimal trigger.// A single element per row does NOT reproduce the bug.String[][] rows = {
{"12345678901234567890.123456789012345678", "12345678901234567890.123456789012345678"},
{"22.2345", "22.2345"},
};
try (ParquetWriter<Group> writer = ExampleParquetWriter.builder(path)
.withConf(conf)
.withType(schema)
.withCompressionCodec(CompressionCodecName.UNCOMPRESSED)
.withDictionaryEncoding(false)
.build()) {
SimpleGroupFactoryfactory = newSimpleGroupFactory(schema);
for (String[] row : rows) {
Groupgroup = factory.newGroup();
GrouplistGroup = group.addGroup(0);
for (StringdecVal : row) {
GrouprepeatedGroup = listGroup.addGroup(0);
byte[] bytes = toFixedLenBytes(decVal, 18, 16);
repeatedGroup.add(0, Binary.fromReusedByteArray(bytes));
}
writer.write(group);
}
}
try (ParquetReader<Group> reader = ParquetReader.builder(newGroupReadSupport(), path)
.withConf(conf)
.build()) {
Groupg;
inti = 0;
while ((g = reader.read()) != null) {
GrouplistGroup = g.getGroup(0, 0);
intcount = listGroup.getFieldRepetitionCount(0);
StringBuildersb = newStringBuilder("row " + i + ": ");
for (intj = 0; j < count; j++) {
GrouprepeatedGroup = listGroup.getGroup(0, j);
byte[] readBytes = repeatedGroup.getBinary(0, 0).getBytes();
BigDecimalbd = newBigDecimal(newBigInteger(readBytes), 18);
sb.append(bd).append(" ");
}
System.out.println(sb);
i++;
}
}
}
privatestaticbyte[] toFixedLenBytes(StringdecStr, intscale, intlen) {
BigDecimalbd = newBigDecimal(decStr).setScale(scale);
BigIntegerunscaled = bd.unscaledValue();
byte[] full = unscaled.toByteArray();
byte[] tgt = newbyte[len];
if (unscaled.signum() == -1) {
Arrays.fill(tgt, (byte) 0xFF);
}
intsrcStart = Math.max(0, full.length - len);
intcopyLen = full.length - srcStart;
System.arraycopy(full, srcStart, tgt, len - copyLen, copyLen);
returntgt;
}
}Component(s)
No response
Describe the bug, including details regarding any error messages, version, and platform.
We have an existing passing test case to write a parquet numeric array and read it back. After upgrading parquet-java from 1.17.1 to 1.18.0, the test failed because of the read mismatch.
For example:
I can reproduce this issue with the following test code:
Component(s)
No response