Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ license = "MIT OR Apache-2.0"
members = [".", "sqlb-macros"]

[dependencies]
sqlx = { version = "0.7", features = [ "runtime-tokio-rustls", "postgres", "time", "uuid" ] }
sqlx = { version = "0.8.0", features = [ "runtime-tokio-rustls", "postgres", "time", "uuid" ] }
sqlb-macros = { version="0.4.0", path = "sqlb-macros" }
async-trait = "0.1"
time = "0.3.20"
Expand All @@ -33,9 +33,9 @@ rust_decimal = { version = "1.34", optional = true }
default = []
chrono-support = ["chrono"]
json = ["serde_json"]
decimal = ["rust_decimal", "sqlx:rust_decimal"]
decimal = ["rust_decimal"]

[dev-dependencies]
anyhow = "1"
tokio = { version = "1", features = ["full"] }
serial_test = "2"
serial_test = "3.1.1"
6 changes: 6 additions & 0 deletions sqlb-macros/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,6 +77,12 @@ pub fn derives_fields(input: TokenStream) -> TokenStream {
#props_all_names,
)*]
}

fn field_names_prefixed(prefix: &str) -> Vec<String> {
vec![#(
format!("{}{}", prefix, #props_all_names),
)*]
}
}
};

Expand Down
14 changes: 3 additions & 11 deletions src/core.rs
Original file line number Diff line number Diff line change
@@ -1,18 +1,7 @@
use async_trait::async_trait;

pub use crate::delete::delete;
pub use crate::delete::delete_all;
pub use crate::delete::DeleteSqlBuilder;
pub use crate::insert::insert;
pub use crate::insert::InsertSqlBuilder;
pub use crate::select::select;
pub use crate::select::SelectSqlBuilder;
pub use crate::update::update;
pub use crate::update::update_all;
pub use crate::update::UpdateSqlBuilder;
use crate::utils::x_column_name;
pub use crate::val::SqlxBindable;
pub use sqlb_macros::Fields;
use sqlx::Executor;
use sqlx::FromRow;
use sqlx::Postgres;
Expand Down Expand Up @@ -53,6 +42,9 @@ pub trait HasFields {

/// Return the array of all field names this struct has.
fn field_names() -> &'static [&'static str];

/// Return the array of all field names this struct has.
fn field_names_prefixed(prefix: &str) -> Vec<String>;
}

// region: Common Types
Expand Down
26 changes: 22 additions & 4 deletions src/sqlx_exec.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
////////////////////////////////////
// sqlx-exec - module for the sqlx query executor
////
////////////////////////////////////

use crate::SqlBuilder;
use sqlx::{postgres::PgArguments, Execute, Executor, FromRow, Postgres};
Expand All @@ -22,7 +22,13 @@ where
}

// create the QueryAs
let query = sqlx::query_as_with::<sqlx::Postgres, D, PgArguments>(&sql, query.take_arguments().unwrap());
let arguments = query.take_arguments().unwrap();
let query;
if let Some(arguments) = arguments {
query = sqlx::query_as_with::<sqlx::Postgres, D, PgArguments>(&sql, arguments);
} else {
query = sqlx::query_as::<sqlx::Postgres, D>(&sql);
}

// exec and return
let r = query.fetch_one(db_pool).await?;
Expand All @@ -46,7 +52,13 @@ where
}

// create the QueryAs
let query = sqlx::query_as_with::<sqlx::Postgres, D, PgArguments>(&sql, query.take_arguments().unwrap());
let arguments = query.take_arguments().unwrap();
let query;
if let Some(arguments) = arguments {
query = sqlx::query_as_with::<sqlx::Postgres, D, PgArguments>(&sql, arguments);
} else {
query = sqlx::query_as::<sqlx::Postgres, D>(&sql);
}

// exec and return
let r = query.fetch_optional(db_pool).await?;
Expand All @@ -70,7 +82,13 @@ where
}

// create the QueryAs
let query = sqlx::query_as_with::<sqlx::Postgres, D, PgArguments>(&sql, query.take_arguments().unwrap());
let arguments = query.take_arguments().unwrap();
let query;
if let Some(arguments) = arguments {
query = sqlx::query_as_with::<sqlx::Postgres, D, PgArguments>(&sql, arguments);
} else {
query = sqlx::query_as::<sqlx::Postgres, D>(&sql);
}

// exec and return
let r = query.fetch_all(db_pool).await?;
Expand Down
3 changes: 1 addition & 2 deletions src/update.rs
Original file line number Diff line number Diff line change
Expand Up @@ -124,8 +124,7 @@ impl<'a> SqlBuilder<'a> for UpdateSqlBuilder<'a> {
let fields = &self.data;
let sql_set = fields
.iter()
.enumerate()
.map(|(_, f)| {
.map(|f| {
let mut part = format!("{} = ", x_column_name(&f.name));
match f.value.raw() {
None => {
Expand Down
108 changes: 55 additions & 53 deletions src/val.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,14 @@ use time::OffsetDateTime;
use uuid::Uuid;

pub trait SqlxBindable: std::fmt::Debug {
fn bind_query<'q>(
&'q self,
query: sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments>,
) -> sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments>;

fn raw(&self) -> Option<&str> {
None
}
fn bind_query<'q>(
&'q self,
query: sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments>,
) -> sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments>;

fn raw(&self) -> Option<&str> {
None
}
}

#[macro_export]
Expand Down Expand Up @@ -65,17 +65,17 @@ bindable_to_string!(String, str);

impl<T> SqlxBindable for Option<T>
where
T: SqlxBindable + Clone + Send,
T: for<'r> sqlx::Encode<'r, sqlx::Postgres>,
T: sqlx::Type<sqlx::Postgres>,
T: SqlxBindable + Clone + Send,
T: for<'r> sqlx::Encode<'r, sqlx::Postgres>,
T: sqlx::Type<sqlx::Postgres>,
{
fn bind_query<'q>(
&'q self,
query: sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments>,
) -> sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments> {
let query = query.bind(self.clone());
query
}
fn bind_query<'q>(
&'q self,
query: sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments>,
) -> sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments> {
let query = query.bind(self.clone());
query
}
}

// Bind the boolean
Expand All @@ -86,14 +86,16 @@ bindable!(i8, i16, i32, i64, f32, f64);

bindable!(Uuid, OffsetDateTime);

bindable!(Vec<String>, Vec<i64>);

// region: --- Raw Value

// region: --- chrono support
#[cfg(feature = "chrono-support")]
mod chrono_support {
use chrono::{NaiveDateTime, NaiveDate, NaiveTime, DateTime, Utc};
use chrono::{DateTime, NaiveDate, NaiveDateTime, NaiveTime, Utc};

bindable!(NaiveDateTime, NaiveDate, NaiveTime, DateTime<Utc>);
bindable!(NaiveDateTime, NaiveDate, NaiveTime, DateTime<Utc>);
}
// endregion: --- chrono support

Expand All @@ -102,7 +104,7 @@ mod chrono_support {
mod json {
use serde_json::Value;

bindable!(Value);
bindable!(Value);
}
// endregion: --- json support

Expand All @@ -111,48 +113,48 @@ mod json {
mod decimal {
use rust_decimal::Decimal;

bindable!(Decimal);
bindable!(Decimal);
}
// endregion: --- decimal support

#[derive(Debug)]
pub struct Raw(pub &'static str);

impl SqlxBindable for Raw {
// just return the query given, since no binding should be taken place
fn bind_query<'q>(
&self,
query: sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments>,
) -> sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments> {
query
}

fn raw(&self) -> Option<&str> {
Some(self.0)
}
// just return the query given, since no binding should be taken place
fn bind_query<'q>(
&self,
query: sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments>,
) -> sqlx::query::Query<'q, sqlx::Postgres, sqlx::postgres::PgArguments> {
query
}

fn raw(&self) -> Option<&str> {
Some(self.0)
}
}
// endregion: --- Raw Value

#[cfg(test)]
mod tests {
use crate::Field;

#[test]
fn field_from_str() {
let field = Field::from(("name1", "v2"));
assert_eq!("name1", field.name);

let field: Field = ("name1", "v2").into();
assert_eq!("name1", field.name);
}

#[test]
fn field_from_string() {
let field = Field::from(("name1", "v1"));
assert_eq!("name1", field.name);

let v2 = &"v2".to_string();
let field: Field = ("name2", v2).into();
assert_eq!("name2", field.name);
}
use crate::Field;

#[test]
fn field_from_str() {
let field = Field::from(("name1", "v2"));
assert_eq!("name1", field.name);

let field: Field = ("name1", "v2").into();
assert_eq!("name1", field.name);
}

#[test]
fn field_from_string() {
let field = Field::from(("name1", "v1"));
assert_eq!("name1", field.name);

let v2 = &"v2".to_string();
let field: Field = ("name2", v2).into();
assert_eq!("name2", field.name);
}
}
2 changes: 1 addition & 1 deletion tests/test_sb_select.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ async fn sb_select_ok_limit_offset() -> Result<(), Box<dyn Error>> {

// -- Check
assert_eq!(todos.len(), 3, "number of todos");
let todo_02 = todos.get(0).unwrap();
let todo_02 = todos.first().unwrap();
assert_eq!(todo_02.title, "sb_select_ok_limit_offset-02");

// -- Clean
Expand Down
6 changes: 5 additions & 1 deletion tests/utils/mod.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#![allow(unused)]

use std::env;

use anyhow::Result;
use sqlb::{Field, HasFields};
use sqlb_macros::Fields;
Expand Down Expand Up @@ -105,9 +107,11 @@ pub async fn util_fetch_todo(db_pool: &Pool<Postgres>, id: i64) -> Result<Todo>

// region: Test Utils
pub async fn init_db() -> Result<Pool<Postgres>, sqlx::Error> {
let database_url: String = env::var("DATABASE_URL").ok()
.unwrap_or("postgres://postgres:welcome@localhost/postgres".to_string());
let pool = PgPoolOptions::new()
.max_connections(5)
.connect("postgres://postgres:welcome@localhost/postgres")
.connect(&database_url)
.await?;

sqlx::query("DROP TABLE IF EXISTS todo").execute(&pool).await?;
Expand Down