xiangfu0 commented on code in PR #20060:
URL: https://github.com/apache/pinot/pull/20060#discussion_r4384708960


##########
pinot-plugins/pinot-input-format/pinot-parquet/src/test/java/org/apache/pinot/plugin/inputformat/parquet/ParquetNativeRecordExtractorTest.java:
##########
@@ -274,6 +320,33 @@ public void testInt96ExtractedAsRawLongEpochNanosWhenRaw() 
{
         epochMillis * 1_000_000L);
   }
 
+  @Test
+  public void testInt96RangeAndNanosecondBoundaries() {
+    MessageType schema = MessageTypeParser.parseMessageType("message R { 
required int96 col; }");
+    for (String text : new String[]{"1970-01-01T00:00:00Z", 
"1969-12-31T23:59:59.999999999Z",
+        "1677-09-21T00:12:43.145224192Z", "2262-04-11T23:47:16.854775807Z",

Review Comment:
   Nice touch exercising the exact Long.MIN/MAX nanosecond endpoints and the 
just-over values here — that's precisely where the 128-bit carry logic could go 
wrong. I independently fuzzed the carry math against BigInteger across many 
millions of cases (including adversarial negative nanosOfDay) and it matches 
exactly. Nit only: the magic 86_400L and 1_000_000_000L literals recur across 
both convert methods; a couple of named constants would make the intent read a 
bit more clearly.



##########
pinot-plugins/pinot-input-format/pinot-parquet/src/main/java/org/apache/pinot/plugin/inputformat/parquet/ParquetNativeRecordExtractor.java:
##########
@@ -149,6 +148,11 @@ private Object extractValue(Group from, int fieldIndex, 
Type fieldType, int inde
           return intValue;
         case INT64:
           long longValue = from.getLong(fieldIndex, index);
+          if (logicalTypeAnnotation instanceof 
LogicalTypeAnnotation.IntLogicalTypeAnnotation integerType
+              && integerType.getBitWidth() == 64 && !integerType.isSigned() && 
longValue < 0) {
+            throw new IllegalArgumentException("Parquet UINT64 field " + 
fieldType.getName() + " value "
+                + Long.toUnsignedString(longValue) + " exceeds the signed Long 
range");

Review Comment:
   Worth confirming the intended behavior: a single UINT64 value above Long.MAX 
will now throw and fail the whole file/segment ingestion rather than the one 
record. That's the right call per fail-fast (silently wrapping to a negative 
was a correctness bug), and since this sits in the recursive extractValue it 
correctly covers nested struct/list/map fields too — the added tests cover that 
well. Just flagging it so the fail-the-whole-file semantics are a conscious 
choice.



-- 
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.

To unsubscribe, e-mail: [email protected]

For queries about this service, please contact Infrastructure at:
[email protected]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to