Skip to content

Commit c478e38

Browse files
xuzifu666iwanttobepowerful
authored andcommitted
[CALCITE-7323] Result of cast Number to Boolean is not correct
1 parent 0fe52b0 commit c478e38

File tree

7 files changed

+88
-1
lines changed

7 files changed

+88
-1
lines changed

core/src/main/java/org/apache/calcite/adapter/enumerable/RexToLixTranslator.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -428,6 +428,20 @@ private Expression getConvertExpression(
428428
case CHAR:
429429
case VARCHAR:
430430
return Expressions.call(BuiltInMethod.STRING_TO_BOOLEAN.method, operand);
431+
// Numberic type handle
432+
case TINYINT:
433+
case SMALLINT:
434+
case INTEGER:
435+
case BIGINT:
436+
case UTINYINT:
437+
case USMALLINT:
438+
case UINTEGER:
439+
case UBIGINT:
440+
case DECIMAL:
441+
case FLOAT:
442+
case REAL:
443+
case DOUBLE:
444+
return Expressions.call(BuiltInMethod.NUMBER_TO_BOOLEAN.method, operand);
431445

432446
default:
433447
return defaultExpression.get();

core/src/main/java/org/apache/calcite/runtime/SqlFunctions.java

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4735,6 +4735,18 @@ public static boolean toBoolean(String s) {
47354735
}
47364736

47374737
public static boolean toBoolean(Number number) {
4738+
if (number instanceof BigDecimal) {
4739+
BigDecimal decimal = (BigDecimal) number;
4740+
return decimal.compareTo(BigDecimal.ZERO) != 0;
4741+
}
4742+
if (number instanceof Double) {
4743+
Double d = (Double) number;
4744+
return !d.equals(Double.valueOf(0));
4745+
}
4746+
if (number instanceof Float) {
4747+
Float f = (Float) number;
4748+
return !f.equals(Float.valueOf(0));
4749+
}
47384750
return !number.equals(0);
47394751
}
47404752

core/src/main/java/org/apache/calcite/util/BuiltInMethod.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -682,6 +682,7 @@ public enum BuiltInMethod {
682682
"getModifiableCollection"),
683683
SCANNABLE_TABLE_SCAN(ScannableTable.class, "scan", DataContext.class),
684684
STRING_TO_BOOLEAN(SqlFunctions.class, "toBoolean", String.class),
685+
NUMBER_TO_BOOLEAN(SqlFunctions.class, "toBoolean", Number.class),
685686
INTERNAL_TO_DATE(SqlFunctions.class, "internalToDate", int.class),
686687
INTERNAL_TO_TIME(SqlFunctions.class, "internalToTime", int.class),
687688
INTERNAL_TO_TIMESTAMP(SqlFunctions.class, "internalToTimestamp", long.class),

core/src/test/java/org/apache/calcite/rel/rel2sql/RelToSqlConverterTest.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -771,6 +771,10 @@ private static String toSql(RelNode root, SqlDialect dialect,
771771
query = "select FALSE = 0.0e0";
772772
expected = "SELECT *\nFROM (VALUES (TRUE)) AS \"t\" (\"EXPR$0\")";
773773
sql(query).ok(expected);
774+
775+
query = "select cast(\"product_id\" as BOOLEAN) from \"product\"";
776+
expected = "SELECT \"product_id\" <> 0\nFROM \"foodmart\".\"product\"";
777+
sql(query).ok(expected);
774778
}
775779

776780
@Test void testSelectQueryWithWhereClauseOfBasicOperators() {

core/src/test/java/org/apache/calcite/rex/RexProgramTest.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3152,7 +3152,9 @@ private SqlOperator getNoDeterministicOperator() {
31523152
checkSimplify(cast(literal(1), varcharType), "'1':VARCHAR(10)");
31533153
checkSimplifyUnchanged(cast(literalAbc, booleanType));
31543154
checkSimplify(cast(literal(1), booleanType),
3155-
"false"); // different from Hive
3155+
"true");
3156+
checkSimplify(cast(literal(0), booleanType),
3157+
"false");
31563158
checkSimplifyUnchanged(cast(literalAbc, dateType));
31573159
checkSimplify(cast(literal(1), dateType),
31583160
"1970-01-02"); // different from Hive

core/src/test/resources/sql/cast.iq

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1978,4 +1978,28 @@ SELECT ARRAY[cast(null as integer), cast(null as integer), cast(null as integer)
19781978
EXPR$0 INTEGER ARRAY NOT NULL
19791979
!type
19801980

1981+
# [CALCITE-7323] Result of cast Number to Boolean is not correct
1982+
select cast(mod(deptno, 3) as BOOLEAN), mod(deptno, 3) from emp;
1983+
+--------+--------+
1984+
| EXPR$0 | EXPR$1 |
1985+
+--------+--------+
1986+
| false | 0 |
1987+
| false | 0 |
1988+
| false | 0 |
1989+
| false | 0 |
1990+
| false | 0 |
1991+
| false | 0 |
1992+
| true | 1 |
1993+
| true | 1 |
1994+
| true | 1 |
1995+
| true | 2 |
1996+
| true | 2 |
1997+
| true | 2 |
1998+
| true | 2 |
1999+
| true | 2 |
2000+
+--------+--------+
2001+
(14 rows)
2002+
2003+
!ok
2004+
19812005
# End cast.iq

testkit/src/main/java/org/apache/calcite/test/SqlOperatorTest.java

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -825,6 +825,36 @@ void testCastToExactNumeric(CastType castType, SqlOperatorFixture f) {
825825
f.checkNull("CAST(CAST(NULL AS VARCHAR) AS VARBINARY)");
826826
}
827827

828+
/**
829+
* Test case for <a href="https://issues.apache.org/jira/browse/CALCITE-7323">
830+
* Result of cast Number to Boolean is not correct</a>. */
831+
@Test public void testNumbericBooleanCast() {
832+
SqlOperatorFixture f = fixture();
833+
f.setFor(SqlStdOperatorTable.MAX, VM_EXPAND);
834+
String[] values = {"0", "CAST(null AS INTEGER)", "2", "2"};
835+
f.checkAgg("cast(max(x) as BOOLEAN)", values, isSingle(true));
836+
String[] values1 = {"0", "CAST(null AS INTEGER)", "0", "-2"};
837+
f.checkAgg("cast(max(x) as BOOLEAN)", values1, isSingle(false));
838+
f.checkScalar("CAST(1 AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
839+
f.checkScalar("CAST(2 AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
840+
f.checkScalar("CAST(abs(2) AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
841+
f.checkScalar("CAST(abs(0) AS BOOLEAN)", "false", "BOOLEAN NOT NULL");
842+
f.checkScalar("CAST(-1 AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
843+
f.checkScalar("CAST(1.2 AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
844+
f.checkScalar("CAST(CAST(100.5e0 AS DECIMAL(4, 1)) AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
845+
f.checkScalar("CAST(0 AS BOOLEAN)", "false", "BOOLEAN NOT NULL");
846+
f.checkScalar("CAST(0.0 AS BOOLEAN)", "false", "BOOLEAN NOT NULL");
847+
f.checkScalar("CAST(0.0e0 AS BOOLEAN)", "false", "BOOLEAN NOT NULL");
848+
f.checkScalar("CAST(0.01e0 AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
849+
f.checkScalar("CAST(0e0 AS BOOLEAN)", "false", "BOOLEAN NOT NULL");
850+
f.checkScalar("CAST(-0e0 AS BOOLEAN)", "false", "BOOLEAN NOT NULL");
851+
f.checkNull("CAST(NULL AS BOOLEAN)");
852+
f.checkScalar("CAST(CAST(1.2 AS FLOAT) AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
853+
f.checkScalar("CAST(CAST(1.2 AS Double) AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
854+
f.checkScalar("CAST(cast(1 as INTEGER UNSIGNED) AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
855+
f.checkScalar("CAST(cast(1 as TINYINT UNSIGNED) AS BOOLEAN)", "true", "BOOLEAN NOT NULL");
856+
}
857+
828858
@ParameterizedTest
829859
@MethodSource("safeParameters")
830860
void testCastStringToDecimal(CastType castType, SqlOperatorFixture f) {

0 commit comments

Comments
 (0)