diff --git a/node_engine/src/lib.rs b/node_engine/src/lib.rs index 86c0fe03..6f36044c 100644 --- a/node_engine/src/lib.rs +++ b/node_engine/src/lib.rs @@ -12,11 +12,36 @@ // See the License for the specific language governing permissions and // limitations under the License. +use data_manipulation::QueryPlan; +pub use node_engine_old::NodeEngineOld; +use postgre_sql::query_ast::Query; +use std::collections::HashMap; +use types::SqlTypeFamily; + mod node_engine_old; -mod query_engine; mod query_engine_old; -mod session; mod session_old; +mod transaction_manager; +mod txn_context; mod worker; -pub use node_engine_old::NodeEngineOld; +#[derive(Default)] +#[allow(dead_code)] +pub struct QueryPlanCache { + plans: HashMap)>, +} + +#[allow(dead_code)] +impl QueryPlanCache { + pub fn allocate(&mut self, name: String, _query_plan: QueryPlan, query_ast: Query, params: Vec) { + self.plans.insert(name, (query_ast, params)); + } + + pub fn lookup(&self, name: &str) -> Option<&(Query, Vec)> { + self.plans.get(name) + } + + pub fn deallocate(&mut self, name: &str) -> Option<(Query, Vec)> { + self.plans.remove(name) + } +} diff --git a/node_engine/src/query_engine_old/mod.rs b/node_engine/src/query_engine_old/mod.rs index c7116f48..56f3f235 100644 --- a/node_engine/src/query_engine_old/mod.rs +++ b/node_engine/src/query_engine_old/mod.rs @@ -19,14 +19,14 @@ use crate::session_old::{ use catalog::CatalogHandlerOld; use data_definition::ExecutionOutcome; use data_manipulation::{ - DynamicTypedTree, QueryExecutionResult, StaticTypedTree, TypedDeleteQuery, TypedInsertQuery, TypedQuery, - TypedSelectQuery, TypedUpdateQuery, UntypedQuery, + DynamicTypedTree, StaticTypedTree, TypedDeleteQuery, TypedInsertQuery, TypedQuery, TypedSelectQuery, + TypedUpdateQuery, UntypedQuery, }; use data_repr::scalar::ScalarValue; use definition::ColumnDef; use definition_planner::DefinitionPlannerOld; use postgre_sql::{ - query_ast::{Extended, Statement}, + query_ast::{Extended, Request, Statement}, query_parser::QueryParser, query_response::{QueryError, QueryEvent}, wire_protocol::{payload::*, Sender}, @@ -153,7 +153,7 @@ impl QueryEngineOld { let result = match &*inner { Inbound::Query { sql } => { match query_parser.parse(&sql) { - Ok(mut statements) => match statements.pop().expect("single query") { + Ok(Request::Statement(statement)) => match statement { Statement::Extended(extended_query) => match extended_query { Extended::Prepare { query, @@ -233,14 +233,16 @@ impl QueryEngineOld { values: type_coerced, })) .execute(param_values) - .map(|r| { let r: QueryEvent = r.into(); r }) - .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }) { + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { Ok(ok) => ok, Err(err) => err, }; - self.sender.lock().unwrap().send(&query_result).expect("To Send to client"); + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); + } } UntypedQuery::Update(update) => { let typed_values = update @@ -285,14 +287,16 @@ impl QueryEngineOld { filter: type_coerced_filter })) .execute(param_values) - .map(|r| { let r: QueryEvent = r.into(); r }) - .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }) { + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { Ok(ok) => ok, Err(err) => err, }; - self.sender.lock().unwrap().send(&query_result).expect("To Send to client"); + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); + } } UntypedQuery::Select(select) => { log::debug!("SELECT UNTYPED VALUES - {:?}", select.projection_items); @@ -325,41 +329,22 @@ impl QueryEngineOld { .map(|value| self.type_coercion.coerce_dynamic(value)); log::debug!("SELECT TYPE COERCED FILTER - {:?}", type_coerced_filter); - let query_result = query_planner + let query_result = match query_planner .plan(TypedQuery::Select(TypedSelectQuery { projection_items: type_coerced, full_table_name: select.full_table_name, filter: type_coerced_filter })) .execute(param_values) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }); - match query_result { - Ok(QueryExecutionResult::Selected((desc, data))) => { - let x45: Vec = QueryEvent::RowDescription(desc).into(); - self.sender.lock().unwrap() - .send(&x45) - .expect("To Send to client"); - let len = data.len(); - for row in data { - let x44: Vec = QueryEvent::DataRow( - row.into_iter() - .map(|scalar| scalar.as_text()) - .collect(), - ).into(); - self.sender.lock().unwrap() - .send(&x44) - .expect("To Send to client"); - } - let x43: Vec = QueryEvent::RecordsSelected(len).into(); - self.sender.lock().unwrap() - .send(&x43) - .expect("To Send to client"); - } - Ok(_) => unreachable!(), - Err(error) => { - self.sender.lock().unwrap().send(&error).expect("To Send to client"); - } + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { + Ok(ok) => ok, + Err(err) => err, + }; + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); } } UntypedQuery::Delete(delete) => { @@ -382,14 +367,16 @@ impl QueryEngineOld { filter: type_coerced_filter })) .execute(param_values) - .map(|r| { let r: QueryEvent = r.into(); r }) - .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }) { + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { Ok(ok) => ok, Err(err) => err, }; - self.sender.lock().unwrap().send(&query_result).expect("To Send to client"); + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); + } } }, None => { @@ -451,14 +438,16 @@ impl QueryEngineOld { filter: type_coerced_filter })) .execute(vec![]) - .map(|r| { let r: QueryEvent = r.into(); r }) - .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }) { + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { Ok(ok) => ok, Err(err) => err, }; - self.sender.lock().unwrap().send(&query_result).expect("To Send to client"); + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); + } } Ok(UntypedQuery::Update(update)) => { let typed_values = update @@ -497,14 +486,16 @@ impl QueryEngineOld { filter: type_coerced_filter })) .execute(vec![]) - .map(|r| { let r: QueryEvent = r.into(); r }) - .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }) { + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { Ok(ok) => ok, Err(err) => err, }; - self.sender.lock().unwrap().send(&query_result).expect("To Send to client"); + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); + } } Ok(UntypedQuery::Insert(insert)) => { log::debug!("INSERT UNTYPED VALUES {:?}", insert.values); @@ -551,14 +542,16 @@ impl QueryEngineOld { values: type_coerced, })) .execute(vec![]) - .map(|r| { let r: QueryEvent = r.into(); r }) - .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }) { + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { Ok(ok) => ok, Err(err) => err, }; - self.sender.lock().unwrap().send(&query_result).expect("To Send to client"); + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); + } } Ok(UntypedQuery::Select(select)) => { log::debug!("SELECT UNTYPED VALUES - {:?}", select.projection_items); @@ -591,39 +584,22 @@ impl QueryEngineOld { .map(|value| self.type_coercion.coerce_dynamic(value)); log::debug!("SELECT TYPE COERCED FILTER - {:?}", type_coerced_filter); - let query_result = query_planner + let query_result = match query_planner .plan(TypedQuery::Select(TypedSelectQuery { projection_items: type_coerced_values, full_table_name: select.full_table_name, filter: type_coerced_filter })) .execute(vec![]) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }); - match query_result { - Ok(QueryExecutionResult::Selected((desc, data))) => { - let x38: Vec = QueryEvent::RowDescription(desc).into(); - self.sender.lock().unwrap() - .send(&x38) - .expect("To Send to client"); - let len = data.len(); - for row in data { - let x37: Vec = QueryEvent::DataRow( - row.into_iter().map(|scalar| scalar.as_text()).collect(), - ).into(); - self.sender.lock().unwrap() - .send(&x37) - .expect("To Send to client"); - } - let x36: Vec = QueryEvent::RecordsSelected(len).into(); - self.sender.lock().unwrap() - .send(&x36) - .expect("To Send to client"); - } - Ok(_) => unreachable!(), - Err(error) => { - self.sender.lock().unwrap().send(&error).expect("To Send to client"); - } + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { + Ok(ok) => ok, + Err(err) => err, + }; + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); } } Err(error) => { @@ -632,21 +608,21 @@ impl QueryEngineOld { self.sender.lock().unwrap().send(&x35).expect("To Send Error to Client"); } }, - Statement::Config(_) => { - // sending ok to the client to proceed with other requests - let x34: Vec = QueryEvent::VariableSet.into(); - self.sender.lock().unwrap() - .send(&x34) - .expect("To Send Result to Client"); - } - _ => unimplemented!(), }, Err(parser_error) => { let x33: Vec = QueryError::syntax_error(parser_error).into(); self.sender.lock().unwrap() .send(&x33) .expect("To Send ParseComplete Event"); + }, + Ok(Request::Config(_)) => { + // sending ok to the client to proceed with other requests + let x34: Vec = QueryEvent::VariableSet.into(); + self.sender.lock().unwrap() + .send(&x34) + .expect("To Send Result to Client"); } + _ => unimplemented!(), } let x32: Vec = QueryEvent::QueryComplete.into(); self.sender.lock().unwrap() @@ -661,8 +637,8 @@ impl QueryEngineOld { } => { match session.get_prepared_statement(&statement_name) { Some(stmt) if stmt.raw_query() == sql => match query_parser.parse(&sql) { - Ok(mut statements) => match statements.pop() { - Some(Statement::Query(query)) => { + Ok(Request::Statement(statement)) => match statement { + Statement::Query(query) => { stmt.parsed_with_params( query, param_types @@ -688,10 +664,11 @@ impl QueryEngineOld { .send(&x29) .expect("To Send Syntax Error Event"); } + _ => unimplemented!(), }, _ => match query_parser.parse(&sql) { - Ok(mut statements) => match statements.pop() { - Some(Statement::Query(query)) => { + Ok(Request::Statement(statement)) => match statement { + Statement::Query(query) => { if param_types.is_empty() || param_types.iter().all(|o| *o != 0) { let mut prep = PreparedStatement::parsed(sql.clone(), query.clone()); prep.parsed_with_params( @@ -722,6 +699,7 @@ impl QueryEngineOld { .send(&x26) .expect("To Send Syntax Error Event"); } + _ => unimplemented!(), }, } Ok(()) @@ -1009,14 +987,16 @@ impl QueryEngineOld { values: type_coerced, })) .execute(portal.param_values()) - .map(|r| { let r: QueryEvent = r.into(); r }) - .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }) { + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { Ok(ok) => ok, Err(err) => err, }; - self.sender.lock().unwrap().send(&query_result).expect("To Send to client"); + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); + } } UntypedQuery::Update(update) => { let typed_values = update @@ -1057,14 +1037,16 @@ impl QueryEngineOld { filter: type_coerced_filter })) .execute(portal.param_values()) - .map(|r| { let r: QueryEvent = r.into(); r }) - .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }) { + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { Ok(ok) => ok, Err(err) => err, }; - self.sender.lock().unwrap().send(&query_result).expect("To Send to client"); + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); + } } UntypedQuery::Select(select) => { log::debug!("SELECT UNTYPED VALUES - {:?}", select.projection_items); @@ -1097,39 +1079,22 @@ impl QueryEngineOld { .map(|value| self.type_coercion.coerce_dynamic(value)); log::debug!("SELECT TYPE COERCED FILTER - {:?}", type_coerced_filter); - let query_result = query_planner + let query_result = match query_planner .plan(TypedQuery::Select(TypedSelectQuery { projection_items: type_coerced, full_table_name: select.full_table_name, filter: type_coerced_filter })) .execute(vec![]) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }); - match query_result { - Ok(QueryExecutionResult::Selected((desc, data))) => { - let x5: Vec = QueryEvent::RowDescription(desc).into(); - self.sender.lock().unwrap() - .send(&x5) - .expect("To Send to client"); - let len = data.len(); - for row in data { - let x6: Vec = QueryEvent::DataRow( - row.into_iter().map(|scalar| scalar.as_text()).collect(), - ).into(); - self.sender.lock().unwrap() - .send(&x6) - .expect("To Send to client"); - } - let x4: Vec = QueryEvent::RecordsSelected(len).into(); - self.sender.lock().unwrap() - .send(&x4) - .expect("To Send to client"); - } - Ok(_) => unreachable!(), - Err(error) => { - self.sender.lock().unwrap().send(&error).expect("To Send to client"); - } + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { + Ok(ok) => ok, + Err(err) => err, + }; + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); } } UntypedQuery::Delete(delete) => { @@ -1152,14 +1117,16 @@ impl QueryEngineOld { filter: type_coerced_filter })) .execute(vec![]) - .map(|r| { let r: QueryEvent = r.into(); r }) - .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec = r.into(); r }) + .map(|r| { let r: Vec> = r.into_iter().map(|q| { let r: Vec = q.into(); r }).collect::>(); r }) .map_err(|e| { let e: QueryError = e.into(); e }) - .map_err(|e| { let e: Vec = e.into(); e }) { + .map_err(|e| { let e: Vec = e.into(); vec![e] }) { Ok(ok) => ok, Err(err) => err, }; - self.sender.lock().unwrap().send(&query_result).expect("To Send to client"); + for result in query_result { + self.sender.lock().unwrap().send(&result).expect("To Send to client"); + } } }, None => { diff --git a/node_engine/src/session/mod.rs b/node_engine/src/transaction_manager.rs similarity index 52% rename from node_engine/src/session/mod.rs rename to node_engine/src/transaction_manager.rs index dd4dda61..d281f7e9 100644 --- a/node_engine/src/session/mod.rs +++ b/node_engine/src/transaction_manager.rs @@ -12,24 +12,19 @@ // See the License for the specific language governing permissions and // limitations under the License. -use data_manipulation::QueryPlan; -use postgre_sql::query_ast::Query; -use std::collections::HashMap; -use types::SqlTypeFamily; +use crate::txn_context::TransactionContext; +use storage::Database; -#[derive(Default)] -#[allow(dead_code)] -pub struct Session { - plans: HashMap)>, +pub struct TransactionManager { + database: Database, } -#[allow(dead_code)] -impl Session { - pub fn cache(&mut self, name: String, _query_plan: QueryPlan, query_ast: Query, params: Vec) { - self.plans.insert(name, (query_ast, params)); +impl TransactionManager { + pub fn new(database: Database) -> TransactionManager { + TransactionManager { database } } - pub fn find(&self, name: &str) -> Option<&(Query, Vec)> { - self.plans.get(name) + pub fn start_transaction(&self) -> TransactionContext { + TransactionContext::new(self.database.transaction()) } } diff --git a/node_engine/src/query_engine/mod.rs b/node_engine/src/txn_context/mod.rs similarity index 90% rename from node_engine/src/query_engine/mod.rs rename to node_engine/src/txn_context/mod.rs index e79b5de5..f2e6a2c2 100644 --- a/node_engine/src/query_engine/mod.rs +++ b/node_engine/src/txn_context/mod.rs @@ -19,18 +19,18 @@ use data_manipulation::{ }; use definition_planner::DefinitionPlanner; use postgre_sql::{ - query_ast::{Definition, Query, Statement}, - query_parser::QueryParser, + query_ast::{Definition, Query}, query_response::{QueryError, QueryEvent}, }; use query_analyzer::QueryAnalyzer; use query_planner::QueryPlanner; use query_processing::{TypeChecker, TypeCoercion, TypeInference}; -use storage::{Database, Transaction}; +use std::fmt::{self, Debug, Formatter}; +use storage::Transaction; use types::SqlTypeFamily; +#[derive(Clone)] pub struct TransactionContext<'t> { - parser: QueryParser, definition_planner: DefinitionPlanner<'t>, catalog: CatalogHandler<'t>, query_analyzer: QueryAnalyzer<'t>, @@ -40,10 +40,15 @@ pub struct TransactionContext<'t> { query_planner: QueryPlanner<'t>, } +impl<'t> Debug for TransactionContext<'t> { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + write!(f, "txn") + } +} + impl<'t> TransactionContext<'t> { - fn new(transaction: Transaction<'t>) -> TransactionContext<'t> { + pub fn new(transaction: Transaction<'t>) -> TransactionContext<'t> { TransactionContext { - parser: QueryParser, definition_planner: DefinitionPlanner::from(transaction.clone()), catalog: CatalogHandler::from(transaction.clone()), query_analyzer: QueryAnalyzer::from(transaction.clone()), @@ -56,11 +61,7 @@ impl<'t> TransactionContext<'t> { pub fn commit(self) {} - pub fn parse(&self, sql: &str) -> Result, QueryError> { - Ok(self.parser.parse(sql)?) - } - - pub fn execute_ddl(&self, definition: Definition) -> Result { + pub fn apply_schema_change(&self, definition: Definition) -> Result { let schema_change = self.definition_planner.plan(definition)?; Ok(self.catalog.apply(schema_change)?.into()) } @@ -167,20 +168,5 @@ impl<'t> TransactionContext<'t> { } } -#[derive(Clone)] -pub struct QueryEngine { - database: Database, -} - -impl QueryEngine { - pub fn new(database: Database) -> QueryEngine { - QueryEngine { database } - } - - pub fn start_transaction(&self) -> TransactionContext { - TransactionContext::new(self.database.transaction()) - } -} - #[cfg(test)] mod tests; diff --git a/node_engine/src/query_engine/tests/delete.rs b/node_engine/src/txn_context/tests/delete.rs similarity index 95% rename from node_engine/src/query_engine/tests/delete.rs rename to node_engine/src/txn_context/tests/delete.rs index b5ee2fc3..beeb42a5 100644 --- a/node_engine/src/query_engine/tests/delete.rs +++ b/node_engine/src/txn_context/tests/delete.rs @@ -15,7 +15,7 @@ use super::*; #[rstest::rstest] -fn delete_all_records(with_schema: QueryEngine) { +fn delete_all_records(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -56,7 +56,7 @@ fn delete_all_records(with_schema: QueryEngine) { } #[rstest::rstest] -fn delete_value_by_predicate_on_single_field(with_schema: QueryEngine) { +fn delete_value_by_predicate_on_single_field(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( diff --git a/node_engine/src/query_engine/tests/insert.rs b/node_engine/src/txn_context/tests/insert.rs similarity index 91% rename from node_engine/src/query_engine/tests/insert.rs rename to node_engine/src/txn_context/tests/insert.rs index 1eeb60ea..f8d88c4e 100644 --- a/node_engine/src/query_engine/tests/insert.rs +++ b/node_engine/src/txn_context/tests/insert.rs @@ -15,7 +15,7 @@ use super::*; #[rstest::rstest] -fn insert_value_in_non_existent_column(with_schema: QueryEngine) { +fn insert_value_in_non_existent_column(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -33,7 +33,7 @@ fn insert_value_in_non_existent_column(with_schema: QueryEngine) { } #[rstest::rstest] -fn insert_and_select_single_row(with_schema: QueryEngine) { +fn insert_and_select_single_row(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -58,7 +58,7 @@ fn insert_and_select_single_row(with_schema: QueryEngine) { } #[rstest::rstest] -fn insert_and_select_multiple_rows(with_schema: QueryEngine) { +fn insert_and_select_multiple_rows(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -90,7 +90,7 @@ fn insert_and_select_multiple_rows(with_schema: QueryEngine) { } #[rstest::rstest] -fn insert_and_select_named_columns(with_schema: QueryEngine) { +fn insert_and_select_named_columns(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -123,7 +123,7 @@ fn insert_and_select_named_columns(with_schema: QueryEngine) { } #[rstest::rstest] -fn insert_multiple_rows(with_schema: QueryEngine) { +fn insert_multiple_rows(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -157,7 +157,7 @@ fn insert_multiple_rows(with_schema: QueryEngine) { } #[rstest::rstest] -fn insert_and_select_different_integer_types(with_schema: QueryEngine) { +fn insert_and_select_different_integer_types(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -195,7 +195,7 @@ fn insert_and_select_different_integer_types(with_schema: QueryEngine) { } #[rstest::rstest] -fn insert_and_select_different_character_types(with_schema: QueryEngine) { +fn insert_and_select_different_character_types(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -228,7 +228,7 @@ fn insert_and_select_different_character_types(with_schema: QueryEngine) { } #[rstest::rstest] -fn insert_booleans(with_schema: QueryEngine) { +fn insert_booleans(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -265,7 +265,7 @@ mod operators { use super::*; #[rstest::fixture] - fn with_table(with_schema: QueryEngine) -> QueryEngine { + fn with_table(with_schema: TransactionManager) -> TransactionManager { let txn = with_schema.start_transaction(); assert_definition( @@ -280,7 +280,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn addition(with_table: QueryEngine) { + fn addition(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -301,7 +301,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn subtraction(with_table: QueryEngine) { + fn subtraction(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -322,7 +322,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn multiplication(with_table: QueryEngine) { + fn multiplication(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -344,7 +344,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn division(with_table: QueryEngine) { + fn division(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -364,7 +364,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn modulo(with_table: QueryEngine) { + fn modulo(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -384,7 +384,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn exponentiation(with_table: QueryEngine) { + fn exponentiation(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -404,7 +404,7 @@ mod operators { #[rstest::rstest] #[ignore] //TODO: TypeInference#infer_static is not implemented - fn square_root(with_table: QueryEngine) { + fn square_root(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -424,7 +424,7 @@ mod operators { #[rstest::rstest] #[ignore] //TODO: TypeInference#infer_static is not implemented - fn cube_root(with_table: QueryEngine) { + fn cube_root(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -444,7 +444,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn factorial(with_table: QueryEngine) { + fn factorial(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -465,7 +465,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn prefix_factorial(with_table: QueryEngine) { + fn prefix_factorial(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -485,7 +485,7 @@ mod operators { } #[rstest::rstest] - fn absolute_value(with_table: QueryEngine) { + fn absolute_value(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -506,7 +506,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn bitwise_and(with_table: QueryEngine) { + fn bitwise_and(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -527,7 +527,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn bitwise_or(with_table: QueryEngine) { + fn bitwise_or(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -547,7 +547,7 @@ mod operators { } #[rstest::rstest] - fn bitwise_not(with_table: QueryEngine) { + fn bitwise_not(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -568,7 +568,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn bitwise_shift_left(with_table: QueryEngine) { + fn bitwise_shift_left(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -589,7 +589,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn bitwise_right_left(with_table: QueryEngine) { + fn bitwise_right_left(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -610,7 +610,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn evaluate_many_operations(with_table: QueryEngine) { + fn evaluate_many_operations(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -635,7 +635,7 @@ mod operators { use super::*; #[rstest::fixture] - fn with_table(with_schema: QueryEngine) -> QueryEngine { + fn with_table(with_schema: TransactionManager) -> TransactionManager { let txn = with_schema.start_transaction(); assert_definition( @@ -649,7 +649,7 @@ mod operators { } #[rstest::rstest] - fn concatenation(with_table: QueryEngine) { + fn concatenation(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -670,7 +670,7 @@ mod operators { #[rstest::rstest] #[ignore] //TODO: TypeInference#infer_static is not implemented - fn concatenation_with_number(with_table: QueryEngine) { + fn concatenation_with_number(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -695,7 +695,7 @@ mod operators { } #[rstest::rstest] - fn non_string_concatenation_not_supported(with_table: QueryEngine) { + fn non_string_concatenation_not_supported(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( diff --git a/node_engine/src/query_engine/tests/mod.rs b/node_engine/src/txn_context/tests/mod.rs similarity index 83% rename from node_engine/src/query_engine/tests/mod.rs rename to node_engine/src/txn_context/tests/mod.rs index 70e05566..1c967936 100644 --- a/node_engine/src/query_engine/tests/mod.rs +++ b/node_engine/src/txn_context/tests/mod.rs @@ -13,13 +13,17 @@ // limitations under the License. use super::*; +use crate::transaction_manager::TransactionManager; use bigdecimal::BigDecimal; use data_manipulation::QueryExecutionResult; use data_repr::scalar::ScalarValue; use postgre_sql::{ + query_ast::{Request, Statement}, + query_parser::QueryParser, query_response::QueryEvent, wire_protocol::payload::{BIGINT, CHAR, INT, SMALLINT, VARCHAR}, }; +use storage::Database; use types::SqlTypeFamily; #[cfg(test)] @@ -68,17 +72,17 @@ fn string(value: &str) -> ScalarValue { } fn assert_definition(txn: &TransactionContext, sql: &str, expected: Result) { - match txn.parse(sql).expect("query parsed").pop() { - Some(Statement::Definition(definition)) => { - assert_eq!(txn.execute_ddl(definition), expected); + match QueryParser.parse(sql) { + Ok(Request::Statement(Statement::Definition(definition))) => { + assert_eq!(txn.apply_schema_change(definition), expected); } other => panic!("expected DDL query but was {:?}", other), } } fn assert_query(txn: &TransactionContext, sql: &str, expected: Result) { - match txn.parse(sql).expect("query parsed").pop() { - Some(Statement::Query(query)) => { + match QueryParser.parse(sql) { + Ok(Request::Statement(Statement::Query(query))) => { let query_result = txn .process(query, vec![]) .map(|typed_query| txn.plan(typed_query)) @@ -90,9 +94,9 @@ fn assert_query(txn: &TransactionContext, sql: &str, expected: Result QueryEngine { +fn with_schema() -> TransactionManager { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_definition(&txn, "create schema schema_name", Ok(QueryEvent::SchemaCreated)); diff --git a/node_engine/src/query_engine/tests/schema.rs b/node_engine/src/txn_context/tests/schema.rs similarity index 87% rename from node_engine/src/query_engine/tests/schema.rs rename to node_engine/src/txn_context/tests/schema.rs index d293e2ae..ed6ec733 100644 --- a/node_engine/src/query_engine/tests/schema.rs +++ b/node_engine/src/txn_context/tests/schema.rs @@ -17,7 +17,7 @@ use super::*; #[test] fn create_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_definition(&txn, "create schema schema_name;", Ok(QueryEvent::SchemaCreated)); @@ -27,7 +27,7 @@ fn create_schema() { #[test] fn create_same_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_definition(&txn, "create schema schema_name;", Ok(QueryEvent::SchemaCreated)); @@ -42,7 +42,7 @@ fn create_same_schema() { #[test] fn drop_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_definition(&txn, "create schema schema_name;", Ok(QueryEvent::SchemaCreated)); @@ -53,7 +53,7 @@ fn drop_schema() { #[test] fn drop_non_existent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_definition( @@ -67,7 +67,7 @@ fn drop_non_existent_schema() { #[test] fn drop_if_exists_non_existent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_definition( @@ -81,7 +81,7 @@ fn drop_if_exists_non_existent_schema() { #[test] fn drop_if_exists_existent_and_non_existent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_definition(&txn, "create schema existent_schema;", Ok(QueryEvent::SchemaCreated)); @@ -97,7 +97,7 @@ fn drop_if_exists_existent_and_non_existent_schema() { #[test] fn select_from_nonexistent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_query( @@ -111,7 +111,7 @@ fn select_from_nonexistent_schema() { #[test] fn select_named_columns_from_nonexistent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_query( @@ -125,7 +125,7 @@ fn select_named_columns_from_nonexistent_schema() { #[test] fn insert_into_table_in_nonexistent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_query( @@ -139,7 +139,7 @@ fn insert_into_table_in_nonexistent_schema() { #[test] fn update_records_in_table_from_non_existent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_query( @@ -153,7 +153,7 @@ fn update_records_in_table_from_non_existent_schema() { #[test] fn delete_from_table_in_nonexistent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_query( diff --git a/node_engine/src/query_engine/tests/select.rs b/node_engine/src/txn_context/tests/select.rs similarity index 93% rename from node_engine/src/query_engine/tests/select.rs rename to node_engine/src/txn_context/tests/select.rs index 46a92ac4..2170bd28 100644 --- a/node_engine/src/query_engine/tests/select.rs +++ b/node_engine/src/txn_context/tests/select.rs @@ -15,7 +15,7 @@ use super::*; #[rstest::rstest] -fn select_all_from_table_with_multiple_columns(with_schema: QueryEngine) { +fn select_all_from_table_with_multiple_columns(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -43,7 +43,7 @@ fn select_all_from_table_with_multiple_columns(with_schema: QueryEngine) { } #[rstest::rstest] -fn select_not_all_columns(with_schema: QueryEngine) { +fn select_not_all_columns(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -72,7 +72,7 @@ fn select_not_all_columns(with_schema: QueryEngine) { } #[rstest::rstest] -fn select_non_existing_columns_from_table(with_schema: QueryEngine) { +fn select_non_existing_columns_from_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -89,7 +89,7 @@ fn select_non_existing_columns_from_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn select_first_and_last_columns_from_table_with_multiple_columns(with_schema: QueryEngine) { +fn select_first_and_last_columns_from_table_with_multiple_columns(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -118,7 +118,7 @@ fn select_first_and_last_columns_from_table_with_multiple_columns(with_schema: Q } #[rstest::rstest] -fn select_all_columns_reordered_from_table_with_multiple_columns(with_schema: QueryEngine) { +fn select_all_columns_reordered_from_table_with_multiple_columns(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -151,7 +151,7 @@ fn select_all_columns_reordered_from_table_with_multiple_columns(with_schema: Qu } #[rstest::rstest] -fn select_with_column_name_duplication(with_schema: QueryEngine) { +fn select_with_column_name_duplication(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -186,7 +186,7 @@ fn select_with_column_name_duplication(with_schema: QueryEngine) { } #[rstest::rstest] -fn select_different_integer_types(with_schema: QueryEngine) { +fn select_different_integer_types(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -215,7 +215,7 @@ fn select_different_integer_types(with_schema: QueryEngine) { } #[rstest::rstest] -fn select_different_character_strings_types(with_schema: QueryEngine) { +fn select_different_character_strings_types(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -250,7 +250,7 @@ fn select_different_character_strings_types(with_schema: QueryEngine) { } #[rstest::rstest] -fn select_value_by_predicate_on_single_field(with_schema: QueryEngine) { +fn select_value_by_predicate_on_single_field(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( diff --git a/node_engine/src/query_engine/tests/table.rs b/node_engine/src/txn_context/tests/table.rs similarity index 85% rename from node_engine/src/query_engine/tests/table.rs rename to node_engine/src/txn_context/tests/table.rs index 3eb3fe4b..02100d3e 100644 --- a/node_engine/src/query_engine/tests/table.rs +++ b/node_engine/src/txn_context/tests/table.rs @@ -21,7 +21,7 @@ mod schemaless { #[test] fn create_table_in_non_existent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_definition( @@ -35,7 +35,7 @@ mod schemaless { #[test] fn drop_table_from_non_existent_schema() { let database = Database::new("IN_MEMORY"); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); let txn = query_engine.start_transaction(); assert_definition( @@ -48,7 +48,7 @@ mod schemaless { } #[rstest::rstest] -fn create_table(with_schema: QueryEngine) { +fn create_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -60,7 +60,7 @@ fn create_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn create_same_table(with_schema: QueryEngine) { +fn create_same_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -77,7 +77,7 @@ fn create_same_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn drop_table(with_schema: QueryEngine) { +fn drop_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -94,7 +94,7 @@ fn drop_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn drop_non_existent_table(with_schema: QueryEngine) { +fn drop_non_existent_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -106,7 +106,7 @@ fn drop_non_existent_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn drop_if_exists_non_existent_table(with_schema: QueryEngine) { +fn drop_if_exists_non_existent_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -118,7 +118,7 @@ fn drop_if_exists_non_existent_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn drop_if_exists_existent_and_non_existent_table(with_schema: QueryEngine) { +fn drop_if_exists_existent_and_non_existent_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -140,7 +140,7 @@ fn drop_if_exists_existent_and_non_existent_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn delete_from_nonexistent_table(with_schema: QueryEngine) { +fn delete_from_nonexistent_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_query( &txn, @@ -151,7 +151,7 @@ fn delete_from_nonexistent_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn insert_into_nonexistent_table(with_schema: QueryEngine) { +fn insert_into_nonexistent_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_query( @@ -163,7 +163,7 @@ fn insert_into_nonexistent_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn select_from_not_existed_table(with_schema: QueryEngine) { +fn select_from_not_existed_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_query( @@ -175,7 +175,7 @@ fn select_from_not_existed_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn select_named_columns_from_non_existent_table(with_schema: QueryEngine) { +fn select_named_columns_from_non_existent_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_query( @@ -187,7 +187,7 @@ fn select_named_columns_from_non_existent_table(with_schema: QueryEngine) { } #[rstest::rstest] -fn update_records_in_nonexistent_table(with_schema: QueryEngine) { +fn update_records_in_nonexistent_table(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_query( &txn, @@ -202,7 +202,7 @@ mod different_types { use super::*; #[rstest::rstest] - fn ints(with_schema: QueryEngine) { + fn ints(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -218,7 +218,7 @@ mod different_types { } #[rstest::rstest] - fn strings(with_schema: QueryEngine) { + fn strings(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -233,7 +233,7 @@ mod different_types { } #[rstest::rstest] - fn boolean(with_schema: QueryEngine) { + fn boolean(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( diff --git a/node_engine/src/query_engine/tests/type_constraints.rs b/node_engine/src/txn_context/tests/type_constraints.rs similarity index 89% rename from node_engine/src/query_engine/tests/type_constraints.rs rename to node_engine/src/txn_context/tests/type_constraints.rs index 8efa108e..213d219c 100644 --- a/node_engine/src/query_engine/tests/type_constraints.rs +++ b/node_engine/src/txn_context/tests/type_constraints.rs @@ -15,7 +15,7 @@ use super::*; #[rstest::fixture] -fn int_table(with_schema: QueryEngine) -> QueryEngine { +fn int_table(with_schema: TransactionManager) -> TransactionManager { let txn = with_schema.start_transaction(); assert_definition( @@ -29,7 +29,7 @@ fn int_table(with_schema: QueryEngine) -> QueryEngine { } #[rstest::fixture] -fn multiple_ints_table(with_schema: QueryEngine) -> QueryEngine { +fn multiple_ints_table(with_schema: TransactionManager) -> TransactionManager { let txn = with_schema.start_transaction(); assert_definition( @@ -43,7 +43,7 @@ fn multiple_ints_table(with_schema: QueryEngine) -> QueryEngine { } #[rstest::fixture] -fn str_table(with_schema: QueryEngine) -> QueryEngine { +fn str_table(with_schema: TransactionManager) -> TransactionManager { let txn = with_schema.start_transaction(); assert_definition( @@ -62,7 +62,7 @@ mod insert { use types::SqlType; #[rstest::rstest] - fn out_of_range(int_table: QueryEngine) { + fn out_of_range(int_table: TransactionManager) { let txn = int_table.start_transaction(); assert_query( @@ -74,7 +74,7 @@ mod insert { } #[rstest::rstest] - fn type_mismatch(int_table: QueryEngine) { + fn type_mismatch(int_table: TransactionManager) { let txn = int_table.start_transaction(); assert_query( @@ -86,7 +86,7 @@ mod insert { } #[rstest::rstest] - fn multiple_columns_multiple_row_violation(multiple_ints_table: QueryEngine) { + fn multiple_columns_multiple_row_violation(multiple_ints_table: TransactionManager) { let txn = multiple_ints_table.start_transaction(); // assert_query( @@ -104,7 +104,7 @@ mod insert { } #[rstest::rstest] - fn violation_in_the_second_row(multiple_ints_table: QueryEngine) { + fn violation_in_the_second_row(multiple_ints_table: TransactionManager) { let txn = multiple_ints_table.start_transaction(); assert_query( @@ -117,7 +117,7 @@ mod insert { #[rstest::rstest] #[ignore] // TODO: string length is not checked - fn value_too_long(str_table: QueryEngine) { + fn value_too_long(str_table: TransactionManager) { let txn = str_table.start_transaction(); assert_query( @@ -135,7 +135,7 @@ mod update { use types::SqlType; #[rstest::rstest] - fn out_of_range(int_table: QueryEngine) { + fn out_of_range(int_table: TransactionManager) { let txn = int_table.start_transaction(); assert_query( @@ -152,7 +152,7 @@ mod update { } #[rstest::rstest] - fn type_mismatch(int_table: QueryEngine) { + fn type_mismatch(int_table: TransactionManager) { let txn = int_table.start_transaction(); assert_query( @@ -170,7 +170,7 @@ mod update { #[rstest::rstest] #[ignore] // TODO: string length is not checked - fn value_too_long(str_table: QueryEngine) { + fn value_too_long(str_table: TransactionManager) { let txn = str_table.start_transaction(); assert_query( @@ -187,7 +187,7 @@ mod update { } #[rstest::rstest] - fn multiple_columns_violation(multiple_ints_table: QueryEngine) { + fn multiple_columns_violation(multiple_ints_table: TransactionManager) { let txn = multiple_ints_table.start_transaction(); assert_query( diff --git a/node_engine/src/query_engine/tests/update.rs b/node_engine/src/txn_context/tests/update.rs similarity index 92% rename from node_engine/src/query_engine/tests/update.rs rename to node_engine/src/txn_context/tests/update.rs index 545a1150..b5638939 100644 --- a/node_engine/src/query_engine/tests/update.rs +++ b/node_engine/src/txn_context/tests/update.rs @@ -15,7 +15,7 @@ use super::*; #[rstest::rstest] -fn update_all_records(with_schema: QueryEngine) { +fn update_all_records(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -53,7 +53,7 @@ fn update_all_records(with_schema: QueryEngine) { } #[rstest::rstest] -fn update_single_column_of_all_records(with_schema: QueryEngine) { +fn update_single_column_of_all_records(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -97,7 +97,7 @@ fn update_single_column_of_all_records(with_schema: QueryEngine) { } #[rstest::rstest] -fn update_multiple_columns_of_all_records(with_schema: QueryEngine) { +fn update_multiple_columns_of_all_records(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -149,7 +149,7 @@ fn update_multiple_columns_of_all_records(with_schema: QueryEngine) { } #[rstest::rstest] -fn update_all_records_in_multiple_columns(with_schema: QueryEngine) { +fn update_all_records_in_multiple_columns(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -202,7 +202,7 @@ fn update_all_records_in_multiple_columns(with_schema: QueryEngine) { } #[rstest::rstest] -fn update_non_existent_columns_of_records(with_schema: QueryEngine) { +fn update_non_existent_columns_of_records(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -233,7 +233,7 @@ fn update_non_existent_columns_of_records(with_schema: QueryEngine) { #[rstest::rstest] #[ignore] // TODO: type coercion -fn test_update_with_dynamic_expression(with_schema: QueryEngine) { +fn test_update_with_dynamic_expression(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -293,7 +293,7 @@ fn test_update_with_dynamic_expression(with_schema: QueryEngine) { } #[rstest::rstest] -fn update_value_by_predicate_on_single_field(with_schema: QueryEngine) { +fn update_value_by_predicate_on_single_field(with_schema: TransactionManager) { let txn = with_schema.start_transaction(); assert_definition( @@ -350,7 +350,7 @@ mod operators { use super::*; #[rstest::fixture] - fn with_table(with_schema: QueryEngine) -> QueryEngine { + fn with_table(with_schema: TransactionManager) -> TransactionManager { let txn = with_schema.start_transaction(); assert_definition( @@ -370,7 +370,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn addition(with_table: QueryEngine) { + fn addition(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -392,7 +392,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn subtraction(with_table: QueryEngine) { + fn subtraction(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -413,7 +413,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn multiplication(with_table: QueryEngine) { + fn multiplication(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -434,7 +434,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn division(with_table: QueryEngine) { + fn division(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -455,7 +455,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn modulo(with_table: QueryEngine) { + fn modulo(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -476,7 +476,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn exponentiation(with_table: QueryEngine) { + fn exponentiation(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -497,7 +497,7 @@ mod operators { #[rstest::rstest] #[ignore] //TODO: TypeInference#infer_static is not implemented - fn square_root(with_table: QueryEngine) { + fn square_root(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -518,7 +518,7 @@ mod operators { #[rstest::rstest] #[ignore] //TODO: TypeInference#infer_static is not implemented - fn cube_root(with_table: QueryEngine) { + fn cube_root(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -539,7 +539,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn factorial(with_table: QueryEngine) { + fn factorial(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -560,7 +560,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn prefix_factorial(with_table: QueryEngine) { + fn prefix_factorial(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -580,7 +580,7 @@ mod operators { } #[rstest::rstest] - fn absolute_value(with_table: QueryEngine) { + fn absolute_value(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -601,7 +601,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn bitwise_and(with_table: QueryEngine) { + fn bitwise_and(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -622,7 +622,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn bitwise_or(with_table: QueryEngine) { + fn bitwise_or(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -642,7 +642,7 @@ mod operators { } #[rstest::rstest] - fn bitwise_not(with_table: QueryEngine) { + fn bitwise_not(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -663,7 +663,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn bitwise_shift_left(with_table: QueryEngine) { + fn bitwise_shift_left(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -684,7 +684,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn bitwise_right_left(with_table: QueryEngine) { + fn bitwise_right_left(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -705,7 +705,7 @@ mod operators { #[rstest::rstest] #[ignore] // TODO: type coercion - fn evaluate_many_operations(with_table: QueryEngine) { + fn evaluate_many_operations(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -730,7 +730,7 @@ mod operators { use super::*; #[rstest::fixture] - fn with_table(with_schema: QueryEngine) -> QueryEngine { + fn with_table(with_schema: TransactionManager) -> TransactionManager { let txn = with_schema.start_transaction(); assert_definition( @@ -749,7 +749,7 @@ mod operators { } #[rstest::rstest] - fn concatenation(with_table: QueryEngine) { + fn concatenation(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -770,7 +770,7 @@ mod operators { #[rstest::rstest] #[ignore] //TODO: TypeInference#infer_static is not implemented - fn concatenation_with_number(with_table: QueryEngine) { + fn concatenation_with_number(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( @@ -803,7 +803,7 @@ mod operators { } #[rstest::rstest] - fn non_string_concatenation_not_supported(with_table: QueryEngine) { + fn non_string_concatenation_not_supported(with_table: TransactionManager) { let txn = with_table.start_transaction(); assert_query( diff --git a/node_engine/src/worker.rs b/node_engine/src/worker.rs index 4a1b39ad..3b988df2 100644 --- a/node_engine/src/worker.rs +++ b/node_engine/src/worker.rs @@ -12,11 +12,12 @@ // See the License for the specific language governing permissions and // limitations under the License. -use crate::{query_engine::QueryEngine, session::Session}; +use crate::{transaction_manager::TransactionManager, txn_context::TransactionContext, QueryPlanCache}; use data_manipulation::QueryExecutionResult; use data_repr::scalar::ScalarValue; use postgre_sql::{ - query_ast::{Extended, Statement, Transaction}, + query_ast::{Extended, Request, Statement, Transaction}, + query_parser::QueryParser, wire_protocol::{ payload::{Inbound, Outbound}, WireConnection, @@ -25,114 +26,139 @@ use postgre_sql::{ use storage::Database; use types::{SqlType, SqlTypeFamily}; +struct QueryExecutor; + +impl QueryExecutor { + fn execute( + &self, + statement: Statement, + txn: &TransactionContext, + query_plan_cache: &mut QueryPlanCache, + ) -> Vec { + let mut responses = vec![]; + match statement { + Statement::Definition(definition) => match txn.apply_schema_change(definition) { + Ok(success) => responses.push(success.into()), + Err(failure) => responses.push(failure.into()), + }, + Statement::Extended(extended) => match extended { + Extended::Prepare { + query, + name, + param_types, + } => { + let params: Vec = + param_types.into_iter().map(|dt| SqlType::from(dt).family()).collect(); + let typed_query = txn.process(query.clone(), params.clone()).unwrap(); + let query_plan = txn.plan(typed_query); + query_plan_cache.allocate(name, query_plan, query, params); + responses.push(Outbound::StatementPrepared); + } + Extended::Execute { name, param_values } => { + match query_plan_cache.lookup(&name) { + None => unimplemented!(), + // TODO: workaround situate that QueryPlan is not clone ¯\_(ツ)_/¯ + Some((query, params)) => { + let typed_query = txn.process(query.clone(), params.clone()).unwrap(); + let query_plan = txn.plan(typed_query); + match query_plan.execute(param_values.into_iter().map(ScalarValue::from).collect()) { + Ok(QueryExecutionResult::Inserted(inserted)) => { + responses.push(Outbound::RecordsInserted(inserted)); + } + Ok(_) => {} + Err(_) => unimplemented!(), + } + } + } + } + Extended::Deallocate { name } => match query_plan_cache.deallocate(&name) { + None => {} + Some(_) => {} + }, + }, + Statement::Query(query) => { + let typed_query = txn.process(query, vec![]).unwrap(); + let query_plan = txn.plan(typed_query); + match query_plan.execute(vec![]) { + Ok(QueryExecutionResult::Selected((desc, data))) => { + responses.push(Outbound::RowDescription(desc)); + let selected = data.len(); + for datum in data { + responses.push(Outbound::DataRow(datum.into_iter().map(|v| v.as_text()).collect())); + } + responses.push(Outbound::RecordsSelected(selected)); + } + other => { + unimplemented!("branch {:?} is not implemented", other) + } + } + } + } + responses.push(Outbound::ReadyForQuery); + responses + } +} + #[allow(dead_code)] pub struct Worker; impl Worker { #[allow(dead_code)] fn process(&self, connection: &mut C, db_name: &str) { - let mut session = Session::default(); + let mut query_plan_cache = QueryPlanCache::default(); + let query_parser = QueryParser; let database = Database::new(db_name); - let query_engine = QueryEngine::new(database); + let query_engine = TransactionManager::new(database); - let mut explicit_txn = false; - let mut end_txn = true; + let mut txn_state: Option = None; loop { - let txn = query_engine.start_transaction(); - match connection.receive() { - Ok(Ok(inbound_request)) => match inbound_request { - Inbound::Query { sql } => { - let statements = match txn.parse(&sql) { - Ok(parsed) => parsed, - _ => unimplemented!(), - }; - for statement in statements { - match statement { - Statement::Definition(ddl) => match txn.execute_ddl(ddl) { - Ok(success) => { - connection.send(success.into()).unwrap(); - } - Err(error) => { - connection.send(error.into()).unwrap(); - } - }, - Statement::Transaction(txn_flow) => match txn_flow { + let inbound_request = connection.receive(); + match inbound_request { + Ok(Ok(inbound)) => match inbound { + Inbound::Query { sql } => match query_parser.parse(&sql) { + Ok(request) => match request { + Request::Transaction(transaction) => { + match transaction { Transaction::Begin => { - end_txn = false; - explicit_txn = true; + debug_assert!(txn_state.is_none(), "transaction state should be implicit"); + txn_state = Some(query_engine.start_transaction()); connection.send(Outbound::TransactionBegin).unwrap(); } Transaction::Commit => { - end_txn = true; - } - }, - Statement::Extended(extended) => match extended { - Extended::Prepare { - query, - name, - param_types, - } => { - let params: Vec = - param_types.into_iter().map(|dt| SqlType::from(dt).family()).collect(); - let typed_query = txn.process(query.clone(), params.clone()).unwrap(); - let query_plan = txn.plan(typed_query); - session.cache(name, query_plan, query, params); - connection.send(Outbound::StatementPrepared).unwrap(); - } - Extended::Execute { name, param_values } => match session.find(&name) { - None => unimplemented!(), - // TODO: workaround situate that QueryPlan is not clone ¯\_(ツ)_/¯ - Some((query, params)) => { - let typed_query = txn.process(query.clone(), params.clone()).unwrap(); - let query_plan = txn.plan(typed_query); - match query_plan - .execute(param_values.into_iter().map(ScalarValue::from).collect()) - { - Ok(QueryExecutionResult::Inserted(inserted)) => { - connection.send(Outbound::RecordsInserted(inserted)).unwrap(); - } - Ok(_) => {} - Err(_) => unimplemented!(), - } - } - }, - _ => unimplemented!(), - }, - Statement::Query(query) => { - let typed_query = txn.process(query, vec![]).unwrap(); - let query_plan = txn.plan(typed_query); - match query_plan.execute(vec![]) { - Ok(QueryExecutionResult::Selected((desc, data))) => { - connection.send(Outbound::RowDescription(desc)).unwrap(); - let selected = data.len(); - for datum in data { - connection - .send(Outbound::DataRow( - datum.into_iter().map(|v| v.as_text()).collect(), - )) - .unwrap(); + debug_assert!(txn_state.is_some(), "transaction state should be in progress"); + match txn_state { + None => unimplemented!(), + Some(txn) => { + txn.commit(); + connection.send(Outbound::TransactionCommit).unwrap(); + txn_state = None; } - connection.send(Outbound::RecordsSelected(selected)).unwrap(); } - other => unimplemented!("branch {:?} is not implemented", other), } } - stmt => unimplemented!("statement {:?} could not processed", stmt), + connection.send(Outbound::ReadyForQuery).unwrap(); } - } - if end_txn { - txn.commit(); - if explicit_txn { - connection.send(Outbound::TransactionCommit).unwrap(); - // reset the state - explicit_txn = false; - end_txn = true; + Request::Config(_) => unimplemented!(), + Request::Statement(statement) => { + let (txn, finish_txn) = match txn_state.take() { + None => (query_engine.start_transaction(), true), + Some(txn) => (txn, false), + }; + let test = QueryExecutor; + for outbound in test.execute(statement, &txn, &mut query_plan_cache) { + connection.send(outbound).unwrap(); + } + if finish_txn { + txn.commit(); + } else { + txn_state = Some(txn); + } } - } - connection.send(Outbound::ReadyForQuery).unwrap(); - } - _ => unimplemented!(), + }, + Err(_) => unimplemented!(), + }, + other => unimplemented!("other inbound request {:?} is not handled", other), }, _ => break, } @@ -142,12 +168,14 @@ impl Worker { #[cfg(test)] mod tests { - use super::*; + use std::io; + use postgre_sql::wire_protocol::{ payload::{Outbound, SMALLINT}, WireError, WireResult, }; - use std::io; + + use super::*; struct MockConnection { inbound: Vec, diff --git a/postgre_sql/query_ast/src/lib.rs b/postgre_sql/query_ast/src/lib.rs index 90c682d2..7896e8ba 100644 --- a/postgre_sql/query_ast/src/lib.rs +++ b/postgre_sql/query_ast/src/lib.rs @@ -14,13 +14,18 @@ use std::fmt::{self, Display, Formatter}; +#[derive(Debug, PartialEq)] +pub enum Request { + Transaction(Transaction), + Config(Set), + Statement(Statement), +} + #[derive(Debug, PartialEq)] pub enum Statement { Definition(Definition), Query(Query), - Config(Set), Extended(Extended), - Transaction(Transaction), } impl Display for Statement { diff --git a/postgre_sql/query_parser/src/lib.rs b/postgre_sql/query_parser/src/lib.rs index de4a64cf..bbd09002 100644 --- a/postgre_sql/query_parser/src/lib.rs +++ b/postgre_sql/query_parser/src/lib.rs @@ -15,8 +15,8 @@ use postgres_parser::{nodes, sys, Node, PgParserError, SqlStatementScanner}; use query_ast::{ Assignment, BinaryOperator, ColumnDef, DataType, Definition, DeleteStatement, Expr, Extended, InsertSource, - InsertStatement, Query, SelectItem, SelectStatement, Set, Statement, Transaction, UnaryOperator, UpdateStatement, - Value, Values, + InsertStatement, Query, Request, SelectItem, SelectStatement, Set, Statement, Transaction, UnaryOperator, + UpdateStatement, Value, Values, }; use query_response::QueryError; use std::fmt::{self, Display, Formatter}; @@ -28,8 +28,7 @@ impl QueryParser { QueryParser } - pub fn parse(&self, sql: &str) -> Result, ParserError> { - let mut statements = vec![]; + pub fn parse(&self, sql: &str) -> Result { for scanned_query in SqlStatementScanner::new(sql).into_iter() { match scanned_query.parsetree { Err(error) => return Err(ParserError::from(error)), @@ -39,10 +38,12 @@ impl QueryParser { authrole: _auth_role, schemaElts: _schema_elements, if_not_exists, - }))) => statements.push(Statement::Definition(Definition::CreateSchema { - schema_name: schema_name.unwrap(), - if_not_exists, - })), + }))) => { + return Ok(Request::Statement(Statement::Definition(Definition::CreateSchema { + schema_name: schema_name.unwrap(), + if_not_exists, + }))) + } Ok(Some(Node::CreateStmt(nodes::CreateStmt { relation: table_name, tableElts: table_elements, @@ -62,12 +63,12 @@ impl QueryParser { columns.push(self.process_column(table_element)); } let table_name = table_name.unwrap(); - statements.push(Statement::Definition(Definition::CreateTable { + return Ok(Request::Statement(Statement::Definition(Definition::CreateTable { if_not_exists, schema_name: table_name.schemaname.unwrap_or_else(|| "public".to_owned()), table_name: table_name.relname.unwrap(), columns, - })); + }))); } Ok(Some(Node::DropStmt(nodes::DropStmt { objects, @@ -86,11 +87,11 @@ impl QueryParser { _ => unimplemented!(), } } - statements.push(Statement::Definition(Definition::DropSchemas { + return Ok(Request::Statement(Statement::Definition(Definition::DropSchemas { names, if_exists: missing_ok, cascade: behavior == sys::DropBehavior::DROP_CASCADE, - })); + }))); } sys::ObjectType::OBJECT_TABLE => { let mut names = vec![]; @@ -122,11 +123,11 @@ impl QueryParser { _ => unimplemented!(), } } - statements.push(Statement::Definition(Definition::DropTables { + return Ok(Request::Statement(Statement::Definition(Definition::DropTables { names, if_exists: missing_ok, cascade: behavior == sys::DropBehavior::DROP_CASCADE, - })); + }))); } _ => unimplemented!(), }; @@ -167,27 +168,27 @@ impl QueryParser { } } let table_name = table_name.unwrap(); - statements.push(Statement::Definition(Definition::CreateIndex { + return Ok(Request::Statement(Statement::Definition(Definition::CreateIndex { name: index_name.unwrap(), schema_name: table_name.schemaname.unwrap_or_else(|| "public".to_owned()), table_name: table_name.relname.unwrap(), column_names, - })); + }))); } Ok(Some(insert @ Node::InsertStmt(_))) => { - statements.push(Statement::Query(self.process_query(insert))); + return Ok(Request::Statement(Statement::Query(self.process_query(insert)))); } Ok(Some(select @ Node::SelectStmt(_))) => { - statements.push(Statement::Query(self.process_query(select))); + return Ok(Request::Statement(Statement::Query(self.process_query(select)))); } Ok(Some(update @ Node::UpdateStmt(_))) => { - statements.push(Statement::Query(self.process_query(update))); + return Ok(Request::Statement(Statement::Query(self.process_query(update)))); } Ok(Some(delete @ Node::DeleteStmt(_))) => { - statements.push(Statement::Query(self.process_query(delete))); + return Ok(Request::Statement(Statement::Query(self.process_query(delete)))); } Ok(Some(Node::VariableSetStmt(nodes::VariableSetStmt { name, .. }))) => { - statements.push(Statement::Config(Set { + return Ok(Request::Config(Set { variable: name.unwrap(), value: "value".to_owned(), })) @@ -204,11 +205,11 @@ impl QueryParser { _ => unimplemented!(), } } - statements.push(Statement::Extended(Extended::Prepare { + return Ok(Request::Statement(Statement::Extended(Extended::Prepare { name, param_types, query: self.process_query(*query), - })) + }))); } Ok(Some(Node::ExecuteStmt(nodes::ExecuteStmt { name: Some(name), @@ -221,23 +222,26 @@ impl QueryParser { other => unreachable!("{:?} could not be used as parameter", other), } } - statements.push(Statement::Extended(Extended::Execute { name, param_values })) + return Ok(Request::Statement(Statement::Extended(Extended::Execute { + name, + param_values, + }))); } Ok(Some(Node::DeallocateStmt(nodes::DeallocateStmt { name: Some(name) }))) => { - statements.push(Statement::Extended(Extended::Deallocate { name })) + return Ok(Request::Statement(Statement::Extended(Extended::Deallocate { name }))) } Ok(Some(Node::TransactionStmt(nodes::TransactionStmt { kind, .. }))) => { let stmt = match kind { - sys::TransactionStmtKind::TRANS_STMT_BEGIN => Statement::Transaction(Transaction::Begin), - sys::TransactionStmtKind::TRANS_STMT_COMMIT => Statement::Transaction(Transaction::Commit), + sys::TransactionStmtKind::TRANS_STMT_BEGIN => Request::Transaction(Transaction::Begin), + sys::TransactionStmtKind::TRANS_STMT_COMMIT => Request::Transaction(Transaction::Commit), _ => unimplemented!(), }; - statements.push(stmt); + return Ok(stmt); } Ok(Some(node)) => unimplemented!("NODE is not processed {:?}", node), } } - Ok(statements) + unreachable!("should not reach here!") } fn process_query(&self, node: Node) -> Query { diff --git a/postgre_sql/query_parser/src/tests/delete.rs b/postgre_sql/query_parser/src/tests/delete.rs index 5d10b3de..9a6ec2b1 100644 --- a/postgre_sql/query_parser/src/tests/delete.rs +++ b/postgre_sql/query_parser/src/tests/delete.rs @@ -20,10 +20,10 @@ fn delete_from_table() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Delete(DeleteStatement { + Ok(Request::Statement(Statement::Query(Query::Delete(DeleteStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), where_clause: None, - }))]) + })))) ); } diff --git a/postgre_sql/query_parser/src/tests/extended.rs b/postgre_sql/query_parser/src/tests/extended.rs index 4a19646c..cac2dad2 100644 --- a/postgre_sql/query_parser/src/tests/extended.rs +++ b/postgre_sql/query_parser/src/tests/extended.rs @@ -22,7 +22,7 @@ fn prepare() { assert_eq!( statement, - Ok(vec![Statement::Extended(Extended::Prepare { + Ok(Request::Statement(Statement::Extended(Extended::Prepare { query: Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), @@ -31,7 +31,7 @@ fn prepare() { }), name: "foo_plan".to_owned(), param_types: vec![DataType::SmallInt] - })]) + }))) ); } @@ -41,9 +41,9 @@ fn deallocate() { assert_eq!( statement, - Ok(vec![Statement::Extended(Extended::Deallocate { + Ok(Request::Statement(Statement::Extended(Extended::Deallocate { name: "foo_plan".to_owned() - })]) + }))) ); } @@ -53,9 +53,9 @@ fn execute() { assert_eq!( statement, - Ok(vec![Statement::Extended(Extended::Execute { + Ok(Request::Statement(Statement::Extended(Extended::Execute { name: "foo_plan".to_owned(), param_values: vec![Value::Int(123)] - })]) + }))) ) } diff --git a/postgre_sql/query_parser/src/tests/index.rs b/postgre_sql/query_parser/src/tests/index.rs index 2dc6ced1..aea1b231 100644 --- a/postgre_sql/query_parser/src/tests/index.rs +++ b/postgre_sql/query_parser/src/tests/index.rs @@ -20,11 +20,11 @@ fn create_index() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::CreateIndex { + Ok(Request::Statement(Statement::Definition(Definition::CreateIndex { name: "index_name".to_owned(), schema_name: "public".to_owned(), table_name: "table_name".to_owned(), column_names: vec!["col_1".to_owned(), "col_2".to_owned()] - })]) + }))) ); } diff --git a/postgre_sql/query_parser/src/tests/insert.rs b/postgre_sql/query_parser/src/tests/insert.rs index 60838645..5687980f 100644 --- a/postgre_sql/query_parser/src/tests/insert.rs +++ b/postgre_sql/query_parser/src/tests/insert.rs @@ -20,12 +20,12 @@ fn insert_int() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec![], source: InsertSource::Values(Values(vec![vec![Expr::Value(Value::Int(123))]])) - }))]) + })))) ); } @@ -35,12 +35,12 @@ fn insert_string() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec![], source: InsertSource::Values(Values(vec![vec![Expr::Value(Value::String("abc".to_owned()))]])) - }))]) + })))) ); } @@ -80,7 +80,7 @@ mod operators { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec![], @@ -89,7 +89,7 @@ mod operators { op: expected, right: Box::new(Expr::Value(Value::Int(456))) }]])) - }))]) + })))) ); } @@ -111,7 +111,7 @@ mod operators { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec![], @@ -123,7 +123,7 @@ mod operators { right: Box::new(Expr::Value(Value::Int(456))) }) }]])) - }))]) + })))) ); } @@ -133,7 +133,7 @@ mod operators { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec![], @@ -141,7 +141,7 @@ mod operators { op: UnaryOperator::PostfixFactorial, expr: Box::new(Expr::Value(Value::Int(456))) }]])) - }))]) + })))) ); } } @@ -152,12 +152,12 @@ fn insert_with_columns() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec!["col1".to_owned()], source: InsertSource::Values(Values(vec![vec![Expr::Value(Value::Int(123))]])) - }))]) + })))) ); } @@ -167,12 +167,12 @@ fn insert_params() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec!["col1".to_owned()], source: InsertSource::Values(Values(vec![vec![Expr::Param(1)]])) - }))]) + })))) ); } @@ -182,12 +182,12 @@ fn insert_column() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec!["col1".to_owned()], source: InsertSource::Values(Values(vec![vec![Expr::Column("col2".to_owned())]])) - }))]) + })))) ); } @@ -200,7 +200,7 @@ fn insert_int_max() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec![], @@ -212,7 +212,7 @@ fn insert_int_max() { Expr::Value(Value::Number("9223372036854775807".to_owned())), Expr::Value(Value::Number("-9223372036854775808".to_owned())), ]])) - }))]) + })))) ); } @@ -222,7 +222,7 @@ fn cast() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Insert(InsertStatement { + Ok(Request::Statement(Statement::Query(Query::Insert(InsertStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), columns: vec![], @@ -230,6 +230,6 @@ fn cast() { expr: Box::new(Expr::Value(Value::String("true".to_owned()))), data_type: DataType::Bool }]])) - }))]) + })))) ); } diff --git a/postgre_sql/query_parser/src/tests/mod.rs b/postgre_sql/query_parser/src/tests/mod.rs index e059bc9b..c1a0d54f 100644 --- a/postgre_sql/query_parser/src/tests/mod.rs +++ b/postgre_sql/query_parser/src/tests/mod.rs @@ -41,9 +41,9 @@ fn set_variable() { assert_eq!( statements, - Ok(vec![Statement::Config(Set { + Ok(Request::Config(Set { variable: "variable".to_owned(), value: "value".to_owned() - })]) + })) ); } diff --git a/postgre_sql/query_parser/src/tests/predicate.rs b/postgre_sql/query_parser/src/tests/predicate.rs index be6573aa..ab57cc2c 100644 --- a/postgre_sql/query_parser/src/tests/predicate.rs +++ b/postgre_sql/query_parser/src/tests/predicate.rs @@ -20,7 +20,7 @@ fn select() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Select(SelectStatement { + Ok(Request::Statement(Statement::Query(Query::Select(SelectStatement { select_items: vec![SelectItem::Wildcard], schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), @@ -29,7 +29,7 @@ fn select() { op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Int(1))) }), - }))]) + })))) ); } @@ -39,7 +39,7 @@ fn update() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Update(UpdateStatement { + Ok(Request::Statement(Statement::Query(Query::Update(UpdateStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), assignments: vec![Assignment { @@ -51,7 +51,7 @@ fn update() { op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Int(2))) }), - }))]) + })))) ); } @@ -61,7 +61,7 @@ fn delete() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Delete(DeleteStatement { + Ok(Request::Statement(Statement::Query(Query::Delete(DeleteStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), where_clause: Some(Expr::BinaryOp { @@ -69,6 +69,6 @@ fn delete() { op: BinaryOperator::Eq, right: Box::new(Expr::Value(Value::Int(1))) }), - }))]) + })))) ); } diff --git a/postgre_sql/query_parser/src/tests/schema.rs b/postgre_sql/query_parser/src/tests/schema.rs index 5ef7f7a5..0b94217f 100644 --- a/postgre_sql/query_parser/src/tests/schema.rs +++ b/postgre_sql/query_parser/src/tests/schema.rs @@ -20,10 +20,10 @@ fn create_schema() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::CreateSchema { + Ok(Request::Statement(Statement::Definition(Definition::CreateSchema { schema_name: "schema_name".to_owned(), if_not_exists: false - })]) + }))) ); } @@ -33,10 +33,10 @@ fn create_schema_if_not_exists() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::CreateSchema { + Ok(Request::Statement(Statement::Definition(Definition::CreateSchema { schema_name: "schema_name".to_owned(), if_not_exists: true - })]) + }))) ); } @@ -46,11 +46,11 @@ fn drop_schema() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::DropSchemas { + Ok(Request::Statement(Statement::Definition(Definition::DropSchemas { names: vec!["schema_name".to_owned()], if_exists: false, cascade: false - })]) + }))) ); } @@ -60,11 +60,11 @@ fn drop_schemas() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::DropSchemas { + Ok(Request::Statement(Statement::Definition(Definition::DropSchemas { names: vec!["schema_name_1".to_owned(), "schema_name_2".to_owned()], if_exists: false, cascade: false - })]) + }))) ); } @@ -74,11 +74,11 @@ fn drop_schemas_cascade() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::DropSchemas { + Ok(Request::Statement(Statement::Definition(Definition::DropSchemas { names: vec!["schema_name_1".to_owned(), "schema_name_2".to_owned()], if_exists: false, cascade: true - })]) + }))) ); } @@ -88,10 +88,10 @@ fn drop_schema_if_exists() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::DropSchemas { + Ok(Request::Statement(Statement::Definition(Definition::DropSchemas { names: vec!["schema_name".to_owned()], if_exists: true, cascade: false - })]) + }))) ); } diff --git a/postgre_sql/query_parser/src/tests/select.rs b/postgre_sql/query_parser/src/tests/select.rs index b5151e35..dead986f 100644 --- a/postgre_sql/query_parser/src/tests/select.rs +++ b/postgre_sql/query_parser/src/tests/select.rs @@ -20,11 +20,11 @@ fn select_all_from_table() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Select(SelectStatement { + Ok(Request::Statement(Statement::Query(Query::Select(SelectStatement { select_items: vec![SelectItem::Wildcard], schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), where_clause: None, - }))]) + })))) ); } diff --git a/postgre_sql/query_parser/src/tests/table.rs b/postgre_sql/query_parser/src/tests/table.rs index 60e9faf7..52ddba23 100644 --- a/postgre_sql/query_parser/src/tests/table.rs +++ b/postgre_sql/query_parser/src/tests/table.rs @@ -20,7 +20,7 @@ fn create_ints_table() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::CreateTable { + Ok(Request::Statement(Statement::Definition(Definition::CreateTable { if_not_exists: false, schema_name: "public".to_owned(), table_name: "table_name".to_owned(), @@ -38,7 +38,7 @@ fn create_ints_table() { data_type: DataType::BigInt, } ], - })]) + }))) ); } @@ -61,7 +61,7 @@ fn create_strings_table() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::CreateTable { + Ok(Request::Statement(Statement::Definition(Definition::CreateTable { if_not_exists: false, schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), @@ -99,7 +99,7 @@ fn create_strings_table() { data_type: DataType::VarChar(Some(255)), } ], - })]) + }))) ); } @@ -109,7 +109,7 @@ fn create_float_table() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::CreateTable { + Ok(Request::Statement(Statement::Definition(Definition::CreateTable { if_not_exists: false, schema_name: "public".to_owned(), table_name: "table_name".to_owned(), @@ -123,7 +123,7 @@ fn create_float_table() { data_type: DataType::Double, } ], - })]) + }))) ); } @@ -133,7 +133,7 @@ fn create_boolean_table() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::CreateTable { + Ok(Request::Statement(Statement::Definition(Definition::CreateTable { if_not_exists: false, schema_name: "public".to_owned(), table_name: "table_name".to_owned(), @@ -141,7 +141,7 @@ fn create_boolean_table() { name: "col_b".to_owned(), data_type: DataType::Bool, }], - })]) + }))) ); } @@ -151,11 +151,11 @@ fn drop_table() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::DropTables { + Ok(Request::Statement(Statement::Definition(Definition::DropTables { names: vec![("public".to_owned(), "table_name".to_owned())], if_exists: false, cascade: false - })]) + }))) ); } @@ -165,14 +165,14 @@ fn drop_tables() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::DropTables { + Ok(Request::Statement(Statement::Definition(Definition::DropTables { names: vec![ ("public".to_owned(), "table_name_1".to_owned()), ("public".to_owned(), "table_name_2".to_owned()) ], if_exists: false, cascade: false - })]) + }))) ); } @@ -182,14 +182,14 @@ fn drop_table_cascade() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::DropTables { + Ok(Request::Statement(Statement::Definition(Definition::DropTables { names: vec![ ("public".to_owned(), "table_name_1".to_owned()), ("public".to_owned(), "table_name_2".to_owned()) ], if_exists: false, cascade: true - })]) + }))) ); } @@ -199,10 +199,10 @@ fn drop_table_if_exists() { assert_eq!( statements, - Ok(vec![Statement::Definition(Definition::DropTables { + Ok(Request::Statement(Statement::Definition(Definition::DropTables { names: vec![("public".to_owned(), "table_name".to_owned())], if_exists: true, cascade: false - })]) + }))) ); } diff --git a/postgre_sql/query_parser/src/tests/update.rs b/postgre_sql/query_parser/src/tests/update.rs index ce227d6d..22f5fd39 100644 --- a/postgre_sql/query_parser/src/tests/update.rs +++ b/postgre_sql/query_parser/src/tests/update.rs @@ -20,7 +20,7 @@ fn update_int() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Update(UpdateStatement { + Ok(Request::Statement(Statement::Query(Query::Update(UpdateStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), assignments: vec![Assignment { @@ -28,7 +28,7 @@ fn update_int() { value: Expr::Value(Value::Int(123)) }], where_clause: None - }))]) + })))) ); } @@ -38,7 +38,7 @@ fn update_string() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Update(UpdateStatement { + Ok(Request::Statement(Statement::Query(Query::Update(UpdateStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), assignments: vec![Assignment { @@ -46,7 +46,7 @@ fn update_string() { value: Expr::Value(Value::String("abc".to_owned())) }], where_clause: None - }))]) + })))) ); } @@ -86,7 +86,7 @@ mod bi_ops { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Update(UpdateStatement { + Ok(Request::Statement(Statement::Query(Query::Update(UpdateStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), assignments: vec![Assignment { @@ -98,7 +98,7 @@ mod bi_ops { } }], where_clause: None - }))]) + })))) ); } } @@ -109,7 +109,7 @@ fn update_params() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Update(UpdateStatement { + Ok(Request::Statement(Statement::Query(Query::Update(UpdateStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), assignments: vec![Assignment { @@ -117,7 +117,7 @@ fn update_params() { value: Expr::Param(1) }], where_clause: None, - }))]) + })))) ); } @@ -127,7 +127,7 @@ fn update_columns() { assert_eq!( statements, - Ok(vec![Statement::Query(Query::Update(UpdateStatement { + Ok(Request::Statement(Statement::Query(Query::Update(UpdateStatement { schema_name: "schema_name".to_owned(), table_name: "table_name".to_owned(), assignments: vec![Assignment { @@ -139,6 +139,6 @@ fn update_columns() { } }], where_clause: None, - }))]) + })))) ); } diff --git a/postgre_sql/wire_protocol/src/lib.rs b/postgre_sql/wire_protocol/src/lib.rs index e2332682..0d5e6fde 100644 --- a/postgre_sql/wire_protocol/src/lib.rs +++ b/postgre_sql/wire_protocol/src/lib.rs @@ -30,6 +30,7 @@ use wire_protocol_payload::{ pub type WireResult = std::result::Result; +#[derive(Debug)] pub struct WireError; pub trait WireConnection { diff --git a/sql_engine/catalog/src/lib.rs b/sql_engine/catalog/src/lib.rs index 3776e959..11408678 100644 --- a/sql_engine/catalog/src/lib.rs +++ b/sql_engine/catalog/src/lib.rs @@ -27,6 +27,7 @@ const TABLES_TABLE: &str = "TABLES"; const INDEXES_TABLE: &str = "TABLES"; const COLUMNS_TABLE: &str = "COLUMNS"; +#[derive(Clone)] pub struct CatalogHandler<'c> { transaction: Transaction<'c>, } diff --git a/sql_engine/data_manipulation/query_plan/src/lib.rs b/sql_engine/data_manipulation/query_plan/src/lib.rs index 13ae4feb..121b0836 100644 --- a/sql_engine/data_manipulation/query_plan/src/lib.rs +++ b/sql_engine/data_manipulation/query_plan/src/lib.rs @@ -33,13 +33,23 @@ pub enum QueryExecutionResult { Selected((Vec<(String, u32)>, Vec>)), } -impl From for QueryEvent { - fn from(plan_result: QueryExecutionResult) -> QueryEvent { +impl From for Vec { + fn from(plan_result: QueryExecutionResult) -> Vec { match plan_result { - QueryExecutionResult::Inserted(inserted) => QueryEvent::RecordsInserted(inserted), - QueryExecutionResult::Deleted(inserted) => QueryEvent::RecordsDeleted(inserted), - QueryExecutionResult::Updated(inserted) => QueryEvent::RecordsUpdated(inserted), - _ => unreachable!(), + QueryExecutionResult::Inserted(inserted) => vec![QueryEvent::RecordsInserted(inserted)], + QueryExecutionResult::Deleted(inserted) => vec![QueryEvent::RecordsDeleted(inserted)], + QueryExecutionResult::Updated(inserted) => vec![QueryEvent::RecordsUpdated(inserted)], + QueryExecutionResult::Selected((desc, data)) => { + let mut events = vec![QueryEvent::RowDescription(desc)]; + let len = data.len(); + for row in data { + events.push(QueryEvent::DataRow( + row.into_iter().map(|scalar| scalar.as_text()).collect(), + )); + } + events.push(QueryEvent::RecordsSelected(len)); + events + } } } } diff --git a/sql_engine/definition_planner/src/lib.rs b/sql_engine/definition_planner/src/lib.rs index 50b41bb5..56f46ef7 100644 --- a/sql_engine/definition_planner/src/lib.rs +++ b/sql_engine/definition_planner/src/lib.rs @@ -22,6 +22,7 @@ use query_response::QueryError; use storage::{Transaction, TransactionalDatabase}; use types::SqlType; +#[derive(Clone)] pub struct DefinitionPlanner<'p> { catalog: CatalogHandler<'p>, } diff --git a/sql_engine/query_analyzer/src/lib.rs b/sql_engine/query_analyzer/src/lib.rs index e0b15784..9fc7689b 100644 --- a/sql_engine/query_analyzer/src/lib.rs +++ b/sql_engine/query_analyzer/src/lib.rs @@ -30,6 +30,7 @@ use storage::{Transaction, TransactionalDatabase}; mod dynamic_tree_builder; mod static_tree_builder; +#[derive(Clone)] pub struct QueryAnalyzer<'a> { catalog: CatalogHandler<'a>, } diff --git a/sql_engine/query_planner/src/lib.rs b/sql_engine/query_planner/src/lib.rs index 8d09fa72..19754949 100644 --- a/sql_engine/query_planner/src/lib.rs +++ b/sql_engine/query_planner/src/lib.rs @@ -21,6 +21,7 @@ use data_manipulation_typed_queries::TypedQuery; use data_manipulation_typed_tree::{DynamicTypedItem, DynamicTypedTree}; use storage::{Transaction, TransactionalDatabase}; +#[derive(Clone)] pub struct QueryPlanner<'p> { transaction: Transaction<'p>, catalog: CatalogHandler<'p>, diff --git a/sql_engine/query_processing/type_check/src/lib.rs b/sql_engine/query_processing/type_check/src/lib.rs index 8ddd10cd..ebcdccab 100644 --- a/sql_engine/query_processing/type_check/src/lib.rs +++ b/sql_engine/query_processing/type_check/src/lib.rs @@ -14,6 +14,7 @@ use data_manipulation_typed_tree::{DynamicTypedTree, StaticTypedTree}; +#[derive(Clone)] pub struct TypeChecker; impl TypeChecker { diff --git a/sql_engine/query_processing/type_coercion/src/lib.rs b/sql_engine/query_processing/type_coercion/src/lib.rs index 77bb7851..4f6bc0f2 100644 --- a/sql_engine/query_processing/type_coercion/src/lib.rs +++ b/sql_engine/query_processing/type_coercion/src/lib.rs @@ -15,6 +15,7 @@ use data_manipulation_typed_tree::{DynamicTypedTree, StaticTypedTree}; use types::SqlType; +#[derive(Clone)] pub struct TypeCoercion; impl TypeCoercion { diff --git a/sql_engine/query_processing/type_inference/src/lib.rs b/sql_engine/query_processing/type_inference/src/lib.rs index 08454d19..72096980 100644 --- a/sql_engine/query_processing/type_inference/src/lib.rs +++ b/sql_engine/query_processing/type_inference/src/lib.rs @@ -20,6 +20,7 @@ use data_manipulation_untyped_tree::{ use std::ops::RangeInclusive; use types::{Bool, SqlTypeFamily}; +#[derive(Clone)] pub struct TypeInference { small_int_range: RangeInclusive, integer_range: RangeInclusive,