use crate::generation::table::{GTValue, LTValue}; use crate::generation::{one_of, Arbitrary, ArbitraryFrom}; use crate::model::query::{Create, Delete, Insert, Predicate, Query, Select}; use crate::model::table::{Table, Value}; use rand::Rng; use super::{frequency, pick}; impl Arbitrary for Create { fn arbitrary(rng: &mut R) -> Self { Create { table: Table::arbitrary(rng), } } } impl ArbitraryFrom> for Select { fn arbitrary_from(rng: &mut R, tables: &Vec) -> Self { let table = pick(tables, rng); Self { table: table.name.clone(), predicate: Predicate::arbitrary_from(rng, table), } } } impl ArbitraryFrom> for Select { fn arbitrary_from(rng: &mut R, tables: &Vec<&Table>) -> Self { let table = pick(tables, rng); Self { table: table.name.clone(), predicate: Predicate::arbitrary_from(rng, *table), } } } impl ArbitraryFrom
for Insert { fn arbitrary_from(rng: &mut R, table: &Table) -> Self { let num_rows = rng.gen_range(1..10); let values: Vec> = (0..num_rows) .map(|_| { table .columns .iter() .map(|c| Value::arbitrary_from(rng, &c.column_type)) .collect() }) .collect(); Self { table: table.name.clone(), values, } } } impl ArbitraryFrom
for Delete { fn arbitrary_from(rng: &mut R, table: &Table) -> Self { Self { table: table.name.clone(), predicate: Predicate::arbitrary_from(rng, table), } } } impl ArbitraryFrom
for Query { fn arbitrary_from(rng: &mut R, table: &Table) -> Self { frequency( vec![ (1, Box::new(|rng| Self::Create(Create::arbitrary(rng)))), ( 100, Box::new(|rng| Self::Select(Select::arbitrary_from(rng, &vec![table]))), ), ( 100, Box::new(|rng| Self::Insert(Insert::arbitrary_from(rng, table))), ), ( 0, Box::new(|rng| Self::Delete(Delete::arbitrary_from(rng, table))), ), ], rng, ) } } struct CompoundPredicate(Predicate); struct SimplePredicate(Predicate); impl ArbitraryFrom<(&Table, bool)> for SimplePredicate { fn arbitrary_from(rng: &mut R, (table, predicate_value): &(&Table, bool)) -> Self { // Pick a random column let column_index = rng.gen_range(0..table.columns.len()); let column = &table.columns[column_index]; let column_values = table .rows .iter() .map(|r| &r[column_index]) .collect::>(); // Pick an operator let operator = match predicate_value { true => one_of( vec![ Box::new(|rng| { Predicate::Eq( column.name.clone(), Value::arbitrary_from(rng, &column_values), ) }), Box::new(|rng| { Predicate::Gt( column.name.clone(), GTValue::arbitrary_from(rng, &column_values).0, ) }), Box::new(|rng| { Predicate::Lt( column.name.clone(), LTValue::arbitrary_from(rng, &column_values).0, ) }), ], rng, ), false => one_of( vec![ Box::new(|rng| { Predicate::Neq( column.name.clone(), Value::arbitrary_from(rng, &column.column_type), ) }), Box::new(|rng| { Predicate::Gt( column.name.clone(), LTValue::arbitrary_from(rng, &column_values).0, ) }), Box::new(|rng| { Predicate::Lt( column.name.clone(), GTValue::arbitrary_from(rng, &column_values).0, ) }), ], rng, ), }; Self(operator) } } impl ArbitraryFrom<(&Table, bool)> for CompoundPredicate { fn arbitrary_from(rng: &mut R, (table, predicate_value): &(&Table, bool)) -> Self { // Decide if you want to create an AND or an OR Self(if rng.gen_bool(0.7) { // An AND for true requires each of its children to be true // An AND for false requires at least one of its children to be false if *predicate_value { Predicate::And( (0..rng.gen_range(1..=3)) .map(|_| SimplePredicate::arbitrary_from(rng, &(*table, true)).0) .collect(), ) } else { // Create a vector of random booleans let mut booleans = (0..rng.gen_range(1..=3)) .map(|_| rng.gen_bool(0.5)) .collect::>(); let len = booleans.len(); // Make sure at least one of them is false if booleans.iter().all(|b| *b) { booleans[rng.gen_range(0..len)] = false; } Predicate::And( booleans .iter() .map(|b| SimplePredicate::arbitrary_from(rng, &(*table, *b)).0) .collect(), ) } } else { // An OR for true requires at least one of its children to be true // An OR for false requires each of its children to be false if *predicate_value { // Create a vector of random booleans let mut booleans = (0..rng.gen_range(1..=3)) .map(|_| rng.gen_bool(0.5)) .collect::>(); let len = booleans.len(); // Make sure at least one of them is true if booleans.iter().all(|b| !*b) { booleans[rng.gen_range(0..len)] = true; } Predicate::Or( booleans .iter() .map(|b| SimplePredicate::arbitrary_from(rng, &(*table, *b)).0) .collect(), ) } else { Predicate::Or( (0..rng.gen_range(1..=3)) .map(|_| SimplePredicate::arbitrary_from(rng, &(*table, false)).0) .collect(), ) } }) } } impl ArbitraryFrom
for Predicate { fn arbitrary_from(rng: &mut R, table: &Table) -> Self { let predicate_value = rng.gen_bool(0.5); CompoundPredicate::arbitrary_from(rng, &(table, predicate_value)).0 } } impl ArbitraryFrom<(&str, &Value)> for Predicate { fn arbitrary_from(rng: &mut R, (column_name, value): &(&str, &Value)) -> Self { one_of( vec![ Box::new(|_| Predicate::Eq(column_name.to_string(), (*value).clone())), Box::new(|rng| { Self::Gt( column_name.to_string(), GTValue::arbitrary_from(rng, *value).0, ) }), Box::new(|rng| { Self::Lt( column_name.to_string(), LTValue::arbitrary_from(rng, *value).0, ) }), ], rng, ) } }