Skip to content

Commit 3907fcd

Browse files
authored
fix: cast numeric to boolean and and/or only has Null on one side (#142)
* fix: cast numeric to boolean and `and/or` only has Null on one side * code fmt
1 parent 4989ba2 commit 3907fcd

File tree

5 files changed

+138
-9
lines changed

5 files changed

+138
-9
lines changed

src/expression/value_compute.rs

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -469,19 +469,19 @@ impl DataValue {
469469

470470
match op {
471471
BinaryOperator::And => {
472-
let value = if let (Some(v1), Some(v2)) = (left_value, right_value) {
473-
Some(v1 && v2)
474-
} else {
475-
None
472+
let value = match (left_value, right_value) {
473+
(Some(v1), Some(v2)) => Some(v1 && v2),
474+
(Some(false), _) | (_, Some(false)) => Some(false),
475+
_ => None,
476476
};
477477

478478
DataValue::Boolean(value)
479479
}
480480
BinaryOperator::Or => {
481-
let value = if let (Some(v1), Some(v2)) = (left_value, right_value) {
482-
Some(v1 || v2)
483-
} else {
484-
None
481+
let value = match (left_value, right_value) {
482+
(Some(v1), Some(v2)) => Some(v1 || v2),
483+
(Some(true), _) | (_, Some(true)) => Some(true),
484+
_ => None,
485485
};
486486

487487
DataValue::Boolean(value)
@@ -1478,7 +1478,7 @@ mod test {
14781478
&DataValue::Boolean(Some(true)),
14791479
&BinaryOperator::Or
14801480
)?,
1481-
DataValue::Boolean(None)
1481+
DataValue::Boolean(Some(true))
14821482
);
14831483

14841484
Ok(())

src/types/value.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,16 @@ macro_rules! varchar_cast {
247247
};
248248
}
249249

250+
macro_rules! numeric_to_boolean {
251+
($value:expr) => {
252+
match $value {
253+
Some(0) => Ok(DataValue::Boolean(Some(false))),
254+
Some(1) => Ok(DataValue::Boolean(Some(true))),
255+
_ => Err(DatabaseError::CastFail),
256+
}
257+
};
258+
}
259+
250260
impl DataValue {
251261
pub fn date(&self) -> Option<NaiveDate> {
252262
if let DataValue::Date32(Some(val)) = self {
@@ -670,6 +680,7 @@ impl DataValue {
670680

671681
decimal
672682
}))),
683+
LogicalType::Boolean => numeric_to_boolean!(value),
673684
_ => Err(DatabaseError::CastFail),
674685
},
675686
DataValue::Int16(value) => match to {
@@ -696,6 +707,7 @@ impl DataValue {
696707

697708
decimal
698709
}))),
710+
LogicalType::Boolean => numeric_to_boolean!(value),
699711
_ => Err(DatabaseError::CastFail),
700712
},
701713
DataValue::Int32(value) => match to {
@@ -721,6 +733,7 @@ impl DataValue {
721733

722734
decimal
723735
}))),
736+
LogicalType::Boolean => numeric_to_boolean!(value),
724737
_ => Err(DatabaseError::CastFail),
725738
},
726739
DataValue::Int64(value) => match to {
@@ -745,6 +758,7 @@ impl DataValue {
745758

746759
decimal
747760
}))),
761+
LogicalType::Boolean => numeric_to_boolean!(value),
748762
_ => Err(DatabaseError::CastFail),
749763
},
750764
DataValue::UInt8(value) => match to {
@@ -765,6 +779,7 @@ impl DataValue {
765779

766780
decimal
767781
}))),
782+
LogicalType::Boolean => numeric_to_boolean!(value),
768783
_ => Err(DatabaseError::CastFail),
769784
},
770785
DataValue::UInt16(value) => match to {
@@ -783,6 +798,7 @@ impl DataValue {
783798

784799
decimal
785800
}))),
801+
LogicalType::Boolean => numeric_to_boolean!(value),
786802
_ => Err(DatabaseError::CastFail),
787803
},
788804
DataValue::UInt32(value) => match to {
@@ -799,6 +815,7 @@ impl DataValue {
799815

800816
decimal
801817
}))),
818+
LogicalType::Boolean => numeric_to_boolean!(value),
802819
_ => Err(DatabaseError::CastFail),
803820
},
804821
DataValue::UInt64(value) => match to {
@@ -813,6 +830,7 @@ impl DataValue {
813830

814831
decimal
815832
}))),
833+
LogicalType::Boolean => numeric_to_boolean!(value),
816834
_ => Err(DatabaseError::CastFail),
817835
},
818836
DataValue::Utf8(value) => match to {

tests/slt/crdb/and_or.slt

Lines changed: 63 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,63 @@
1+
statement ok
2+
DROP TABLE IF EXISTS t
3+
4+
statement ok
5+
CREATE TABLE t (k INT PRIMARY KEY null, a INT null, b INT null)
6+
7+
statement ok
8+
INSERT INTO t VALUES (1, NULL, NULL), (2, NULL, 1), (3, 1, NULL), (4, 2, 0), (5, 3, 3)
9+
10+
statement error (?s)1006.*divided by zero while evaluating function `divide\(3, 0\)`
11+
SELECT a <> 2 AND 3 / b = 1 FROM t ORDER BY k
12+
13+
query I
14+
SELECT a FROM t WHERE a <> 2 AND 3 / b = 1 ORDER BY k
15+
----
16+
3
17+
18+
statement error (?s)1006.*divided by zero while evaluating function `divide\(3, 0\)`
19+
SELECT a = 2 OR 3 / b = 1 FROM t ORDER BY k
20+
21+
query I
22+
SELECT a FROM t WHERE a = 2 OR 3 / b = 1 ORDER BY k
23+
----
24+
2
25+
3
26+
27+
statement ok
28+
truncate table t
29+
30+
statement ok
31+
INSERT INTO t VALUES (1, NULL, NULL), (2, NULL, 1), (3, 1, NULL), (4, 2, 1), (5, 3, 3)
32+
33+
query T
34+
SELECT a <> 2 AND 3 / b = 1 FROM t ORDER BY k
35+
----
36+
null
37+
false
38+
null
39+
false
40+
true
41+
42+
query I
43+
SELECT a FROM t WHERE a <> 2 AND 3 / b = 1 ORDER BY k
44+
----
45+
3
46+
47+
query T
48+
SELECT a = 2 OR 3 / b = 1 FROM t ORDER BY k
49+
----
50+
null
51+
null
52+
null
53+
true
54+
true
55+
56+
query I
57+
SELECT a FROM t WHERE a = 2 OR 3 / b = 1 ORDER BY k
58+
----
59+
2
60+
3
61+
62+
statement ok
63+
DROP TABLE IF EXISTS t

tests/slt/dummy.slt

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
query I
2+
SELECT 1
3+
----
4+
1
5+
6+
statement error
7+
SELECT x
8+
9+
query T
10+
SELECT 'a'
11+
----
12+
a
13+
14+
query B
15+
SELECT NOT(1=1)
16+
----
17+
false
18+
19+
query B
20+
SELECT NOT(1::boolean)
21+
----
22+
false
23+
24+
query B
25+
SELECT TRUE
26+
----
27+
true
28+
29+
query B
30+
SELECT FALSE
31+
----
32+
false
33+
34+
query B
35+
SELECT NOT(TRUE)
36+
----
37+
false
38+
39+
# issue: https://github.com/sqlparser-rs/sqlparser-rs/issues/362
40+
# query T
41+
# SELECT 'That\'s good.'
42+
# ----
43+
# That's good.
44+
45+
statement error
46+
SELECT *

tests/slt/filter.slt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -146,6 +146,7 @@ select * from t1 where id not in (1, 2)
146146
query IT
147147
select * from t1 where id in (1, null)
148148
----
149+
1 KipDB
149150

150151
query IT
151152
select * from t1 where null in (1, 2)
@@ -195,6 +196,7 @@ select * from t1 where null between 1 and null
195196
query IT
196197
select * from t1 where id not between 1 and null
197198
----
199+
0 KipSQL
198200

199201
query IT
200202
select * from t1 where null not between 1 and 2

0 commit comments

Comments
 (0)