use super::support::*;
use crate::{
db::predicate::{CoercionId, CompareOp, ComparePredicate, Predicate},
value::Value,
};
#[test]
fn load_filter_after_access_with_optional_equality() {
init_commit_store_for_tests().expect("commit store init should succeed");
reset_store();
let save = SaveExecutor::<PhaseEntity>::new(DB, false);
let id = Ulid::from_u128(501);
save.insert(PhaseEntity {
id,
opt_rank: Some(7),
rank: 7,
tags: vec![1, 2, 3],
label: "alpha".to_string(),
})
.expect("save should succeed");
let load = LoadExecutor::<PhaseEntity>::new(DB, false);
let equals_opt_value = Predicate::Compare(ComparePredicate::with_coercion(
"opt_rank",
CompareOp::Eq,
Value::Uint(7),
CoercionId::Strict,
));
let match_plan = Query::<PhaseEntity>::new(MissingRowPolicy::Ignore)
.by_id(id)
.filter_predicate(equals_opt_value)
.plan()
.map(crate::db::executor::PreparedExecutionPlan::from)
.expect("optional equality plan should build");
let match_response = load
.execute(match_plan)
.expect("optional equality should load");
assert_eq!(
match_response.len(),
1,
"filter should run after by_id access and keep matching rows",
);
let no_match = Predicate::Compare(ComparePredicate::with_coercion(
"opt_rank",
CompareOp::Eq,
Value::Uint(99),
CoercionId::Strict,
));
let mismatch_plan = Query::<PhaseEntity>::new(MissingRowPolicy::Ignore)
.by_id(id)
.filter_predicate(no_match)
.plan()
.map(crate::db::executor::PreparedExecutionPlan::from)
.expect("mismatch plan should build");
let mismatch_response = load
.execute(mismatch_plan)
.expect("mismatch predicate should execute");
assert_eq!(
mismatch_response.len(),
0,
"filter should be applied after access and drop non-matching rows",
);
}
#[test]
fn load_in_and_text_ops_respect_ordered_pagination() {
init_commit_store_for_tests().expect("commit store init should succeed");
reset_store();
let save = SaveExecutor::<PhaseEntity>::new(DB, false);
for row in [
PhaseEntity {
id: Ulid::from_u128(601),
opt_rank: Some(30),
rank: 30,
tags: vec![1, 3],
label: "needle alpha".to_string(),
},
PhaseEntity {
id: Ulid::from_u128(602),
opt_rank: Some(10),
rank: 10,
tags: vec![2],
label: "other".to_string(),
},
PhaseEntity {
id: Ulid::from_u128(603),
opt_rank: Some(20),
rank: 20,
tags: vec![9],
label: "NEEDLE beta".to_string(),
},
PhaseEntity {
id: Ulid::from_u128(604),
opt_rank: Some(40),
rank: 40,
tags: vec![4],
label: "needle gamma".to_string(),
},
] {
save.insert(row).expect("seed row save should succeed");
}
let predicate = Predicate::And(vec![
Predicate::Compare(ComparePredicate::with_coercion(
"rank",
CompareOp::In,
Value::List(vec![Value::Uint(20), Value::Uint(30), Value::Uint(40)]),
CoercionId::Strict,
)),
Predicate::TextContainsCi {
field: "label".to_string(),
value: Value::Text("needle".to_string()),
},
]);
let load = LoadExecutor::<PhaseEntity>::new(DB, false);
let plan = Query::<PhaseEntity>::new(MissingRowPolicy::Ignore)
.filter_predicate(predicate)
.order_term(crate::db::asc("rank"))
.limit(1)
.offset(1)
.plan()
.map(crate::db::executor::PreparedExecutionPlan::from)
.expect("in+text ordered page plan should build");
let response = load
.execute(plan)
.expect("in+text ordered page should load");
assert_eq!(
response.len(),
1,
"ordered pagination should return one row",
);
assert_eq!(
response[0].entity_ref().rank,
30,
"pagination should apply to the filtered+ordered window",
);
}
#[test]
fn load_contains_filters_after_by_id_access() {
init_commit_store_for_tests().expect("commit store init should succeed");
reset_store();
let save = SaveExecutor::<PhaseEntity>::new(DB, false);
let id = Ulid::from_u128(701);
save.insert(PhaseEntity {
id,
opt_rank: Some(1),
rank: 1,
tags: vec![2, 9],
label: "contains".to_string(),
})
.expect("save should succeed");
let contains_nine = Predicate::Compare(ComparePredicate::with_coercion(
"tags",
CompareOp::Contains,
Value::Uint(9),
CoercionId::CollectionElement,
));
let load = LoadExecutor::<PhaseEntity>::new(DB, false);
let hit_plan = Query::<PhaseEntity>::new(MissingRowPolicy::Ignore)
.by_id(id)
.filter_predicate(contains_nine)
.plan()
.map(crate::db::executor::PreparedExecutionPlan::from)
.expect("contains hit plan should build");
let hit = load.execute(hit_plan).expect("contains hit should execute");
assert_eq!(hit.len(), 1, "contains predicate should match row");
let contains_missing = Predicate::Compare(ComparePredicate::with_coercion(
"tags",
CompareOp::Contains,
Value::Uint(8),
CoercionId::CollectionElement,
));
let miss_plan = Query::<PhaseEntity>::new(MissingRowPolicy::Ignore)
.by_id(id)
.filter_predicate(contains_missing)
.plan()
.map(crate::db::executor::PreparedExecutionPlan::from)
.expect("contains miss plan should build");
let miss = load
.execute(miss_plan)
.expect("contains miss should execute");
assert_eq!(
miss.len(),
0,
"contains predicate should filter out non-matching rows after access"
);
}
#[test]
fn delete_limit_applies_to_filtered_rows_only() {
init_commit_store_for_tests().expect("commit store init should succeed");
reset_store();
let save = SaveExecutor::<PhaseEntity>::new(DB, false);
for row in [
PhaseEntity {
id: Ulid::from_u128(801),
opt_rank: Some(1),
rank: 1,
tags: vec![1],
label: "keep-low-1".to_string(),
},
PhaseEntity {
id: Ulid::from_u128(802),
opt_rank: Some(2),
rank: 2,
tags: vec![2],
label: "keep-low-2".to_string(),
},
PhaseEntity {
id: Ulid::from_u128(803),
opt_rank: Some(100),
rank: 100,
tags: vec![3],
label: "delete-first".to_string(),
},
PhaseEntity {
id: Ulid::from_u128(804),
opt_rank: Some(200),
rank: 200,
tags: vec![4],
label: "delete-second".to_string(),
},
] {
save.insert(row).expect("seed row save should succeed");
}
let predicate = Predicate::Compare(ComparePredicate::with_coercion(
"rank",
CompareOp::Gte,
Value::Uint(100),
CoercionId::NumericWiden,
));
let delete = DeleteExecutor::<PhaseEntity>::new(DB);
let plan = Query::<PhaseEntity>::new(MissingRowPolicy::Ignore)
.delete()
.filter_predicate(predicate)
.order_term(crate::db::asc("rank"))
.limit(1)
.plan()
.map(crate::db::executor::PreparedExecutionPlan::from)
.expect("filtered delete plan should build");
let deleted = delete
.execute(plan)
.expect("filtered delete should execute");
assert_eq!(
deleted.len(),
1,
"delete limit should remove one filtered row"
);
assert_eq!(
deleted[0].entity_ref().rank,
100,
"delete limit should apply after filtering+ordering"
);
let load = LoadExecutor::<PhaseEntity>::new(DB, false);
let remaining_plan = Query::<PhaseEntity>::new(MissingRowPolicy::Ignore)
.order_term(crate::db::asc("rank"))
.plan()
.map(crate::db::executor::PreparedExecutionPlan::from)
.expect("remaining load plan should build");
let remaining = load
.execute(remaining_plan)
.expect("remaining load should execute");
let remaining_ranks: Vec<u64> = remaining
.into_iter()
.map(|row| u64::from(row.entity().rank))
.collect();
assert_eq!(
remaining_ranks,
vec![1, 2, 200],
"only one row from the filtered window should be deleted"
);
}