Skip to content
Merged
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
12 changes: 6 additions & 6 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,11 +33,11 @@ tokio-postgres = { workspace = true, optional = true }
tiberius = { workspace = true, optional = true }

[workspace.dependencies]
canyon_crud = { version = "0.4.0", path = "canyon_crud" }
canyon_connection = { version = "0.4.0", path = "canyon_connection" }
canyon_entities = { version = "0.4.0", path = "canyon_entities" }
canyon_migrations = { version = "0.4.0", path = "canyon_migrations"}
canyon_macros = { version = "0.4.0", path = "canyon_macros" }
canyon_crud = { version = "0.4.1", path = "canyon_crud" }
canyon_connection = { version = "0.4.1", path = "canyon_connection" }
canyon_entities = { version = "0.4.1", path = "canyon_entities" }
canyon_migrations = { version = "0.4.1", path = "canyon_migrations"}
canyon_macros = { version = "0.4.1", path = "canyon_macros" }

tokio = { version = "1.27.0", features = ["full"] }
tokio-util = { version = "0.7.4", features = ["compat"] }
Expand All @@ -61,7 +61,7 @@ quote = "1.0.9"
proc-macro2 = "1.0.27"

[workspace.package]
version = "0.4.0"
version = "0.4.1"
edition = "2021"
authors = ["Alex Vergara<[email protected]>, Gonzalo Busto Musi<[email protected]>"]
documentation = "https://zerodaycode.github.io/canyon-book/"
Expand Down
38 changes: 30 additions & 8 deletions canyon_crud/src/query_elements/operators.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
pub trait Operator {
fn as_str(&self) -> &'static str;
fn as_str(&self, placeholder_counter: usize) -> String;
}

/// Enumerated type for represent the comparison operations
Expand All @@ -18,15 +18,37 @@ pub enum Comp {
/// Operator "=<" less or equals than value
LtEq,
}

impl Operator for Comp {
fn as_str(&self) -> &'static str {
fn as_str(&self, placeholder_counter: usize) -> String {
match *self {
Self::Eq => format!(" = ${placeholder_counter}"),
Self::Neq => format!(" <> ${placeholder_counter}"),
Self::Gt => format!(" > ${placeholder_counter}"),
Self::GtEq => format!(" >= ${placeholder_counter}"),
Self::Lt => format!(" < ${placeholder_counter}"),
Self::LtEq => format!(" <= ${placeholder_counter}"),
}
}
}

pub enum Like {
/// Operator "LIKE" as '%pattern%'
Full,
/// Operator "LIKE" as '%pattern'
Left,
/// Operator "LIKE" as 'pattern%'
Right,
}

impl Operator for Like {
fn as_str(&self, placeholder_counter: usize) -> String {
match *self {
Self::Eq => " = ",
Self::Neq => " <> ",
Self::Gt => " > ",
Self::GtEq => " >= ",
Self::Lt => " < ",
Self::LtEq => " <= ",
Like::Full => {
format!(" LIKE CONCAT('%', CAST(${placeholder_counter} AS VARCHAR) ,'%')")
}
Like::Left => format!(" LIKE CONCAT('%', CAST(${placeholder_counter} AS VARCHAR))"),
Like::Right => format!(" LIKE CONCAT(CAST(${placeholder_counter} AS VARCHAR) ,'%')"),
}
}
}
25 changes: 6 additions & 19 deletions canyon_crud/src/query_elements/query_builder.rs
Original file line number Diff line number Diff line change
Expand Up @@ -180,11 +180,8 @@ where
pub fn r#where<Z: FieldValueIdentifier<'a, T>>(&mut self, r#where: Z, op: impl Operator) {
let (column_name, value) = r#where.value();

let where_ = String::from(" WHERE ")
+ column_name
+ op.as_str()
+ "$"
+ &(self.query.params.len() + 1).to_string();
let where_ =
String::from(" WHERE ") + column_name + &op.as_str(self.query.params.len() + 1);

self.query.sql.push_str(&where_);
self.query.params.push(value);
Expand All @@ -193,12 +190,7 @@ where
pub fn and<Z: FieldValueIdentifier<'a, T>>(&mut self, r#and: Z, op: impl Operator) {
let (column_name, value) = r#and.value();

let and_ = String::from(" AND ")
+ column_name
+ op.as_str()
+ "$"
+ &(self.query.params.len() + 1).to_string()
+ " ";
let and_ = String::from(" AND ") + column_name + &op.as_str(self.query.params.len() + 1);

self.query.sql.push_str(&and_);
self.query.params.push(value);
Expand All @@ -207,12 +199,7 @@ where
pub fn or<Z: FieldValueIdentifier<'a, T>>(&mut self, r#and: Z, op: impl Operator) {
let (column_name, value) = r#and.value();

let and_ = String::from(" OR ")
+ column_name
+ op.as_str()
+ "$"
+ &(self.query.params.len() + 1).to_string()
+ " ";
let and_ = String::from(" OR ") + column_name + &op.as_str(self.query.params.len() + 1);

self.query.sql.push_str(&and_);
self.query.params.push(value);
Expand Down Expand Up @@ -246,7 +233,7 @@ where
self.query.params.push(qp)
});

self.query.sql.push_str(") ");
self.query.sql.push_str(")");
}

fn or_values_in<Z, Q>(&mut self, r#or: Z, values: &'a [Q])
Expand Down Expand Up @@ -277,7 +264,7 @@ where
self.query.params.push(qp)
});

self.query.sql.push_str(") ");
self.query.sql.push_str(")");
}

#[inline]
Expand Down
96 changes: 93 additions & 3 deletions tests/crud/querybuilder_operations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@
///
use canyon_sql::{
crud::CrudOperations,
query::{operators::Comp, ops::QueryBuilder},
query::{operators::Comp, operators::Like, ops::QueryBuilder},
};

#[cfg(feature = "mssql")]
Expand Down Expand Up @@ -34,7 +34,7 @@ fn test_generated_sql_by_the_select_querybuilder() {
// generated SQL by the SelectQueryBuilder<T> is the spected
assert_eq!(
select_with_joins.read_sql(),
"SELECT * FROM league INNER JOIN tournament ON league.id = tournament.league_id LEFT JOIN team ON tournament.id = player.tournament_id WHERE id > $1 AND name = $2 AND name IN ($2, $3) "
"SELECT * FROM league INNER JOIN tournament ON league.id = tournament.league_id LEFT JOIN team ON tournament.id = player.tournament_id WHERE id > $1 AND name = $2 AND name IN ($2, $3)"
)
}

Expand All @@ -59,6 +59,96 @@ fn test_crud_find_with_querybuilder() {
assert_eq!(league_idx_0.region, "KOREA");
}

/// Builds a new SQL statement for retrieves entities of the `T` type, filtered
/// with the parameters that modifies the base SQL to SELECT * FROM <entity>
#[cfg(feature = "postgres")]
#[canyon_sql::macros::canyon_tokio_test]
fn test_crud_find_with_querybuilder_and_fulllike() {
// Find all the leagues with "LC" in their name
let mut filtered_leagues_result = League::select_query();
filtered_leagues_result.r#where(LeagueFieldValue::name(&"LC"), Like::Full);

assert_eq!(
filtered_leagues_result.read_sql(),
"SELECT * FROM league WHERE name LIKE CONCAT('%', CAST($1 AS VARCHAR) ,'%')"
)
}

/// Builds a new SQL statement for retrieves entities of the `T` type, filtered
/// with the parameters that modifies the base SQL to SELECT * FROM <entity>
#[cfg(feature = "mssql")]
#[canyon_sql::macros::canyon_tokio_test]
fn test_crud_find_with_querybuilder_and_fulllike_datasource() {
// Find all the leagues with "LC" in their name
let mut filtered_leagues_result = League::select_query_datasource(SQL_SERVER_DS);
filtered_leagues_result.r#where(LeagueFieldValue::name(&"LC"), Like::Full);

assert_eq!(
filtered_leagues_result.read_sql(),
"SELECT * FROM league WHERE name LIKE CONCAT('%', CAST($1 AS VARCHAR) ,'%')"
)
}

/// Builds a new SQL statement for retrieves entities of the `T` type, filtered
/// with the parameters that modifies the base SQL to SELECT * FROM <entity>
#[cfg(feature = "postgres")]
#[canyon_sql::macros::canyon_tokio_test]
fn test_crud_find_with_querybuilder_and_leftlike() {
// Find all the leagues whose name ends with "CK"
let mut filtered_leagues_result = League::select_query();
filtered_leagues_result.r#where(LeagueFieldValue::name(&"CK"), Like::Left);

assert_eq!(
filtered_leagues_result.read_sql(),
"SELECT * FROM league WHERE name LIKE CONCAT('%', CAST($1 AS VARCHAR))"
)
}

/// Builds a new SQL statement for retrieves entities of the `T` type, filtered
/// with the parameters that modifies the base SQL to SELECT * FROM <entity>
#[cfg(feature = "mssql")]
#[canyon_sql::macros::canyon_tokio_test]
fn test_crud_find_with_querybuilder_and_leftlike_datasource() {
// Find all the leagues whose name ends with "CK"
let mut filtered_leagues_result = League::select_query();
filtered_leagues_result.r#where(LeagueFieldValue::name(&"CK"), Like::Left);

assert_eq!(
filtered_leagues_result.read_sql(),
"SELECT * FROM league WHERE name LIKE CONCAT('%', CAST($1 AS VARCHAR))"
)
}

/// Builds a new SQL statement for retrieves entities of the `T` type, filtered
/// with the parameters that modifies the base SQL to SELECT * FROM <entity>
#[cfg(feature = "postgres")]
#[canyon_sql::macros::canyon_tokio_test]
fn test_crud_find_with_querybuilder_and_rightlike() {
// Find all the leagues whose name starts with "LC"
let mut filtered_leagues_result = League::select_query();
filtered_leagues_result.r#where(LeagueFieldValue::name(&"LC"), Like::Right);

assert_eq!(
filtered_leagues_result.read_sql(),
"SELECT * FROM league WHERE name LIKE CONCAT(CAST($1 AS VARCHAR) ,'%')"
)
}

/// Builds a new SQL statement for retrieves entities of the `T` type, filtered
/// with the parameters that modifies the base SQL to SELECT * FROM <entity>
#[cfg(feature = "mssql")]
#[canyon_sql::macros::canyon_tokio_test]
fn test_crud_find_with_querybuilder_and_rightlike_datasource() {
// Find all the leagues whose name starts with "LC"
let mut filtered_leagues_result = League::select_query_datasource(SQL_SERVER_DS);
filtered_leagues_result.r#where(LeagueFieldValue::name(&"LC"), Like::Right);

assert_eq!(
filtered_leagues_result.read_sql(),
"SELECT * FROM league WHERE name LIKE CONCAT(CAST($1 AS VARCHAR) ,'%')"
)
}

/// Same than the above but with the specified datasource
#[cfg(feature = "mssql")]
#[canyon_sql::macros::canyon_tokio_test]
Expand Down Expand Up @@ -239,7 +329,7 @@ fn test_or_clause_with_in_constraint() {

assert_eq!(
l.read_sql(),
"SELECT * FROM league WHERE name = $1 OR id IN ($1, $2, $3) "
"SELECT * FROM league WHERE name = $1 OR id IN ($1, $2, $3)"
)
}

Expand Down