From d3ab0bc8e4d4c9ebc0fc4e33ce478d276f5d11e4 Mon Sep 17 00:00:00 2001 From: chen768959 <934103231@qq.com> Date: Fri, 1 Dec 2023 20:24:50 +0800 Subject: [PATCH] [CALCITE-6150] JDBC adapter for ClickHouse generates incorrect SQL for certain units in the EXTRACT function Close apache/calcite#3557 --- .../sql/dialect/ClickHouseSqlDialect.java | 23 +++++++ .../rel/rel2sql/RelToSqlConverterTest.java | 69 +++++++++++++++++++ 2 files changed, 92 insertions(+) diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/ClickHouseSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/ClickHouseSqlDialect.java index bd4b2a052c8..802f562c3d6 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/ClickHouseSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/ClickHouseSqlDialect.java @@ -175,6 +175,29 @@ private static SqlDataTypeSpec createSqlDataTypeSpecByName(String typeAlias, super.unparseCall(writer, call, leftPrec, rightPrec); } break; + case EXTRACT: + SqlLiteral node = call.operand(0); + TimeUnitRange unit = node.getValueAs(TimeUnitRange.class); + String funName; + switch (unit) { + case DOW: + funName = "DAYOFWEEK"; + break; + case DOY: + funName = "DAYOFYEAR"; + break; + case WEEK: + funName = "toWeek"; + break; + default: + super.unparseCall(writer, call, leftPrec, rightPrec); + return; + } + writer.print(funName); + final SqlWriter.Frame frame = writer.startList("(", ")"); + call.operand(1).unparse(writer, 0, 0); + writer.endList(frame); + break; default: super.unparseCall(writer, call, leftPrec, rightPrec); } 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 79b6b0b983e..8f10a1386ac 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 @@ -2264,6 +2264,75 @@ private SqlDialect nonOrdinalDialect() { sql(query).withLibrary(SqlLibrary.BIG_QUERY).ok(expected); } + /** Test case for + * [CALCITE-6150] + * JDBC adapter for ClickHouse generates incorrect SQL for certain units in + * the EXTRACT function. Also tests other units in other dialects. */ + @Test void testExtract() { + final String sql = "SELECT\n" + + "EXTRACT(YEAR FROM DATE '2023-12-01'),\n" + + "EXTRACT(QUARTER FROM DATE '2023-12-01'),\n" + + "EXTRACT(MONTH FROM DATE '2023-12-01'),\n" + + "EXTRACT(WEEK FROM DATE '2023-12-01'),\n" + + "EXTRACT(DOY FROM DATE '2023-12-01'),\n" + + "EXTRACT(DAY FROM DATE '2023-12-01'),\n" + + "EXTRACT(DOW FROM DATE '2023-12-01'),\n" + + "EXTRACT(HOUR FROM TIMESTAMP '2023-12-01 00:00:00'),\n" + + "EXTRACT(MINUTE FROM TIMESTAMP '2023-12-01 00:00:00'),\n" + + "EXTRACT(SECOND FROM TIMESTAMP '2023-12-01 00:00:00')"; + final String expectedClickHouse = "SELECT " + + "EXTRACT(YEAR FROM toDate('2023-12-01')), " + + "EXTRACT(QUARTER FROM toDate('2023-12-01')), " + + "EXTRACT(MONTH FROM toDate('2023-12-01')), " + + "toWeek(toDate('2023-12-01')), " + + "DAYOFYEAR(toDate('2023-12-01')), " + + "EXTRACT(DAY FROM toDate('2023-12-01')), " + + "DAYOFWEEK(toDate('2023-12-01')), " + + "EXTRACT(HOUR FROM toDateTime('2023-12-01 00:00:00')), " + + "EXTRACT(MINUTE FROM toDateTime('2023-12-01 00:00:00')), " + + "EXTRACT(SECOND FROM toDateTime('2023-12-01 00:00:00'))"; + final String expectedHive = "SELECT " + + "EXTRACT(YEAR FROM DATE '2023-12-01'), " + + "EXTRACT(QUARTER FROM DATE '2023-12-01'), " + + "EXTRACT(MONTH FROM DATE '2023-12-01'), " + + "EXTRACT(WEEK FROM DATE '2023-12-01'), " + + "EXTRACT(DOY FROM DATE '2023-12-01'), " + + "EXTRACT(DAY FROM DATE '2023-12-01'), " + + "EXTRACT(DOW FROM DATE '2023-12-01'), " + + "EXTRACT(HOUR FROM TIMESTAMP '2023-12-01 00:00:00'), " + + "EXTRACT(MINUTE FROM TIMESTAMP '2023-12-01 00:00:00'), " + + "EXTRACT(SECOND FROM TIMESTAMP '2023-12-01 00:00:00')"; + final String expectedPostgresql = "SELECT " + + "EXTRACT(YEAR FROM DATE '2023-12-01'), " + + "EXTRACT(QUARTER FROM DATE '2023-12-01'), " + + "EXTRACT(MONTH FROM DATE '2023-12-01'), " + + "EXTRACT(WEEK FROM DATE '2023-12-01'), " + + "EXTRACT(DOY FROM DATE '2023-12-01'), " + + "EXTRACT(DAY FROM DATE '2023-12-01'), " + + "EXTRACT(DOW FROM DATE '2023-12-01'), " + + "EXTRACT(HOUR FROM TIMESTAMP '2023-12-01 00:00:00'), " + + "EXTRACT(MINUTE FROM TIMESTAMP '2023-12-01 00:00:00'), " + + "EXTRACT(SECOND FROM TIMESTAMP '2023-12-01 00:00:00')\n" + + "FROM (VALUES (0)) AS \"t\" (\"ZERO\")"; + final String expectedHsqldb = "SELECT " + + "EXTRACT(YEAR FROM DATE '2023-12-01'), " + + "EXTRACT(QUARTER FROM DATE '2023-12-01'), " + + "EXTRACT(MONTH FROM DATE '2023-12-01'), " + + "EXTRACT(WEEK FROM DATE '2023-12-01'), " + + "EXTRACT(DOY FROM DATE '2023-12-01'), " + + "EXTRACT(DAY FROM DATE '2023-12-01'), " + + "EXTRACT(DOW FROM DATE '2023-12-01'), " + + "EXTRACT(HOUR FROM TIMESTAMP '2023-12-01 00:00:00'), " + + "EXTRACT(MINUTE FROM TIMESTAMP '2023-12-01 00:00:00'), " + + "EXTRACT(SECOND FROM TIMESTAMP '2023-12-01 00:00:00')\n" + + "FROM (VALUES (0)) AS t (ZERO)"; + sql(sql) + .withClickHouse().ok(expectedClickHouse) + .withHive().ok(expectedHive) + .withPostgresql().ok(expectedPostgresql) + .withHsqldb().ok(expectedHsqldb); + } + /** Test case for * [CALCITE-3220] * HiveSqlDialect should transform the SQL-standard TRIM function to TRIM,