Skip to content

Commit

Permalink
Implement insert test
Browse files Browse the repository at this point in the history
  • Loading branch information
chaseWillden committed Oct 15, 2024
1 parent 7e5c1ac commit cfedece
Show file tree
Hide file tree
Showing 7 changed files with 183 additions and 13 deletions.
12 changes: 6 additions & 6 deletions .github/workflows/core.yml
Original file line number Diff line number Diff line change
Expand Up @@ -65,12 +65,12 @@ 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: 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: Running Unit Tests for MySQL
run: cargo test mysql
Expand Down
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
31 changes: 31 additions & 0 deletions njord/db/test/mysql.sql
Original file line number Diff line number Diff line change
@@ -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
);
50 changes: 43 additions & 7 deletions njord/src/mysql/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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};
Expand All @@ -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<Column<'a, T>>,
) -> SelectQueryBuilder<'a, T> {
Expand All @@ -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<RefCell<&'a mut PooledConn>>,
table: Option<T>,
columns: Vec<Column<'a, T>>,
Expand All @@ -82,7 +82,7 @@ pub struct SelectQueryBuilder<'a, T: Table + Default + FromRow> {
joins: Option<Vec<Join<'a>>>,
}

impl<'a, T: Table + Default + FromRow> SelectQueryBuilder<'a, T> {
impl<'a, T: Table + Default> SelectQueryBuilder<'a, T> {
/// Creates a new `SelectQueryBuilder` instance.
///
/// # Arguments
Expand Down Expand Up @@ -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<T> = 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<T> = conn.query(final_query.as_str())?;
// Move `instance` to the `results` only after it is fully set up
results.push(instance);
}

Ok(results)
}
Expand All @@ -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()
Expand Down
27 changes: 27 additions & 0 deletions njord/tests/mysql/insert_test.rs
Original file line number Diff line number Diff line change
@@ -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: "mjovanc".to_string(),
email: "[email protected]".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);
}
}
}
51 changes: 51 additions & 0 deletions njord/tests/mysql/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
mod insert_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<usize>,
pub username: String,
pub email: String,
pub address: String,
}

#[derive(Table)]
#[table_name = "users"]
pub struct UserWithSubQuery {
pub id: AutoIncrementPrimaryKey<usize>,
pub username: String,
pub email: String,
pub address: String,
pub additional_address: String,
}

#[derive(Table)]
#[table_name = "categories"]
pub struct Category {
pub id: PrimaryKey<usize>,
pub name: String,
}

#[derive(Table)]
#[table_name = "products"]
pub struct Product {
pub id: PrimaryKey<usize>,
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,
}
24 changes: 24 additions & 0 deletions njord_examples/mysql/src/main.rs
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -26,6 +27,29 @@ pub struct NearEarthObjectResponse {

#[tokio::main]
async fn main() -> Result<(), Error> {
let _ = insert().await;
let _ = select();

Ok(())
}

fn select() -> Result<(), Box<dyn std::error::Error>> {
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<dyn std::error::Error>> {
let neo = get_near_earth_objects(0, 10).await;
let mut near_earth_objects: Vec<NearEarthObject> = Vec::new();

Expand Down

0 comments on commit cfedece

Please sign in to comment.