public static boolean equivalent(
      Expression left, Expression right, Types.StructType struct, boolean caseSensitive) {
    return Binder.bind(struct, Expressions.rewriteNot(left), caseSensitive)
        .isEquivalentTo(Binder.bind(struct, Expressions.rewriteNot(right), caseSensitive));
  }
@Test
  public void testIdenticalExpressionIsEquivalent() {
    Expression[] exprs =
        new Expression[] {
          Expressions.isNull("data"),
          Expressions.notNull("data"),
          Expressions.isNaN("measurement"),
          Expressions.notNaN("measurement"),
          Expressions.lessThan("id", 5),
          Expressions.lessThanOrEqual("id", 5),
          Expressions.greaterThan("id", 5),
          Expressions.greaterThanOrEqual("id", 5),
          Expressions.equal("id", 5),
          Expressions.notEqual("id", 5),
          Expressions.in("id", 5, 6),
          Expressions.notIn("id", 5, 6),
          Expressions.startsWith("data", "aaa"),
          Expressions.notStartsWith("data", "aaa"),
          Expressions.alwaysTrue(),
          Expressions.alwaysFalse(),
          Expressions.and(Expressions.lessThan("id", 5), Expressions.notNull("data")),
          Expressions.or(Expressions.lessThan("id", 5), Expressions.notNull("data")),
        };

    for (Expression expr : exprs) {
      assertThat(ExpressionUtil.equivalent(expr, expr, STRUCT, true))
          .as("Should accept identical expression: " + expr)
          .isTrue();

      for (Expression other : exprs) {
        if (expr != other) {
          assertThat(ExpressionUtil.equivalent(expr, other, STRUCT, true)).isFalse();
        }
      }
    }
  }