maropu commented on a change in pull request #28106: [SPARK-31335][SQL] Add try 
function support
URL: https://github.com/apache/spark/pull/28106#discussion_r407342553
 
 

 ##########
 File path: 
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/expressions/misc.scala
 ##########
 @@ -198,3 +201,69 @@ case class TypeOf(child: Expression) extends 
UnaryExpression {
     defineCodeGen(ctx, ev, _ => 
s"""UTF8String.fromString(${child.dataType.catalogString})""")
   }
 }
+
+// scalastyle:off line.size.limit
+@ExpressionDescription(
+  usage = """
+    _FUNC_(expr) - Evaluate an expression and handle certain types of 
execution errors by returning NULL.
+    In cases where it is preferable that queries produce NULL instead of 
failing when corrupt or invalid data is encountered, the TRY function may be 
useful, especially when ANSI mode is on and the users need null-tolerant on 
certain columns or outputs.
+    AnalysisExceptions will not be handled by this, typically errors handled 
by TRY function are:
+
+      * Division by zero,
+      * Invalid casting,
+      * Numeric value out of range,
+      * e.t.c
+  """,
+  examples = """
+      Examples:
+      > SELECT _FUNC_(1 / 0);
+       NULL
+  """,
+  since = "3.1.0")
+// scalastyle:on line.size.limit
+case class TryExpression(child: Expression) extends UnaryExpression {
+
+  override def nullable: Boolean = true
+  override def dataType: DataType = child.dataType
+  override def prettyName: String = "try"
+
+  override def eval(input: InternalRow): Any = {
+    try {
+      child.eval(input)
+    } catch {
+      case e if TryExpression.canSuppress(e) => null
+    }
+  }
+
+  override def doGenCode(ctx: CodegenContext, ev: ExprCode): ExprCode = {
+    val eval = child.genCode(ctx)
+    val javaType = CodeGenerator.javaType(dataType)
+    ev.copy(code =
+      code"""
+        boolean ${ev.isNull} = false;
+        $javaType ${ev.value} = ${CodeGenerator.defaultValue(dataType)};
+        try {
+          ${eval.code}
+          ${ev.isNull} = ${eval.isNull};
+          ${ev.value} = ${eval.value};
+        } catch (java.lang.Exception e) {
+          if 
(org.apache.spark.sql.catalyst.expressions.TryExpression.canSuppress(e)) {
+            ${ev.isNull} = true;
+          } else {
+            throw e;
+          }
+        }""")
+  }
+}
+
+object TryExpression {
+
+  def canSuppress(e: Throwable): Boolean = e match {
+    case _: IllegalArgumentException |
+         _: ArithmeticException |
+         _: DateTimeException |
+         _: NumberFormatException |
+         _: UnsupportedEncodingException => true
 
 Review comment:
   Ah, I see. Could you leave some comments here about the non-handled cases?

----------------------------------------------------------------
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
 
For queries about this service, please contact Infrastructure at:
[email protected]


With regards,
Apache Git Services

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

Reply via email to