diff --git a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java index b0a2a00a0c2c..67236d9c7456 100644 --- a/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java +++ b/core/src/main/java/org/apache/calcite/runtime/CalciteResource.java @@ -612,6 +612,9 @@ ExInst intervalFractionalSecondPrecisionOutOfRange( @BaseMessage("Argument to function ''{0}'' must not be NULL") ExInst argumentMustNotBeNull(String a0); + @BaseMessage("At least one argument to function ''{0}'' must not be NULL") + ExInst atLeastOneArgumentMustNotBeNull(String a0); + @BaseMessage("Illegal use of ''NULL''") ExInst nullIllegal(); diff --git a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java index 3860ad6122fc..2be1800acc6f 100644 --- a/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java +++ b/core/src/main/java/org/apache/calcite/sql/fun/SqlStdOperatorTable.java @@ -1201,7 +1201,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable { */ public static final SqlFunction BITAND = SqlBasicFunction.create("BITAND", SqlKind.BITAND, - ReturnTypes.LARGEST_INT_OR_FIRST_NON_NULL_DEFAULT_INTEGER, + ReturnTypes.LARGEST_INT_OR_FIRST_NON_NULL, OperandTypes.INTEGER_INTEGER.or(OperandTypes.BINARY_BINARY)); /** @@ -1209,7 +1209,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable { */ public static final SqlFunction BITOR = SqlBasicFunction.create("BITOR", SqlKind.BITOR, - ReturnTypes.LARGEST_INT_OR_FIRST_NON_NULL_DEFAULT_INTEGER, + ReturnTypes.LARGEST_INT_OR_FIRST_NON_NULL, OperandTypes.INTEGER_INTEGER.or(OperandTypes.BINARY_BINARY)); /** @@ -1217,7 +1217,7 @@ public class SqlStdOperatorTable extends ReflectiveSqlOperatorTable { */ public static final SqlFunction BITXOR = SqlBasicFunction.create("BITXOR", SqlKind.BITXOR, - ReturnTypes.LARGEST_INT_OR_FIRST_NON_NULL_DEFAULT_INTEGER, + ReturnTypes.LARGEST_INT_OR_FIRST_NON_NULL, OperandTypes.INTEGER_INTEGER.or(OperandTypes.BINARY_BINARY)); /** diff --git a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java index c6b52061df1a..e2e4c2fb5f87 100644 --- a/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java +++ b/core/src/main/java/org/apache/calcite/sql/type/ReturnTypes.java @@ -621,7 +621,7 @@ public static SqlCall stripSeparator(SqlCall call) { * As a fallback, choose the type of the first argument that is not of the NULL type. * Nullable if at least one argument is nullable. */ - public static final SqlReturnTypeInference LARGEST_INT_OR_FIRST_NON_NULL_DEFAULT_INTEGER = + public static final SqlReturnTypeInference LARGEST_INT_OR_FIRST_NON_NULL = opBinding -> { final RelDataTypeFactory typeFactory = opBinding.getTypeFactory(); RelDataType largestIntegerType = null; @@ -646,8 +646,9 @@ public static SqlCall stripSeparator(SqlCall call) { } else if (firstNonNullType != null) { return typeFactory.createTypeWithNullability(firstNonNullType, nullable); } - return typeFactory.createTypeWithNullability( - typeFactory.createSqlType(SqlTypeName.INTEGER), true); + throw opBinding.newError( + RESOURCE.atLeastOneArgumentMustNotBeNull( + opBinding.getOperator().getName())); }; /** diff --git a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties index c860c001652e..55bf0ba73c3b 100644 --- a/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties +++ b/core/src/main/resources/org/apache/calcite/runtime/CalciteResource.properties @@ -206,6 +206,7 @@ ArgumentMustBeNumericLiteralInRange=Argument to function ''{0}'' must be a numer ValidationError=Validation Error: {0} IllegalLocaleFormat=Locale ''{0}'' in an illegal format ArgumentMustNotBeNull=Argument to function ''{0}'' must not be NULL +AtLeastOneArgumentMustNotBeNull=At least one argument to function ''{0}'' must not be NULL NullIllegal=Illegal use of ''NULL'' DynamicParamIllegal=Illegal use of dynamic parameter InvalidBoolean=''{0}'' is not a valid boolean value diff --git a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java index 5ceb157e2b9d..3a04c8f6bb12 100644 --- a/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java +++ b/testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java @@ -15512,7 +15512,9 @@ private static void checkLogicalOrFunc(SqlOperatorFixture f) { false); f.checkNull("bitand(NULL, 1)"); f.checkNull("bitand(1, NULL)"); - f.checkNull("bitand(NULL, NULL)"); + f.checkFails("^bitand(NULL, NULL)^", + "At least one argument to function 'BITAND' must not be NULL", + false); f.checkFails("bitand(CAST(x'0201' AS VARBINARY), CAST(x'02' AS VARBINARY))", "Different length for bitwise operands: the first: 2, the second: 1", true); @@ -15552,7 +15554,9 @@ private static void checkLogicalOrFunc(SqlOperatorFixture f) { false); f.checkNull("bitor(NULL, 1)"); f.checkNull("bitor(1, NULL)"); - f.checkNull("bitor(NULL, NULL)"); + f.checkFails("^bitor(NULL, NULL)^", + "At least one argument to function 'BITOR' must not be NULL", + false); f.checkFails("bitor(CAST(x'0201' AS VARBINARY), CAST(x'02' AS VARBINARY))", "Different length for bitwise operands: the first: 2, the second: 1", true); @@ -15592,7 +15596,9 @@ private static void checkLogicalOrFunc(SqlOperatorFixture f) { false); f.checkNull("bitxor(NULL, 1)"); f.checkNull("bitxor(1, NULL)"); - f.checkNull("bitxor(NULL, NULL)"); + f.checkFails("^bitxor(NULL, NULL)^", + "At least one argument to function 'BITXOR' must not be NULL", + false); f.checkFails("bitxor(CAST(x'0201' AS VARBINARY), CAST(x'02' AS VARBINARY))", "Different length for bitwise operands: the first: 2, the second: 1", true);