Skip to content

Commit

Permalink
refactor: separate the quote char and value (#3455)
Browse files Browse the repository at this point in the history
refactor: use ident instead of string
  • Loading branch information
WenyXu committed Mar 7, 2024
1 parent a218f12 commit 3f3ef2e
Show file tree
Hide file tree
Showing 14 changed files with 172 additions and 95 deletions.
6 changes: 3 additions & 3 deletions tests-fuzz/src/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,13 +16,13 @@ use std::sync::Arc;

use partition::partition::PartitionDef;

use crate::ir::{Column, CreateTableExpr};
use crate::ir::{Column, CreateTableExpr, Ident};

pub type TableContextRef = Arc<TableContext>;

/// TableContext stores table info.
pub struct TableContext {
pub name: String,
pub name: Ident,
pub columns: Vec<Column>,

// GreptimeDB specific options
Expand All @@ -41,7 +41,7 @@ impl From<&CreateTableExpr> for TableContext {
}: &CreateTableExpr,
) -> Self {
Self {
name: name.to_string(),
name: name.clone(),
columns: columns.clone(),
partition: partition.clone(),
primary_keys: primary_keys.clone(),
Expand Down
62 changes: 38 additions & 24 deletions tests-fuzz/src/fake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use rand::Rng;

use crate::generator::Random;
use crate::impl_random;
use crate::ir::Ident;

lazy_static! {
pub static ref LOREM_WORDS: Vec<String> = include_str!("data/lorem_words")
Expand Down Expand Up @@ -49,7 +50,7 @@ macro_rules! faker_impl_from_values {
pub struct Word(String);
faker_impl_from_values!(Word, LOREM_WORDS);
pub struct WordGenerator;
impl_random!(String, WordGenerator, LOREM_WORDS);
impl_random!(Ident, WordGenerator, LOREM_WORDS);

pub struct MappedGenerator<T, F, R, V>
where
Expand All @@ -63,15 +64,19 @@ where
_v: PhantomData<V>,
}

pub fn random_capitalize_map<R: Rng + 'static>(rng: &mut R, s: String) -> String {
let mut v = s.chars().collect::<Vec<_>>();
pub fn random_capitalize_map<R: Rng + 'static>(rng: &mut R, s: Ident) -> Ident {
let mut v = s.value.chars().collect::<Vec<_>>();

let select = rng.gen_range(0..s.len());
for idx in (0..s.len()).choose_multiple(rng, select) {
let str_len = s.value.len();
let select = rng.gen_range(0..str_len);
for idx in (0..str_len).choose_multiple(rng, select) {
v[idx] = v[idx].to_uppercase().next().unwrap();
}

v.into_iter().collect::<String>()
Ident {
quote_style: s.quote_style,
value: v.into_iter().collect::<String>(),
}
}

lazy_static! {
Expand All @@ -98,12 +103,15 @@ pub fn is_keyword_or_contain_uppercase(s: &str) -> bool {

pub fn make_backtick_map<R: Rng + 'static, F: Fn(&str) -> bool>(
f: F,
) -> impl Fn(&mut R, String) -> String {
move |_rng, s| -> String {
let need = f(&s);
) -> impl Fn(&mut R, Ident) -> Ident {
move |_rng, s| -> Ident {
let need = f(&s.value);

if need {
format!("`{s}`")
Ident {
value: s.value,
quote_style: Some('`'),
}
} else {
s
}
Expand All @@ -112,49 +120,55 @@ pub fn make_backtick_map<R: Rng + 'static, F: Fn(&str) -> bool>(

pub fn make_quote_map<R: Rng + 'static, F: Fn(&str) -> bool>(
f: F,
) -> impl Fn(&mut R, String) -> String {
move |_rng, s| -> String {
let need = f(&s);
) -> impl Fn(&mut R, Ident) -> Ident {
move |_rng, s| -> Ident {
let need = f(&s.value);

if need {
format!("\"{s}\"")
Ident {
value: s.value,
quote_style: Some('"'),
}
} else {
s
}
}
}

/// Adds backticks if it contains uppercase chars.
pub fn auto_backtick_map<R: Rng + 'static>(_rng: &mut R, s: String) -> String {
let need = s.chars().any(|c| c.is_uppercase());
pub fn auto_backtick_map<R: Rng + 'static>(_rng: &mut R, s: Ident) -> Ident {
let need = s.value.chars().any(|c| c.is_uppercase());

if need {
format!("`{s}`")
Ident {
value: s.value,
quote_style: Some('`'),
}
} else {
s
}
}

/// Adds backticks if it contains uppercase chars.
pub fn uppercase_and_keyword_backtick_map<R: Rng + 'static>(rng: &mut R, s: String) -> String {
pub fn uppercase_and_keyword_backtick_map<R: Rng + 'static>(rng: &mut R, s: Ident) -> Ident {
make_backtick_map(is_keyword_or_contain_uppercase)(rng, s)
}

/// Adds quotes if it contains uppercase chars.
pub fn auto_quote_map<R: Rng + 'static>(rng: &mut R, s: String) -> String {
pub fn auto_quote_map<R: Rng + 'static>(rng: &mut R, s: Ident) -> Ident {
make_quote_map(contain_uppercase_char)(rng, s)
}

/// Adds quotes if it contains uppercase chars.
pub fn uppercase_and_keyword_quote_map<R: Rng + 'static>(rng: &mut R, s: String) -> String {
pub fn uppercase_and_keyword_quote_map<R: Rng + 'static>(rng: &mut R, s: Ident) -> Ident {
make_quote_map(is_keyword_or_contain_uppercase)(rng, s)
}

pub fn merge_two_word_map_fn<R: Rng>(
f1: impl Fn(&mut R, String) -> String,
f2: impl Fn(&mut R, String) -> String,
) -> impl Fn(&mut R, String) -> String {
move |rng, s| -> String {
f1: impl Fn(&mut R, Ident) -> Ident,
f2: impl Fn(&mut R, Ident) -> Ident,
) -> impl Fn(&mut R, Ident) -> Ident {
move |rng, s| -> Ident {
let s = f1(rng, s);
f2(rng, s)
}
Expand Down
2 changes: 1 addition & 1 deletion tests-fuzz/src/generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ macro_rules! impl_random {
while result.len() != amount {
result.insert($values.choose(rng).unwrap().clone());
}
let mut result = result.into_iter().collect::<Vec<_>>();
let mut result = result.into_iter().map(Into::into).collect::<Vec<_>>();
// Shuffles the result slice.
result.shuffle(rng);
result
Expand Down
23 changes: 10 additions & 13 deletions tests-fuzz/src/generator/alter_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ use crate::fake::WordGenerator;
use crate::generator::{ColumnOptionGenerator, ConcreteDataTypeGenerator, Generator, Random};
use crate::ir::alter_expr::{AlterTableExpr, AlterTableOperation};
use crate::ir::{
column_options_generator, droppable_columns, generate_columns, ColumnTypeGenerator,
column_options_generator, droppable_columns, generate_columns, ColumnTypeGenerator, Ident,
};

/// Generates the [AlterTableOperation::AddColumn] of [AlterTableExpr].
Expand All @@ -36,7 +36,7 @@ pub struct AlterExprAddColumnGenerator<R: Rng + 'static> {
#[builder(default)]
location: bool,
#[builder(default = "Box::new(WordGenerator)")]
name_generator: Box<dyn Random<String, R>>,
name_generator: Box<dyn Random<Ident, R>>,
#[builder(default = "Box::new(column_options_generator)")]
column_options_generator: ColumnOptionGenerator<R>,
#[builder(default = "Box::new(ColumnTypeGenerator)")]
Expand Down Expand Up @@ -74,7 +74,7 @@ impl<R: Rng + 'static> Generator<AlterTableExpr, R> for AlterExprAddColumnGenera
)
.remove(0);
Ok(AlterTableExpr {
table_name: self.table_ctx.name.to_string(),
table_name: self.table_ctx.name.clone(),
alter_options: AlterTableOperation::AddColumn { column, location },
})
}
Expand All @@ -95,11 +95,9 @@ impl<R: Rng> Generator<AlterTableExpr, R> for AlterExprDropColumnGenerator<R> {
fn generate(&self, rng: &mut R) -> Result<AlterTableExpr> {
let droppable = droppable_columns(&self.table_ctx.columns);
ensure!(!droppable.is_empty(), error::DroppableColumnsSnafu);
let name = droppable[rng.gen_range(0..droppable.len())]
.name
.to_string();
let name = droppable[rng.gen_range(0..droppable.len())].name.clone();
Ok(AlterTableExpr {
table_name: self.table_ctx.name.to_string(),
table_name: self.table_ctx.name.clone(),
alter_options: AlterTableOperation::DropColumn { name },
})
}
Expand All @@ -111,7 +109,7 @@ impl<R: Rng> Generator<AlterTableExpr, R> for AlterExprDropColumnGenerator<R> {
pub struct AlterExprRenameGenerator<R: Rng> {
table_ctx: TableContextRef,
#[builder(default = "Box::new(WordGenerator)")]
name_generator: Box<dyn Random<String, R>>,
name_generator: Box<dyn Random<Ident, R>>,
}

impl<R: Rng> Generator<AlterTableExpr, R> for AlterExprRenameGenerator<R> {
Expand All @@ -120,7 +118,7 @@ impl<R: Rng> Generator<AlterTableExpr, R> for AlterExprRenameGenerator<R> {
fn generate(&self, rng: &mut R) -> Result<AlterTableExpr> {
let new_table_name = self.name_generator.gen(rng);
Ok(AlterTableExpr {
table_name: self.table_ctx.name.to_string(),
table_name: self.table_ctx.name.clone(),
alter_options: AlterTableOperation::RenameTable { new_table_name },
})
}
Expand Down Expand Up @@ -155,7 +153,7 @@ mod tests {
.generate(&mut rng)
.unwrap();
let serialized = serde_json::to_string(&expr).unwrap();
let expected = r#"{"table_name":"animI","alter_options":{"AddColumn":{"column":{"name":"velit","column_type":{"Int32":{}},"options":[{"DefaultValue":{"Int32":853246610}}]},"location":null}}}"#;
let expected = r#"{"table_name":{"value":"animI","quote_style":null},"alter_options":{"AddColumn":{"column":{"name":{"value":"velit","quote_style":null},"column_type":{"Int32":{}},"options":[{"DefaultValue":{"Int32":853246610}}]},"location":null}}}"#;
assert_eq!(expected, serialized);

let expr = AlterExprRenameGeneratorBuilder::default()
Expand All @@ -165,8 +163,7 @@ mod tests {
.generate(&mut rng)
.unwrap();
let serialized = serde_json::to_string(&expr).unwrap();
let expected =
r#"{"table_name":"animI","alter_options":{"RenameTable":{"new_table_name":"iure"}}}"#;
let expected = r#"{"table_name":{"value":"animI","quote_style":null},"alter_options":{"RenameTable":{"new_table_name":{"value":"iure","quote_style":null}}}}"#;
assert_eq!(expected, serialized);

let expr = AlterExprDropColumnGeneratorBuilder::default()
Expand All @@ -176,7 +173,7 @@ mod tests {
.generate(&mut rng)
.unwrap();
let serialized = serde_json::to_string(&expr).unwrap();
let expected = r#"{"table_name":"animI","alter_options":{"DropColumn":{"name":"toTAm"}}}"#;
let expected = r#"{"table_name":{"value":"animI","quote_style":null},"alter_options":{"DropColumn":{"name":{"value":"toTAm","quote_style":null}}}}"#;
assert_eq!(expected, serialized);
}
}
20 changes: 13 additions & 7 deletions tests-fuzz/src/generator/create_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ use crate::ir::create_expr::CreateTableExprBuilder;
use crate::ir::{
column_options_generator, generate_columns, generate_random_value,
partible_column_options_generator, ts_column_options_generator, ColumnTypeGenerator,
CreateTableExpr, PartibleColumnTypeGenerator, TsColumnTypeGenerator,
CreateTableExpr, Ident, PartibleColumnTypeGenerator, TsColumnTypeGenerator,
};

#[derive(Builder)]
Expand All @@ -39,7 +39,7 @@ pub struct CreateTableExprGenerator<R: Rng + 'static> {
if_not_exists: bool,
#[builder(setter(into))]
name: String,
name_generator: Box<dyn Random<String, R>>,
name_generator: Box<dyn Random<Ident, R>>,
ts_column_type_generator: ConcreteDataTypeGenerator<R>,
column_type_generator: ConcreteDataTypeGenerator<R>,
partible_column_type_generator: ConcreteDataTypeGenerator<R>,
Expand Down Expand Up @@ -93,7 +93,7 @@ impl<R: Rng + 'static> Generator<CreateTableExpr, R> for CreateTableExprGenerato
let name = column_names.pop().unwrap();
let column = generate_columns(
rng,
vec![name.to_string()],
vec![name.clone()],
self.ts_column_type_generator.as_ref(),
self.ts_column_options_generator.as_ref(),
)
Expand All @@ -111,7 +111,10 @@ impl<R: Rng + 'static> Generator<CreateTableExpr, R> for CreateTableExprGenerato
partition_bounds.sort();
}
partition_bounds.push(PartitionBound::MaxValue);
builder.partition(PartitionDef::new(vec![name], partition_bounds));
builder.partition(PartitionDef::new(
vec![name.value.to_string()],
partition_bounds,
));
}

columns.push(column);
Expand All @@ -122,7 +125,7 @@ impl<R: Rng + 'static> Generator<CreateTableExpr, R> for CreateTableExprGenerato
let name = column_names.pop().unwrap();
let column = generate_columns(
rng,
vec![name.to_string()],
vec![name.clone()],
self.partible_column_type_generator.as_ref(),
self.partible_column_options_generator.as_ref(),
)
Expand All @@ -139,7 +142,10 @@ impl<R: Rng + 'static> Generator<CreateTableExpr, R> for CreateTableExprGenerato
partition_bounds.sort();
}
partition_bounds.push(PartitionBound::MaxValue);
builder.partition(PartitionDef::new(vec![name], partition_bounds));
builder.partition(PartitionDef::new(
vec![name.value.to_string()],
partition_bounds,
));
columns.push(column);
}
// Generates the ts column.
Expand Down Expand Up @@ -230,7 +236,7 @@ mod tests {
.unwrap();

let serialized = serde_json::to_string(&expr).unwrap();
let expected = r#"{"table_name":"tEmporIbUS","columns":[{"name":"IMpEdIT","column_type":{"String":null},"options":["PrimaryKey","NotNull"]},{"name":"natuS","column_type":{"Timestamp":{"Nanosecond":null}},"options":["TimeIndex"]},{"name":"ADIPisCI","column_type":{"Int16":{}},"options":[{"DefaultValue":{"Int16":4864}}]},{"name":"EXpEdita","column_type":{"Int64":{}},"options":["PrimaryKey"]},{"name":"cUlpA","column_type":{"Float64":{}},"options":["NotNull"]},{"name":"MOLeStIAs","column_type":{"Boolean":null},"options":["Null"]},{"name":"cUmquE","column_type":{"Float32":{}},"options":[{"DefaultValue":{"Float32":0.21569687}}]},{"name":"toTAm","column_type":{"Float64":{}},"options":["NotNull"]},{"name":"deBitIs","column_type":{"Float32":{}},"options":["Null"]},{"name":"QUi","column_type":{"Int64":{}},"options":["Null"]}],"if_not_exists":true,"partition":{"partition_columns":["IMpEdIT"],"partition_bounds":[{"Value":{"String":"򟘲"}},{"Value":{"String":"򴥫"}},"MaxValue"]},"engine":"mito2","options":{},"primary_keys":[0,3]}"#;
let expected = r#"{"table_name":{"value":"tEmporIbUS","quote_style":null},"columns":[{"name":{"value":"IMpEdIT","quote_style":null},"column_type":{"String":null},"options":["PrimaryKey","NotNull"]},{"name":{"value":"natuS","quote_style":null},"column_type":{"Timestamp":{"Nanosecond":null}},"options":["TimeIndex"]},{"name":{"value":"ADIPisCI","quote_style":null},"column_type":{"Int16":{}},"options":[{"DefaultValue":{"Int16":4864}}]},{"name":{"value":"EXpEdita","quote_style":null},"column_type":{"Int64":{}},"options":["PrimaryKey"]},{"name":{"value":"cUlpA","quote_style":null},"column_type":{"Float64":{}},"options":["NotNull"]},{"name":{"value":"MOLeStIAs","quote_style":null},"column_type":{"Boolean":null},"options":["Null"]},{"name":{"value":"cUmquE","quote_style":null},"column_type":{"Float32":{}},"options":[{"DefaultValue":{"Float32":0.21569687}}]},{"name":{"value":"toTAm","quote_style":null},"column_type":{"Float64":{}},"options":["NotNull"]},{"name":{"value":"deBitIs","quote_style":null},"column_type":{"Float32":{}},"options":["Null"]},{"name":{"value":"QUi","quote_style":null},"column_type":{"Int64":{}},"options":["Null"]}],"if_not_exists":true,"partition":{"partition_columns":["IMpEdIT"],"partition_bounds":[{"Value":{"String":"򟘲"}},{"Value":{"String":"򴥫"}},"MaxValue"]},"engine":"mito2","options":{},"primary_keys":[0,3]}"#;
assert_eq!(expected, serialized);
}
}
4 changes: 2 additions & 2 deletions tests-fuzz/src/generator/insert_expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@ use crate::context::TableContextRef;
use crate::error::{Error, Result};
use crate::fake::WordGenerator;
use crate::generator::{Generator, Random};
use crate::ir::generate_random_value;
use crate::ir::insert_expr::InsertIntoExpr;
use crate::ir::{generate_random_value, Ident};

/// Generates [InsertIntoExpr].
#[derive(Builder)]
Expand All @@ -33,7 +33,7 @@ pub struct InsertExprGenerator<R: Rng + 'static> {
#[builder(default = "1")]
rows: usize,
#[builder(default = "Box::new(WordGenerator)")]
word_generator: Box<dyn Random<String, R>>,
word_generator: Box<dyn Random<Ident, R>>,
#[builder(default)]
_phantom: PhantomData<R>,
}
Expand Down

0 comments on commit 3f3ef2e

Please sign in to comment.