Skip to content

Commit

Permalink
add postgres
Browse files Browse the repository at this point in the history
  • Loading branch information
chaseWillden committed Oct 10, 2024
1 parent 5890bf5 commit 6e83537
Show file tree
Hide file tree
Showing 4 changed files with 95 additions and 33 deletions.
Binary file modified njord/db/insert.db
Binary file not shown.
112 changes: 83 additions & 29 deletions njord/src/postgres/select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,14 +38,16 @@ use crate::{
},
query::QueryBuilder,
};
use std::{collections::HashMap, sync::Arc};
use std::{cell::RefCell, collections::HashMap, rc::Rc, sync::Arc};

use log::info;
use postgres::Client;

use crate::table::Table;
use crate::util::{Join, JoinType};

use super::error::PostgresError;

/// Constructs a new SELECT query builder.
///
/// # Arguments
Expand All @@ -57,7 +59,7 @@ use crate::util::{Join, JoinType};
///
/// A `SelectQueryBuilder` instance.
pub fn select<'a, T: Table + Default>(
conn: &'a Client,
conn: &'a mut Client,
columns: Vec<Column<'a, T>>,
) -> SelectQueryBuilder<'a, T> {
SelectQueryBuilder::new(conn, columns)
Expand All @@ -66,7 +68,7 @@ pub fn select<'a, T: Table + Default>(
/// A builder for constructing SELECT queries.
#[derive(Clone)]
pub struct SelectQueryBuilder<'a, T: Table + Default> {
conn: &'a Client,
conn: Rc<RefCell<&'a mut Client>>,
table: Option<T>,
columns: Vec<Column<'a, T>>,
where_condition: Option<Condition<'a>>,
Expand All @@ -88,9 +90,9 @@ impl<'a, T: Table + Default> SelectQueryBuilder<'a, T> {
///
/// * `conn` - A `Client` to the Postgres database.
/// * `columns` - A vector of strings representing the columns to be selected.
pub fn new(conn: &'a Client, columns: Vec<Column<'a, T>>) -> Self {
pub fn new(conn: &'a mut Client, columns: Vec<Column<'a, T>>) -> Self {
SelectQueryBuilder {
conn,
conn: Rc::new(RefCell::new(conn)),
table: None,
columns,
where_condition: None,
Expand Down Expand Up @@ -359,42 +361,94 @@ impl<'a, T: Table + Default> SelectQueryBuilder<'a, T> {
///
/// A `Result` containing a vector of selected table rows if successful,
/// or a `ruPostgres::Error` if an error occurs during the execution.
pub fn build(self) -> Result<Vec<T>> {
pub fn build(self) -> Result<Vec<T>, PostgresError> {
let final_query = self.build_query();

info!("{}", final_query);
println!("{}", final_query);

// Prepare SQL statement
let mut stmt = self.conn.prepare(final_query.as_str())?;
let mut conn = self.conn.borrow_mut();
let results = conn.query(final_query.as_str(), &[])?;

// Rest of the query execution remains unchanged
let iter = stmt.query_map((), |row| {
let mut instance = T::default();
let columns = instance.get_column_fields();
let instance = T::default();
let columns = instance.get_columns();

println!("Columns: {:?}", columns);

for (index, column) in columns.iter().enumerate() {
let value = row.get::<usize, Value>(index)?;
// Create a HashMap for quicker column type lookups
let column_map: HashMap<&str, &str> = columns
.iter()
.map(|(name, typ)| (name.as_str(), typ.as_str()))
.collect();

let string_value = match value {
Value::Integer(val) => val.to_string(),
Value::Null => String::new(),
Value::Real(val) => val.to_string(),
Value::Text(val) => val.to_string(),
Value::Blob(val) => String::from_utf8_lossy(&val).to_string(),
};
let mut instances: Vec<T> = Vec::new();
// Get index
for row in results {
let mut instance = T::default();

instance.set_column_value(column, &string_value);
for (index, column) in row.columns().iter().enumerate() {
let column_name = column.name();
if let Some(&column_type) = column_map.get(column_name) {
match column_type {
"INTEGER" => {
let value: i32 = row.get(index);
instance.set_column_value(column_name, &value.to_string());
}
"REAL" => {
let value: f32 = row.get(index);
instance.set_column_value(column_name, &value.to_string());
}
"TEXT" => {
let value: &str = row.get(index);
instance.set_column_value(column_name, value);
}
"BLOB" => {
let value: Vec<u8> = row.get(index);
instance.set_column_value(column_name, &format!("{:?}", value));
}
"TEXT NULL" => {
let value: Option<&str> = row.get(index);
match value {
Some(v) => instance.set_column_value(column_name, v),
None => instance.set_column_value(column_name, "NULL"),
}
}
"INTEGER NULL" => {
let value: Option<i32> = row.get(index);
match value {
Some(v) => instance.set_column_value(column_name, &v.to_string()),
None => instance.set_column_value(column_name, "NULL"),
}
}
"REAL NULL" => {
let value: Option<f32> = row.get(index);
match value {
Some(v) => instance.set_column_value(column_name, &v.to_string()),
None => instance.set_column_value(column_name, "NULL"),
}
}
"BLOB NULL" => {
let value: Option<Vec<u8>> = row.get(index);
match value {
Some(v) => {
instance.set_column_value(column_name, &format!("{:?}", v))
}
None => instance.set_column_value(column_name, "NULL"),
}
}
_ => {
let value: &str = row.get(index);
instance.set_column_value(column_name, value);
}
}
}
}

Ok(instance)
})?;

let result: Result<Vec<T>> = iter
.map(|row_result| row_result.and_then(|row| Ok(row)))
.collect::<Result<Vec<T>>>();
instances.push(instance);
}

result.map_err(|err| err.into())
Ok(instances)
}
}

Expand Down
4 changes: 2 additions & 2 deletions njord_derive/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ pub fn table_derive(input: TokenStream) -> TokenStream {
let mut columns = std::collections::HashMap::new();
#(
let column_type = match stringify!(#field_types) {
"i64" | "i32" | "i16" | "i8" | "u64" | "u32" | "u16" | "u8" | "usize" => "INTEGER",
"i64" | "i32" | "i16" | "i8" | "u64" | "u32" | "u16" | "u8" | "usize" | "AutoIncrementPrimaryKey < usize >" => "INTEGER",
"String" => "TEXT",
"f64" | "f32" => "REAL",
"Vec<u8>" => "BLOB",
Expand All @@ -130,7 +130,7 @@ pub fn table_derive(input: TokenStream) -> TokenStream {
"Option<Vec<u8>>" => "BLOB NULL",
"bool" => "TEXT",
_ => {
eprintln!("Warning: Unknown data type for column '{}'", stringify!(#field_names));
eprintln!("Warning: Unknown data type for column '{}' {}", stringify!(#field_names), stringify!(#field_types));
"UNKNOWN_TYPE"
}
};
Expand Down
12 changes: 10 additions & 2 deletions njord_examples/postgres/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
use crate::schema::NearEarthObject;
use njord::{keys::AutoIncrementPrimaryKey, postgres};
use njord::{column::Column, keys::AutoIncrementPrimaryKey, postgres};
use reqwest::header::ACCEPT;
use serde::Deserialize;
use serde_json::Value;
Expand Down Expand Up @@ -35,6 +35,14 @@ async fn main() -> Result<(), Box<dyn Error>> {
postgres::open("postgresql://myuser:mypassword@localhost:5432/mydatabase").unwrap();

postgres::insert(&mut conn, near_earth_objects).unwrap();

let results = postgres::select(&mut conn, vec![Column::Text("id".to_string())])
.from(NearEarthObject::default())
.build();

for r in results.unwrap() {
println!("{:#?}", r);
}
})
.join()
{
Expand Down Expand Up @@ -65,7 +73,7 @@ async fn get_and_process_neos() -> Result<Vec<NearEarthObject>, Box<dyn Error>>
is_sentry_object: false, // Set this field as needed
};

println!("{:#?}", near_earth_obj);
// println!("{:#?}", near_earth_obj);
near_earth_objects.push(near_earth_obj);
}

Expand Down

0 comments on commit 6e83537

Please sign in to comment.