Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 12 additions & 1 deletion Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion dozer-sql/expression/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ license = "AGPL-3.0-or-later"
dozer-types = { path = "../../dozer-types" }
dozer-core = { path = "../../dozer-core" }
num-traits = "0.2.16"
sqlparser = { git = "https://github.com/getdozer/sqlparser-rs.git" }
sqlparser = { git = "https://github.com/getdozer/sqlparser-rs.git", features = ["visitor"] }
bigdecimal = { version = "0.3", features = ["serde"], optional = true }
ort = { version = "1.15.2", optional = true }
ndarray = { version = "0.15", optional = true }
Expand Down
4 changes: 2 additions & 2 deletions dozer-sql/expression/src/builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ impl ExpressionBuilder {
.collect();

match matching_by_field.len() {
1 => Ok(Expression::Column {
1 if src_table_or_alias.is_none() => Ok(Expression::Column {
index: matching_by_field[0].0,
}),
_ => match src_table_or_alias {
Expand All @@ -239,7 +239,7 @@ impl ExpressionBuilder {
.collect();

match matching_by_table_or_alias.len() {
1 => Ok(Expression::Column {
1 if src_connection.is_none() => Ok(Expression::Column {
index: matching_by_table_or_alias[0].0,
}),
_ => match src_connection {
Expand Down
6 changes: 3 additions & 3 deletions dozer-sql/expression/src/execution.rs
Original file line number Diff line number Diff line change
Expand Up @@ -544,7 +544,7 @@ fn get_binary_operator_type(
match (left_field_type.return_type, right_field_type.return_type) {
(FieldType::Boolean, FieldType::Boolean) => Ok(ExpressionType::new(
FieldType::Boolean,
false,
left_field_type.nullable || right_field_type.nullable,
SourceDefinition::Dynamic,
false,
)),
Expand All @@ -558,7 +558,7 @@ fn get_binary_operator_type(
| FieldType::Text,
) => Ok(ExpressionType::new(
FieldType::Boolean,
false,
left_field_type.nullable || right_field_type.nullable,
SourceDefinition::Dynamic,
false,
)),
Expand All @@ -572,7 +572,7 @@ fn get_binary_operator_type(
FieldType::Boolean,
) => Ok(ExpressionType::new(
FieldType::Boolean,
false,
left_field_type.nullable || right_field_type.nullable,
SourceDefinition::Dynamic,
false,
)),
Expand Down
181 changes: 47 additions & 134 deletions dozer-sql/expression/src/logical.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,72 +4,27 @@ use dozer_types::types::{Field, Schema};
use crate::error::Error;
use crate::execution::Expression;

fn boolean_operand(field: Field, operator: &str) -> Result<Option<bool>, Error> {
match field {
Field::Boolean(value) => Ok(Some(value)),
Field::Null => Ok(None),
other => Err(Error::InvalidType(other, operator.to_string())),
}
}

pub fn evaluate_and(
schema: &Schema,
left: &mut Expression,
right: &mut Expression,
record: &Record,
) -> Result<Field, Error> {
let l_field = left.evaluate(record, schema)?;
let r_field = right.evaluate(record, schema)?;
match l_field {
Field::Boolean(true) => match r_field {
Field::Boolean(true) => Ok(Field::Boolean(true)),
Field::Boolean(false) => Ok(Field::Boolean(false)),
Field::Null => Ok(Field::Boolean(false)),
Field::UInt(_)
| Field::U128(_)
| Field::Int(_)
| Field::Int8(_)
| Field::I128(_)
| Field::Float(_)
| Field::String(_)
| Field::Text(_)
| Field::Binary(_)
| Field::Decimal(_)
| Field::Timestamp(_)
| Field::Date(_)
| Field::Json(_)
| Field::Point(_)
| Field::Duration(_) => Err(Error::InvalidType(r_field, "AND".to_string())),
},
Field::Boolean(false) => match r_field {
Field::Boolean(true) => Ok(Field::Boolean(false)),
Field::Boolean(false) => Ok(Field::Boolean(false)),
Field::Null => Ok(Field::Boolean(false)),
Field::UInt(_)
| Field::U128(_)
| Field::Int(_)
| Field::Int8(_)
| Field::I128(_)
| Field::Float(_)
| Field::String(_)
| Field::Text(_)
| Field::Binary(_)
| Field::Decimal(_)
| Field::Timestamp(_)
| Field::Date(_)
| Field::Json(_)
| Field::Point(_)
| Field::Duration(_) => Err(Error::InvalidType(r_field, "AND".to_string())),
},
Field::Null => Ok(Field::Boolean(false)),
Field::UInt(_)
| Field::U128(_)
| Field::Int(_)
| Field::Int8(_)
| Field::I128(_)
| Field::Float(_)
| Field::String(_)
| Field::Text(_)
| Field::Binary(_)
| Field::Decimal(_)
| Field::Timestamp(_)
| Field::Date(_)
| Field::Json(_)
| Field::Point(_)
| Field::Duration(_) => Err(Error::InvalidType(l_field, "AND".to_string())),
}
let left = boolean_operand(left.evaluate(record, schema)?, "AND")?;
let right = boolean_operand(right.evaluate(record, schema)?, "AND")?;
Ok(match (left, right) {
(Some(false), _) | (_, Some(false)) => Field::Boolean(false),
(Some(true), Some(true)) => Field::Boolean(true),
_ => Field::Null,
})
}

pub fn evaluate_or(
Expand All @@ -78,65 +33,13 @@ pub fn evaluate_or(
right: &mut Expression,
record: &Record,
) -> Result<Field, Error> {
let l_field = left.evaluate(record, schema)?;
let r_field = right.evaluate(record, schema)?;
match l_field {
Field::Boolean(true) => match r_field {
Field::Boolean(false) => Ok(Field::Boolean(true)),
Field::Boolean(true) => Ok(Field::Boolean(true)),
Field::Null => Ok(Field::Boolean(true)),
Field::UInt(_)
| Field::U128(_)
| Field::Int(_)
| Field::Int8(_)
| Field::I128(_)
| Field::Float(_)
| Field::String(_)
| Field::Text(_)
| Field::Binary(_)
| Field::Decimal(_)
| Field::Timestamp(_)
| Field::Date(_)
| Field::Json(_)
| Field::Point(_)
| Field::Duration(_) => Err(Error::InvalidType(r_field, "OR".to_string())),
},
Field::Boolean(false) | Field::Null => match right.evaluate(record, schema)? {
Field::Boolean(false) => Ok(Field::Boolean(false)),
Field::Boolean(true) => Ok(Field::Boolean(true)),
Field::Null => Ok(Field::Boolean(false)),
Field::UInt(_)
| Field::U128(_)
| Field::Int(_)
| Field::Int8(_)
| Field::I128(_)
| Field::Float(_)
| Field::String(_)
| Field::Text(_)
| Field::Binary(_)
| Field::Decimal(_)
| Field::Timestamp(_)
| Field::Date(_)
| Field::Json(_)
| Field::Point(_)
| Field::Duration(_) => Err(Error::InvalidType(r_field, "OR".to_string())),
},
Field::UInt(_)
| Field::U128(_)
| Field::Int(_)
| Field::Int8(_)
| Field::I128(_)
| Field::Float(_)
| Field::String(_)
| Field::Text(_)
| Field::Binary(_)
| Field::Decimal(_)
| Field::Timestamp(_)
| Field::Date(_)
| Field::Json(_)
| Field::Point(_)
| Field::Duration(_) => Err(Error::InvalidType(l_field, "OR".to_string())),
}
let left = boolean_operand(left.evaluate(record, schema)?, "OR")?;
let right = boolean_operand(right.evaluate(record, schema)?, "OR")?;
Ok(match (left, right) {
(Some(true), _) | (_, Some(true)) => Field::Boolean(true),
(Some(false), Some(false)) => Field::Boolean(false),
_ => Field::Null,
})
}

pub fn evaluate_not(
Expand Down Expand Up @@ -235,13 +138,17 @@ mod tests {

fn _test_bool_null_and(f1: Field, f2: Field) {
let row = Record::new(vec![]);
let expected = if f1 == Field::Boolean(false) || f2 == Field::Boolean(false) {
Field::Boolean(false)
} else {
Field::Null
};
let mut l = Box::new(Literal(f1));
let mut r = Box::new(Literal(f2));
assert!(matches!(
evaluate_and(&Schema::default(), &mut l, &mut r, &row)
.unwrap_or_else(|e| panic!("{}", e.to_string())),
Field::Boolean(false)
));
assert_eq!(
evaluate_and(&Schema::default(), &mut l, &mut r, &row).unwrap(),
expected
);
}

fn _test_bool_bool_or(bool1: bool, bool2: bool) {
Expand All @@ -259,22 +166,28 @@ mod tests {
let row = Record::new(vec![]);
let mut l = Box::new(Literal(Field::Boolean(_bool)));
let mut r = Box::new(Literal(Field::Null));
assert!(matches!(
evaluate_or(&Schema::default(), &mut l, &mut r, &row)
.unwrap_or_else(|e| panic!("{}", e.to_string())),
Field::Boolean(_bool)
));
assert_eq!(
evaluate_or(&Schema::default(), &mut l, &mut r, &row).unwrap(),
if _bool {
Field::Boolean(true)
} else {
Field::Null
}
);
}

fn _test_null_bool_or(_bool: bool) {
let row = Record::new(vec![]);
let mut l = Box::new(Literal(Field::Null));
let mut r = Box::new(Literal(Field::Boolean(_bool)));
assert!(matches!(
evaluate_or(&Schema::default(), &mut l, &mut r, &row)
.unwrap_or_else(|e| panic!("{}", e.to_string())),
Field::Boolean(_bool)
));
assert_eq!(
evaluate_or(&Schema::default(), &mut l, &mut r, &row).unwrap(),
if _bool {
Field::Boolean(true)
} else {
Field::Null
}
);
}

fn _test_bool_not(bool: bool) {
Expand Down
Loading