dtenedor commented on code in PR #36365: URL: https://github.com/apache/spark/pull/36365#discussion_r870575731
########## sql/catalyst/src/test/scala/org/apache/spark/sql/catalyst/expressions/StringExpressionsSuite.scala: ########## @@ -1108,6 +1125,366 @@ class StringExpressionsSuite extends SparkFunSuite with ExpressionEvalHelper { } } + test("ToCharacter: positive tests") { + // Test '0' and '9' + Seq( + (Decimal(454), + "9999") -> + " 454", + (Decimal(454), + "99999") -> + " 454", + (Decimal(4), + "0") -> + "4", + (Decimal(45), + "00") -> + "45", + (Decimal(454), + "000") -> + "454", + (Decimal(454), + "0000") -> + "0454", + (Decimal(454), + "00000") -> + "00454" + ).foreach { case ((decimal, format), expected) => + var expr: Expression = ToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + } + + // Test '.' and 'D' + Seq( + (Decimal(0.4542), + ".00000") -> + ".4542 ", + (Decimal(454.2), + "000.0") -> + "454.2", + (Decimal(454), + "000.0") -> + "454 ", + (Decimal(454.2), + "000.00") -> + "454.2 ", + (Decimal(454), + "000.00") -> + "454 ", + (Decimal(0.4542), + ".0000") -> + ".4542", + (Decimal(4542), + "0000.") -> + "4542 " + ).foreach { case ((decimal, format), expected) => + val format2 = format.replace('.', 'D') + var expr: Expression = ToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = ToCharacter(Literal(decimal), Literal(format2)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format2)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + } + + Seq( + (Decimal(454.2), + "0000.00") -> + "0454.2 ", + (Decimal(454), + "0000.00") -> + "0454 ", + (Decimal(4542), + "00000.") -> + "04542 ", + (Decimal(454.2), + "9999.99") -> + " 454.2 ", + (Decimal(454), + "9999.99") -> + " 454 ", + // There are no digits after the decimal point. + (Decimal(4542), + "99999.") -> + " 4542 " + ).foreach { case ((decimal, format), expected) => + var expr: Expression = ToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + } + + // Test ',' and 'G' + Seq( + (Decimal(12454), + "0,0000") -> + "1,2454", + (Decimal(12454), + "00,000") -> + "12,454", + (Decimal(124543), + "000,000") -> + "124,543", + (Decimal(12), + "000,000") -> + "000,012", + (Decimal(1245436), + "0,000,000") -> + "1,245,436", + (Decimal(12454367), + "00,000,000") -> + "12,454,367" + ).foreach { case ((decimal, format), expected) => + val format2 = format.replace(',', 'G') + var expr: Expression = ToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = ToCharacter(Literal(decimal), Literal(format2)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format2)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + } + + Seq( + (Decimal(12454), + "000,000") -> + "012,454", + (Decimal(12454), + "00,0000") -> + "01,2454", + (Decimal(12454), + "000,0000") -> + "001,2454", + (Decimal(12454), + "0000,0000") -> + "0001,2454", + (Decimal(12454), + "00,0000") -> + "01,2454", + (Decimal(12454), + "000,0000") -> + "001,2454", + (Decimal(12454), + "0000,0000") -> + "0001,2454", + (Decimal(12454367), + "000,000,000") -> + "012,454,367", + (Decimal(12454), + "000,000") -> + "012,454", + (Decimal(12454), + "999,999") -> + " 12,454", + (Decimal(12454), + "9,9999") -> + "1,2454", + (Decimal(12454), + "99,9999") -> + " 1,2454", + (Decimal(12454), + "999,9999") -> + " 1,2454", + (Decimal(12454), + "9999,9999") -> + " 1,2454", + (Decimal(12454367), + "999,999,999") -> + " 12,454,367", + (Decimal(12454), + "999,999") -> + " 12,454" + ).foreach { case ((decimal, format), expected) => + var expr: Expression = ToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + } + + // Test '$' + Seq( + (Decimal(78.12), + "$99.99") -> + "$78.12", + (Decimal(78.12), + "$00.00") -> + "$78.12" + ).foreach { case ((decimal, format), expected) => + var expr: Expression = ToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + } + + // Test 'S' + Seq( + (Decimal(83028485), + "S99999999999.9999999") -> + " +83028485 ", + (Decimal(0), + "9999999999999999.999999999999999S") -> + " 0+ ", + (Decimal(unscaled = 43100000000L, precision = 38, scale = 10), + "9999999999999999.999999999999999S") -> + " 4.31+ ", + (Decimal(-454.8), + "99G999.9S") -> + " 454.8-", + (Decimal(-454.8), + "00G000.0S") -> + "00,454.8-", + (Decimal(-454), + "S999") -> + "-454", + (Decimal(-454), + "999S") -> + "454-", + (Decimal(-12454.8), + "99G999D9S") -> + "12,454.8-", + (Decimal(-83028485), + "99999999999.9999999S") -> + " 83028485- " + ).foreach { case ((decimal, format), expected) => + var expr: Expression = ToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + } + + // Test 'MI' + Seq( + (Decimal(4.31), + "9999999999999999.999999999999999MI") -> + " 4.31 ", + (Decimal(0), + "9999999999999999.999999999999999MI") -> + " 0 ", + (Decimal(unscaled = 43100000000L, precision = 38, scale = 10), + "9999999999999999.999999999999999MI") -> + " 4.31 ", + (Decimal(-454.8), + "99G999.9MI") -> + " 454.8- ", + (Decimal(-454.8), + "00G000.0MI") -> + "00,454.8- ", + (Decimal(-454), + "999MI") -> + "454- ", + (Decimal(-12454.8), + "99G999D9MI") -> + "12,454.8- " + ).foreach { case ((decimal, format), expected) => + var expr: Expression = ToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + + expr = TryToCharacter(Literal(decimal), Literal(format)) + assert(expr.checkInputDataTypes() == TypeCheckResult.TypeCheckSuccess) + checkEvaluation(expr, expected) + } + + // Test 'PR' + Seq( + (Decimal(4.31), + "9999999999999999.999999999999999PR") -> + " 4.31 ", + (Decimal(0), + "9999999999999999.999999999999999PR") -> + " 0 ", + (Decimal(unscaled = 43100000000L, precision = 38, scale = 10), + "9999999999999999.999999999999999PR") -> + " 4.31 ", + (Decimal(-123), + "9999999999999999.999PR") -> + " <123> ", + (Decimal(-123.4), + "9999999999999999.999PR") -> + " <123.4> ", Review Comment: We could do that, but then the positioning of the decimal point would be inconsistent between positive and negative numbers. Consider the following examples: ``` select to_char(Decimal(8), '9PR') > ' 8 ' select to_char(Decimal(-8), '9PR') > '<8>' select to_char(Decimal(8.8), '9.9PR') > ' 8.8 ' select to_char(Decimal(-8.8), '9.9PR') > '<8.8>' ``` In these cases the result string gains two extra characters from the `PR` which can be either spaces or `<`/`>`. It looks like this is the behavior that Postgres uses as well. Thoughts? -- 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. To unsubscribe, e-mail: reviews-unsubscr...@spark.apache.org For queries about this service, please contact Infrastructure at: us...@infra.apache.org --------------------------------------------------------------------- To unsubscribe, e-mail: reviews-unsubscr...@spark.apache.org For additional commands, e-mail: reviews-h...@spark.apache.org