diff --git a/src/binder/expr.rs b/src/binder/expr.rs index 41f8f2ae..890d6d62 100644 --- a/src/binder/expr.rs +++ b/src/binder/expr.rs @@ -143,22 +143,22 @@ impl<'a, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'a, '_, T }) } Expr::Exists { subquery, negated } => { - let (sub_query, column) = self.bind_subquery(subquery)?; + let (sub_query, column) = self.bind_subquery(None, subquery)?; let (_, sub_query) = if !self.context.is_step(&QueryBindStep::Where) { self.bind_temp_table(column, sub_query)? } else { - (ScalarExpression::ColumnRef(column), sub_query) + (column, sub_query) }; self.context .sub_query(SubQueryType::ExistsSubQuery(*negated, sub_query)); Ok(ScalarExpression::Constant(DataValue::Boolean(true))) } Expr::Subquery(subquery) => { - let (sub_query, column) = self.bind_subquery(subquery)?; + let (sub_query, column) = self.bind_subquery(None, subquery)?; let (expr, sub_query) = if !self.context.is_step(&QueryBindStep::Where) { self.bind_temp_table(column, sub_query)? } else { - (ScalarExpression::ColumnRef(column), sub_query) + (column, sub_query) }; self.context.sub_query(SubQueryType::SubQuery(sub_query)); Ok(expr) @@ -169,7 +169,8 @@ impl<'a, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'a, '_, T negated, } => { let left_expr = Box::new(self.bind_expr(expr)?); - let (sub_query, column) = self.bind_subquery(subquery)?; + let (sub_query, column) = + self.bind_subquery(Some(left_expr.return_type()), subquery)?; if !self.context.is_step(&QueryBindStep::Where) { return Err(DatabaseError::UnsupportedStmt( @@ -250,14 +251,14 @@ impl<'a, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'a, '_, T fn bind_temp_table( &mut self, - column: ColumnRef, + expr: ScalarExpression, sub_query: LogicalPlan, ) -> Result<(ScalarExpression, LogicalPlan), DatabaseError> { - let mut alias_column = ColumnCatalog::clone(&column); + let mut alias_column = ColumnCatalog::clone(&expr.output_column()); alias_column.set_ref_table(self.context.temp_table(), ColumnId::new(), true); let alias_expr = ScalarExpression::Alias { - expr: Box::new(ScalarExpression::ColumnRef(column)), + expr: Box::new(expr), alias: AliasType::Expr(Box::new(ScalarExpression::ColumnRef(ColumnRef::from( alias_column, )))), @@ -268,8 +269,9 @@ impl<'a, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'a, '_, T fn bind_subquery( &mut self, + in_ty: Option, subquery: &Query, - ) -> Result<(LogicalPlan, ColumnRef), DatabaseError> { + ) -> Result<(LogicalPlan, ScalarExpression), DatabaseError> { let BinderContext { table_cache, view_cache, @@ -294,14 +296,30 @@ impl<'a, T: Transaction, A: AsRef<[(&'static str, DataValue)]>> Binder<'a, '_, T let mut sub_query = binder.bind_query(subquery)?; let sub_query_schema = sub_query.output_schema(); - if sub_query_schema.len() != 1 { - return Err(DatabaseError::MisMatch( - "expects only one expression to be returned", - "the expression returned by the subquery", - )); - } - let column = sub_query_schema[0].clone(); - Ok((sub_query, column)) + let fn_check = |len: usize| { + if sub_query_schema.len() != len { + return Err(DatabaseError::MisMatch( + "expects only one expression to be returned", + "the expression returned by the subquery", + )); + } + Ok(()) + }; + + let expr = if let Some(LogicalType::Tuple(tys)) = in_ty { + fn_check(tys.len())?; + + let columns = sub_query_schema + .iter() + .map(|column| ScalarExpression::ColumnRef(column.clone())) + .collect::>(); + ScalarExpression::Tuple(columns) + } else { + fn_check(1)?; + + ScalarExpression::ColumnRef(sub_query_schema[0].clone()) + }; + Ok((sub_query, expr)) } pub fn bind_like( diff --git a/src/binder/insert.rs b/src/binder/insert.rs index a0b4b609..4c8e78c1 100644 --- a/src/binder/insert.rs +++ b/src/binder/insert.rs @@ -74,8 +74,12 @@ impl> Binder<'_, '_, T, A> ConstantCalculator.visit(&mut expression)?; match expression { - ScalarExpression::Constant(value) => { + ScalarExpression::Constant(mut value) => { let ty = schema_ref[i].datatype(); + + if &value.logical_type() != ty { + value = value.cast(ty)?; + } // Check if the value length is too long value.check_len(ty)?; diff --git a/src/errors.rs b/src/errors.rs index 6366b685..422a2573 100644 --- a/src/errors.rs +++ b/src/errors.rs @@ -19,8 +19,8 @@ pub enum DatabaseError { ), #[error("cache size overflow")] CacheSizeOverFlow, - #[error("cast fail")] - CastFail, + #[error("cast fail: {from} -> {to}")] + CastFail { from: LogicalType, to: LogicalType }, #[error("channel close")] ChannelClose, #[error("columns empty")] @@ -89,8 +89,10 @@ pub enum DatabaseError { ParametersNotFound(String), #[error("no transaction begin")] NoTransactionBegin, - #[error("cannot be Null")] + #[error("cannot be null")] NotNull, + #[error("over flow")] + OverFlow, #[error("parser bool: {0}")] ParseBool( #[source] diff --git a/src/execution/dql/aggregate/avg.rs b/src/execution/dql/aggregate/avg.rs index 9e1a9080..019fda85 100644 --- a/src/execution/dql/aggregate/avg.rs +++ b/src/execution/dql/aggregate/avg.rs @@ -56,6 +56,6 @@ impl Accumulator for AvgAccumulator { value = value.cast(&quantity_ty)? } let evaluator = EvaluatorFactory::binary_create(quantity_ty, BinaryOperator::Divide)?; - Ok(evaluator.0.binary_eval(&value, &quantity)) + evaluator.0.binary_eval(&value, &quantity) } } diff --git a/src/execution/dql/aggregate/min_max.rs b/src/execution/dql/aggregate/min_max.rs index 8026c9de..35e8d02d 100644 --- a/src/execution/dql/aggregate/min_max.rs +++ b/src/execution/dql/aggregate/min_max.rs @@ -26,7 +26,7 @@ impl Accumulator for MinMaxAccumulator { if !value.is_null() { if let Some(inner_value) = &self.inner { let evaluator = EvaluatorFactory::binary_create(value.logical_type(), self.op)?; - if let DataValue::Boolean(result) = evaluator.0.binary_eval(inner_value, value) { + if let DataValue::Boolean(result) = evaluator.0.binary_eval(inner_value, value)? { result } else { return Err(DatabaseError::InvalidType); diff --git a/src/execution/dql/aggregate/sum.rs b/src/execution/dql/aggregate/sum.rs index 1a210e4a..14502dab 100644 --- a/src/execution/dql/aggregate/sum.rs +++ b/src/execution/dql/aggregate/sum.rs @@ -29,7 +29,7 @@ impl Accumulator for SumAccumulator { if self.result.is_null() { self.result = value.clone(); } else { - self.result = self.evaluator.0.binary_eval(&self.result, value); + self.result = self.evaluator.0.binary_eval(&self.result, value)?; } } diff --git a/src/expression/evaluator.rs b/src/expression/evaluator.rs index 262989c8..069b80dd 100644 --- a/src/expression/evaluator.rs +++ b/src/expression/evaluator.rs @@ -76,11 +76,11 @@ impl ScalarExpression { let left = left_expr.eval(tuple)?; let right = right_expr.eval(tuple)?; - Ok(evaluator + evaluator .as_ref() .ok_or(DatabaseError::EvaluatorNotFound)? .0 - .binary_eval(&left, &right)) + .binary_eval(&left, &right) } ScalarExpression::IsNull { expr, negated } => { let mut is_null = expr.eval(tuple)?.is_null(); @@ -340,7 +340,7 @@ impl ScalarExpression { } evaluator .0 - .binary_eval(operand_value, &when_value) + .binary_eval(operand_value, &when_value)? .is_true()? } else { when_value.is_true()? diff --git a/src/expression/range_detacher.rs b/src/expression/range_detacher.rs index 29bb0a74..7284038c 100644 --- a/src/expression/range_detacher.rs +++ b/src/expression/range_detacher.rs @@ -1,4 +1,5 @@ use crate::catalog::ColumnRef; +use crate::errors::DatabaseError; use crate::expression::{BinaryOperator, ScalarExpression}; use crate::types::value::{DataValue, NULL_VALUE}; use crate::types::ColumnId; @@ -177,14 +178,17 @@ impl<'a> RangeDetacher<'a> { } } - pub(crate) fn detach(&mut self, expr: &ScalarExpression) -> Option { - match expr { + pub(crate) fn detach( + &mut self, + expr: &ScalarExpression, + ) -> Result, DatabaseError> { + Ok(match expr { ScalarExpression::Binary { left_expr, right_expr, op, .. - } => match (self.detach(left_expr), self.detach(right_expr)) { + } => match (self.detach(left_expr)?, self.detach(right_expr)?) { (Some(left_binary), Some(right_binary)) => { Self::merge_binary(*op, left_binary, right_binary) } @@ -208,18 +212,18 @@ impl<'a> RangeDetacher<'a> { | ScalarExpression::Unary { expr, .. } | ScalarExpression::In { expr, .. } | ScalarExpression::Between { expr, .. } - | ScalarExpression::SubString { expr, .. } => self.detach(expr), - ScalarExpression::Position { expr, .. } => self.detach(expr), - ScalarExpression::Trim { expr, .. } => self.detach(expr), + | ScalarExpression::SubString { expr, .. } => self.detach(expr)?, + ScalarExpression::Position { expr, .. } => self.detach(expr)?, + ScalarExpression::Trim { expr, .. } => self.detach(expr)?, ScalarExpression::IsNull { expr, negated, .. } => match expr.as_ref() { ScalarExpression::ColumnRef(column) => { if let (Some(col_id), Some(col_table)) = (column.id(), column.table_name()) { if &col_id == self.column_id && col_table.as_str() == self.table_name { return if *negated { // Range::NotEq(NULL_VALUE.clone()) - None + Ok(None) } else { - Some(Range::Eq(NULL_VALUE.clone())) + Ok(Some(Range::Eq(NULL_VALUE.clone()))) }; } } @@ -243,7 +247,7 @@ impl<'a> RangeDetacher<'a> { | ScalarExpression::IfNull { .. } | ScalarExpression::NullIf { .. } | ScalarExpression::Coalesce { .. } - | ScalarExpression::CaseWhen { .. } => self.detach(expr), + | ScalarExpression::CaseWhen { .. } => self.detach(expr)?, ScalarExpression::Tuple(_) | ScalarExpression::TableFunction(_) | ScalarExpression::Reference { .. } @@ -262,7 +266,7 @@ impl<'a> RangeDetacher<'a> { ScalarExpression::TableFunction(_) | ScalarExpression::Reference { .. } | ScalarExpression::Empty => unreachable!(), - } + }) } fn merge_binary(op: BinaryOperator, left_binary: Range, right_binary: Range) -> Option { @@ -446,6 +450,7 @@ impl<'a> RangeDetacher<'a> { } } + #[allow(unreachable_code)] fn extract_merge_ranges( op: BinaryOperator, mut binary: Option, @@ -549,8 +554,22 @@ impl<'a> RangeDetacher<'a> { _ => None, }; } + (Some(Range::SortedRanges(l_ranges)), r_range) => { + return Self::extract_merge_ranges( + op, + Some(r_range.clone()), + l_ranges.clone(), + &mut 0, + ); + } (None, _) => break, - _ => unreachable!(), + _ => { + #[cfg(debug_assertions)] + { + unreachable!(); + } + return vec![]; + } } } if let Some(range) = binary { @@ -689,11 +708,14 @@ impl<'a> RangeDetacher<'a> { &mut self, mut op: BinaryOperator, col: ColumnRef, - val: DataValue, + mut val: DataValue, is_flip: bool, - ) -> Option { + ) -> Result, DatabaseError> { if !Self::_is_belong(self.table_name, &col) || col.id() != Some(*self.column_id) { - return None; + return Ok(None); + } + if &val.logical_type() != col.datatype() { + val = val.cast(col.datatype())? } if is_flip { op = match op { @@ -704,7 +726,7 @@ impl<'a> RangeDetacher<'a> { source_op => source_op, }; } - match op { + Ok(match op { BinaryOperator::Gt => Some(Range::Scope { min: Bound::Excluded(val.clone()), max: Bound::Unbounded, @@ -723,7 +745,7 @@ impl<'a> RangeDetacher<'a> { }), BinaryOperator::Eq | BinaryOperator::Spaceship => Some(Range::Eq(val.clone())), _ => None, - } + }) } /// check if: `c1 > c2 or c1 > 1` or `c2 > 1 or c1 > 1` @@ -806,16 +828,25 @@ mod test { let plan = table_state.plan("select * from t1 where c1 = 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = 1 => {}", range); assert_eq!(range, Range::Eq(DataValue::Int32(1))) } + { + let plan = table_state.plan("select * from t1 where c1 = 1.0")?; + let op = plan_filter(plan)?.unwrap(); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)? + .unwrap(); + println!("c1 = 1.0 => {}", range); + assert_eq!(range, Range::Eq(DataValue::Int32(1))) + } { let plan = table_state.plan("select * from t1 where c1 != 1")?; let op = plan_filter(plan)?.unwrap(); - let range = - RangeDetacher::new("t1", table_state.column_id_by_name("c1")).detach(&op.predicate); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)?; println!("c1 != 1 => {:#?}", range); assert_eq!(range, None) } @@ -823,7 +854,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 > 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 > 1 => c1: {}", range); assert_eq!( @@ -838,7 +869,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 >= 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 >= 1 => c1: {}", range); assert_eq!( @@ -853,7 +884,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 < 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 < 1 => c1: {}", range); assert_eq!( @@ -868,7 +899,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 <= 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 <= 1 => c1: {}", range); assert_eq!( @@ -883,7 +914,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 < 1 and c1 >= 0")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 < 1 and c1 >= 0 => c1: {}", range); assert_eq!( @@ -898,7 +929,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 < 1 or c1 >= 0")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 < 1 or c1 >= 0 => c1: {}", range); assert_eq!( @@ -914,7 +945,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 = 1 and c1 = 0")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = 1 and c1 = 0 => c1: {}", range); assert_eq!(range, Range::Dummy) @@ -923,7 +954,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 = 1 or c1 = 0")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = 1 or c1 = 0 => c1: {}", range); assert_eq!( @@ -938,7 +969,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 = 1 and c1 = 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = 1 and c1 = 1 => c1: {}", range); assert_eq!(range, Range::Eq(DataValue::Int32(1))) @@ -947,7 +978,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 = 1 or c1 = 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = 1 or c1 = 1 => c1: {}", range); assert_eq!(range, Range::Eq(DataValue::Int32(1))) @@ -957,7 +988,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 > 1 and c1 = 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 > 1 and c1 = 1 => c1: {}", range); assert_eq!(range, Range::Dummy) @@ -966,7 +997,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 >= 1 and c1 = 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 >= 1 and c1 = 1 => c1: {}", range); assert_eq!(range, Range::Eq(DataValue::Int32(1))) @@ -975,7 +1006,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 > 1 or c1 = 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 > 1 or c1 = 1 => c1: {}", range); assert_eq!( @@ -990,7 +1021,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 >= 1 or c1 = 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 >= 1 or c1 = 1 => c1: {}", range); assert_eq!( @@ -1007,7 +1038,7 @@ mod test { .plan("select * from t1 where (c1 > 0 and c1 < 3) and (c1 > 1 and c1 < 4)")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!( "(c1 > 0 and c1 < 3) and (c1 > 1 and c1 < 4) => c1: {}", @@ -1026,7 +1057,7 @@ mod test { .plan("select * from t1 where (c1 > 0 and c1 < 3) or (c1 > 1 and c1 < 4)")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!( "(c1 > 0 and c1 < 3) or (c1 > 1 and c1 < 4) => c1: {}", @@ -1047,7 +1078,7 @@ mod test { )?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!( "((c1 > 0 and c1 < 3) and (c1 > 1 and c1 < 4)) and c1 = 0 => c1: {}", @@ -1061,7 +1092,7 @@ mod test { )?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!( "((c1 > 0 and c1 < 3) or (c1 > 1 and c1 < 4)) and c1 = 0 => c1: {}", @@ -1075,7 +1106,7 @@ mod test { )?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!( "((c1 > 0 and c1 < 3) and (c1 > 1 and c1 < 4)) or c1 = 0 => c1: {}", @@ -1098,7 +1129,7 @@ mod test { )?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!( "((c1 > 0 and c1 < 3) or (c1 > 1 and c1 < 4)) or c1 = 0 => c1: {}", @@ -1117,7 +1148,7 @@ mod test { let plan = table_state.plan("select * from t1 where (((c1 > 0 and c1 < 3) and (c1 > 1 and c1 < 4)) and c1 = 0) and (c1 >= 0 and c1 <= 2)")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("(((c1 > 0 and c1 < 3) and (c1 > 1 and c1 < 4)) and c1 = 0) and (c1 >= 0 and c1 <= 2) => c1: {}", range); assert_eq!(range, Range::Dummy) @@ -1126,7 +1157,7 @@ mod test { let plan = table_state.plan("select * from t1 where (((c1 > 0 and c1 < 3) and (c1 > 1 and c1 < 4)) and c1 = 0) or (c1 >= 0 and c1 <= 2)")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("(((c1 > 0 and c1 < 3) and (c1 > 1 and c1 < 4)) and c1 = 0) or (c1 >= 0 and c1 <= 2) => c1: {}", range); assert_eq!( @@ -1142,7 +1173,7 @@ mod test { let plan = table_state.plan("select * from t1 where ((c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) and ((c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5))")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("((c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) and ((c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5)) => c1: {}", range); assert_eq!( @@ -1163,7 +1194,7 @@ mod test { let plan = table_state.plan("select * from t1 where ((c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) or ((c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5))")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("((c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) or ((c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5)) => c1: {}", range); assert_eq!( @@ -1184,8 +1215,8 @@ mod test { { let plan = table_state.plan("select * from t1 where true")?; let op = plan_filter(plan)?.unwrap(); - let range = - RangeDetacher::new("t1", table_state.column_id_by_name("c1")).detach(&op.predicate); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)?; println!("empty => c1: {:#?}", range); assert_eq!(range, None) } @@ -1193,24 +1224,24 @@ mod test { { let plan = table_state.plan("select * from t1 where c2 = 1")?; let op = plan_filter(plan)?.unwrap(); - let range = - RangeDetacher::new("t1", table_state.column_id_by_name("c1")).detach(&op.predicate); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)?; println!("c2 = 1 => c1: {:#?}", range); assert_eq!(range, None) } { let plan = table_state.plan("select * from t1 where c1 > 1 or c2 > 1")?; let op = plan_filter(plan)?.unwrap(); - let range = - RangeDetacher::new("t1", table_state.column_id_by_name("c1")).detach(&op.predicate); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)?; println!("c1 > 1 or c2 > 1 => c1: {:#?}", range); assert_eq!(range, None) } { let plan = table_state.plan("select * from t1 where c1 > c2 or c2 > 1")?; let op = plan_filter(plan)?.unwrap(); - let range = - RangeDetacher::new("t1", table_state.column_id_by_name("c1")).detach(&op.predicate); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)?; println!("c1 > c2 or c2 > 1 => c1: {:#?}", range); assert_eq!(range, None) } @@ -1221,7 +1252,7 @@ mod test { )?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!( "c1 = 5 or (c1 > 5 and (c1 > 6 or c1 < 8) and c1 < 12) => c1: {}", @@ -1242,7 +1273,7 @@ mod test { )?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!( "((c2 >= -8 and -4 >= c1) or (c1 >= 0 and 5 > c2)) and ((c2 > 0 and c1 <= 1) or (c1 > -8 and c2 < -6)) => c1: {}", @@ -1275,7 +1306,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 = null")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = null => c1: {}", range); assert_eq!(range, Range::Eq(DataValue::Null)) @@ -1284,7 +1315,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 = null or c1 = 1")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = null or c1 = 1 => c1: {}", range); assert_eq!( @@ -1299,7 +1330,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 = null or c1 < 5")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = null or c1 < 5 => c1: {}", range); assert_eq!( @@ -1315,7 +1346,7 @@ mod test { table_state.plan("select * from t1 where c1 = null or (c1 > 1 and c1 < 5)")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = null or (c1 > 1 and c1 < 5) => c1: {}", range); assert_eq!( @@ -1333,7 +1364,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 = null and c1 < 5")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = null and c1 < 5 => c1: {}", range); assert_eq!(range, Range::Eq(DataValue::Null)) @@ -1343,7 +1374,7 @@ mod test { table_state.plan("select * from t1 where c1 = null and (c1 > 1 and c1 < 5)")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 = null and (c1 > 1 and c1 < 5) => c1: {}", range); assert_eq!(range, Range::Dummy) @@ -1352,24 +1383,24 @@ mod test { { let plan = table_state.plan("select * from t1 where c1 != null")?; let op = plan_filter(plan)?.unwrap(); - let range = - RangeDetacher::new("t1", table_state.column_id_by_name("c1")).detach(&op.predicate); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)?; println!("c1 != null => c1: {:#?}", range); assert_eq!(range, None) } { let plan = table_state.plan("select * from t1 where c1 = null or c1 != 1")?; let op = plan_filter(plan)?.unwrap(); - let range = - RangeDetacher::new("t1", table_state.column_id_by_name("c1")).detach(&op.predicate); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)?; println!("c1 = null or c1 != 1 => c1: {:#?}", range); assert_eq!(range, None) } { let plan = table_state.plan("select * from t1 where c1 != null or c1 < 5")?; let op = plan_filter(plan)?.unwrap(); - let range = - RangeDetacher::new("t1", table_state.column_id_by_name("c1")).detach(&op.predicate); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)?; println!("c1 != null or c1 < 5 => c1: {:#?}", range); assert_eq!(range, None) } @@ -1377,8 +1408,8 @@ mod test { let plan = table_state.plan("select * from t1 where c1 != null or (c1 > 1 and c1 < 5)")?; let op = plan_filter(plan)?.unwrap(); - let range = - RangeDetacher::new("t1", table_state.column_id_by_name("c1")).detach(&op.predicate); + let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) + .detach(&op.predicate)?; println!("c1 != null or (c1 > 1 and c1 < 5) => c1: {:#?}", range); assert_eq!(range, None) } @@ -1386,7 +1417,7 @@ mod test { let plan = table_state.plan("select * from t1 where c1 != null and c1 < 5")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 != null and c1 < 5 => c1: {}", range); assert_eq!( @@ -1402,7 +1433,7 @@ mod test { table_state.plan("select * from t1 where c1 != null and (c1 > 1 and c1 < 5)")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("c1 != null and (c1 > 1 and c1 < 5) => c1: {}", range); assert_eq!( @@ -1417,7 +1448,7 @@ mod test { let plan = table_state.plan("select * from t1 where (c1 = null or (c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) or ((c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5))")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("(c1 = null or (c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) or ((c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5)) => c1: {}", range); assert_eq!( @@ -1439,7 +1470,7 @@ mod test { let plan = table_state.plan("select * from t1 where ((c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) or (c1 = null or (c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5))")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("((c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) or (c1 = null or (c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5)) => c1: {}", range); assert_eq!( @@ -1461,7 +1492,7 @@ mod test { let plan = table_state.plan("select * from t1 where (c1 = null or (c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) and ((c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5))")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("(c1 = null or (c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) and ((c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5)) => c1: {}", range); assert_eq!( @@ -1482,7 +1513,7 @@ mod test { let plan = table_state.plan("select * from t1 where ((c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) and (c1 = null or (c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5))")?; let op = plan_filter(plan)?.unwrap(); let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&op.predicate) + .detach(&op.predicate)? .unwrap(); println!("((c1 < 2 and c1 > 0) or (c1 < 6 and c1 > 4)) and (c1 = null or (c1 < 3 and c1 > 1) or (c1 < 7 and c1 > 5)) => c1: {}", range); assert_eq!( @@ -1922,7 +1953,7 @@ mod test { unreachable!() }; assert_eq!( - TupleLtBinaryEvaluator.binary_eval(&min, &max), + TupleLtBinaryEvaluator.binary_eval(&min, &max).unwrap(), DataValue::Boolean(true) ) } diff --git a/src/expression/simplify.rs b/src/expression/simplify.rs index c7f7b9a6..820206e4 100644 --- a/src/expression/simplify.rs +++ b/src/expression/simplify.rs @@ -79,7 +79,7 @@ impl VisitorMut<'_> for ConstantCalculator { if right_val.logical_type() != ty { *right_val = right_val.clone().cast(&ty)?; } - let value = evaluator.0.binary_eval(left_val, right_val); + let value = evaluator.0.binary_eval(left_val, right_val)?; let _ = mem::replace(expr, ScalarExpression::Constant(value)); } } @@ -467,15 +467,15 @@ impl ScalarExpression { if &right.logical_type() != ty { right = right.cast(ty).ok()?; } - let binary_value = if let Some(evaluator) = evaluator { + if let Some(evaluator) = evaluator { evaluator.0.binary_eval(&left, &right) } else { EvaluatorFactory::binary_create(ty.clone(), *op) .ok()? .0 .binary_eval(&left, &right) - }; - Some(binary_value) + } + .ok() } _ => None, } diff --git a/src/optimizer/core/histogram.rs b/src/optimizer/core/histogram.rs index 000001e7..69319edd 100644 --- a/src/optimizer/core/histogram.rs +++ b/src/optimizer/core/histogram.rs @@ -215,7 +215,7 @@ fn is_under( BinaryOperator::LtEq }, )?; - let value = evaluator.0.binary_eval(value, target); + let value = evaluator.0.binary_eval(value, target)?; Ok::(matches!(value, DataValue::Boolean(true))) }; @@ -240,7 +240,7 @@ fn is_above( BinaryOperator::Gt }, )?; - let value = evaluator.0.binary_eval(value, target); + let value = evaluator.0.binary_eval(value, target)?; Ok::(matches!(value, DataValue::Boolean(true))) }; Ok(match target { @@ -331,7 +331,7 @@ impl Histogram { }, LogicalType::Date | LogicalType::DateTime - | LogicalType::Time(_, _) + | LogicalType::Time(_) | LogicalType::TimeStamp(_, _) => match value { DataValue::Date32(value) => DataValue::Int32(*value) .cast(&LogicalType::Double)? diff --git a/src/optimizer/rule/normalization/pushdown_predicates.rs b/src/optimizer/rule/normalization/pushdown_predicates.rs index 0a3851a5..da457b24 100644 --- a/src/optimizer/rule/normalization/pushdown_predicates.rs +++ b/src/optimizer/rule/normalization/pushdown_predicates.rs @@ -226,10 +226,10 @@ impl NormalizationRule for PushPredicateIntoScan { | IndexType::Unique | IndexType::Normal => { RangeDetacher::new(meta.table_name.as_str(), &meta.column_ids[0]) - .detach(&op.predicate) + .detach(&op.predicate)? } IndexType::PrimaryKey { is_multiple: true } | IndexType::Composite => { - Self::composite_range(&op, meta) + Self::composite_range(&op, meta)? } }; } @@ -242,14 +242,17 @@ impl NormalizationRule for PushPredicateIntoScan { } impl PushPredicateIntoScan { - fn composite_range(op: &FilterOperator, meta: &mut IndexMetaRef) -> Option { + fn composite_range( + op: &FilterOperator, + meta: &mut IndexMetaRef, + ) -> Result, DatabaseError> { let mut res = None; let mut eq_ranges = Vec::with_capacity(meta.column_ids.len()); let mut apply_column_count = 0; for column_id in meta.column_ids.iter() { if let Some(range) = - RangeDetacher::new(meta.table_name.as_str(), column_id).detach(&op.predicate) + RangeDetacher::new(meta.table_name.as_str(), column_id).detach(&op.predicate)? { apply_column_count += 1; @@ -266,7 +269,7 @@ impl PushPredicateIntoScan { res = range.combining_eqs(&eq_ranges); } } - res.map(|range| { + Ok(res.map(|range| { if range.only_eq() && apply_column_count != meta.column_ids.len() { fn eq_to_scope(range: Range) -> Range { match range { @@ -289,7 +292,7 @@ impl PushPredicateIntoScan { return eq_to_scope(range); } range - }) + })) } } diff --git a/src/optimizer/rule/normalization/simplification.rs b/src/optimizer/rule/normalization/simplification.rs index 4543bd05..a220c065 100644 --- a/src/optimizer/rule/normalization/simplification.rs +++ b/src/optimizer/rule/normalization/simplification.rs @@ -163,7 +163,7 @@ mod test { let filter_op = best_plan.childrens.pop_only(); if let Operator::Filter(filter_op) = filter_op.operator { let range = RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&filter_op.predicate) + .detach(&filter_op.predicate)? .unwrap(); assert_eq!( range, @@ -217,7 +217,7 @@ mod test { if let Operator::Filter(filter_op) = filter_op.operator { Ok( RangeDetacher::new("t1", table_state.column_id_by_name("c1")) - .detach(&filter_op.predicate), + .detach(&filter_op.predicate)?, ) } else { Ok(None) @@ -332,7 +332,7 @@ mod test { let filter_op = best_plan.childrens.pop_only(); if let Operator::Filter(filter_op) = filter_op.operator { - Ok(RangeDetacher::new("t1", &column_id).detach(&filter_op.predicate)) + Ok(RangeDetacher::new("t1", &column_id).detach(&filter_op.predicate)?) } else { Ok(None) } diff --git a/src/types/evaluator/boolean.rs b/src/types/evaluator/boolean.rs index fb9d8574..95bde45a 100644 --- a/src/types/evaluator/boolean.rs +++ b/src/types/evaluator/boolean.rs @@ -1,3 +1,4 @@ +use crate::errors::DatabaseError; use crate::types::evaluator::DataValue; use crate::types::evaluator::{BinaryEvaluator, UnaryEvaluator}; use serde::{Deserialize, Serialize}; @@ -26,8 +27,8 @@ impl UnaryEvaluator for BooleanNotUnaryEvaluator { } #[typetag::serde] impl BinaryEvaluator for BooleanAndBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Boolean(v1), DataValue::Boolean(v2)) => DataValue::Boolean(*v1 && *v2), (DataValue::Boolean(false), DataValue::Null) | (DataValue::Null, DataValue::Boolean(false)) => DataValue::Boolean(false), @@ -35,14 +36,14 @@ impl BinaryEvaluator for BooleanAndBinaryEvaluator { | (DataValue::Boolean(true), DataValue::Null) | (DataValue::Null, DataValue::Boolean(true)) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for BooleanOrBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Boolean(v1), DataValue::Boolean(v2)) => DataValue::Boolean(*v1 || *v2), (DataValue::Boolean(true), DataValue::Null) | (DataValue::Null, DataValue::Boolean(true)) => DataValue::Boolean(true), @@ -50,32 +51,32 @@ impl BinaryEvaluator for BooleanOrBinaryEvaluator { | (DataValue::Boolean(false), DataValue::Null) | (DataValue::Null, DataValue::Boolean(false)) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for BooleanEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Boolean(v1), DataValue::Boolean(v2)) => DataValue::Boolean(*v1 == *v2), (DataValue::Null, DataValue::Boolean(_)) | (DataValue::Boolean(_), DataValue::Null) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for BooleanNotEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Boolean(v1), DataValue::Boolean(v2)) => DataValue::Boolean(*v1 != *v2), (DataValue::Null, DataValue::Boolean(_)) | (DataValue::Boolean(_), DataValue::Null) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } diff --git a/src/types/evaluator/date.rs b/src/types/evaluator/date.rs index db345d70..c31561e7 100644 --- a/src/types/evaluator/date.rs +++ b/src/types/evaluator/date.rs @@ -1,6 +1,7 @@ use crate::numeric_binary_evaluator_definition; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; +use crate::types::DatabaseError; use paste::paste; use serde::{Deserialize, Serialize}; use std::hint; diff --git a/src/types/evaluator/datetime.rs b/src/types/evaluator/datetime.rs index c5dda53b..cd3e6634 100644 --- a/src/types/evaluator/datetime.rs +++ b/src/types/evaluator/datetime.rs @@ -1,6 +1,7 @@ use crate::numeric_binary_evaluator_definition; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; +use crate::types::DatabaseError; use paste::paste; use serde::{Deserialize, Serialize}; use std::hint; diff --git a/src/types/evaluator/decimal.rs b/src/types/evaluator/decimal.rs index 3828536c..077518f2 100644 --- a/src/types/evaluator/decimal.rs +++ b/src/types/evaluator/decimal.rs @@ -1,3 +1,4 @@ +use crate::errors::DatabaseError; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; use serde::{Deserialize, Serialize}; @@ -28,133 +29,133 @@ pub struct DecimalModBinaryEvaluator; #[typetag::serde] impl BinaryEvaluator for DecimalPlusBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Decimal(v1 + v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalMinusBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Decimal(v1 - v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalMultiplyBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Decimal(v1 * v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalDivideBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Decimal(v1 / v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalGtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Boolean(v1 > v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalGtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Boolean(v1 >= v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalLtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Boolean(v1 < v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalLtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Boolean(v1 <= v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Boolean(v1 == v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalNotEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Boolean(v1 != v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for DecimalModBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Decimal(v1), DataValue::Decimal(v2)) => DataValue::Decimal(v1 % v2), (DataValue::Decimal(_), DataValue::Null) | (DataValue::Null, DataValue::Decimal(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } diff --git a/src/types/evaluator/float32.rs b/src/types/evaluator/float32.rs index ad474c58..1dfd6482 100644 --- a/src/types/evaluator/float32.rs +++ b/src/types/evaluator/float32.rs @@ -1,3 +1,4 @@ +use crate::errors::DatabaseError; use crate::types::evaluator::DataValue; use crate::types::evaluator::{BinaryEvaluator, UnaryEvaluator}; use serde::{Deserialize, Serialize}; @@ -50,44 +51,44 @@ pub struct Float32ModBinaryEvaluator; #[typetag::serde] impl BinaryEvaluator for Float32PlusBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Float32(*v1 + *v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32MinusBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Float32(*v1 - *v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32MultiplyBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Float32(*v1 * *v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32DivideBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => { DataValue::Float64(ordered_float::OrderedFloat(**v1 as f64 / **v2 as f64)) } @@ -95,90 +96,90 @@ impl BinaryEvaluator for Float32DivideBinaryEvaluator { | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32GtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Boolean(v1 > v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32GtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Boolean(v1 >= v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32LtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Boolean(v1 < v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32LtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Boolean(v1 <= v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32EqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Boolean(v1 == v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32NotEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Boolean(v1 != v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float32ModBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float32(v1), DataValue::Float32(v2)) => DataValue::Float32(*v1 % *v2), (DataValue::Float32(_), DataValue::Null) | (DataValue::Null, DataValue::Float32(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } diff --git a/src/types/evaluator/float64.rs b/src/types/evaluator/float64.rs index 8adf3e5d..86e90e93 100644 --- a/src/types/evaluator/float64.rs +++ b/src/types/evaluator/float64.rs @@ -1,3 +1,4 @@ +use crate::errors::DatabaseError; use crate::types::evaluator::DataValue; use crate::types::evaluator::{BinaryEvaluator, UnaryEvaluator}; use serde::{Deserialize, Serialize}; @@ -50,44 +51,44 @@ pub struct Float64ModBinaryEvaluator; #[typetag::serde] impl BinaryEvaluator for Float64PlusBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Float64(*v1 + *v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64MinusBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Float64(*v1 - *v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64MultiplyBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Float64(*v1 * *v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64DivideBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => { DataValue::Float64(ordered_float::OrderedFloat(**v1 / **v2)) } @@ -95,90 +96,90 @@ impl BinaryEvaluator for Float64DivideBinaryEvaluator { | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64GtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Boolean(v1 > v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64GtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Boolean(v1 >= v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64LtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Boolean(v1 < v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64LtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Boolean(v1 <= v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64EqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Boolean(v1 == v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64NotEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Boolean(v1 != v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Float64ModBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Float64(v1), DataValue::Float64(v2)) => DataValue::Float64(*v1 % *v2), (DataValue::Float64(_), DataValue::Null) | (DataValue::Null, DataValue::Float64(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } diff --git a/src/types/evaluator/int16.rs b/src/types/evaluator/int16.rs index b2c4a748..ad5675a3 100644 --- a/src/types/evaluator/int16.rs +++ b/src/types/evaluator/int16.rs @@ -1,5 +1,6 @@ use crate::types::evaluator::DataValue; use crate::types::evaluator::{BinaryEvaluator, UnaryEvaluator}; +use crate::types::DatabaseError; use crate::{numeric_binary_evaluator_definition, numeric_unary_evaluator_definition}; use paste::paste; use serde::{Deserialize, Serialize}; diff --git a/src/types/evaluator/int32.rs b/src/types/evaluator/int32.rs index cc7b0e86..296dfe29 100644 --- a/src/types/evaluator/int32.rs +++ b/src/types/evaluator/int32.rs @@ -1,5 +1,6 @@ use crate::types::evaluator::DataValue; use crate::types::evaluator::{BinaryEvaluator, UnaryEvaluator}; +use crate::types::DatabaseError; use crate::{numeric_binary_evaluator_definition, numeric_unary_evaluator_definition}; use paste::paste; use serde::{Deserialize, Serialize}; diff --git a/src/types/evaluator/int64.rs b/src/types/evaluator/int64.rs index eafac83e..9f0be2ff 100644 --- a/src/types/evaluator/int64.rs +++ b/src/types/evaluator/int64.rs @@ -1,5 +1,6 @@ use crate::types::evaluator::DataValue; use crate::types::evaluator::{BinaryEvaluator, UnaryEvaluator}; +use crate::types::DatabaseError; use crate::{numeric_binary_evaluator_definition, numeric_unary_evaluator_definition}; use paste::paste; use serde::{Deserialize, Serialize}; diff --git a/src/types/evaluator/int8.rs b/src/types/evaluator/int8.rs index b3abe5f7..ebda024e 100644 --- a/src/types/evaluator/int8.rs +++ b/src/types/evaluator/int8.rs @@ -1,5 +1,6 @@ use crate::types::evaluator::DataValue; use crate::types::evaluator::{BinaryEvaluator, UnaryEvaluator}; +use crate::types::DatabaseError; use crate::{numeric_binary_evaluator_definition, numeric_unary_evaluator_definition}; use paste::paste; use serde::{Deserialize, Serialize}; diff --git a/src/types/evaluator/mod.rs b/src/types/evaluator/mod.rs index b2f597f8..3ea8ba33 100644 --- a/src/types/evaluator/mod.rs +++ b/src/types/evaluator/mod.rs @@ -52,11 +52,12 @@ use paste::paste; use serde::{Deserialize, Serialize}; use std::fmt::Debug; use std::hash::{Hash, Hasher}; +use std::ops::Deref; use std::sync::Arc; #[typetag::serde(tag = "binary")] pub trait BinaryEvaluator: Send + Sync + Debug { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue; + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result; } #[typetag::serde(tag = "unary")] @@ -67,8 +68,20 @@ pub trait UnaryEvaluator: Send + Sync + Debug { #[derive(Clone, Debug, Serialize, Deserialize)] pub struct BinaryEvaluatorBox(pub Arc); +impl Deref for BinaryEvaluatorBox { + type Target = Arc; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + impl BinaryEvaluatorBox { - pub fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { + pub fn binary_eval( + &self, + left: &DataValue, + right: &DataValue, + ) -> Result { self.0.binary_eval(left, right) } } @@ -193,7 +206,7 @@ impl EvaluatorFactory { LogicalType::Double => numeric_binary_evaluator!(Float64, op, LogicalType::Double), LogicalType::Date => numeric_binary_evaluator!(Date, op, LogicalType::Date), LogicalType::DateTime => numeric_binary_evaluator!(DateTime, op, LogicalType::DateTime), - LogicalType::Time(_, _) => match op { + LogicalType::Time(_) => match op { BinaryOperator::Plus => Ok(BinaryEvaluatorBox(Arc::new(TimePlusBinaryEvaluator))), BinaryOperator::Minus => Ok(BinaryEvaluatorBox(Arc::new(TimeMinusBinaryEvaluator))), BinaryOperator::Gt => Ok(BinaryEvaluatorBox(Arc::new(TimeGtBinaryEvaluator))), @@ -324,112 +337,112 @@ macro_rules! numeric_binary_evaluator_definition { #[typetag::serde] impl BinaryEvaluator for [<$value_type PlusBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - ($compute_type(v1), $compute_type(v2)) => $compute_type(*v1 + *v2), + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + ($compute_type(v1), $compute_type(v2)) => $compute_type(v1.checked_add(*v2).ok_or(DatabaseError::OverFlow)?), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type MinusBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - ($compute_type(v1), $compute_type(v2)) => $compute_type(*v1 - *v2), + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + ($compute_type(v1), $compute_type(v2)) => $compute_type(v1.checked_sub(*v2).ok_or(DatabaseError::OverFlow)?), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type MultiplyBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - ($compute_type(v1), $compute_type(v2)) => $compute_type(*v1 * *v2), + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + ($compute_type(v1), $compute_type(v2)) => $compute_type(v1.checked_mul(*v2).ok_or(DatabaseError::OverFlow)?), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type DivideBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { ($compute_type(v1), $compute_type(v2)) => DataValue::Float64(ordered_float::OrderedFloat(*v1 as f64 / *v2 as f64)), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type GtBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { ($compute_type(v1), $compute_type(v2)) => DataValue::Boolean(v1 > v2), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type GtEqBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { ($compute_type(v1), $compute_type(v2)) => DataValue::Boolean(v1 >= v2), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type LtBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { ($compute_type(v1), $compute_type(v2)) => DataValue::Boolean(v1 < v2), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type LtEqBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { ($compute_type(v1), $compute_type(v2)) => DataValue::Boolean(v1 <= v2), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type EqBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { ($compute_type(v1), $compute_type(v2)) => DataValue::Boolean(v1 == v2), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type NotEqBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { ($compute_type(v1), $compute_type(v2)) => DataValue::Boolean(v1 != v2), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for [<$value_type ModBinaryEvaluator>] { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { ($compute_type(v1), $compute_type(v2)) => $compute_type(*v1 % *v2), ($compute_type(_), DataValue::Null) | (DataValue::Null, $compute_type(_)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } } @@ -457,16 +470,16 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Plus)?; let plus_i32_1 = plus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let plus_i32_2 = plus_evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Null); + .binary_eval(&DataValue::Int32(1), &DataValue::Null)?; let plus_i32_3 = plus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(1)); + .binary_eval(&DataValue::Null, &DataValue::Int32(1))?; let plus_i32_4 = plus_evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1)); + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1))?; assert_eq!(plus_i32_1, plus_i32_2); assert_eq!(plus_i32_2, plus_i32_3); @@ -476,16 +489,16 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Bigint, BinaryOperator::Plus)?; let plus_i64_1 = plus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let plus_i64_2 = plus_evaluator .0 - .binary_eval(&DataValue::Int64(1), &DataValue::Null); + .binary_eval(&DataValue::Int64(1), &DataValue::Null)?; let plus_i64_3 = plus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int64(1)); + .binary_eval(&DataValue::Null, &DataValue::Int64(1))?; let plus_i64_4 = plus_evaluator .0 - .binary_eval(&DataValue::Int64(1), &DataValue::Int64(1)); + .binary_eval(&DataValue::Int64(1), &DataValue::Int64(1))?; assert_eq!(plus_i64_1, plus_i64_2); assert_eq!(plus_i64_2, plus_i64_3); @@ -495,17 +508,17 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Double, BinaryOperator::Plus)?; let plus_f64_1 = plus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let plus_f64_2 = plus_evaluator .0 - .binary_eval(&DataValue::Float64(OrderedFloat(1.0)), &DataValue::Null); + .binary_eval(&DataValue::Float64(OrderedFloat(1.0)), &DataValue::Null)?; let plus_f64_3 = plus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Float64(OrderedFloat(1.0))); + .binary_eval(&DataValue::Null, &DataValue::Float64(OrderedFloat(1.0)))?; let plus_f64_4 = plus_evaluator.0.binary_eval( &DataValue::Float64(OrderedFloat(1.0)), &DataValue::Float64(OrderedFloat(1.0)), - ); + )?; assert_eq!(plus_f64_1, plus_f64_2); assert_eq!(plus_f64_2, plus_f64_3); @@ -520,16 +533,16 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Minus)?; let minus_i32_1 = minus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let minus_i32_2 = minus_evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Null); + .binary_eval(&DataValue::Int32(1), &DataValue::Null)?; let minus_i32_3 = minus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(1)); + .binary_eval(&DataValue::Null, &DataValue::Int32(1))?; let minus_i32_4 = minus_evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1)); + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1))?; assert_eq!(minus_i32_1, minus_i32_2); assert_eq!(minus_i32_2, minus_i32_3); @@ -539,16 +552,16 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Bigint, BinaryOperator::Minus)?; let minus_i64_1 = minus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let minus_i64_2 = minus_evaluator .0 - .binary_eval(&DataValue::Int64(1), &DataValue::Null); + .binary_eval(&DataValue::Int64(1), &DataValue::Null)?; let minus_i64_3 = minus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int64(1)); + .binary_eval(&DataValue::Null, &DataValue::Int64(1))?; let minus_i64_4 = minus_evaluator .0 - .binary_eval(&DataValue::Int64(1), &DataValue::Int64(1)); + .binary_eval(&DataValue::Int64(1), &DataValue::Int64(1))?; assert_eq!(minus_i64_1, minus_i64_2); assert_eq!(minus_i64_2, minus_i64_3); @@ -558,17 +571,17 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Double, BinaryOperator::Minus)?; let minus_f64_1 = minus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let minus_f64_2 = minus_evaluator .0 - .binary_eval(&DataValue::Float64(OrderedFloat(1.0)), &DataValue::Null); + .binary_eval(&DataValue::Float64(OrderedFloat(1.0)), &DataValue::Null)?; let minus_f64_3 = minus_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Float64(OrderedFloat(1.0))); + .binary_eval(&DataValue::Null, &DataValue::Float64(OrderedFloat(1.0)))?; let minus_f64_4 = minus_evaluator.0.binary_eval( &DataValue::Float64(OrderedFloat(1.0)), &DataValue::Float64(OrderedFloat(1.0)), - ); + )?; assert_eq!(minus_f64_1, minus_f64_2); assert_eq!(minus_f64_2, minus_f64_3); @@ -583,16 +596,16 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Multiply)?; let multiply_i32_1 = multiply_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let multiply_i32_2 = multiply_evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Null); + .binary_eval(&DataValue::Int32(1), &DataValue::Null)?; let multiply_i32_3 = multiply_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(1)); + .binary_eval(&DataValue::Null, &DataValue::Int32(1))?; let multiply_i32_4 = multiply_evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1)); + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1))?; assert_eq!(multiply_i32_1, multiply_i32_2); assert_eq!(multiply_i32_2, multiply_i32_3); @@ -602,16 +615,16 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Bigint, BinaryOperator::Multiply)?; let multiply_i64_1 = multiply_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let multiply_i64_2 = multiply_evaluator .0 - .binary_eval(&DataValue::Int64(1), &DataValue::Null); + .binary_eval(&DataValue::Int64(1), &DataValue::Null)?; let multiply_i64_3 = multiply_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int64(1)); + .binary_eval(&DataValue::Null, &DataValue::Int64(1))?; let multiply_i64_4 = multiply_evaluator .0 - .binary_eval(&DataValue::Int64(1), &DataValue::Int64(1)); + .binary_eval(&DataValue::Int64(1), &DataValue::Int64(1))?; assert_eq!(multiply_i64_1, multiply_i64_2); assert_eq!(multiply_i64_2, multiply_i64_3); @@ -621,17 +634,17 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Double, BinaryOperator::Multiply)?; let multiply_f64_1 = multiply_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let multiply_f64_2 = multiply_evaluator .0 - .binary_eval(&DataValue::Float64(OrderedFloat(1.0)), &DataValue::Null); + .binary_eval(&DataValue::Float64(OrderedFloat(1.0)), &DataValue::Null)?; let multiply_f64_3 = multiply_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Float64(OrderedFloat(1.0))); + .binary_eval(&DataValue::Null, &DataValue::Float64(OrderedFloat(1.0)))?; let multiply_f64_4 = multiply_evaluator.0.binary_eval( &DataValue::Float64(OrderedFloat(1.0)), &DataValue::Float64(OrderedFloat(1.0)), - ); + )?; assert_eq!(multiply_f64_1, multiply_f64_2); assert_eq!(multiply_f64_2, multiply_f64_3); @@ -646,16 +659,16 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Divide)?; let divide_i32_1 = divide_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let divide_i32_2 = divide_evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Null); + .binary_eval(&DataValue::Int32(1), &DataValue::Null)?; let divide_i32_3 = divide_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(1)); + .binary_eval(&DataValue::Null, &DataValue::Int32(1))?; let divide_i32_4 = divide_evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1)); + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1))?; assert_eq!(divide_i32_1, divide_i32_2); assert_eq!(divide_i32_2, divide_i32_3); @@ -665,16 +678,16 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Bigint, BinaryOperator::Divide)?; let divide_i64_1 = divide_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let divide_i64_2 = divide_evaluator .0 - .binary_eval(&DataValue::Int64(1), &DataValue::Null); + .binary_eval(&DataValue::Int64(1), &DataValue::Null)?; let divide_i64_3 = divide_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int64(1)); + .binary_eval(&DataValue::Null, &DataValue::Int64(1))?; let divide_i64_4 = divide_evaluator .0 - .binary_eval(&DataValue::Int64(1), &DataValue::Int64(1)); + .binary_eval(&DataValue::Int64(1), &DataValue::Int64(1))?; assert_eq!(divide_i64_1, divide_i64_2); assert_eq!(divide_i64_2, divide_i64_3); @@ -684,17 +697,17 @@ mod test { EvaluatorFactory::binary_create(LogicalType::Double, BinaryOperator::Divide)?; let divide_f64_1 = divide_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Null); + .binary_eval(&DataValue::Null, &DataValue::Null)?; let divide_f64_2 = divide_evaluator .0 - .binary_eval(&DataValue::Float64(OrderedFloat(1.0)), &DataValue::Null); + .binary_eval(&DataValue::Float64(OrderedFloat(1.0)), &DataValue::Null)?; let divide_f64_3 = divide_evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Float64(OrderedFloat(1.0))); + .binary_eval(&DataValue::Null, &DataValue::Float64(OrderedFloat(1.0)))?; let divide_f64_4 = divide_evaluator.0.binary_eval( &DataValue::Float64(OrderedFloat(1.0)), &DataValue::Float64(OrderedFloat(1.0)), - ); + )?; assert_eq!(divide_f64_1, divide_f64_2); assert_eq!(divide_f64_2, divide_f64_3); @@ -709,14 +722,14 @@ mod test { assert_eq!( evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(0),), + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(0),)?, DataValue::Boolean(true) ); let evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Lt)?; assert_eq!( evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(0),), + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(0),)?, DataValue::Boolean(false) ); let evaluator = @@ -724,7 +737,7 @@ mod test { assert_eq!( evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1),), + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1),)?, DataValue::Boolean(true) ); let evaluator = @@ -732,7 +745,7 @@ mod test { assert_eq!( evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1),), + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1),)?, DataValue::Boolean(true) ); let evaluator = @@ -740,28 +753,28 @@ mod test { assert_eq!( evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1),), + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1),)?, DataValue::Boolean(false) ); let evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Eq)?; assert_eq!( evaluator .0 - .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1),), + .binary_eval(&DataValue::Int32(1), &DataValue::Int32(1),)?, DataValue::Boolean(true) ); let evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Gt)?; assert_eq!( evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(0),), + .binary_eval(&DataValue::Null, &DataValue::Int32(0),)?, DataValue::Null ); let evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Lt)?; assert_eq!( evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(0),), + .binary_eval(&DataValue::Null, &DataValue::Int32(0),)?, DataValue::Null ); let evaluator = @@ -769,7 +782,7 @@ mod test { assert_eq!( evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(1),), + .binary_eval(&DataValue::Null, &DataValue::Int32(1),)?, DataValue::Null ); let evaluator = @@ -777,7 +790,7 @@ mod test { assert_eq!( evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(1),), + .binary_eval(&DataValue::Null, &DataValue::Int32(1),)?, DataValue::Null ); let evaluator = @@ -785,19 +798,21 @@ mod test { assert_eq!( evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(1),), + .binary_eval(&DataValue::Null, &DataValue::Int32(1),)?, DataValue::Null ); let evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Eq)?; assert_eq!( evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Int32(1),), + .binary_eval(&DataValue::Null, &DataValue::Int32(1),)?, DataValue::Null ); let evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Eq)?; assert_eq!( - evaluator.0.binary_eval(&DataValue::Null, &DataValue::Null,), + evaluator + .0 + .binary_eval(&DataValue::Null, &DataValue::Null,)?, DataValue::Null ); @@ -810,50 +825,50 @@ mod test { assert_eq!( evaluator .0 - .binary_eval(&DataValue::Boolean(true), &DataValue::Boolean(true),), + .binary_eval(&DataValue::Boolean(true), &DataValue::Boolean(true),)?, DataValue::Boolean(true) ); assert_eq!( evaluator .0 - .binary_eval(&DataValue::Boolean(false), &DataValue::Boolean(true),), + .binary_eval(&DataValue::Boolean(false), &DataValue::Boolean(true),)?, DataValue::Boolean(false) ); assert_eq!( evaluator .0 - .binary_eval(&DataValue::Boolean(false), &DataValue::Boolean(false),), + .binary_eval(&DataValue::Boolean(false), &DataValue::Boolean(false),)?, DataValue::Boolean(false) ); assert_eq!( evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Boolean(true),), + .binary_eval(&DataValue::Null, &DataValue::Boolean(true),)?, DataValue::Null ); let evaluator = EvaluatorFactory::binary_create(LogicalType::Boolean, BinaryOperator::Or)?; assert_eq!( evaluator .0 - .binary_eval(&DataValue::Boolean(true), &DataValue::Boolean(true),), + .binary_eval(&DataValue::Boolean(true), &DataValue::Boolean(true),)?, DataValue::Boolean(true) ); assert_eq!( evaluator .0 - .binary_eval(&DataValue::Boolean(false), &DataValue::Boolean(true),), + .binary_eval(&DataValue::Boolean(false), &DataValue::Boolean(true),)?, DataValue::Boolean(true) ); assert_eq!( evaluator .0 - .binary_eval(&DataValue::Boolean(false), &DataValue::Boolean(false),), + .binary_eval(&DataValue::Boolean(false), &DataValue::Boolean(false),)?, DataValue::Boolean(false) ); assert_eq!( evaluator .0 - .binary_eval(&DataValue::Null, &DataValue::Boolean(true),), + .binary_eval(&DataValue::Null, &DataValue::Boolean(true),)?, DataValue::Boolean(true) ); @@ -878,7 +893,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Boolean(false) ); let evaluator = EvaluatorFactory::binary_create( @@ -897,7 +912,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Boolean(true) ); let evaluator = EvaluatorFactory::binary_create( @@ -916,7 +931,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Boolean(true) ); let evaluator = EvaluatorFactory::binary_create( @@ -935,7 +950,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Boolean(true) ); let evaluator = EvaluatorFactory::binary_create( @@ -954,7 +969,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Boolean(false) ); let evaluator = EvaluatorFactory::binary_create( @@ -973,7 +988,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Boolean(true) ); let evaluator = EvaluatorFactory::binary_create( @@ -988,7 +1003,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Null ); let evaluator = EvaluatorFactory::binary_create( @@ -1003,7 +1018,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Null ); let evaluator = EvaluatorFactory::binary_create( @@ -1018,7 +1033,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Null ); let evaluator = EvaluatorFactory::binary_create( @@ -1033,7 +1048,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Null ); let evaluator = EvaluatorFactory::binary_create( @@ -1048,7 +1063,7 @@ mod test { ty: Utf8Type::Variable(None), unit: CharLengthUnits::Characters, }, - ), + )?, DataValue::Null ); @@ -1058,155 +1073,155 @@ mod test { #[test] fn test_binary_op_time32_and_time64() -> Result<(), DatabaseError> { let evaluator_time32 = - EvaluatorFactory::binary_create(LogicalType::Time(None, false), BinaryOperator::Plus)?; + EvaluatorFactory::binary_create(LogicalType::Time(None), BinaryOperator::Plus)?; assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(4190119896, 3, false), - &DataValue::Time32(2621204256, 4, false), - ), - DataValue::Time32(2618593017, 4, false) + &DataValue::Time32(4190119896, 3), + &DataValue::Time32(2621204256, 4), + )?, + DataValue::Time32(2618593017, 4) ); assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(4190175696, 3, false), - &DataValue::Time32(2621224256, 4, false), - ), + &DataValue::Time32(4190175696, 3), + &DataValue::Time32(2621224256, 4), + )?, DataValue::Null ); let evaluator_time32 = - EvaluatorFactory::binary_create(LogicalType::Time(None, false), BinaryOperator::Minus)?; + EvaluatorFactory::binary_create(LogicalType::Time(None), BinaryOperator::Minus)?; assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(4190119896, 3, false), - &DataValue::Time32(2621204256, 4, false), - ), + &DataValue::Time32(4190119896, 3), + &DataValue::Time32(2621204256, 4), + )?, DataValue::Null ); assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(2621204256, 4, false), - &DataValue::Time32(4190119896, 3, false), - ), - DataValue::Time32(2375496, 4, false) + &DataValue::Time32(2621204256, 4), + &DataValue::Time32(4190119896, 3), + )?, + DataValue::Time32(2375496, 4) ); let evaluator_time32 = - EvaluatorFactory::binary_create(LogicalType::Time(None, false), BinaryOperator::Gt)?; + EvaluatorFactory::binary_create(LogicalType::Time(None), BinaryOperator::Gt)?; let evaluator_time64 = EvaluatorFactory::binary_create( LogicalType::TimeStamp(None, false), BinaryOperator::Gt, )?; assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(2621204256, 4, false), - &DataValue::Time32(4190119896, 3, false), - ), + &DataValue::Time32(2621204256, 4), + &DataValue::Time32(4190119896, 3), + )?, DataValue::Boolean(true) ); assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(4190119896, 3, false), - &DataValue::Time32(2621204256, 4, false), - ), + &DataValue::Time32(4190119896, 3), + &DataValue::Time32(2621204256, 4), + )?, DataValue::Boolean(false) ); assert_eq!( evaluator_time64.0.binary_eval( &DataValue::Time64(1736055775154814, 6, false), &DataValue::Time64(1738734177256, 3, false), - ), + )?, DataValue::Boolean(false) ); assert_eq!( evaluator_time64.0.binary_eval( &DataValue::Time64(1738734177256, 3, false), &DataValue::Time64(1736055775154814, 6, false), - ), + )?, DataValue::Boolean(true) ); let evaluator_time32 = - EvaluatorFactory::binary_create(LogicalType::Time(None, false), BinaryOperator::GtEq)?; + EvaluatorFactory::binary_create(LogicalType::Time(None), BinaryOperator::GtEq)?; let evaluator_time64 = EvaluatorFactory::binary_create( LogicalType::TimeStamp(None, false), BinaryOperator::GtEq, )?; assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(2621204256, 4, false), - &DataValue::Time32(4190119896, 3, false), - ), + &DataValue::Time32(2621204256, 4), + &DataValue::Time32(4190119896, 3), + )?, DataValue::Boolean(true) ); assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(4190119896, 3, false), - &DataValue::Time32(2621204256, 4, false), - ), + &DataValue::Time32(4190119896, 3), + &DataValue::Time32(2621204256, 4), + )?, DataValue::Boolean(false) ); assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(4190119896, 3, false), - &DataValue::Time32(2618828760, 4, false), - ), + &DataValue::Time32(4190119896, 3), + &DataValue::Time32(2618828760, 4), + )?, DataValue::Boolean(true) ); assert_eq!( evaluator_time64.0.binary_eval( &DataValue::Time64(1736055775154814, 6, false), &DataValue::Time64(1738734177256, 3, false), - ), + )?, DataValue::Boolean(false) ); assert_eq!( evaluator_time64.0.binary_eval( &DataValue::Time64(1738734177256, 3, false), &DataValue::Time64(1736055775154814, 6, false), - ), + )?, DataValue::Boolean(true) ); assert_eq!( evaluator_time64.0.binary_eval( &DataValue::Time64(1738734177256, 3, false), &DataValue::Time64(1738734177256000, 6, false), - ), + )?, DataValue::Boolean(true) ); let evaluator_time32 = - EvaluatorFactory::binary_create(LogicalType::Time(None, false), BinaryOperator::Eq)?; + EvaluatorFactory::binary_create(LogicalType::Time(None), BinaryOperator::Eq)?; let evaluator_time64 = EvaluatorFactory::binary_create( LogicalType::TimeStamp(None, false), BinaryOperator::Eq, )?; assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(4190119896, 3, false), - &DataValue::Time32(2621204256, 4, false), - ), + &DataValue::Time32(4190119896, 3), + &DataValue::Time32(2621204256, 4), + )?, DataValue::Boolean(false) ); assert_eq!( evaluator_time32.0.binary_eval( - &DataValue::Time32(4190119896, 3, false), - &DataValue::Time32(2618828760, 4, false), - ), + &DataValue::Time32(4190119896, 3), + &DataValue::Time32(2618828760, 4), + )?, DataValue::Boolean(true) ); assert_eq!( evaluator_time64.0.binary_eval( &DataValue::Time64(1738734177256, 3, false), &DataValue::Time64(1736055775154814, 6, false), - ), + )?, DataValue::Boolean(false) ); assert_eq!( evaluator_time64.0.binary_eval( &DataValue::Time64(1738734177256, 3, false), &DataValue::Time64(1738734177256000, 6, false), - ), + )?, DataValue::Boolean(true) ); diff --git a/src/types/evaluator/null.rs b/src/types/evaluator/null.rs index 1632a644..f0995976 100644 --- a/src/types/evaluator/null.rs +++ b/src/types/evaluator/null.rs @@ -1,3 +1,4 @@ +use crate::errors::DatabaseError; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; use serde::{Deserialize, Serialize}; @@ -9,7 +10,7 @@ pub struct NullBinaryEvaluator; #[typetag::serde] impl BinaryEvaluator for NullBinaryEvaluator { - fn binary_eval(&self, _: &DataValue, _: &DataValue) -> DataValue { - DataValue::Null + fn binary_eval(&self, _: &DataValue, _: &DataValue) -> Result { + Ok(DataValue::Null) } } diff --git a/src/types/evaluator/time32.rs b/src/types/evaluator/time32.rs index c9d99c24..8b41acb0 100644 --- a/src/types/evaluator/time32.rs +++ b/src/types/evaluator/time32.rs @@ -1,3 +1,4 @@ +use crate::errors::DatabaseError; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; use crate::types::value::{ONE_DAY_TO_SEC, ONE_SEC_TO_NANO}; @@ -23,9 +24,9 @@ pub struct TimeNotEqBinaryEvaluator; #[typetag::serde] impl BinaryEvaluator for TimePlusBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - (DataValue::Time32(v1, p1, _), DataValue::Time32(v2, p2, ..)) => { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + (DataValue::Time32(v1, p1), DataValue::Time32(v2, p2)) => { let (mut v1, n1) = DataValue::unpack(*v1, *p1); let (v2, n2) = DataValue::unpack(*v2, *p2); let mut n = n1 + n2; @@ -35,22 +36,22 @@ impl BinaryEvaluator for TimePlusBinaryEvaluator { } let p = if p2 > p1 { *p2 } else { *p1 }; if v1 + v2 > ONE_DAY_TO_SEC { - return DataValue::Null; + return Ok(DataValue::Null); } - DataValue::Time32(DataValue::pack(v1 + v2, n, p), p, false) + DataValue::Time32(DataValue::pack(v1 + v2, n, p), p) } (DataValue::Time32(..), DataValue::Null) | (DataValue::Null, DataValue::Time32(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TimeMinusBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - (DataValue::Time32(v1, p1, _), DataValue::Time32(v2, p2, ..)) => { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + (DataValue::Time32(v1, p1), DataValue::Time32(v2, p2, ..)) => { let (mut v1, mut n1) = DataValue::unpack(*v1, *p1); let (v2, n2) = DataValue::unpack(*v2, *p2); while n1 < n2 { @@ -58,24 +59,24 @@ impl BinaryEvaluator for TimeMinusBinaryEvaluator { n1 += ONE_SEC_TO_NANO; } if v1 < v2 { - return DataValue::Null; + return Ok(DataValue::Null); } let p = if p2 > p1 { *p2 } else { *p1 }; - DataValue::Time32(DataValue::pack(v1 - v2, n1 - n2, p), p, false) + DataValue::Time32(DataValue::pack(v1 - v2, n1 - n2, p), p) } (DataValue::Time32(..), DataValue::Null) | (DataValue::Null, DataValue::Time32(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TimeGtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - (DataValue::Time32(v1, p1, _), DataValue::Time32(v2, p2, ..)) => { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + (DataValue::Time32(v1, p1), DataValue::Time32(v2, p2, ..)) => { let (v1, n1) = DataValue::unpack(*v1, *p1); let (v2, n2) = DataValue::unpack(*v2, *p2); DataValue::Boolean(v1.cmp(&v2).then_with(|| n1.cmp(&n2)).is_gt()) @@ -84,14 +85,14 @@ impl BinaryEvaluator for TimeGtBinaryEvaluator { | (DataValue::Null, DataValue::Time32(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TimeGtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - (DataValue::Time32(v1, p1, _), DataValue::Time32(v2, p2, ..)) => { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + (DataValue::Time32(v1, p1), DataValue::Time32(v2, p2, ..)) => { let (v1, n1) = DataValue::unpack(*v1, *p1); let (v2, n2) = DataValue::unpack(*v2, *p2); DataValue::Boolean(!v1.cmp(&v2).then_with(|| n1.cmp(&n2)).is_lt()) @@ -100,14 +101,14 @@ impl BinaryEvaluator for TimeGtEqBinaryEvaluator { | (DataValue::Null, DataValue::Time32(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TimeLtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - (DataValue::Time32(v1, p1, _), DataValue::Time32(v2, p2, ..)) => { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + (DataValue::Time32(v1, p1), DataValue::Time32(v2, p2, ..)) => { let (v1, n1) = DataValue::unpack(*v1, *p1); let (v2, n2) = DataValue::unpack(*v2, *p2); DataValue::Boolean(v1.cmp(&v2).then_with(|| n1.cmp(&n2)).is_lt()) @@ -116,14 +117,14 @@ impl BinaryEvaluator for TimeLtBinaryEvaluator { | (DataValue::Null, DataValue::Time32(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TimeLtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - (DataValue::Time32(v1, p1, _), DataValue::Time32(v2, p2, ..)) => { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + (DataValue::Time32(v1, p1), DataValue::Time32(v2, p2, ..)) => { let (v1, n1) = DataValue::unpack(*v1, *p1); let (v2, n2) = DataValue::unpack(*v2, *p2); DataValue::Boolean(!v1.cmp(&v2).then_with(|| n1.cmp(&n2)).is_gt()) @@ -132,14 +133,14 @@ impl BinaryEvaluator for TimeLtEqBinaryEvaluator { | (DataValue::Null, DataValue::Time32(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TimeEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - (DataValue::Time32(v1, p1, _), DataValue::Time32(v2, p2, ..)) => { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + (DataValue::Time32(v1, p1), DataValue::Time32(v2, p2, ..)) => { let (v1, n1) = DataValue::unpack(*v1, *p1); let (v2, n2) = DataValue::unpack(*v2, *p2); DataValue::Boolean(v1.cmp(&v2).then_with(|| n1.cmp(&n2)).is_eq()) @@ -148,14 +149,14 @@ impl BinaryEvaluator for TimeEqBinaryEvaluator { | (DataValue::Null, DataValue::Time32(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TimeNotEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { - (DataValue::Time32(v1, p1, _), DataValue::Time32(v2, p2, ..)) => { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { + (DataValue::Time32(v1, p1), DataValue::Time32(v2, p2, ..)) => { let (v1, n1) = DataValue::unpack(*v1, *p1); let (v2, n2) = DataValue::unpack(*v2, *p2); DataValue::Boolean(!v1.cmp(&v2).then_with(|| n1.cmp(&n2)).is_eq()) @@ -164,6 +165,6 @@ impl BinaryEvaluator for TimeNotEqBinaryEvaluator { | (DataValue::Null, DataValue::Time32(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } diff --git a/src/types/evaluator/time64.rs b/src/types/evaluator/time64.rs index f3fa6932..b7cfc696 100644 --- a/src/types/evaluator/time64.rs +++ b/src/types/evaluator/time64.rs @@ -1,3 +1,4 @@ +use crate::errors::DatabaseError; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; use serde::{Deserialize, Serialize}; @@ -18,8 +19,8 @@ pub struct Time64NotEqBinaryEvaluator; #[typetag::serde] impl BinaryEvaluator for Time64GtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Time64(v1, p1, _), DataValue::Time64(v2, p2, _)) => { if let (Some(v1), Some(v2)) = ( DataValue::from_timestamp_precision(*v1, *p1), @@ -38,13 +39,13 @@ impl BinaryEvaluator for Time64GtBinaryEvaluator { | (DataValue::Null, DataValue::Time64(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Time64GtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Time64(v1, p1, _), DataValue::Time64(v2, p2, _)) => { if let (Some(v1), Some(v2)) = ( DataValue::from_timestamp_precision(*v1, *p1), @@ -63,13 +64,13 @@ impl BinaryEvaluator for Time64GtEqBinaryEvaluator { | (DataValue::Null, DataValue::Time64(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Time64LtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Time64(v1, p1, _), DataValue::Time64(v2, p2, _)) => { if let (Some(v1), Some(v2)) = ( DataValue::from_timestamp_precision(*v1, *p1), @@ -88,13 +89,13 @@ impl BinaryEvaluator for Time64LtBinaryEvaluator { | (DataValue::Null, DataValue::Time64(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Time64LtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Time64(v1, p1, _), DataValue::Time64(v2, p2, _)) => { if let (Some(v1), Some(v2)) = ( DataValue::from_timestamp_precision(*v1, *p1), @@ -113,13 +114,13 @@ impl BinaryEvaluator for Time64LtEqBinaryEvaluator { | (DataValue::Null, DataValue::Time64(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Time64EqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Time64(v1, p1, _), DataValue::Time64(v2, p2, _)) => { if let (Some(v1), Some(v2)) = ( DataValue::from_timestamp_precision(*v1, *p1), @@ -138,13 +139,13 @@ impl BinaryEvaluator for Time64EqBinaryEvaluator { | (DataValue::Null, DataValue::Time64(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Time64NotEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Time64(v1, p1, _), DataValue::Time64(v2, p2, _)) => { if let (Some(v1), Some(v2)) = ( DataValue::from_timestamp_precision(*v1, *p1), @@ -163,6 +164,6 @@ impl BinaryEvaluator for Time64NotEqBinaryEvaluator { | (DataValue::Null, DataValue::Time64(..)) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } diff --git a/src/types/evaluator/tuple.rs b/src/types/evaluator/tuple.rs index 6c19dfab..601568af 100644 --- a/src/types/evaluator/tuple.rs +++ b/src/types/evaluator/tuple.rs @@ -1,3 +1,4 @@ +use crate::errors::DatabaseError; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; use serde::{Deserialize, Serialize}; @@ -50,32 +51,32 @@ fn tuple_cmp( #[typetag::serde] impl BinaryEvaluator for TupleEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Tuple(v1, ..), DataValue::Tuple(v2, ..)) => DataValue::Boolean(*v1 == *v2), (DataValue::Null, DataValue::Boolean(_)) | (DataValue::Boolean(_), DataValue::Null) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TupleNotEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Tuple(v1, ..), DataValue::Tuple(v2, ..)) => DataValue::Boolean(*v1 != *v2), (DataValue::Null, DataValue::Boolean(_)) | (DataValue::Boolean(_), DataValue::Null) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TupleGtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Tuple(v1, is_upper1), DataValue::Tuple(v2, is_upper2)) => { tuple_cmp((v1, is_upper1), (v2, is_upper2)) .map(|order| DataValue::Boolean(order.is_gt())) @@ -85,13 +86,13 @@ impl BinaryEvaluator for TupleGtBinaryEvaluator { | (DataValue::Boolean(_), DataValue::Null) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TupleGtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Tuple(v1, is_upper1), DataValue::Tuple(v2, is_upper2)) => { tuple_cmp((v1, is_upper1), (v2, is_upper2)) .map(|order| DataValue::Boolean(order.is_ge())) @@ -101,13 +102,13 @@ impl BinaryEvaluator for TupleGtEqBinaryEvaluator { | (DataValue::Boolean(_), DataValue::Null) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TupleLtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Tuple(v1, is_upper1), DataValue::Tuple(v2, is_upper2)) => { tuple_cmp((v1, is_upper1), (v2, is_upper2)) .map(|order| DataValue::Boolean(order.is_lt())) @@ -117,13 +118,13 @@ impl BinaryEvaluator for TupleLtBinaryEvaluator { | (DataValue::Boolean(_), DataValue::Null) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for TupleLtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Tuple(v1, is_upper1), DataValue::Tuple(v2, is_upper2)) => { tuple_cmp((v1, is_upper1), (v2, is_upper2)) .map(|order| DataValue::Boolean(order.is_le())) @@ -133,6 +134,6 @@ impl BinaryEvaluator for TupleLtEqBinaryEvaluator { | (DataValue::Boolean(_), DataValue::Null) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } diff --git a/src/types/evaluator/uint16.rs b/src/types/evaluator/uint16.rs index e8a4bbab..fc23a0ae 100644 --- a/src/types/evaluator/uint16.rs +++ b/src/types/evaluator/uint16.rs @@ -1,6 +1,7 @@ use crate::numeric_binary_evaluator_definition; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; +use crate::types::DatabaseError; use paste::paste; use serde::{Deserialize, Serialize}; use std::hint; diff --git a/src/types/evaluator/uint32.rs b/src/types/evaluator/uint32.rs index b21e011d..2807517a 100644 --- a/src/types/evaluator/uint32.rs +++ b/src/types/evaluator/uint32.rs @@ -1,6 +1,7 @@ use crate::numeric_binary_evaluator_definition; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; +use crate::types::DatabaseError; use paste::paste; use serde::{Deserialize, Serialize}; use std::hint; diff --git a/src/types/evaluator/uint64.rs b/src/types/evaluator/uint64.rs index 0a3a1274..a5901954 100644 --- a/src/types/evaluator/uint64.rs +++ b/src/types/evaluator/uint64.rs @@ -1,6 +1,7 @@ use crate::numeric_binary_evaluator_definition; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; +use crate::types::DatabaseError; use paste::paste; use serde::{Deserialize, Serialize}; use std::hint; diff --git a/src/types/evaluator/uint8.rs b/src/types/evaluator/uint8.rs index 15530d46..a652672f 100644 --- a/src/types/evaluator/uint8.rs +++ b/src/types/evaluator/uint8.rs @@ -1,6 +1,7 @@ use crate::numeric_binary_evaluator_definition; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; +use crate::types::DatabaseError; use paste::paste; use serde::{Deserialize, Serialize}; use std::hint; diff --git a/src/types/evaluator/utf8.rs b/src/types/evaluator/utf8.rs index a262e575..c041fd0f 100644 --- a/src/types/evaluator/utf8.rs +++ b/src/types/evaluator/utf8.rs @@ -1,3 +1,4 @@ +use crate::errors::DatabaseError; use crate::types::evaluator::BinaryEvaluator; use crate::types::evaluator::DataValue; use crate::types::value::Utf8Type; @@ -31,8 +32,8 @@ pub struct Utf8NotLikeBinaryEvaluator { #[typetag::serde] impl BinaryEvaluator for Utf8GtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Utf8 { value: v1, .. }, DataValue::Utf8 { value: v2, .. }) => { DataValue::Boolean(v1 > v2) } @@ -40,13 +41,13 @@ impl BinaryEvaluator for Utf8GtBinaryEvaluator { | (DataValue::Null, DataValue::Utf8 { .. }) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Utf8GtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Utf8 { value: v1, .. }, DataValue::Utf8 { value: v2, .. }) => { DataValue::Boolean(v1 >= v2) } @@ -54,13 +55,13 @@ impl BinaryEvaluator for Utf8GtEqBinaryEvaluator { | (DataValue::Null, DataValue::Utf8 { .. }) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Utf8LtBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Utf8 { value: v1, .. }, DataValue::Utf8 { value: v2, .. }) => { DataValue::Boolean(v1 < v2) } @@ -68,13 +69,13 @@ impl BinaryEvaluator for Utf8LtBinaryEvaluator { | (DataValue::Null, DataValue::Utf8 { .. }) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Utf8LtEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Utf8 { value: v1, .. }, DataValue::Utf8 { value: v2, .. }) => { DataValue::Boolean(v1 <= v2) } @@ -82,13 +83,13 @@ impl BinaryEvaluator for Utf8LtEqBinaryEvaluator { | (DataValue::Null, DataValue::Utf8 { .. }) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Utf8EqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Utf8 { value: v1, .. }, DataValue::Utf8 { value: v2, .. }) => { DataValue::Boolean(v1 == v2) } @@ -96,13 +97,13 @@ impl BinaryEvaluator for Utf8EqBinaryEvaluator { | (DataValue::Null, DataValue::Utf8 { .. }) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Utf8NotEqBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Utf8 { value: v1, .. }, DataValue::Utf8 { value: v2, .. }) => { DataValue::Boolean(v1 != v2) } @@ -110,13 +111,13 @@ impl BinaryEvaluator for Utf8NotEqBinaryEvaluator { | (DataValue::Null, DataValue::Utf8 { .. }) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Utf8StringConcatBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Utf8 { value: v1, .. }, DataValue::Utf8 { value: v2, .. }) => { DataValue::Utf8 { value: v1.clone() + v2, @@ -128,13 +129,13 @@ impl BinaryEvaluator for Utf8StringConcatBinaryEvaluator { | (DataValue::Null, DataValue::Utf8 { .. }) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Utf8LikeBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Utf8 { value, .. }, DataValue::Utf8 { value: pattern, .. }) => { DataValue::Boolean(string_like(value, pattern, self.escape_char)) } @@ -142,13 +143,13 @@ impl BinaryEvaluator for Utf8LikeBinaryEvaluator { | (DataValue::Null, DataValue::Utf8 { .. }) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } #[typetag::serde] impl BinaryEvaluator for Utf8NotLikeBinaryEvaluator { - fn binary_eval(&self, left: &DataValue, right: &DataValue) -> DataValue { - match (left, right) { + fn binary_eval(&self, left: &DataValue, right: &DataValue) -> Result { + Ok(match (left, right) { (DataValue::Utf8 { value, .. }, DataValue::Utf8 { value: pattern, .. }) => { DataValue::Boolean(!string_like(value, pattern, self.escape_char)) } @@ -156,7 +157,7 @@ impl BinaryEvaluator for Utf8NotLikeBinaryEvaluator { | (DataValue::Null, DataValue::Utf8 { .. }) | (DataValue::Null, DataValue::Null) => DataValue::Null, _ => unsafe { hint::unreachable_unchecked() }, - } + }) } } diff --git a/src/types/mod.rs b/src/types/mod.rs index de3e83fb..620d403e 100644 --- a/src/types/mod.rs +++ b/src/types/mod.rs @@ -48,7 +48,7 @@ pub enum LogicalType { Varchar(Option, CharLengthUnits), Date, DateTime, - Time(Option, bool), + Time(Option), TimeStamp(Option, bool), // decimal (precision, scale) Decimal(Option, Option), @@ -84,7 +84,7 @@ impl LogicalType { } else if type_id == TypeId::of::() { Some(LogicalType::DateTime) } else if type_id == TypeId::of::() { - Some(LogicalType::Time(Some(0), false)) + Some(LogicalType::Time(Some(0))) } else if type_id == TypeId::of::() { Some(LogicalType::Decimal(None, None)) } else if type_id == TypeId::of::() { @@ -117,7 +117,7 @@ impl LogicalType { LogicalType::Decimal(_, _) => Some(16), LogicalType::Date => Some(4), LogicalType::DateTime => Some(8), - LogicalType::Time(_, _) => Some(4), + LogicalType::Time(_) => Some(4), LogicalType::TimeStamp(_, _) => Some(8), LogicalType::Tuple(_) => unreachable!(), } @@ -447,7 +447,7 @@ impl TryFrom for LogicalType { "time's zone is not supported".to_string(), )); } - Ok(LogicalType::Time(precision, false)) + Ok(LogicalType::Time(precision)) } sqlparser::ast::DataType::Timestamp(precision, info) => { let mut zone = false; @@ -502,7 +502,7 @@ impl std::fmt::Display for LogicalType { LogicalType::TimeStamp(precision, zone) => { write!(f, "TimeStamp({:?}, {:?})", precision, zone)? } - LogicalType::Time(precision, zone) => write!(f, "Time({:?}, {:?})", precision, zone)?, + LogicalType::Time(precision) => write!(f, "Time({:?})", precision)?, LogicalType::Decimal(precision, scale) => { write!(f, "Decimal({:?}, {:?})", precision, scale)? } @@ -602,23 +602,9 @@ pub(crate) mod test { fn_assert( &mut cursor, &mut reference_tables, - LogicalType::Time(Some(3), true), - )?; - fn_assert( - &mut cursor, - &mut reference_tables, - LogicalType::Time(Some(3), false), - )?; - fn_assert( - &mut cursor, - &mut reference_tables, - LogicalType::Time(None, true), - )?; - fn_assert( - &mut cursor, - &mut reference_tables, - LogicalType::Time(None, false), + LogicalType::Time(Some(3)), )?; + fn_assert(&mut cursor, &mut reference_tables, LogicalType::Time(None))?; fn_assert( &mut cursor, &mut reference_tables, diff --git a/src/types/value.rs b/src/types/value.rs index ac583a96..207655ad 100644 --- a/src/types/value.rs +++ b/src/types/value.rs @@ -1,7 +1,6 @@ use super::LogicalType; use crate::errors::DatabaseError; use crate::storage::table_codec::{BumpBytes, BOUND_MAX_TAG, BOUND_MIN_TAG}; -use crate::types::LogicalType::{Date, TimeStamp}; use byteorder::{LittleEndian, ReadBytesExt, WriteBytesExt}; use chrono::format::{DelayedFormat, StrftimeItems}; use chrono::{DateTime, Datelike, NaiveDate, NaiveDateTime, NaiveTime, Timelike, Utc}; @@ -70,7 +69,7 @@ pub enum DataValue { Date32(i32), /// Date stored as a signed 64bit int timestamp since UNIX epoch 1970-01-01 Date64(i64), - Time32(u32, u64, bool), + Time32(u32, u64), Time64(i64, u64, bool), Decimal(Decimal), /// (values, is_upper) @@ -258,15 +257,56 @@ macro_rules! varchar_cast { } macro_rules! numeric_to_boolean { - ($value:expr) => { + ($value:expr, $from_ty:expr) => { match $value { 0 => Ok(DataValue::Boolean(false)), 1 => Ok(DataValue::Boolean(true)), - _ => Err(DatabaseError::CastFail), + _ => Err(DatabaseError::CastFail { + from: $from_ty, + to: LogicalType::Boolean, + }), } }; } +macro_rules! float_to_int { + ($float_value:expr, $int_type:ty, $float_type:ty) => {{ + let float_value: $float_type = $float_value; + if float_value.is_nan() { + Ok(0) + } else if float_value <= 0.0 || float_value > <$int_type>::MAX as $float_type { + Err(DatabaseError::OverFlow) + } else { + Ok(float_value as $int_type) + } + }}; +} + +macro_rules! decimal_to_int { + ($decimal:expr, $int_type:ty) => {{ + let d = $decimal; + if d.is_sign_negative() { + if <$int_type>::MIN == 0 { + 0 + } else { + let min = Decimal::from(<$int_type>::MIN); + if d <= min { + <$int_type>::MIN + } else { + d.to_i128().unwrap() as $int_type + } + } + } else { + let max = Decimal::from(<$int_type>::MAX); + if d >= max { + <$int_type>::MAX + } else { + d.to_i128().unwrap() as $int_type + } + } + }}; +} + impl DataValue { pub fn float(&self) -> Option { if let DataValue::Float32(val) = self { @@ -408,7 +448,7 @@ impl DataValue { _ => 31, }; let scaled_a = combined >> p; - let b = combined & 2_u32.pow(p) - 1; + let b = combined & (2_u32.pow(p) - 1); (b, scaled_a * (1000000000 / 10_u32.pow(precision as u32))) } @@ -420,8 +460,8 @@ impl DataValue { Self::date_time_format(value).map(|fmt| format!("{}", fmt)) } - fn format_time(value: u32, presicion: u64) -> Option { - Self::time_format(value, presicion, false).map(|fmt| format!("{}", fmt)) + fn format_time(value: u32, precision: u64) -> Option { + Self::time_format(value, precision).map(|fmt| format!("{}", fmt)) } fn format_timestamp(value: i64, precision: u64) -> Option { @@ -460,11 +500,11 @@ impl DataValue { }, LogicalType::Date => DataValue::Date32(UNIX_DATETIME.num_days_from_ce()), LogicalType::DateTime => DataValue::Date64(UNIX_DATETIME.and_utc().timestamp()), - LogicalType::Time(precision, zone) => match precision { - Some(i) => DataValue::Time32(UNIX_TIME.num_seconds_from_midnight(), *i, *zone), - None => DataValue::Time32(UNIX_TIME.num_seconds_from_midnight(), 0, *zone), + LogicalType::Time(precision) => match precision { + Some(i) => DataValue::Time32(UNIX_TIME.num_seconds_from_midnight(), *i), + None => DataValue::Time32(UNIX_TIME.num_seconds_from_midnight(), 0), }, - TimeStamp(precision, zone) => match precision { + LogicalType::TimeStamp(precision, zone) => match precision { Some(3) => DataValue::Time64(UNIX_DATETIME.and_utc().timestamp_millis(), 3, *zone), Some(6) => DataValue::Time64(UNIX_DATETIME.and_utc().timestamp_micros(), 6, *zone), Some(9) => { @@ -733,7 +773,7 @@ impl DataValue { } DataValue::Date64(reader.read_i64::()?) } - LogicalType::Time(precision, zone) => { + LogicalType::Time(precision) => { let precision = match precision { Some(precision) => *precision, None => 0, @@ -742,9 +782,9 @@ impl DataValue { reader.seek(SeekFrom::Current(4))?; return Ok(None); } - DataValue::Time32(reader.read_u32::()?, precision, *zone) + DataValue::Time32(reader.read_u32::()?, precision) } - TimeStamp(precision, zone) => { + LogicalType::TimeStamp(precision, zone) => { let precision = match precision { Some(precision) => *precision, None => 0, @@ -797,8 +837,8 @@ impl DataValue { } => LogicalType::Char(*len, *unit), DataValue::Date32(_) => LogicalType::Date, DataValue::Date64(_) => LogicalType::DateTime, - DataValue::Time32(..) => LogicalType::Time(None, false), - DataValue::Time64(..) => TimeStamp(None, false), + DataValue::Time32(..) => LogicalType::Time(None), + DataValue::Time64(..) => LogicalType::TimeStamp(None, false), DataValue::Decimal(_) => LogicalType::Decimal(None, None), DataValue::Tuple(values, ..) => { let types = values.iter().map(|v| v.logical_type()).collect_vec(); @@ -1068,7 +1108,10 @@ impl DataValue { LogicalType::Varchar(len, unit) => { varchar_cast!(value, len, Utf8Type::Variable(*len), *unit) } - _ => Err(DatabaseError::CastFail), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Float32(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1081,12 +1124,57 @@ impl DataValue { varchar_cast!(value, len, Utf8Type::Variable(*len), *unit) } LogicalType::Decimal(_, option) => { - let mut decimal = Decimal::from_f32(value.0).ok_or(DatabaseError::CastFail)?; + let mut decimal = + Decimal::from_f32(value.0).ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + })?; Self::decimal_round_f(option, &mut decimal); Ok(DataValue::Decimal(decimal)) } - _ => Err(DatabaseError::CastFail), + LogicalType::Tinyint => { + Ok(DataValue::Int8(float_to_int!(value.into_inner(), i8, f32)?)) + } + LogicalType::Smallint => Ok(DataValue::Int16(float_to_int!( + value.into_inner(), + i16, + f32 + )?)), + LogicalType::Integer => Ok(DataValue::Int32(float_to_int!( + value.into_inner(), + i32, + f32 + )?)), + LogicalType::Bigint => Ok(DataValue::Int64(float_to_int!( + value.into_inner(), + i64, + f32 + )?)), + LogicalType::UTinyint => Ok(DataValue::UInt8(float_to_int!( + value.into_inner(), + u8, + f32 + )?)), + LogicalType::USmallint => Ok(DataValue::UInt16(float_to_int!( + value.into_inner(), + u16, + f32 + )?)), + LogicalType::UInteger => Ok(DataValue::UInt32(float_to_int!( + value.into_inner(), + u32, + f32 + )?)), + LogicalType::UBigint => Ok(DataValue::UInt64(float_to_int!( + value.into_inner(), + u64, + f32 + )?)), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Float64(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1099,12 +1187,57 @@ impl DataValue { varchar_cast!(value, len, Utf8Type::Variable(*len), *unit) } LogicalType::Decimal(_, option) => { - let mut decimal = Decimal::from_f64(value.0).ok_or(DatabaseError::CastFail)?; + let mut decimal = + Decimal::from_f64(value.0).ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + })?; Self::decimal_round_f(option, &mut decimal); Ok(DataValue::Decimal(decimal)) } - _ => Err(DatabaseError::CastFail), + LogicalType::Tinyint => { + Ok(DataValue::Int8(float_to_int!(value.into_inner(), i8, f64)?)) + } + LogicalType::Smallint => Ok(DataValue::Int16(float_to_int!( + value.into_inner(), + i16, + f64 + )?)), + LogicalType::Integer => Ok(DataValue::Int32(float_to_int!( + value.into_inner(), + i32, + f64 + )?)), + LogicalType::Bigint => Ok(DataValue::Int64(float_to_int!( + value.into_inner(), + i64, + f64 + )?)), + LogicalType::UTinyint => Ok(DataValue::UInt8(float_to_int!( + value.into_inner(), + u8, + f64 + )?)), + LogicalType::USmallint => Ok(DataValue::UInt16(float_to_int!( + value.into_inner(), + u16, + f64 + )?)), + LogicalType::UInteger => Ok(DataValue::UInt32(float_to_int!( + value.into_inner(), + u32, + f64 + )?)), + LogicalType::UBigint => Ok(DataValue::UInt64(float_to_int!( + value.into_inner(), + u64, + f64 + )?)), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Int8(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1130,8 +1263,11 @@ impl DataValue { Ok(DataValue::Decimal(decimal)) } - LogicalType::Boolean => numeric_to_boolean!(value), - _ => Err(DatabaseError::CastFail), + LogicalType::Boolean => numeric_to_boolean!(value, self.logical_type()), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Int16(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1157,8 +1293,11 @@ impl DataValue { Ok(DataValue::Decimal(decimal)) } - LogicalType::Boolean => numeric_to_boolean!(value), - _ => Err(DatabaseError::CastFail), + LogicalType::Boolean => numeric_to_boolean!(value, self.logical_type()), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Int32(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1184,8 +1323,11 @@ impl DataValue { Ok(DataValue::Decimal(decimal)) } - LogicalType::Boolean => numeric_to_boolean!(value), - _ => Err(DatabaseError::CastFail), + LogicalType::Boolean => numeric_to_boolean!(value, self.logical_type()), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Int64(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1211,8 +1353,11 @@ impl DataValue { Ok(DataValue::Decimal(decimal)) } - LogicalType::Boolean => numeric_to_boolean!(value), - _ => Err(DatabaseError::CastFail), + LogicalType::Boolean => numeric_to_boolean!(value, self.logical_type()), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::UInt8(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1238,8 +1383,11 @@ impl DataValue { Ok(DataValue::Decimal(decimal)) } - LogicalType::Boolean => numeric_to_boolean!(value), - _ => Err(DatabaseError::CastFail), + LogicalType::Boolean => numeric_to_boolean!(value, self.logical_type()), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::UInt16(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1265,8 +1413,11 @@ impl DataValue { Ok(DataValue::Decimal(decimal)) } - LogicalType::Boolean => numeric_to_boolean!(value), - _ => Err(DatabaseError::CastFail), + LogicalType::Boolean => numeric_to_boolean!(value, self.logical_type()), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::UInt32(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1292,8 +1443,11 @@ impl DataValue { Ok(DataValue::Decimal(decimal)) } - LogicalType::Boolean => numeric_to_boolean!(value), - _ => Err(DatabaseError::CastFail), + LogicalType::Boolean => numeric_to_boolean!(value, self.logical_type()), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::UInt64(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), @@ -1319,78 +1473,72 @@ impl DataValue { Ok(DataValue::Decimal(decimal)) } - LogicalType::Boolean => numeric_to_boolean!(value), - _ => Err(DatabaseError::CastFail), + LogicalType::Boolean => numeric_to_boolean!(value, self.logical_type()), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, - DataValue::Utf8 { value, .. } => match to { + DataValue::Utf8 { ref value, .. } => match to { LogicalType::SqlNull => Ok(DataValue::Null), - LogicalType::Boolean => Ok(DataValue::Boolean(bool::from_str(&value)?)), - LogicalType::Tinyint => Ok(DataValue::Int8(i8::from_str(&value)?)), - LogicalType::UTinyint => Ok(DataValue::UInt8(u8::from_str(&value)?)), - LogicalType::Smallint => Ok(DataValue::Int16(i16::from_str(&value)?)), - LogicalType::USmallint => Ok(DataValue::UInt16(u16::from_str(&value)?)), - LogicalType::Integer => Ok(DataValue::Int32(i32::from_str(&value)?)), - LogicalType::UInteger => Ok(DataValue::UInt32(u32::from_str(&value)?)), - LogicalType::Bigint => Ok(DataValue::Int64(i64::from_str(&value)?)), - LogicalType::UBigint => Ok(DataValue::UInt64(u64::from_str(&value)?)), - LogicalType::Float => Ok(DataValue::Float32(OrderedFloat(f32::from_str(&value)?))), - LogicalType::Double => Ok(DataValue::Float64(OrderedFloat(f64::from_str(&value)?))), + LogicalType::Boolean => Ok(DataValue::Boolean(bool::from_str(value)?)), + LogicalType::Tinyint => Ok(DataValue::Int8(i8::from_str(value)?)), + LogicalType::UTinyint => Ok(DataValue::UInt8(u8::from_str(value)?)), + LogicalType::Smallint => Ok(DataValue::Int16(i16::from_str(value)?)), + LogicalType::USmallint => Ok(DataValue::UInt16(u16::from_str(value)?)), + LogicalType::Integer => Ok(DataValue::Int32(i32::from_str(value)?)), + LogicalType::UInteger => Ok(DataValue::UInt32(u32::from_str(value)?)), + LogicalType::Bigint => Ok(DataValue::Int64(i64::from_str(value)?)), + LogicalType::UBigint => Ok(DataValue::UInt64(u64::from_str(value)?)), + LogicalType::Float => Ok(DataValue::Float32(OrderedFloat(f32::from_str(value)?))), + LogicalType::Double => Ok(DataValue::Float64(OrderedFloat(f64::from_str(value)?))), LogicalType::Char(len, unit) => { varchar_cast!(value, Some(len), Utf8Type::Fixed(*len), *unit) } LogicalType::Varchar(len, unit) => { varchar_cast!(value, len, Utf8Type::Variable(*len), *unit) } - Date => { - let value = NaiveDate::parse_from_str(&value, DATE_FMT) - .map(|date| date.num_days_from_ce())?; + LogicalType::Date => { + let value = NaiveDate::parse_from_str(value, DATE_FMT) + .map(|date| date.num_days_from_ce()) + .unwrap(); Ok(DataValue::Date32(value)) } LogicalType::DateTime => { - let value = NaiveDateTime::parse_from_str(&value, DATE_TIME_FMT) + let value = NaiveDateTime::parse_from_str(value, DATE_TIME_FMT) .or_else(|_| { - NaiveDate::parse_from_str(&value, DATE_FMT) + NaiveDate::parse_from_str(value, DATE_FMT) .map(|date| date.and_hms_opt(0, 0, 0).unwrap()) }) .map(|date_time| date_time.and_utc().timestamp())?; Ok(DataValue::Date64(value)) } - LogicalType::Time(precision, zone) => { + LogicalType::Time(precision) => { let precision = match precision { Some(precision) => *precision, None => 0, }; - let fmt = match (precision, *zone) { - (0, false) => TIME_FMT, - (0, true) => TIME_FMT_WITHOUT_PRECISION, - (1..5, false) => TIME_FMT_WITHOUT_ZONE, - _ => TIME_FMT_WITH_ZONE, - }; - let complete_value = if *zone { - match value.contains("+") { - false => format!("{}+00:00", value.clone()), - true => value.clone(), - } + let fmt = if precision == 0 { + TIME_FMT } else { - value.clone() + TIME_FMT_WITHOUT_ZONE }; let (value, nano) = match precision { 0 => ( - NaiveTime::parse_from_str(&complete_value, fmt) + NaiveTime::parse_from_str(value, fmt) .map(|time| time.num_seconds_from_midnight())?, 0, ), - _ => NaiveTime::parse_from_str(&complete_value, fmt) + _ => NaiveTime::parse_from_str(value, fmt) .map(|time| (time.num_seconds_from_midnight(), time.nanosecond()))?, }; Ok(DataValue::Time32( Self::pack(value, nano, precision), precision, - *zone, )) } - TimeStamp(precision, zone) => { + LogicalType::TimeStamp(precision, zone) => { let precision = match precision { Some(precision) => *precision, None => 0, @@ -1427,7 +1575,10 @@ impl DataValue { { value } else { - return Err(DatabaseError::CastFail); + return Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }); } } 0 => value.map(|date_time| date_time.timestamp())?, @@ -1435,14 +1586,20 @@ impl DataValue { }; Ok(DataValue::Time64(value, precision, *zone)) } - LogicalType::Decimal(_, _) => Ok(DataValue::Decimal(Decimal::from_str(&value)?)), - _ => Err(DatabaseError::CastFail), + LogicalType::Decimal(_, _) => Ok(DataValue::Decimal(Decimal::from_str(value)?)), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Date32(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), LogicalType::Char(len, unit) => { varchar_cast!( - Self::format_date(value).ok_or(DatabaseError::CastFail)?, + Self::format_date(value).ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone() + })?, Some(len), Utf8Type::Fixed(*len), *unit @@ -1450,7 +1607,10 @@ impl DataValue { } LogicalType::Varchar(len, unit) => { varchar_cast!( - Self::format_date(value).ok_or(DatabaseError::CastFail)?, + Self::format_date(value).ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone() + })?, len, Utf8Type::Variable(*len), *unit @@ -1459,21 +1619,33 @@ impl DataValue { LogicalType::Date => Ok(DataValue::Date32(value)), LogicalType::DateTime => { let value = NaiveDate::from_num_days_from_ce_opt(value) - .ok_or(DatabaseError::CastFail)? + .ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + })? .and_hms_opt(0, 0, 0) - .ok_or(DatabaseError::CastFail)? + .ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + })? .and_utc() .timestamp(); Ok(DataValue::Date64(value)) } - _ => Err(DatabaseError::CastFail), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Date64(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), LogicalType::Char(len, unit) => { varchar_cast!( - Self::format_datetime(value).ok_or(DatabaseError::CastFail)?, + Self::format_datetime(value).ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone() + })?, Some(len), Utf8Type::Fixed(*len), *unit @@ -1481,7 +1653,10 @@ impl DataValue { } LogicalType::Varchar(len, unit) => { varchar_cast!( - Self::format_datetime(value).ok_or(DatabaseError::CastFail)?, + Self::format_datetime(value).ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone() + })?, len, Utf8Type::Variable(*len), *unit @@ -1489,7 +1664,10 @@ impl DataValue { } LogicalType::Date => { let value = DateTime::from_timestamp(value, 0) - .ok_or(DatabaseError::CastFail)? + .ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + })? .naive_utc() .date() .num_days_from_ce(); @@ -1497,31 +1675,40 @@ impl DataValue { Ok(DataValue::Date32(value)) } LogicalType::DateTime => Ok(DataValue::Date64(value)), - LogicalType::Time(precision, zone) => { + LogicalType::Time(precision) => { let precision = match precision { Some(precision) => *precision, None => 0, }; let value = DateTime::from_timestamp(value, 0) .map(|date_time| date_time.time().num_seconds_from_midnight()) - .ok_or(DatabaseError::CastFail)?; + .ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + })?; - Ok(DataValue::Time32(Self::pack(value, 0, 0), precision, *zone)) + Ok(DataValue::Time32(Self::pack(value, 0, 0), precision)) } - TimeStamp(precision, zone) => { + LogicalType::TimeStamp(precision, zone) => { let precision = match precision { Some(precision) => *precision, None => 0, }; Ok(DataValue::Time64(value, precision, *zone)) } - _ => Err(DatabaseError::CastFail), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, - DataValue::Time32(value, precision, _) => match to { + DataValue::Time32(value, precision) => match to { LogicalType::SqlNull => Ok(DataValue::Null), LogicalType::Char(len, unit) => { varchar_cast!( - Self::format_time(value, precision).ok_or(DatabaseError::CastFail)?, + Self::format_time(value, precision).ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone() + })?, Some(len), Utf8Type::Fixed(*len), *unit @@ -1529,19 +1716,33 @@ impl DataValue { } LogicalType::Varchar(len, unit) => { varchar_cast!( - Self::format_time(value, precision).ok_or(DatabaseError::CastFail)?, + Self::format_time(value, precision).ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone() + })?, len, Utf8Type::Variable(*len), *unit ) } - _ => Err(DatabaseError::CastFail), + LogicalType::Time(to_precision) => { + Ok(DataValue::Time32(value, to_precision.unwrap_or(0))) + } + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Time64(value, precision, _) => match to { LogicalType::SqlNull => Ok(DataValue::Null), LogicalType::Char(len, unit) => { varchar_cast!( - Self::format_timestamp(value, precision).ok_or(DatabaseError::CastFail)?, + Self::format_timestamp(value, precision).ok_or( + DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone() + } + )?, Some(len), Utf8Type::Fixed(*len), *unit @@ -1549,15 +1750,23 @@ impl DataValue { } LogicalType::Varchar(len, unit) => { varchar_cast!( - Self::format_timestamp(value, precision).ok_or(DatabaseError::CastFail)?, + Self::format_timestamp(value, precision).ok_or( + DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone() + } + )?, len, Utf8Type::Variable(*len), *unit ) } - Date => { + LogicalType::Date => { let value = Self::from_timestamp_precision(value, precision) - .ok_or(DatabaseError::CastFail)? + .ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + })? .naive_utc() .date() .num_days_from_ce(); @@ -1566,11 +1775,14 @@ impl DataValue { } LogicalType::DateTime => { let value = Self::from_timestamp_precision(value, precision) - .ok_or(DatabaseError::CastFail)? + .ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + })? .timestamp(); Ok(DataValue::Date64(value)) } - LogicalType::Time(p, zone) => { + LogicalType::Time(p) => { let p = match p { Some(p) => *p, None => 0, @@ -1582,26 +1794,34 @@ impl DataValue { date_time.time().nanosecond(), ) }) - .ok_or(DatabaseError::CastFail)?; - Ok(DataValue::Time32(Self::pack(value, nano, p), p, *zone)) - } - TimeStamp(precision, zone) => { - let precision = match precision { - Some(precision) => *precision, - None => 0, - }; - Ok(DataValue::Time64(value, precision, *zone)) - } - _ => Err(DatabaseError::CastFail), + .ok_or(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + })?; + Ok(DataValue::Time32(Self::pack(value, nano, p), p)) + } + LogicalType::TimeStamp(to_precision, zone) => { + Ok(DataValue::Time64(value, to_precision.unwrap_or(0), *zone)) + } + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Decimal(value) => match to { LogicalType::SqlNull => Ok(DataValue::Null), - LogicalType::Float => Ok(DataValue::Float32(OrderedFloat( - value.to_f32().ok_or(DatabaseError::CastFail)?, - ))), - LogicalType::Double => Ok(DataValue::Float64(OrderedFloat( - value.to_f64().ok_or(DatabaseError::CastFail)?, - ))), + LogicalType::Float => Ok(DataValue::Float32(OrderedFloat(value.to_f32().ok_or( + DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }, + )?))), + LogicalType::Double => Ok(DataValue::Float64(OrderedFloat(value.to_f64().ok_or( + DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }, + )?))), LogicalType::Decimal(_, _) => Ok(DataValue::Decimal(value)), LogicalType::Char(len, unit) => { varchar_cast!(value, Some(len), Utf8Type::Fixed(*len), *unit) @@ -1609,7 +1829,18 @@ impl DataValue { LogicalType::Varchar(len, unit) => { varchar_cast!(value, len, Utf8Type::Variable(*len), *unit) } - _ => Err(DatabaseError::CastFail), + LogicalType::Tinyint => Ok(DataValue::Int8(decimal_to_int!(value, i8))), + LogicalType::Smallint => Ok(DataValue::Int16(decimal_to_int!(value, i16))), + LogicalType::Integer => Ok(DataValue::Int32(decimal_to_int!(value, i32))), + LogicalType::Bigint => Ok(DataValue::Int64(decimal_to_int!(value, i64))), + LogicalType::UTinyint => Ok(DataValue::UInt8(decimal_to_int!(value, u8))), + LogicalType::USmallint => Ok(DataValue::UInt16(decimal_to_int!(value, u16))), + LogicalType::UInteger => Ok(DataValue::UInt32(decimal_to_int!(value, u32))), + LogicalType::UBigint => Ok(DataValue::UInt64(decimal_to_int!(value, u64))), + _ => Err(DatabaseError::CastFail { + from: self.logical_type(), + to: to.clone(), + }), }, DataValue::Tuple(mut values, is_upper) => match to { LogicalType::Tuple(types) => { @@ -1620,7 +1851,10 @@ impl DataValue { } Ok(DataValue::Tuple(values, is_upper)) } - _ => Err(DatabaseError::CastFail), + _ => Err(DatabaseError::CastFail { + from: LogicalType::Tuple(values.iter().map(DataValue::logical_type).collect()), + to: to.clone(), + }), }, }?; value.check_len(to)?; @@ -1689,11 +1923,7 @@ impl DataValue { DateTime::from_timestamp(v, 0).map(|date_time| date_time.format(DATE_TIME_FMT)) } - fn time_format<'a>( - v: u32, - precision: u64, - _zone: bool, - ) -> Option>> { + fn time_format<'a>(v: u32, precision: u64) -> Option>> { let (v, n) = Self::unpack(v, precision); NaiveTime::from_num_seconds_from_midnight_opt(v, n) .map(|time| time.format(TIME_FMT_WITHOUT_ZONE)) @@ -1716,13 +1946,7 @@ impl DataValue { match precision { 3 => v.timestamp_millis(), 6 => v.timestamp_micros(), - 9 => { - if let Some(value) = v.timestamp_nanos_opt() { - value - } else { - 0 - } - } + 9 => v.timestamp_nanos_opt().unwrap_or(0), 0 => v.timestamp(), _ => unreachable!(), } @@ -1867,7 +2091,6 @@ impl From<&NaiveTime> for DataValue { DataValue::Time32( Self::pack(value.num_seconds_from_midnight(), value.nanosecond(), 4), 6, - false, ) } } @@ -1878,7 +2101,6 @@ impl From> for DataValue { DataValue::Time32( Self::pack(value.num_seconds_from_midnight(), value.nanosecond(), 4), 0, - false, ) } else { DataValue::Null @@ -1945,11 +2167,9 @@ impl fmt::Display for DataValue { DataValue::Null => write!(f, "null")?, DataValue::Date32(e) => write!(f, "{}", DataValue::date_format(*e).unwrap())?, DataValue::Date64(e) => write!(f, "{}", DataValue::date_time_format(*e).unwrap())?, - DataValue::Time32(e, precision, zone) => write!( - f, - "{}", - DataValue::time_format(*e, *precision, *zone).unwrap() - )?, + DataValue::Time32(e, precision) => { + write!(f, "{}", DataValue::time_format(*e, *precision).unwrap())? + } DataValue::Time64(e, precision, zone) => write!( f, "{}", diff --git a/tests/macros-test/src/main.rs b/tests/macros-test/src/main.rs index 04b1319b..df7e7400 100644 --- a/tests/macros-test/src/main.rs +++ b/tests/macros-test/src/main.rs @@ -81,9 +81,7 @@ mod test { } scala_function!(MyScalaFunction::SUM(LogicalType::Integer, LogicalType::Integer) -> LogicalType::Integer => (|v1: DataValue, v2: DataValue| { - let plus_evaluator = EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Plus)?; - - Ok(plus_evaluator.0.binary_eval(&v1, &v2)) + EvaluatorFactory::binary_create(LogicalType::Integer, BinaryOperator::Plus)?.binary_eval(&v1, &v2) })); table_function!(MyTableFunction::TEST_NUMBERS(LogicalType::Integer) -> [c1: LogicalType::Integer, c2: LogicalType::Integer] => (|v1: DataValue| { diff --git a/tests/slt/crdb/where.slt b/tests/slt/crdb/where.slt new file mode 100644 index 00000000..92079ffd --- /dev/null +++ b/tests/slt/crdb/where.slt @@ -0,0 +1,111 @@ +control sortmode rowsort + +statement ok +drop table if exists kv + +statement ok +CREATE TABLE kv (k INT PRIMARY KEY, v INT) + +statement ok +INSERT INTO kv VALUES (1, 2), (3, 4), (5, 6), (7, 8) + +statement ok +drop table if exists kvString + +statement ok +CREATE TABLE kvString (k STRING PRIMARY KEY, v STRING) + +statement ok +INSERT INTO kvString VALUES ('like1', 'hell%'), ('like2', 'worl%') + +query II +SELECT * FROM kv WHERE True +---- +1 2 +3 4 +5 6 +7 8 + +statement ok +SELECT * FROM kv WHERE False + +query II +SELECT * FROM kv WHERE k IN (1, 3) +---- +1 2 +3 4 + +query II +SELECT * FROM kv WHERE v IN (6) +---- +5 6 + +query II +SELECT * FROM kv WHERE k IN (SELECT k FROM kv) +---- +1 2 +3 4 +5 6 +7 8 + +statement error 1065 +SELECT * FROM kv WHERE (k,v) IN (SELECT * FROM kv) + +query II +SELECT * FROM kv WHERE k IN (SELECT k FROM kv) +---- +1 2 +3 4 +5 6 +7 8 + +statement error +SELECT * FROM kv WHERE nonexistent = 1 + +query B +SELECT 'hello' LIKE v FROM kvString WHERE k LIKE 'like%' ORDER BY k +---- +false +true + +query II +SELECT * FROM kv WHERE k IN (1, 5.0, 9) +---- +1 2 +5 6 + +statement ok +drop table if exists ab + +statement ok +CREATE TABLE ab (pk int primary key,a INT NULL, b INT NULL) + +statement ok +INSERT INTO ab VALUES (0, 1, 10), (1, 2, 20), (2, 3, 30), (3, 4, NULL), (4, NULL, 50), (5, NULL, NULL) + +query II +SELECT a, b FROM ab WHERE a IN (1, 3, 4) +---- +1 10 +3 30 +4 null + +query II +SELECT a, b FROM ab WHERE a IN (1, 3, 4, NULL) +---- +1 10 +3 30 +4 null + +query +SELECT a, b FROM ab WHERE (a, b) IN ((1, 10), (3, 30), (4, 40)) +---- +1 10 +3 30 + +query +SELECT a, b FROM ab WHERE (a, b) IN ((1, 10), (4, NULL), (NULL, 50)) +---- +1 10 +4 null +null 50