This is an automated email from the ASF dual-hosted git repository. jhyde pushed a commit to branch main in repository https://gitbox.apache.org/repos/asf/calcite.git
commit 97d62ac73a8f635d07b8672f1d96990855ab7d3c Author: Nitish Kumar <[email protected]> AuthorDate: Tue Jun 4 17:40:20 2024 +0530 [CALCITE-6414] JDBC adapter should generate BOOLOR_AGG, BOOLAND_AGG for MAX, MIN on BOOLEAN values in Snowflake dialect Close apache/calcite#3812 --- .../calcite/sql/dialect/SnowflakeSqlDialect.java | 32 ++++++++++++++++++++++ .../calcite/rel/rel2sql/RelToSqlConverterTest.java | 5 ++++ 2 files changed, 37 insertions(+) diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/SnowflakeSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/SnowflakeSqlDialect.java index 9b38821202..9686a9ec1b 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/SnowflakeSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/SnowflakeSqlDialect.java @@ -17,11 +17,17 @@ package org.apache.calcite.sql.dialect; import org.apache.calcite.avatica.util.Casing; +import org.apache.calcite.rel.type.RelDataType; +import org.apache.calcite.sql.SqlBasicCall; import org.apache.calcite.sql.SqlCall; import org.apache.calcite.sql.SqlDialect; +import org.apache.calcite.sql.SqlKind; +import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlWriter; import org.apache.calcite.sql.fun.SqlLibraryOperators; import org.apache.calcite.sql.parser.SqlParserPos; +import org.apache.calcite.sql.type.SqlTypeName; /** * A <code>SqlDialect</code> implementation for the Snowflake database. @@ -73,6 +79,32 @@ public class SnowflakeSqlDialect extends SqlDialect { } } + @Override public SqlNode rewriteMaxMinExpr(SqlNode aggCall, RelDataType relDataType) { + return rewriteMaxMin(aggCall, relDataType); + } + + /** + * Helper for rewrites of MAX/MIN. + * Snowflake, rewrite as + * BOOLOR_AGG/BOOLAND_AGG if the return type is BOOLEAN. + */ + public static SqlNode rewriteMaxMin(SqlNode aggCall, RelDataType relDataType) { + // The behavior of this method depends on the argument type, + // and whether it is MIN/MAX + final SqlTypeName type = relDataType.getSqlTypeName(); + final boolean isMax = aggCall.getKind() == SqlKind.MAX; + // If the type is BOOLEAN, create a new call to the correct operator + if (type == SqlTypeName.BOOLEAN) { + final SqlOperator op = + isMax ? SqlLibraryOperators.BOOLOR_AGG + : SqlLibraryOperators.BOOLAND_AGG; + final SqlNode operand = ((SqlBasicCall) aggCall).operand(0); + return op.createCall(SqlParserPos.ZERO, operand); + } + // Otherwise, just return as it arrived + return aggCall; + } + @Override public boolean supportsApproxCountDistinct() { return true; } 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 1e8da43a2f..af4ff86794 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 @@ -6968,10 +6968,15 @@ class RelToSqlConverterTest { + "BOOL_AND(\"brand_name\" = 'a'), " + "MIN(\"brand_name\")\n" + "FROM \"foodmart\".\"product\""; + final String expectedSnowflake = "SELECT BOOLOR_AGG(\"brand_name\" = 'a'), " + + "BOOLAND_AGG(\"brand_name\" = 'a'), " + + "MIN(\"brand_name\")\n" + + "FROM \"foodmart\".\"product\""; sql(query) .ok(expected) .withBigQuery().ok(expectedBigQuery) .withPostgresql().ok(expectedPostgres) + .withSnowflake().ok(expectedSnowflake) .withRedshift().ok(expectedPostgres); }
