use crate::ast::values::IntervalUnit;
use crate::ast::*;
use proptest::prelude::*;
pub fn arb_identifier() -> impl Strategy<Value = String> {
"[a-z][a-z0-9_]{0,15}".prop_map(|s| s.to_string())
}
pub fn arb_interval_unit() -> impl Strategy<Value = IntervalUnit> {
prop_oneof![
Just(IntervalUnit::Second),
Just(IntervalUnit::Minute),
Just(IntervalUnit::Hour),
Just(IntervalUnit::Day),
Just(IntervalUnit::Week),
Just(IntervalUnit::Month),
Just(IntervalUnit::Year),
]
}
pub fn arb_operator() -> impl Strategy<Value = Operator> {
prop_oneof![
10 => Just(Operator::Eq),
10 => Just(Operator::Ne),
5 => Just(Operator::Gt),
5 => Just(Operator::Gte),
5 => Just(Operator::Lt),
5 => Just(Operator::Lte),
3 => Just(Operator::In),
3 => Just(Operator::NotIn),
3 => Just(Operator::IsNull),
3 => Just(Operator::IsNotNull),
2 => Just(Operator::Like),
2 => Just(Operator::ILike),
2 => Just(Operator::NotLike),
2 => Just(Operator::NotILike),
1 => Just(Operator::Between),
1 => Just(Operator::NotBetween),
1 => Just(Operator::Fuzzy),
1 => Just(Operator::Contains),
1 => Just(Operator::Regex),
1 => Just(Operator::RegexI),
]
}
pub fn arb_sort_order() -> impl Strategy<Value = SortOrder> {
prop_oneof![
Just(SortOrder::Asc),
Just(SortOrder::Desc),
Just(SortOrder::AscNullsFirst),
Just(SortOrder::AscNullsLast),
Just(SortOrder::DescNullsFirst),
Just(SortOrder::DescNullsLast),
]
}
pub fn arb_aggregate_func() -> impl Strategy<Value = AggregateFunc> {
prop_oneof![
Just(AggregateFunc::Count),
Just(AggregateFunc::Sum),
Just(AggregateFunc::Avg),
Just(AggregateFunc::Min),
Just(AggregateFunc::Max),
Just(AggregateFunc::ArrayAgg),
Just(AggregateFunc::StringAgg),
Just(AggregateFunc::JsonAgg),
Just(AggregateFunc::JsonbAgg),
Just(AggregateFunc::BoolAnd),
Just(AggregateFunc::BoolOr),
]
}
pub fn arb_logical_op() -> impl Strategy<Value = LogicalOp> {
prop_oneof![Just(LogicalOp::And), Just(LogicalOp::Or),]
}
fn is_safe_float(f: &f64) -> bool {
f.is_finite() && f.abs() > 1e-100 && f.abs() < 1e100
}
pub fn arb_value_leaf() -> impl Strategy<Value = Value> {
prop_oneof![
5 => Just(Value::Null),
10 => any::<bool>().prop_map(Value::Bool),
10 => any::<i64>().prop_map(Value::Int),
5 => any::<f64>().prop_filter("safe floats", is_safe_float).prop_map(Value::Float),
10 => "[a-zA-Z0-9 _-]{0,50}".prop_map(Value::String),
5 => (1usize..100).prop_map(Value::Param),
3 => arb_identifier().prop_map(Value::NamedParam),
3 => arb_identifier().prop_map(Value::Column),
2 => (1i64..1000, arb_interval_unit()).prop_map(|(amount, unit)| Value::Interval { amount, unit }),
]
}
pub fn arb_expr_leaf() -> impl Strategy<Value = Expr> {
prop_oneof![
5 => Just(Expr::Star),
20 => arb_identifier().prop_map(Expr::Named),
10 => (arb_identifier(), arb_identifier()).prop_map(|(name, alias)| Expr::Aliased { name, alias }),
5 => arb_value_leaf().prop_map(Expr::Literal),
]
}
pub fn arb_condition() -> impl Strategy<Value = Condition> {
(arb_expr_leaf(), arb_operator(), arb_value_leaf()).prop_map(|(left, op, value)| Condition {
left,
op,
value,
is_array_unnest: false,
})
}
pub fn arb_cage_kind() -> impl Strategy<Value = CageKind> {
prop_oneof![
Just(CageKind::Filter),
(1usize..1000).prop_map(CageKind::Limit),
(0usize..1000).prop_map(CageKind::Offset),
arb_sort_order().prop_map(CageKind::Sort),
]
}
pub fn arb_cage() -> impl Strategy<Value = Cage> {
(
arb_cage_kind(),
proptest::collection::vec(arb_condition(), 0..3),
arb_logical_op(),
)
.prop_map(|(kind, conditions, logical_op)| Cage {
kind,
conditions,
logical_op,
})
}
pub fn arb_qail_get() -> impl Strategy<Value = Qail> {
(
arb_identifier(),
proptest::collection::vec(arb_expr_leaf(), 1..5),
proptest::collection::vec(arb_cage(), 0..3),
)
.prop_map(|(table, columns, cages)| Qail {
action: Action::Get,
table,
columns,
cages,
..Default::default()
})
}