diff --git a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java index 964fa03f8f91..979ed20cb111 100644 --- a/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java +++ b/core/src/main/java/org/apache/calcite/sql/dialect/MssqlSqlDialect.java @@ -35,8 +35,6 @@ import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlNode; import org.apache.calcite.sql.SqlNodeList; -import org.apache.calcite.sql.SqlOperator; -import org.apache.calcite.sql.SqlSyntax; import org.apache.calcite.sql.SqlUtil; import org.apache.calcite.sql.SqlWriter; import org.apache.calcite.sql.fun.SqlLibraryOperators; @@ -49,6 +47,7 @@ import org.checkerframework.checker.nullness.qual.Nullable; import static org.apache.calcite.util.RelToSqlConverterUtil.unparseBoolLiteralToCondition; +import static org.apache.calcite.util.RelToSqlConverterUtil.unparseWithBinaryOperator; import static java.util.Objects.requireNonNull; @@ -222,8 +221,8 @@ private static SqlNode createDatetimeCastSpec(String typeAlias, RelDataType type unparseFloor(writer, call); break; case MOD: - SqlOperator op = SqlStdOperatorTable.PERCENT_REMAINDER; - SqlSyntax.BINARY.unparse(writer, op, call, leftPrec, rightPrec); + unparseWithBinaryOperator(writer, SqlStdOperatorTable.PERCENT_REMAINDER, call, + leftPrec, rightPrec); break; case SAFE_CAST: // MSSQL uses TRY_CAST instead of SAFE_CAST (BigQuery) diff --git a/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java b/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java index db417179afc3..9041dbecd163 100644 --- a/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java +++ b/core/src/main/java/org/apache/calcite/util/RelToSqlConverterUtil.java @@ -31,7 +31,9 @@ import org.apache.calcite.sql.SqlLiteral; import org.apache.calcite.sql.SqlMapTypeNameSpec; import org.apache.calcite.sql.SqlNode; +import org.apache.calcite.sql.SqlOperator; import org.apache.calcite.sql.SqlSpecialOperator; +import org.apache.calcite.sql.SqlSyntax; import org.apache.calcite.sql.SqlTypeNameSpec; import org.apache.calcite.sql.SqlWriter; import org.apache.calcite.sql.fun.SqlStdOperatorTable; @@ -339,6 +341,26 @@ public static void unparseBoolLiteralToCondition(SqlWriter writer, boolean value writer.endList(frame); } + /** + * Writes a two-operand call with an operator other than its own, + * parenthesized as that operator requires. + * + *
{@link SqlCall#unparse} chooses the parentheses from the call's own
+ * operator before the dialect is consulted, so an operator that binds less
+ * tightly needs them added here.
+ */
+ public static void unparseWithBinaryOperator(SqlWriter writer, SqlOperator operator,
+ SqlCall call, int leftPrec, int rightPrec) {
+ if (leftPrec > operator.getLeftPrec()
+ || (operator.getRightPrec() <= rightPrec && rightPrec != 0)) {
+ final SqlWriter.Frame frame = writer.startList("(", ")");
+ SqlSyntax.BINARY.unparse(writer, operator, call, 0, 0);
+ writer.endList(frame);
+ } else {
+ SqlSyntax.BINARY.unparse(writer, operator, call, leftPrec, rightPrec);
+ }
+ }
+
/**
* Transformation Map type from {@code MAP