From f81b311fdbe41d2599e39068cb9a3a4821a71f95 Mon Sep 17 00:00:00 2001 From: Chase Willden Date: Tue, 15 Oct 2024 13:08:05 -0600 Subject: [PATCH] Add tests, commented tests will come later --- .github/workflows/core.yml | 20 +- docker-compose.yml | 1 + njord/db/insert.db | Bin 20480 -> 167936 bytes njord/db/test/mysql.sql | 31 ++ njord/src/mysql/select.rs | 50 ++- njord/src/mysql/update.rs | 11 +- njord/tests/mysql/delete_test.rs | 52 +++ njord/tests/mysql/insert_test.rs | 27 ++ njord/tests/mysql/mod.rs | 56 +++ njord/tests/mysql/open_test.rs | 8 + njord/tests/mysql/select_joins_test.rs | 85 +++++ njord/tests/mysql/select_test.rs | 509 +++++++++++++++++++++++++ njord/tests/mysql/update_test.rs | 57 +++ njord_examples/mysql/src/main.rs | 24 ++ 14 files changed, 910 insertions(+), 21 deletions(-) create mode 100644 njord/tests/mysql/delete_test.rs create mode 100644 njord/tests/mysql/insert_test.rs create mode 100644 njord/tests/mysql/open_test.rs create mode 100644 njord/tests/mysql/select_joins_test.rs create mode 100644 njord/tests/mysql/select_test.rs create mode 100644 njord/tests/mysql/update_test.rs diff --git a/.github/workflows/core.yml b/.github/workflows/core.yml index 08050be0..adb01715 100644 --- a/.github/workflows/core.yml +++ b/.github/workflows/core.yml @@ -65,12 +65,19 @@ jobs: - name: Running Integration Tests for SQLite run: cargo test --test sqlite_tests -# - name: Set up MySQL schema -# env: -# MYSQL_PWD: rootpassword -# run: | -# echo "Injecting schema and data into MySQL..." -# mysql -h 127.0.0.1 -u root njord_db < njord/db/test/mysql.sql + - name: Wait for MySQL to be ready + run: | + until mysqladmin ping -h 127.0.0.1 --silent; do + echo "Waiting for MySQL to be ready..." + sleep 5 + done + + - name: Set up MySQL schema + env: + MYSQL_PWD: rootpassword + run: | + echo "Injecting schema and data into MySQL..." + mysql -h 127.0.0.1 -u njord_user -pnjord_password njord_db < njord/db/test/mysql.sql - name: Running Unit Tests for MySQL run: cargo test mysql @@ -82,4 +89,3 @@ jobs: MYSQL_PASSWORD: njord_password MYSQL_HOST: 127.0.0.1 run: cargo test --test sqlite_tests - diff --git a/docker-compose.yml b/docker-compose.yml index a55753d8..99c46843 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -14,6 +14,7 @@ services: volumes: - mysql_data:/var/lib/mysql - ./njord_examples/mysql/init.sql:/docker-entrypoint-initdb.d/init.sql + - ./njord/db/test/mysql.sql:/docker-entrypoint-initdb.d/tests.sql volumes: mysql_data: diff --git a/njord/db/insert.db b/njord/db/insert.db index b8c8894cff9874b0ce1943e1b0268e8cca9cc76e..cf2d4537b4765abecb1e42b33bbf44bef8a87bfb 100644 GIT binary patch literal 167936 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 delta 71 zcmZozz}2vTae_4KR0akH)`<%Cj8iuzEaB&2;{OU1U|{9{&Hr_?fWcG#&0ppD6_};C bS|+nQm~Jfe;9@pz)SbN0!*uf=FBet-?pGD3 diff --git a/njord/db/test/mysql.sql b/njord/db/test/mysql.sql index e69de29b..f2468ce3 100644 --- a/njord/db/test/mysql.sql +++ b/njord/db/test/mysql.sql @@ -0,0 +1,31 @@ +DROP DATABASE IF EXISTS njord_db; + +CREATE DATABASE njord_db; + +USE njord_db; + +-- Table: users +CREATE TABLE users ( + id INT AUTO_INCREMENT PRIMARY KEY, -- Auto incrementing primary key for the user ID + username VARCHAR(255) NOT NULL, -- Username field + email VARCHAR(255) NOT NULL, -- Email field + address VARCHAR(255) -- Address field +); + +-- Table: categories +CREATE TABLE categories ( + id INT PRIMARY KEY, -- Primary key for categories + name VARCHAR(255) NOT NULL -- Name of the category +); + +-- Table: products +CREATE TABLE products ( + id INT PRIMARY KEY, -- Primary key for products + name VARCHAR(255) NOT NULL, -- Product name + description TEXT, -- Product description + price DECIMAL(10, 2) NOT NULL, -- Price with up to two decimal places + stock_quantity INT NOT NULL, -- Stock quantity + category_id INT NOT NULL, -- Foreign key to categories (one-to-one relationship) + discount DECIMAL(5, 2) DEFAULT 0.00, -- Discount field with default value + FOREIGN KEY (category_id) REFERENCES categories(id) -- Foreign key constraint to categories table +); diff --git a/njord/src/mysql/select.rs b/njord/src/mysql/select.rs index 9387e9a0..d614571e 100644 --- a/njord/src/mysql/select.rs +++ b/njord/src/mysql/select.rs @@ -42,7 +42,7 @@ use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc}; use log::info; use mysql::prelude::*; -use mysql::{prelude::FromRow, Error, PooledConn}; +use mysql::{Error, PooledConn, Value}; use crate::table::Table; use crate::util::{Join, JoinType}; @@ -57,7 +57,7 @@ use crate::util::{Join, JoinType}; /// # Returns /// /// A `SelectQueryBuilder` instance. -pub fn select<'a, T: Table + Default + FromRow>( +pub fn select<'a, T: Table + Default>( conn: &'a mut PooledConn, columns: Vec>, ) -> SelectQueryBuilder<'a, T> { @@ -66,7 +66,7 @@ pub fn select<'a, T: Table + Default + FromRow>( /// A builder for constructing SELECT queries. #[derive(Clone)] -pub struct SelectQueryBuilder<'a, T: Table + Default + FromRow> { +pub struct SelectQueryBuilder<'a, T: Table + Default> { conn: Rc>, table: Option, columns: Vec>, @@ -82,7 +82,7 @@ pub struct SelectQueryBuilder<'a, T: Table + Default + FromRow> { joins: Option>>, } -impl<'a, T: Table + Default + FromRow> SelectQueryBuilder<'a, T> { +impl<'a, T: Table + Default> SelectQueryBuilder<'a, T> { /// Creates a new `SelectQueryBuilder` instance. /// /// # Arguments @@ -366,10 +366,46 @@ impl<'a, T: Table + Default + FromRow> SelectQueryBuilder<'a, T> { info!("{}", final_query); println!("{}", final_query); - // Borrow the connection mutably from the RefCell let mut conn = self.conn.borrow_mut(); + let query_set = conn.query_iter(final_query.as_str()).unwrap(); + + let mut results: Vec = Vec::new(); + + for row_result in query_set { + let row = row_result.unwrap(); // Unwrap the row result + let mut instance = T::default(); + + for column in row.columns_ref() { + // Cells in a row can be indexed by numeric index or by column name + let column_value = &row[column.name_str().as_ref()]; + + let column_value_str = match column_value { + Value::NULL => "NULL".to_string(), + Value::Bytes(bytes) => String::from_utf8_lossy(bytes).to_string(), + Value::Int(i) => i.to_string(), + Value::UInt(u) => u.to_string(), + Value::Float(f) => f.to_string(), + Value::Double(d) => d.to_string(), + Value::Date(year, month, day, hour, min, sec, micro) => format!( + "{:04}-{:02}-{:02} {:02}:{:02}:{:02}.{:06}", + year, month, day, hour, min, sec, micro + ), + Value::Time(neg, days, hours, minutes, seconds, micros) => format!( + "{}{:02}:{:02}:{:02}.{:06}", + if *neg { "-" } else { "" }, + days * 24 + u32::from(*hours), + minutes, + seconds, + micros + ), + }; + + instance.set_column_value(column.name_str().as_ref(), &column_value_str); + } - let results: Vec = conn.query(final_query.as_str())?; + // Move `instance` to the `results` only after it is fully set up + results.push(instance); + } Ok(results) } @@ -380,7 +416,7 @@ impl<'a, T: Table + Default + FromRow> SelectQueryBuilder<'a, T> { /// The where statement ensures the T is long lived impl<'a, T> QueryBuilder<'a> for SelectQueryBuilder<'a, T> where - T: Table + Default + Clone + FromRow + 'a, // Added 'a bound here + T: Table + Default + Clone + 'a, // Added 'a bound here { fn to_sql(&self) -> String { self.build_query() diff --git a/njord/src/mysql/update.rs b/njord/src/mysql/update.rs index 78eec0d0..5f835fb6 100644 --- a/njord/src/mysql/update.rs +++ b/njord/src/mysql/update.rs @@ -40,10 +40,7 @@ use crate::{ }; use log::info; -use mysql::{ - prelude::{FromRow, Queryable}, - PooledConn, -}; +use mysql::{prelude::Queryable, PooledConn}; use crate::table::Table; @@ -59,7 +56,7 @@ use super::select::SelectQueryBuilder; /// # Returns /// /// An `UpdateQueryBuilder` instance. -pub fn update<'a, T: Table + Default + FromRow>( +pub fn update<'a, T: Table + Default>( conn: &'a mut PooledConn, table: T, ) -> UpdateQueryBuilder<'a, T> { @@ -67,7 +64,7 @@ pub fn update<'a, T: Table + Default + FromRow>( } /// A builder for constructing UPDATE queries. -pub struct UpdateQueryBuilder<'a, T: Table + Default + FromRow> { +pub struct UpdateQueryBuilder<'a, T: Table + Default> { conn: &'a mut PooledConn, table: Option, columns: Vec, @@ -78,7 +75,7 @@ pub struct UpdateQueryBuilder<'a, T: Table + Default + FromRow> { offset: Option, } -impl<'a, T: Table + Default + FromRow> UpdateQueryBuilder<'a, T> { +impl<'a, T: Table + Default> UpdateQueryBuilder<'a, T> { /// Creates a new `UpdateQueryBuilder` instance. /// /// # Arguments diff --git a/njord/tests/mysql/delete_test.rs b/njord/tests/mysql/delete_test.rs new file mode 100644 index 00000000..22073dc2 --- /dev/null +++ b/njord/tests/mysql/delete_test.rs @@ -0,0 +1,52 @@ +use super::User; +use njord::condition::{Condition, Value}; +use njord::keys::AutoIncrementPrimaryKey; +use njord::mysql; +use std::vec; + +#[test] +fn delete_row() { + insert_row(); + + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let mut conn = mysql::open(url); + + match conn { + Ok(ref mut c) => { + let result = mysql::delete(c) + .from(User::default()) + .where_clause(Condition::Eq( + "username".to_string(), + Value::Literal("chasewillden2".to_string()), + )) + .build(); + assert!(result.is_ok()); + } + Err(e) => { + panic!("Failed to DELETE: {:?}", e); + } + } +} + +/// Helper function to insert a row to be deleted +fn insert_row() { + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let mut conn = mysql::open(url); + + let table_row: User = User { + id: AutoIncrementPrimaryKey::default(), + username: "chasewillden2".to_string(), + email: "chase.willden@example.com".to_string(), + address: "Some Random Address 1".to_string(), + }; + + match conn { + Ok(ref mut c) => { + let result = mysql::insert(c, vec![table_row]); + assert!(result.is_ok()); + } + Err(e) => { + panic!("Failed to INSERT: {:?}", e); + } + } +} diff --git a/njord/tests/mysql/insert_test.rs b/njord/tests/mysql/insert_test.rs new file mode 100644 index 00000000..a4a9ccc4 --- /dev/null +++ b/njord/tests/mysql/insert_test.rs @@ -0,0 +1,27 @@ +use super::User; +use njord::keys::AutoIncrementPrimaryKey; +use njord::mysql; +use std::vec; + +#[test] +fn insert_row() { + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let mut conn = mysql::open(url); + + let table_row: User = User { + id: AutoIncrementPrimaryKey::default(), + username: "chasewillden".to_string(), + email: "chase.willden@example.com".to_string(), + address: "Some Random Address 1".to_string(), + }; + + match conn { + Ok(ref mut c) => { + let result = mysql::insert(c, vec![table_row]); + assert!(result.is_ok()); + } + Err(e) => { + panic!("Failed to INSERT: {:?}", e); + } + } +} diff --git a/njord/tests/mysql/mod.rs b/njord/tests/mysql/mod.rs index e69de29b..a8a49f93 100644 --- a/njord/tests/mysql/mod.rs +++ b/njord/tests/mysql/mod.rs @@ -0,0 +1,56 @@ +mod delete_test; +mod insert_test; +mod open_test; +mod select_joins_test; +mod select_test; +mod update_test; + +use njord::keys::{AutoIncrementPrimaryKey, PrimaryKey}; +use njord::table::Table; +use njord_derive::Table; + +#[derive(Table, Clone)] +#[table_name = "users"] +pub struct User { + pub id: AutoIncrementPrimaryKey, + pub username: String, + pub email: String, + pub address: String, +} + +#[derive(Table)] +#[table_name = "users"] +pub struct UserWithSubQuery { + pub id: AutoIncrementPrimaryKey, + pub username: String, + pub email: String, + pub address: String, + pub additional_address: String, +} + +#[derive(Table)] +#[table_name = "categories"] +pub struct Category { + pub id: PrimaryKey, + pub name: String, +} + +#[derive(Table)] +#[table_name = "products"] +pub struct Product { + pub id: PrimaryKey, + pub name: String, + pub description: String, + pub price: f64, + pub stock_quantity: usize, + pub category: Category, // one-to-one relationship + pub discount: f64, +} + +#[derive(Table)] +#[table_name = "users"] +pub struct UsersWithJoin { + username: String, + price: f64, + name: String, +} diff --git a/njord/tests/mysql/open_test.rs b/njord/tests/mysql/open_test.rs new file mode 100644 index 00000000..82a4ccbe --- /dev/null +++ b/njord/tests/mysql/open_test.rs @@ -0,0 +1,8 @@ +use njord::mysql; + +#[test] +fn open_db() { + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let result = mysql::open(url); + assert!(result.is_ok()); +} diff --git a/njord/tests/mysql/select_joins_test.rs b/njord/tests/mysql/select_joins_test.rs new file mode 100644 index 00000000..d2b11f9e --- /dev/null +++ b/njord/tests/mysql/select_joins_test.rs @@ -0,0 +1,85 @@ +use njord::condition::Condition; +use njord::mysql; +use njord::util::JoinType; +use njord::{column::Column, condition::Value}; +use std::sync::Arc; + +use crate::{Product, UsersWithJoin}; + +// FIXME +// #[test] +// fn select_inner_join() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// // Assume we have pre-inserted some data into the users and products tables +// let columns = vec![ +// Column::Text("users.username".to_string()), +// Column::Text("products.name".to_string()), +// Column::Text("products.price".to_string()), +// ]; + +// // Assuming a hypothetical join condition: users.id = products.user_id +// let join_condition = Condition::Eq( +// "users.id".to_string(), +// Value::Literal("products.user_id".to_string()), +// ); +// match conn { +// Ok(ref mut c) => { +// let result = mysql::select(c, columns) +// .from(UsersWithJoin::default()) +// .join( +// JoinType::Inner, +// Arc::new(Product::default()), +// join_condition, +// ) +// .build(); +// match result { +// Ok(r) => { +// // Check the number of results and assert against expected values +// assert!(!r.is_empty(), "Expected results, but got none."); +// // Further assertions on expected data can be made here based on inserted data +// } +// Err(e) => panic!("Failed to SELECT with JOIN: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// } +// } + +// #[test] +// fn select_left_join() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// // Assume we have pre-inserted some data into the users and products tables +// let columns = vec![ +// Column::Text("users.username".to_string()), +// Column::Text("products.name".to_string()), +// Column::Text("products.price".to_string()), +// ]; + +// // Assuming a hypothetical join condition: users.id = products.user_id +// let join_condition = Condition::Eq( +// "users.id".to_string(), +// Value::Literal("products.user_id".to_string()), +// ); +// match conn { +// Ok(ref mut c) => { +// let result = mysql::select(c, columns) +// .from(UsersWithJoin::default()) +// .join(JoinType::Left, Arc::new(Product::default()), join_condition) +// .build(); +// match result { +// Ok(r) => { +// // Check the number of results and assert against expected values +// assert!(!r.is_empty(), "Expected results, but got none."); +// assert_eq!(r.len(), 2, "Expected 2 results from the LEFT JOIN query."); +// // Further assertions on expected data can be made here based on inserted data +// } +// Err(e) => panic!("Failed to SELECT with JOIN: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// } +// } diff --git a/njord/tests/mysql/select_test.rs b/njord/tests/mysql/select_test.rs new file mode 100644 index 00000000..0594695c --- /dev/null +++ b/njord/tests/mysql/select_test.rs @@ -0,0 +1,509 @@ +use njord::condition::Condition; +use njord::keys::AutoIncrementPrimaryKey; +use njord::mysql; +use njord::{column::Column, condition::Value}; +use std::collections::HashMap; + +use crate::User; + +#[test] +fn open_db() { + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let conn = mysql::open(url); + assert!(conn.is_ok()); +} + +#[test] +fn insert_row() { + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let mut conn = mysql::open(url); + + let table_row: User = User { + id: AutoIncrementPrimaryKey::default(), + username: "mjovanc".to_string(), + email: "mjovanc@icloud.com".to_string(), + address: "Some Random Address 1".to_string(), + }; + + match conn { + Ok(ref mut c) => { + let result = mysql::insert(c, vec![table_row]); + assert!(result.is_ok()); + } + Err(e) => { + panic!("Failed to INSERT: {:?}", e); + } + } +} + +#[test] +fn update() { + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let mut conn = mysql::open(url); + + let columns = vec!["username".to_string()]; + + let condition = Condition::Eq( + "username".to_string(), + Value::Literal("mjovanc".to_string()), + ); + + let table_row: User = User { + id: AutoIncrementPrimaryKey::::new(Some(0)), + username: "mjovanc".to_string(), + email: "mjovanc@icloud.com".to_string(), + address: "Some Random Address 1".to_string(), + }; + + let mut order = HashMap::new(); + order.insert(vec!["id".to_string()], "DESC".to_string()); + + match conn { + Ok(ref mut c) => { + let result = mysql::update(c, table_row) + .set(columns) + .where_clause(condition) + .order_by(order) + .limit(4) + .offset(0) + .build(); + println!("{:?}", result); + assert!(result.is_ok()); + } + Err(e) => { + panic!("Failed to UPDATE: {:?}", e); + } + } +} + +#[test] +fn delete() { + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let mut conn = mysql::open(url); + + let condition = Condition::Eq( + "address".to_string(), + Value::Literal("Some Random Address 1".to_string()), + ); + + let mut order = HashMap::new(); + order.insert(vec!["id".to_string()], "DESC".to_string()); + + match conn { + Ok(ref mut c) => { + let result = mysql::delete(c) + .from(User::default()) + .where_clause(condition) + .order_by(order) + .limit(20) + .offset(0) + .build(); + println!("{:?}", result); + assert!(result.is_ok()); + } + Err(e) => { + panic!("Failed to DELETE: {:?}", e); + } + } +} + +// FIXME +// #[test] +// fn select() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// let columns = vec![ +// Column::Text("id".to_string()), +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// Column::Text("address".to_string()), +// ]; +// let condition = Condition::Eq( +// "username".to_string(), +// Value::Literal("mjovanc".to_string()), +// ); + +// match conn { +// Ok(ref mut c) => { +// let result = mysql::select(c, columns) +// .from(User::default()) +// .where_clause(condition) +// .build(); + +// match result { +// Ok(r) => assert_eq!(r.len(), 2), +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } + +// FIXME +// #[test] +// fn select_distinct() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// let columns = vec![ +// Column::Text("id".to_string()), +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// Column::Text("address".to_string()), +// ]; +// let condition = Condition::Eq( +// "username".to_string(), +// Value::Literal("mjovanc".to_string()), +// ); + +// match conn { +// Ok(ref mut c) => { +// let result = mysql::select(c, columns) +// .from(User::default()) +// .where_clause(condition) +// .distinct() +// .build(); + +// match result { +// Ok(r) => { +// // TODO: this test does not work properly since it should return 1 but it seems +// // like it returns all rows because id is different. Need to check up on that. +// assert_eq!(r.len(), 2); +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } + +// #[test] +// fn select_group_by() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// let columns = vec![ +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// ]; +// let condition = Condition::Eq( +// "username".to_string(), +// Value::Literal("mjovanc".to_string()), +// ); +// let group_by = vec!["username".to_string(), "email".to_string()]; + +// match conn { +// Ok(ref mut c) => { +// let result = mysql::select(c, columns) +// .from(User::default()) +// .where_clause(condition) +// .group_by(group_by) +// .build(); + +// match result { +// Ok(r) => assert_eq!(r.len(), 1), +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } + +// #[test] +// fn select_order_by() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// let columns = vec![ +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// ]; +// let condition = Condition::Eq( +// "username".to_string(), +// Value::Literal("mjovanc".to_string()), +// ); +// let group_by = vec!["username".to_string(), "email".to_string()]; + +// let mut order_by = HashMap::new(); +// order_by.insert(vec!["email".to_string()], "ASC".to_string()); + +// match conn { +// Ok(ref mut c) => { +// let result = mysql::select(c, columns) +// .from(User::default()) +// .where_clause(condition) +// .order_by(order_by) +// .group_by(group_by) +// .build(); + +// match result { +// Ok(r) => assert_eq!(r.len(), 1), +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } + +// FIXME: +// #[test] +// fn select_limit_offset() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// let columns = vec![ +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// ]; +// let condition = Condition::Eq( +// "username".to_string(), +// Value::Literal("mjovanc".to_string()), +// ); +// let group_by = vec!["username".to_string(), "email".to_string()]; + +// let mut order_by = HashMap::new(); +// order_by.insert(vec!["id".to_string()], "DESC".to_string()); + +// match conn { +// Ok(ref mut c) => { +// let result = mysql::select(c, columns) +// .from(User::default()) +// .where_clause(condition) +// .order_by(order_by) +// .group_by(group_by) +// .limit(1) +// .offset(0) +// .build(); + +// match result { +// Ok(r) => assert_eq!(r.len(), 1), +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } +// Err(error) => panic!("Failed to SELECT: {:?}", error), +// }; +// } + +// FIXME +// #[test] +// fn select_having() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// let columns = vec![ +// Column::Text("id".to_string()), +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// ]; +// let condition = Condition::Eq( +// "username".to_string(), +// Value::Literal("mjovanc".to_string()), +// ); +// let group_by = vec!["username".to_string(), "email".to_string()]; + +// let mut order_by = HashMap::new(); +// order_by.insert(vec!["email".to_string()], "DESC".to_string()); + +// let having_condition = Condition::Gt("id".to_string(), Value::Literal("1".to_string())); + +// match conn { +// Ok(ref mut c) => { +// let result = mysql::select(c, columns) +// .from(User::default()) +// .where_clause(condition) +// .order_by(order_by) +// .group_by(group_by) +// .having(having_condition) +// .build(); + +// match result { +// Ok(r) => assert_eq!(r.len(), 1), +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// } +// } + +// FIXME: Figure out how to implement these below +// #[test] +// fn select_except() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// let columns = vec![ +// Column::Text("id".to_string()), +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// Column::Text("address".to_string()), +// ]; + +// let condition1 = Condition::Eq( +// "username".to_string(), +// Value::Literal("mjovanc".to_string()), +// ); +// let condition2 = Condition::Eq( +// "username".to_string(), +// Value::Literal("otheruser".to_string()), +// ); +// let condition3 = Condition::Eq( +// "username".to_string(), +// Value::Literal("anotheruser".to_string()), +// ); + +// match conn { +// Ok(ref mut c) => { +// // Create a new connection for each query builder +// let query1 = mysql::select(c, columns.clone()) +// .from(User::default()) +// .where_clause(condition1); + +// let query2 = mysql::select(c, columns.clone()) +// .from(User::default()) +// .where_clause(condition2); + +// let query3 = mysql::select(c, columns.clone()) +// .from(User::default()) +// .where_clause(condition3); + +// // Test a chain of EXCEPT queries (query1 EXCEPT query2 EXCEPT query3) +// let result = query1.except(query2).except(query3).build(); + +// match result { +// Ok(r) => { +// assert_eq!(r.len(), 2, "Expected 2 results after EXCEPT clauses."); +// } +// Err(e) => panic!("Failed to SELECT with EXCEPT: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } + +// #[test] +// fn select_union() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// let columns = vec![ +// Column::Text("id".to_string()), +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// Column::Text("address".to_string()), +// ]; + +// let condition1 = Condition::Eq("id".to_string(), Value::Literal(42.to_string())); +// let condition2 = Condition::Eq("id".to_string(), Value::Literal(43.to_string())); + +// match conn { +// Ok(ref mut c) => { +// // Create a new connection for each query builder +// let query1 = mysql::select(c, columns.clone()) +// .from(User::default()) +// .where_clause(condition1); + +// let query2 = mysql::select(c, columns.clone()) +// .from(User::default()) +// .where_clause(condition2); + +// // Test a chain of UNION queries (query1 UNION query2) +// let result = query1.union(query2).build(); + +// match result { +// Ok(r) => { +// // We expect two results: mjovanc and otheruser +// assert_eq!(r.len(), 2, "Expected 2 results from the UNION query."); +// assert_eq!( +// r[0].id, +// AutoIncrementPrimaryKey::new(Some(42)), +// "First user should be mjovanc." +// ); +// assert_eq!( +// r[1].id, +// AutoIncrementPrimaryKey::new(Some(43)), +// "Second user should be otheruser." +// ); +// } +// Err(e) => panic!("Failed to SELECT with UNION: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// } +// } + +// #[test] +// fn select_sub_queries() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// match conn { +// Ok(c) => { +// let sub_query = mysql::select(&c, vec![Column::Text("username".to_string())]) +// .from(UserWithSubQuery::default()); + +// let columns = vec![ +// Column::Text("id".to_string()), +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// Column::Text("address".to_string()), +// Column::SubQuery(sub_query), +// ]; + +// let result = mysql::select(&c, columns) +// .from(UserWithSubQuery::default()) +// .build(); + +// match result { +// Ok(r) => { +// assert_eq!(r.len(), 2); +// assert_eq!(r[0].additional_address, "mjovanc"); +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } + +// #[test] +// fn select_in() { +// let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; +// let mut conn = mysql::open(url); + +// let columns = vec![ +// Column::Text("id".to_string()), +// Column::Text("username".to_string()), +// Column::Text("email".to_string()), +// Column::Text("address".to_string()), +// ]; + +// let condition = Condition::And( +// Box::new(Condition::In( +// "username".to_string(), +// vec![ +// Value::Literal("mjovanc".to_string()), +// Value::Literal("otheruser".to_string()), +// ], +// )), +// Box::new(Condition::NotIn( +// "username".to_string(), +// vec![Value::Literal("chasewillden".to_string())], +// )), +// ); + +// match conn { +// Ok(ref mut c) => { +// let result = mysql::select(c, columns) +// .from(User::default()) +// .where_clause(condition) +// .build(); + +// match result { +// Ok(r) => assert_eq!(r.len(), 2), +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } +// Err(e) => panic!("Failed to SELECT: {:?}", e), +// }; +// } diff --git a/njord/tests/mysql/update_test.rs b/njord/tests/mysql/update_test.rs new file mode 100644 index 00000000..09d429ac --- /dev/null +++ b/njord/tests/mysql/update_test.rs @@ -0,0 +1,57 @@ +use super::User; +use njord::condition::{Condition, Value}; +use njord::keys::AutoIncrementPrimaryKey; +use njord::mysql; +use std::vec; + +#[test] +fn delete_row() { + insert_row(); + + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let mut conn = mysql::open(url); + + let columns = vec!["username".to_string()]; + let condition = Condition::Eq( + "username".to_string(), + Value::Literal("chasewillden2".to_string()), + ); + + match conn { + Ok(ref mut c) => { + let result = mysql::update(c, User::default()) + .set(columns) + .where_clause(condition) + .limit(4) + .offset(0) + .build(); + assert!(result.is_ok()); + } + Err(e) => { + panic!("Failed to DELETE: {:?}", e); + } + } +} + +/// Helper function to insert a row to be updated +fn insert_row() { + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let mut conn = mysql::open(url); + + let table_row: User = User { + id: AutoIncrementPrimaryKey::default(), + username: "chasewillden2".to_string(), + email: "chase.willden@example.com".to_string(), + address: "Some Random Address 1".to_string(), + }; + + match conn { + Ok(ref mut c) => { + let result = mysql::insert(c, vec![table_row]); + assert!(result.is_ok()); + } + Err(e) => { + panic!("Failed to INSERT: {:?}", e); + } + } +} diff --git a/njord_examples/mysql/src/main.rs b/njord_examples/mysql/src/main.rs index fc832b0f..370b6761 100644 --- a/njord_examples/mysql/src/main.rs +++ b/njord_examples/mysql/src/main.rs @@ -1,6 +1,7 @@ use std::fmt::Error; use crate::schema::NearEarthObject; +use njord::column::Column; use njord::keys::AutoIncrementPrimaryKey; use njord::mysql; use reqwest::header::ACCEPT; @@ -26,6 +27,29 @@ pub struct NearEarthObjectResponse { #[tokio::main] async fn main() -> Result<(), Error> { + let _ = insert().await; + let _ = select(); + + Ok(()) +} + +fn select() -> Result<(), Box> { + let url = "mysql://njord_user:njord_password@localhost:3306/njord_db"; + let mut conn = mysql::open(url).unwrap(); + + let results = mysql::select(&mut conn, vec![Column::Text("id".to_string())]) + .from(NearEarthObject::default()) + .build(); + + match results { + Ok(data) => println!("Selected: {:#?}", data.len()), + Err(err) => eprintln!("Error: {}", err), + } + + Ok(()) +} + +async fn insert() -> Result<(), Box> { let neo = get_near_earth_objects(0, 10).await; let mut near_earth_objects: Vec = Vec::new();