Apache Iceberg version
main (development), commit c4784768b
Query engine
Spark 4.1 and Java API
Please describe the bug
With an integer partition transform whose width is Integer.MAX_VALUE, a positive value Integer.MAX_VALUE - 1 is assigned a negative partition key instead of zero. A table scan filtered by id >= 0 then excludes the matching file.
Schema schema = new Schema(Types.NestedField.required(1, "id", Types.IntegerType.get()));
PartitionSpec spec = PartitionSpec.builderFor(schema).truncate("id", Integer.MAX_VALUE).build();
int partition = Transforms.<Integer>truncate(Integer.MAX_VALUE)
.bind(Types.IntegerType.get()).apply(Integer.MAX_VALUE - 1);
Expected partition: 0. Actual partition: -2147483647.
The regression also computes a PartitionKey, appends a data-file entry carrying it, and checks table.newScan().filter(Expressions.greaterThanOrEqual("id", 0)).planFiles(). The matching file is omitted.
TruncateUtil overflows while adding the positive remainder to the width, before the second remainder operation. This differs from an inherently unrepresentable final partition value: all inputs and the correct result here fit in an int. Related decimal/final-result overflow discussions: #12915 and #17027.
Proposed fix: use an overflow-safe nonnegative remainder for int and the narrower integer helpers. Include transform arithmetic and scan-planning regressions.
Spark SQL reproduction
Run in a configured Iceberg catalog:
CREATE TABLE truncate_repro (id INT) USING iceberg
PARTITIONED BY (truncate(2147483647, id));
INSERT INTO truncate_repro VALUES (2147483646);
SELECT id FROM truncate_repro WHERE id >= 0;
On the original implementation the query returns no rows. With the fix it returns 2147483646. A Spark 4.1 regression in #18112 verifies this create/write/read flow for Parquet, Avro, and ORC; all three fail before the fix and pass afterward.
Willingness to contribute
This report and its reproduction were prepared with AI assistance and verified locally.
Apache Iceberg version
main (development), commit
c4784768bQuery engine
Spark 4.1 and Java API
Please describe the bug
With an integer partition transform whose width is
Integer.MAX_VALUE, a positive valueInteger.MAX_VALUE - 1is assigned a negative partition key instead of zero. A table scan filtered byid >= 0then excludes the matching file.Expected partition:
0. Actual partition:-2147483647.The regression also computes a
PartitionKey, appends a data-file entry carrying it, and checkstable.newScan().filter(Expressions.greaterThanOrEqual("id", 0)).planFiles(). The matching file is omitted.TruncateUtiloverflows while adding the positive remainder to the width, before the second remainder operation. This differs from an inherently unrepresentable final partition value: all inputs and the correct result here fit in an int. Related decimal/final-result overflow discussions: #12915 and #17027.Proposed fix: use an overflow-safe nonnegative remainder for int and the narrower integer helpers. Include transform arithmetic and scan-planning regressions.
Spark SQL reproduction
Run in a configured Iceberg catalog:
On the original implementation the query returns no rows. With the fix it returns
2147483646. A Spark 4.1 regression in #18112 verifies this create/write/read flow for Parquet, Avro, and ORC; all three fail before the fix and pass afterward.Willingness to contribute
This report and its reproduction were prepared with AI assistance and verified locally.