This is an automated email from the ASF dual-hosted git repository.
xiong 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 24cc46b191 [CALCITE-7021] Support parse 'CAST('1' AS INTERVAL)'
24cc46b191 is described below
commit 24cc46b191299ca3ca2e341ea81dd097bb8ed584
Author: Juntao Zhang <[email protected]>
AuthorDate: Tue May 20 10:31:31 2025 +0800
[CALCITE-7021] Support parse 'CAST('1' AS INTERVAL)'
---
babel/src/main/codegen/config.fmpp | 1 +
.../org/apache/calcite/test/BabelParserTest.java | 8 ++++++++
babel/src/test/resources/sql/postgresql.iq | 21 +++++++++++++++++++++
core/src/main/codegen/default_config.fmpp | 1 +
core/src/main/codegen/templates/Parser.jj | 18 ++++++++++++++++++
.../apache/calcite/sql/parser/SqlParserTest.java | 2 ++
6 files changed, 51 insertions(+)
diff --git a/babel/src/main/codegen/config.fmpp
b/babel/src/main/codegen/config.fmpp
index 981768ba9d..c41f28bd71 100644
--- a/babel/src/main/codegen/config.fmpp
+++ b/babel/src/main/codegen/config.fmpp
@@ -616,6 +616,7 @@ data: {
setOptionParserMethod: "PostgresSqlSetOption"
includePosixOperators: true
includeParsingStringLiteralAsArrayLiteral: true
+ includeIntervalWithoutQualifier: true
}
}
diff --git a/babel/src/test/java/org/apache/calcite/test/BabelParserTest.java
b/babel/src/test/java/org/apache/calcite/test/BabelParserTest.java
index 11fa5489be..a0fb721aef 100644
--- a/babel/src/test/java/org/apache/calcite/test/BabelParserTest.java
+++ b/babel/src/test/java/org/apache/calcite/test/BabelParserTest.java
@@ -52,6 +52,14 @@ class BabelParserTest extends SqlParserTest {
.withConfig(c -> c.withParserFactory(SqlBabelParserImpl.FACTORY));
}
+ /** Tests that the Babel parser correctly parses a CAST to INTERVAL type
+ * in PostgreSQL dialect. */
+ @Test void testCastToInterval() {
+ SqlParserFixture postgreF =
fixture().withDialect(PostgresqlSqlDialect.DEFAULT);
+ postgreF.sql("select cast(x as interval)")
+ .ok("SELECT CAST(\"x\" AS INTERVAL SECOND)");
+ }
+
@Test void testReservedWords() {
assertThat(isReserved("escape"), is(false));
}
diff --git a/babel/src/test/resources/sql/postgresql.iq
b/babel/src/test/resources/sql/postgresql.iq
index bc1116af2b..ef9edb7b53 100644
--- a/babel/src/test/resources/sql/postgresql.iq
+++ b/babel/src/test/resources/sql/postgresql.iq
@@ -18,6 +18,27 @@
!use scott-postgresql
!set outputformat csv
+# Test CAST INTERVAL
+select CAST('3723' AS INTERVAL HOUR TO SECOND);
+EXPR$0
++1:02:03.000000
+!ok
+
+select CAST('3721' AS INTERVAL SECOND);
+EXPR$0
++3721.000000
+!ok
+
+select CAST('2' AS INTERVAL);
+EXPR$0
++2.000000
+!ok
+
+select CAST('-3723' AS INTERVAL);
+EXPR$0
+-3723.000000
+!ok
+
# Test string and array comparison
select array[0,1,2] = '{0,1,2}';
EXPR$0
diff --git a/core/src/main/codegen/default_config.fmpp
b/core/src/main/codegen/default_config.fmpp
index f3c048bd5b..a2547273cb 100644
--- a/core/src/main/codegen/default_config.fmpp
+++ b/core/src/main/codegen/default_config.fmpp
@@ -459,4 +459,5 @@ parser: {
includeBraces: true
includeAdditionalDeclarations: false
includeParsingStringLiteralAsArrayLiteral: false
+ includeIntervalWithoutQualifier: false
}
diff --git a/core/src/main/codegen/templates/Parser.jj
b/core/src/main/codegen/templates/Parser.jj
index fa7593c194..ae367d549a 100644
--- a/core/src/main/codegen/templates/Parser.jj
+++ b/core/src/main/codegen/templates/Parser.jj
@@ -5218,6 +5218,19 @@ TimeUnit Second() :
<SECONDS> { return warn(TimeUnit.SECOND); }
}
+SqlIntervalQualifier IntervalWithoutQualifier() :
+{
+ final Span s;
+ int secondFracPrec = RelDataType.PRECISION_NOT_SPECIFIED;
+}
+{
+ {
+ s = span();
+ return new SqlIntervalQualifier(TimeUnit.SECOND, -1, null,
secondFracPrec,
+ s.end(this));
+ }
+}
+
SqlIntervalQualifier IntervalQualifier() :
{
final Span s;
@@ -6282,7 +6295,12 @@ SqlNode BuiltinFunctionCall() :
(
dt = DataType() { args.add(dt); }
|
+ LOOKAHEAD(2)
<INTERVAL> e = IntervalQualifier() { args.add(e); }
+<#if
(parser.includeIntervalWithoutQualifier!default.parser.includeIntervalWithoutQualifier)
>
+ |
+ <INTERVAL> e = IntervalWithoutQualifier() { args.add(e); }
+</#if>
)
[ <FORMAT> format = StringLiteral() { args.add(format); } ]
<RPAREN> {
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 8ef2c7601e..07dc89179e 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
@@ -7250,6 +7250,8 @@ private static Consumer<List<? extends Throwable>>
checkWarnings(
.ok("CAST(`X` AS INTERVAL MINUTE TO SECOND)");
expr("cast(interval '3-2' year to month as CHAR(5))")
.ok("CAST(INTERVAL '3-2' YEAR TO MONTH AS CHAR(5))");
+ expr("cast(x as ^interval^)")
+ .fails("(?s)Encountered \"interval \\)\".*");
}
@Test void testCastToVarchar() {