You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@druid.apache.org by su...@apache.org on 2021/11/17 16:23:10 UTC

[druid] branch master updated: Adding safe divide function (#11904)

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

suneet pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/druid.git


The following commit(s) were added to refs/heads/master by this push:
     new 2971078  Adding safe divide function (#11904)
2971078 is described below

commit 29710789a438bd2c16bf2d1e556b96f8ccb57611
Author: somu-imply <93...@users.noreply.github.com>
AuthorDate: Wed Nov 17 08:22:41 2021 -0800

    Adding safe divide function (#11904)
    
    * IMPLY-4344: Adding safe divide function along with testcases and documentation updates
    
    * Changing based on review comments
    
    * Addressing review comments, fixing coding style, docs and spelling
    
    * Checkstyle passes for all code
    
    * Fixing expected results for infinity
    
    * Revert "Fixing expected results for infinity"
    
    This reverts commit 5fd5cd480dd29706dd6e4b3c736611fe8dc74c85.
    
    * Updating test result and a space in docs
---
 .../java/org/apache/druid/math/expr/Function.java  |   62 +-
 .../org/apache/druid/math/expr/FunctionTest.java   |  141 ++-
 .../org/apache/druid/math/expr/OutputTypeTest.java |  192 +++-
 docs/misc/math-expr.md                             |    1 +
 docs/querying/sql.md                               |    2 +
 .../builtin/SafeDivideOperatorConversion.java      |   51 +
 .../sql/calcite/planner/DruidOperatorTable.java    |    7 +
 .../apache/druid/sql/calcite/CalciteQueryTest.java | 1073 +++++++++++++-------
 website/.spelling                                  |    1 +
 9 files changed, 1056 insertions(+), 474 deletions(-)

diff --git a/core/src/main/java/org/apache/druid/math/expr/Function.java b/core/src/main/java/org/apache/druid/math/expr/Function.java
index 2d45567..b02f88e 100644
--- a/core/src/main/java/org/apache/druid/math/expr/Function.java
+++ b/core/src/main/java/org/apache/druid/math/expr/Function.java
@@ -59,7 +59,7 @@ import java.util.stream.Stream;
 /**
  * Base interface describing the mechanism used to evaluate a {@link FunctionExpr}. All {@link Function} implementations
  * are immutable.
- *
+ * <p>
  * Do NOT remove "unused" members in this class. They are used by generated Antlr
  */
 @SuppressWarnings("unused")
@@ -1165,6 +1165,51 @@ public interface Function
     }
   }
 
+  class SafeDivide extends BivariateMathFunction
+  {
+    public static final String NAME = "safe_divide";
+
+    @Override
+    public String name()
+    {
+      return NAME;
+    }
+
+    @Nullable
+    @Override
+    public ExpressionType getOutputType(Expr.InputBindingInspector inspector, List<Expr> args)
+    {
+      return ExpressionTypeConversion.function(
+          args.get(0).getOutputType(inspector),
+          args.get(1).getOutputType(inspector)
+      );
+    }
+
+    @Override
+    protected ExprEval eval(final long x, final long y)
+    {
+      if (y == 0) {
+        if (x != 0) {
+          return ExprEval.ofLong(NullHandling.defaultLongValue());
+        }
+        return ExprEval.ofLong(0);
+      }
+      return ExprEval.ofLong(x / y);
+    }
+
+    @Override
+    protected ExprEval eval(final double x, final double y)
+    {
+      if (y == 0 || Double.isNaN(y)) {
+        if (x != 0) {
+          return ExprEval.ofDouble(NullHandling.defaultDoubleValue());
+        }
+        return ExprEval.ofDouble(0);
+      }
+      return ExprEval.ofDouble(x / y);
+    }
+  }
+
   class Div extends BivariateMathFunction
   {
     @Override
@@ -1932,7 +1977,9 @@ public interface Function
     public Set<Expr> getScalarInputs(List<Expr> args)
     {
       if (args.get(1).isLiteral()) {
-        ExpressionType castTo = ExpressionType.fromString(StringUtils.toUpperCase(args.get(1).getLiteralValue().toString()));
+        ExpressionType castTo = ExpressionType.fromString(StringUtils.toUpperCase(args.get(1)
+                                                                                      .getLiteralValue()
+                                                                                      .toString()));
         switch (castTo.getType()) {
           case ARRAY:
             return Collections.emptySet();
@@ -1948,7 +1995,9 @@ public interface Function
     public Set<Expr> getArrayInputs(List<Expr> args)
     {
       if (args.get(1).isLiteral()) {
-        ExpressionType castTo = ExpressionType.fromString(StringUtils.toUpperCase(args.get(1).getLiteralValue().toString()));
+        ExpressionType castTo = ExpressionType.fromString(StringUtils.toUpperCase(args.get(1)
+                                                                                      .getLiteralValue()
+                                                                                      .toString()));
         switch (castTo.getType()) {
           case LONG:
           case DOUBLE:
@@ -3237,7 +3286,9 @@ public interface Function
               break;
             }
           }
-          return index < 0 ? ExprEval.ofLong(NullHandling.replaceWithDefault() ? -1 : null) : ExprEval.ofLong(index + 1);
+          return index < 0
+                 ? ExprEval.ofLong(NullHandling.replaceWithDefault() ? -1 : null)
+                 : ExprEval.ofLong(index + 1);
         default:
           throw new IAE("Function[%s] 2nd argument must be a a scalar type", name());
       }
@@ -3591,7 +3642,8 @@ public interface Function
             name()
         );
       }
-      ExpressionType complexType = ExpressionTypeFactory.getInstance().ofComplex((String) args.get(0).getLiteralValue());
+      ExpressionType complexType = ExpressionTypeFactory.getInstance()
+                                                        .ofComplex((String) args.get(0).getLiteralValue());
       ObjectByteStrategy strategy = Types.getStrategy(complexType.getComplexTypeName());
       if (strategy == null) {
         throw new IAE(
diff --git a/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java b/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java
index bc7afa3..11d6b23 100644
--- a/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java
+++ b/core/src/test/java/org/apache/druid/math/expr/FunctionTest.java
@@ -52,30 +52,36 @@ public class FunctionTest extends InitializedNullHandlingTest
   @BeforeClass
   public static void setupClass()
   {
-    Types.registerStrategy(TypesTest.NULLABLE_TEST_PAIR_TYPE.getComplexTypeName(), new TypesTest.PairObjectByteStrategy());
+    Types.registerStrategy(
+        TypesTest.NULLABLE_TEST_PAIR_TYPE.getComplexTypeName(),
+        new TypesTest.PairObjectByteStrategy()
+    );
   }
 
   @Before
   public void setup()
   {
     ImmutableMap.Builder<String, Object> builder = ImmutableMap.<String, Object>builder()
-        .put("x", "foo")
-        .put("y", 2)
-        .put("z", 3.1)
-        .put("d", 34.56D)
-        .put("maxLong", Long.MAX_VALUE)
-        .put("minLong", Long.MIN_VALUE)
-        .put("f", 12.34F)
-        .put("nan", Double.NaN)
-        .put("inf", Double.POSITIVE_INFINITY)
-        .put("-inf", Double.NEGATIVE_INFINITY)
-        .put("o", 0)
-        .put("od", 0D)
-        .put("of", 0F)
-        .put("a", new String[] {"foo", "bar", "baz", "foobar"})
-        .put("b", new Long[] {1L, 2L, 3L, 4L, 5L})
-        .put("c", new Double[] {3.1, 4.2, 5.3})
-        .put("someComplex", new TypesTest.NullableLongPair(1L, 2L));
+                                                               .put("x", "foo")
+                                                               .put("y", 2)
+                                                               .put("z", 3.1)
+                                                               .put("d", 34.56D)
+                                                               .put("maxLong", Long.MAX_VALUE)
+                                                               .put("minLong", Long.MIN_VALUE)
+                                                               .put("f", 12.34F)
+                                                               .put("nan", Double.NaN)
+                                                               .put("inf", Double.POSITIVE_INFINITY)
+                                                               .put("-inf", Double.NEGATIVE_INFINITY)
+                                                               .put("o", 0)
+                                                               .put("od", 0D)
+                                                               .put("of", 0F)
+                                                               .put("a", new String[]{"foo", "bar", "baz", "foobar"})
+                                                               .put("b", new Long[]{1L, 2L, 3L, 4L, 5L})
+                                                               .put("c", new Double[]{3.1, 4.2, 5.3})
+                                                               .put(
+                                                                   "someComplex",
+                                                                   new TypesTest.NullableLongPair(1L, 2L)
+                                                               );
     bindings = InputBindings.withMap(builder.build());
   }
 
@@ -350,17 +356,20 @@ public class FunctionTest extends InitializedNullHandlingTest
     assertArrayExpr("cast([1, 2, 3], 'STRING_ARRAY')", new String[]{"1", "2", "3"});
     assertArrayExpr("cast([1, 2, 3], 'DOUBLE_ARRAY')", new Double[]{1.0, 2.0, 3.0});
     assertArrayExpr("cast(c, 'LONG_ARRAY')", new Long[]{3L, 4L, 5L});
-    assertArrayExpr("cast(string_to_array(array_to_string(b, ','), ','), 'LONG_ARRAY')", new Long[]{1L, 2L, 3L, 4L, 5L});
+    assertArrayExpr(
+        "cast(string_to_array(array_to_string(b, ','), ','), 'LONG_ARRAY')",
+        new Long[]{1L, 2L, 3L, 4L, 5L}
+    );
     assertArrayExpr("cast(['1.0', '2.0', '3.0'], 'LONG_ARRAY')", new Long[]{1L, 2L, 3L});
   }
 
   @Test
   public void testArraySlice()
   {
-    assertArrayExpr("array_slice([1, 2, 3, 4], 1, 3)", new Long[] {2L, 3L});
-    assertArrayExpr("array_slice([1.0, 2.1, 3.2, 4.3], 2)", new Double[] {3.2, 4.3});
-    assertArrayExpr("array_slice(['a', 'b', 'c', 'd'], 4, 6)", new String[] {null, null});
-    assertArrayExpr("array_slice([1, 2, 3, 4], 2, 2)", new Long[] {});
+    assertArrayExpr("array_slice([1, 2, 3, 4], 1, 3)", new Long[]{2L, 3L});
+    assertArrayExpr("array_slice([1.0, 2.1, 3.2, 4.3], 2)", new Double[]{3.2, 4.3});
+    assertArrayExpr("array_slice(['a', 'b', 'c', 'd'], 4, 6)", new String[]{null, null});
+    assertArrayExpr("array_slice([1, 2, 3, 4], 2, 2)", new Long[]{});
     assertArrayExpr("array_slice([1, 2, 3, 4], 5, 7)", null);
     assertArrayExpr("array_slice([1, 2, 3, 4], 2, 1)", null);
   }
@@ -438,12 +447,24 @@ public class FunctionTest extends InitializedNullHandlingTest
     assertExpr("round(maxLong)", BigDecimal.valueOf(Long.MAX_VALUE).setScale(0, RoundingMode.HALF_UP).longValue());
     assertExpr("round(minLong)", BigDecimal.valueOf(Long.MIN_VALUE).setScale(0, RoundingMode.HALF_UP).longValue());
     // overflow
-    assertExpr("round(maxLong + 1, 1)", BigDecimal.valueOf(Long.MIN_VALUE).setScale(1, RoundingMode.HALF_UP).longValue());
+    assertExpr(
+        "round(maxLong + 1, 1)",
+        BigDecimal.valueOf(Long.MIN_VALUE).setScale(1, RoundingMode.HALF_UP).longValue()
+    );
     // underflow
-    assertExpr("round(minLong - 1, -2)", BigDecimal.valueOf(Long.MAX_VALUE).setScale(-2, RoundingMode.HALF_UP).longValue());
+    assertExpr(
+        "round(minLong - 1, -2)",
+        BigDecimal.valueOf(Long.MAX_VALUE).setScale(-2, RoundingMode.HALF_UP).longValue()
+    );
 
-    assertExpr("round(CAST(maxLong, 'DOUBLE') + 1, 1)", BigDecimal.valueOf(((double) Long.MAX_VALUE) + 1).setScale(1, RoundingMode.HALF_UP).doubleValue());
-    assertExpr("round(CAST(minLong, 'DOUBLE') - 1, -2)", BigDecimal.valueOf(((double) Long.MIN_VALUE) - 1).setScale(-2, RoundingMode.HALF_UP).doubleValue());
+    assertExpr(
+        "round(CAST(maxLong, 'DOUBLE') + 1, 1)",
+        BigDecimal.valueOf(((double) Long.MAX_VALUE) + 1).setScale(1, RoundingMode.HALF_UP).doubleValue()
+    );
+    assertExpr(
+        "round(CAST(minLong, 'DOUBLE') - 1, -2)",
+        BigDecimal.valueOf(((double) Long.MIN_VALUE) - 1).setScale(-2, RoundingMode.HALF_UP).doubleValue()
+    );
   }
 
   @Test
@@ -643,7 +664,10 @@ public class FunctionTest extends InitializedNullHandlingTest
       Assert.assertTrue(NullHandling.sqlCompatible() ? true : false);
     }
     catch (IAE e) {
-      Assert.assertEquals("Function[human_readable_binary_byte_format] needs a number as its first argument", e.getMessage());
+      Assert.assertEquals(
+          "Function[human_readable_binary_byte_format] needs a number as its first argument",
+          e.getMessage()
+      );
     }
 
     try {
@@ -655,7 +679,10 @@ public class FunctionTest extends InitializedNullHandlingTest
       Assert.assertTrue(false);
     }
     catch (IAE e) {
-      Assert.assertEquals("Function[human_readable_binary_byte_format] needs an integer as its second argument", e.getMessage());
+      Assert.assertEquals(
+          "Function[human_readable_binary_byte_format] needs an integer as its second argument",
+          e.getMessage()
+      );
     }
 
     try {
@@ -667,7 +694,10 @@ public class FunctionTest extends InitializedNullHandlingTest
       Assert.assertTrue(false);
     }
     catch (IAE e) {
-      Assert.assertEquals("Function[human_readable_binary_byte_format] needs an integer as its second argument", e.getMessage());
+      Assert.assertEquals(
+          "Function[human_readable_binary_byte_format] needs an integer as its second argument",
+          e.getMessage()
+      );
     }
 
     try {
@@ -679,7 +709,10 @@ public class FunctionTest extends InitializedNullHandlingTest
       Assert.assertTrue(false);
     }
     catch (IAE e) {
-      Assert.assertEquals("Function[human_readable_binary_byte_format] needs an integer as its second argument", e.getMessage());
+      Assert.assertEquals(
+          "Function[human_readable_binary_byte_format] needs an integer as its second argument",
+          e.getMessage()
+      );
     }
   }
 
@@ -692,7 +725,10 @@ public class FunctionTest extends InitializedNullHandlingTest
       Assert.assertTrue(false);
     }
     catch (IAE e) {
-      Assert.assertEquals("Given precision[9223372036854775807] of Function[human_readable_binary_byte_format] must be in the range of [0,3]", e.getMessage());
+      Assert.assertEquals(
+          "Given precision[9223372036854775807] of Function[human_readable_binary_byte_format] must be in the range of [0,3]",
+          e.getMessage()
+      );
     }
 
     try {
@@ -701,7 +737,10 @@ public class FunctionTest extends InitializedNullHandlingTest
       Assert.assertTrue(false);
     }
     catch (IAE e) {
-      Assert.assertEquals("Given precision[-9223372036854775808] of Function[human_readable_binary_byte_format] must be in the range of [0,3]", e.getMessage());
+      Assert.assertEquals(
+          "Given precision[-9223372036854775808] of Function[human_readable_binary_byte_format] must be in the range of [0,3]",
+          e.getMessage()
+      );
     }
 
     try {
@@ -710,7 +749,10 @@ public class FunctionTest extends InitializedNullHandlingTest
       Assert.assertTrue(false);
     }
     catch (IAE e) {
-      Assert.assertEquals("Given precision[-1] of Function[human_readable_binary_byte_format] must be in the range of [0,3]", e.getMessage());
+      Assert.assertEquals(
+          "Given precision[-1] of Function[human_readable_binary_byte_format] must be in the range of [0,3]",
+          e.getMessage()
+      );
     }
 
     try {
@@ -719,7 +761,10 @@ public class FunctionTest extends InitializedNullHandlingTest
       Assert.assertTrue(false);
     }
     catch (IAE e) {
-      Assert.assertEquals("Given precision[4] of Function[human_readable_binary_byte_format] must be in the range of [0,3]", e.getMessage());
+      Assert.assertEquals(
+          "Given precision[4] of Function[human_readable_binary_byte_format] must be in the range of [0,3]",
+          e.getMessage()
+      );
     }
   }
 
@@ -733,6 +778,21 @@ public class FunctionTest extends InitializedNullHandlingTest
   }
 
   @Test
+  public void testSafeDivide()
+  {
+    // happy path maths
+    assertExpr("safe_divide(3, 1)", 3L);
+    assertExpr("safe_divide(4.5, 2)", 2.25);
+    assertExpr("safe_divide(3, 0)", NullHandling.defaultLongValue());
+    assertExpr("safe_divide(1, 0.0)", NullHandling.defaultDoubleValue());
+    // NaN and Infinity cases
+    assertExpr("safe_divide(NaN, 0.0)", NullHandling.defaultDoubleValue());
+    assertExpr("safe_divide(0, NaN)", 0.0);
+    assertExpr("safe_divide(0, POSITIVE_INFINITY)", NullHandling.defaultLongValue());
+    assertExpr("safe_divide(POSITIVE_INFINITY,0)", NullHandling.defaultLongValue());
+  }
+
+  @Test
   public void testBitwise()
   {
     // happy path maths
@@ -763,7 +823,10 @@ public class FunctionTest extends InitializedNullHandlingTest
       Assert.fail("Did not throw IllegalArgumentException");
     }
     catch (IllegalArgumentException e) {
-      Assert.assertEquals("Possible data truncation, param [461168601842738800000000000000.000000] is out of long value range", e.getMessage());
+      Assert.assertEquals(
+          "Possible data truncation, param [461168601842738800000000000000.000000] is out of long value range",
+          e.getMessage()
+      );
     }
 
     // doubles are cast
@@ -845,7 +908,8 @@ public class FunctionTest extends InitializedNullHandlingTest
   public void testComplexDecodeBaseArg0BadType()
   {
     expectedException.expect(IAE.class);
-    expectedException.expectMessage("Function[complex_decode_base64] first argument must be constant 'STRING' expression containing a valid complex type name");
+    expectedException.expectMessage(
+        "Function[complex_decode_base64] first argument must be constant 'STRING' expression containing a valid complex type name");
     assertExpr(
         "complex_decode_base64(1, string)",
         null
@@ -856,7 +920,8 @@ public class FunctionTest extends InitializedNullHandlingTest
   public void testComplexDecodeBaseArg0Unknown()
   {
     expectedException.expect(IAE.class);
-    expectedException.expectMessage("Function[complex_decode_base64] first argument must be a valid complex type name, unknown complex type [COMPLEX<unknown>]");
+    expectedException.expectMessage(
+        "Function[complex_decode_base64] first argument must be a valid complex type name, unknown complex type [COMPLEX<unknown>]");
     assertExpr(
         "complex_decode_base64('unknown', string)",
         null
diff --git a/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java b/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java
index 07d523a..2cb097e 100644
--- a/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java
+++ b/core/src/test/java/org/apache/druid/math/expr/OutputTypeTest.java
@@ -33,18 +33,18 @@ public class OutputTypeTest extends InitializedNullHandlingTest
 {
   private final Expr.InputBindingInspector inspector = inspectorFromMap(
       ImmutableMap.<String, ExpressionType>builder().put("x", ExpressionType.STRING)
-                                              .put("x_", ExpressionType.STRING)
-                                              .put("y", ExpressionType.LONG)
-                                              .put("y_", ExpressionType.LONG)
-                                              .put("z", ExpressionType.DOUBLE)
-                                              .put("z_", ExpressionType.DOUBLE)
-                                              .put("a", ExpressionType.STRING_ARRAY)
-                                              .put("a_", ExpressionType.STRING_ARRAY)
-                                              .put("b", ExpressionType.LONG_ARRAY)
-                                              .put("b_", ExpressionType.LONG_ARRAY)
-                                              .put("c", ExpressionType.DOUBLE_ARRAY)
-                                              .put("c_", ExpressionType.DOUBLE_ARRAY)
-                                              .build()
+                  .put("x_", ExpressionType.STRING)
+                  .put("y", ExpressionType.LONG)
+                  .put("y_", ExpressionType.LONG)
+                  .put("z", ExpressionType.DOUBLE)
+                  .put("z_", ExpressionType.DOUBLE)
+                  .put("a", ExpressionType.STRING_ARRAY)
+                  .put("a_", ExpressionType.STRING_ARRAY)
+                  .put("b", ExpressionType.LONG_ARRAY)
+                  .put("b_", ExpressionType.LONG_ARRAY)
+                  .put("c", ExpressionType.DOUBLE_ARRAY)
+                  .put("c_", ExpressionType.DOUBLE_ARRAY)
+                  .build()
   );
 
   @Rule
@@ -169,6 +169,11 @@ public class OutputTypeTest extends InitializedNullHandlingTest
     assertOutputType("hypot(y,y_)", inspector, ExpressionType.DOUBLE);
     assertOutputType("hypot(y,z_)", inspector, ExpressionType.DOUBLE);
     assertOutputType("hypot(z,z_)", inspector, ExpressionType.DOUBLE);
+
+    assertOutputType("safe_divide(y,y_)", inspector, ExpressionType.LONG);
+    assertOutputType("safe_divide(y,z_)", inspector, ExpressionType.DOUBLE);
+    assertOutputType("safe_divide(z,z_)", inspector, ExpressionType.DOUBLE);
+
   }
 
   @Test
@@ -436,19 +441,49 @@ public class OutputTypeTest extends InitializedNullHandlingTest
     Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.operator(ExpressionType.STRING, null));
     Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.operator(null, ExpressionType.STRING));
     // only long stays long
-    Assert.assertEquals(ExpressionType.LONG, ExpressionTypeConversion.operator(ExpressionType.LONG, ExpressionType.LONG));
+    Assert.assertEquals(
+        ExpressionType.LONG,
+        ExpressionTypeConversion.operator(ExpressionType.LONG, ExpressionType.LONG)
+    );
     // only string stays string
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.operator(ExpressionType.STRING, ExpressionType.STRING));
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.operator(ExpressionType.STRING, ExpressionType.STRING)
+    );
     // for operators, doubles is the catch all
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.operator(ExpressionType.LONG, ExpressionType.DOUBLE));
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.operator(ExpressionType.DOUBLE, ExpressionType.LONG));
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.operator(ExpressionType.DOUBLE, ExpressionType.DOUBLE));
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.operator(ExpressionType.DOUBLE, ExpressionType.STRING));
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.operator(ExpressionType.STRING, ExpressionType.DOUBLE));
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.operator(ExpressionType.STRING, ExpressionType.LONG));
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.operator(ExpressionType.LONG, ExpressionType.STRING));
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.operator(ExpressionType.LONG, ExpressionType.DOUBLE)
+    );
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.operator(ExpressionType.DOUBLE, ExpressionType.LONG)
+    );
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.operator(ExpressionType.DOUBLE, ExpressionType.DOUBLE)
+    );
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.operator(ExpressionType.DOUBLE, ExpressionType.STRING)
+    );
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.operator(ExpressionType.STRING, ExpressionType.DOUBLE)
+    );
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.operator(ExpressionType.STRING, ExpressionType.LONG)
+    );
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.operator(ExpressionType.LONG, ExpressionType.STRING)
+    );
     // unless it is an array, and those have to be the same
-    Assert.assertEquals(ExpressionType.LONG_ARRAY, ExpressionTypeConversion.operator(ExpressionType.LONG_ARRAY, ExpressionType.LONG_ARRAY));
+    Assert.assertEquals(
+        ExpressionType.LONG_ARRAY,
+        ExpressionTypeConversion.operator(ExpressionType.LONG_ARRAY, ExpressionType.LONG_ARRAY)
+    );
     Assert.assertEquals(
         ExpressionType.DOUBLE_ARRAY,
         ExpressionTypeConversion.operator(ExpressionType.DOUBLE_ARRAY, ExpressionType.DOUBLE_ARRAY)
@@ -470,19 +505,49 @@ public class OutputTypeTest extends InitializedNullHandlingTest
     Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.function(ExpressionType.STRING, null));
     Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.function(null, ExpressionType.STRING));
     // only long stays long
-    Assert.assertEquals(ExpressionType.LONG, ExpressionTypeConversion.function(ExpressionType.LONG, ExpressionType.LONG));
+    Assert.assertEquals(
+        ExpressionType.LONG,
+        ExpressionTypeConversion.function(ExpressionType.LONG, ExpressionType.LONG)
+    );
     // any double makes all doubles
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.function(ExpressionType.LONG, ExpressionType.DOUBLE));
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.function(ExpressionType.DOUBLE, ExpressionType.LONG));
-    Assert.assertEquals(ExpressionType.DOUBLE, ExpressionTypeConversion.function(ExpressionType.DOUBLE, ExpressionType.DOUBLE));
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.function(ExpressionType.LONG, ExpressionType.DOUBLE)
+    );
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.function(ExpressionType.DOUBLE, ExpressionType.LONG)
+    );
+    Assert.assertEquals(
+        ExpressionType.DOUBLE,
+        ExpressionTypeConversion.function(ExpressionType.DOUBLE, ExpressionType.DOUBLE)
+    );
     // any string makes become string
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.function(ExpressionType.LONG, ExpressionType.STRING));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.function(ExpressionType.STRING, ExpressionType.LONG));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.function(ExpressionType.DOUBLE, ExpressionType.STRING));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.function(ExpressionType.STRING, ExpressionType.DOUBLE));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.function(ExpressionType.STRING, ExpressionType.STRING));
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.function(ExpressionType.LONG, ExpressionType.STRING)
+    );
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.function(ExpressionType.STRING, ExpressionType.LONG)
+    );
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.function(ExpressionType.DOUBLE, ExpressionType.STRING)
+    );
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.function(ExpressionType.STRING, ExpressionType.DOUBLE)
+    );
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.function(ExpressionType.STRING, ExpressionType.STRING)
+    );
     // unless it is an array, and those have to be the same
-    Assert.assertEquals(ExpressionType.LONG_ARRAY, ExpressionTypeConversion.function(ExpressionType.LONG_ARRAY, ExpressionType.LONG_ARRAY));
+    Assert.assertEquals(
+        ExpressionType.LONG_ARRAY,
+        ExpressionTypeConversion.function(ExpressionType.LONG_ARRAY, ExpressionType.LONG_ARRAY)
+    );
     Assert.assertEquals(
         ExpressionType.DOUBLE_ARRAY,
         ExpressionTypeConversion.function(ExpressionType.DOUBLE_ARRAY, ExpressionType.DOUBLE_ARRAY)
@@ -501,21 +566,60 @@ public class OutputTypeTest extends InitializedNullHandlingTest
     Assert.assertEquals(ExpressionType.LONG, ExpressionTypeConversion.integerMathFunction(null, ExpressionType.LONG));
     Assert.assertEquals(ExpressionType.LONG, ExpressionTypeConversion.integerMathFunction(ExpressionType.DOUBLE, null));
     Assert.assertEquals(ExpressionType.LONG, ExpressionTypeConversion.integerMathFunction(null, ExpressionType.DOUBLE));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.integerMathFunction(ExpressionType.STRING, null));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.integerMathFunction(null, ExpressionType.STRING));
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.STRING, null)
+    );
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.integerMathFunction(null, ExpressionType.STRING)
+    );
     // all numbers are longs
-    Assert.assertEquals(ExpressionType.LONG, ExpressionTypeConversion.integerMathFunction(ExpressionType.LONG, ExpressionType.LONG));
-    Assert.assertEquals(ExpressionType.LONG, ExpressionTypeConversion.integerMathFunction(ExpressionType.LONG, ExpressionType.DOUBLE));
-    Assert.assertEquals(ExpressionType.LONG, ExpressionTypeConversion.integerMathFunction(ExpressionType.DOUBLE, ExpressionType.LONG));
-    Assert.assertEquals(ExpressionType.LONG, ExpressionTypeConversion.integerMathFunction(ExpressionType.DOUBLE, ExpressionType.DOUBLE));
+    Assert.assertEquals(
+        ExpressionType.LONG,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.LONG, ExpressionType.LONG)
+    );
+    Assert.assertEquals(
+        ExpressionType.LONG,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.LONG, ExpressionType.DOUBLE)
+    );
+    Assert.assertEquals(
+        ExpressionType.LONG,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.DOUBLE, ExpressionType.LONG)
+    );
+    Assert.assertEquals(
+        ExpressionType.LONG,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.DOUBLE, ExpressionType.DOUBLE)
+    );
     // any string makes become string
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.integerMathFunction(ExpressionType.LONG, ExpressionType.STRING));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.integerMathFunction(ExpressionType.STRING, ExpressionType.LONG));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.integerMathFunction(ExpressionType.DOUBLE, ExpressionType.STRING));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.integerMathFunction(ExpressionType.STRING, ExpressionType.DOUBLE));
-    Assert.assertEquals(ExpressionType.STRING, ExpressionTypeConversion.integerMathFunction(ExpressionType.STRING, ExpressionType.STRING));
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.LONG, ExpressionType.STRING)
+    );
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.STRING, ExpressionType.LONG)
+    );
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.DOUBLE, ExpressionType.STRING)
+    );
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.STRING, ExpressionType.DOUBLE)
+    );
+    Assert.assertEquals(
+        ExpressionType.STRING,
+        ExpressionTypeConversion.integerMathFunction(ExpressionType.STRING, ExpressionType.STRING)
+    );
     // unless it is an array
-    Assert.assertEquals(ExpressionType.LONG_ARRAY, ExpressionTypeConversion.integerMathFunction(ExpressionType.LONG_ARRAY, ExpressionType.LONG_ARRAY));
+    Assert.assertEquals(
+        ExpressionType.LONG_ARRAY,
+        ExpressionTypeConversion.integerMathFunction(
+            ExpressionType.LONG_ARRAY,
+            ExpressionType.LONG_ARRAY
+        )
+    );
     Assert.assertEquals(
         ExpressionType.DOUBLE_ARRAY,
         ExpressionTypeConversion.integerMathFunction(ExpressionType.DOUBLE_ARRAY, ExpressionType.DOUBLE_ARRAY)
diff --git a/docs/misc/math-expr.md b/docs/misc/math-expr.md
index 7f3b036..99e86bd 100644
--- a/docs/misc/math-expr.md
+++ b/docs/misc/math-expr.md
@@ -154,6 +154,7 @@ See javadoc of java.lang.Math for detailed explanation for each function.
 |remainder|remainder(x, y) returns the remainder operation on two arguments as prescribed by the IEEE 754 standard|
 |rint|rint(x) returns value that is closest in value to x and is equal to a mathematical integer|
 |round|round(x, y) returns the value of the x rounded to the y decimal places. While x can be an integer or floating-point number, y must be an integer. The type of the return value is specified by that of x. y defaults to 0 if omitted. When y is negative, x is rounded on the left side of the y decimal points. If x is `NaN`, x returns 0. If x is infinity, x will be converted to the nearest finite double. |
+|safe_divide|safe_divide(x,y) returns the division of x by y if y is not equal to 0. In case y is 0 it returns 0 or `null` if `druid.generic.useDefaultValueForNull=false` |
 |scalb|scalb(d, sf) returns d * 2^sf rounded as if performed by a single correctly rounded floating-point multiply to a member of the double value set|
 |signum|signum(x) returns the signum function of the argument x|
 |sin|sin(x) returns the trigonometric sine of an angle x|
diff --git a/docs/querying/sql.md b/docs/querying/sql.md
index cb1ecb5..92bf71b 100644
--- a/docs/querying/sql.md
+++ b/docs/querying/sql.md
@@ -414,9 +414,11 @@ to FLOAT. At runtime, Druid will widen 32-bit floats to 64-bit for most expressi
 |`BITWISE_SHIFT_LEFT(expr1, expr2)`|Returns the result of `expr1 << expr2`. Double values will be implicitly cast to longs, use `BITWISE_CONVERT_DOUBLE_TO_LONG_BITS` to perform bitwise operations directly with doubles|
 |`BITWISE_SHIFT_RIGHT(expr1, expr2)`|Returns the result of `expr1 >> expr2`. Double values will be implicitly cast to longs, use `BITWISE_CONVERT_DOUBLE_TO_LONG_BITS` to perform bitwise operations directly with doubles|
 |`BITWISE_XOR(expr1, expr2)`|Returns the result of `expr1 ^ expr2`. Double values will be implicitly cast to longs, use `BITWISE_CONVERT_DOUBLE_TO_LONG_BITS` to perform bitwise operations directly with doubles|
+|`DIV(x,y)`|Returns the result of integer division of x by y |
 |`HUMAN_READABLE_BINARY_BYTE_FORMAT(value[, precision])`| Format a number in human-readable [IEC](https://en.wikipedia.org/wiki/Binary_prefix) format. For example, HUMAN_READABLE_BINARY_BYTE_FORMAT(1048576) returns `1.00 MiB`. `precision` must be in the range of [0,3] (default: 2). |
 |`HUMAN_READABLE_DECIMAL_BYTE_FORMAT(value[, precision])`| Format a number in human-readable [SI](https://en.wikipedia.org/wiki/Binary_prefix) format. HUMAN_READABLE_DECIMAL_BYTE_FORMAT(1048576) returns `1.04 MB`. `precision` must be in the range of [0,3] (default: 2). `precision` must be in the range of [0,3] (default: 2). |
 |`HUMAN_READABLE_DECIMAL_FORMAT(value[, precision])`| Format a number in human-readable SI format. For example, HUMAN_READABLE_DECIMAL_FORMAT(1048576) returns `1.04 M`. `precision` must be in the range of [0,3] (default: 2). |
+|`SAFE_DIVIDE(x,y)`|Returns the division of x by y guarded on division by 0. In case y is 0 it returns 0, or `null` if `druid.generic.useDefaultValueForNull=false` |
 
 
 ### String functions
diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/SafeDivideOperatorConversion.java b/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/SafeDivideOperatorConversion.java
new file mode 100644
index 0000000..dd09feef
--- /dev/null
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/expression/builtin/SafeDivideOperatorConversion.java
@@ -0,0 +1,51 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.apache.druid.sql.calcite.expression.builtin;
+
+import org.apache.calcite.sql.SqlFunction;
+import org.apache.calcite.sql.SqlFunctionCategory;
+import org.apache.calcite.sql.SqlOperator;
+import org.apache.calcite.sql.type.OperandTypes;
+import org.apache.calcite.sql.type.ReturnTypes;
+import org.apache.druid.java.util.common.StringUtils;
+import org.apache.druid.math.expr.Function;
+import org.apache.druid.sql.calcite.expression.DirectOperatorConversion;
+import org.apache.druid.sql.calcite.expression.OperatorConversions;
+
+public class SafeDivideOperatorConversion extends DirectOperatorConversion
+{
+  private static final SqlFunction SQL_FUNCTION = OperatorConversions
+      .operatorBuilder(StringUtils.toUpperCase(Function.SafeDivide.NAME))
+      .operandTypeChecker(OperandTypes.ANY_NUMERIC)
+      .returnTypeInference(ReturnTypes.QUOTIENT_NULLABLE)
+      .functionCategory(SqlFunctionCategory.USER_DEFINED_FUNCTION)
+      .build();
+
+  public SafeDivideOperatorConversion()
+  {
+    super(SQL_FUNCTION, Function.SafeDivide.NAME);
+  }
+
+  @Override
+  public SqlOperator calciteOperator()
+  {
+    return SQL_FUNCTION;
+  }
+}
diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidOperatorTable.java b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidOperatorTable.java
index 118b6ef..41ed11c 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidOperatorTable.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/planner/DruidOperatorTable.java
@@ -96,6 +96,7 @@ import org.apache.druid.sql.calcite.expression.builtin.RepeatOperatorConversion;
 import org.apache.druid.sql.calcite.expression.builtin.ReverseOperatorConversion;
 import org.apache.druid.sql.calcite.expression.builtin.RightOperatorConversion;
 import org.apache.druid.sql.calcite.expression.builtin.RoundOperatorConversion;
+import org.apache.druid.sql.calcite.expression.builtin.SafeDivideOperatorConversion;
 import org.apache.druid.sql.calcite.expression.builtin.StringFormatOperatorConversion;
 import org.apache.druid.sql.calcite.expression.builtin.StringToArrayOperatorConversion;
 import org.apache.druid.sql.calcite.expression.builtin.StrposOperatorConversion;
@@ -260,6 +261,11 @@ public class DruidOperatorTable implements SqlOperatorTable
                    .add(HumanReadableFormatOperatorConversion.DECIMAL_FORMAT)
                    .build();
 
+  private static final List<SqlOperatorConversion> CUSTOM_MATH_OPERATOR_CONVERSIONS =
+      ImmutableList.<SqlOperatorConversion>builder()
+                   .add(new SafeDivideOperatorConversion())
+                   .build();
+
   private static final List<SqlOperatorConversion> BITWISE_OPERATOR_CONVERSIONS =
       ImmutableList.<SqlOperatorConversion>builder()
                    .add(OperatorConversions.druidBinaryLongFn("BITWISE_AND", "bitwiseAnd"))
@@ -354,6 +360,7 @@ public class DruidOperatorTable implements SqlOperatorTable
                    .addAll(IPV4ADDRESS_OPERATOR_CONVERSIONS)
                    .addAll(FORMAT_OPERATOR_CONVERSIONS)
                    .addAll(BITWISE_OPERATOR_CONVERSIONS)
+                   .addAll(CUSTOM_MATH_OPERATOR_CONVERSIONS)
                    .build();
 
   // Operators that have no conversion, but are handled in the convertlet table, so they still need to exist.
diff --git a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
index a632f0e..7dc1e85 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteQueryTest.java
@@ -235,7 +235,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                       InlineDataSource.fromIterable(
                           ImmutableList.of(
                               new Object[]{Long.MAX_VALUE, Long.MAX_VALUE, Long.MIN_VALUE, Long.MIN_VALUE, 0L}
-                              ),
+                          ),
                           RowSignature.builder()
                                       .add("EXPR$0", ColumnType.LONG)
                                       .add("EXPR$1", ColumnType.LONG)
@@ -252,7 +252,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                   .build()
         ),
         ImmutableList.of(
-            new Object[] {
+            new Object[]{
                 Long.MAX_VALUE,
                 Long.MAX_VALUE,
                 Long.MIN_VALUE,
@@ -288,7 +288,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @Test
   public void testSelectConstantExpressionEquivalentToNaN() throws Exception
   {
-    expectedException.expectMessage("'(log10(0) - log10(0))' evaluates to 'NaN' that is not supported in SQL. You can either cast the expression as bigint ('cast((log10(0) - log10(0)) as bigint)') or char ('cast((log10(0) - log10(0)) as char)') or change the expression itself");
+    expectedException.expectMessage(
+        "'(log10(0) - log10(0))' evaluates to 'NaN' that is not supported in SQL. You can either cast the expression as bigint ('cast((log10(0) - log10(0)) as bigint)') or char ('cast((log10(0) - log10(0)) as char)') or change the expression itself");
     testQuery(
         "SELECT log10(0) - log10(0), dim1 FROM foo LIMIT 1",
         ImmutableList.of(),
@@ -299,7 +300,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   @Test
   public void testSelectConstantExpressionEquivalentToInfinity() throws Exception
   {
-    expectedException.expectMessage("'log10(0)' evaluates to '-Infinity' that is not supported in SQL. You can either cast the expression as bigint ('cast(log10(0) as bigint)') or char ('cast(log10(0) as char)') or change the expression itself");
+    expectedException.expectMessage(
+        "'log10(0)' evaluates to '-Infinity' that is not supported in SQL. You can either cast the expression as bigint ('cast(log10(0) as bigint)') or char ('cast(log10(0) as char)') or change the expression itself");
     testQuery(
         "SELECT log10(0), dim1 FROM foo LIMIT 1",
         ImmutableList.of(),
@@ -447,8 +449,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         .setAggregatorSpecs(
                             useDefault
                             ? aggregators(
-                              new DoubleSumAggregatorFactory("a0:sum", "m2"),
-                              new CountAggregatorFactory("a0:count")
+                                new DoubleSumAggregatorFactory("a0:sum", "m2"),
+                                new CountAggregatorFactory("a0:count")
                             )
                             : aggregators(
                                 new DoubleSumAggregatorFactory("a0:sum", "m2"),
@@ -586,13 +588,13 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         .setDataSource(
                             join(
                                 new QueryDataSource(
-                                  newScanQueryBuilder()
-                                      .dataSource(CalciteTests.DATASOURCE1)
-                                      .intervals(querySegmentSpec(Filtration.eternity()))
-                                      .columns("dim2", "m1", "m2")
-                                      .context(QUERY_CONTEXT_DEFAULT)
-                                      .limit(10)
-                                      .build()
+                                    newScanQueryBuilder()
+                                        .dataSource(CalciteTests.DATASOURCE1)
+                                        .intervals(querySegmentSpec(Filtration.eternity()))
+                                        .columns("dim2", "m1", "m2")
+                                        .context(QUERY_CONTEXT_DEFAULT)
+                                        .limit(10)
+                                        .build()
                                 ),
                                 new QueryDataSource(
                                     newScanQueryBuilder()
@@ -734,7 +736,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                 new QueryDataSource(
                                     GroupByQuery.builder()
                                                 .setDataSource(CalciteTests.DATASOURCE1)
-                                                .setInterval(querySegmentSpec(Intervals.of("1994-04-29/2020-01-11T00:00:00.001Z")))
+                                                .setInterval(querySegmentSpec(Intervals.of(
+                                                    "1994-04-29/2020-01-11T00:00:00.001Z")))
                                                 .setVirtualColumns(
                                                     expressionVirtualColumn(
                                                         "v0",
@@ -744,7 +747,11 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                                 )
                                                 .setDimFilter(selector("dim3", "b", null))
                                                 .setGranularity(Granularities.ALL)
-                                                .setDimensions(dimensions(new DefaultDimensionSpec("v0", "d0", ColumnType.LONG)))
+                                                .setDimensions(dimensions(new DefaultDimensionSpec(
+                                                    "v0",
+                                                    "d0",
+                                                    ColumnType.LONG
+                                                )))
                                                 .setAggregatorSpecs(aggregators(
                                                     new FloatMinAggregatorFactory("a0", "m1")
                                                 ))
@@ -1008,6 +1015,55 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
     );
   }
 
+  @Test
+  public void testSafeDivideExpressions() throws Exception
+  {
+    List<Object[]> expected;
+    if (useDefault) {
+      expected = ImmutableList.of(
+          new Object[]{0.0F, 0L, 0.0, 7.0F},
+          new Object[]{1.0F, 1L, 1.0, 3253230.0F},
+          new Object[]{0.0F, 0L, 0.0, 0.0F},
+          new Object[]{0.0F, 0L, 0.0, 0.0F},
+          new Object[]{0.0F, 0L, 0.0, 0.0F},
+          new Object[]{0.0F, 0L, 0.0, 0.0F}
+      );
+    } else {
+      expected = ImmutableList.of(
+          new Object[]{null, null, null, 7.0F},
+          new Object[]{1.0F, 1L, 1.0, 3253230.0F},
+          new Object[]{0.0F, 0L, 0.0, 0.0F},
+          new Object[]{null, null, null, null},
+          new Object[]{null, null, null, null},
+          new Object[]{null, null, null, null}
+      );
+    }
+    testQuery(
+        "SELECT\n"
+        + "SAFE_DIVIDE(f1, f2),\n"
+        + "SAFE_DIVIDE(l1, l2),\n"
+        + "SAFE_DIVIDE(d2, d1),\n"
+        + "SAFE_DIVIDE(l1, f1)\n"
+        + "FROM numfoo",
+        ImmutableList.of(
+            Druids.newScanQueryBuilder()
+                  .dataSource(CalciteTests.DATASOURCE3)
+                  .intervals(querySegmentSpec(Filtration.eternity()))
+                  .columns("v0", "v1", "v2", "v3")
+                  .virtualColumns(
+                      expressionVirtualColumn("v0", "safe_divide(\"f1\",\"f2\")", ColumnType.FLOAT),
+                      expressionVirtualColumn("v1", "safe_divide(\"l1\",\"l2\")", ColumnType.LONG),
+                      expressionVirtualColumn("v2", "safe_divide(\"d2\",\"d1\")", ColumnType.DOUBLE),
+                      expressionVirtualColumn("v3", "safe_divide(\"l1\",\"f1\")", ColumnType.FLOAT)
+                  )
+                  .context(QUERY_CONTEXT_DEFAULT)
+                  .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
+                  .legacy(false)
+                  .build()
+        ),
+        expected
+    );
+  }
 
   @Test
   public void testExplainSelectConstantExpression() throws Exception
@@ -1019,7 +1075,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         "EXPLAIN PLAN FOR SELECT 1 + 1",
         ImmutableList.of(),
         ImmutableList.of(
-            new Object[]{"DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"inline\",\"columnNames\":[\"EXPR$0\"],\"columnTypes\":[\"LONG\"],\"rows\":[[2]]},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"virtualColumns\":[],\"resultFormat\":\"compactedList\",\"batchSize\":20480,\"order\":\"none\",\"filter\":null,\"columns\":[\"EXPR$0\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000, [...]
+            new Object[]{
+                "DruidQueryRel(query=[{\"queryType\":\"scan\",\"dataSource\":{\"type\":\"inline\",\"columnNames\":[\"EXPR$0\"],\"columnTypes\":[\"LONG\"],\"rows\":[[2]]},\"intervals\":{\"type\":\"intervals\",\"intervals\":[\"-146136543-09-08T08:23:32.096Z/146140482-04-24T15:36:27.903Z\"]},\"virtualColumns\":[],\"resultFormat\":\"compactedList\",\"batchSize\":20480,\"order\":\"none\",\"filter\":null,\"columns\":[\"EXPR$0\"],\"legacy\":false,\"context\":{\"defaultTimeout\":300000,\"maxScat [...]
+                "[]"
+            }
         )
     );
   }
@@ -1049,31 +1108,31 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         + "WHERE TABLE_TYPE IN ('SYSTEM_TABLE', 'TABLE', 'VIEW')",
         ImmutableList.of(),
         ImmutableList.<Object[]>builder()
-            .add(new Object[]{"druid", CalciteTests.BROADCAST_DATASOURCE, "TABLE", "YES", "YES"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE1, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE2, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE4, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE5, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE3, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.SOME_DATASOURCE, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.SOMEXDATASOURCE, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.USERVISITDATASOURCE, "TABLE", "NO", "NO"})
-            .add(new Object[]{"INFORMATION_SCHEMA", "COLUMNS", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"INFORMATION_SCHEMA", "SCHEMATA", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"INFORMATION_SCHEMA", "TABLES", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"lookup", "lookyloo", "TABLE", "YES", "YES"})
-            .add(new Object[]{"sys", "segments", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"sys", "server_segments", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"sys", "servers", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"sys", "supervisors", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"sys", "tasks", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"view", "aview", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "bview", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "cview", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "dview", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "invalidView", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "restrictedView", "VIEW", "NO", "NO"})
-            .build()
+                     .add(new Object[]{"druid", CalciteTests.BROADCAST_DATASOURCE, "TABLE", "YES", "YES"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE1, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE2, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE4, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE5, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE3, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.SOME_DATASOURCE, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.SOMEXDATASOURCE, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.USERVISITDATASOURCE, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"INFORMATION_SCHEMA", "COLUMNS", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"INFORMATION_SCHEMA", "SCHEMATA", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"INFORMATION_SCHEMA", "TABLES", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"lookup", "lookyloo", "TABLE", "YES", "YES"})
+                     .add(new Object[]{"sys", "segments", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"sys", "server_segments", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"sys", "servers", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"sys", "supervisors", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"sys", "tasks", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"view", "aview", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "bview", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "cview", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "dview", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "invalidView", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "restrictedView", "VIEW", "NO", "NO"})
+                     .build()
     );
 
     testQuery(
@@ -1084,33 +1143,33 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         CalciteTests.SUPER_USER_AUTH_RESULT,
         ImmutableList.of(),
         ImmutableList.<Object[]>builder()
-            .add(new Object[]{"druid", CalciteTests.BROADCAST_DATASOURCE, "TABLE", "YES", "YES"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE1, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE2, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE4, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.FORBIDDEN_DATASOURCE, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE5, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.DATASOURCE3, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.SOME_DATASOURCE, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.SOMEXDATASOURCE, "TABLE", "NO", "NO"})
-            .add(new Object[]{"druid", CalciteTests.USERVISITDATASOURCE, "TABLE", "NO", "NO"})
-            .add(new Object[]{"INFORMATION_SCHEMA", "COLUMNS", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"INFORMATION_SCHEMA", "SCHEMATA", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"INFORMATION_SCHEMA", "TABLES", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"lookup", "lookyloo", "TABLE", "YES", "YES"})
-            .add(new Object[]{"sys", "segments", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"sys", "server_segments", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"sys", "servers", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"sys", "supervisors", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"sys", "tasks", "SYSTEM_TABLE", "NO", "NO"})
-            .add(new Object[]{"view", "aview", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "bview", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "cview", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "dview", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "forbiddenView", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "invalidView", "VIEW", "NO", "NO"})
-            .add(new Object[]{"view", "restrictedView", "VIEW", "NO", "NO"})
-            .build()
+                     .add(new Object[]{"druid", CalciteTests.BROADCAST_DATASOURCE, "TABLE", "YES", "YES"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE1, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE2, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE4, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.FORBIDDEN_DATASOURCE, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE5, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.DATASOURCE3, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.SOME_DATASOURCE, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.SOMEXDATASOURCE, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"druid", CalciteTests.USERVISITDATASOURCE, "TABLE", "NO", "NO"})
+                     .add(new Object[]{"INFORMATION_SCHEMA", "COLUMNS", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"INFORMATION_SCHEMA", "SCHEMATA", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"INFORMATION_SCHEMA", "TABLES", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"lookup", "lookyloo", "TABLE", "YES", "YES"})
+                     .add(new Object[]{"sys", "segments", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"sys", "server_segments", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"sys", "servers", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"sys", "supervisors", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"sys", "tasks", "SYSTEM_TABLE", "NO", "NO"})
+                     .add(new Object[]{"view", "aview", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "bview", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "cview", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "dview", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "forbiddenView", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "invalidView", "VIEW", "NO", "NO"})
+                     .add(new Object[]{"view", "restrictedView", "VIEW", "NO", "NO"})
+                     .build()
     );
   }
 
@@ -1788,20 +1847,20 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                 .intervals(querySegmentSpec(Intervals.of("1990-01-01T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
                 .columns(
                     ImmutableList.<String>builder()
-                        .add("__time")
-                        .add("count")
-                        .add("dimHyperUnique")
-                        .add("dimMultivalEnumerated")
-                        .add("dimMultivalEnumerated2")
-                        .add("dimMultivalSequentialWithNulls")
-                        .add("dimSequential")
-                        .add("dimSequentialHalfNull")
-                        .add("dimUniform")
-                        .add("dimZipf")
-                        .add("metFloatNormal")
-                        .add("metFloatZipf")
-                        .add("metLongSequential")
-                        .build()
+                                 .add("__time")
+                                 .add("count")
+                                 .add("dimHyperUnique")
+                                 .add("dimMultivalEnumerated")
+                                 .add("dimMultivalEnumerated2")
+                                 .add("dimMultivalSequentialWithNulls")
+                                 .add("dimSequential")
+                                 .add("dimSequentialHalfNull")
+                                 .add("dimUniform")
+                                 .add("dimZipf")
+                                 .add("metFloatNormal")
+                                 .add("metFloatZipf")
+                                 .add("metLongSequential")
+                                 .build()
                 )
                 .limit(2)
                 .order(ScanQuery.Order.DESCENDING)
@@ -1856,21 +1915,21 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                 .intervals(querySegmentSpec(Intervals.of("1990-01-01T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
                 .columns(
                     ImmutableList.<String>builder()
-                        .add("__time")
-                        .add("count")
-                        .add("dimHyperUnique")
-                        .add("dimMultivalEnumerated")
-                        .add("dimMultivalEnumerated2")
-                        .add("dimMultivalSequentialWithNulls")
-                        .add("dimSequential")
-                        .add("dimSequentialHalfNull")
-                        .add("dimUniform")
-                        .add("dimZipf")
-                        .add("metFloatNormal")
-                        .add("metFloatZipf")
-                        .add("metLongSequential")
-                        .add("metLongUniform")
-                        .build()
+                                 .add("__time")
+                                 .add("count")
+                                 .add("dimHyperUnique")
+                                 .add("dimMultivalEnumerated")
+                                 .add("dimMultivalEnumerated2")
+                                 .add("dimMultivalSequentialWithNulls")
+                                 .add("dimSequential")
+                                 .add("dimSequentialHalfNull")
+                                 .add("dimUniform")
+                                 .add("dimZipf")
+                                 .add("metFloatNormal")
+                                 .add("metFloatZipf")
+                                 .add("metLongSequential")
+                                 .add("metLongUniform")
+                                 .build()
                 )
                 .limit(2)
                 .order(ScanQuery.Order.DESCENDING)
@@ -2352,7 +2411,9 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                   .context(QUERY_CONTEXT_DEFAULT)
                   .build()
         ),
-        NullHandling.sqlCompatible() ? ImmutableList.of(new Object[]{1L, 1.0f, 1.0, "", 2L, 2.0f, "1"}) : ImmutableList.of(new Object[]{1L, 1.0f, 1.0, "", 2L, 2.0f, "1"})
+        NullHandling.sqlCompatible()
+        ? ImmutableList.of(new Object[]{1L, 1.0f, 1.0, "", 2L, 2.0f, "1"})
+        : ImmutableList.of(new Object[]{1L, 1.0f, 1.0, "", 2L, 2.0f, "1"})
     );
   }
 
@@ -2393,19 +2454,19 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         "SELECT ANY_VALUE(l1), ANY_VALUE(d1), ANY_VALUE(f1) FROM druid.numfoo GROUP BY dim2",
         ImmutableList.of(
             GroupByQuery.builder()
-                  .setDataSource(CalciteTests.DATASOURCE3)
-                  .setInterval(querySegmentSpec(Filtration.eternity()))
-                  .setGranularity(Granularities.ALL)
-                  .setDimensions(dimensions(new DefaultDimensionSpec("dim2", "_d0")))
-                  .setAggregatorSpecs(
-                      aggregators(
-                          new LongAnyAggregatorFactory("a0", "l1"),
-                          new DoubleAnyAggregatorFactory("a1", "d1"),
-                          new FloatAnyAggregatorFactory("a2", "f1")
-                      )
-                  )
-                  .setContext(QUERY_CONTEXT_DEFAULT)
-                  .build()
+                        .setDataSource(CalciteTests.DATASOURCE3)
+                        .setInterval(querySegmentSpec(Filtration.eternity()))
+                        .setGranularity(Granularities.ALL)
+                        .setDimensions(dimensions(new DefaultDimensionSpec("dim2", "_d0")))
+                        .setAggregatorSpecs(
+                            aggregators(
+                                new LongAnyAggregatorFactory("a0", "l1"),
+                                new DoubleAnyAggregatorFactory("a1", "d1"),
+                                new FloatAnyAggregatorFactory("a2", "f1")
+                            )
+                        )
+                        .setContext(QUERY_CONTEXT_DEFAULT)
+                        .build()
         ),
 
         NullHandling.sqlCompatible()
@@ -2441,9 +2502,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                         .setGranularity(Granularities.ALL)
                                         .setDimensions(dimensions(new DefaultDimensionSpec("dim2", "d0")))
                                         .setAggregatorSpecs(aggregators(
-                                            new FloatLastAggregatorFactory("a0:a", "m1"),
-                                            new LongLastAggregatorFactory("a1:a", "cnt"),
-                                            new DoubleLastAggregatorFactory("a2:a", "m2"))
+                                                                new FloatLastAggregatorFactory("a0:a", "m1"),
+                                                                new LongLastAggregatorFactory("a1:a", "cnt"),
+                                                                new DoubleLastAggregatorFactory("a2:a", "m2")
+                                                            )
                                         )
                                         .setPostAggregatorSpecs(
                                             ImmutableList.of(
@@ -2459,15 +2521,17 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         .setInterval(querySegmentSpec(Filtration.eternity()))
                         .setGranularity(Granularities.ALL)
                         .setAggregatorSpecs(aggregators(
-                            new DoubleSumAggregatorFactory("_a0", "a0"),
-                            new LongSumAggregatorFactory("_a1", "a1"),
-                            new DoubleSumAggregatorFactory("_a2", "a2")
+                                                new DoubleSumAggregatorFactory("_a0", "a0"),
+                                                new LongSumAggregatorFactory("_a1", "a1"),
+                                                new DoubleSumAggregatorFactory("_a2", "a2")
                                             )
                         )
                         .setContext(QUERY_CONTEXT_DEFAULT)
                         .build()
         ),
-        NullHandling.sqlCompatible() ? ImmutableList.of(new Object[]{18.0, 4L, 18.0}) : ImmutableList.of(new Object[]{15.0, 3L, 15.0})
+        NullHandling.sqlCompatible()
+        ? ImmutableList.of(new Object[]{18.0, 4L, 18.0})
+        : ImmutableList.of(new Object[]{15.0, 3L, 15.0})
     );
   }
 
@@ -2489,9 +2553,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                         .setGranularity(Granularities.ALL)
                                         .setDimensions(dimensions(new DefaultDimensionSpec("dim2", "d0")))
                                         .setAggregatorSpecs(aggregators(
-                                            new FloatFirstAggregatorFactory("a0:a", "m1"),
-                                            new LongFirstAggregatorFactory("a1:a", "cnt"),
-                                            new DoubleFirstAggregatorFactory("a2:a", "m2"))
+                                                                new FloatFirstAggregatorFactory("a0:a", "m1"),
+                                                                new LongFirstAggregatorFactory("a1:a", "cnt"),
+                                                                new DoubleFirstAggregatorFactory("a2:a", "m2")
+                                                            )
                                         )
                                         .setPostAggregatorSpecs(
                                             ImmutableList.of(
@@ -2507,15 +2572,17 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         .setInterval(querySegmentSpec(Filtration.eternity()))
                         .setGranularity(Granularities.ALL)
                         .setAggregatorSpecs(aggregators(
-                            new DoubleSumAggregatorFactory("_a0", "a0"),
-                            new LongSumAggregatorFactory("_a1", "a1"),
-                            new DoubleSumAggregatorFactory("_a2", "a2")
+                                                new DoubleSumAggregatorFactory("_a0", "a0"),
+                                                new LongSumAggregatorFactory("_a1", "a1"),
+                                                new DoubleSumAggregatorFactory("_a2", "a2")
                                             )
                         )
                         .setContext(QUERY_CONTEXT_DEFAULT)
                         .build()
         ),
-        NullHandling.sqlCompatible() ? ImmutableList.of(new Object[]{11.0, 4L, 11.0}) : ImmutableList.of(new Object[]{8.0, 3L, 8.0})
+        NullHandling.sqlCompatible()
+        ? ImmutableList.of(new Object[]{11.0, 4L, 11.0})
+        : ImmutableList.of(new Object[]{8.0, 3L, 8.0})
     );
   }
 
@@ -2536,7 +2603,11 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                         .setInterval(querySegmentSpec(Filtration.eternity()))
                                         .setGranularity(Granularities.ALL)
                                         .setDimensions(dimensions(new DefaultDimensionSpec("dim2", "d0")))
-                                        .setAggregatorSpecs(aggregators(new StringLastAggregatorFactory("a0:a", "dim1", 10)))
+                                        .setAggregatorSpecs(aggregators(new StringLastAggregatorFactory(
+                                            "a0:a",
+                                            "dim1",
+                                            10
+                                        )))
                                         .setPostAggregatorSpecs(
                                             ImmutableList.of(
                                                 new FinalizingFieldAccessPostAggregator("a0", "a0:a")
@@ -2547,7 +2618,12 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         )
                         .setInterval(querySegmentSpec(Filtration.eternity()))
                         .setGranularity(Granularities.ALL)
-                        .setAggregatorSpecs(aggregators(new DoubleSumAggregatorFactory("_a0", null, "CAST(\"a0\", 'DOUBLE')", ExprMacroTable.nil())))
+                        .setAggregatorSpecs(aggregators(new DoubleSumAggregatorFactory(
+                            "_a0",
+                            null,
+                            "CAST(\"a0\", 'DOUBLE')",
+                            ExprMacroTable.nil()
+                        )))
                         .setContext(QUERY_CONTEXT_DEFAULT)
                         .build()
         ),
@@ -2574,7 +2650,11 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                         .setInterval(querySegmentSpec(Filtration.eternity()))
                                         .setGranularity(Granularities.ALL)
                                         .setDimensions(dimensions(new DefaultDimensionSpec("dim2", "d0")))
-                                        .setAggregatorSpecs(aggregators(new StringFirstAggregatorFactory("a0:a", "dim1", 10)))
+                                        .setAggregatorSpecs(aggregators(new StringFirstAggregatorFactory(
+                                            "a0:a",
+                                            "dim1",
+                                            10
+                                        )))
                                         .setPostAggregatorSpecs(
                                             ImmutableList.of(
                                                 new FinalizingFieldAccessPostAggregator("a0", "a0:a")
@@ -2585,7 +2665,12 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         )
                         .setInterval(querySegmentSpec(Filtration.eternity()))
                         .setGranularity(Granularities.ALL)
-                        .setAggregatorSpecs(aggregators(new DoubleSumAggregatorFactory("_a0", null, "CAST(\"a0\", 'DOUBLE')", ExprMacroTable.nil())))
+                        .setAggregatorSpecs(aggregators(new DoubleSumAggregatorFactory(
+                            "_a0",
+                            null,
+                            "CAST(\"a0\", 'DOUBLE')",
+                            ExprMacroTable.nil()
+                        )))
                         .setContext(QUERY_CONTEXT_DEFAULT)
                         .build()
         ),
@@ -2625,9 +2710,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                         .setGranularity(Granularities.ALL)
                                         .setDimensions(dimensions(new DefaultDimensionSpec("dim2", "d0")))
                                         .setAggregatorSpecs(aggregators(
-                                            new FloatAnyAggregatorFactory("a0:a", "m1"),
-                                            new LongAnyAggregatorFactory("a1:a", "cnt"),
-                                            new DoubleAnyAggregatorFactory("a2:a", "m2"))
+                                                                new FloatAnyAggregatorFactory("a0:a", "m1"),
+                                                                new LongAnyAggregatorFactory("a1:a", "cnt"),
+                                                                new DoubleAnyAggregatorFactory("a2:a", "m2")
+                                                            )
                                         )
                                         .setPostAggregatorSpecs(
                                             ImmutableList.of(
@@ -2643,15 +2729,17 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         .setInterval(querySegmentSpec(Filtration.eternity()))
                         .setGranularity(Granularities.ALL)
                         .setAggregatorSpecs(aggregators(
-                            new DoubleSumAggregatorFactory("_a0", "a0"),
-                            new LongSumAggregatorFactory("_a1", "a1"),
-                            new DoubleSumAggregatorFactory("_a2", "a2")
-                            )
+                                                new DoubleSumAggregatorFactory("_a0", "a0"),
+                                                new LongSumAggregatorFactory("_a1", "a1"),
+                                                new DoubleSumAggregatorFactory("_a2", "a2")
+                                            )
                         )
                         .setContext(QUERY_CONTEXT_DEFAULT)
                         .build()
         ),
-        NullHandling.sqlCompatible() ? ImmutableList.of(new Object[]{11.0, 4L, 11.0}) : ImmutableList.of(new Object[]{8.0, 3L, 8.0})
+        NullHandling.sqlCompatible()
+        ? ImmutableList.of(new Object[]{11.0, 4L, 11.0})
+        : ImmutableList.of(new Object[]{8.0, 3L, 8.0})
     );
   }
 
@@ -2669,7 +2757,11 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                         .setInterval(querySegmentSpec(Filtration.eternity()))
                                         .setGranularity(Granularities.ALL)
                                         .setDimensions(dimensions(new DefaultDimensionSpec("dim2", "d0")))
-                                        .setAggregatorSpecs(aggregators(new StringAnyAggregatorFactory("a0:a", "dim1", 10)))
+                                        .setAggregatorSpecs(aggregators(new StringAnyAggregatorFactory(
+                                            "a0:a",
+                                            "dim1",
+                                            10
+                                        )))
                                         .setPostAggregatorSpecs(
                                             ImmutableList.of(
                                                 new FinalizingFieldAccessPostAggregator("a0", "a0:a")
@@ -2680,7 +2772,12 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         )
                         .setInterval(querySegmentSpec(Filtration.eternity()))
                         .setGranularity(Granularities.ALL)
-                        .setAggregatorSpecs(aggregators(new DoubleSumAggregatorFactory("_a0", null, "CAST(\"a0\", 'DOUBLE')", ExprMacroTable.nil())))
+                        .setAggregatorSpecs(aggregators(new DoubleSumAggregatorFactory(
+                            "_a0",
+                            null,
+                            "CAST(\"a0\", 'DOUBLE')",
+                            ExprMacroTable.nil()
+                        )))
                         .setContext(QUERY_CONTEXT_DEFAULT)
                         .build()
         ),
@@ -2743,7 +2840,11 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                   .build()
         ),
         ImmutableList.of(
-            new Object[]{NullHandling.defaultLongValue(), NullHandling.defaultDoubleValue(), NullHandling.defaultFloatValue()}
+            new Object[]{
+                NullHandling.defaultLongValue(),
+                NullHandling.defaultDoubleValue(),
+                NullHandling.defaultFloatValue()
+            }
         )
     );
   }
@@ -2909,19 +3010,19 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         "SELECT dim1, EARLIEST(f1) FROM druid.numfoo GROUP BY 1 ORDER BY 2 LIMIT 10",
         ImmutableList.of(
             new TopNQueryBuilder()
-                  .dataSource(CalciteTests.DATASOURCE3)
-                  .intervals(querySegmentSpec(Filtration.eternity()))
-                  .granularity(Granularities.ALL)
-                  .dimension(new DefaultDimensionSpec("dim1", "_d0"))
-                  .aggregators(
-                      aggregators(
-                          new FloatFirstAggregatorFactory("a0", "f1")
-                      )
-                  )
-                  .metric(new InvertedTopNMetricSpec(new NumericTopNMetricSpec("a0")))
-                  .threshold(10)
-                  .context(QUERY_CONTEXT_DEFAULT)
-                  .build()
+                .dataSource(CalciteTests.DATASOURCE3)
+                .intervals(querySegmentSpec(Filtration.eternity()))
+                .granularity(Granularities.ALL)
+                .dimension(new DefaultDimensionSpec("dim1", "_d0"))
+                .aggregators(
+                    aggregators(
+                        new FloatFirstAggregatorFactory("a0", "f1")
+                    )
+                )
+                .metric(new InvertedTopNMetricSpec(new NumericTopNMetricSpec("a0")))
+                .threshold(10)
+                .context(QUERY_CONTEXT_DEFAULT)
+                .build()
         ),
         expected
     );
@@ -4503,12 +4604,12 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
             Druids.newTimeseriesQueryBuilder()
                   .dataSource(
                       join(
-                      new TableDataSource(CalciteTests.DATASOURCE1),
-                      new LookupDataSource("lookyloo"),
-                      "j0.",
-                      equalsCondition(DruidExpression.fromColumn("dim1"), DruidExpression.fromColumn("j0.k")),
-                      JoinType.INNER
-                  ))
+                          new TableDataSource(CalciteTests.DATASOURCE1),
+                          new LookupDataSource("lookyloo"),
+                          "j0.",
+                          equalsCondition(DruidExpression.fromColumn("dim1"), DruidExpression.fromColumn("j0.k")),
+                          JoinType.INNER
+                      ))
                   .intervals(querySegmentSpec(Filtration.eternity()))
                   .granularity(Granularities.ALL)
                   .aggregators(aggregators(new CountAggregatorFactory("a0")))
@@ -5061,35 +5162,39 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   public void testLongPredicateIsNull() throws Exception
   {
     testQuery(
-          "SELECT l1 is null FROM druid.numfoo",
-          ImmutableList.of(
+        "SELECT l1 is null FROM druid.numfoo",
+        ImmutableList.of(
             newScanQueryBuilder()
-            .dataSource(CalciteTests.DATASOURCE3)
-            .intervals(querySegmentSpec(Filtration.eternity()))
-            .columns("v0")
-            .virtualColumns(
-            expressionVirtualColumn("v0", NullHandling.replaceWithDefault() ? "0" : "isnull(\"l1\")", ColumnType.LONG)
-        )
-          .context(QUERY_CONTEXT_DEFAULT)
-          .build()
-        ),
-              NullHandling.replaceWithDefault() ?
-                      ImmutableList.of(
-                              new Object[]{false},
-                              new Object[]{false},
-                              new Object[]{false},
-                              new Object[]{false},
-                              new Object[]{false},
-                              new Object[]{false}
-                      ) :
-                      ImmutableList.of(
-                              new Object[]{false},
-                              new Object[]{false},
-                              new Object[]{false},
-                              new Object[]{true},
-                              new Object[]{true},
-                              new Object[]{true}
-                      )
+                .dataSource(CalciteTests.DATASOURCE3)
+                .intervals(querySegmentSpec(Filtration.eternity()))
+                .columns("v0")
+                .virtualColumns(
+                    expressionVirtualColumn(
+                        "v0",
+                        NullHandling.replaceWithDefault() ? "0" : "isnull(\"l1\")",
+                        ColumnType.LONG
+                    )
+                )
+                .context(QUERY_CONTEXT_DEFAULT)
+                .build()
+        ),
+        NullHandling.replaceWithDefault() ?
+        ImmutableList.of(
+            new Object[]{false},
+            new Object[]{false},
+            new Object[]{false},
+            new Object[]{false},
+            new Object[]{false},
+            new Object[]{false}
+        ) :
+        ImmutableList.of(
+            new Object[]{false},
+            new Object[]{false},
+            new Object[]{false},
+            new Object[]{true},
+            new Object[]{true},
+            new Object[]{true}
+        )
     );
   }
 
@@ -5886,31 +5991,31 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
             Druids.newTimeseriesQueryBuilder()
                   .dataSource(
                       join(
-                        join(
-                            new TableDataSource(CalciteTests.DATASOURCE1),
-                            new QueryDataSource(
-                                newScanQueryBuilder().dataSource(CalciteTests.DATASOURCE3)
-                                                     .intervals(querySegmentSpec(Filtration.eternity()))
-                                                     .columns("dim2")
-                                                     .context(queryContext)
-                                                     .build()
-                            ),
-                            "j0.",
-                            "(\"dim2\" == \"j0.dim2\")",
-                            JoinType.INNER,
-                            bound("dim2", "a", "a", false, false, null, null)
-                        ),
-                        new QueryDataSource(
-                            newScanQueryBuilder().dataSource(CalciteTests.DATASOURCE1)
-                                                 .intervals(querySegmentSpec(Filtration.eternity()))
-                                                 .columns("dim2")
-                                                 .context(queryContext)
-                                                 .build()
-                        ),
-                        "_j0.",
-                        "('a' == \"_j0.dim2\")",
-                        JoinType.INNER
-                    )
+                          join(
+                              new TableDataSource(CalciteTests.DATASOURCE1),
+                              new QueryDataSource(
+                                  newScanQueryBuilder().dataSource(CalciteTests.DATASOURCE3)
+                                                       .intervals(querySegmentSpec(Filtration.eternity()))
+                                                       .columns("dim2")
+                                                       .context(queryContext)
+                                                       .build()
+                              ),
+                              "j0.",
+                              "(\"dim2\" == \"j0.dim2\")",
+                              JoinType.INNER,
+                              bound("dim2", "a", "a", false, false, null, null)
+                          ),
+                          new QueryDataSource(
+                              newScanQueryBuilder().dataSource(CalciteTests.DATASOURCE1)
+                                                   .intervals(querySegmentSpec(Filtration.eternity()))
+                                                   .columns("dim2")
+                                                   .context(queryContext)
+                                                   .build()
+                          ),
+                          "_j0.",
+                          "('a' == \"_j0.dim2\")",
+                          JoinType.INNER
+                      )
                   )
                   .intervals(querySegmentSpec(Filtration.eternity()))
                   .filters(not(selector("dim1", "z", new SubstringDimExtractionFn(0, 1))))
@@ -6155,16 +6260,16 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         "SELECT  MIN(l1), MIN(cnt), MAX(l1) FROM druid.numfoo",
         ImmutableList.of(
             Druids.newTimeseriesQueryBuilder()
-                .dataSource(CalciteTests.DATASOURCE3)
-                .intervals(querySegmentSpec(Filtration.eternity()))
-                .granularity(Granularities.ALL)
-                .aggregators(aggregators(
-                                new LongMinAggregatorFactory("a0", "l1"),
-                                new LongMinAggregatorFactory("a1", "cnt"),
-                                new LongMaxAggregatorFactory("a2", "l1")
-                            ))
-                .context(QUERY_CONTEXT_DEFAULT)
-                .build()
+                  .dataSource(CalciteTests.DATASOURCE3)
+                  .intervals(querySegmentSpec(Filtration.eternity()))
+                  .granularity(Granularities.ALL)
+                  .aggregators(aggregators(
+                      new LongMinAggregatorFactory("a0", "l1"),
+                      new LongMinAggregatorFactory("a1", "cnt"),
+                      new LongMaxAggregatorFactory("a2", "l1")
+                  ))
+                  .context(QUERY_CONTEXT_DEFAULT)
+                  .build()
         ),
         ImmutableList.of(
             new Object[]{0L, 1L, 325323L}
@@ -8073,7 +8178,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
   {
     requireMergeBuffers(4);
     testQuery(
-        PLANNER_CONFIG_NO_HLL.withOverrides(ImmutableMap.of(PlannerConfig.CTX_KEY_USE_GROUPING_SET_FOR_EXACT_DISTINCT, "true")),
+        PLANNER_CONFIG_NO_HLL.withOverrides(ImmutableMap.of(
+            PlannerConfig.CTX_KEY_USE_GROUPING_SET_FOR_EXACT_DISTINCT,
+            "true"
+        )),
         "SELECT FLOOR(__time to day), COUNT(distinct city), COUNT(distinct user) FROM druid.visits GROUP BY 1",
         CalciteTests.REGULAR_USER_AUTH_RESULT,
         ImmutableList.of(
@@ -8550,12 +8658,12 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         .setAggregatorSpecs(
                             useDefault
                             ? aggregators(
-                              new LongMaxAggregatorFactory("_a0", "a0"),
-                              new LongMinAggregatorFactory("_a1", "a0"),
-                              new LongSumAggregatorFactory("_a2:sum", "a0"),
-                              new CountAggregatorFactory("_a2:count"),
-                              new LongMaxAggregatorFactory("_a3", "d0"),
-                              new CountAggregatorFactory("_a4")
+                                new LongMaxAggregatorFactory("_a0", "a0"),
+                                new LongMinAggregatorFactory("_a1", "a0"),
+                                new LongSumAggregatorFactory("_a2:sum", "a0"),
+                                new CountAggregatorFactory("_a2:count"),
+                                new LongMaxAggregatorFactory("_a3", "d0"),
+                                new CountAggregatorFactory("_a4")
                             )
                             : aggregators(
                                 new LongMaxAggregatorFactory("_a0", "a0"),
@@ -8634,8 +8742,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         .setAggregatorSpecs(
                             useDefault
                             ? aggregators(
-                              new LongSumAggregatorFactory("_a0:sum", "a0"),
-                              new CountAggregatorFactory("_a0:count")
+                                new LongSumAggregatorFactory("_a0:sum", "a0"),
+                                new CountAggregatorFactory("_a0:count")
                             )
                             : aggregators(
                                 new LongSumAggregatorFactory("_a0:sum", "a0"),
@@ -10327,7 +10435,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testFilterAndGroupByLookupUsingJoinOperatorWithValueFilterPushdownMatchesNothig(Map<String, Object> queryContext) throws Exception
+  public void testFilterAndGroupByLookupUsingJoinOperatorWithValueFilterPushdownMatchesNothig(Map<String, Object> queryContext)
+      throws Exception
   {
     // Cannot vectorize JOIN operator.
     cannotVectorize();
@@ -10450,7 +10559,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testFilterAndGroupByLookupUsingJoinOperatorWithNotFilter(Map<String, Object> queryContext) throws Exception
+  public void testFilterAndGroupByLookupUsingJoinOperatorWithNotFilter(Map<String, Object> queryContext)
+      throws Exception
   {
     // Cannot vectorize JOIN operator.
     cannotVectorize();
@@ -10573,7 +10683,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testFilterAndGroupByLookupUsingPostAggregationJoinOperator(Map<String, Object> queryContext) throws Exception
+  public void testFilterAndGroupByLookupUsingPostAggregationJoinOperator(Map<String, Object> queryContext)
+      throws Exception
   {
     testQuery(
         "SELECT base.dim2, lookyloo.v, base.cnt FROM (\n"
@@ -10818,7 +10929,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testInnerJoinTableLookupLookupWithFilterWithOuterLimitWithAllColumns(Map<String, Object> queryContext) throws Exception
+  public void testInnerJoinTableLookupLookupWithFilterWithOuterLimitWithAllColumns(Map<String, Object> queryContext)
+      throws Exception
   {
     testQuery(
         "SELECT __time, cnt, dim1, dim2, dim3, m1, m2, unique_dim1\n"
@@ -10861,7 +10973,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testInnerJoinTableLookupLookupWithFilterWithoutLimitWithAllColumns(Map<String, Object> queryContext) throws Exception
+  public void testInnerJoinTableLookupLookupWithFilterWithoutLimitWithAllColumns(Map<String, Object> queryContext)
+      throws Exception
   {
     testQuery(
         "SELECT __time, cnt, dim1, dim2, dim3, m1, m2, unique_dim1\n"
@@ -10950,100 +11063,169 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                                                                     join(
                                                                                         join(
                                                                                             join(
-                                                                                                new TableDataSource(CalciteTests.DATASOURCE1),
-                                                                                                new LookupDataSource("lookyloo"),
+                                                                                                new TableDataSource(
+                                                                                                    CalciteTests.DATASOURCE1),
+                                                                                                new LookupDataSource(
+                                                                                                    "lookyloo"),
                                                                                                 "j0.",
-                                                                                                equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("j0.k")),
-                                                                                                JoinType.INNER
+                                                                                                equalsCondition(
+                                                                                                    DruidExpression.fromColumn(
+                                                                                                        "dim2"),
+                                                                                                    DruidExpression.fromColumn(
+                                                                                                        "j0.k")
                                                                                                 ),
-                                                                                            new LookupDataSource("lookyloo"),
+                                                                                                JoinType.INNER
+                                                                                            ),
+                                                                                            new LookupDataSource(
+                                                                                                "lookyloo"),
                                                                                             "_j0.",
-                                                                                            equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("_j0.k")),
+                                                                                            equalsCondition(
+                                                                                                DruidExpression.fromColumn(
+                                                                                                    "dim2"),
+                                                                                                DruidExpression.fromColumn(
+                                                                                                    "_j0.k")
+                                                                                            ),
                                                                                             JoinType.INNER
                                                                                         ),
                                                                                         new LookupDataSource("lookyloo"),
                                                                                         "__j0.",
-                                                                                        equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("__j0.k")),
+                                                                                        equalsCondition(
+                                                                                            DruidExpression.fromColumn(
+                                                                                                "dim2"),
+                                                                                            DruidExpression.fromColumn(
+                                                                                                "__j0.k")
+                                                                                        ),
                                                                                         JoinType.INNER
                                                                                     ),
                                                                                     new LookupDataSource("lookyloo"),
                                                                                     "___j0.",
-                                                                                    equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("___j0.k")),
+                                                                                    equalsCondition(
+                                                                                        DruidExpression.fromColumn(
+                                                                                            "dim2"),
+                                                                                        DruidExpression.fromColumn(
+                                                                                            "___j0.k")
+                                                                                    ),
                                                                                     JoinType.INNER
                                                                                 ),
                                                                                 new LookupDataSource("lookyloo"),
                                                                                 "____j0.",
-                                                                                equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("____j0.k")),
+                                                                                equalsCondition(
+                                                                                    DruidExpression.fromColumn("dim2"),
+                                                                                    DruidExpression.fromColumn(
+                                                                                        "____j0.k")
+                                                                                ),
                                                                                 JoinType.INNER
                                                                             ),
                                                                             new LookupDataSource("lookyloo"),
                                                                             "_____j0.",
-                                                                            equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("_____j0.k")),
+                                                                            equalsCondition(
+                                                                                DruidExpression.fromColumn("dim2"),
+                                                                                DruidExpression.fromColumn("_____j0.k")
+                                                                            ),
                                                                             JoinType.INNER
                                                                         ),
                                                                         new LookupDataSource("lookyloo"),
                                                                         "______j0.",
-                                                                        equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("______j0.k")),
+                                                                        equalsCondition(
+                                                                            DruidExpression.fromColumn("dim2"),
+                                                                            DruidExpression.fromColumn("______j0.k")
+                                                                        ),
                                                                         JoinType.INNER
                                                                     ),
                                                                     new LookupDataSource("lookyloo"),
                                                                     "_______j0.",
-                                                                    equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("_______j0.k")),
+                                                                    equalsCondition(
+                                                                        DruidExpression.fromColumn("dim2"),
+                                                                        DruidExpression.fromColumn("_______j0.k")
+                                                                    ),
                                                                     JoinType.INNER
                                                                 ),
                                                                 new LookupDataSource("lookyloo"),
                                                                 "________j0.",
-                                                                equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("________j0.k")),
+                                                                equalsCondition(
+                                                                    DruidExpression.fromColumn("dim2"),
+                                                                    DruidExpression.fromColumn("________j0.k")
+                                                                ),
                                                                 JoinType.INNER
                                                             ),
                                                             new LookupDataSource("lookyloo"),
                                                             "_________j0.",
-                                                            equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("_________j0.k")),
+                                                            equalsCondition(
+                                                                DruidExpression.fromColumn("dim2"),
+                                                                DruidExpression.fromColumn("_________j0.k")
+                                                            ),
                                                             JoinType.INNER
                                                         ),
                                                         new LookupDataSource("lookyloo"),
                                                         "__________j0.",
-                                                        equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("__________j0.k")),
+                                                        equalsCondition(
+                                                            DruidExpression.fromColumn("dim2"),
+                                                            DruidExpression.fromColumn("__________j0.k")
+                                                        ),
                                                         JoinType.INNER
                                                     ),
                                                     new LookupDataSource("lookyloo"),
                                                     "___________j0.",
-                                                    equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("___________j0.k")),
+                                                    equalsCondition(
+                                                        DruidExpression.fromColumn("dim2"),
+                                                        DruidExpression.fromColumn("___________j0.k")
+                                                    ),
                                                     JoinType.INNER
                                                 ),
                                                 new LookupDataSource("lookyloo"),
                                                 "____________j0.",
-                                                equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("____________j0.k")),
+                                                equalsCondition(
+                                                    DruidExpression.fromColumn("dim2"),
+                                                    DruidExpression.fromColumn("____________j0.k")
+                                                ),
                                                 JoinType.INNER
                                             ),
                                             new LookupDataSource("lookyloo"),
                                             "_____________j0.",
-                                            equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("_____________j0.k")),
+                                            equalsCondition(
+                                                DruidExpression.fromColumn("dim2"),
+                                                DruidExpression.fromColumn("_____________j0.k")
+                                            ),
                                             JoinType.INNER
                                         ),
                                         new LookupDataSource("lookyloo"),
                                         "______________j0.",
-                                        equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("______________j0.k")),
+                                        equalsCondition(
+                                            DruidExpression.fromColumn("dim2"),
+                                            DruidExpression.fromColumn("______________j0.k")
+                                        ),
                                         JoinType.INNER
                                     ),
                                     new LookupDataSource("lookyloo"),
                                     "_______________j0.",
-                                    equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("_______________j0.k")),
+                                    equalsCondition(
+                                        DruidExpression.fromColumn("dim2"),
+                                        DruidExpression.fromColumn("_______________j0.k")
+                                    ),
                                     JoinType.INNER
                                 ),
                                 new LookupDataSource("lookyloo"),
                                 "________________j0.",
-                                equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("________________j0.k")),
+                                equalsCondition(
+                                    DruidExpression.fromColumn("dim2"),
+                                    DruidExpression.fromColumn("________________j0.k")
+                                ),
                                 JoinType.INNER
                             ),
                             new LookupDataSource("lookyloo"),
                             "_________________j0.",
-                            equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("_________________j0.k")),
+                            equalsCondition(
+                                DruidExpression.fromColumn("dim2"),
+                                DruidExpression.fromColumn("_________________j0.k")
+                            ),
                             JoinType.INNER
                         ),
                         new LookupDataSource("lookyloo"),
                         "__________________j0.",
-                        equalsCondition(DruidExpression.fromColumn("dim2"), DruidExpression.fromColumn("__________________j0.k")),
+                        equalsCondition(
+                            DruidExpression.fromColumn("dim2"),
+                            DruidExpression.fromColumn("__________________j0.k")
+                        ),
                         JoinType.INNER
                     )
                 )
@@ -11213,7 +11395,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testInnerJoinTwoLookupsToTableUsingNumericColumnInReverse(Map<String, Object> queryContext) throws Exception
+  public void testInnerJoinTwoLookupsToTableUsingNumericColumnInReverse(Map<String, Object> queryContext)
+      throws Exception
   {
     // Like "testInnerJoinTwoLookupsToTableUsingNumericColumn", but the tables are specified backwards.
 
@@ -12574,31 +12757,31 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                   .build()
         ),
         ImmutableList.<Object[]>builder()
-            .add(new Object[]{1L, timestamp("2000-01-01")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T01")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T02")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T03")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T04")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T05")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T06")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T07")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T08")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T09")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T10")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T11")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T12")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T13")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T14")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T15")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T16")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T17")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T18")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T19")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T20")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T21")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T22")})
-            .add(new Object[]{defaultVal, timestamp("2000-01-01T23")})
-            .build()
+                     .add(new Object[]{1L, timestamp("2000-01-01")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T01")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T02")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T03")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T04")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T05")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T06")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T07")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T08")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T09")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T10")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T11")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T12")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T13")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T14")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T15")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T16")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T17")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T18")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T19")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T20")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T21")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T22")})
+                     .add(new Object[]{defaultVal, timestamp("2000-01-01T23")})
+                     .build()
     );
   }
 
@@ -12775,7 +12958,19 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         ),
         ImmutableList.of(
             useDefault
-            ? new Object[]{0L, 0L, 0L, 0.0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0L, Long.MIN_VALUE, Long.MAX_VALUE, 0L, Double.NaN}
+            ? new Object[]{
+                0L,
+                0L,
+                0L,
+                0.0,
+                Double.NEGATIVE_INFINITY,
+                Double.POSITIVE_INFINITY,
+                0L,
+                Long.MIN_VALUE,
+                Long.MAX_VALUE,
+                0L,
+                Double.NaN
+            }
             : new Object[]{0L, 0L, 0L, null, null, null, null, null, null, null, null}
         )
     );
@@ -12846,21 +13041,21 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                               not(selector("dim3", null, null))
                           ),
                           new FilteredAggregatorFactory(
-                            new ExpressionLambdaAggregatorFactory(
-                                "a8",
-                                ImmutableSet.of("l1"),
-                                "__acc",
-                                "0",
-                                "0",
-                                NullHandling.sqlCompatible(),
-                                "bitwiseAnd(\"__acc\", \"l1\")",
-                                "bitwiseAnd(\"__acc\", \"a8\")",
-                                null,
-                                null,
-                                ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES,
-                                TestExprMacroTable.INSTANCE
-                            ),
-                            not(selector("l1", null, null))
+                              new ExpressionLambdaAggregatorFactory(
+                                  "a8",
+                                  ImmutableSet.of("l1"),
+                                  "__acc",
+                                  "0",
+                                  "0",
+                                  NullHandling.sqlCompatible(),
+                                  "bitwiseAnd(\"__acc\", \"l1\")",
+                                  "bitwiseAnd(\"__acc\", \"a8\")",
+                                  null,
+                                  null,
+                                  ExpressionLambdaAggregatorFactory.DEFAULT_MAX_SIZE_BYTES,
+                                  TestExprMacroTable.INSTANCE
+                              ),
+                              not(selector("l1", null, null))
                           ),
                           new FilteredAggregatorFactory(
                               new ExpressionLambdaAggregatorFactory(
@@ -12942,11 +13137,23 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                     selector("dim1", "nonexistent", null)
                                 ),
                                 new FilteredAggregatorFactory(
-                                    new CardinalityAggregatorFactory("a1", null, ImmutableList.of(DefaultDimensionSpec.of("dim1")), false, true),
+                                    new CardinalityAggregatorFactory(
+                                        "a1",
+                                        null,
+                                        ImmutableList.of(DefaultDimensionSpec.of("dim1")),
+                                        false,
+                                        true
+                                    ),
                                     selector("dim1", "nonexistent", null)
                                 ),
                                 new FilteredAggregatorFactory(
-                                    new CardinalityAggregatorFactory("a2", null, ImmutableList.of(DefaultDimensionSpec.of("dim1")), false, true),
+                                    new CardinalityAggregatorFactory(
+                                        "a2",
+                                        null,
+                                        ImmutableList.of(DefaultDimensionSpec.of("dim1")),
+                                        false,
+                                        true
+                                    ),
                                     selector("dim1", "nonexistent", null)
                                 ),
                                 new FilteredAggregatorFactory(
@@ -13026,7 +13233,20 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         ),
         ImmutableList.of(
             useDefault
-            ? new Object[]{"a", 0L, 0L, 0L, 0.0, Double.NEGATIVE_INFINITY, Double.POSITIVE_INFINITY, 0L, Long.MIN_VALUE, Long.MAX_VALUE, 0L, Double.NaN}
+            ? new Object[]{
+                "a",
+                0L,
+                0L,
+                0L,
+                0.0,
+                Double.NEGATIVE_INFINITY,
+                Double.POSITIVE_INFINITY,
+                0L,
+                Long.MIN_VALUE,
+                Long.MAX_VALUE,
+                0L,
+                Double.NaN
+            }
             : new Object[]{"a", 0L, 0L, 0L, null, null, null, null, null, null, null, null}
         )
     );
@@ -14563,7 +14783,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                 new QueryDataSource(
                                     newScanQueryBuilder()
                                         .dataSource(CalciteTests.DATASOURCE1)
-                                        .intervals(querySegmentSpec(Intervals.of("2001-01-02T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
+                                        .intervals(querySegmentSpec(Intervals.of(
+                                            "2001-01-02T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
                                         .columns("dim1")
                                         .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
                                         .context(queryContext)
@@ -14572,7 +14793,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                 new QueryDataSource(
                                     newScanQueryBuilder()
                                         .dataSource(CalciteTests.DATASOURCE1)
-                                        .intervals(querySegmentSpec(Intervals.of("2001-01-02T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
+                                        .intervals(querySegmentSpec(Intervals.of(
+                                            "2001-01-02T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
                                         .columns("dim1", "m2")
                                         .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
                                         .context(queryContext)
@@ -14602,7 +14824,7 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                 .setInterval(querySegmentSpec(Filtration.eternity()))
                 .build()
         ),
-        ImmutableList.of(new Object[] {1L})
+        ImmutableList.of(new Object[]{1L})
     );
   }
 
@@ -14635,7 +14857,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                 new QueryDataSource(
                     newScanQueryBuilder()
                         .dataSource(CalciteTests.DATASOURCE1)
-                        .intervals(querySegmentSpec(Intervals.of("2001-01-02T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
+                        .intervals(querySegmentSpec(Intervals.of(
+                            "2001-01-02T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
                         .columns("dim1")
                         .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
                         .context(queryContext)
@@ -14644,7 +14867,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                 new QueryDataSource(
                     newScanQueryBuilder()
                         .dataSource(CalciteTests.DATASOURCE1)
-                        .intervals(querySegmentSpec(Intervals.of("2001-01-02T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
+                        .intervals(querySegmentSpec(Intervals.of(
+                            "2001-01-02T00:00:00.000Z/146140482-04-24T15:36:27.903Z")))
                         .columns("dim1", "m2")
                         .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
                         .context(queryContext)
@@ -14986,7 +15210,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                 in("dim1", ImmutableList.of("abc", "def"), null),
                                 or(
                                     selector("_j0._a0", "0", null),
-                                    and(selector("__j0.p0", null, null), expressionFilter("(\"_j0._a1\" >= \"_j0._a0\")"))
+                                    and(
+                                        selector("__j0.p0", null, null),
+                                        expressionFilter("(\"_j0._a1\" >= \"_j0._a0\")")
+                                    )
                                 )
                             )
                         )
@@ -15660,8 +15887,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                         .setInterval(querySegmentSpec(Filtration.eternity()))
                                         .setGranularity(Granularities.ALL)
                                         .setDimensions(
-                                              useDefault
-                                              ? dimensions(
+                                            useDefault
+                                            ? dimensions(
                                                 new DefaultDimensionSpec("__time", "d0", ColumnType.LONG),
                                                 new DefaultDimensionSpec("m2", "d1", ColumnType.DOUBLE),
                                                 new DefaultDimensionSpec("dim1", "d2")
@@ -15777,19 +16004,19 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                 .aggregators(
                     useDefault
                     ? aggregators(
-                      new DoubleSumAggregatorFactory("a0:sum", "m2"),
-                      new CountAggregatorFactory("a0:count"),
-                      new DoubleSumAggregatorFactory("a1", "m1"),
-                      new DoubleSumAggregatorFactory("a2", "m2")
+                        new DoubleSumAggregatorFactory("a0:sum", "m2"),
+                        new CountAggregatorFactory("a0:count"),
+                        new DoubleSumAggregatorFactory("a1", "m1"),
+                        new DoubleSumAggregatorFactory("a2", "m2")
                     )
                     : aggregators(
-                      new DoubleSumAggregatorFactory("a0:sum", "m2"),
-                      new FilteredAggregatorFactory(
-                          new CountAggregatorFactory("a0:count"),
-                          not(selector("m2", null, null))
-                      ),
-                      new DoubleSumAggregatorFactory("a1", "m1"),
-                      new DoubleSumAggregatorFactory("a2", "m2")
+                        new DoubleSumAggregatorFactory("a0:sum", "m2"),
+                        new FilteredAggregatorFactory(
+                            new CountAggregatorFactory("a0:count"),
+                            not(selector("m2", null, null))
+                        ),
+                        new DoubleSumAggregatorFactory("a1", "m1"),
+                        new DoubleSumAggregatorFactory("a2", "m2")
                     )
                 )
                 .postAggregators(
@@ -16760,7 +16987,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testLeftJoinOnTwoInlineDataSourcesWithTimeFilter_withLeftDirectAccess(Map<String, Object> queryContext) throws Exception
+  public void testLeftJoinOnTwoInlineDataSourcesWithTimeFilter_withLeftDirectAccess(Map<String, Object> queryContext)
+      throws Exception
   {
     queryContext = withLeftDirectAccessEnabled(queryContext);
     testQuery(
@@ -16872,7 +17100,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testLeftJoinOnTwoInlineDataSourcesWithOuterWhere_withLeftDirectAccess(Map<String, Object> queryContext) throws Exception
+  public void testLeftJoinOnTwoInlineDataSourcesWithOuterWhere_withLeftDirectAccess(Map<String, Object> queryContext)
+      throws Exception
   {
     queryContext = withLeftDirectAccessEnabled(queryContext);
     testQuery(
@@ -16898,7 +17127,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                 .build()
                         ),
                         "j0.",
-                        equalsCondition(DruidExpression.fromExpression("'10.1'"), DruidExpression.fromColumn("j0.dim1")),
+                        equalsCondition(
+                            DruidExpression.fromExpression("'10.1'"),
+                            DruidExpression.fromColumn("j0.dim1")
+                        ),
                         JoinType.LEFT,
                         selector("dim1", "10.1", null)
                     )
@@ -16996,7 +17228,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                 .build()
                         ),
                         "j0.",
-                        equalsCondition(DruidExpression.fromExpression("'10.1'"), DruidExpression.fromColumn("j0.dim1")),
+                        equalsCondition(
+                            DruidExpression.fromExpression("'10.1'"),
+                            DruidExpression.fromColumn("j0.dim1")
+                        ),
                         JoinType.LEFT,
                         selector("dim1", "10.1", null)
                     )
@@ -17069,7 +17304,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testInnerJoinOnTwoInlineDataSourcesWithOuterWhere_withLeftDirectAccess(Map<String, Object> queryContext) throws Exception
+  public void testInnerJoinOnTwoInlineDataSourcesWithOuterWhere_withLeftDirectAccess(Map<String, Object> queryContext)
+      throws Exception
   {
     queryContext = withLeftDirectAccessEnabled(queryContext);
     testQuery(
@@ -17095,7 +17331,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                 .build()
                         ),
                         "j0.",
-                        equalsCondition(DruidExpression.fromExpression("'10.1'"), DruidExpression.fromColumn("j0.dim1")),
+                        equalsCondition(
+                            DruidExpression.fromExpression("'10.1'"),
+                            DruidExpression.fromColumn("j0.dim1")
+                        ),
                         JoinType.INNER,
                         selector("dim1", "10.1", null)
                     )
@@ -17167,7 +17406,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testInnerJoinOnTwoInlineDataSources_withLeftDirectAccess(Map<String, Object> queryContext) throws Exception
+  public void testInnerJoinOnTwoInlineDataSources_withLeftDirectAccess(Map<String, Object> queryContext)
+      throws Exception
   {
     queryContext = withLeftDirectAccessEnabled(queryContext);
     testQuery(
@@ -17193,7 +17433,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                 .build()
                         ),
                         "j0.",
-                        equalsCondition(DruidExpression.fromExpression("'10.1'"), DruidExpression.fromColumn("j0.dim1")),
+                        equalsCondition(
+                            DruidExpression.fromExpression("'10.1'"),
+                            DruidExpression.fromColumn("j0.dim1")
+                        ),
                         JoinType.INNER,
                         selector("dim1", "10.1", null)
                     )
@@ -17339,7 +17582,8 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
   @Test
   @Parameters(source = QueryContextForJoinProvider.class)
-  public void testTopNOnStringWithNonSortedOrUniqueDictionaryOrderByDim(Map<String, Object> queryContext) throws Exception
+  public void testTopNOnStringWithNonSortedOrUniqueDictionaryOrderByDim(Map<String, Object> queryContext)
+      throws Exception
   {
     testQuery(
         "SELECT druid.broadcast.dim4, COUNT(*)\n"
@@ -17412,7 +17656,11 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                              .dataSource(CalciteTests.DATASOURCE1)
                              .intervals(querySegmentSpec(Filtration.eternity()))
                              .virtualColumns(
-                                 expressionVirtualColumn("v0", "timestamp_shift(\"__time\",'P0M',1,'UTC')", ColumnType.LONG)
+                                 expressionVirtualColumn(
+                                     "v0",
+                                     "timestamp_shift(\"__time\",'P0M',1,'UTC')",
+                                     ColumnType.LONG
+                                 )
                              )
                              .columns("v0")
                              .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
@@ -17439,7 +17687,11 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                              .dataSource(CalciteTests.DATASOURCE1)
                              .intervals(querySegmentSpec(Filtration.eternity()))
                              .virtualColumns(
-                                 expressionVirtualColumn("v0", "timestamp_shift(\"__time\",'P0M',1,'UTC')", ColumnType.LONG)
+                                 expressionVirtualColumn(
+                                     "v0",
+                                     "timestamp_shift(\"__time\",'P0M',1,'UTC')",
+                                     ColumnType.LONG
+                                 )
                              )
                              .columns("v0")
                              .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
@@ -17473,7 +17725,11 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                              .dataSource(CalciteTests.DATASOURCE1)
                              .intervals(querySegmentSpec(Filtration.eternity()))
                              .virtualColumns(
-                                 expressionVirtualColumn("v0", "timestamp_shift(\"__time\",'P1M',1,'UTC')", ColumnType.LONG)
+                                 expressionVirtualColumn(
+                                     "v0",
+                                     "timestamp_shift(\"__time\",'P1M',1,'UTC')",
+                                     ColumnType.LONG
+                                 )
                              )
                              .columns("v0")
                              .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
@@ -17497,7 +17753,11 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                              .dataSource(CalciteTests.DATASOURCE1)
                              .intervals(querySegmentSpec(Filtration.eternity()))
                              .virtualColumns(
-                                 expressionVirtualColumn("v0", "timestamp_shift(\"__time\",concat('P', (1 * \"cnt\"), 'M'),1,'UTC')", ColumnType.LONG)
+                                 expressionVirtualColumn(
+                                     "v0",
+                                     "timestamp_shift(\"__time\",concat('P', (1 * \"cnt\"), 'M'),1,'UTC')",
+                                     ColumnType.LONG
+                                 )
                              )
                              .columns("v0")
                              .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
@@ -17731,7 +17991,16 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                                   .dataSource(CalciteTests.DATASOURCE1)
                                   .intervals(querySegmentSpec(Filtration.eternity()))
                                   .resultFormat(ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
-                                  .filters(new BoundDimFilter("m1", "2", null, true, false, null, null, StringComparators.NUMERIC))
+                                  .filters(new BoundDimFilter(
+                                      "m1",
+                                      "2",
+                                      null,
+                                      true,
+                                      false,
+                                      null,
+                                      null,
+                                      StringComparators.NUMERIC
+                                  ))
                                   .columns("dim2")
                                   .legacy(false)
                                   .build()
@@ -17949,27 +18218,30 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         "SELECT count(*) FROM druid.foo t1 inner join druid.foo t2 on t1.__time = t2.__time",
         CalciteTests.REGULAR_USER_AUTH_RESULT,
         ImmutableList.of(Druids.newTimeseriesQueryBuilder()
-                               .dataSource(JoinDataSource.create(new TableDataSource(CalciteTests.DATASOURCE1),
-                                                                 new QueryDataSource(
-                                                                     Druids.newScanQueryBuilder()
-                                                                           .dataSource(CalciteTests.DATASOURCE1)
-                                                                           .intervals(querySegmentSpec(Filtration.eternity()))
-                                                                           .resultFormat(ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
-                                                                           .columns("__time")
-                                                                           .legacy(false)
-                                                                           .context(QUERY_CONTEXT_DEFAULT)
-                                                                           .build()),
-                                                                 "j0.",
-                                                                 "(\"__time\" == \"j0.__time\")",
-                                                                 JoinType.INNER,
-                                                                 null,
-                                                                 ExprMacroTable.nil()))
+                               .dataSource(JoinDataSource.create(
+                                   new TableDataSource(CalciteTests.DATASOURCE1),
+                                   new QueryDataSource(
+                                       Druids.newScanQueryBuilder()
+                                             .dataSource(CalciteTests.DATASOURCE1)
+                                             .intervals(querySegmentSpec(Filtration.eternity()))
+                                             .resultFormat(ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
+                                             .columns("__time")
+                                             .legacy(false)
+                                             .context(QUERY_CONTEXT_DEFAULT)
+                                             .build()),
+                                   "j0.",
+                                   "(\"__time\" == \"j0.__time\")",
+                                   JoinType.INNER,
+                                   null,
+                                   ExprMacroTable.nil()
+                               ))
                                .intervals(querySegmentSpec(Filtration.eternity()))
                                .granularity(Granularities.ALL)
                                .aggregators(aggregators(new CountAggregatorFactory("a0")))
                                .context(QUERY_CONTEXT_DEFAULT)
                                .build()),
-        ImmutableList.of(new Object[]{6L}));
+        ImmutableList.of(new Object[]{6L})
+    );
   }
 
   @Test
@@ -18263,7 +18535,9 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         .context(queryContext)
         .build();
 
-    boolean isJoinFilterRewriteEnabled = queryContext.getOrDefault(JOIN_FILTER_REWRITE_ENABLE_KEY, true).toString().equals("true");
+    boolean isJoinFilterRewriteEnabled = queryContext.getOrDefault(JOIN_FILTER_REWRITE_ENABLE_KEY, true)
+                                                     .toString()
+                                                     .equals("true");
     testQuery(
         "SELECT dim1, l1.k\n"
         + "FROM foo\n"
@@ -18271,12 +18545,16 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
         + "WHERE l1.k IS NOT NULL\n",
         queryContext,
         ImmutableList.of(NullHandling.sqlCompatible() ? nullCompatibleModePlan : nonNullCompatibleModePlan),
-        NullHandling.sqlCompatible() || !isJoinFilterRewriteEnabled ? ImmutableList.of(new Object[]{"abc", "abc"}) : ImmutableList.of(
-                         new Object[]{"10.1", ""}, // this result is incorrect. TODO : fix this result when the JoinFilterAnalyzer bug is fixed
-                         new Object[]{"2", ""},
-                         new Object[]{"1", ""},
-                         new Object[]{"def", ""},
-                         new Object[]{"abc", "abc"})
+        NullHandling.sqlCompatible() || !isJoinFilterRewriteEnabled
+        ? ImmutableList.of(new Object[]{"abc", "abc"})
+        : ImmutableList.of(
+            new Object[]{"10.1", ""},
+            // this result is incorrect. TODO : fix this result when the JoinFilterAnalyzer bug is fixed
+            new Object[]{"2", ""},
+            new Object[]{"1", ""},
+            new Object[]{"def", ""},
+            new Object[]{"abc", "abc"}
+        )
     );
   }
 
@@ -18289,8 +18567,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
 
     // disable the cost model where inner join is treated like a filter
     // this leads to cost(left join) < cost(converted inner join) for the below query
-    queryContext = QueryContextForJoinProvider.withOverrides(queryContext,
-                                                             ImmutableMap.of("computeInnerJoinCostAsFilter", "false"));
+    queryContext = QueryContextForJoinProvider.withOverrides(
+        queryContext,
+        ImmutableMap.of("computeInnerJoinCostAsFilter", "false")
+    );
     testQuery(
         "SELECT dim1, l1.k\n"
         + "FROM foo\n"
@@ -18348,12 +18628,12 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                     join(
                         new TableDataSource(CalciteTests.DATASOURCE1),
                         new QueryDataSource(newScanQueryBuilder()
-                            .dataSource(CalciteTests.DATASOURCE1)
-                            .intervals(querySegmentSpec(Filtration.eternity()))
-                            .columns(ImmutableList.of("dim1"))
-                            .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
-                            .context(QUERY_CONTEXT_DEFAULT)
-                            .build()),
+                                                .dataSource(CalciteTests.DATASOURCE1)
+                                                .intervals(querySegmentSpec(Filtration.eternity()))
+                                                .columns(ImmutableList.of("dim1"))
+                                                .resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
+                                                .context(QUERY_CONTEXT_DEFAULT)
+                                                .build()),
                         "j0.",
                         equalsCondition(DruidExpression.fromColumn("dim1"), DruidExpression.fromColumn("j0.dim1")),
                         JoinType.LEFT
@@ -18408,7 +18688,10 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                         StringUtils.format(
                             "(%s && %s)",
                             equalsCondition(DruidExpression.fromColumn("dim1"), DruidExpression.fromColumn("j0.d0")),
-                            equalsCondition(DruidExpression.fromExpression("'abc'"), DruidExpression.fromColumn("j0.d0"))
+                            equalsCondition(
+                                DruidExpression.fromExpression("'abc'"),
+                                DruidExpression.fromColumn("j0.d0")
+                            )
                         ),
                         JoinType.INNER
                     )
@@ -18763,7 +19046,9 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                   .build()
         ),
         ImmutableList.of(
-            useDefault ? new Object[]{"1a,a,2,abc,10.1,defabc", "1a||a||2||abc||10.1||defabc"} : new Object[]{"1a,a,2,defabc", "1a||a||2||defabc"}
+            useDefault
+            ? new Object[]{"1a,a,2,abc,10.1,defabc", "1a||a||2||abc||10.1||defabc"}
+            : new Object[]{"1a,a,2,defabc", "1a||a||2||defabc"}
         )
     );
   }
@@ -18865,14 +19150,27 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                 // NOTE: the first expression HUMAN_READABLE_BINARY_BYTE_FORMAT(45678) in SQL is calculated during SQL parse phase,
                 // so the converted Druid native query is its result intead of the raw function call
                 //
-                .virtualColumns(expressionVirtualColumn("v0", "'44.61 KiB'", ColumnType.STRING),
-                                expressionVirtualColumn("v1", "human_readable_binary_byte_format((\"m1\" * 12345))", ColumnType.STRING),
-                                expressionVirtualColumn("v2", "human_readable_binary_byte_format((\"m1\" * 12345),0)", ColumnType.STRING),
-                                expressionVirtualColumn("v3", "human_readable_decimal_byte_format((\"m1\" * 12345))", ColumnType.STRING),
-                                expressionVirtualColumn("v4", "human_readable_decimal_format((\"m1\" * 12345))", ColumnType.STRING),
-                                expressionVirtualColumn("v5", "human_readable_binary_byte_format(\"l1\")", ColumnType.STRING),
-                                expressionVirtualColumn("v6", "human_readable_decimal_byte_format(\"l1\")", ColumnType.STRING),
-                                expressionVirtualColumn("v7", "human_readable_decimal_format(\"l1\")", ColumnType.STRING)
+                .virtualColumns(
+                    expressionVirtualColumn("v0", "'44.61 KiB'", ColumnType.STRING),
+                    expressionVirtualColumn(
+                        "v1",
+                        "human_readable_binary_byte_format((\"m1\" * 12345))",
+                        ColumnType.STRING
+                    ),
+                    expressionVirtualColumn(
+                        "v2",
+                        "human_readable_binary_byte_format((\"m1\" * 12345),0)",
+                        ColumnType.STRING
+                    ),
+                    expressionVirtualColumn(
+                        "v3",
+                        "human_readable_decimal_byte_format((\"m1\" * 12345))",
+                        ColumnType.STRING
+                    ),
+                    expressionVirtualColumn("v4", "human_readable_decimal_format((\"m1\" * 12345))", ColumnType.STRING),
+                    expressionVirtualColumn("v5", "human_readable_binary_byte_format(\"l1\")", ColumnType.STRING),
+                    expressionVirtualColumn("v6", "human_readable_decimal_byte_format(\"l1\")", ColumnType.STRING),
+                    expressionVirtualColumn("v7", "human_readable_decimal_format(\"l1\")", ColumnType.STRING)
                 )
                 .columns("m1", "v0", "v1", "v2", "v3", "v4", "v5", "v6", "v7")
                 .filters(selector("dim1", "1", null))
@@ -18882,15 +19180,16 @@ public class CalciteQueryTest extends BaseCalciteQueryTest
                 .build()
         ),
         ImmutableList.of(
-            new Object[]{(float) 4.0,
-                         "44.61 KiB", // 45678 / 1024
-                         "48.22 KiB", // = m1(4.0) * 12345 / 1024
-                         "48 KiB", // = m1(4.0) * 12345 / 1024, precision = 0
-                         "49.38 KB", // decimal byte format, m1(4.0) * 12345 / 1000,
-                         "49.38 K", // decimal format, m1(4.0) * 12345 / 1000,
-                         NullHandling.replaceWithDefault() ? "0 B" : null,
-                         NullHandling.replaceWithDefault() ? "0 B" : null,
-                         NullHandling.replaceWithDefault() ? "0" : null
+            new Object[]{
+                (float) 4.0,
+                "44.61 KiB", // 45678 / 1024
+                "48.22 KiB", // = m1(4.0) * 12345 / 1024
+                "48 KiB", // = m1(4.0) * 12345 / 1024, precision = 0
+                "49.38 KB", // decimal byte format, m1(4.0) * 12345 / 1000,
+                "49.38 K", // decimal format, m1(4.0) * 12345 / 1000,
+                NullHandling.replaceWithDefault() ? "0 B" : null,
+                NullHandling.replaceWithDefault() ? "0 B" : null,
+                NullHandling.replaceWithDefault() ? "0" : null
             }
         )
     );
diff --git a/website/.spelling b/website/.spelling
index 01e9ff3..53a2dca 100644
--- a/website/.spelling
+++ b/website/.spelling
@@ -1203,6 +1203,7 @@ result2
 rint
 rpad
 rtrim
+safe_divide
 scalb
 signum
 str1

---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@druid.apache.org
For additional commands, e-mail: commits-help@druid.apache.org