voonhous commented on code in PR #19495:
URL: https://github.com/apache/hudi/pull/19495#discussion_r3709386372


##########
hudi-trino/src/test/java/io/trino/plugin/hudi/util/TestHudiAvroSerializer.java:
##########
@@ -41,32 +45,39 @@
 
 class TestHudiAvroSerializer
 {
-    @Test
-    public void testDecimalConverter()
-    {
-        HudiAvroSerializer.AvroDecimalConverter converter = new 
HudiAvroSerializer.AvroDecimalConverter();
-
-        assertThat(converter.convert(10, 2, 
unscaledBytes("123.45"))).isEqualTo(new BigDecimal("123.45"));
-        // Same (precision, scale) again: served from the cached schema
-        assertThat(converter.convert(10, 2, 
unscaledBytes("-0.07"))).isEqualTo(new BigDecimal("-0.07"));
-        // Same precision, different scale, and vice versa: must not collide 
in the cache
-        assertThat(converter.convert(10, 4, 
unscaledBytes("123.4567"))).isEqualTo(new BigDecimal("123.4567"));
-        assertThat(converter.convert(18, 2, 
unscaledBytes("9999999999999999.99"))).isEqualTo(new 
BigDecimal("9999999999999999.99"));
-        assertThat(converter.convert(5, 0, unscaledBytes("42"))).isEqualTo(new 
BigDecimal("42"));
-    }
-
-    @Test
-    public void testAppendShortDecimalFromAvroFixed()
+    /**
+     * A short decimal is stored in Trino as the unscaled value, which is 
exactly what Avro writes into the
+     * fixed bytes, so the read is a plain big-endian two's complement decode. 
The cases below pin the parts
+     * that decode gets wrong if it is ever rewritten: sign extension for 
negatives, scale 0, and the
+     * full-width value at the maximum short-decimal precision.
+     */
+    @ParameterizedTest
+    @MethodSource("shortDecimals")
+    public void testAppendShortDecimalFromAvroFixed(int precision, int scale, 
String value, long expectedUnscaled)
     {
-        DecimalType type = DecimalType.createDecimalType(10, 2);
-        byte[] bytes = unscaledBytes("123.45");
+        DecimalType type = DecimalType.createDecimalType(precision, scale);
+        byte[] bytes = unscaledBytes(value);

Review Comment:
   Confirmed and fixed. `unscaledBytes` gave the minimal encoding, so `-0.07` 
was a single `F9` byte and `-42` a single `D6` -- no case ever crossed a 
padding byte, which is exactly the part the decode is most likely to get wrong.
   
   The fixture now sizes the fixed from the precision (matching how 
`TestHudiUtilColumnHandles` builds its decimal fixed schema) and runs the value 
through Avro's own `DecimalConversion.toFixed`, so the bytes are what a writer 
actually emits:
   
   | case | before | after |
   | --- | --- | --- |
   | `dec(10,2) 123.45` | `30 39` | `00 00 00 30 39` |
   | `dec(10,2) -0.07` | `F9` | `FF FF FF FF F9` |
   | `dec(5,0) -42` | `D6` | `FF FF D6` |
   
   Same cases, still green.



-- 
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]

Reply via email to