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

jiajunxie pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/calcite.git


The following commit(s) were added to refs/heads/main by this push:
     new f901d7d44a [CALCITE-5870] Allow literals like DECIMAL '12.3' 
(consistent with Postgres)
f901d7d44a is described below

commit f901d7d44a41e3a1db010c42dd4a422dcb31996c
Author: shenlang <shenl...@zbyte-inc.com>
AuthorDate: Tue Jul 25 20:14:07 2023 +0800

    [CALCITE-5870] Allow literals like DECIMAL '12.3' (consistent with Postgres)
---
 core/src/main/codegen/templates/Parser.jj          |  6 +++
 .../apache/calcite/sql/parser/SqlParserUtil.java   | 12 ++++++
 .../apache/calcite/sql/test/SqlAdvisorTest.java    |  1 +
 .../org/apache/calcite/test/SqlValidatorTest.java  |  2 +
 core/src/test/resources/sql/misc.iq                | 23 ++++++++++++
 site/_docs/reference.md                            |  2 +-
 .../apache/calcite/sql/parser/SqlParserTest.java   | 43 ++++++++++++++++++++++
 7 files changed, 88 insertions(+), 1 deletion(-)

diff --git a/core/src/main/codegen/templates/Parser.jj 
b/core/src/main/codegen/templates/Parser.jj
index ee9a9c02a7..6780339003 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -4447,6 +4447,7 @@ SqlNode LiteralOrIntervalExpression() :
 /** Parses a unsigned numeric literal */
 SqlNumericLiteral UnsignedNumericLiteral() :
 {
+final String p;
 }
 {
     <UNSIGNED_INTEGER_LITERAL> {
@@ -4456,6 +4457,11 @@ SqlNumericLiteral UnsignedNumericLiteral() :
     <DECIMAL_NUMERIC_LITERAL> {
         return SqlLiteral.createExactNumeric(token.image, getPos());
     }
+|
+    <DECIMAL>
+    p = SimpleStringLiteral() {
+        return SqlParserUtil.parseDecimalLiteral(SqlParserUtil.trim(p, " "), 
getPos());
+    }
 |
     <APPROX_NUMERIC_LITERAL> {
         return SqlLiteral.createApproxNumeric(token.image, getPos());
diff --git 
a/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java 
b/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
index 5f36342e81..e4b8ef2b41 100644
--- a/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
+++ b/core/src/main/java/org/apache/calcite/sql/parser/SqlParserUtil.java
@@ -325,6 +325,18 @@ public final class SqlParserUtil {
     return SqlLiteral.createDate(d, pos);
   }
 
+  public static SqlNumericLiteral parseDecimalLiteral(String s, SqlParserPos 
pos) {
+    try {
+      // The s maybe scientific notation string,e.g. 1.2E-3,
+      // we need to convert it to 0.0012
+      s = new BigDecimal(s).toPlainString();
+    } catch (NumberFormatException e) {
+      throw SqlUtil.newContextException(pos,
+          RESOURCE.invalidLiteral(s, "DECIMAL"));
+    }
+    return SqlLiteral.createExactNumeric(s, pos);
+  }
+
   public static SqlTimeLiteral parseTimeLiteral(String s, SqlParserPos pos) {
     final DateTimeUtils.PrecisionTime pt =
         DateTimeUtils.parsePrecisionDateTimeLiteral(s,
diff --git a/core/src/test/java/org/apache/calcite/sql/test/SqlAdvisorTest.java 
b/core/src/test/java/org/apache/calcite/sql/test/SqlAdvisorTest.java
index eba04ac157..f3195b3f92 100644
--- a/core/src/test/java/org/apache/calcite/sql/test/SqlAdvisorTest.java
+++ b/core/src/test/java/org/apache/calcite/sql/test/SqlAdvisorTest.java
@@ -165,6 +165,7 @@ class SqlAdvisorTest extends SqlValidatorTestCase {
           "KEYWORD(CURSOR)",
           "KEYWORD(DATE)",
           "KEYWORD(DATETIME)",
+          "KEYWORD(DECIMAL)",
           "KEYWORD(DENSE_RANK)",
           "KEYWORD(ELEMENT)",
           "KEYWORD(EVERY)",
diff --git a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java 
b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
index cb6184d65d..d068702d59 100644
--- a/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
+++ b/core/src/test/java/org/apache/calcite/test/SqlValidatorTest.java
@@ -243,6 +243,8 @@ public class SqlValidatorTest extends SqlValidatorTestCase {
         .columnType("BOOLEAN NOT NULL");
     expr("unknown")
         .columnType("BOOLEAN");
+    expr("DECIMAL '123456.7890'")
+        .columnType("DECIMAL(10, 4) NOT NULL");
   }
 
   /** Tests that date-time literals with invalid strings are considered 
invalid.
diff --git a/core/src/test/resources/sql/misc.iq 
b/core/src/test/resources/sql/misc.iq
index b868a090f1..321843c183 100644
--- a/core/src/test/resources/sql/misc.iq
+++ b/core/src/test/resources/sql/misc.iq
@@ -2520,4 +2520,27 @@ EnumerableCalc(expr#0..7=[{inputs}], 
expr#8=[CAST($t6):INTEGER], expr#9=[IS NOT
   EnumerableTableScan(table=[[scott, EMP]])
 !plan
 
+# [CALCITE-5870] Allow literals like DECIMAL '12.3' (consistent with Postgres)
+# Test a decimal value between decimal logic for range checking.
+select 12.3 between decimal '5.6' and decimal '17.8';
++--------+
+| EXPR$0 |
++--------+
+| true   |
++--------+
+(1 row)
+
+!ok
+
+# Test the decimal 'xx' + a decimal constant value case
+select decimal'12.3' + 5.6;
++--------+
+| EXPR$0 |
++--------+
+|   17.9 |
++--------+
+(1 row)
+
+!ok
+
 # End misc.iq
diff --git a/site/_docs/reference.md b/site/_docs/reference.md
index 791fce5b4f..e31ee67fd1 100644
--- a/site/_docs/reference.md
+++ b/site/_docs/reference.md
@@ -1154,7 +1154,7 @@ name will have been converted to upper case also.
 | SMALLINT    | 2 byte signed integer     | Range is -32768 to 32767
 | INTEGER, INT | 4 byte signed integer    | Range is -2147483648 to 2147483647
 | BIGINT      | 8 byte signed integer     | Range is -9223372036854775808 to 
9223372036854775807
-| DECIMAL(p, s) | Fixed point             | Example: 123.45 is a DECIMAL(5, 2) 
value.
+| DECIMAL(p, s) | Fixed point             | Example: 123.45 or DECIMAL 
'123.45' is a DECIMAL(5, 2) value.
 | NUMERIC     | Fixed point               |
 | REAL, FLOAT | 4 byte floating point     | 6 decimal digits precision
 | DOUBLE      | 8 byte floating point     | 15 decimal digits precision
diff --git 
a/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java 
b/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java
index 7cadf913bb..b1c9762649 100644
--- a/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java
+++ b/testkit/src/main/java/org/apache/calcite/sql/parser/SqlParserTest.java
@@ -907,6 +907,49 @@ public class SqlParserTest {
         .ok(expectedBigQuery);
   }
 
+  @Test void testDecimalLiteral() {
+    sql("select DECIMAL '99.999'")
+        .ok("SELECT 99.999");
+    sql("select DECIMAL '   99.999'")
+        .ok("SELECT 99.999");
+    sql("select DECIMAL '   99.999   '")
+        .ok("SELECT 99.999");
+    sql("select DECIMAL '+99.999'")
+        .ok("SELECT 99.999");
+    sql("select DECIMAL '-99.999'")
+        .ok("SELECT -99.999");
+    sql("select DECIMAL'-99.999'")
+        .ok("SELECT -99.999");
+    sql("select DECIMAL'99.999'")
+        .ok("SELECT 99.999");
+    sql("select DECIMAL'.999'")
+        .ok("SELECT 0.999");
+    sql("select DECIMAL'999.'")
+        .ok("SELECT 999");
+    sql("select DECIMAL'999'")
+        .ok("SELECT 999");
+    sql("select DECIMAL '2.11E-2'")
+        .ok("SELECT 0.0211");
+    sql("select DECIMAL '2.11E2'")
+        .ok("SELECT 211");
+    sql("select DECIMAL '.11E-2'")
+        .ok("SELECT 0.0011");
+    sql("select DECIMAL ^''^")
+        .fails("(?s)Literal '' can not be parsed to type 'DECIMAL'.*");
+    sql("select DECIMAL ^'-'^")
+        .fails("(?s)Literal '-' can not be parsed to type 'DECIMAL'.*");
+    sql("select DECIMAL ^'foo'^")
+        .fails("(?s)Literal 'foo' can not be parsed to type 'DECIMAL'.*");
+
+    // Test with bigquery
+    sql("select DECIMAL \"2.11E-2\"")
+        .withDialect(BIG_QUERY)
+        .ok("SELECT 0.0211");
+    sql("select DECIMAL \"999\"")
+        .withDialect(BIG_QUERY)
+        .ok("SELECT 999");
+  }
+
   @Test void testDerivedColumnList() {
     sql("select * from emp as e (empno, gender) where true")
         .ok("SELECT *\n"

Reply via email to