This is an automated email from the ASF dual-hosted git repository.

amoghj pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/main by this push:
     new e23cf65e9e API, Core: Fix byte buffer conversion for Variant in bounds 
(#14362)
e23cf65e9e is described below

commit e23cf65e9ee0c4f8c5d5677a7ab95eaff2f295c5
Author: Amogh Jahagirdar <[email protected]>
AuthorDate: Sat Oct 18 12:04:36 2025 -0600

    API, Core: Fix byte buffer conversion for Variant in bounds (#14362)
---
 .../java/org/apache/iceberg/types/Conversions.java | 16 ++++++++++++++++
 .../iceberg/variants/TestPrimitiveWrapper.java     | 14 ++++++++++++++
 .../iceberg/variants/TestShreddedObject.java       | 22 ++++++++++++++++++++++
 .../apache/iceberg/variants/TestValueArray.java    | 14 ++++++++++++++
 4 files changed, 66 insertions(+)

diff --git a/api/src/main/java/org/apache/iceberg/types/Conversions.java 
b/api/src/main/java/org/apache/iceberg/types/Conversions.java
index e18c7b4362..3b840ba6df 100644
--- a/api/src/main/java/org/apache/iceberg/types/Conversions.java
+++ b/api/src/main/java/org/apache/iceberg/types/Conversions.java
@@ -32,6 +32,9 @@ import java.util.UUID;
 import org.apache.iceberg.exceptions.RuntimeIOException;
 import org.apache.iceberg.expressions.Literal;
 import org.apache.iceberg.util.UUIDUtil;
+import org.apache.iceberg.variants.Variant;
+import org.apache.iceberg.variants.VariantMetadata;
+import org.apache.iceberg.variants.VariantValue;
 
 public class Conversions {
 
@@ -117,6 +120,17 @@ public class Conversions {
         return (ByteBuffer) value;
       case DECIMAL:
         return ByteBuffer.wrap(((BigDecimal) 
value).unscaledValue().toByteArray());
+      case VARIANT:
+        // Produce a concatenated buffer of metadata and value
+        Variant variant = (Variant) value;
+        VariantMetadata variantMetadata = variant.metadata();
+        VariantValue variantValue = variant.value();
+        ByteBuffer variantBuffer =
+            ByteBuffer.allocate(variantMetadata.sizeInBytes() + 
variantValue.sizeInBytes())
+                .order(ByteOrder.LITTLE_ENDIAN);
+        variantMetadata.writeTo(variantBuffer, 0);
+        variantValue.writeTo(variantBuffer, variantMetadata.sizeInBytes());
+        return variantBuffer;
       default:
         throw new UnsupportedOperationException("Cannot serialize type: " + 
typeId);
     }
@@ -177,6 +191,8 @@ public class Conversions {
         byte[] unscaledBytes = new byte[buffer.remaining()];
         tmp.get(unscaledBytes);
         return new BigDecimal(new BigInteger(unscaledBytes), decimal.scale());
+      case VARIANT:
+        return Variant.from(tmp);
       default:
         throw new UnsupportedOperationException("Cannot deserialize type: " + 
type);
     }
diff --git 
a/core/src/test/java/org/apache/iceberg/variants/TestPrimitiveWrapper.java 
b/core/src/test/java/org/apache/iceberg/variants/TestPrimitiveWrapper.java
index 5af3dbfb5f..c131ad0d50 100644
--- a/core/src/test/java/org/apache/iceberg/variants/TestPrimitiveWrapper.java
+++ b/core/src/test/java/org/apache/iceberg/variants/TestPrimitiveWrapper.java
@@ -24,6 +24,8 @@ import java.math.BigDecimal;
 import java.nio.ByteBuffer;
 import java.nio.ByteOrder;
 import java.util.Random;
+import org.apache.iceberg.types.Conversions;
+import org.apache.iceberg.types.Types;
 import org.apache.iceberg.util.RandomUtil;
 import org.junit.jupiter.params.ParameterizedTest;
 import org.junit.jupiter.params.provider.FieldSource;
@@ -84,4 +86,16 @@ public class TestPrimitiveWrapper {
     assertThat(actual).isInstanceOf(VariantPrimitive.class);
     assertThat(actual.asPrimitive().get()).isEqualTo(primitive.get());
   }
+
+  @ParameterizedTest
+  @FieldSource("PRIMITIVES")
+  public void testByteBufferConversion(VariantPrimitive<?> primitive) {
+    VariantMetadata primitiveMetadata = Variants.metadata("$['primitive']");
+    Variant expectedVariant = Variant.of(primitiveMetadata, primitive);
+    ByteBuffer convertedValue = 
Conversions.toByteBuffer(Types.VariantType.get(), expectedVariant);
+    Variant readValue = Conversions.fromByteBuffer(Types.VariantType.get(), 
convertedValue);
+
+    VariantTestUtil.assertEqual(expectedVariant.metadata(), 
readValue.metadata());
+    VariantTestUtil.assertEqual(expectedVariant.value(), readValue.value());
+  }
 }
diff --git 
a/core/src/test/java/org/apache/iceberg/variants/TestShreddedObject.java 
b/core/src/test/java/org/apache/iceberg/variants/TestShreddedObject.java
index 431f38cb19..1ebb433a54 100644
--- a/core/src/test/java/org/apache/iceberg/variants/TestShreddedObject.java
+++ b/core/src/test/java/org/apache/iceberg/variants/TestShreddedObject.java
@@ -30,6 +30,8 @@ import java.util.Set;
 import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
 import org.apache.iceberg.relocated.com.google.common.collect.Maps;
 import org.apache.iceberg.relocated.com.google.common.collect.Sets;
+import org.apache.iceberg.types.Conversions;
+import org.apache.iceberg.types.Types;
 import org.apache.iceberg.util.DateTimeUtil;
 import org.apache.iceberg.util.RandomUtil;
 import org.junit.jupiter.api.Test;
@@ -60,6 +62,26 @@ public class TestShreddedObject {
     assertThat(object.get("c").asPrimitive().get()).isEqualTo(new 
BigDecimal("12.21"));
   }
 
+  @Test
+  public void testByteBufferConversion() {
+    Map<String, VariantValue> pathNormalizedFields =
+        ImmutableMap.of(
+            "$['a']",
+            Variants.of(34),
+            "$['b']",
+            Variants.of("iceberg"),
+            "$['c']",
+            Variants.of(new BigDecimal("12.21")));
+    ShreddedObject object = createShreddedObject(pathNormalizedFields);
+    VariantMetadata metadata = Variants.metadata("$['a']", "$['b']", "$['c']");
+    Variant expectedVariant = Variant.of(metadata, object);
+    ByteBuffer convertedValue = 
Conversions.toByteBuffer(Types.VariantType.get(), expectedVariant);
+    Variant readValue = Conversions.fromByteBuffer(Types.VariantType.get(), 
convertedValue);
+
+    VariantTestUtil.assertEqual(expectedVariant.metadata(), 
readValue.metadata());
+    VariantTestUtil.assertEqual(expectedVariant.value(), readValue.value());
+  }
+
   @Test
   public void testShreddedSerializationMinimalBuffer() {
     ShreddedObject object = createShreddedObject(FIELDS);
diff --git a/core/src/test/java/org/apache/iceberg/variants/TestValueArray.java 
b/core/src/test/java/org/apache/iceberg/variants/TestValueArray.java
index d281d8a381..7a8b3c533d 100644
--- a/core/src/test/java/org/apache/iceberg/variants/TestValueArray.java
+++ b/core/src/test/java/org/apache/iceberg/variants/TestValueArray.java
@@ -27,6 +27,8 @@ import java.util.List;
 import java.util.Random;
 import org.apache.iceberg.relocated.com.google.common.collect.ImmutableList;
 import org.apache.iceberg.relocated.com.google.common.collect.Lists;
+import org.apache.iceberg.types.Conversions;
+import org.apache.iceberg.types.Types;
 import org.apache.iceberg.util.RandomUtil;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.params.ParameterizedTest;
@@ -87,6 +89,18 @@ public class TestValueArray {
     assertThat(actual.get(2).asPrimitive().get()).isEqualTo(new 
BigDecimal("12.21"));
   }
 
+  @Test
+  public void testByteBufferConversion() {
+    ValueArray arr = createArray(ELEMENTS);
+    VariantMetadata metadata = Variants.metadata("$['arr']");
+    Variant expectedVariant = Variant.of(metadata, arr);
+    ByteBuffer convertedValue = 
Conversions.toByteBuffer(Types.VariantType.get(), expectedVariant);
+    Variant readValue = Conversions.fromByteBuffer(Types.VariantType.get(), 
convertedValue);
+
+    VariantTestUtil.assertEqual(expectedVariant.metadata(), 
readValue.metadata());
+    VariantTestUtil.assertEqual(expectedVariant.value(), readValue.value());
+  }
+
   @ParameterizedTest
   @ValueSource(ints = {300, 70_000, 16_777_300})
   public void testMultiByteOffsets(int len) {

Reply via email to