AngersZhuuuu commented on a change in pull request #32940:
URL: https://github.com/apache/spark/pull/32940#discussion_r654484165



##########
File path: 
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/IntervalUtils.scala
##########
@@ -108,18 +108,22 @@ object IntervalUtils {
 
   def castStringToYMInterval(
       input: UTF8String,
-      // TODO(SPARK-35768): Take into account year-month interval fields in 
cast
       startField: Byte,
       endField: Byte): Int = {
+
+    def truncatedMonth(month: String) : String = {
+      if (endField == YearMonthIntervalType.YEAR) "0" else month
+    }
+
     input.trimAll().toString match {
-      case yearMonthRegex("-", year, month) => toYMInterval(year, month, -1)
-      case yearMonthRegex(_, year, month) => toYMInterval(year, month, 1)
+      case yearMonthRegex("-", year, month) => toYMInterval(year, 
truncatedMonth(month), -1)
+      case yearMonthRegex(_, year, month) => toYMInterval(year, 
truncatedMonth(month), 1)
       case yearMonthLiteralRegex(firstSign, secondSign, year, month) =>
         (firstSign, secondSign) match {
-          case ("-", "-") => toYMInterval(year, month, 1)
-          case ("-", _) => toYMInterval(year, month, -1)
-          case (_, "-") => toYMInterval(year, month, -1)
-          case (_, _) => toYMInterval(year, month, 1)
+          case ("-", "-") => toYMInterval(year, truncatedMonth(month), 1)
+          case ("-", _) => toYMInterval(year, truncatedMonth(month), -1)
+          case (_, "-") => toYMInterval(year, truncatedMonth(month), -1)
+          case (_, _) => toYMInterval(year, truncatedMonth(month), 1)
         }
       case _ => throw new IllegalArgumentException(

Review comment:
       > Could you change the error message, please. It should reflect 
`startField` and `endField`.
   
   How about current?

##########
File path: 
sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuite.scala
##########
@@ -651,4 +652,54 @@ class CastSuite extends CastSuiteBase {
         checkEvaluation(cast(cast(interval, StringType), 
YearMonthIntervalType()), period)
       }
   }
+
+  test("SPARK-35768: Take into account year-month interval fields in cast") {
+    checkEvaluation(cast(Literal.create("1-1"),
+      YearMonthIntervalType(YEAR, YEAR)), 12)
+    checkEvaluation(cast(Literal.create("1-1"),
+      YearMonthIntervalType(YEAR, MONTH)), 13)
+    checkEvaluation(cast(Literal.create("1-1"),
+      YearMonthIntervalType(MONTH, MONTH)), 13)
+    checkEvaluation(cast(Literal.create("-1-1"),
+      YearMonthIntervalType(YEAR, YEAR)), -12)
+    checkEvaluation(cast(Literal.create("-1-1"),
+      YearMonthIntervalType(YEAR, MONTH)), -13)
+    checkEvaluation(cast(Literal.create("-1-1"),
+      YearMonthIntervalType(MONTH, MONTH)), -13)
+
+    checkEvaluation(cast(Literal.create("INTERVAL '1-1' YEAR TO MONTH"),

Review comment:
       Done

##########
File path: 
sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/CastSuite.scala
##########
@@ -651,4 +652,54 @@ class CastSuite extends CastSuiteBase {
         checkEvaluation(cast(cast(interval, StringType), 
YearMonthIntervalType()), period)
       }
   }
+
+  test("SPARK-35768: Take into account year-month interval fields in cast") {

Review comment:
       Done

##########
File path: 
sql/catalyst/src/main/scala/org/apache/spark/sql/catalyst/util/IntervalUtils.scala
##########
@@ -103,27 +103,45 @@ object IntervalUtils {
 
   private val yearMonthPatternString = "([+|-])?(\\d+)-(\\d+)"
   private val yearMonthRegex = (s"^$yearMonthPatternString$$").r
+  private val yearYearLiteralRegex =
+    (s"(?i)^INTERVAL\\s+([+|-])?'$yearMonthPatternString'\\s+YEAR$$").r
   private val yearMonthLiteralRegex =
     
(s"(?i)^INTERVAL\\s+([+|-])?'$yearMonthPatternString'\\s+YEAR\\s+TO\\s+MONTH$$").r
+  private val monthMonthLiteralRegex =
+    (s"(?i)^INTERVAL\\s+([+|-])?'$yearMonthPatternString'\\s+MONTH$$").r
 
   def castStringToYMInterval(
       input: UTF8String,
-      // TODO(SPARK-35768): Take into account year-month interval fields in 
cast
       startField: Byte,
       endField: Byte): Int = {
+
+    def truncatedMonth(month: String) : String = {
+      if (endField == YearMonthIntervalType.YEAR) "0" else month
+    }
+
+    def getSigh(firstSign: String, secondSign: String): Int = {
+      (firstSign, secondSign) match {
+        case ("-", "-") => 1
+        case ("-", _) => -1
+        case (_, "-") => -1
+        case (_, _) => 1
+      }
+    }
+
     input.trimAll().toString match {
-      case yearMonthRegex("-", year, month) => toYMInterval(year, month, -1)
-      case yearMonthRegex(_, year, month) => toYMInterval(year, month, 1)
+      case yearMonthRegex("-", year, month) => toYMInterval(year, 
truncatedMonth(month), -1)
+      case yearMonthRegex(_, year, month) => toYMInterval(year, 
truncatedMonth(month), 1)
+      case yearYearLiteralRegex(firstSign, secondSign, year, _) =>
+        toYMInterval(year, "0", getSigh(firstSign, secondSign))

Review comment:
       @MaxGekk  Is the logic right here?




-- 
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]



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

Reply via email to