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

singhpk234 pushed a commit to branch feature/serialize-bound-expression
in repository https://gitbox.apache.org/repos/asf/iceberg.git

commit 11269fceac9324610fd17c5933504b27a6b7f016
Author: Prashant Kumar Singh <[email protected]>
AuthorDate: Fri Sep 26 02:49:25 2025 +0000

    Add ref impl
---
 .../iceberg/expressions/ResolvedTransform.java     |   2 +-
 .../iceberg/expressions/TestResolvedReference.java |  20 +-
 .../iceberg/expressions/ExpressionParser.java      |  11 +-
 .../TestEnhancedExpressionParserWithFieldIds.java  | 299 +++++------
 .../TestExpressionParserWithResolvedReference.java | 572 +++++++++++----------
 5 files changed, 466 insertions(+), 438 deletions(-)

diff --git 
a/api/src/main/java/org/apache/iceberg/expressions/ResolvedTransform.java 
b/api/src/main/java/org/apache/iceberg/expressions/ResolvedTransform.java
index 287fc6d994..07065b2cd7 100644
--- a/api/src/main/java/org/apache/iceberg/expressions/ResolvedTransform.java
+++ b/api/src/main/java/org/apache/iceberg/expressions/ResolvedTransform.java
@@ -85,4 +85,4 @@ public class ResolvedTransform<S, T> implements 
UnboundTerm<T>, Term {
   public int hashCode() {
     return 31 * ref.hashCode() + transform.hashCode();
   }
-}
\ No newline at end of file
+}
diff --git 
a/api/src/test/java/org/apache/iceberg/expressions/TestResolvedReference.java 
b/api/src/test/java/org/apache/iceberg/expressions/TestResolvedReference.java
index 54c5694138..9b03a4e8ea 100644
--- 
a/api/src/test/java/org/apache/iceberg/expressions/TestResolvedReference.java
+++ 
b/api/src/test/java/org/apache/iceberg/expressions/TestResolvedReference.java
@@ -65,7 +65,7 @@ public class TestResolvedReference {
   @Test
   public void testResolvedReferenceBindIgnoresCaseSensitivity() {
     ResolvedReference<Integer> ref = new ResolvedReference<>("A", 34);
-    
+
     // Should work regardless of case sensitivity since we use fieldId
     BoundTerm<Integer> bound1 = ref.bind(SCHEMA.asStruct(), true);
     BoundTerm<Integer> bound2 = ref.bind(SCHEMA.asStruct(), false);
@@ -79,7 +79,7 @@ public class TestResolvedReference {
   @Test
   public void testResolvedReferenceBindWithInvalidFieldId() {
     ResolvedReference<Integer> ref = new ResolvedReference<>("invalid", 999);
-    
+
     assertThatThrownBy(() -> ref.bind(SCHEMA.asStruct(), true))
         .isInstanceOf(ValidationException.class)
         .hasMessageContaining("Cannot find field 'invalid' in struct");
@@ -89,14 +89,14 @@ public class TestResolvedReference {
   public void testResolvedReferenceRef() {
     ResolvedReference<Integer> ref = new ResolvedReference<>("a", 34);
     NamedReference<?> namedRef = ref.ref();
-    
+
     assertThat(namedRef.name()).isEqualTo("a");
   }
 
   @Test
   public void testResolvedReferenceToString() {
     ResolvedReference<Integer> ref = new ResolvedReference<>("a", 34);
-    
+
     assertThat(ref.toString()).isEqualTo("ref(name=\"a\", fieldId=\"34\")");
   }
 
@@ -105,10 +105,10 @@ public class TestResolvedReference {
     // Test that ResolvedReference works in expression predicates
     Expression expr = Expressions.equal(Expressions.ref("a", 34), 5);
     assertThat(expr).isInstanceOf(UnboundPredicate.class);
-    
+
     UnboundPredicate<?> predicate = (UnboundPredicate<?>) expr;
     assertThat(predicate.term()).isInstanceOf(ResolvedReference.class);
-    
+
     ResolvedReference<?> resolvedRef = (ResolvedReference<?>) predicate.term();
     assertThat(resolvedRef.name()).isEqualTo("a");
     assertThat(resolvedRef.fieldId()).isEqualTo(34);
@@ -119,14 +119,14 @@ public class TestResolvedReference {
     // Test that unbinding a bound reference returns a NamedReference for 
compatibility
     Expression expr = Expressions.equal(Expressions.ref("a", 34), 5);
     Expression boundExpr = Binder.bind(SCHEMA.asStruct(), expr, true);
-    
+
     assertThat(boundExpr).isInstanceOf(BoundPredicate.class);
     BoundPredicate<?> boundPred = (BoundPredicate<?>) boundExpr;
-    
+
     UnboundTerm<?> unbound = ExpressionUtil.unbind(boundPred.term());
     assertThat(unbound).isInstanceOf(NamedReference.class);
-    
+
     NamedReference<?> namedRef = (NamedReference<?>) unbound;
     assertThat(namedRef.name()).isEqualTo("a");
   }
-}
\ No newline at end of file
+}
diff --git 
a/core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java 
b/core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java
index 396520f997..91c5355092 100644
--- a/core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java
+++ b/core/src/main/java/org/apache/iceberg/expressions/ExpressionParser.java
@@ -252,7 +252,10 @@ public class ExpressionParser {
       } else if (term instanceof ResolvedTransform) {
         ResolvedTransform<?, ?> transform = (ResolvedTransform<?, ?>) term;
         if (includeFieldIds) {
-          transformWithFieldId(transform.transform().toString(), 
transform.resolvedRef().name(), transform.resolvedRef().fieldId());
+          transformWithFieldId(
+              transform.transform().toString(),
+              transform.resolvedRef().name(),
+              transform.resolvedRef().fieldId());
         } else {
           transform(transform.transform().toString(), transform.ref().name());
         }
@@ -260,7 +263,8 @@ public class ExpressionParser {
       } else if (term instanceof BoundTransform) {
         BoundTransform<?, ?> transform = (BoundTransform<?, ?>) term;
         if (includeFieldIds) {
-          transformWithFieldId(transform.transform().toString(), 
transform.ref().name(), transform.ref().fieldId());
+          transformWithFieldId(
+              transform.transform().toString(), transform.ref().name(), 
transform.ref().fieldId());
         } else {
           transform(transform.transform().toString(), transform.ref().name());
         }
@@ -289,7 +293,8 @@ public class ExpressionParser {
       gen.writeEndObject();
     }
 
-    private void transformWithFieldId(String transform, String name, int 
fieldId) throws IOException {
+    private void transformWithFieldId(String transform, String name, int 
fieldId)
+        throws IOException {
       gen.writeStartObject();
       gen.writeStringField(TYPE, TRANSFORM);
       gen.writeStringField(TRANSFORM, transform);
diff --git 
a/core/src/test/java/org/apache/iceberg/expressions/TestEnhancedExpressionParserWithFieldIds.java
 
b/core/src/test/java/org/apache/iceberg/expressions/TestEnhancedExpressionParserWithFieldIds.java
index 9d5817e82d..e5e2d28a32 100644
--- 
a/core/src/test/java/org/apache/iceberg/expressions/TestEnhancedExpressionParserWithFieldIds.java
+++ 
b/core/src/test/java/org/apache/iceberg/expressions/TestEnhancedExpressionParserWithFieldIds.java
@@ -28,17 +28,16 @@ import java.io.IOException;
 import java.io.UncheckedIOException;
 import java.util.function.Supplier;
 import org.apache.iceberg.Schema;
-import org.apache.iceberg.relocated.com.google.common.base.Preconditions;
 import org.apache.iceberg.types.Types;
 import org.apache.iceberg.util.JsonUtil;
 import org.junit.jupiter.api.Test;
 
 /**
- * Test demonstrating how ExpressionParser could be enhanced to support field 
IDs 
- * for ResolvedReference serialization/deserialization.
- * 
- * This is a proof of concept showing the enhanced JSON format that would 
preserve
- * field ID information during serialization round-trips.
+ * Test demonstrating how ExpressionParser could be enhanced to support field 
IDs for
+ * ResolvedReference serialization/deserialization.
+ *
+ * <p>This is a proof of concept showing the enhanced JSON format that would 
preserve field ID
+ * information during serialization round-trips.
  */
 public class TestEnhancedExpressionParserWithFieldIds {
 
@@ -58,44 +57,46 @@ public class TestEnhancedExpressionParserWithFieldIds {
   public void testEnhancedJsonFormatWithFieldIds() {
     // Test the enhanced JSON format that would support field IDs
     Expression resolvedExpr = Expressions.equal(Expressions.ref("data", 101), 
"test");
-    
+
     // Generate enhanced JSON manually to show the concept
     String enhancedJson = generateEnhancedJson(resolvedExpr);
-    
+
     // Expected enhanced JSON structure with field ID
-    String expectedJson = "{\n" +
-        "  \"type\" : \"eq\",\n" +
-        "  \"term\" : {\n" +
-        "    \"type\" : \"resolved-reference\",\n" +
-        "    \"name\" : \"data\",\n" +
-        "    \"field-id\" : 101\n" +
-        "  },\n" +
-        "  \"value\" : \"test\"\n" +
-        "}";
-    
+    String expectedJson =
+        "{\n"
+            + "  \"type\" : \"eq\",\n"
+            + "  \"term\" : {\n"
+            + "    \"type\" : \"resolved-reference\",\n"
+            + "    \"name\" : \"data\",\n"
+            + "    \"field-id\" : 101\n"
+            + "  },\n"
+            + "  \"value\" : \"test\"\n"
+            + "}";
+
     assertThat(enhancedJson).isEqualTo(expectedJson);
   }
 
   @Test
   public void testEnhancedParsingWithFieldIds() {
     // Test parsing enhanced JSON that includes field IDs
-    String enhancedJson = "{\n" +
-        "  \"type\" : \"eq\",\n" +
-        "  \"term\" : {\n" +
-        "    \"type\" : \"resolved-reference\",\n" +
-        "    \"name\" : \"data\",\n" +
-        "    \"field-id\" : 101\n" +
-        "  },\n" +
-        "  \"value\" : \"test\"\n" +
-        "}";
-    
+    String enhancedJson =
+        "{\n"
+            + "  \"type\" : \"eq\",\n"
+            + "  \"term\" : {\n"
+            + "    \"type\" : \"resolved-reference\",\n"
+            + "    \"name\" : \"data\",\n"
+            + "    \"field-id\" : 101\n"
+            + "  },\n"
+            + "  \"value\" : \"test\"\n"
+            + "}";
+
     // Parse using enhanced parser (concept)
     Expression parsed = parseEnhancedJson(enhancedJson);
-    
+
     assertThat(parsed).isInstanceOf(UnboundPredicate.class);
     UnboundPredicate<?> predicate = (UnboundPredicate<?>) parsed;
     assertThat(predicate.term()).isInstanceOf(ResolvedReference.class);
-    
+
     ResolvedReference<?> resolvedRef = (ResolvedReference<?>) predicate.term();
     assertThat(resolvedRef.name()).isEqualTo("data");
     assertThat(resolvedRef.fieldId()).isEqualTo(101);
@@ -104,18 +105,19 @@ public class TestEnhancedExpressionParserWithFieldIds {
   @Test
   public void testBackwardCompatibilityWithExistingFormat() {
     // Test that enhanced parser can handle existing JSON format without field 
IDs
-    String standardJson = "{\n" +
-        "  \"type\" : \"eq\",\n" +
-        "  \"term\" : \"data\",\n" +
-        "  \"value\" : \"test\"\n" +
-        "}";
-    
+    String standardJson =
+        "{\n"
+            + "  \"type\" : \"eq\",\n"
+            + "  \"term\" : \"data\",\n"
+            + "  \"value\" : \"test\"\n"
+            + "}";
+
     Expression parsed = parseEnhancedJson(standardJson);
-    
+
     assertThat(parsed).isInstanceOf(UnboundPredicate.class);
     UnboundPredicate<?> predicate = (UnboundPredicate<?>) parsed;
     assertThat(predicate.term()).isInstanceOf(NamedReference.class);
-    
+
     NamedReference<?> namedRef = (NamedReference<?>) predicate.term();
     assertThat(namedRef.name()).isEqualTo("data");
   }
@@ -123,28 +125,29 @@ public class TestEnhancedExpressionParserWithFieldIds {
   @Test
   public void testComplexExpressionWithMixedReferences() {
     // Test complex expression with both ResolvedReference and NamedReference
-    Expression mixedExpr = Expressions.and(
-        Expressions.equal(Expressions.ref("data", 101), "test"), // 
ResolvedReference
-        Expressions.isNull("active")); // NamedReference
-    
+    Expression mixedExpr =
+        Expressions.and(
+            Expressions.equal(Expressions.ref("data", 101), "test"), // 
ResolvedReference
+            Expressions.isNull("active")); // NamedReference
+
     String enhancedJson = generateEnhancedJson(mixedExpr);
-    
+
     // Should contain both reference types in JSON
     assertThat(enhancedJson).contains("\"resolved-reference\"");
     assertThat(enhancedJson).contains("\"field-id\" : 101");
     assertThat(enhancedJson).contains("\"active\"");
-    
+
     // Parse back and verify
     Expression parsed = parseEnhancedJson(enhancedJson);
     assertThat(parsed).isInstanceOf(And.class);
-    
+
     And andExpr = (And) parsed;
-    
+
     // Left side should be ResolvedReference
     UnboundPredicate<?> leftPred = (UnboundPredicate<?>) andExpr.left();
     assertThat(leftPred.term()).isInstanceOf(ResolvedReference.class);
-    
-    // Right side should be NamedReference  
+
+    // Right side should be NamedReference
     UnboundPredicate<?> rightPred = (UnboundPredicate<?>) andExpr.right();
     assertThat(rightPred.term()).isInstanceOf(NamedReference.class);
   }
@@ -152,26 +155,27 @@ public class TestEnhancedExpressionParserWithFieldIds {
   @Test
   public void testFieldIdPreservationThroughRoundTrip() {
     // Test that field IDs are preserved through complete round-trip
-    Expression original = Expressions.and(
-        Expressions.greaterThan(Expressions.ref("id", 100), 50L),
-        Expressions.equal(Expressions.ref("data", 101), "test"));
-    
+    Expression original =
+        Expressions.and(
+            Expressions.greaterThan(Expressions.ref("id", 100), 50L),
+            Expressions.equal(Expressions.ref("data", 101), "test"));
+
     // Generate enhanced JSON
     String json = generateEnhancedJson(original);
-    
+
     // Parse back
     Expression parsed = parseEnhancedJson(json);
-    
+
     // Verify structure is preserved
     assertThat(parsed).isInstanceOf(And.class);
     And andExpr = (And) parsed;
-    
+
     // Check left predicate (id > 50)
     UnboundPredicate<?> leftPred = (UnboundPredicate<?>) andExpr.left();
     ResolvedReference<?> leftRef = (ResolvedReference<?>) leftPred.term();
     assertThat(leftRef.name()).isEqualTo("id");
     assertThat(leftRef.fieldId()).isEqualTo(100);
-    
+
     // Check right predicate (data = "test")
     UnboundPredicate<?> rightPred = (UnboundPredicate<?>) andExpr.right();
     ResolvedReference<?> rightRef = (ResolvedReference<?>) rightPred.term();
@@ -182,13 +186,15 @@ public class TestEnhancedExpressionParserWithFieldIds {
   // Helper methods to demonstrate enhanced JSON generation and parsing
 
   private String generateEnhancedJson(Expression expr) {
-    return JsonUtil.generate(gen -> {
-      try {
-        generateEnhanced(expr, gen);
-      } catch (IOException e) {
-        throw new UncheckedIOException(e);
-      }
-    }, true);
+    return JsonUtil.generate(
+        gen -> {
+          try {
+            generateEnhanced(expr, gen);
+          } catch (IOException e) {
+            throw new UncheckedIOException(e);
+          }
+        },
+        true);
   }
 
   private void generateEnhanced(Expression expr, JsonGenerator gen) throws 
IOException {
@@ -205,7 +211,8 @@ public class TestEnhancedExpressionParserWithFieldIds {
   }
 
   // Enhanced JSON visitor that supports field IDs
-  private static class EnhancedJsonVisitor extends 
ExpressionVisitors.CustomOrderExpressionVisitor<Void> {
+  private static class EnhancedJsonVisitor
+      extends ExpressionVisitors.CustomOrderExpressionVisitor<Void> {
     private final JsonGenerator gen;
 
     EnhancedJsonVisitor(JsonGenerator gen) {
@@ -227,103 +234,109 @@ public class TestEnhancedExpressionParserWithFieldIds {
 
     @Override
     public Void alwaysTrue() {
-      return generate(() -> {
-        try {
-          gen.writeBoolean(true);
-        } catch (IOException e) {
-          throw new UncheckedIOException(e);
-        }
-      });
+      return generate(
+          () -> {
+            try {
+              gen.writeBoolean(true);
+            } catch (IOException e) {
+              throw new UncheckedIOException(e);
+            }
+          });
     }
 
     @Override
     public Void alwaysFalse() {
-      return generate(() -> {
-        try {
-          gen.writeBoolean(false);
-        } catch (IOException e) {
-          throw new UncheckedIOException(e);
-        }
-      });
+      return generate(
+          () -> {
+            try {
+              gen.writeBoolean(false);
+            } catch (IOException e) {
+              throw new UncheckedIOException(e);
+            }
+          });
     }
 
     @Override
     public Void not(Supplier<Void> result) {
-      return generate(() -> {
-        try {
-          gen.writeStartObject();
-          gen.writeStringField("type", "not");
-          gen.writeFieldName("child");
-          toJson(result);
-          gen.writeEndObject();
-        } catch (IOException e) {
-          throw new UncheckedIOException(e);
-        }
-      });
+      return generate(
+          () -> {
+            try {
+              gen.writeStartObject();
+              gen.writeStringField("type", "not");
+              gen.writeFieldName("child");
+              toJson(result);
+              gen.writeEndObject();
+            } catch (IOException e) {
+              throw new UncheckedIOException(e);
+            }
+          });
     }
 
     @Override
     public Void and(Supplier<Void> leftResult, Supplier<Void> rightResult) {
-      return generate(() -> {
-        try {
-          gen.writeStartObject();
-          gen.writeStringField("type", "and");
-          gen.writeFieldName("left");
-          toJson(leftResult);
-          gen.writeFieldName("right");
-          toJson(rightResult);
-          gen.writeEndObject();
-        } catch (IOException e) {
-          throw new UncheckedIOException(e);
-        }
-      });
+      return generate(
+          () -> {
+            try {
+              gen.writeStartObject();
+              gen.writeStringField("type", "and");
+              gen.writeFieldName("left");
+              toJson(leftResult);
+              gen.writeFieldName("right");
+              toJson(rightResult);
+              gen.writeEndObject();
+            } catch (IOException e) {
+              throw new UncheckedIOException(e);
+            }
+          });
     }
 
     @Override
     public Void or(Supplier<Void> leftResult, Supplier<Void> rightResult) {
-      return generate(() -> {
-        try {
-          gen.writeStartObject();
-          gen.writeStringField("type", "or");
-          gen.writeFieldName("left");
-          toJson(leftResult);
-          gen.writeFieldName("right");
-          toJson(rightResult);
-          gen.writeEndObject();
-        } catch (IOException e) {
-          throw new UncheckedIOException(e);
-        }
-      });
+      return generate(
+          () -> {
+            try {
+              gen.writeStartObject();
+              gen.writeStringField("type", "or");
+              gen.writeFieldName("left");
+              toJson(leftResult);
+              gen.writeFieldName("right");
+              toJson(rightResult);
+              gen.writeEndObject();
+            } catch (IOException e) {
+              throw new UncheckedIOException(e);
+            }
+          });
     }
 
     @Override
     public <T> Void predicate(UnboundPredicate<T> pred) {
-      return generate(() -> {
-        try {
-          gen.writeStartObject();
-          gen.writeStringField("type", 
pred.op().toString().toLowerCase().replace("_", "-"));
-          gen.writeFieldName("term");
-          writeTerm(pred.term());
-          
-          if (pred.literals() != null && !pred.literals().isEmpty()) {
-            if (pred.literals().size() == 1) {
-              gen.writeFieldName("value");
-              writeLiteral(pred.literals().get(0));
-            } else {
-              gen.writeFieldName("values");
-              gen.writeStartArray();
-              for (Literal<T> literal : pred.literals()) {
-                writeLiteral(literal);
+      return generate(
+          () -> {
+            try {
+              gen.writeStartObject();
+              gen.writeStringField("type", 
pred.op().toString().toLowerCase().replace("_", "-"));
+              gen.writeFieldName("term");
+              writeTerm(pred.term());
+
+              if (pred.literals() != null && !pred.literals().isEmpty()) {
+                if (pred.literals().size() == 1) {
+                  gen.writeFieldName("value");
+                  writeLiteral(pred.literals().get(0));
+                } else {
+                  gen.writeFieldName("values");
+                  gen.writeStartArray();
+                  for (Literal<T> literal : pred.literals()) {
+                    writeLiteral(literal);
+                  }
+                  gen.writeEndArray();
+                }
               }
-              gen.writeEndArray();
+
+              gen.writeEndObject();
+            } catch (IOException e) {
+              throw new UncheckedIOException(e);
             }
-          }
-          
-          gen.writeEndObject();
-        } catch (IOException e) {
-          throw new UncheckedIOException(e);
-        }
-      });
+          });
     }
 
     private void writeTerm(UnboundTerm<?> term) throws IOException {
@@ -385,12 +398,10 @@ public class TestEnhancedExpressionParserWithFieldIds {
         return Expressions.not(parseEnhancedExpression(JsonUtil.get("child", 
node)));
       case "eq":
         return Expressions.equal(
-            parseEnhancedTerm(JsonUtil.get("term", node)),
-            parseValue(JsonUtil.get("value", node)));
+            parseEnhancedTerm(JsonUtil.get("term", node)), 
parseValue(JsonUtil.get("value", node)));
       case "gt":
         return Expressions.greaterThan(
-            parseEnhancedTerm(JsonUtil.get("term", node)),
-            parseValue(JsonUtil.get("value", node)));
+            parseEnhancedTerm(JsonUtil.get("term", node)), 
parseValue(JsonUtil.get("value", node)));
       case "is-null":
         return Expressions.isNull(parseEnhancedTerm(JsonUtil.get("term", 
node)));
       default:
@@ -430,4 +441,4 @@ public class TestEnhancedExpressionParserWithFieldIds {
     }
     return node.asText();
   }
-}
\ No newline at end of file
+}
diff --git 
a/core/src/test/java/org/apache/iceberg/expressions/TestExpressionParserWithResolvedReference.java
 
b/core/src/test/java/org/apache/iceberg/expressions/TestExpressionParserWithResolvedReference.java
index 97981a6471..8a2b0dd139 100644
--- 
a/core/src/test/java/org/apache/iceberg/expressions/TestExpressionParserWithResolvedReference.java
+++ 
b/core/src/test/java/org/apache/iceberg/expressions/TestExpressionParserWithResolvedReference.java
@@ -53,30 +53,31 @@ public class TestExpressionParserWithResolvedReference {
   @Test
   public void testResolvedReferenceExpressionSerialization() {
     // Create expressions using ResolvedReference
-    Expression[] resolvedExpressions = new Expression[] {
-      Expressions.equal(Expressions.ref("id", 100), 42L),
-      Expressions.lessThan(Expressions.ref("data", 101), "test"),
-      Expressions.greaterThanOrEqual(Expressions.ref("i", 103), 10),
-      Expressions.isNull(Expressions.ref("f", 105)),
-      Expressions.notNull(Expressions.ref("date", 107)),
-      Expressions.startsWith(Expressions.ref("s", 110), "prefix"),
-      Expressions.in(Expressions.ref("l", 104), 1L, 2L, 3L),
-      Expressions.notIn(Expressions.ref("b", 102), true, false),
-      Expressions.isNaN(Expressions.ref("d", 106)),
-      Expressions.notNaN(Expressions.ref("f", 105))
-    };
+    Expression[] resolvedExpressions =
+        new Expression[] {
+          Expressions.equal(Expressions.ref("id", 100), 42L),
+          Expressions.lessThan(Expressions.ref("data", 101), "test"),
+          Expressions.greaterThanOrEqual(Expressions.ref("i", 103), 10),
+          Expressions.isNull(Expressions.ref("f", 105)),
+          Expressions.notNull(Expressions.ref("date", 107)),
+          Expressions.startsWith(Expressions.ref("s", 110), "prefix"),
+          Expressions.in(Expressions.ref("l", 104), 1L, 2L, 3L),
+          Expressions.notIn(Expressions.ref("b", 102), true, false),
+          Expressions.isNaN(Expressions.ref("d", 106)),
+          Expressions.notNaN(Expressions.ref("f", 105))
+        };
 
     for (Expression expr : resolvedExpressions) {
       // Verify the expression uses ResolvedReference
       assertThat(expr).isInstanceOf(UnboundPredicate.class);
       UnboundPredicate<?> predicate = (UnboundPredicate<?>) expr;
       assertThat(predicate.term()).isInstanceOf(ResolvedReference.class);
-      
+
       // Test JSON serialization
       String json = ExpressionParser.toJson(expr, true);
       assertThat(json).isNotNull();
       assertThat(json).contains("\"type\"");
-      
+
       // Test that JSON contains the field name (not field ID since parser 
doesn't support it yet)
       ResolvedReference<?> resolvedRef = (ResolvedReference<?>) 
predicate.term();
       assertThat(json).contains(resolvedRef.name());
@@ -88,20 +89,20 @@ public class TestExpressionParserWithResolvedReference {
     // Test that ResolvedReference expressions can be serialized and parsed 
back
     Expression resolvedExpr = Expressions.equal(Expressions.ref("id", 100), 
42L);
     Expression namedExpr = Expressions.equal(Expressions.ref("id"), 42L);
-    
+
     // Both should produce the same JSON since parser only uses names
     String resolvedJson = ExpressionParser.toJson(resolvedExpr, true);
     String namedJson = ExpressionParser.toJson(namedExpr, true);
     assertThat(resolvedJson).isEqualTo(namedJson);
-    
+
     // Parse back and verify equivalence
     Expression parsedFromResolved = ExpressionParser.fromJson(resolvedJson, 
SCHEMA);
     Expression parsedFromNamed = ExpressionParser.fromJson(namedJson, SCHEMA);
-    
+
     // Both parsed expressions should be equivalent
     assertThat(ExpressionUtil.equivalent(parsedFromResolved, parsedFromNamed, 
STRUCT_TYPE, true))
         .isTrue();
-        
+
     // The parsed expression should be equivalent to the original named 
reference expression
     assertThat(ExpressionUtil.equivalent(namedExpr, parsedFromResolved, 
STRUCT_TYPE, true))
         .isTrue();
@@ -110,59 +111,55 @@ public class TestExpressionParserWithResolvedReference {
   @Test
   public void testResolvedReferenceComplexExpressions() {
     // Test complex expressions with ResolvedReference
-    Expression complexExpr = Expressions.and(
-        Expressions.or(
-            Expressions.equal(Expressions.ref("data", 101), "test"),
-            Expressions.isNull(Expressions.ref("data", 101))),
-        Expressions.greaterThanOrEqual(Expressions.ref("id", 100), 100L));
-    
+    Expression complexExpr =
+        Expressions.and(
+            Expressions.or(
+                Expressions.equal(Expressions.ref("data", 101), "test"),
+                Expressions.isNull(Expressions.ref("data", 101))),
+            Expressions.greaterThanOrEqual(Expressions.ref("id", 100), 100L));
+
     // Serialize to JSON
     String json = ExpressionParser.toJson(complexExpr, true);
     assertThat(json).contains("\"type\" : \"and\"");
     assertThat(json).contains("\"type\" : \"or\"");
     assertThat(json).contains("\"data\"");
     assertThat(json).contains("\"id\"");
-    
+
     // Parse back
     Expression parsed = ExpressionParser.fromJson(json, SCHEMA);
-    
+
     // Create equivalent expression with NamedReference for comparison
-    Expression namedEquivalent = Expressions.and(
-        Expressions.or(
-            Expressions.equal("data", "test"),
-            Expressions.isNull("data")),
-        Expressions.greaterThanOrEqual("id", 100L));
-    
+    Expression namedEquivalent =
+        Expressions.and(
+            Expressions.or(Expressions.equal("data", "test"), 
Expressions.isNull("data")),
+            Expressions.greaterThanOrEqual("id", 100L));
+
     // Should be equivalent
-    assertThat(ExpressionUtil.equivalent(namedEquivalent, parsed, STRUCT_TYPE, 
true))
-        .isTrue();
+    assertThat(ExpressionUtil.equivalent(namedEquivalent, parsed, STRUCT_TYPE, 
true)).isTrue();
   }
 
   @Test
   public void testResolvedReferenceTransformExpressions() {
-    // Test transform expressions - using NamedReference for transforms since 
+    // Test transform expressions - using NamedReference for transforms since
     // ResolvedReference needs proper type parameters for transform methods
-    Expression dayTransform = Expressions.equal(
-        Expressions.day("date"), "2023-01-15");
-    Expression bucketTransform = Expressions.equal(
-        Expressions.bucket("id", 10), 5);
-    
+    Expression dayTransform = Expressions.equal(Expressions.day("date"), 
"2023-01-15");
+    Expression bucketTransform = Expressions.equal(Expressions.bucket("id", 
10), 5);
+
     // Test serialization
     String dayJson = ExpressionParser.toJson(dayTransform, true);
     String bucketJson = ExpressionParser.toJson(bucketTransform, true);
-    
+
     assertThat(dayJson).contains("\"transform\" : \"day\"");
     assertThat(dayJson).contains("\"term\" : \"date\"");
     assertThat(bucketJson).contains("\"transform\" : \"bucket[10]\"");
     assertThat(bucketJson).contains("\"term\" : \"id\"");
-    
+
     // Test round-trip
     Expression parsedDay = ExpressionParser.fromJson(dayJson, SCHEMA);
     Expression parsedBucket = ExpressionParser.fromJson(bucketJson, SCHEMA);
-    
+
     // Should maintain equivalence after round-trip
-    assertThat(ExpressionUtil.equivalent(dayTransform, parsedDay, STRUCT_TYPE, 
true))
-        .isTrue();
+    assertThat(ExpressionUtil.equivalent(dayTransform, parsedDay, STRUCT_TYPE, 
true)).isTrue();
     assertThat(ExpressionUtil.equivalent(bucketTransform, parsedBucket, 
STRUCT_TYPE, true))
         .isTrue();
   }
@@ -171,22 +168,22 @@ public class TestExpressionParserWithResolvedReference {
   public void testResolvedReferenceBindingAfterParsing() {
     // Test that expressions with ResolvedReference bind correctly after 
parsing
     Expression original = Expressions.equal(Expressions.ref("id", 100), 42L);
-    
+
     // Serialize and parse
     String json = ExpressionParser.toJson(original, true);
     Expression parsed = ExpressionParser.fromJson(json, SCHEMA);
-    
+
     // Both should bind successfully
     Expression originalBound = Binder.bind(STRUCT_TYPE, original, true);
     Expression parsedBound = Binder.bind(STRUCT_TYPE, parsed, true);
-    
+
     // Both bound expressions should be identical
     assertThat(originalBound).isInstanceOf(BoundPredicate.class);
     assertThat(parsedBound).isInstanceOf(BoundPredicate.class);
-    
+
     BoundPredicate<?> originalBoundPred = (BoundPredicate<?>) originalBound;
     BoundPredicate<?> parsedBoundPred = (BoundPredicate<?>) parsedBound;
-    
+
     // Should reference the same field
     assertThat(originalBoundPred.ref().fieldId()).isEqualTo(100);
     assertThat(parsedBoundPred.ref().fieldId()).isEqualTo(100);
@@ -197,26 +194,27 @@ public class TestExpressionParserWithResolvedReference {
   @Test
   public void testResolvedReferenceWithDifferentTypes() {
     // Test ResolvedReference with various data types
-    Expression[] typedExpressions = new Expression[] {
-      Expressions.equal(Expressions.ref("b", 102), true),
-      Expressions.equal(Expressions.ref("i", 103), 42),
-      Expressions.equal(Expressions.ref("l", 104), 42L),
-      Expressions.equal(Expressions.ref("f", 105), 3.14f),
-      Expressions.equal(Expressions.ref("d", 106), 3.14159),
-      Expressions.equal(Expressions.ref("s", 110), "test string"),
-      Expressions.equal(Expressions.ref("uuid", 111), UUID.randomUUID()),
-      Expressions.equal(Expressions.ref("dec_11_2", 115), new 
BigDecimal("123.45"))
-    };
-    
+    Expression[] typedExpressions =
+        new Expression[] {
+          Expressions.equal(Expressions.ref("b", 102), true),
+          Expressions.equal(Expressions.ref("i", 103), 42),
+          Expressions.equal(Expressions.ref("l", 104), 42L),
+          Expressions.equal(Expressions.ref("f", 105), 3.14f),
+          Expressions.equal(Expressions.ref("d", 106), 3.14159),
+          Expressions.equal(Expressions.ref("s", 110), "test string"),
+          Expressions.equal(Expressions.ref("uuid", 111), UUID.randomUUID()),
+          Expressions.equal(Expressions.ref("dec_11_2", 115), new 
BigDecimal("123.45"))
+        };
+
     for (Expression expr : typedExpressions) {
       // Test serialization doesn't break with different types
       String json = ExpressionParser.toJson(expr, true);
       assertThat(json).isNotNull();
-      
+
       // Test parsing back
       Expression parsed = ExpressionParser.fromJson(json, SCHEMA);
       assertThat(parsed).isNotNull();
-      
+
       // Test binding
       Expression bound = Binder.bind(STRUCT_TYPE, parsed, true);
       assertThat(bound).isInstanceOf(BoundPredicate.class);
@@ -228,20 +226,21 @@ public class TestExpressionParserWithResolvedReference {
     // Test the exact JSON structure produced by ResolvedReference
     Expression expr = Expressions.equal(Expressions.ref("data", 101), "test");
     String json = ExpressionParser.toJson(expr, true);
-    
+
     // The JSON should look like a regular reference since parser doesn't 
support field IDs yet
-    String expectedStructure = "{\n" +
-        "  \"type\" : \"eq\",\n" +
-        "  \"term\" : \"data\",\n" +
-        "  \"value\" : \"test\"\n" +
-        "}";
-    
+    String expectedStructure =
+        "{\n"
+            + "  \"type\" : \"eq\",\n"
+            + "  \"term\" : \"data\",\n"
+            + "  \"value\" : \"test\"\n"
+            + "}";
+
     assertThat(json).isEqualTo(expectedStructure);
-    
+
     // Verify it parses back correctly
     Expression parsed = ExpressionParser.fromJson(json);
     assertThat(parsed).isInstanceOf(UnboundPredicate.class);
-    
+
     UnboundPredicate<?> predicate = (UnboundPredicate<?>) parsed;
     assertThat(predicate.term()).isInstanceOf(NamedReference.class);
     assertThat(predicate.term().ref().name()).isEqualTo("data");
@@ -250,58 +249,57 @@ public class TestExpressionParserWithResolvedReference {
   @Test
   public void testResolvedReferenceEquivalenceAfterSerialization() {
     // Test that ResolvedReference expressions maintain equivalence after 
serialization
-    Expression resolvedExpr = Expressions.and(
-        Expressions.greaterThan(Expressions.ref("id", 100), 50L),
-        Expressions.lessThan(Expressions.ref("id", 100), 200L));
-        
-    Expression namedExpr = Expressions.and(
-        Expressions.greaterThan("id", 50L),
-        Expressions.lessThan("id", 200L));
-    
+    Expression resolvedExpr =
+        Expressions.and(
+            Expressions.greaterThan(Expressions.ref("id", 100), 50L),
+            Expressions.lessThan(Expressions.ref("id", 100), 200L));
+
+    Expression namedExpr =
+        Expressions.and(Expressions.greaterThan("id", 50L), 
Expressions.lessThan("id", 200L));
+
     // Serialize both
     String resolvedJson = ExpressionParser.toJson(resolvedExpr, true);
     String namedJson = ExpressionParser.toJson(namedExpr, true);
-    
+
     // Should produce identical JSON
     assertThat(resolvedJson).isEqualTo(namedJson);
-    
+
     // Parse both back
     Expression parsedResolved = ExpressionParser.fromJson(resolvedJson, 
SCHEMA);
     Expression parsedNamed = ExpressionParser.fromJson(namedJson, SCHEMA);
-    
+
     // All should be equivalent
-    assertThat(ExpressionUtil.equivalent(resolvedExpr, namedExpr, STRUCT_TYPE, 
true))
-        .isTrue();
-    assertThat(ExpressionUtil.equivalent(parsedResolved, parsedNamed, 
STRUCT_TYPE, true))
-        .isTrue();
-    assertThat(ExpressionUtil.equivalent(resolvedExpr, parsedResolved, 
STRUCT_TYPE, true))
-        .isTrue();
+    assertThat(ExpressionUtil.equivalent(resolvedExpr, namedExpr, STRUCT_TYPE, 
true)).isTrue();
+    assertThat(ExpressionUtil.equivalent(parsedResolved, parsedNamed, 
STRUCT_TYPE, true)).isTrue();
+    assertThat(ExpressionUtil.equivalent(resolvedExpr, parsedResolved, 
STRUCT_TYPE, true)).isTrue();
   }
 
   @Test
   public void testResolvedReferenceTransformExpressionEquivalence() {
-    // Test expressions that reference transforms where the transform terms 
are equivalent to resolved references
-    // Since UnboundTransform only accepts NamedReference, we test equivalence 
through binding/unbinding
-    
+    // Test expressions that reference transforms where the transform terms 
are equivalent to
+    // resolved references
+    // Since UnboundTransform only accepts NamedReference, we test equivalence 
through
+    // binding/unbinding
+
     // Create transform expressions using NamedReference (current approach)
     Expression dayTransformNamed = Expressions.equal(Expressions.day("date"), 
"2023-01-15");
     Expression bucketTransformNamed = 
Expressions.equal(Expressions.bucket("id", 10), 5);
     Expression truncateTransformNamed = 
Expressions.equal(Expressions.truncate("data", 4), "test");
-    
+
     // Create equivalent expressions using ResolvedReference for the predicate 
terms
     Expression dayWithResolvedRef = Expressions.equal(Expressions.ref("date", 
107), "2023-01-15");
     Expression bucketWithResolvedRef = Expressions.equal(Expressions.ref("id", 
100), 5L);
     Expression truncateWithResolvedRef = 
Expressions.equal(Expressions.ref("data", 101), "test");
-    
+
     // Bind all expressions
     Expression boundDayTransform = Binder.bind(STRUCT_TYPE, dayTransformNamed, 
true);
     Expression boundBucketTransform = Binder.bind(STRUCT_TYPE, 
bucketTransformNamed, true);
     Expression boundTruncateTransform = Binder.bind(STRUCT_TYPE, 
truncateTransformNamed, true);
-    
+
     Expression boundDayResolved = Binder.bind(STRUCT_TYPE, dayWithResolvedRef, 
true);
     Expression boundBucketResolved = Binder.bind(STRUCT_TYPE, 
bucketWithResolvedRef, true);
     Expression boundTruncateResolved = Binder.bind(STRUCT_TYPE, 
truncateWithResolvedRef, true);
-    
+
     // Verify all expressions bound successfully
     assertThat(boundDayTransform).isInstanceOf(BoundPredicate.class);
     assertThat(boundBucketTransform).isInstanceOf(BoundPredicate.class);
@@ -309,40 +307,42 @@ public class TestExpressionParserWithResolvedReference {
     assertThat(boundDayResolved).isInstanceOf(BoundPredicate.class);
     assertThat(boundBucketResolved).isInstanceOf(BoundPredicate.class);
     assertThat(boundTruncateResolved).isInstanceOf(BoundPredicate.class);
-    
+
     // Test transform expressions in complex expressions with resolved 
references
-    Expression complexTransformExpr = Expressions.and(
-        Expressions.equal(Expressions.day("date"), "2023-01-15"),
-        Expressions.equal(Expressions.ref("id", 100), 42L));
-        
+    Expression complexTransformExpr =
+        Expressions.and(
+            Expressions.equal(Expressions.day("date"), "2023-01-15"),
+            Expressions.equal(Expressions.ref("id", 100), 42L));
+
     Expression boundComplexExpr = Binder.bind(STRUCT_TYPE, 
complexTransformExpr, true);
     assertThat(boundComplexExpr).isInstanceOf(And.class);
-    
+
     // Verify serialization works for transform expressions that coexist with 
resolved references
     String complexJson = ExpressionParser.toJson(complexTransformExpr, true);
     assertThat(complexJson).contains("\"transform\" : \"day\"");
     assertThat(complexJson).contains("\"term\" : \"date\"");
     assertThat(complexJson).contains("\"term\" : \"id\"");
-    
+
     // Verify round-trip maintains correctness
     Expression parsedComplex = ExpressionParser.fromJson(complexJson, SCHEMA);
     Expression boundParsedComplex = Binder.bind(STRUCT_TYPE, parsedComplex, 
true);
-    
+
     // Both bound expressions should reference the same fields
     
assertThat(boundComplexExpr.toString()).isEqualTo(boundParsedComplex.toString());
   }
 
-  @Test 
+  @Test
   public void testResolvedReferenceInComplexTransformExpressions() {
     // Test complex expressions that combine transforms with resolved 
references
-    Expression complexExpr = Expressions.or(
-        Expressions.and(
-            Expressions.equal(Expressions.bucket("id", 8), 3),
-            Expressions.equal(Expressions.ref("data", 101), "test")),
-        Expressions.and(
-            Expressions.equal(Expressions.day("date"), "2023-01-15"), 
-            Expressions.isNull(Expressions.ref("f", 105))));
-    
+    Expression complexExpr =
+        Expressions.or(
+            Expressions.and(
+                Expressions.equal(Expressions.bucket("id", 8), 3),
+                Expressions.equal(Expressions.ref("data", 101), "test")),
+            Expressions.and(
+                Expressions.equal(Expressions.day("date"), "2023-01-15"),
+                Expressions.isNull(Expressions.ref("f", 105))));
+
     // Test serialization
     String json = ExpressionParser.toJson(complexExpr, true);
     assertThat(json).contains("\"transform\" : \"bucket[8]\"");
@@ -351,21 +351,21 @@ public class TestExpressionParserWithResolvedReference {
     assertThat(json).contains("\"term\" : \"date\"");
     assertThat(json).contains("\"term\" : \"data\"");
     assertThat(json).contains("\"term\" : \"f\"");
-    
+
     // Test that parsing back maintains structure
     Expression parsed = ExpressionParser.fromJson(json, SCHEMA);
     assertThat(parsed).isInstanceOf(Or.class);
-    
+
     // Test binding works correctly
     Expression bound = Binder.bind(STRUCT_TYPE, parsed, true);
     assertThat(bound).isInstanceOf(Or.class);
-    
+
     // Verify equivalence with original
     assertThat(ExpressionUtil.equivalent(complexExpr, parsed, STRUCT_TYPE, 
true)).isTrue();
-    
+
     // Test that mixed transform and resolved reference expressions bind to 
same fields
     Expression originalBound = Binder.bind(STRUCT_TYPE, complexExpr, true);
-    
+
     // Both bound expressions should be structurally equivalent
     assertThat(originalBound.toString()).isEqualTo(bound.toString());
   }
@@ -374,38 +374,36 @@ public class TestExpressionParserWithResolvedReference {
   public void testTransformExpressionsWithResolvedReference() {
     // Test expressions that reference transforms which in turn reference 
resolved references
     // Create transforms using the new ResolvedReference-based factory methods
-    Expression bucketExpr = Expressions.equal(
-        Expressions.bucket(Expressions.ref("id", 100), 8), 3);
-    Expression dayExpr = Expressions.equal(
-        Expressions.day(Expressions.ref("date", 107)), "2023-01-15");
-    Expression hourExpr = Expressions.equal(
-        Expressions.hour(Expressions.ref("ts", 108)), 10);
-    Expression truncateExpr = Expressions.equal(
-        Expressions.truncate(Expressions.ref("data", 101), 4), "test");
-    
+    Expression bucketExpr = 
Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 8), 3);
+    Expression dayExpr =
+        Expressions.equal(Expressions.day(Expressions.ref("date", 107)), 
"2023-01-15");
+    Expression hourExpr = 
Expressions.equal(Expressions.hour(Expressions.ref("ts", 108)), 10);
+    Expression truncateExpr =
+        Expressions.equal(Expressions.truncate(Expressions.ref("data", 101), 
4), "test");
+
     // Verify the expressions are created correctly
     assertThat(bucketExpr).isInstanceOf(UnboundPredicate.class);
     assertThat(dayExpr).isInstanceOf(UnboundPredicate.class);
     assertThat(hourExpr).isInstanceOf(UnboundPredicate.class);
     assertThat(truncateExpr).isInstanceOf(UnboundPredicate.class);
-    
+
     // Verify the terms are ResolvedTransform instances
     UnboundPredicate<?> bucketPred = (UnboundPredicate<?>) bucketExpr;
     UnboundPredicate<?> dayPred = (UnboundPredicate<?>) dayExpr;
     UnboundPredicate<?> hourPred = (UnboundPredicate<?>) hourExpr;
     UnboundPredicate<?> truncatePred = (UnboundPredicate<?>) truncateExpr;
-    
+
     assertThat(bucketPred.term()).isInstanceOf(ResolvedTransform.class);
     assertThat(dayPred.term()).isInstanceOf(ResolvedTransform.class);
     assertThat(hourPred.term()).isInstanceOf(ResolvedTransform.class);
     assertThat(truncatePred.term()).isInstanceOf(ResolvedTransform.class);
-    
+
     // Verify that ResolvedTransform preserves the ResolvedReference with 
field IDs
     ResolvedTransform<?, ?> bucketTransform = (ResolvedTransform<?, ?>) 
bucketPred.term();
     ResolvedTransform<?, ?> dayTransform = (ResolvedTransform<?, ?>) 
dayPred.term();
     ResolvedTransform<?, ?> hourTransform = (ResolvedTransform<?, ?>) 
hourPred.term();
     ResolvedTransform<?, ?> truncateTransform = (ResolvedTransform<?, ?>) 
truncatePred.term();
-    
+
     assertThat(bucketTransform.resolvedRef().fieldId()).isEqualTo(100);
     assertThat(bucketTransform.resolvedRef().name()).isEqualTo("id");
     assertThat(dayTransform.resolvedRef().fieldId()).isEqualTo(107);
@@ -414,13 +412,13 @@ public class TestExpressionParserWithResolvedReference {
     assertThat(hourTransform.resolvedRef().name()).isEqualTo("ts");
     assertThat(truncateTransform.resolvedRef().fieldId()).isEqualTo(101);
     assertThat(truncateTransform.resolvedRef().name()).isEqualTo("data");
-    
+
     // Test serialization
     String bucketJson = ExpressionParser.toJson(bucketExpr, true);
     String dayJson = ExpressionParser.toJson(dayExpr, true);
     String hourJson = ExpressionParser.toJson(hourExpr, true);
     String truncateJson = ExpressionParser.toJson(truncateExpr, true);
-    
+
     // Verify JSON contains the expected transform and term information
     assertThat(bucketJson).contains("\"transform\" : \"bucket[8]\"");
     assertThat(bucketJson).contains("\"term\" : \"id\"");
@@ -430,36 +428,36 @@ public class TestExpressionParserWithResolvedReference {
     assertThat(hourJson).contains("\"term\" : \"ts\"");
     assertThat(truncateJson).contains("\"transform\" : \"truncate[4]\"");
     assertThat(truncateJson).contains("\"term\" : \"data\"");
-    
+
     // Test parsing back
     Expression parsedBucket = ExpressionParser.fromJson(bucketJson, SCHEMA);
     Expression parsedDay = ExpressionParser.fromJson(dayJson, SCHEMA);
     Expression parsedHour = ExpressionParser.fromJson(hourJson, SCHEMA);
     Expression parsedTruncate = ExpressionParser.fromJson(truncateJson, 
SCHEMA);
-    
+
     // Verify equivalence after round-trip
     assertThat(ExpressionUtil.equivalent(bucketExpr, parsedBucket, 
STRUCT_TYPE, true)).isTrue();
     assertThat(ExpressionUtil.equivalent(dayExpr, parsedDay, STRUCT_TYPE, 
true)).isTrue();
     assertThat(ExpressionUtil.equivalent(hourExpr, parsedHour, STRUCT_TYPE, 
true)).isTrue();
     assertThat(ExpressionUtil.equivalent(truncateExpr, parsedTruncate, 
STRUCT_TYPE, true)).isTrue();
-    
+
     // Test binding works correctly
     Expression boundBucket = Binder.bind(STRUCT_TYPE, parsedBucket, true);
     Expression boundDay = Binder.bind(STRUCT_TYPE, parsedDay, true);
     Expression boundHour = Binder.bind(STRUCT_TYPE, parsedHour, true);
     Expression boundTruncate = Binder.bind(STRUCT_TYPE, parsedTruncate, true);
-    
+
     assertThat(boundBucket).isInstanceOf(BoundPredicate.class);
     assertThat(boundDay).isInstanceOf(BoundPredicate.class);
     assertThat(boundHour).isInstanceOf(BoundPredicate.class);
     assertThat(boundTruncate).isInstanceOf(BoundPredicate.class);
-    
+
     // Verify bound expressions reference correct field IDs
     BoundPredicate<?> boundBucketPred = (BoundPredicate<?>) boundBucket;
     BoundPredicate<?> boundDayPred = (BoundPredicate<?>) boundDay;
     BoundPredicate<?> boundHourPred = (BoundPredicate<?>) boundHour;
     BoundPredicate<?> boundTruncatePred = (BoundPredicate<?>) boundTruncate;
-    
+
     assertThat(boundBucketPred.term()).isInstanceOf(BoundTransform.class);
     assertThat(boundDayPred.term()).isInstanceOf(BoundTransform.class);
     assertThat(boundHourPred.term()).isInstanceOf(BoundTransform.class);
@@ -469,17 +467,18 @@ public class TestExpressionParserWithResolvedReference {
   @Test
   public void testComplexExpressionsWithResolvedReferenceTransforms() {
     // Test complex expressions combining transforms created from 
ResolvedReference
-    Expression complexExpr = Expressions.and(
-        Expressions.or(
-            Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 
8), 3),
-            Expressions.equal(Expressions.day(Expressions.ref("date", 107)), 
"2023-01-15")),
+    Expression complexExpr =
         Expressions.and(
-            Expressions.equal(Expressions.truncate(Expressions.ref("data", 
101), 4), "test"),
-            Expressions.isNull(Expressions.ref("f", 105))));
-    
+            Expressions.or(
+                Expressions.equal(Expressions.bucket(Expressions.ref("id", 
100), 8), 3),
+                Expressions.equal(Expressions.day(Expressions.ref("date", 
107)), "2023-01-15")),
+            Expressions.and(
+                Expressions.equal(Expressions.truncate(Expressions.ref("data", 
101), 4), "test"),
+                Expressions.isNull(Expressions.ref("f", 105))));
+
     // Test serialization of complex expression
     String json = ExpressionParser.toJson(complexExpr, true);
-    
+
     // Verify all transforms and terms are present in JSON
     assertThat(json).contains("\"transform\" : \"bucket[8]\"");
     assertThat(json).contains("\"transform\" : \"day\"");
@@ -488,18 +487,18 @@ public class TestExpressionParserWithResolvedReference {
     assertThat(json).contains("\"term\" : \"date\"");
     assertThat(json).contains("\"term\" : \"data\"");
     assertThat(json).contains("\"term\" : \"f\"");
-    
+
     // Test parsing back maintains structure
     Expression parsed = ExpressionParser.fromJson(json, SCHEMA);
     assertThat(parsed).isInstanceOf(And.class);
-    
+
     // Test binding works correctly for the complex expression
     Expression bound = Binder.bind(STRUCT_TYPE, parsed, true);
     assertThat(bound).isInstanceOf(And.class);
-    
+
     // Verify equivalence after round-trip
     assertThat(ExpressionUtil.equivalent(complexExpr, parsed, STRUCT_TYPE, 
true)).isTrue();
-    
+
     // Test that the bound expression maintains correct structure
     Expression originalBound = Binder.bind(STRUCT_TYPE, complexExpr, true);
     assertThat(originalBound.toString()).isEqualTo(bound.toString());
@@ -507,46 +506,50 @@ public class TestExpressionParserWithResolvedReference {
 
   @Test
   public void testResolvedReferenceTransformCompatibilityWithNamedReference() {
-    // Test that transforms created with ResolvedReference are equivalent to 
those created with NamedReference
-    
+    // Test that transforms created with ResolvedReference are equivalent to 
those created with
+    // NamedReference
+
     // Create equivalent transforms using both approaches
-    Expression bucketWithResolved = Expressions.equal(
-        Expressions.bucket(Expressions.ref("id", 100), 8), 3);
-    Expression bucketWithNamed = Expressions.equal(
-        Expressions.bucket("id", 8), 3);
-    
-    Expression dayWithResolved = Expressions.equal(
-        Expressions.day(Expressions.ref("date", 107)), "2023-01-15");
-    Expression dayWithNamed = Expressions.equal(
-        Expressions.day("date"), "2023-01-15");
-    
+    Expression bucketWithResolved =
+        Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 8), 
3);
+    Expression bucketWithNamed = Expressions.equal(Expressions.bucket("id", 
8), 3);
+
+    Expression dayWithResolved =
+        Expressions.equal(Expressions.day(Expressions.ref("date", 107)), 
"2023-01-15");
+    Expression dayWithNamed = Expressions.equal(Expressions.day("date"), 
"2023-01-15");
+
     // Test that both serialize to the same JSON
     String resolvedBucketJson = ExpressionParser.toJson(bucketWithResolved, 
true);
     String namedBucketJson = ExpressionParser.toJson(bucketWithNamed, true);
     String resolvedDayJson = ExpressionParser.toJson(dayWithResolved, true);
     String namedDayJson = ExpressionParser.toJson(dayWithNamed, true);
-    
+
     assertThat(resolvedBucketJson).isEqualTo(namedBucketJson);
     assertThat(resolvedDayJson).isEqualTo(namedDayJson);
-    
+
     // Test that parsing back produces equivalent expressions
     Expression parsedResolvedBucket = 
ExpressionParser.fromJson(resolvedBucketJson, SCHEMA);
     Expression parsedNamedBucket = ExpressionParser.fromJson(namedBucketJson, 
SCHEMA);
     Expression parsedResolvedDay = ExpressionParser.fromJson(resolvedDayJson, 
SCHEMA);
     Expression parsedNamedDay = ExpressionParser.fromJson(namedDayJson, 
SCHEMA);
-    
+
     // All should be equivalent
-    assertThat(ExpressionUtil.equivalent(bucketWithResolved, bucketWithNamed, 
STRUCT_TYPE, true)).isTrue();
-    assertThat(ExpressionUtil.equivalent(dayWithResolved, dayWithNamed, 
STRUCT_TYPE, true)).isTrue();
-    assertThat(ExpressionUtil.equivalent(parsedResolvedBucket, 
parsedNamedBucket, STRUCT_TYPE, true)).isTrue();
-    assertThat(ExpressionUtil.equivalent(parsedResolvedDay, parsedNamedDay, 
STRUCT_TYPE, true)).isTrue();
-    
+    assertThat(ExpressionUtil.equivalent(bucketWithResolved, bucketWithNamed, 
STRUCT_TYPE, true))
+        .isTrue();
+    assertThat(ExpressionUtil.equivalent(dayWithResolved, dayWithNamed, 
STRUCT_TYPE, true))
+        .isTrue();
+    assertThat(
+            ExpressionUtil.equivalent(parsedResolvedBucket, parsedNamedBucket, 
STRUCT_TYPE, true))
+        .isTrue();
+    assertThat(ExpressionUtil.equivalent(parsedResolvedDay, parsedNamedDay, 
STRUCT_TYPE, true))
+        .isTrue();
+
     // Test that binding produces identical results
     Expression boundResolvedBucket = Binder.bind(STRUCT_TYPE, 
parsedResolvedBucket, true);
     Expression boundNamedBucket = Binder.bind(STRUCT_TYPE, parsedNamedBucket, 
true);
     Expression boundResolvedDay = Binder.bind(STRUCT_TYPE, parsedResolvedDay, 
true);
     Expression boundNamedDay = Binder.bind(STRUCT_TYPE, parsedNamedDay, true);
-    
+
     
assertThat(boundResolvedBucket.toString()).isEqualTo(boundNamedBucket.toString());
     
assertThat(boundResolvedDay.toString()).isEqualTo(boundNamedDay.toString());
   }
@@ -555,40 +558,40 @@ public class TestExpressionParserWithResolvedReference {
   public void testResolvedTransformPreservesFieldIdInformation() {
     // Test that ResolvedTransform preserves field ID information through 
binding
     // This is the key advantage over UnboundTransform with NamedReference
-    
+
     // Create a transform expression using ResolvedReference
     ResolvedReference<Long> idRef = Expressions.ref("id", 100);
     Expression bucketExpr = Expressions.equal(Expressions.bucket(idRef, 8), 3);
-    
+
     // Verify it's a ResolvedTransform
     UnboundPredicate<?> predicate = (UnboundPredicate<?>) bucketExpr;
     assertThat(predicate.term()).isInstanceOf(ResolvedTransform.class);
-    
+
     ResolvedTransform<?, ?> resolvedTransform = (ResolvedTransform<?, ?>) 
predicate.term();
-    
+
     // Verify the ResolvedReference is preserved with field ID
     assertThat(resolvedTransform.resolvedRef().fieldId()).isEqualTo(100);
     assertThat(resolvedTransform.resolvedRef().name()).isEqualTo("id");
-    
+
     // Test binding works correctly with field ID information
     Expression bound = Binder.bind(STRUCT_TYPE, bucketExpr, true);
     assertThat(bound).isInstanceOf(BoundPredicate.class);
-    
+
     BoundPredicate<?> boundPredicate = (BoundPredicate<?>) bound;
     assertThat(boundPredicate.term()).isInstanceOf(BoundTransform.class);
-    
+
     BoundTransform<?, ?> boundTransform = (BoundTransform<?, ?>) 
boundPredicate.term();
     assertThat(boundTransform.ref().fieldId()).isEqualTo(100);
     assertThat(boundTransform.ref().name()).isEqualTo("id");
-    
+
     // Compare with equivalent NamedReference approach to show they bind to 
same field
     Expression namedBucketExpr = Expressions.equal(Expressions.bucket("id", 
8), 3);
     Expression boundNamed = Binder.bind(STRUCT_TYPE, namedBucketExpr, true);
-    
+
     // Both should resolve to the same field ID since they reference the same 
field
     BoundPredicate<?> boundNamedPredicate = (BoundPredicate<?>) boundNamed;
     BoundTransform<?, ?> boundNamedTransform = (BoundTransform<?, ?>) 
boundNamedPredicate.term();
-    
+
     
assertThat(boundTransform.ref().fieldId()).isEqualTo(boundNamedTransform.ref().fieldId());
     
assertThat(boundTransform.toString()).isEqualTo(boundNamedTransform.toString());
   }
@@ -596,43 +599,42 @@ public class TestExpressionParserWithResolvedReference {
   @Test
   public void testResolvedTransformExpressionParserIntegration() {
     // Test that expressions with ResolvedTransform integrate correctly with 
ExpressionParser
-    
+
     // Create expressions using ResolvedTransform
-    Expression bucketExpr = Expressions.equal(
-        Expressions.bucket(Expressions.ref("id", 100), 8), 3);
-    Expression dayExpr = Expressions.equal(
-        Expressions.day(Expressions.ref("date", 107)), "2023-01-15");
-    
+    Expression bucketExpr = 
Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 8), 3);
+    Expression dayExpr =
+        Expressions.equal(Expressions.day(Expressions.ref("date", 107)), 
"2023-01-15");
+
     // Test that they can be serialized (even though they become 
NamedReference in JSON)
     String bucketJson = ExpressionParser.toJson(bucketExpr, true);
     String dayJson = ExpressionParser.toJson(dayExpr, true);
-    
+
     assertThat(bucketJson).contains("\"transform\" : \"bucket[8]\"");
     assertThat(bucketJson).contains("\"term\" : \"id\"");
     assertThat(dayJson).contains("\"transform\" : \"day\"");
     assertThat(dayJson).contains("\"term\" : \"date\"");
-    
+
     // Test parsing back (will create UnboundTransform with NamedReference)
     Expression parsedBucket = ExpressionParser.fromJson(bucketJson, SCHEMA);
     Expression parsedDay = ExpressionParser.fromJson(dayJson, SCHEMA);
-    
+
     // The parsed expressions will have UnboundTransform (not 
ResolvedTransform)
     // but they should still be functionally equivalent when bound
     UnboundPredicate<?> parsedBucketPred = (UnboundPredicate<?>) parsedBucket;
     UnboundPredicate<?> parsedDayPred = (UnboundPredicate<?>) parsedDay;
-    
+
     assertThat(parsedBucketPred.term()).isInstanceOf(UnboundTransform.class);
     assertThat(parsedDayPred.term()).isInstanceOf(UnboundTransform.class);
-    
+
     // Both original and parsed should bind to the same fields
     Expression originalBucketBound = Binder.bind(STRUCT_TYPE, bucketExpr, 
true);
     Expression parsedBucketBound = Binder.bind(STRUCT_TYPE, parsedBucket, 
true);
     Expression originalDayBound = Binder.bind(STRUCT_TYPE, dayExpr, true);
     Expression parsedDayBound = Binder.bind(STRUCT_TYPE, parsedDay, true);
-    
+
     
assertThat(originalBucketBound.toString()).isEqualTo(parsedBucketBound.toString());
     
assertThat(originalDayBound.toString()).isEqualTo(parsedDayBound.toString());
-    
+
     // Test equivalence
     assertThat(ExpressionUtil.equivalent(bucketExpr, parsedBucket, 
STRUCT_TYPE, true)).isTrue();
     assertThat(ExpressionUtil.equivalent(dayExpr, parsedDay, STRUCT_TYPE, 
true)).isTrue();
@@ -641,65 +643,68 @@ public class TestExpressionParserWithResolvedReference {
   @Test
   public void testMixedResolvedTransformAndResolvedReferenceExpressions() {
     // Test complex expressions mixing ResolvedTransform and direct 
ResolvedReference
-    Expression complexExpr = Expressions.and(
-        Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 8), 
3),
-        Expressions.or(
-            Expressions.equal(Expressions.ref("data", 101), "test"),
-            Expressions.equal(Expressions.day(Expressions.ref("date", 107)), 
"2023-01-15")));
-    
+    Expression complexExpr =
+        Expressions.and(
+            Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 
8), 3),
+            Expressions.or(
+                Expressions.equal(Expressions.ref("data", 101), "test"),
+                Expressions.equal(Expressions.day(Expressions.ref("date", 
107)), "2023-01-15")));
+
     // Verify structure contains both ResolvedTransform and ResolvedReference
     assertThat(complexExpr).isInstanceOf(And.class);
     And andExpr = (And) complexExpr;
-    
+
     // First part should be ResolvedTransform
     UnboundPredicate<?> bucketPred = (UnboundPredicate<?>) andExpr.left();
     assertThat(bucketPred.term()).isInstanceOf(ResolvedTransform.class);
-    
+
     // Second part is OR with ResolvedReference and ResolvedTransform
     Or orExpr = (Or) andExpr.right();
     UnboundPredicate<?> dataPred = (UnboundPredicate<?>) orExpr.left();
     UnboundPredicate<?> dayPred = (UnboundPredicate<?>) orExpr.right();
-    
+
     assertThat(dataPred.term()).isInstanceOf(ResolvedReference.class);
     assertThat(dayPred.term()).isInstanceOf(ResolvedTransform.class);
-    
+
     // Test serialization and parsing
     String json = ExpressionParser.toJson(complexExpr, true);
     Expression parsed = ExpressionParser.fromJson(json, SCHEMA);
-    
+
     // Test binding works correctly
     Expression bound = Binder.bind(STRUCT_TYPE, parsed, true);
     Expression originalBound = Binder.bind(STRUCT_TYPE, complexExpr, true);
-    
+
     assertThat(bound.toString()).isEqualTo(originalBound.toString());
     assertThat(ExpressionUtil.equivalent(complexExpr, parsed, STRUCT_TYPE, 
true)).isTrue();
   }
 
   @Test
   public void testBoundExpressionSerializationWithResolvedReference() {
-    // Test that bound expressions serialize to JSON with ResolvedReference 
terms when includeFieldIds=true
-    
+    // Test that bound expressions serialize to JSON with ResolvedReference 
terms when
+    // includeFieldIds=true
+
     // Create and bind simple expressions
     Expression simpleExpr = Expressions.equal(Expressions.ref("id", 100), 42L);
     Expression boundSimple = Binder.bind(STRUCT_TYPE, simpleExpr, true);
-    
+
     // Test serialization without field IDs (existing behavior)
     String jsonWithoutFieldIds = ExpressionParser.toJson(boundSimple, true);
     assertThat(jsonWithoutFieldIds).contains("\"term\" : \"id\"");
     assertThat(jsonWithoutFieldIds).doesNotContain("fieldId");
-    
+
     // Test serialization with field IDs (new behavior)
     String jsonWithFieldIds = ExpressionParser.toJson(boundSimple, true, true);
     assertThat(jsonWithFieldIds).contains("\"type\" : \"ref\"");
     assertThat(jsonWithFieldIds).contains("\"name\" : \"id\"");
     assertThat(jsonWithFieldIds).contains("\"fieldId\" : 100");
-    
+
     // Test complex expressions
-    Expression complexExpr = Expressions.and(
-        Expressions.equal(Expressions.ref("data", 101), "test"),
-        Expressions.greaterThan(Expressions.ref("id", 100), 50L));
+    Expression complexExpr =
+        Expressions.and(
+            Expressions.equal(Expressions.ref("data", 101), "test"),
+            Expressions.greaterThan(Expressions.ref("id", 100), 50L));
     Expression boundComplex = Binder.bind(STRUCT_TYPE, complexExpr, true);
-    
+
     String complexJsonWithFieldIds = ExpressionParser.toJson(boundComplex, 
true, true);
     assertThat(complexJsonWithFieldIds).contains("\"fieldId\" : 100");
     assertThat(complexJsonWithFieldIds).contains("\"fieldId\" : 101");
@@ -709,31 +714,31 @@ public class TestExpressionParserWithResolvedReference {
 
   @Test
   public void testBoundTransformExpressionSerializationWithResolvedReference() 
{
-    // Test that bound transform expressions serialize to JSON with 
ResolvedReference terms when includeFieldIds=true
-    
+    // Test that bound transform expressions serialize to JSON with 
ResolvedReference terms when
+    // includeFieldIds=true
+
     // Create transform expressions using ResolvedTransform
-    Expression bucketExpr = Expressions.equal(
-        Expressions.bucket(Expressions.ref("id", 100), 8), 3);
-    Expression dayExpr = Expressions.equal(
-        Expressions.day(Expressions.ref("date", 107)), "2023-01-15");
-    
+    Expression bucketExpr = 
Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 8), 3);
+    Expression dayExpr =
+        Expressions.equal(Expressions.day(Expressions.ref("date", 107)), 
"2023-01-15");
+
     // Bind the expressions
     Expression boundBucket = Binder.bind(STRUCT_TYPE, bucketExpr, true);
     Expression boundDay = Binder.bind(STRUCT_TYPE, dayExpr, true);
-    
+
     // Test serialization without field IDs (existing behavior)
     String bucketJsonNoFieldIds = ExpressionParser.toJson(boundBucket, true);
     assertThat(bucketJsonNoFieldIds).contains("\"transform\" : \"bucket[8]\"");
     assertThat(bucketJsonNoFieldIds).contains("\"term\" : \"id\"");
     assertThat(bucketJsonNoFieldIds).doesNotContain("fieldId");
-    
+
     // Test serialization with field IDs (new behavior)
     String bucketJsonWithFieldIds = ExpressionParser.toJson(boundBucket, true, 
true);
     assertThat(bucketJsonWithFieldIds).contains("\"transform\" : 
\"bucket[8]\"");
     assertThat(bucketJsonWithFieldIds).contains("\"type\" : \"ref\"");
     assertThat(bucketJsonWithFieldIds).contains("\"name\" : \"id\"");
     assertThat(bucketJsonWithFieldIds).contains("\"fieldId\" : 100");
-    
+
     String dayJsonWithFieldIds = ExpressionParser.toJson(boundDay, true, true);
     assertThat(dayJsonWithFieldIds).contains("\"transform\" : \"day\"");
     assertThat(dayJsonWithFieldIds).contains("\"type\" : \"ref\"");
@@ -744,83 +749,89 @@ public class TestExpressionParserWithResolvedReference {
   @Test
   public void 
testComplexBoundTransformExpressionSerializationWithResolvedReference() {
     // Test complex bound expressions with mixed transforms and references
-    Expression complexExpr = Expressions.and(
-        Expressions.or(
-            Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 
8), 3),
-            Expressions.equal(Expressions.day(Expressions.ref("date", 107)), 
"2023-01-15")),
+    Expression complexExpr =
         Expressions.and(
-            Expressions.equal(Expressions.truncate(Expressions.ref("data", 
101), 4), "test"),
-            Expressions.isNull(Expressions.ref("f", 105))));
-    
+            Expressions.or(
+                Expressions.equal(Expressions.bucket(Expressions.ref("id", 
100), 8), 3),
+                Expressions.equal(Expressions.day(Expressions.ref("date", 
107)), "2023-01-15")),
+            Expressions.and(
+                Expressions.equal(Expressions.truncate(Expressions.ref("data", 
101), 4), "test"),
+                Expressions.isNull(Expressions.ref("f", 105))));
+
     // Bind the complex expression
     Expression bound = Binder.bind(STRUCT_TYPE, complexExpr, true);
-    
+
     // Test serialization with field IDs
     String jsonWithFieldIds = ExpressionParser.toJson(bound, true, true);
-    
+
     // Verify all field IDs are present
     assertThat(jsonWithFieldIds).contains("\"fieldId\" : 100"); // id field
-    assertThat(jsonWithFieldIds).contains("\"fieldId\" : 107"); // date field  
+    assertThat(jsonWithFieldIds).contains("\"fieldId\" : 107"); // date field
     assertThat(jsonWithFieldIds).contains("\"fieldId\" : 101"); // data field
     assertThat(jsonWithFieldIds).contains("\"fieldId\" : 105"); // f field
-    
+
     // Verify all field names are present
     assertThat(jsonWithFieldIds).contains("\"name\" : \"id\"");
     assertThat(jsonWithFieldIds).contains("\"name\" : \"date\"");
     assertThat(jsonWithFieldIds).contains("\"name\" : \"data\"");
     assertThat(jsonWithFieldIds).contains("\"name\" : \"f\"");
-    
+
     // Verify transforms are serialized correctly
     assertThat(jsonWithFieldIds).contains("\"transform\" : \"bucket[8]\"");
     assertThat(jsonWithFieldIds).contains("\"transform\" : \"day\"");
     assertThat(jsonWithFieldIds).contains("\"transform\" : \"truncate[4]\"");
-    
+
     // Verify ResolvedReference structure for both transforms and direct 
references
     // Count occurrences of "type" : "ref" to ensure all references use 
ResolvedReference format
-    long refTypeCount = jsonWithFieldIds.lines()
-        .mapToLong(line -> {
-          int count = 0;
-          int index = 0;
-          String pattern = "\"type\" : \"ref\"";
-          while ((index = line.indexOf(pattern, index)) != -1) {
-            count++;
-            index += pattern.length();
-          }
-          return count;
-        })
-        .sum();
-    
+    long refTypeCount =
+        jsonWithFieldIds
+            .lines()
+            .mapToLong(
+                line -> {
+                  int count = 0;
+                  int index = 0;
+                  String pattern = "\"type\" : \"ref\"";
+                  while ((index = line.indexOf(pattern, index)) != -1) {
+                    count++;
+                    index += pattern.length();
+                  }
+                  return count;
+                })
+            .sum();
+
     assertThat(refTypeCount).isEqualTo(4); // Should have 4 ResolvedReference 
objects
   }
 
   @Test
   public void testBoundExpressionRoundTripWithResolvedReference() {
     // Test that bound expressions with ResolvedReference can be serialized 
and maintain information
-    
+
     // Create expressions using both ResolvedTransform and ResolvedReference
-    Expression originalExpr = Expressions.and(
-        Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 8), 
3),
-        Expressions.equal(Expressions.ref("data", 101), "test"));
-    
+    Expression originalExpr =
+        Expressions.and(
+            Expressions.equal(Expressions.bucket(Expressions.ref("id", 100), 
8), 3),
+            Expressions.equal(Expressions.ref("data", 101), "test"));
+
     // Bind the expression
     Expression bound = Binder.bind(STRUCT_TYPE, originalExpr, true);
-    
+
     // Serialize with field IDs
     String jsonWithFieldIds = ExpressionParser.toJson(bound, true, true);
-    
+
     // Verify the JSON structure contains complete ResolvedReference 
information
     assertThat(jsonWithFieldIds).contains("\"type\" : \"ref\"");
     assertThat(jsonWithFieldIds).contains("\"fieldId\" : 100");
     assertThat(jsonWithFieldIds).contains("\"fieldId\" : 101");
-    
+
     // Note: The current parser doesn't support parsing ResolvedReference 
format back to expressions
-    // This test documents the serialization capability for external systems 
that need field ID information
-    
+    // This test documents the serialization capability for external systems 
that need field ID
+    // information
+
     // Verify that the bound expression maintains the same field IDs after 
serialization
     BoundPredicate<?> boundPred = (BoundPredicate<?>) ((And) bound).left();
     BoundTransform<?, ?> boundTransform = (BoundTransform<?, ?>) 
boundPred.term();
     assertThat(boundTransform.ref().fieldId()).isEqualTo(100);
-    
+
     BoundPredicate<?> boundDataPred = (BoundPredicate<?>) ((And) 
bound).right();
     BoundReference<?> boundDataRef = (BoundReference<?>) boundDataPred.term();
     assertThat(boundDataRef.fieldId()).isEqualTo(101);
@@ -829,35 +840,36 @@ public class TestExpressionParserWithResolvedReference {
   @Test
   public void testBoundExpressionFieldIdPreservationAcrossAllTypes() {
     // Test that all data types preserve field IDs correctly in bound 
expression serialization
-    
+
     // Create expressions for fields that support meaningful comparisons
-    Expression[] expressions = new Expression[] {
-        Expressions.equal(Expressions.ref("id", 100), 42L),
-        Expressions.equal(Expressions.ref("data", 101), "test"),
-        Expressions.equal(Expressions.ref("b", 102), true),
-        Expressions.equal(Expressions.ref("i", 103), 42),
-        Expressions.equal(Expressions.ref("l", 104), 42L),
-        Expressions.equal(Expressions.ref("f", 105), 3.14f),
-        Expressions.equal(Expressions.ref("d", 106), 3.14159),
-        Expressions.equal(Expressions.ref("s", 110), "test-string"),
-        Expressions.greaterThan(Expressions.ref("id", 100), 10L)
-    };
-    
+    Expression[] expressions =
+        new Expression[] {
+          Expressions.equal(Expressions.ref("id", 100), 42L),
+          Expressions.equal(Expressions.ref("data", 101), "test"),
+          Expressions.equal(Expressions.ref("b", 102), true),
+          Expressions.equal(Expressions.ref("i", 103), 42),
+          Expressions.equal(Expressions.ref("l", 104), 42L),
+          Expressions.equal(Expressions.ref("f", 105), 3.14f),
+          Expressions.equal(Expressions.ref("d", 106), 3.14159),
+          Expressions.equal(Expressions.ref("s", 110), "test-string"),
+          Expressions.greaterThan(Expressions.ref("id", 100), 10L)
+        };
+
     for (Expression expr : expressions) {
       // Bind each expression
       Expression bound = Binder.bind(STRUCT_TYPE, expr, true);
-      
+
       // Serialize with field IDs
       String json = ExpressionParser.toJson(bound, true, true);
-      
+
       // Extract expected field ID from the original ResolvedReference
       UnboundPredicate<?> unboundPred = (UnboundPredicate<?>) expr;
       ResolvedReference<?> resolvedRef = (ResolvedReference<?>) 
unboundPred.term();
       int expectedFieldId = resolvedRef.fieldId();
-      
+
       // Verify the field ID is preserved in the JSON
       assertThat(json).contains("\"fieldId\" : " + expectedFieldId);
       assertThat(json).contains("\"type\" : \"ref\"");
     }
   }
-}
\ No newline at end of file
+}

Reply via email to