#![allow(unused_imports, dead_code)]
pub mod common;
pub use common::{TestContext, features::*, setup::*};
use pretty_assertions::assert_eq;
use sea_orm::{DerivePartialModel, FromQueryResult, QuerySelect, Set, entity::prelude::*};
use sea_query::ExprTrait;
use serde_json::json;
#[sea_orm_macros::test]
fn cursor_tests() -> Result<(), DbErr> {
let ctx = TestContext::new("cursor_tests");
create_insert_default_table(&ctx.db)?;
create_insert_default(&ctx.db)?;
cursor_pagination(&ctx.db)?;
bakery_chain_schema::create_bakery_table(&ctx.db)?;
bakery_chain_schema::create_baker_table(&ctx.db)?;
bakery_chain_schema::create_cake_table(&ctx.db)?;
bakery_chain_schema::create_cakes_bakers_table(&ctx.db)?;
create_baker_cake(&ctx.db)?;
cursor_related_pagination(&ctx.db)?;
ctx.delete();
Ok(())
}
pub fn create_insert_default(db: &DatabaseConnection) -> Result<(), DbErr> {
use insert_default::*;
for _ in 0..10 {
ActiveModel {
..Default::default()
}
.insert(db)?;
}
assert_eq!(
Entity::find().all(db)?,
[
Model { id: 1 },
Model { id: 2 },
Model { id: 3 },
Model { id: 4 },
Model { id: 5 },
Model { id: 6 },
Model { id: 7 },
Model { id: 8 },
Model { id: 9 },
Model { id: 10 },
]
);
Ok(())
}
pub fn cursor_pagination(db: &DatabaseConnection) -> Result<(), DbErr> {
use insert_default::*;
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.before(5);
assert_eq!(
cursor.first(4).all(db)?,
[
Model { id: 1 },
Model { id: 2 },
Model { id: 3 },
Model { id: 4 },
]
);
assert_eq!(
cursor.first(5).all(db)?,
[
Model { id: 1 },
Model { id: 2 },
Model { id: 3 },
Model { id: 4 },
]
);
assert_eq!(
cursor.last(4).all(db)?,
[
Model { id: 1 },
Model { id: 2 },
Model { id: 3 },
Model { id: 4 },
]
);
assert_eq!(
cursor.last(5).all(db)?,
[
Model { id: 1 },
Model { id: 2 },
Model { id: 3 },
Model { id: 4 },
]
);
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.before(5).desc();
assert_eq!(
cursor.first(4).all(db)?,
[
Model { id: 10 },
Model { id: 9 },
Model { id: 8 },
Model { id: 7 },
]
);
assert_eq!(
cursor.first(5).all(db)?,
[
Model { id: 10 },
Model { id: 9 },
Model { id: 8 },
Model { id: 7 },
Model { id: 6 },
]
);
assert_eq!(
cursor.last(4).all(db)?,
[
Model { id: 9 },
Model { id: 8 },
Model { id: 7 },
Model { id: 6 },
]
);
assert_eq!(
cursor.last(5).all(db)?,
[
Model { id: 10 },
Model { id: 9 },
Model { id: 8 },
Model { id: 7 },
Model { id: 6 },
]
);
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.after(5);
assert_eq!(
cursor.first(4).all(db)?,
[
Model { id: 6 },
Model { id: 7 },
Model { id: 8 },
Model { id: 9 },
]
);
assert_eq!(
cursor.first(5).all(db)?,
[
Model { id: 6 },
Model { id: 7 },
Model { id: 8 },
Model { id: 9 },
Model { id: 10 },
]
);
assert_eq!(
cursor.first(6).all(db)?,
[
Model { id: 6 },
Model { id: 7 },
Model { id: 8 },
Model { id: 9 },
Model { id: 10 },
]
);
assert_eq!(
cursor.last(4).all(db)?,
[
Model { id: 7 },
Model { id: 8 },
Model { id: 9 },
Model { id: 10 },
]
);
assert_eq!(
cursor.last(5).all(db)?,
[
Model { id: 6 },
Model { id: 7 },
Model { id: 8 },
Model { id: 9 },
Model { id: 10 },
]
);
assert_eq!(
cursor.last(6).all(db)?,
[
Model { id: 6 },
Model { id: 7 },
Model { id: 8 },
Model { id: 9 },
Model { id: 10 },
]
);
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.after(5).desc();
assert_eq!(
cursor.first(3).all(db)?,
[Model { id: 4 }, Model { id: 3 }, Model { id: 2 },]
);
assert_eq!(
cursor.first(4).all(db)?,
[
Model { id: 4 },
Model { id: 3 },
Model { id: 2 },
Model { id: 1 },
]
);
assert_eq!(
cursor.first(5).all(db)?,
[
Model { id: 4 },
Model { id: 3 },
Model { id: 2 },
Model { id: 1 },
]
);
assert_eq!(
cursor.last(3).all(db)?,
[Model { id: 3 }, Model { id: 2 }, Model { id: 1 },]
);
assert_eq!(
cursor.last(4).all(db)?,
[
Model { id: 4 },
Model { id: 3 },
Model { id: 2 },
Model { id: 1 },
]
);
assert_eq!(
cursor.last(5).all(db)?,
[
Model { id: 4 },
Model { id: 3 },
Model { id: 2 },
Model { id: 1 },
]
);
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.after(5).before(8);
assert_eq!(cursor.first(1).all(db)?, [Model { id: 6 }]);
assert_eq!(cursor.first(2).all(db)?, [Model { id: 6 }, Model { id: 7 }]);
assert_eq!(cursor.first(3).all(db)?, [Model { id: 6 }, Model { id: 7 }]);
assert_eq!(cursor.last(1).all(db)?, [Model { id: 7 }]);
assert_eq!(cursor.last(2).all(db)?, [Model { id: 6 }, Model { id: 7 }]);
assert_eq!(cursor.last(3).all(db)?, [Model { id: 6 }, Model { id: 7 }]);
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.after(8).before(5).desc();
assert_eq!(cursor.first(1).all(db)?, [Model { id: 7 }]);
assert_eq!(cursor.first(2).all(db)?, [Model { id: 7 }, Model { id: 6 }]);
assert_eq!(cursor.first(3).all(db)?, [Model { id: 7 }, Model { id: 6 }]);
assert_eq!(cursor.last(1).all(db)?, [Model { id: 6 }]);
assert_eq!(cursor.last(2).all(db)?, [Model { id: 7 }, Model { id: 6 }]);
assert_eq!(cursor.last(3).all(db)?, [Model { id: 7 }, Model { id: 6 }]);
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.first(2);
assert_eq!(cursor.all(db)?, [Model { id: 1 }, Model { id: 2 },]);
assert_eq!(cursor.asc().all(db)?, [Model { id: 1 }, Model { id: 2 },]);
assert_eq!(cursor.desc().all(db)?, [Model { id: 10 }, Model { id: 9 },]);
assert_eq!(cursor.asc().all(db)?, [Model { id: 1 }, Model { id: 2 },]);
assert_eq!(cursor.desc().all(db)?, [Model { id: 10 }, Model { id: 9 },]);
#[derive(FromQueryResult, Debug, PartialEq, Clone)]
struct Row {
id: i32,
}
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.after(5).before(8);
let mut cursor = cursor.into_model::<Row>();
assert_eq!(cursor.first(2).all(db)?, [Row { id: 6 }, Row { id: 7 }]);
assert_eq!(cursor.first(3).all(db)?, [Row { id: 6 }, Row { id: 7 }]);
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.after(8).before(5).desc();
let mut cursor = cursor.into_model::<Row>();
assert_eq!(cursor.first(2).all(db)?, [Row { id: 7 }, Row { id: 6 }]);
assert_eq!(cursor.first(3).all(db)?, [Row { id: 7 }, Row { id: 6 }]);
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.after(5).before(8);
let mut cursor = cursor.into_json();
assert_eq!(
cursor.first(2).all(db)?,
[json!({ "id": 6 }), json!({ "id": 7 })]
);
assert_eq!(
cursor.first(3).all(db)?,
[json!({ "id": 6 }), json!({ "id": 7 })]
);
#[derive(DerivePartialModel, Debug, PartialEq, Clone)]
#[sea_orm(entity = "Entity")]
struct PartialRow {
#[sea_orm(from_col = "id")]
id: i32,
#[sea_orm(from_expr = "sea_query::Expr::col(Column::Id).add(1000)")]
id_shifted: i32,
}
let mut cursor = cursor.into_partial_model::<PartialRow>();
assert_eq!(
cursor.first(2).all(db)?,
[
PartialRow {
id: 6,
id_shifted: 1006,
},
PartialRow {
id: 7,
id_shifted: 1007,
}
]
);
assert_eq!(
cursor.first(3).all(db)?,
[
PartialRow {
id: 6,
id_shifted: 1006,
},
PartialRow {
id: 7,
id_shifted: 1007,
}
]
);
let mut cursor = Entity::find().cursor_by(Column::Id);
cursor.after(8).before(5).desc();
let mut cursor = cursor.into_json();
assert_eq!(
cursor.first(2).all(db)?,
[json!({ "id": 7 }), json!({ "id": 6 })]
);
assert_eq!(
cursor.first(3).all(db)?,
[json!({ "id": 7 }), json!({ "id": 6 })]
);
let mut cursor = cursor.into_partial_model::<PartialRow>();
assert_eq!(
cursor.first(2).all(db)?,
[
PartialRow {
id: 7,
id_shifted: 1007,
},
PartialRow {
id: 6,
id_shifted: 1006,
}
]
);
assert_eq!(
cursor.first(3).all(db)?,
[
PartialRow {
id: 7,
id_shifted: 1007,
},
PartialRow {
id: 6,
id_shifted: 1006,
},
]
);
Ok(())
}
use common::bakery_chain::{
Baker, Bakery, Cake, CakesBakers, baker, bakery, cake, cakes_bakers,
schema as bakery_chain_schema,
};
fn bakery(i: i32) -> bakery::Model {
bakery::Model {
name: i.to_string(),
profit_margin: 10.4,
id: i,
}
}
fn baker(c: char) -> baker::Model {
baker::Model {
name: c.clone().to_string(),
contact_details: serde_json::json!({
"mobile": "+61424000000",
}),
bakery_id: Some((c as i32 - 65) % 10 + 1),
id: c as i32 - 64,
}
}
#[derive(Debug, FromQueryResult, PartialEq)]
pub struct CakeBakerlite {
pub cake_name: String,
pub cake_id: i32,
pub baker_name: String,
}
fn cakebaker(cake: char, baker: char) -> CakeBakerlite {
CakeBakerlite {
cake_name: cake.to_string(),
cake_id: cake as i32 - 96,
baker_name: baker.to_string(),
}
}
pub fn create_baker_cake(db: &DatabaseConnection) -> Result<(), DbErr> {
let mut bakeries: Vec<bakery::ActiveModel> = vec![];
for i in 1..=10 {
bakeries.push(bakery::ActiveModel {
name: Set(i.to_string()),
profit_margin: Set(10.4),
..Default::default()
});
}
let _ = Bakery::insert_many(bakeries).exec(db)?;
let mut bakers: Vec<baker::ActiveModel> = vec![];
let mut cakes: Vec<cake::ActiveModel> = vec![];
let mut cakes_bakers: Vec<cakes_bakers::ActiveModel> = vec![];
for c in 'A'..='Z' {
bakers.push(baker::ActiveModel {
name: Set(c.clone().to_string()),
contact_details: Set(serde_json::json!({
"mobile": "+61424000000",
})),
bakery_id: Set(Some((c as i32 - 65) % 10 + 1)),
..Default::default()
});
cakes.push(cake::ActiveModel {
name: Set(c.to_ascii_lowercase().to_string()),
price: Set(rust_dec(10.25)),
gluten_free: Set(false),
serial: Set(Uuid::new_v4()),
bakery_id: Set(Some((c as i32 - 65) % 10 + 1)),
..Default::default()
});
cakes_bakers.push(cakes_bakers::ActiveModel {
cake_id: Set(c as i32 - 64),
baker_id: Set(c as i32 - 64),
})
}
cakes_bakers.append(
vec![
cakes_bakers::ActiveModel {
cake_id: Set(2),
baker_id: Set(1),
},
cakes_bakers::ActiveModel {
cake_id: Set(1),
baker_id: Set(2),
},
]
.as_mut(),
);
Baker::insert_many(bakers).exec(db)?;
Cake::insert_many(cakes).exec(db)?;
CakesBakers::insert_many(cakes_bakers).exec(db)?;
Ok(())
}
pub fn cursor_related_pagination(db: &DatabaseConnection) -> Result<(), DbErr> {
use common::bakery_chain::*;
assert_eq!(
bakery::Entity::find()
.cursor_by(bakery::Column::Id)
.before(5)
.first(4)
.all(db)?,
[bakery(1), bakery(2), bakery(3), bakery(4),]
);
assert_eq!(
bakery::Entity::find()
.cursor_by(bakery::Column::Id)
.before(5)
.first(4)
.desc()
.all(db)?,
[bakery(10), bakery(9), bakery(8), bakery(7),]
);
assert_eq!(
bakery::Entity::find()
.find_also_related(Baker)
.cursor_by(bakery::Column::Id)
.before(5)
.first(20)
.all(db)?,
[
(bakery(1), Some(baker('A'))),
(bakery(1), Some(baker('K'))),
(bakery(1), Some(baker('U'))),
(bakery(2), Some(baker('B'))),
(bakery(2), Some(baker('L'))),
(bakery(2), Some(baker('V'))),
(bakery(3), Some(baker('C'))),
(bakery(3), Some(baker('M'))),
(bakery(3), Some(baker('W'))),
(bakery(4), Some(baker('D'))),
(bakery(4), Some(baker('N'))),
(bakery(4), Some(baker('X'))),
]
);
assert_eq!(
bakery::Entity::find()
.find_also_related(Baker)
.cursor_by(bakery::Column::Id)
.after(5)
.last(20)
.desc()
.all(db)?,
[
(bakery(4), Some(baker('X'))),
(bakery(4), Some(baker('N'))),
(bakery(4), Some(baker('D'))),
(bakery(3), Some(baker('W'))),
(bakery(3), Some(baker('M'))),
(bakery(3), Some(baker('C'))),
(bakery(2), Some(baker('V'))),
(bakery(2), Some(baker('L'))),
(bakery(2), Some(baker('B'))),
(bakery(1), Some(baker('U'))),
(bakery(1), Some(baker('K'))),
(bakery(1), Some(baker('A'))),
]
);
assert_eq!(
bakery::Entity::find()
.find_also_related(Baker)
.cursor_by(bakery::Column::Id)
.before(5)
.first(4)
.all(db)?,
[
(bakery(1), Some(baker('A'))),
(bakery(1), Some(baker('K'))),
(bakery(1), Some(baker('U'))),
(bakery(2), Some(baker('B'))),
]
);
assert_eq!(
bakery::Entity::find()
.find_also_related(Baker)
.cursor_by(bakery::Column::Id)
.after(5)
.last(4)
.desc()
.all(db)?,
[
(bakery(2), Some(baker('B'))),
(bakery(1), Some(baker('U'))),
(bakery(1), Some(baker('K'))),
(bakery(1), Some(baker('A'))),
]
);
assert_eq!(
bakery::Entity::find()
.find_also_related(Baker)
.cursor_by(bakery::Column::Name)
.after("3")
.last(4)
.desc()
.all(db)?,
[
(bakery(10), Some(baker('J'))),
(bakery(1), Some(baker('U'))),
(bakery(1), Some(baker('K'))),
(bakery(1), Some(baker('A'))),
]
);
assert_eq!(
bakery::Entity::find()
.find_also_related(Baker)
.cursor_by(bakery::Column::Name)
.before("3")
.first(4)
.all(db)?,
[
(bakery(1), Some(baker('A'))),
(bakery(1), Some(baker('K'))),
(bakery(1), Some(baker('U'))),
(bakery(10), Some(baker('J'))),
]
);
assert_eq!(
bakery::Entity::find()
.find_also_related(Baker)
.cursor_by(bakery::Column::Name)
.after("3")
.last(4)
.desc()
.all(db)?,
[
(bakery(10), Some(baker('J'))),
(bakery(1), Some(baker('U'))),
(bakery(1), Some(baker('K'))),
(bakery(1), Some(baker('A'))),
]
);
#[derive(Copy, Clone, Debug, EnumIter, DeriveColumn)]
enum QueryAs {
CakeId,
CakeName,
BakerName,
}
assert_eq!(
cake::Entity::find()
.find_also_related(Baker)
.select_only()
.column_as(cake::Column::Id, QueryAs::CakeId)
.column_as(cake::Column::Name, QueryAs::CakeName)
.column_as(baker::Column::Name, QueryAs::BakerName)
.cursor_by(cake::Column::Name)
.before("e")
.first(4)
.clone()
.into_model::<CakeBakerlite>()
.all(db)?,
vec![
cakebaker('a', 'A'),
cakebaker('a', 'B'),
cakebaker('b', 'A'),
cakebaker('b', 'B')
]
);
assert_eq!(
cake::Entity::find()
.find_also_related(Baker)
.select_only()
.column_as(cake::Column::Id, QueryAs::CakeId)
.column_as(cake::Column::Name, QueryAs::CakeName)
.column_as(baker::Column::Name, QueryAs::BakerName)
.cursor_by(cake::Column::Name)
.after("e")
.last(4)
.desc()
.clone()
.into_model::<CakeBakerlite>()
.all(db)?,
vec![
cakebaker('b', 'B'),
cakebaker('b', 'A'),
cakebaker('a', 'B'),
cakebaker('a', 'A')
]
);
assert_eq!(
cake::Entity::find()
.find_also_related(Baker)
.select_only()
.column_as(cake::Column::Id, QueryAs::CakeId)
.column_as(cake::Column::Name, QueryAs::CakeName)
.column_as(baker::Column::Name, QueryAs::BakerName)
.cursor_by(cake::Column::Name)
.before("b")
.first(4)
.clone()
.into_model::<CakeBakerlite>()
.all(db)?,
vec![cakebaker('a', 'A'), cakebaker('a', 'B')]
);
assert_eq!(
cake::Entity::find()
.find_also_related(Baker)
.select_only()
.column_as(cake::Column::Id, QueryAs::CakeId)
.column_as(cake::Column::Name, QueryAs::CakeName)
.column_as(baker::Column::Name, QueryAs::BakerName)
.cursor_by(cake::Column::Name)
.after("b")
.last(4)
.desc()
.clone()
.into_model::<CakeBakerlite>()
.all(db)?,
vec![cakebaker('a', 'B'), cakebaker('a', 'A')]
);
assert_eq!(
cake::Entity::find()
.find_also_related(Baker)
.select_only()
.column_as(cake::Column::Id, QueryAs::CakeId)
.column_as(cake::Column::Name, QueryAs::CakeName)
.column_as(baker::Column::Name, QueryAs::BakerName)
.cursor_by_other(baker::Column::Name)
.before("B")
.first(4)
.clone()
.into_model::<CakeBakerlite>()
.all(db)?,
vec![cakebaker('a', 'A'), cakebaker('b', 'A'),]
);
assert_eq!(
cake::Entity::find()
.find_also_related(Baker)
.select_only()
.column_as(cake::Column::Id, QueryAs::CakeId)
.column_as(cake::Column::Name, QueryAs::CakeName)
.column_as(baker::Column::Name, QueryAs::BakerName)
.cursor_by_other(baker::Column::Name)
.after("B")
.last(4)
.desc()
.clone()
.into_model::<CakeBakerlite>()
.all(db)?,
vec![cakebaker('b', 'A'), cakebaker('a', 'A'),]
);
assert_eq!(
cake::Entity::find()
.find_also_related(Baker)
.select_only()
.column_as(cake::Column::Id, QueryAs::CakeId)
.column_as(cake::Column::Name, QueryAs::CakeName)
.column_as(baker::Column::Name, QueryAs::BakerName)
.cursor_by_other(baker::Column::Name)
.before("E")
.first(20)
.clone()
.into_model::<CakeBakerlite>()
.all(db)?,
vec![
cakebaker('a', 'A'),
cakebaker('b', 'A'),
cakebaker('a', 'B'),
cakebaker('b', 'B'),
cakebaker('c', 'C'),
cakebaker('d', 'D'),
]
);
assert_eq!(
cake::Entity::find()
.find_also_related(Baker)
.select_only()
.column_as(cake::Column::Id, QueryAs::CakeId)
.column_as(cake::Column::Name, QueryAs::CakeName)
.column_as(baker::Column::Name, QueryAs::BakerName)
.cursor_by_other(baker::Column::Name)
.after("E")
.last(20)
.desc()
.clone()
.into_model::<CakeBakerlite>()
.all(db)?,
vec![
cakebaker('d', 'D'),
cakebaker('c', 'C'),
cakebaker('b', 'B'),
cakebaker('a', 'B'),
cakebaker('b', 'A'),
cakebaker('a', 'A'),
]
);
Ok(())
}