From 7461e3927d89c2418da3f32acdc2ad11ff9f664b Mon Sep 17 00:00:00 2001 From: Kould <2435992353@qq.com> Date: Sun, 31 Dec 2023 21:44:15 +0800 Subject: [PATCH 1/2] refactor(tuple_builder) --- src/binder/copy.rs | 15 ++-- .../executor/ddl/alter_table/add_column.rs | 5 +- .../executor/ddl/alter_table/drop_column.rs | 5 +- src/execution/executor/ddl/create_table.rs | 8 +- src/execution/executor/dml/copy_from_file.rs | 49 +++++------ src/execution/mod.rs | 6 +- src/planner/operator/copy_from_file.rs | 2 - src/types/errors.rs | 2 + src/types/tuple_builder.rs | 86 +++++++------------ 9 files changed, 68 insertions(+), 110 deletions(-) diff --git a/src/binder/copy.rs b/src/binder/copy.rs index 9d23eed3..350e35b7 100644 --- a/src/binder/copy.rs +++ b/src/binder/copy.rs @@ -79,27 +79,24 @@ impl<'a, T: Transaction> Binder<'a, T> { }, format: FileFormat::from_options(options), }; - let types = cols.iter().map(|c| c.desc.column_datatype).collect(); - let copy = if to { + if to { // COPY TO - LogicalPlan { + Ok(LogicalPlan { operator: Operator::CopyToFile(CopyToFileOperator { source: ext_source }), childrens: vec![], - } + }) } else { // COPY FROM - LogicalPlan { + Ok(LogicalPlan { operator: Operator::CopyFromFile(CopyFromFileOperator { source: ext_source, - types, columns: cols, table: table_name.to_string(), }), childrens: vec![], - } - }; - Ok(copy) + }) + } } else { Err(BindError::InvalidTable(format!( "not found table {}", diff --git a/src/execution/executor/ddl/alter_table/add_column.rs b/src/execution/executor/ddl/alter_table/add_column.rs index 64b2891e..5a6297c1 100644 --- a/src/execution/executor/ddl/alter_table/add_column.rs +++ b/src/execution/executor/ddl/alter_table/add_column.rs @@ -73,9 +73,6 @@ impl AddColumn { } } - let tuple_builder = TupleBuilder::new_result(); - let tuple = tuple_builder.push_result("ALTER TABLE SUCCESS", "1")?; - - yield tuple; + yield TupleBuilder::build_result("ALTER TABLE SUCCESS".to_string(), "1".to_string())?; } } diff --git a/src/execution/executor/ddl/alter_table/drop_column.rs b/src/execution/executor/ddl/alter_table/drop_column.rs index 63a751e8..f114e7eb 100644 --- a/src/execution/executor/ddl/alter_table/drop_column.rs +++ b/src/execution/executor/ddl/alter_table/drop_column.rs @@ -68,9 +68,6 @@ impl DropColumn { } transaction.drop_column(table_name, column_name, *if_exists)?; - let tuple_builder = TupleBuilder::new_result(); - let tuple = tuple_builder.push_result("ALTER TABLE SUCCESS", "1")?; - - yield tuple; + yield TupleBuilder::build_result("ALTER TABLE SUCCESS".to_string(), "1".to_string())?; } } diff --git a/src/execution/executor/ddl/create_table.rs b/src/execution/executor/ddl/create_table.rs index 58ffec73..387b8018 100644 --- a/src/execution/executor/ddl/create_table.rs +++ b/src/execution/executor/ddl/create_table.rs @@ -32,10 +32,10 @@ impl CreateTable { if_not_exists, } = self.op; let _ = transaction.create_table(table_name.clone(), columns, if_not_exists)?; - let tuple_builder = TupleBuilder::new_result(); - let tuple = tuple_builder - .push_result("CREATE TABLE SUCCESS", format!("{}", table_name).as_str())?; - yield tuple; + yield TupleBuilder::build_result( + "CREATE TABLE SUCCESS".to_string(), + format!("{}", table_name), + )?; } } diff --git a/src/execution/executor/dml/copy_from_file.rs b/src/execution/executor/dml/copy_from_file.rs index af8ae5c4..ac9cc04b 100644 --- a/src/execution/executor/dml/copy_from_file.rs +++ b/src/execution/executor/dml/copy_from_file.rs @@ -71,12 +71,10 @@ impl CopyFromFile { .from_reader(&mut buf_reader), }; - let column_count = self.op.types.len(); - let mut size_count = 0; + let column_count = self.op.columns.len(); + let mut tuple_builder = TupleBuilder::new(self.op.columns.clone()); for record in reader.records() { - let mut tuple_builder = - TupleBuilder::new(self.op.types.clone(), self.op.columns.clone()); // read records and push raw str rows into data chunk builder let record = record?; @@ -89,23 +87,22 @@ impl CopyFromFile { }); } - size_count += 1; - - // push a raw str row and send it if necessary - if let Some(chunk) = tuple_builder.push_str_row(record.iter())? { - tx.blocking_send(chunk).map_err(|_| ExecutorError::Abort)?; - } + self.size += 1; + tx.blocking_send(tuple_builder.build_with_row(record.iter())?) + .map_err(|_| ExecutorError::ChannelClose)?; } - self.size = size_count; Ok(()) } } fn return_result(size: usize, tx: Sender) -> Result<(), ExecutorError> { - let tuple_builder = TupleBuilder::new_result(); - let tuple = - tuple_builder.push_result("COPY FROM SOURCE", format!("import {} rows", size).as_str())?; - tx.blocking_send(tuple).map_err(|_| ExecutorError::Abort)?; + let tuple = TupleBuilder::build_result( + "COPY FROM SOURCE".to_string(), + format!("import {} rows", size), + )?; + + tx.blocking_send(tuple) + .map_err(|_| ExecutorError::ChannelClose)?; Ok(()) } @@ -172,12 +169,7 @@ mod tests { }, }, - types: vec![ - LogicalType::Integer, - LogicalType::Float, - LogicalType::Varchar(Some(10)), - ], - columns: columns.clone(), + columns, }; let executor = CopyFromFile { op: op.clone(), @@ -191,13 +183,16 @@ mod tests { .await; let storage = db.storage; let transaction = RefCell::new(storage.transaction().await?); - let actual = executor.execute(&transaction).next().await.unwrap()?; - let tuple_builder = TupleBuilder::new_result(); - let expected = tuple_builder - .push_result("COPY FROM SOURCE", format!("import {} rows", 2).as_str()) - .unwrap(); - assert_eq!(actual, expected); + let tuple = executor.execute(&transaction).next().await.unwrap()?; + assert_eq!( + tuple, + TupleBuilder::build_result( + "COPY FROM SOURCE".to_string(), + format!("import {} rows", 2) + ) + .unwrap() + ); Ok(()) } diff --git a/src/execution/mod.rs b/src/execution/mod.rs index 9f1caaed..31ce96e2 100644 --- a/src/execution/mod.rs +++ b/src/execution/mod.rs @@ -54,14 +54,12 @@ pub enum ExecutorError { ), #[error("tuple length mismatch: expected {expected} but got {actual}")] LengthMismatch { expected: usize, actual: usize }, - #[error("abort")] - Abort, - #[error("unknown error")] - Unknown, #[error("join error")] JoinError( #[from] #[source] tokio::task::JoinError, ), + #[error("channel close")] + ChannelClose, } diff --git a/src/planner/operator/copy_from_file.rs b/src/planner/operator/copy_from_file.rs index 70d8caa5..12c1413d 100644 --- a/src/planner/operator/copy_from_file.rs +++ b/src/planner/operator/copy_from_file.rs @@ -1,11 +1,9 @@ use crate::binder::copy::ExtSource; use crate::catalog::ColumnRef; -use crate::types::LogicalType; #[derive(Debug, PartialEq, Clone)] pub struct CopyFromFileOperator { pub table: String, pub source: ExtSource, - pub types: Vec, pub columns: Vec, } diff --git a/src/types/errors.rs b/src/types/errors.rs index 6aae5dc1..255d93b4 100644 --- a/src/types/errors.rs +++ b/src/types/errors.rs @@ -67,4 +67,6 @@ pub enum TypeError { #[from] FromUtf8Error, ), + #[error("{0} and {1} do not match")] + MisMatch(String, String), } diff --git a/src/types/tuple_builder.rs b/src/types/tuple_builder.rs index 8544cd1a..c3cd5368 100644 --- a/src/types/tuple_builder.rs +++ b/src/types/tuple_builder.rs @@ -2,82 +2,56 @@ use crate::catalog::{ColumnCatalog, ColumnRef}; use crate::types::errors::TypeError; use crate::types::tuple::Tuple; use crate::types::value::{DataValue, ValueRef}; -use crate::types::LogicalType; -use std::collections::HashMap; use std::sync::Arc; pub struct TupleBuilder { - data_types: Vec, - data_values: Vec, columns: Vec, } impl TupleBuilder { - pub fn new(data_types: Vec, columns: Vec) -> Self { - TupleBuilder { - data_types, - data_values: Vec::new(), - columns, - } + pub fn new(columns: Vec) -> Self { + TupleBuilder { columns } } - pub fn new_result() -> Self { - TupleBuilder { - data_types: Vec::new(), - data_values: Vec::new(), - columns: Vec::new(), - } - } + pub fn build_result(header: String, message: String) -> Result { + let columns: Vec = vec![Arc::new(ColumnCatalog::new_dummy(header))]; + let values: Vec = vec![Arc::new(DataValue::Utf8(Some(message)))]; - pub fn push_result(self, header: &str, message: &str) -> Result { - let columns: Vec = vec![Arc::new(ColumnCatalog::new_dummy(header.to_string()))]; - let values: Vec = vec![Arc::new(DataValue::Utf8(Some(String::from(message))))]; - let t = Tuple { + Ok(Tuple { id: None, columns, values, - }; - Ok(t) + }) } - pub fn push_str_row<'a>( - &mut self, + pub fn build_with_row<'a>( + &self, row: impl IntoIterator, - ) -> Result, TypeError> { - let mut primary_key_index = None; - let columns = self.columns.clone(); - let mut tuple_map = HashMap::new(); + ) -> Result { + let mut values = Vec::with_capacity(self.columns.len()); + let mut primary_key = None; for (i, value) in row.into_iter().enumerate() { - let data_value = DataValue::Utf8(Some(value.to_string())); - let cast_data_value = data_value.cast(&self.data_types[i])?; - self.data_values.push(Arc::new(cast_data_value.clone())); - let col = &columns[i]; - col.id() - .map(|col_id| tuple_map.insert(col_id, Arc::new(cast_data_value.clone()))); - if primary_key_index.is_none() && col.desc.is_primary { - primary_key_index = Some(i); + let data_value = Arc::new( + DataValue::Utf8(Some(value.to_string())).cast(self.columns[i].datatype())?, + ); + + if primary_key.is_none() && self.columns[i].desc.is_primary { + primary_key = Some(data_value.clone()); } + values.push(data_value); + } + if values.len() != self.columns.len() { + return Err(TypeError::MisMatch( + "types".to_string(), + "values".to_string(), + )); } - let primary_col_id = primary_key_index - .map(|i| columns[i].id().unwrap()) - .ok_or_else(|| TypeError::PrimaryKeyNotFound)?; - - let tuple_id = tuple_map - .get(&primary_col_id) - .ok_or_else(|| TypeError::PrimaryKeyNotFound)? - .clone(); - - let tuple = if self.data_values.len() == self.data_types.len() { - Some(Tuple { - id: Some(tuple_id), - columns: self.columns.clone(), - values: self.data_values.clone(), - }) - } else { - None - }; - Ok(tuple) + Ok(Tuple { + id: primary_key, + columns: self.columns.clone(), + values, + }) } } From afb959f76b67cd18f13f382a518cd53a8ffb0853 Mon Sep 17 00:00:00 2001 From: Kould <2435992353@qq.com> Date: Mon, 1 Jan 2024 02:02:40 +0800 Subject: [PATCH 2/2] refactor(value_compute): use Marco for logic encapsulation --- Cargo.toml | 3 +- src/execution/executor/dml/copy_from_file.rs | 2 +- src/expression/value_compute.rs | 989 ++++++------------- 3 files changed, 319 insertions(+), 675 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 0c038fae..f37743a6 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,7 +2,7 @@ [package] name = "kip-sql" -version = "0.0.1-alpha.6" +version = "0.0.1-alpha.7" edition = "2021" authors = ["Kould ", "Xwg "] description = "build the SQL layer of KipDB database" @@ -24,7 +24,6 @@ tracing = "0.1.37" chrono = "0.4.26" tokio = { version = "1.28.2", features = ["full"] } serde = { version = "1", features = ["derive", "rc"] } -serde_json = "1" bincode = "1.3.3" integer-encoding = "3.0.4" strum_macros = "0.24" diff --git a/src/execution/executor/dml/copy_from_file.rs b/src/execution/executor/dml/copy_from_file.rs index ac9cc04b..cb4609bc 100644 --- a/src/execution/executor/dml/copy_from_file.rs +++ b/src/execution/executor/dml/copy_from_file.rs @@ -72,7 +72,7 @@ impl CopyFromFile { }; let column_count = self.op.columns.len(); - let mut tuple_builder = TupleBuilder::new(self.op.columns.clone()); + let tuple_builder = TupleBuilder::new(self.op.columns.clone()); for record in reader.records() { // read records and push raw str rows into data chunk builder diff --git a/src/expression/value_compute.rs b/src/expression/value_compute.rs index ad124318..18b57c54 100644 --- a/src/expression/value_compute.rs +++ b/src/expression/value_compute.rs @@ -4,48 +4,6 @@ use crate::types::value::DataValue; use crate::types::LogicalType; use regex::Regex; -fn unpack_i32(value: DataValue) -> Option { - match value { - DataValue::Int32(inner) => inner, - _ => None, - } -} - -fn unpack_i64(value: DataValue) -> Option { - match value { - DataValue::Int64(inner) => inner, - _ => None, - } -} - -fn unpack_u32(value: DataValue) -> Option { - match value { - DataValue::UInt32(inner) => inner, - _ => None, - } -} - -fn unpack_u64(value: DataValue) -> Option { - match value { - DataValue::UInt64(inner) => inner, - _ => None, - } -} - -fn unpack_f64(value: DataValue) -> Option { - match value { - DataValue::Float64(inner) => inner, - _ => None, - } -} - -fn unpack_f32(value: DataValue) -> Option { - match value { - DataValue::Float32(inner) => inner, - _ => None, - } -} - fn unpack_bool(value: DataValue) -> Option { match value { DataValue::Boolean(inner) => inner, @@ -53,13 +11,6 @@ fn unpack_bool(value: DataValue) -> Option { } } -fn unpack_date(value: DataValue) -> Option { - match value { - DataValue::Date64(inner) => inner, - _ => None, - } -} - fn unpack_utf8(value: DataValue) -> Option { match value { DataValue::Utf8(inner) => inner, @@ -108,6 +59,121 @@ pub fn unary_op(value: &DataValue, op: &UnaryOperator) -> Result { + match $op { + BinaryOperator::Plus => { + let value = if let ($compute_type(Some(v1)), $compute_type(Some(v2))) = + ($left.cast($unified_type)?, $right.cast($unified_type)?) + { + Some(v1 + v2) + } else { + None + }; + + $compute_type(value) + } + BinaryOperator::Minus => { + let value = if let ($compute_type(Some(v1)), $compute_type(Some(v2))) = + ($left.cast($unified_type)?, $right.cast($unified_type)?) + { + Some(v1 - v2) + } else { + None + }; + + $compute_type(value) + } + BinaryOperator::Multiply => { + let value = if let ($compute_type(Some(v1)), $compute_type(Some(v2))) = + ($left.cast($unified_type)?, $right.cast($unified_type)?) + { + Some(v1 * v2) + } else { + None + }; + + $compute_type(value) + } + BinaryOperator::Divide => { + let value = if let ($compute_type(Some(v1)), $compute_type(Some(v2))) = + ($left.cast($unified_type)?, $right.cast($unified_type)?) + { + Some(v1 as f64 / v2 as f64) + } else { + None + }; + + DataValue::Float64(value) + } + + BinaryOperator::Gt => { + let value = if let ($compute_type(Some(v1)), $compute_type(Some(v2))) = + ($left.cast($unified_type)?, $right.cast($unified_type)?) + { + Some(v1 > v2) + } else { + None + }; + + DataValue::Boolean(value) + } + BinaryOperator::Lt => { + let value = if let ($compute_type(Some(v1)), $compute_type(Some(v2))) = + ($left.cast($unified_type)?, $right.cast($unified_type)?) + { + Some(v1 < v2) + } else { + None + }; + + DataValue::Boolean(value) + } + BinaryOperator::GtEq => { + let value = if let ($compute_type(Some(v1)), $compute_type(Some(v2))) = + ($left.cast($unified_type)?, $right.cast($unified_type)?) + { + Some(v1 >= v2) + } else { + None + }; + + DataValue::Boolean(value) + } + BinaryOperator::LtEq => { + let value = if let ($compute_type(Some(v1)), $compute_type(Some(v2))) = + ($left.cast($unified_type)?, $right.cast($unified_type)?) + { + Some(v1 <= v2) + } else { + None + }; + + DataValue::Boolean(value) + } + BinaryOperator::Eq => { + let value = match ($left.cast($unified_type)?, $right.cast($unified_type)?) { + ($compute_type(Some(v1)), $compute_type(Some(v2))) => Some(v1 == v2), + ($compute_type(None), $compute_type(None)) => Some(true), + (_, _) => None, + }; + + DataValue::Boolean(value) + } + BinaryOperator::NotEq => { + let value = match ($left.cast($unified_type)?, $right.cast($unified_type)?) { + ($compute_type(Some(v1)), $compute_type(Some(v2))) => Some(v1 != v2), + ($compute_type(None), $compute_type(None)) => Some(false), + (_, _) => None, + }; + + DataValue::Boolean(value) + } + _ => todo!("unsupported operator"), + } + }; +} + /// Tips: /// - Null values operate as null values pub fn binary_op( @@ -134,98 +200,234 @@ pub fn binary_op( let unified_type = LogicalType::max_logical_type(&left.logical_type(), &right.logical_type())?; let value = match &unified_type { + LogicalType::Tinyint => { + numeric_binary_compute!( + DataValue::Int8, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::Smallint => { + numeric_binary_compute!( + DataValue::Int16, + left.clone(), + right.clone(), + op, + &unified_type + ) + } LogicalType::Integer => { - let left_value = unpack_i32(left.clone().cast(&unified_type)?); - let right_value = unpack_i32(right.clone().cast(&unified_type)?); + numeric_binary_compute!( + DataValue::Int32, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::Bigint => { + numeric_binary_compute!( + DataValue::Int64, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::UTinyint => { + numeric_binary_compute!( + DataValue::UInt8, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::USmallint => { + numeric_binary_compute!( + DataValue::UInt16, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::UInteger => { + numeric_binary_compute!( + DataValue::UInt32, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::UBigint => { + numeric_binary_compute!( + DataValue::UInt64, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::Float => { + numeric_binary_compute!( + DataValue::Float32, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::Double => { + numeric_binary_compute!( + DataValue::Float64, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::Date => { + numeric_binary_compute!( + DataValue::Date32, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::DateTime => { + numeric_binary_compute!( + DataValue::Date64, + left.clone(), + right.clone(), + op, + &unified_type + ) + } + LogicalType::Decimal(_, _) => { + let left_value = left.clone().cast(&unified_type)?; + let right_value = right.clone().cast(&unified_type)?; match op { BinaryOperator::Plus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 + v2) - } else { - None - }; + let value = + if let (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) = + (left_value, right_value) + { + Some(v1 + v2) + } else { + None + }; - DataValue::Int32(value) + DataValue::Decimal(value) } BinaryOperator::Minus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 - v2) - } else { - None - }; + let value = + if let (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) = + (left_value, right_value) + { + Some(v1 - v2) + } else { + None + }; - DataValue::Int32(value) + DataValue::Decimal(value) } BinaryOperator::Multiply => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 * v2) - } else { - None - }; + let value = + if let (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) = + (left_value, right_value) + { + Some(v1 * v2) + } else { + None + }; - DataValue::Int32(value) + DataValue::Decimal(value) } BinaryOperator::Divide => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 as f64 / v2 as f64) - } else { - None - }; + let value = + if let (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) = + (left_value, right_value) + { + Some(v1 / v2) + } else { + None + }; - DataValue::Float64(value) + DataValue::Decimal(value) } BinaryOperator::Gt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 > v2) - } else { - None - }; + let value = + if let (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) = + (left_value, right_value) + { + Some(v1 > v2) + } else { + None + }; DataValue::Boolean(value) } BinaryOperator::Lt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 < v2) - } else { - None - }; + let value = + if let (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) = + (left_value, right_value) + { + Some(v1 < v2) + } else { + None + }; DataValue::Boolean(value) } BinaryOperator::GtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 >= v2) - } else { - None - }; + let value = + if let (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) = + (left_value, right_value) + { + Some(v1 >= v2) + } else { + None + }; DataValue::Boolean(value) } BinaryOperator::LtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 <= v2) - } else { - None - }; + let value = + if let (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) = + (left_value, right_value) + { + Some(v1 <= v2) + } else { + None + }; DataValue::Boolean(value) } BinaryOperator::Eq => { let value = match (left_value, right_value) { - (Some(v1), Some(v2)) => Some(v1 == v2), - (None, None) => Some(true), + (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) => { + Some(v1 == v2) + } + (DataValue::Decimal(None), DataValue::Decimal(None)) => Some(true), (_, _) => None, }; DataValue::Boolean(value) } BinaryOperator::NotEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 != v2) - } else { - None + let value = match (left_value, right_value) { + (DataValue::Decimal(Some(v1)), DataValue::Decimal(Some(v2))) => { + Some(v1 != v2) + } + (DataValue::Decimal(None), DataValue::Decimal(None)) => Some(false), + (_, _) => None, }; DataValue::Boolean(value) @@ -233,96 +435,23 @@ pub fn binary_op( _ => todo!("unsupported operator"), } } - LogicalType::Bigint => { - let left_value = unpack_i64(left.clone().cast(&unified_type)?); - let right_value = unpack_i64(right.clone().cast(&unified_type)?); + LogicalType::Boolean => { + let left_value = unpack_bool(left.clone().cast(&unified_type)?); + let right_value = unpack_bool(right.clone().cast(&unified_type)?); match op { - BinaryOperator::Plus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 + v2) - } else { - None - }; - - DataValue::Int64(value) - } - BinaryOperator::Minus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 - v2) - } else { - None - }; - - DataValue::Int64(value) - } - BinaryOperator::Multiply => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 * v2) - } else { - None - }; - - DataValue::Int64(value) - } - BinaryOperator::Divide => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 as f64 / v2 as f64) - } else { - None - }; - - DataValue::Float64(value) - } - - BinaryOperator::Gt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 > v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Lt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 < v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::GtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 >= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::LtEq => { + BinaryOperator::And => { let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 <= v2) + Some(v1 && v2) } else { None }; DataValue::Boolean(value) } - BinaryOperator::Eq => { - let value = match (left_value, right_value) { - (Some(v1), Some(v2)) => Some(v1 == v2), - (None, None) => Some(true), - (_, _) => None, - }; - - DataValue::Boolean(value) - } - BinaryOperator::NotEq => { + BinaryOperator::Or => { let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 != v2) + Some(v1 || v2) } else { None }; @@ -332,48 +461,11 @@ pub fn binary_op( _ => todo!("unsupported operator"), } } - LogicalType::UInteger => { - let left_value = unpack_u32(left.clone().cast(&unified_type)?); - let right_value = unpack_u32(right.clone().cast(&unified_type)?); + LogicalType::Varchar(_) => { + let left_value = unpack_utf8(left.clone().cast(&unified_type)?); + let right_value = unpack_utf8(right.clone().cast(&unified_type)?); match op { - BinaryOperator::Plus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 + v2) - } else { - None - }; - - DataValue::UInt32(value) - } - BinaryOperator::Minus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 - v2) - } else { - None - }; - - DataValue::UInt32(value) - } - BinaryOperator::Multiply => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 * v2) - } else { - None - }; - - DataValue::UInt32(value) - } - BinaryOperator::Divide => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 as f64 / v2 as f64) - } else { - None - }; - - DataValue::Float64(value) - } - BinaryOperator::Gt => { let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { Some(v1 > v2) @@ -420,466 +512,19 @@ pub fn binary_op( DataValue::Boolean(value) } BinaryOperator::NotEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 != v2) - } else { - None - }; - - DataValue::Boolean(value) - } - _ => todo!("unsupported operator"), - } - } - LogicalType::UBigint => { - let left_value = unpack_u64(left.clone().cast(&unified_type)?); - let right_value = unpack_u64(right.clone().cast(&unified_type)?); - - match op { - BinaryOperator::Plus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 + v2) - } else { - None - }; - - DataValue::UInt64(value) - } - BinaryOperator::Minus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 - v2) - } else { - None - }; - - DataValue::UInt64(value) - } - BinaryOperator::Multiply => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 * v2) - } else { - None - }; - - DataValue::UInt64(value) - } - BinaryOperator::Divide => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 as f64 / v2 as f64) - } else { - None - }; - - DataValue::Float64(value) - } - - BinaryOperator::Gt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 > v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Lt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 < v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::GtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 >= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::LtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 <= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Eq => { let value = match (left_value, right_value) { - (Some(v1), Some(v2)) => Some(v1 == v2), - (None, None) => Some(true), + (Some(v1), Some(v2)) => Some(v1 != v2), + (None, None) => Some(false), (_, _) => None, }; DataValue::Boolean(value) } - BinaryOperator::NotEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 != v2) - } else { - None - }; - - DataValue::Boolean(value) - } - _ => todo!("unsupported operator"), - } - } - LogicalType::Double => { - let left_value = unpack_f64(left.clone().cast(&unified_type)?); - let right_value = unpack_f64(right.clone().cast(&unified_type)?); - - match op { - BinaryOperator::Plus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 + v2) - } else { - None - }; - - DataValue::Float64(value) - } - BinaryOperator::Minus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 - v2) - } else { - None - }; - - DataValue::Float64(value) - } - BinaryOperator::Multiply => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 * v2) - } else { - None - }; - - DataValue::Float64(value) - } - BinaryOperator::Divide => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 / v2) - } else { - None - }; - - DataValue::Float64(value) - } - - BinaryOperator::Gt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 > v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Lt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 < v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::GtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 >= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::LtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 <= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Eq => { - let value = match (left_value, right_value) { - (Some(v1), Some(v2)) => Some(v1 == v2), - (None, None) => Some(true), - (_, _) => None, - }; - - DataValue::Boolean(value) - } - BinaryOperator::NotEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 != v2) - } else { - None - }; - - DataValue::Boolean(value) - } - _ => todo!("unsupported operator"), - } - } - LogicalType::Boolean => { - let left_value = unpack_bool(left.clone().cast(&unified_type)?); - let right_value = unpack_bool(right.clone().cast(&unified_type)?); - - match op { - BinaryOperator::And => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 && v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Or => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 || v2) - } else { - None - }; - - DataValue::Boolean(value) - } - _ => todo!("unsupported operator"), - } - } - LogicalType::Float => { - let left_value = unpack_f32(left.clone().cast(&unified_type)?); - let right_value = unpack_f32(right.clone().cast(&unified_type)?); - - match op { - BinaryOperator::Plus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 + v2) - } else { - None - }; - - DataValue::Float32(value) - } - BinaryOperator::Minus => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 - v2) - } else { - None - }; - - DataValue::Float32(value) - } - BinaryOperator::Multiply => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 * v2) - } else { - None - }; - - DataValue::Float32(value) - } - BinaryOperator::Divide => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 as f64 / v2 as f64) - } else { - None - }; - - DataValue::Float64(value) - } - BinaryOperator::Gt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 > v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Lt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 < v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::GtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 >= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::LtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 <= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Eq => { - let value = match (left_value, right_value) { - (Some(v1), Some(v2)) => Some(v1 == v2), - (None, None) => Some(true), - (_, _) => None, - }; - - DataValue::Boolean(value) - } - BinaryOperator::NotEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 != v2) - } else { - None - }; - - DataValue::Boolean(value) - } - _ => todo!("unsupported operator"), - } - } - LogicalType::SqlNull => DataValue::Boolean(None), - LogicalType::DateTime => { - let left_value = unpack_date(left.clone().cast(&unified_type)?); - let right_value = unpack_date(right.clone().cast(&unified_type)?); - - match op { - BinaryOperator::Gt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 > v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Lt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 < v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::GtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 >= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::LtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 <= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Eq => { - let value = match (left_value, right_value) { - (Some(v1), Some(v2)) => Some(v1 == v2), - (None, None) => Some(true), - (_, _) => None, - }; - - DataValue::Boolean(value) - } - BinaryOperator::NotEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 != v2) - } else { - None - }; - - DataValue::Boolean(value) - } - _ => todo!("unsupported operator"), - } - } - LogicalType::Varchar(None) => { - let left_value = unpack_utf8(left.clone().cast(&unified_type)?); - let right_value = unpack_utf8(right.clone().cast(&unified_type)?); - - match op { - BinaryOperator::Gt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 > v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Lt => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 < v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::GtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 >= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::LtEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 <= v2) - } else { - None - }; - - DataValue::Boolean(value) - } - BinaryOperator::Eq => { - let value = match (left_value, right_value) { - (Some(v1), Some(v2)) => Some(v1 == v2), - (None, None) => Some(true), - (_, _) => None, - }; - - DataValue::Boolean(value) - } - BinaryOperator::NotEq => { - let value = if let (Some(v1), Some(v2)) = (left_value, right_value) { - Some(v1 != v2) - } else { - None - }; - - DataValue::Boolean(value) - } _ => todo!("unsupported operator"), } } - // Utf8 - _ => todo!("unsupported data type"), + LogicalType::SqlNull => return Err(TypeError::NotNull), + LogicalType::Invalid => return Err(TypeError::InvalidType), }; Ok(value)