tests_fuzz/generator/
insert_expr.rsuse std::marker::PhantomData;
use datatypes::value::Value;
use derive_builder::Builder;
use rand::seq::{IndexedRandom, SliceRandom};
use rand::Rng;
use super::TsValueGenerator;
use crate::context::TableContextRef;
use crate::error::{Error, Result};
use crate::fake::WordGenerator;
use crate::generator::{Generator, Random, ValueGenerator};
use crate::ir::insert_expr::{InsertIntoExpr, RowValue};
use crate::ir::{generate_random_timestamp, generate_random_value, Ident};
#[derive(Builder)]
#[builder(pattern = "owned")]
pub struct InsertExprGenerator<R: Rng + 'static> {
table_ctx: TableContextRef,
omit_column_list: bool,
#[builder(default = "1")]
rows: usize,
#[builder(default = "Box::new(WordGenerator)")]
word_generator: Box<dyn Random<Ident, R>>,
#[builder(default = "Box::new(generate_random_value)")]
value_generator: ValueGenerator<R>,
#[builder(default = "Box::new(generate_random_timestamp)")]
ts_value_generator: TsValueGenerator<R>,
#[builder(default)]
_phantom: PhantomData<R>,
}
impl<R: Rng + 'static> Generator<InsertIntoExpr, R> for InsertExprGenerator<R> {
type Error = Error;
fn generate(&self, rng: &mut R) -> Result<InsertIntoExpr> {
let mut values_columns = vec![];
if self.omit_column_list {
values_columns.clone_from(&self.table_ctx.columns);
} else {
for column in &self.table_ctx.columns {
let can_omit = column.is_nullable() || column.has_default_value();
if !can_omit || rng.random_bool(0.5) {
values_columns.push(column.clone());
}
}
values_columns.shuffle(rng);
if values_columns.is_empty() {
values_columns.push(self.table_ctx.columns.choose(rng).unwrap().clone());
}
}
let mut values_list = Vec::with_capacity(self.rows);
for _ in 0..self.rows {
let mut row = Vec::with_capacity(values_columns.len());
for column in &values_columns {
if column.is_nullable() && rng.random_bool(0.2) {
row.push(RowValue::Value(Value::Null));
continue;
}
if column.has_default_value() && rng.random_bool(0.2) {
row.push(RowValue::Default);
continue;
}
if column.is_time_index() {
row.push(RowValue::Value((self.ts_value_generator)(
rng,
column.timestamp_type().unwrap(),
)));
} else {
row.push(RowValue::Value((self.value_generator)(
rng,
&column.column_type,
Some(self.word_generator.as_ref()),
)));
}
}
values_list.push(row);
}
Ok(InsertIntoExpr {
table_name: self.table_ctx.name.clone(),
omit_column_list: self.omit_column_list,
columns: values_columns,
values_list,
})
}
}