Skip to content

Commit

Permalink
Update the Join to be Arc, clean up query, hydrate select_join.db
Browse files Browse the repository at this point in the history
  • Loading branch information
chaseWillden committed Oct 7, 2024
1 parent 974d554 commit 00f3f0f
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 50 deletions.
Binary file added njord/db/select_join.db
Binary file not shown.
5 changes: 4 additions & 1 deletion njord/src/condition.rs
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,10 @@ impl Condition {
pub fn build(&self) -> String {
match self {
Condition::Eq(column, value) => {
if Condition::is_numeric(value) {
// If contains a dot, assume it's a table.column
if column.contains('.') {
format!("{} = {}", column, value)
} else if Condition::is_numeric(value) {
format!("{} = {}", column, value)
} else {
format!("{} = '{}'", column, value)
Expand Down
38 changes: 26 additions & 12 deletions njord/src/sqlite/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,8 +35,8 @@ use crate::{
generate_order_by_str, generate_where_condition_str,
},
};
use std::collections::HashMap;
use rusqlite::{Connection, Result};
use std::{collections::HashMap, sync::Arc};

use log::info;
use rusqlite::types::Value;
Expand Down Expand Up @@ -76,7 +76,7 @@ pub struct SelectQueryBuilder<'a, T: Table + Default> {
having_condition: Option<Condition>,
except_clauses: Option<Vec<SelectQueryBuilder<'a, T>>>,
union_clauses: Option<Vec<SelectQueryBuilder<'a, T>>>,
joins: Option<Vec<Join<T>>>,
joins: Option<Vec<Join>>,
}

impl<'a, T: Table + Default> SelectQueryBuilder<'a, T> {
Expand Down Expand Up @@ -252,7 +252,12 @@ impl<'a, T: Table + Default> SelectQueryBuilder<'a, T> {
/// # Returns
///
/// Returns the modified `SelectQueryBuilder` instance with the new JOIN clause added.
pub fn join(mut self, join_type: JoinType, table: T, on_condition: Condition) -> Self {
pub fn join(
mut self,
join_type: JoinType,
table: Arc<dyn Table>,
on_condition: Condition,
) -> Self {
match self.joins {
Some(ref mut joins) => joins.push(Join::new(join_type, table, on_condition)),
None => self.joins = Some(vec![Join::new(join_type, table, on_condition)]),
Expand All @@ -277,15 +282,24 @@ impl<'a, T: Table + Default> SelectQueryBuilder<'a, T> {

// Generate JOIN clauses, if any
let join_clauses: Vec<String> = match &self.joins {
Some(joins) => joins.iter().map(|join| {
let join_type_str = match join.join_type {
JoinType::Inner => "INNER JOIN",
JoinType::Left => "LEFT JOIN",
JoinType::Right => "RIGHT JOIN",
JoinType::Full => "FULL OUTER JOIN",
};
format!("{} {} ON {}", join_type_str, join.table.get_name(), generate_where_condition_str(Some(join.on_condition.clone())))
}).collect(),
Some(joins) => joins
.iter()
.map(|join| {
let join_type_str = match join.join_type {
JoinType::Inner => "INNER JOIN",
JoinType::Left => "LEFT JOIN",
JoinType::Right => "RIGHT JOIN",
JoinType::Full => "FULL OUTER JOIN",
};
format!(
"{} {} ON {}",
join_type_str,
join.table.get_name(),
generate_where_condition_str(Some(join.on_condition.clone()))
.replace("WHERE", "")
)
})
.collect(),
None => Vec::new(),
};

Expand Down
10 changes: 6 additions & 4 deletions njord/src/util.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,8 @@
//! OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
//! OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
use std::sync::Arc;

use crate::condition::Condition;
use crate::table::Table;

Expand All @@ -39,14 +41,14 @@ pub enum JoinType {
}

#[derive(Clone)]
pub struct Join<T: Table + Default> {
pub struct Join {
pub join_type: JoinType,
pub table: T,
pub table: Arc<dyn Table>,
pub on_condition: Condition,
}

impl<T: Table + Default> Join<T> {
pub fn new(join_type: JoinType, table: T, on_condition: Condition) -> Self {
impl Join {
pub fn new(join_type: JoinType, table: Arc<dyn Table>, on_condition: Condition) -> Self {
Join {
join_type,
table,
Expand Down
82 changes: 49 additions & 33 deletions njord/tests/sqlite/select_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,12 @@ use njord::column::Column;
use njord::condition::Condition;
use njord::keys::{AutoIncrementPrimaryKey, PrimaryKey};
use njord::sqlite;
use njord::table::Table;
use njord::util::JoinType;
use njord_derive::Table;
use std::collections::HashMap;
use std::path::Path;
use std::sync::Arc;

#[derive(Table, Clone)]
#[table_name = "users"]
Expand All @@ -24,6 +28,14 @@ pub struct UserWithSubQuery {
additional_address: String,
}

#[derive(Table)]
#[table_name = "users"]
pub struct UsersWithJoin {
username: String,
price: f64,
name: String,
}

#[derive(Table)]
#[table_name = "categories"]
pub struct Category {
Expand Down Expand Up @@ -535,36 +547,40 @@ fn select_in() {
};
}

// #[test]
// fn select_join() {
// let db_relative_path = "./db/select_join.db";
// let db_path = Path::new(&db_relative_path);
// let conn = sqlite::open(db_path);
//
// // Assume we have pre-inserted some data into the users and products tables
// let columns = vec![
// "users.username".to_string(),
// "products.name".to_string(),
// "products.price".to_string(),
// ];
//
// // Assuming a hypothetical join condition: users.id = products.user_id
// let join_condition = Condition::Eq("users.id".to_string(), "products.user_id".to_string());
// match conn {
// Ok(c) => {
// let result = sqlite::select(&c, columns)
// .from(User::default())
// .join(JoinType::Inner, Category::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_join() {
let db_relative_path = "./db/select_join.db";
let db_path = Path::new(&db_relative_path);
let conn = sqlite::open(db_path);

// 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(), "products.user_id".to_string());
match conn {
Ok(c) => {
let result = sqlite::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),
}
}

0 comments on commit 00f3f0f

Please sign in to comment.