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

abhishek 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 2d5b27358e Logging the fieldName in the coerce exceptions  (#14483)
2d5b27358e is described below

commit 2d5b27358e0a1abefcc3c7ddeb3af613ddf88df5
Author: Pranav <[email protected]>
AuthorDate: Mon Jul 3 01:43:27 2023 -0700

    Logging the fieldName in the coerce exceptions  (#14483)
    
    Logging the fieldName in the coerce exceptions
---
 .../org/apache/druid/msq/exec/ControllerImpl.java  |  3 +-
 .../druid/msq/indexing/MSQControllerTask.java      |  2 +-
 .../druid/sql/calcite/run/NativeQueryMaker.java    |  3 +-
 .../apache/druid/sql/calcite/run/SqlResults.java   | 80 ++++++++++++++--------
 .../sql/calcite/CalciteScanSignatureTest.java      | 29 ++++++++
 .../druid/sql/calcite/run/SqlResultsTest.java      | 21 ++++--
 6 files changed, 101 insertions(+), 37 deletions(-)

diff --git 
a/extensions-core/multi-stage-query/src/main/java/org/apache/druid/msq/exec/ControllerImpl.java
 
b/extensions-core/multi-stage-query/src/main/java/org/apache/druid/msq/exec/ControllerImpl.java
index eebc95077b..1a8ef12cb2 100644
--- 
a/extensions-core/multi-stage-query/src/main/java/org/apache/druid/msq/exec/ControllerImpl.java
+++ 
b/extensions-core/multi-stage-query/src/main/java/org/apache/druid/msq/exec/ControllerImpl.java
@@ -1471,7 +1471,8 @@ public class ControllerImpl implements Controller
                                      context.jsonMapper(),
                                      task.getSqlResultsContext(),
                                      value,
-                                     sqlTypeNames.get(i)
+                                     sqlTypeNames.get(i),
+                                     columnMappings.getOutputColumnName(i)
                                  );
                                }
                              }
diff --git 
a/extensions-core/multi-stage-query/src/main/java/org/apache/druid/msq/indexing/MSQControllerTask.java
 
b/extensions-core/multi-stage-query/src/main/java/org/apache/druid/msq/indexing/MSQControllerTask.java
index 0228052573..30047f227f 100644
--- 
a/extensions-core/multi-stage-query/src/main/java/org/apache/druid/msq/indexing/MSQControllerTask.java
+++ 
b/extensions-core/multi-stage-query/src/main/java/org/apache/druid/msq/indexing/MSQControllerTask.java
@@ -82,7 +82,7 @@ public class MSQControllerTask extends AbstractTask 
implements ClientTaskQuery
   private final Map<String, Object> sqlQueryContext;
 
   /**
-   * Enables usage of {@link SqlResults#coerce(ObjectMapper, 
SqlResults.Context, Object, SqlTypeName)}.
+   * Enables usage of {@link SqlResults#coerce(ObjectMapper, 
SqlResults.Context, Object, SqlTypeName, String)}.
    */
   @Nullable
   private final SqlResults.Context sqlResultsContext;
diff --git 
a/sql/src/main/java/org/apache/druid/sql/calcite/run/NativeQueryMaker.java 
b/sql/src/main/java/org/apache/druid/sql/calcite/run/NativeQueryMaker.java
index e2b3059190..e831960a39 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/run/NativeQueryMaker.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/run/NativeQueryMaker.java
@@ -241,7 +241,8 @@ public class NativeQueryMaker implements QueryMaker
                     jsonMapper,
                     sqlResultsContext,
                     array[mapping[i]],
-                    newTypes.get(i).getSqlTypeName()
+                    newTypes.get(i).getSqlTypeName(),
+                    originalFields.get(mapping[i])
                 );
               }
               return newArray;
diff --git a/sql/src/main/java/org/apache/druid/sql/calcite/run/SqlResults.java 
b/sql/src/main/java/org/apache/druid/sql/calcite/run/SqlResults.java
index ab400b97a3..d314a3a4cc 100644
--- a/sql/src/main/java/org/apache/druid/sql/calcite/run/SqlResults.java
+++ b/sql/src/main/java/org/apache/druid/sql/calcite/run/SqlResults.java
@@ -28,8 +28,8 @@ import com.google.common.primitives.Ints;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.calcite.util.NlsString;
 import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.error.DruidException;
 import org.apache.druid.java.util.common.DateTimes;
-import org.apache.druid.java.util.common.ISE;
 import org.apache.druid.math.expr.Evals;
 import org.apache.druid.segment.DimensionHandlerUtils;
 import org.apache.druid.segment.data.ComparableList;
@@ -48,7 +48,7 @@ import java.util.Objects;
 import java.util.stream.Collectors;
 
 /**
- * Holder for the utility method {@link #coerce(ObjectMapper, Context, Object, 
SqlTypeName)}.
+ * Holder for the utility method {@link #coerce(ObjectMapper, Context, Object, 
SqlTypeName, String)}.
  */
 public class SqlResults
 {
@@ -56,7 +56,8 @@ public class SqlResults
       final ObjectMapper jsonMapper,
       final Context context,
       final Object value,
-      final SqlTypeName sqlTypeName
+      final SqlTypeName sqlTypeName,
+      final String fieldName
   )
   {
     final Object coercedValue;
@@ -79,21 +80,21 @@ public class SqlResults
           final List<String> valueStrings =
               ((Collection<?>) maybeList)
                   .stream()
-                  .map(v -> (String) coerce(jsonMapper, context, v, 
sqlTypeName))
+                  .map(v -> (String) coerce(jsonMapper, context, v, 
sqlTypeName, fieldName))
                   .collect(Collectors.toList());
 
           // Must stringify since the caller is expecting CHAR_TYPES.
-          coercedValue = coerceUsingObjectMapper(jsonMapper, valueStrings, 
sqlTypeName);
+          coercedValue = coerceUsingObjectMapper(jsonMapper, valueStrings, 
sqlTypeName, fieldName);
         } else {
-          throw cannotCoerce(value, sqlTypeName);
+          throw cannotCoerce(value, sqlTypeName, fieldName);
         }
       }
     } else if (value == null) {
       coercedValue = null;
     } else if (sqlTypeName == SqlTypeName.DATE) {
-      return Calcites.jodaToCalciteDate(coerceDateTime(value, sqlTypeName), 
context.getTimeZone());
+      return Calcites.jodaToCalciteDate(coerceDateTime(value, sqlTypeName, 
fieldName), context.getTimeZone());
     } else if (sqlTypeName == SqlTypeName.TIMESTAMP) {
-      return Calcites.jodaToCalciteTimestamp(coerceDateTime(value, 
sqlTypeName), context.getTimeZone());
+      return Calcites.jodaToCalciteTimestamp(coerceDateTime(value, 
sqlTypeName, fieldName), context.getTimeZone());
     } else if (sqlTypeName == SqlTypeName.BOOLEAN) {
       if (value instanceof Boolean) {
         coercedValue = value;
@@ -102,7 +103,7 @@ public class SqlResults
       } else if (value instanceof Number) {
         coercedValue = Evals.asBoolean(((Number) value).longValue());
       } else {
-        throw cannotCoerce(value, sqlTypeName);
+        throw cannotCoerce(value, sqlTypeName, fieldName);
       }
     } else if (sqlTypeName == SqlTypeName.INTEGER) {
       if (value instanceof String) {
@@ -110,33 +111,33 @@ public class SqlResults
       } else if (value instanceof Number) {
         coercedValue = ((Number) value).intValue();
       } else {
-        throw cannotCoerce(value, sqlTypeName);
+        throw cannotCoerce(value, sqlTypeName, fieldName);
       }
     } else if (sqlTypeName == SqlTypeName.BIGINT) {
       try {
         coercedValue = DimensionHandlerUtils.convertObjectToLong(value);
       }
       catch (Exception e) {
-        throw cannotCoerce(value, sqlTypeName);
+        throw cannotCoerce(value, sqlTypeName, fieldName);
       }
     } else if (sqlTypeName == SqlTypeName.FLOAT) {
       try {
         coercedValue = DimensionHandlerUtils.convertObjectToFloat(value);
       }
       catch (Exception e) {
-        throw cannotCoerce(value, sqlTypeName);
+        throw cannotCoerce(value, sqlTypeName, fieldName);
       }
     } else if (SqlTypeName.FRACTIONAL_TYPES.contains(sqlTypeName)) {
       try {
         coercedValue = DimensionHandlerUtils.convertObjectToDouble(value);
       }
       catch (Exception e) {
-        throw cannotCoerce(value, sqlTypeName);
+        throw cannotCoerce(value, sqlTypeName, fieldName);
       }
     } else if (sqlTypeName == SqlTypeName.OTHER) {
       // Complex type, try to serialize if we should, else print class name
       if (context.isSerializeComplexValues()) {
-        coercedValue = coerceUsingObjectMapper(jsonMapper, value, sqlTypeName);
+        coercedValue = coerceUsingObjectMapper(jsonMapper, value, sqlTypeName, 
fieldName);
       } else {
         coercedValue = value.getClass().getName();
       }
@@ -147,7 +148,7 @@ public class SqlResults
         } else if (value instanceof NlsString) {
           coercedValue = ((NlsString) value).getValue();
         } else {
-          coercedValue = coerceUsingObjectMapper(jsonMapper, value, 
sqlTypeName);
+          coercedValue = coerceUsingObjectMapper(jsonMapper, value, 
sqlTypeName, fieldName);
         }
       } else {
         // the protobuf jdbc handler prefers lists (it actually can't handle 
java arrays as sql arrays, only java lists)
@@ -155,11 +156,11 @@ public class SqlResults
         // here if needed
         coercedValue = maybeCoerceArrayToList(value, true);
         if (coercedValue == null) {
-          throw cannotCoerce(value, sqlTypeName);
+          throw cannotCoerce(value, sqlTypeName, fieldName);
         }
       }
     } else {
-      throw cannotCoerce(value, sqlTypeName);
+      throw cannotCoerce(value, sqlTypeName, fieldName);
     }
 
     return coercedValue;
@@ -209,7 +210,7 @@ public class SqlResults
     return value;
   }
 
-  private static DateTime coerceDateTime(Object value, SqlTypeName sqlType)
+  private static DateTime coerceDateTime(final Object value, final SqlTypeName 
sqlType, final String fieldName)
   {
     final DateTime dateTime;
 
@@ -220,7 +221,7 @@ public class SqlResults
     } else if (value instanceof DateTime) {
       dateTime = (DateTime) value;
     } else {
-      throw cannotCoerce(value, sqlType);
+      throw cannotCoerce(value, sqlType, fieldName);
     }
     return dateTime;
   }
@@ -228,33 +229,52 @@ public class SqlResults
   private static String coerceUsingObjectMapper(
       final ObjectMapper jsonMapper,
       final Object value,
-      final SqlTypeName sqlTypeName
+      final SqlTypeName sqlTypeName,
+      final String fieldName
   )
   {
     try {
       return jsonMapper.writeValueAsString(value);
     }
     catch (JsonProcessingException e) {
-      throw cannotCoerce(e, value, sqlTypeName);
+      throw cannotCoerce(e, value, sqlTypeName, fieldName);
     }
   }
 
-  private static IllegalStateException cannotCoerce(
-      final Throwable t,
-      final Object value,
-      final SqlTypeName sqlTypeName
-  )
+  private static DruidException cannotCoerce(final Throwable t, final Object 
value, final SqlTypeName sqlTypeName, final String fieldName)
+  {
+    return DruidException.forPersona(DruidException.Persona.USER)
+                         .ofCategory(DruidException.Category.INVALID_INPUT)
+                         .build(
+                             t,
+                             "Cannot coerce field [%s] from type [%s] to type 
[%s]",
+                             fieldName,
+                             value == null
+                             ? "unknown"
+                             : 
mapPriveArrayClassNameToReadableStrings(value.getClass().getName()),
+                             sqlTypeName
+                         );
+  }
+
+  private static String mapPriveArrayClassNameToReadableStrings(String name)
   {
-    return new ISE(t, "Cannot coerce [%s] to [%s]", value == null ? "null" : 
value.getClass().getName(), sqlTypeName);
+    switch (name) {
+      case "[B":
+        return "Byte Array";
+      case "[Z":
+        return "Boolean Array";
+      default:
+        return name;
+    }
   }
 
-  private static IllegalStateException cannotCoerce(final Object value, final 
SqlTypeName sqlTypeName)
+  private static DruidException cannotCoerce(final Object value, final 
SqlTypeName sqlTypeName, final String fieldName)
   {
-    return cannotCoerce(null, value, sqlTypeName);
+    return cannotCoerce(null, value, sqlTypeName, fieldName);
   }
 
   /**
-   * Context for {@link #coerce(ObjectMapper, Context, Object, SqlTypeName)}
+   * Context for {@link #coerce(ObjectMapper, Context, Object, SqlTypeName, 
String)}
    */
   public static class Context
   {
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteScanSignatureTest.java 
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteScanSignatureTest.java
index 13568f4e7a..424a2e8895 100644
--- 
a/sql/src/test/java/org/apache/druid/sql/calcite/CalciteScanSignatureTest.java
+++ 
b/sql/src/test/java/org/apache/druid/sql/calcite/CalciteScanSignatureTest.java
@@ -81,6 +81,35 @@ public class CalciteScanSignatureTest extends 
BaseCalciteQueryTest
     );
   }
 
+  @Test
+  public void testScanSignatureWithDimAsValuePrimitiveByteArr()
+  {
+    final Map<String, Object> context = new HashMap<>(QUERY_CONTEXT_DEFAULT);
+    testQuery(
+        "SELECT CAST(dim1 AS BIGINT) as dimX FROM foo2 limit 2",
+        ImmutableList.of(
+            newScanQueryBuilder()
+                .dataSource(CalciteTests.DATASOURCE2)
+                .intervals(querySegmentSpec(Filtration.eternity()))
+                .columns("v0")
+                .virtualColumns(expressionVirtualColumn(
+                    "v0",
+                    "CAST(\"dim1\", 'LONG')",
+                    ColumnType.LONG
+                ))
+                
.resultFormat(ScanQuery.ResultFormat.RESULT_FORMAT_COMPACTED_LIST)
+                .context(context)
+                .limit(2)
+                .build()
+        ),
+        useDefault ? ImmutableList.of(
+            new Object[]{0L}, new Object[]{0L}
+        ) : ImmutableList.of(
+            new Object[]{null}, new Object[]{null}
+        )
+    );
+  }
+
   @Override
   public SqlEngine createEngine(
       QueryLifecycleFactory qlf,
diff --git 
a/sql/src/test/java/org/apache/druid/sql/calcite/run/SqlResultsTest.java 
b/sql/src/test/java/org/apache/druid/sql/calcite/run/SqlResultsTest.java
index 954170fffe..3c06e52238 100644
--- a/sql/src/test/java/org/apache/druid/sql/calcite/run/SqlResultsTest.java
+++ b/sql/src/test/java/org/apache/druid/sql/calcite/run/SqlResultsTest.java
@@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableSortedSet;
 import org.apache.calcite.sql.type.SqlTypeName;
 import org.apache.druid.common.config.NullHandling;
+import org.apache.druid.error.DruidException;
 import org.apache.druid.java.util.common.StringUtils;
 import org.apache.druid.segment.TestHelper;
 import org.apache.druid.segment.data.ComparableList;
@@ -171,6 +172,7 @@ public class SqlResultsTest extends 
InitializedNullHandlingTest
     assertCoerce(1L, true, SqlTypeName.BIGINT);
 
     assertCannotCoerce(Collections.emptyList(), SqlTypeName.BIGINT);
+    assertCannotCoerce(new byte[]{(byte) 0xe0, 0x4f}, SqlTypeName.BIGINT);
   }
 
   @Test
@@ -222,6 +224,17 @@ public class SqlResultsTest extends 
InitializedNullHandlingTest
     assertCannotCoerce(new Object(), SqlTypeName.VARCHAR);
   }
 
+  @Test
+  public void testCoerceOfArrayOfPrimitives()
+  {
+    try {
+      assertCoerce("", new byte[1], SqlTypeName.BIGINT);
+      Assert.fail("Should throw an exception");
+    }
+    catch (Exception e) {
+      Assert.assertEquals("Cannot coerce field [fieldName] from type [Byte 
Array] to type [BIGINT]", e.getMessage());
+    }
+  }
   @Test
   public void testCoerceArrayFails()
   {
@@ -251,16 +264,16 @@ public class SqlResultsTest extends 
InitializedNullHandlingTest
     Assert.assertEquals(
         StringUtils.format("Coerce [%s] to [%s]", toCoerce, typeName),
         expected,
-        SqlResults.coerce(jsonMapper, DEFAULT_CONTEXT, toCoerce, typeName)
+        SqlResults.coerce(jsonMapper, DEFAULT_CONTEXT, toCoerce, typeName, 
"fieldName")
     );
   }
 
   private void assertCannotCoerce(Object toCoerce, SqlTypeName typeName)
   {
-    final IllegalStateException e = Assert.assertThrows(
+    final DruidException e = Assert.assertThrows(
         StringUtils.format("Coerce [%s] to [%s]", toCoerce, typeName),
-        IllegalStateException.class,
-        () -> SqlResults.coerce(jsonMapper, DEFAULT_CONTEXT, toCoerce, 
typeName)
+        DruidException.class,
+        () -> SqlResults.coerce(jsonMapper, DEFAULT_CONTEXT, toCoerce, 
typeName, "")
     );
 
     MatcherAssert.assertThat(e, 
ThrowableMessageMatcher.hasMessage(CoreMatchers.containsString("Cannot 
coerce")));


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to