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 <[email protected]>
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"