use std::sync::atomic::{AtomicU64, Ordering}; use indexmap::IndexSet; use rand::Rng; use crate::generation::{pick, readable_name_custom, Arbitrary, GenerationContext}; use crate::model::table::{Column, ColumnType, Name, Table}; static COUNTER: AtomicU64 = AtomicU64::new(0); impl Arbitrary for Name { fn arbitrary(rng: &mut R, _c: &C) -> Self { let base = readable_name_custom("_", rng).replace("-", "_"); let id = COUNTER.fetch_add(1, Ordering::Relaxed); Name(format!("{base}_{id}")) } } impl Arbitrary for Table { fn arbitrary(rng: &mut R, context: &C) -> Self { let opts = context.opts().table.clone(); let name = Name::arbitrary(rng, context).0; let large_table = opts.large_table.enable && rng.random_bool(opts.large_table.large_table_prob); let column_size = if large_table { rng.random_range(opts.large_table.column_range) } else { rng.random_range(opts.column_range) } as usize; let mut column_set = IndexSet::with_capacity(column_size); for col in std::iter::repeat_with(|| Column::arbitrary(rng, context)) { column_set.insert(col); if column_set.len() == column_size { break; } } Table { rows: Vec::new(), name, columns: Vec::from_iter(column_set), indexes: vec![], } } } impl Arbitrary for Column { fn arbitrary(rng: &mut R, context: &C) -> Self { let name = Name::arbitrary(rng, context).0; let column_type = ColumnType::arbitrary(rng, context); Self { name, column_type, constraints: vec![], // TODO: later implement arbitrary here for ColumnConstraint } } } impl Arbitrary for ColumnType { fn arbitrary(rng: &mut R, _context: &C) -> Self { pick(&[Self::Integer, Self::Float, Self::Text, Self::Blob], rng).to_owned() } }