Skip to content

Commit

Permalink
fix: cast numeric to boolean and and/or only has Null on one side
Browse files Browse the repository at this point in the history
  • Loading branch information
KKould committed Feb 17, 2024
1 parent 4989ba2 commit 7c0c0b6
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 8 deletions.
16 changes: 8 additions & 8 deletions src/expression/value_compute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -469,19 +469,19 @@ impl DataValue {

match op {
BinaryOperator::And => {
let value = if let (Some(v1), Some(v2)) = (left_value, right_value) {
Some(v1 && v2)
} else {
None
let value = match (left_value, right_value) {
(Some(v1), Some(v2)) => Some(v1 && v2),
(Some(false), _) | (_, Some(false)) => Some(false),
_ => None
};

DataValue::Boolean(value)
}
BinaryOperator::Or => {
let value = if let (Some(v1), Some(v2)) = (left_value, right_value) {
Some(v1 || v2)
} else {
None
let value = match (left_value, right_value) {
(Some(v1), Some(v2)) => Some(v1 || v2),
(Some(true), _) | (_, Some(true)) => Some(true),
_ => None
};

DataValue::Boolean(value)
Expand Down
18 changes: 18 additions & 0 deletions src/types/value.rs
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,16 @@ macro_rules! varchar_cast {
};
}

macro_rules! numeric_to_boolean {
($value:expr) => {
match $value {
Some(0) => Ok(DataValue::Boolean(Some(false))),
Some(1) => Ok(DataValue::Boolean(Some(true))),
_ => Err(DatabaseError::CastFail),
}
};
}

impl DataValue {
pub fn date(&self) -> Option<NaiveDate> {
if let DataValue::Date32(Some(val)) = self {
Expand Down Expand Up @@ -670,6 +680,7 @@ impl DataValue {

decimal
}))),
LogicalType::Boolean => numeric_to_boolean!(value),
_ => Err(DatabaseError::CastFail),
},
DataValue::Int16(value) => match to {
Expand All @@ -696,6 +707,7 @@ impl DataValue {

decimal
}))),
LogicalType::Boolean => numeric_to_boolean!(value),
_ => Err(DatabaseError::CastFail),
},
DataValue::Int32(value) => match to {
Expand All @@ -721,6 +733,7 @@ impl DataValue {

decimal
}))),
LogicalType::Boolean => numeric_to_boolean!(value),
_ => Err(DatabaseError::CastFail),
},
DataValue::Int64(value) => match to {
Expand All @@ -745,6 +758,7 @@ impl DataValue {

decimal
}))),
LogicalType::Boolean => numeric_to_boolean!(value),
_ => Err(DatabaseError::CastFail),
},
DataValue::UInt8(value) => match to {
Expand All @@ -765,6 +779,7 @@ impl DataValue {

decimal
}))),
LogicalType::Boolean => numeric_to_boolean!(value),
_ => Err(DatabaseError::CastFail),
},
DataValue::UInt16(value) => match to {
Expand All @@ -783,6 +798,7 @@ impl DataValue {

decimal
}))),
LogicalType::Boolean => numeric_to_boolean!(value),
_ => Err(DatabaseError::CastFail),
},
DataValue::UInt32(value) => match to {
Expand All @@ -799,6 +815,7 @@ impl DataValue {

decimal
}))),
LogicalType::Boolean => numeric_to_boolean!(value),
_ => Err(DatabaseError::CastFail),
},
DataValue::UInt64(value) => match to {
Expand All @@ -813,6 +830,7 @@ impl DataValue {

decimal
}))),
LogicalType::Boolean => numeric_to_boolean!(value),
_ => Err(DatabaseError::CastFail),
},
DataValue::Utf8(value) => match to {
Expand Down
63 changes: 63 additions & 0 deletions tests/slt/crdb/and_or.slt
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
statement ok
DROP TABLE IF EXISTS t

statement ok
CREATE TABLE t (k INT PRIMARY KEY null, a INT null, b INT null)

statement ok
INSERT INTO t VALUES (1, NULL, NULL), (2, NULL, 1), (3, 1, NULL), (4, 2, 0), (5, 3, 3)

statement error (?s)1006.*divided by zero while evaluating function `divide\(3, 0\)`
SELECT a <> 2 AND 3 / b = 1 FROM t ORDER BY k

query I
SELECT a FROM t WHERE a <> 2 AND 3 / b = 1 ORDER BY k
----
3

statement error (?s)1006.*divided by zero while evaluating function `divide\(3, 0\)`
SELECT a = 2 OR 3 / b = 1 FROM t ORDER BY k

query I
SELECT a FROM t WHERE a = 2 OR 3 / b = 1 ORDER BY k
----
2
3

statement ok
truncate table t

statement ok
INSERT INTO t VALUES (1, NULL, NULL), (2, NULL, 1), (3, 1, NULL), (4, 2, 1), (5, 3, 3)

query T
SELECT a <> 2 AND 3 / b = 1 FROM t ORDER BY k
----
null
false
null
false
true

query I
SELECT a FROM t WHERE a <> 2 AND 3 / b = 1 ORDER BY k
----
3

query T
SELECT a = 2 OR 3 / b = 1 FROM t ORDER BY k
----
null
null
null
true
true

query I
SELECT a FROM t WHERE a = 2 OR 3 / b = 1 ORDER BY k
----
2
3

statement ok
DROP TABLE IF EXISTS t
46 changes: 46 additions & 0 deletions tests/slt/dummy.slt
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
query I
SELECT 1
----
1

statement error
SELECT x

query T
SELECT 'a'
----
a

query B
SELECT NOT(1=1)
----
false

query B
SELECT NOT(1::boolean)
----
false

query B
SELECT TRUE
----
true

query B
SELECT FALSE
----
false

query B
SELECT NOT(TRUE)
----
false

# issue: https://github.com/sqlparser-rs/sqlparser-rs/issues/362
# query T
# SELECT 'That\'s good.'
# ----
# That's good.

statement error
SELECT *
2 changes: 2 additions & 0 deletions tests/slt/filter.slt
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ select * from t1 where id not in (1, 2)
query IT
select * from t1 where id in (1, null)
----
1 KipDB

query IT
select * from t1 where null in (1, 2)
Expand Down Expand Up @@ -195,6 +196,7 @@ select * from t1 where null between 1 and null
query IT
select * from t1 where id not between 1 and null
----
0 KipSQL

query IT
select * from t1 where null not between 1 and 2
Expand Down

0 comments on commit 7c0c0b6

Please sign in to comment.