This is an automated email from the ASF dual-hosted git repository. jbalint pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/calcite.git
commit 35c879044c3a1178760009fae0dd583e79856371 Author: Aymeric <ayme...@firebolt.io> AuthorDate: Wed Jul 27 17:04:23 2022 +0100 [CALCITE-5217] Improve support for INTERVAL qualifier for Firebolt --- .../calcite/sql/dialect/FireboltSqlDialect.java | 44 ++++++++++++++++++++-- .../calcite/rel/rel2sql/RelToSqlConverterTest.java | 22 ++++++++--- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/FireboltSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/FireboltSqlDialect.java index d76e902a27..0f005bd307 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/FireboltSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/FireboltSqlDialect.java @@ -16,14 +16,17 @@ */ package org.apache.calcite.sql.dialect; +import org.apache.calcite.avatica.util.TimeUnit; import org.apache.calcite.avatica.util.TimeUnitRange; import org.apache.calcite.config.NullCollation; import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.rel.type.RelDataTypeSystem; import org.apache.calcite.sql.SqlAlienSystemTypeNameSpec; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlDataTypeSpec; import org.apache.calcite.sql.SqlDialect; import org.apache.calcite.sql.SqlIntervalLiteral; +import org.apache.calcite.sql.SqlIntervalQualifier; import org.apache.calcite.sql.SqlKind; import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; @@ -202,17 +205,52 @@ public class FireboltSqlDialect extends SqlDialect { } } + /** Firebolt interval syntax: sign INTERVAL int64 time_unit. */ @Override public void unparseSqlIntervalLiteral(SqlWriter writer, SqlIntervalLiteral literal, int leftPrec, int rightPrec) { SqlIntervalLiteral.IntervalValue interval = literal.getValueAs(SqlIntervalLiteral.IntervalValue.class); writer.keyword("INTERVAL"); writer.print("'"); - if (interval.getSign() == -1) { - writer.print("-"); + try { + Long.parseLong(interval.getIntervalLiteral()); + } catch (NumberFormatException e) { + throw new RuntimeException("Only INT64 is supported as the interval value for Firebolt."); } writer.literal(interval.getIntervalLiteral()); - writer.print(interval.getIntervalQualifier().toString()); + unparseSqlIntervalQualifier(writer, interval.getIntervalQualifier(), + RelDataTypeSystem.DEFAULT); writer.print("'"); } + + @Override public void unparseSqlIntervalQualifier( + SqlWriter writer, SqlIntervalQualifier qualifier, RelDataTypeSystem typeSystem) { + final String start = validate(qualifier.timeUnitRange.startUnit).name(); + if (qualifier.timeUnitRange.endUnit == null) { + writer.keyword(start); + } else { + throw new RuntimeException("Range time unit is not supported for Firebolt."); + } + } + + private static TimeUnit validate(TimeUnit timeUnit) { + switch (timeUnit) { + case MICROSECOND: + case MILLISECOND: + case SECOND: + case MINUTE: + case HOUR: + case DAY: + case WEEK: + case MONTH: + case YEAR: + case DECADE: + case CENTURY: + case MILLENNIUM: + return timeUnit; + default: + throw new RuntimeException("Time unit " + timeUnit + " is not supported for Firebolt."); + } + } + } diff --git a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java index 05ef6e03c4..0cbda44c6b 100644 --- a/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java +++ b/core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java @@ -4005,15 +4005,27 @@ class RelToSqlConverterTest { } @Test void testUnparseSqlIntervalQualifierFirebolt() { - final String sql = "select * from \"employee\" where \"hire_date\" + " - + "INTERVAL '10' HOUR > TIMESTAMP '2005-10-17 00:00:00' "; + final String sql0 = "select * from \"employee\" where \"hire_date\" - " + + "INTERVAL '19800' SECOND(5) > TIMESTAMP '2005-10-17 00:00:00' "; + final String expect0 = "SELECT *\n" + + "FROM \"foodmart\".\"employee\"\n" + + "WHERE (\"hire_date\" - INTERVAL '19800 SECOND ')" + + " > TIMESTAMP '2005-10-17 00:00:00'"; + sql(sql0).withFirebolt().ok(expect0); - final String expect = "SELECT *\n" + final String sql1 = "select * from \"employee\" where \"hire_date\" + " + + "INTERVAL '10' HOUR > TIMESTAMP '2005-10-17 00:00:00' "; + final String expect1 = "SELECT *\n" + "FROM \"foodmart\".\"employee\"\n" - + "WHERE (\"hire_date\" + INTERVAL '10 HOUR')" + + "WHERE (\"hire_date\" + INTERVAL '10 HOUR ')" + " > TIMESTAMP '2005-10-17 00:00:00'"; - sql(sql).withFirebolt().ok(expect); + sql(sql1).withFirebolt().ok(expect1); + + final String sql2 = "select * from \"employee\" where \"hire_date\" + " + + "INTERVAL '1 2:34:56.78' DAY TO SECOND > TIMESTAMP '2005-10-17 00:00:00' "; + sql(sql2).withFirebolt().throws_("Only INT64 is supported as the interval value for Firebolt."); } + @Test void testFloorMysqlWeek() { String query = "SELECT floor(\"hire_date\" TO WEEK) FROM \"employee\""; String expected = "SELECT STR_TO_DATE(DATE_FORMAT(`hire_date` , '%x%v-1'), '%x%v-%w')\n"