Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Related queries enhancement #84

Merged
merged 18 commits into from
Nov 19, 2022
48 changes: 45 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ Go to http://localhost:8000/ and try out the following queries:
description
releaseYear
filmActor {
actor {
firstName
lastName
nodes {
actor {
firstName
lastName
}
}
}
}
Expand Down Expand Up @@ -135,6 +137,46 @@ Go to http://localhost:8000/ and try out the following queries:
}
```

### Complex query with filters on relations
Find all inactive customers, include their address, and their payments with amount greater than 7 ordered by amount the second result
```graphql
{
customer(
filters: { active: { eq: 0 } }
) {
nodes {
customerId
lastName
email
address {
address
}
payment(
filters: { amount: { gt: "7" } }
orderBy: { amount: ASC }
pagination: { pages: { limit: 1, page: 1 } }
) {
nodes {
paymentId
amount
}
pages
current
pageInfo {
hasPreviousPage
hasNextPage
}
}
}
pageInfo {
hasPreviousPage
hasNextPage
endCursor
}
}
}
```

### Postgres

Setup the [sakila](https://github.com/SeaQL/seaography/blob/main/examples/postgres/sakila-schema.sql) sample database.
Expand Down
59 changes: 32 additions & 27 deletions derive/src/filter.rs
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,12 @@ pub fn filter_fn(item: syn::DataStruct, attrs: SeaOrm) -> Result<TokenStream, cr
#order_by_struct

#order_by_fn

impl seaography::EnchantedEntity for Entity {
type Entity = Entity;
type Filter = Filter;
type OrderBy = OrderBy;
}
})
}

Expand Down Expand Up @@ -121,7 +127,7 @@ pub fn order_by_fn(fields: &[IdentTypeTuple]) -> Result<TokenStream, crate::erro
let column = format_ident!("{}", ident.to_string().to_upper_camel_case());

quote! {
let stmt = if let Some(order_by) = order_by_struct.#ident {
let stmt = if let Some(order_by) = self.#ident {
match order_by {
seaography::OrderByEnum::Asc => stmt.order_by(Column::#column, sea_orm::query::Order::Asc),
seaography::OrderByEnum::Desc => stmt.order_by(Column::#column, sea_orm::query::Order::Desc),
Expand All @@ -134,13 +140,12 @@ pub fn order_by_fn(fields: &[IdentTypeTuple]) -> Result<TokenStream, crate::erro
.collect();

Ok(quote! {
pub fn order_by(stmt: sea_orm::Select<Entity>, order_by_struct: Option<OrderBy>) -> sea_orm::Select<Entity> {
use sea_orm::QueryOrder;
impl seaography::EntityOrderBy<Entity> for OrderBy {
fn order_by(&self, stmt: sea_orm::Select<Entity>) -> sea_orm::Select<Entity> {
use sea_orm::QueryOrder;

if let Some(order_by_struct) = order_by_struct {
#(#fields)*
stmt
} else {

stmt
}
}
Expand All @@ -156,40 +161,40 @@ pub fn recursive_filter_fn(fields: &[IdentTypeTuple]) -> Result<TokenStream, cra
let column_enum_name = format_ident!("{}", ident.to_string().to_upper_camel_case());

quote!{
if let Some(#column_name) = current_filter.#column_name {
if let Some(eq_value) = seaography::FilterTrait::eq(&#column_name) {
if let Some(#column_name) = &self.#column_name {
if let Some(eq_value) = seaography::FilterTrait::eq(#column_name) {
condition = condition.add(Column::#column_enum_name.eq(eq_value))
}

if let Some(ne_value) = seaography::FilterTrait::ne(&#column_name) {
if let Some(ne_value) = seaography::FilterTrait::ne(#column_name) {
condition = condition.add(Column::#column_enum_name.ne(ne_value))
}

if let Some(gt_value) = seaography::FilterTrait::gt(&#column_name) {
if let Some(gt_value) = seaography::FilterTrait::gt(#column_name) {
condition = condition.add(Column::#column_enum_name.gt(gt_value))
}

if let Some(gte_value) = seaography::FilterTrait::gte(&#column_name) {
if let Some(gte_value) = seaography::FilterTrait::gte(#column_name) {
condition = condition.add(Column::#column_enum_name.gte(gte_value))
}

if let Some(lt_value) = seaography::FilterTrait::lt(&#column_name) {
if let Some(lt_value) = seaography::FilterTrait::lt(#column_name) {
condition = condition.add(Column::#column_enum_name.lt(lt_value))
}

if let Some(lte_value) = seaography::FilterTrait::lte(&#column_name) {
if let Some(lte_value) = seaography::FilterTrait::lte(#column_name) {
condition = condition.add(Column::#column_enum_name.lte(lte_value))
}

if let Some(is_in_value) = seaography::FilterTrait::is_in(&#column_name) {
if let Some(is_in_value) = seaography::FilterTrait::is_in(#column_name) {
condition = condition.add(Column::#column_enum_name.is_in(is_in_value))
}

if let Some(is_not_in_value) = seaography::FilterTrait::is_not_in(&#column_name) {
if let Some(is_not_in_value) = seaography::FilterTrait::is_not_in(#column_name) {
condition = condition.add(Column::#column_enum_name.is_not_in(is_not_in_value))
}

if let Some(is_null_value) = seaography::FilterTrait::is_null(&#column_name) {
if let Some(is_null_value) = seaography::FilterTrait::is_null(#column_name) {
if is_null_value {
condition = condition.add(Column::#column_enum_name.is_null())
}
Expand All @@ -200,34 +205,34 @@ pub fn recursive_filter_fn(fields: &[IdentTypeTuple]) -> Result<TokenStream, cra
.collect();

Ok(quote! {
pub fn filter_recursive(root_filter: Option<Filter>) -> sea_orm::Condition {
let mut condition = sea_orm::Condition::all();
impl seaography::EntityFilter for Filter {
fn filter_condition(&self) -> sea_orm::Condition {
let mut condition = sea_orm::Condition::all();

if let Some(current_filter) = root_filter {
if let Some(or_filters) = current_filter.or {
if let Some(or_filters) = &self.or {
let or_condition = or_filters
.into_iter()
.iter()
.fold(
sea_orm::Condition::any(),
|fold_condition, filter| fold_condition.add(filter_recursive(Some(*filter)))
|fold_condition, filter| fold_condition.add(filter.filter_condition())
);
condition = condition.add(or_condition);
}

if let Some(and_filters) = current_filter.and {
if let Some(and_filters) = &self.and {
let and_condition = and_filters
.into_iter()
.iter()
.fold(
sea_orm::Condition::all(),
|fold_condition, filter| fold_condition.add(filter_recursive(Some(*filter)))
|fold_condition, filter| fold_condition.add(filter.filter_condition())
);
condition = condition.add(and_condition);
}

#(#columns_filters)*
}

condition
condition
}
}
})
}
Expand Down
Loading