Skip to main content
Version: 0.3.0

Macros documentation

Filter derive

The Filter derive macro is attached on Sea ORM Models to generate structures and functions that are used by the QueryRoot to provide query functionality on Entities.

Attributes

#[sea_orm(table_name = "film")]
  • table_name: used to supply the macro with the entity name that will be used for the structure names

Input

#[derive(
Clone,
Debug,
PartialEq,
DeriveModel,
DeriveActiveModel,
async_graphql::SimpleObject, // Required by Async GraphQL
seaography::macros::Filter, // The macro
)]
#[sea_orm(table_name = "film")]
#[graphql(complex)] // Used by Relations derive
#[graphql(name = "Film")] // Required by Async GraphQL
pub struct Model {
pub film_id: u16,
pub title: String,
pub rating: Option<Rating>,
pub last_update: DateTimeUtc,
}

Output

Used to describe complex SQL filters

#[derive(Debug, async_graphql::InputObject)]
#[graphql(name = "FilmFilter")]
pub struct Filter {
pub or: Option<Vec<Box<Filter>>>,
pub and: Option<Vec<Box<Filter>>>,
pub film_id: Option<seaography::TypeFilter<u16>>,
pub title: Option<seaography::TypeFilter<String>>,
// See Enumeration derive
pub rating: Option<crate::entities::sea_orm_active_enums::RatingEnumFilter>,
pub last_update: Option<seaography::TypeFilter<DateTimeUtc>>,
}

Used to receive a Filter struct and convect it into sea_orm::Condition that is applied on sea_orm query statement

pub fn filter_recursive(root_filter: Option<Filter>) -> sea_orm::Condition {
...
}

Used to describe order by

#[derive(Debug, async_graphql::InputObject)]
#[graphql(name = "FilmOrderBy")]
pub struct OrderBy {
pub film_id: Option<seaography::OrderByEnum>,
pub title: Option<seaography::OrderByEnum>,
pub rating: Option<seaography::OrderByEnum>,
pub last_update: Option<seaography::OrderByEnum>,
}

Used to receive a query statement and OrderBy struct and update the statement with desired ordering.

pub fn order_by(stmt: sea_orm::Select<Entity>, order_by_struct: Option<OrderBy>) -> sea_orm::Select<Entity> {
...
}

RelationsCompact derive

The RelationsCompact derive macro is attached on Sea ORM Relation enum to generate structures and functions that are used by the Entity to query related Entities. This derive is applied on Entities in compact form.

Input

#[derive(
Copy,
Clone,
Debug,
EnumIter,
DeriveRelation,
seaography::macros::RelationsCompact,
)]
pub enum Relation {
#[sea_orm(
belongs_to = "super::employees::Entity",
from = "Column::SupportRepId",
to = "super::employees::Column::EmployeeId",
on_update = "NoAction",
on_delete = "NoAction"
)]
Employees,
#[sea_orm(has_many = "super::invoices::Entity")]
Invoices,
}

Output

The following are implemented for Entity Model:

// Requires graphql complex flag enabled on Model
#[async_graphql::ComplexObject]
impl Model {
pub fn employees<'a>(
&self,
ctx: &async_graphql::Context<'a>,
) -> Option<#return_type>
{
...
}

pub fn invoices<'a>(
&self,
ctx: &async_graphql::Context<'a>,
) -> Option<#return_type>
{
// Uses context.dataloader.load::<InvoicesFK>(...) to dispatch query
...
}
}

For every enum variant the following things are generated:

// Used for the context loader
#[derive(Clone, Debug)]
pub struct EmployeesFK(...);

// Implement load fn for Foreign key
#[async_trait::async_trait]
impl async_graphql::dataloader::Loader<EmployeesFK> for crate::OrmDataloader {
type Value = #return_type;
type Error = std::sync::Arc<sea_orm::error::DbErr>;

async fn load(
&self,
keys: &[#EmployeesFK],
) -> Result<
std::collections::HashMap<#EmployeesFK, Self::Value>,
Self::Error
>
{
...
}
}

relation macro

The relation macro is attached on Sea ORM RelationTrait implementation to generate structures and functions that are used by the Entity to query related Entities. This derive is applied on Entities in expanded form.

Input

#[seaography::macros::relation]
impl RelationTrait for Relation {
fn def(&self) -> RelationDef {
match self {
Self::Employees => Entity::belongs_to(super::employees::Entity)
.from(Column::SupportRepId)
.to(super::employees::Column::EmployeeId)
.into(),
Self::Invoices => Entity::has_many(super::invoices::Entity).into(),
}
}
}

Output

It produces the same result as RelationsCompact

EnumFilter derive

The EnumFilter macro is attached on Sea ORM Enum to generate its GraphQL filter struct used on Entities Filters

Input

#![doc = "SeaORM Entity. Generated by sea-orm-codegen 0.9.1"]
use sea_orm::entity::prelude::*;
#[derive(
Debug,
Clone,
PartialEq,
EnumIter,
DeriveActiveEnum,
Eq,
Copy,
async_graphql::Enum, // Required by GraphQL
seaography::macros::EnumFilter, // The macro
)]
#[sea_orm(rs_type = "String", db_type = "Enum", enum_name = "rating")]
pub enum Rating {
#[sea_orm(string_value = "G")]
G,
#[sea_orm(string_value = "PG")]
Pg,
#[sea_orm(string_value = "PG-13")]
Pg13,
#[sea_orm(string_value = "R")]
R,
#[sea_orm(string_value = "NC-17")]
Nc17,
}

Output

#[derive(Debug, async_graphql::InputObject)]
pub struct RatingEnumFilter {
pub eq: Option<Rating>,
pub ne: Option<Rating>,
pub gt: Option<Rating>,
pub gte: Option<Rating>,
pub lt: Option<Rating>,
pub lte: Option<Rating>,
pub is_in: Option<Vec<Rating>>,
pub is_not_in: Option<Vec<Rating>>,
pub is_null: Option<bool>,
}

QueryRoot macro

The QueryRoot derive macro is used to generate queries for every Entity that is defined through attributes. The query supports filtering, pagination and ordering.

Attributes

It enables the query for the specified path Entity and it also instructs the QueryRoot derive where to find the required utilities structures and functions for the generated code.

#[seaography(entity = "crate::entities::artists")]

Input

#[derive(Debug, seaography :: macros :: QueryRoot)]
#[seaography(entity = "crate::entities::artists")]
#[seaography(entity = "crate::entities::employees")]
pub struct QueryRoot;

Output

#[derive(Debug, async_graphql::InputObject)]
pub struct PageInput {
pub limit: usize,
pub page: usize,
}

#[derive(Debug, async_graphql::InputObject)]
pub struct CursorInput {
pub cursor: Option<String>,
pub limit: u64,
}

#[derive(async_graphql::OneofObject)]
pub enum Pagination {
Pages(PageInput),
Cursor(CursorInput),
}

/// Extra fields for pager pagination
#[derive(async_graphql::SimpleObject)]
pub struct ExtraPaginationFields {
pub pages: Option<usize>,
pub current: Option<usize>,
}

/// CursorValues is used to encode/decode the primary key of any Model for cursor pagination
#[derive(Debug)]
pub struct CursorValues(pub Vec<sea_orm::Value>);

impl async_graphql::types::connection::CursorType for CursorValues {
type Error = String;

/// Used to decode cursor String into a vector of Values
fn decode_cursor(s: &str) -> Result<Self, Self::Error> {
...
}

/// Used to encode a vector of Values into a cursor String
fn encode_cursor(&self) -> String {
...
}
}

/// Used to track the parsing state of the cursor String
#[derive(Debug)]
pub enum DecodeMode {
Type,
Length,
ColonSkip,
Data,
}

/// Used to parse a vector of Values into a ValueTuple enum
pub fn map_cursor_values(values: Vec<sea_orm::Value>) -> sea_orm::sea_query::value::ValueTuple {
...
}

#[async_graphql::Object]
impl QueryRoot {
pub async fn actor<'a>(
&self,
ctx: &async_graphql::Context<'a>,
filters: Option<crate::entities::actor::Filter>,
pagination: Option<Pagination>,
order_by: Option<crate::entities::actor::OrderBy>,
) -> async_graphql::types::connection::Connection<
String,
crate::entities::actor::Model,
ExtraPaginationFields,
async_graphql::types::connection::EmptyFields,
> {
// 1. use definitions
// 2. initialize db connection
// 3. create sql statement
// 4. apply filters and ordering
// 5. apply pagination
// 6. return result
}

pub async fn address<'a>(
&self,
ctx: &async_graphql::Context<'a>,
filters: Option<crate::entities::address::Filter>,
pagination: Option<Pagination>,
order_by: Option<crate::entities::address::OrderBy>,
) -> async_graphql::types::connection::Connection<
String,
crate::entities::address::Model,
ExtraPaginationFields,
async_graphql::types::connection::EmptyFields,
> {
...
}
}