From f99b08796dadeda187a29f0e6aaab99d6607fe3a Mon Sep 17 00:00:00 2001 From: Weny Xu Date: Fri, 26 Jan 2024 11:59:17 +0900 Subject: [PATCH] feat: add insert/select generator & translator (#3240) * feat: add insert into expr generator & translator * feat: add select expr generator & translator * chore: apply suggestions from CR * fix: fix unit tests --- tests-fuzz/src/context.rs | 2 +- tests-fuzz/src/generator.rs | 2 + tests-fuzz/src/generator/alter_expr.rs | 12 +-- tests-fuzz/src/generator/create_expr.rs | 8 +- tests-fuzz/src/generator/insert_expr.rs | 70 ++++++++++++++ tests-fuzz/src/generator/select_expr.rs | 72 ++++++++++++++ tests-fuzz/src/ir.rs | 17 +++- tests-fuzz/src/ir/alter_expr.rs | 2 +- tests-fuzz/src/ir/create_expr.rs | 2 +- tests-fuzz/src/ir/insert_expr.rs | 25 +++++ tests-fuzz/src/ir/select_expr.rs | 39 ++++++++ tests-fuzz/src/lib.rs | 3 + tests-fuzz/src/test_utils.rs | 59 ++++++++++++ tests-fuzz/src/translator/mysql.rs | 2 + tests-fuzz/src/translator/mysql/alter_expr.rs | 12 +-- .../src/translator/mysql/create_expr.rs | 43 ++------- .../src/translator/mysql/insert_expr.rs | 93 +++++++++++++++++++ .../src/translator/mysql/select_expr.rs | 75 +++++++++++++++ .../src/translator/postgres/alter_expr.rs | 12 +-- .../src/translator/postgres/create_expr.rs | 2 +- 20 files changed, 487 insertions(+), 65 deletions(-) create mode 100644 tests-fuzz/src/generator/insert_expr.rs create mode 100644 tests-fuzz/src/generator/select_expr.rs create mode 100644 tests-fuzz/src/ir/insert_expr.rs create mode 100644 tests-fuzz/src/ir/select_expr.rs create mode 100644 tests-fuzz/src/test_utils.rs create mode 100644 tests-fuzz/src/translator/mysql/insert_expr.rs create mode 100644 tests-fuzz/src/translator/mysql/select_expr.rs diff --git a/tests-fuzz/src/context.rs b/tests-fuzz/src/context.rs index d7fd747a9739..8137b4b20a73 100644 --- a/tests-fuzz/src/context.rs +++ b/tests-fuzz/src/context.rs @@ -33,7 +33,7 @@ pub struct TableContext { impl From<&CreateTableExpr> for TableContext { fn from( CreateTableExpr { - name, + table_name: name, columns, partition, primary_keys, diff --git a/tests-fuzz/src/generator.rs b/tests-fuzz/src/generator.rs index c5f7d2104ffa..b2284e7927da 100644 --- a/tests-fuzz/src/generator.rs +++ b/tests-fuzz/src/generator.rs @@ -14,6 +14,8 @@ pub mod alter_expr; pub mod create_expr; +pub mod insert_expr; +pub mod select_expr; use std::fmt; diff --git a/tests-fuzz/src/generator/alter_expr.rs b/tests-fuzz/src/generator/alter_expr.rs index 3944a05286d6..aff122133077 100644 --- a/tests-fuzz/src/generator/alter_expr.rs +++ b/tests-fuzz/src/generator/alter_expr.rs @@ -74,7 +74,7 @@ impl Generator for AlterExprAddColumnGenera ) .remove(0); Ok(AlterTableExpr { - name: self.table_ctx.name.to_string(), + table_name: self.table_ctx.name.to_string(), alter_options: AlterTableOperation::AddColumn { column, location }, }) } @@ -99,7 +99,7 @@ impl Generator for AlterExprDropColumnGenerator { .name .to_string(); Ok(AlterTableExpr { - name: self.table_ctx.name.to_string(), + table_name: self.table_ctx.name.to_string(), alter_options: AlterTableOperation::DropColumn { name }, }) } @@ -120,7 +120,7 @@ impl Generator for AlterExprRenameGenerator { fn generate(&self, rng: &mut R) -> Result { let new_table_name = self.name_generator.gen(rng); Ok(AlterTableExpr { - name: self.table_ctx.name.to_string(), + table_name: self.table_ctx.name.to_string(), alter_options: AlterTableOperation::RenameTable { new_table_name }, }) } @@ -155,7 +155,7 @@ mod tests { .generate(&mut rng) .unwrap(); let serialized = serde_json::to_string(&expr).unwrap(); - let expected = r#"{"name":"DigNissIMOS","alter_options":{"AddColumn":{"column":{"name":"sit","column_type":{"Boolean":null},"options":["PrimaryKey"]},"location":null}}}"#; + let expected = r#"{"table_name":"DigNissIMOS","alter_options":{"AddColumn":{"column":{"name":"sit","column_type":{"Boolean":null},"options":["PrimaryKey"]},"location":null}}}"#; assert_eq!(expected, serialized); let expr = AlterExprRenameGeneratorBuilder::default() @@ -165,7 +165,7 @@ mod tests { .generate(&mut rng) .unwrap(); let serialized = serde_json::to_string(&expr).unwrap(); - let expected = r#"{"name":"DigNissIMOS","alter_options":{"RenameTable":{"new_table_name":"excepturi"}}}"#; + let expected = r#"{"table_name":"DigNissIMOS","alter_options":{"RenameTable":{"new_table_name":"excepturi"}}}"#; assert_eq!(expected, serialized); let expr = AlterExprDropColumnGeneratorBuilder::default() @@ -176,7 +176,7 @@ mod tests { .unwrap(); let serialized = serde_json::to_string(&expr).unwrap(); let expected = - r#"{"name":"DigNissIMOS","alter_options":{"DropColumn":{"name":"INVentORE"}}}"#; + r#"{"table_name":"DigNissIMOS","alter_options":{"DropColumn":{"name":"INVentORE"}}}"#; assert_eq!(expected, serialized); } } diff --git a/tests-fuzz/src/generator/create_expr.rs b/tests-fuzz/src/generator/create_expr.rs index ae506e650128..1ea56f92790e 100644 --- a/tests-fuzz/src/generator/create_expr.rs +++ b/tests-fuzz/src/generator/create_expr.rs @@ -106,6 +106,7 @@ impl Generator for CreateTableExprGenerato partition_bounds.push(PartitionBound::Value(generate_random_value( rng, &column.column_type, + None, ))); partition_bounds.sort(); } @@ -133,6 +134,7 @@ impl Generator for CreateTableExprGenerato partition_bounds.push(PartitionBound::Value(generate_random_value( rng, &column.column_type, + None, ))); partition_bounds.sort(); } @@ -171,9 +173,9 @@ impl Generator for CreateTableExprGenerato builder.engine(self.engine.to_string()); builder.if_not_exists(self.if_not_exists); if self.name.is_empty() { - builder.name(self.name_generator.gen(rng)); + builder.table_name(self.name_generator.gen(rng)); } else { - builder.name(self.name.to_string()); + builder.table_name(self.name.to_string()); } builder.build().context(error::BuildCreateTableExprSnafu) } @@ -228,7 +230,7 @@ mod tests { .unwrap(); let serialized = serde_json::to_string(&expr).unwrap(); - let expected = r#"{"name":"iN","columns":[{"name":"CUlpa","column_type":{"Int16":{}},"options":["PrimaryKey","NotNull"]},{"name":"dEBiTiS","column_type":{"Timestamp":{"Second":null}},"options":["TimeIndex"]},{"name":"HArum","column_type":{"Int16":{}},"options":["NotNull"]},{"name":"NObIS","column_type":{"Int32":{}},"options":["PrimaryKey"]},{"name":"IMPEDiT","column_type":{"Int16":{}},"options":[{"DefaultValue":{"Int16":-25151}}]},{"name":"bLanDITIis","column_type":{"Boolean":null},"options":[{"DefaultValue":{"Boolean":true}}]},{"name":"Dolores","column_type":{"Float32":{}},"options":["PrimaryKey"]},{"name":"eSt","column_type":{"Float32":{}},"options":[{"DefaultValue":{"Float32":0.9152612}}]},{"name":"INVentORE","column_type":{"Int64":{}},"options":["PrimaryKey"]},{"name":"aDIpiSci","column_type":{"Float64":{}},"options":["Null"]}],"if_not_exists":true,"partition":{"partition_columns":["CUlpa"],"partition_bounds":[{"Value":{"Int16":15966}},{"Value":{"Int16":31925}},"MaxValue"]},"engine":"mito2","options":{},"primary_keys":[6,0,8,3]}"#; + let expected = r#"{"table_name":"iN","columns":[{"name":"CUlpa","column_type":{"Int16":{}},"options":["PrimaryKey","NotNull"]},{"name":"dEBiTiS","column_type":{"Timestamp":{"Second":null}},"options":["TimeIndex"]},{"name":"HArum","column_type":{"Int16":{}},"options":["NotNull"]},{"name":"NObIS","column_type":{"Int32":{}},"options":["PrimaryKey"]},{"name":"IMPEDiT","column_type":{"Int16":{}},"options":[{"DefaultValue":{"Int16":-25151}}]},{"name":"bLanDITIis","column_type":{"Boolean":null},"options":[{"DefaultValue":{"Boolean":true}}]},{"name":"Dolores","column_type":{"Float32":{}},"options":["PrimaryKey"]},{"name":"eSt","column_type":{"Float32":{}},"options":[{"DefaultValue":{"Float32":0.9152612}}]},{"name":"INVentORE","column_type":{"Int64":{}},"options":["PrimaryKey"]},{"name":"aDIpiSci","column_type":{"Float64":{}},"options":["Null"]}],"if_not_exists":true,"partition":{"partition_columns":["CUlpa"],"partition_bounds":[{"Value":{"Int16":15966}},{"Value":{"Int16":31925}},"MaxValue"]},"engine":"mito2","options":{},"primary_keys":[6,0,8,3]}"#; assert_eq!(expected, serialized); } } diff --git a/tests-fuzz/src/generator/insert_expr.rs b/tests-fuzz/src/generator/insert_expr.rs new file mode 100644 index 000000000000..51e4cea184d2 --- /dev/null +++ b/tests-fuzz/src/generator/insert_expr.rs @@ -0,0 +1,70 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::marker::PhantomData; + +use derive_builder::Builder; +use rand::seq::SliceRandom; +use rand::Rng; + +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; + +/// Generates [InsertIntoExpr]. +#[derive(Builder)] +#[builder(pattern = "owned")] +pub struct InsertExprGenerator { + table_ctx: TableContextRef, + #[builder(default = "1")] + rows: usize, + #[builder(default = "Box::new(WordGenerator)")] + word_generator: Box>, + #[builder(default)] + _phantom: PhantomData, +} + +impl Generator for InsertExprGenerator { + type Error = Error; + + /// Generates the [CreateTableExpr]. + fn generate(&self, rng: &mut R) -> Result { + let mut columns = self.table_ctx.columns.clone(); + columns.shuffle(rng); + + let mut rows = Vec::with_capacity(self.rows); + for _ in 0..self.rows { + let mut row = Vec::with_capacity(columns.len()); + for column in &columns { + // TODO(weny): generates the special cases + row.push(generate_random_value( + rng, + &column.column_type, + Some(self.word_generator.as_ref()), + )); + } + + rows.push(row); + } + + Ok(InsertIntoExpr { + table_name: self.table_ctx.name.to_string(), + columns, + rows, + }) + } +} diff --git a/tests-fuzz/src/generator/select_expr.rs b/tests-fuzz/src/generator/select_expr.rs new file mode 100644 index 000000000000..8627b1840781 --- /dev/null +++ b/tests-fuzz/src/generator/select_expr.rs @@ -0,0 +1,72 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::marker::PhantomData; + +use derive_builder::Builder; +use rand::seq::SliceRandom; +use rand::Rng; + +use crate::context::TableContextRef; +use crate::error::{Error, Result}; +use crate::generator::Generator; +use crate::ir::select_expr::{Direction, SelectExpr}; + +#[derive(Builder)] +#[builder(pattern = "owned")] +pub struct SelectExprGenerator { + table_ctx: TableContextRef, + #[builder(default = "8192")] + max_limit: usize, + #[builder(default)] + _phantom: PhantomData, +} + +impl Generator for SelectExprGenerator { + type Error = Error; + + fn generate(&self, rng: &mut R) -> Result { + let selection = rng.gen_range(1..self.table_ctx.columns.len()); + let mut selected_columns = self + .table_ctx + .columns + .choose_multiple(rng, selection) + .cloned() + .collect::>(); + selected_columns.shuffle(rng); + + let order_by_selection = rng.gen_range(1..selection); + + let order_by = selected_columns + .choose_multiple(rng, order_by_selection) + .map(|c| c.name.to_string()) + .collect::>(); + + let limit = rng.gen_range(1..self.max_limit); + + let direction = if rng.gen_bool(1.0 / 2.0) { + Direction::Asc + } else { + Direction::Desc + }; + + Ok(SelectExpr { + table_name: self.table_ctx.name.to_string(), + columns: selected_columns, + order_by, + direction, + limit, + }) + } +} diff --git a/tests-fuzz/src/ir.rs b/tests-fuzz/src/ir.rs index 92db3d26d1c6..0f4862d75581 100644 --- a/tests-fuzz/src/ir.rs +++ b/tests-fuzz/src/ir.rs @@ -16,6 +16,8 @@ pub(crate) mod alter_expr; pub(crate) mod create_expr; +pub(crate) mod insert_expr; +pub(crate) mod select_expr; pub use alter_expr::AlterTableExpr; pub use create_expr::CreateTableExpr; @@ -71,7 +73,11 @@ pub struct TsColumnTypeGenerator; pub struct PartibleColumnTypeGenerator; /// Generates a random [Value]. -pub fn generate_random_value(rng: &mut R, datatype: &ConcreteDataType) -> Value { +pub fn generate_random_value( + rng: &mut R, + datatype: &ConcreteDataType, + random_str: Option<&dyn Random>, +) -> Value { match datatype { &ConcreteDataType::Boolean(_) => Value::from(rng.gen::()), ConcreteDataType::Int16(_) => Value::from(rng.gen::()), @@ -79,9 +85,13 @@ pub fn generate_random_value(rng: &mut R, datatype: &ConcreteDataType) - ConcreteDataType::Int64(_) => Value::from(rng.gen::()), ConcreteDataType::Float32(_) => Value::from(rng.gen::()), ConcreteDataType::Float64(_) => Value::from(rng.gen::()), - ConcreteDataType::String(_) => Value::from(rng.gen::().to_string()), + ConcreteDataType::String(_) => match random_str { + Some(random) => Value::from(random.gen(rng)), + None => Value::from(rng.gen::().to_string()), + }, ConcreteDataType::Date(_) => Value::from(rng.gen::()), ConcreteDataType::DateTime(_) => Value::from(rng.gen::()), + &ConcreteDataType::Timestamp(_) => Value::from(rng.gen::()), _ => unimplemented!("unsupported type: {datatype}"), } @@ -142,6 +152,7 @@ pub fn column_options_generator( 2 => vec![ColumnOption::DefaultValue(generate_random_value( rng, column_type, + None, ))], 3 => vec![ColumnOption::PrimaryKey], _ => vec![], @@ -163,7 +174,7 @@ pub fn partible_column_options_generator( 1 => vec![ColumnOption::PrimaryKey, ColumnOption::NotNull], 2 => vec![ ColumnOption::PrimaryKey, - ColumnOption::DefaultValue(generate_random_value(rng, column_type)), + ColumnOption::DefaultValue(generate_random_value(rng, column_type, None)), ], 3 => vec![ColumnOption::PrimaryKey], _ => unreachable!(), diff --git a/tests-fuzz/src/ir/alter_expr.rs b/tests-fuzz/src/ir/alter_expr.rs index 64cc3d0d9c08..1fa808c83372 100644 --- a/tests-fuzz/src/ir/alter_expr.rs +++ b/tests-fuzz/src/ir/alter_expr.rs @@ -20,7 +20,7 @@ use crate::ir::Column; #[derive(Debug, Builder, Clone, Serialize, Deserialize)] pub struct AlterTableExpr { - pub name: String, + pub table_name: String, pub alter_options: AlterTableOperation, } diff --git a/tests-fuzz/src/ir/create_expr.rs b/tests-fuzz/src/ir/create_expr.rs index be7fabed2c56..8a1b971efc3f 100644 --- a/tests-fuzz/src/ir/create_expr.rs +++ b/tests-fuzz/src/ir/create_expr.rs @@ -50,7 +50,7 @@ impl Display for ColumnOption { #[derive(Debug, Builder, Clone, Serialize, Deserialize)] pub struct CreateTableExpr { #[builder(setter(into))] - pub name: String, + pub table_name: String, pub columns: Vec, #[builder(default)] pub if_not_exists: bool, diff --git a/tests-fuzz/src/ir/insert_expr.rs b/tests-fuzz/src/ir/insert_expr.rs new file mode 100644 index 000000000000..8fc411338449 --- /dev/null +++ b/tests-fuzz/src/ir/insert_expr.rs @@ -0,0 +1,25 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use datatypes::value::Value; + +use crate::ir::Column; + +pub type RowValue = Vec; + +pub struct InsertIntoExpr { + pub table_name: String, + pub columns: Vec, + pub rows: Vec, +} diff --git a/tests-fuzz/src/ir/select_expr.rs b/tests-fuzz/src/ir/select_expr.rs new file mode 100644 index 000000000000..3abb7e94d3c5 --- /dev/null +++ b/tests-fuzz/src/ir/select_expr.rs @@ -0,0 +1,39 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use std::fmt::Display; + +use crate::ir::Column; + +pub enum Direction { + Asc, + Desc, +} + +impl Display for Direction { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + Direction::Asc => write!(f, "ASC"), + Direction::Desc => write!(f, "DESC"), + } + } +} + +pub struct SelectExpr { + pub table_name: String, + pub columns: Vec, + pub order_by: Vec, + pub direction: Direction, + pub limit: usize, +} diff --git a/tests-fuzz/src/lib.rs b/tests-fuzz/src/lib.rs index 9d4a435cbb35..5c5ba00533b1 100644 --- a/tests-fuzz/src/lib.rs +++ b/tests-fuzz/src/lib.rs @@ -21,3 +21,6 @@ pub mod fake; pub mod generator; pub mod ir; pub mod translator; + +#[cfg(test)] +pub mod test_utils; diff --git a/tests-fuzz/src/test_utils.rs b/tests-fuzz/src/test_utils.rs new file mode 100644 index 000000000000..04480aadb3c5 --- /dev/null +++ b/tests-fuzz/src/test_utils.rs @@ -0,0 +1,59 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use datatypes::data_type::ConcreteDataType; + +use crate::context::TableContext; +use crate::ir::create_expr::ColumnOption; +use crate::ir::Column; + +pub fn new_test_ctx() -> TableContext { + TableContext { + name: "test".to_string(), + columns: vec![ + Column { + name: "host".to_string(), + column_type: ConcreteDataType::string_datatype(), + options: vec![ColumnOption::PrimaryKey], + }, + Column { + name: "idc".to_string(), + column_type: ConcreteDataType::string_datatype(), + options: vec![ColumnOption::PrimaryKey], + }, + Column { + name: "cpu_util".to_string(), + column_type: ConcreteDataType::float64_datatype(), + options: vec![], + }, + Column { + name: "memory_util".to_string(), + column_type: ConcreteDataType::float64_datatype(), + options: vec![], + }, + Column { + name: "disk_util".to_string(), + column_type: ConcreteDataType::float64_datatype(), + options: vec![], + }, + Column { + name: "ts".to_string(), + column_type: ConcreteDataType::timestamp_millisecond_datatype(), + options: vec![ColumnOption::TimeIndex], + }, + ], + partition: None, + primary_keys: vec![], + } +} diff --git a/tests-fuzz/src/translator/mysql.rs b/tests-fuzz/src/translator/mysql.rs index 6a86b3fff17e..0c2498a3218b 100644 --- a/tests-fuzz/src/translator/mysql.rs +++ b/tests-fuzz/src/translator/mysql.rs @@ -14,3 +14,5 @@ pub mod alter_expr; pub mod create_expr; +pub mod insert_expr; +pub mod select_expr; diff --git a/tests-fuzz/src/translator/mysql/alter_expr.rs b/tests-fuzz/src/translator/mysql/alter_expr.rs index d08c7fc0a76c..750fb37e45cb 100644 --- a/tests-fuzz/src/translator/mysql/alter_expr.rs +++ b/tests-fuzz/src/translator/mysql/alter_expr.rs @@ -30,11 +30,11 @@ impl DslTranslator for AlterTableExprTranslator { fn translate(&self, input: &AlterTableExpr) -> Result { Ok(match &input.alter_options { AlterTableOperation::AddColumn { column, location } => { - Self::format_add_column(&input.name, column, location) + Self::format_add_column(&input.table_name, column, location) } - AlterTableOperation::DropColumn { name } => Self::format_drop(&input.name, name), + AlterTableOperation::DropColumn { name } => Self::format_drop(&input.table_name, name), AlterTableOperation::RenameTable { new_table_name } => { - Self::format_rename(&input.name, new_table_name) + Self::format_rename(&input.table_name, new_table_name) } }) } @@ -119,7 +119,7 @@ mod tests { #[test] fn test_alter_table_expr() { let alter_expr = AlterTableExpr { - name: "test".to_string(), + table_name: "test".to_string(), alter_options: AlterTableOperation::AddColumn { column: Column { name: "host".to_string(), @@ -137,7 +137,7 @@ mod tests { ); let alter_expr = AlterTableExpr { - name: "test".to_string(), + table_name: "test".to_string(), alter_options: AlterTableOperation::RenameTable { new_table_name: "foo".to_string(), }, @@ -147,7 +147,7 @@ mod tests { assert_eq!("ALTER TABLE test RENAME foo;", output); let alter_expr = AlterTableExpr { - name: "test".to_string(), + table_name: "test".to_string(), alter_options: AlterTableOperation::DropColumn { name: "foo".to_string(), }, diff --git a/tests-fuzz/src/translator/mysql/create_expr.rs b/tests-fuzz/src/translator/mysql/create_expr.rs index a32567353de9..c5fa04d0ae77 100644 --- a/tests-fuzz/src/translator/mysql/create_expr.rs +++ b/tests-fuzz/src/translator/mysql/create_expr.rs @@ -31,7 +31,7 @@ impl DslTranslator for CreateTableExprTranslator { Ok(format!( "CREATE TABLE{}{}(\n{}\n)\n{};", Self::create_if_not_exists(input), - input.name, + input.table_name, Self::format_columns(input), Self::format_table_options(input) )) @@ -149,51 +149,20 @@ impl CreateTableExprTranslator { #[cfg(test)] mod tests { - use datatypes::data_type::ConcreteDataType; use datatypes::value::Value; use partition::partition::{PartitionBound, PartitionDef}; use super::CreateTableExprTranslator; - use crate::ir::create_expr::{ColumnOption, CreateTableExprBuilder}; - use crate::ir::Column; + use crate::ir::create_expr::CreateTableExprBuilder; + use crate::test_utils; use crate::translator::DslTranslator; #[test] fn test_create_table_expr_translator() { + let test_ctx = test_utils::new_test_ctx(); let create_table_expr = CreateTableExprBuilder::default() - .columns(vec![ - Column { - name: "host".to_string(), - column_type: ConcreteDataType::string_datatype(), - options: vec![ColumnOption::PrimaryKey], - }, - Column { - name: "idc".to_string(), - column_type: ConcreteDataType::string_datatype(), - options: vec![ColumnOption::PrimaryKey], - }, - Column { - name: "cpu_util".to_string(), - column_type: ConcreteDataType::float64_datatype(), - options: vec![], - }, - Column { - name: "memory_util".to_string(), - column_type: ConcreteDataType::float64_datatype(), - options: vec![], - }, - Column { - name: "disk_util".to_string(), - column_type: ConcreteDataType::float64_datatype(), - options: vec![], - }, - Column { - name: "ts".to_string(), - column_type: ConcreteDataType::timestamp_millisecond_datatype(), - options: vec![ColumnOption::TimeIndex], - }, - ]) - .name("system_metrics") + .columns(test_ctx.columns.clone()) + .table_name("system_metrics") .engine("mito") .primary_keys(vec![0, 1]) .partition(PartitionDef::new( diff --git a/tests-fuzz/src/translator/mysql/insert_expr.rs b/tests-fuzz/src/translator/mysql/insert_expr.rs new file mode 100644 index 000000000000..d81aa08b98a7 --- /dev/null +++ b/tests-fuzz/src/translator/mysql/insert_expr.rs @@ -0,0 +1,93 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::error::{Error, Result}; +use crate::ir::insert_expr::InsertIntoExpr; +use crate::translator::DslTranslator; + +pub struct InsertIntoExprTranslator; + +impl DslTranslator for InsertIntoExprTranslator { + type Error = Error; + + fn translate(&self, input: &InsertIntoExpr) -> Result { + let columns = input + .columns + .iter() + .map(|c| c.name.as_str()) + .collect::>() + .join(", ") + .to_string(); + + Ok(format!( + "INSERT INTO {} ({})\nVALUES\n{};", + input.table_name, + columns, + Self::format_values(input) + )) + } +} + +impl InsertIntoExprTranslator { + fn format_values(input: &InsertIntoExpr) -> String { + input + .rows + .iter() + .map(|row| { + format!( + "({})", + row.iter() + .map(|v| format!("'{v}'")) + .collect::>() + .join(", ") + ) + }) + .collect::>() + .join(",\n") + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use rand::SeedableRng; + + use super::InsertIntoExprTranslator; + use crate::generator::insert_expr::InsertExprGeneratorBuilder; + use crate::generator::Generator; + use crate::test_utils; + use crate::translator::DslTranslator; + + #[test] + fn test_insert_into_translator() { + let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0); + + let test_ctx = test_utils::new_test_ctx(); + let insert_expr_generator = InsertExprGeneratorBuilder::default() + .table_ctx(Arc::new(test_ctx)) + .rows(2) + .build() + .unwrap(); + + let insert_expr = insert_expr_generator.generate(&mut rng).unwrap(); + + let output = InsertIntoExprTranslator.translate(&insert_expr).unwrap(); + let expected = r#"INSERT INTO test (host, idc, memory_util, ts, cpu_util, disk_util) +VALUES +('adipisci', 'debitis', '0.5495312687894465', '15292064470292927036', '0.9354265029131291', '0.8037816422279636'), +('ut', 'sequi', '0.8807117723618908', '14214208091261382505', '0.5240550121500691', '0.350785883750684');"#; + assert_eq!(output, expected); + } +} diff --git a/tests-fuzz/src/translator/mysql/select_expr.rs b/tests-fuzz/src/translator/mysql/select_expr.rs new file mode 100644 index 000000000000..6a246892dff8 --- /dev/null +++ b/tests-fuzz/src/translator/mysql/select_expr.rs @@ -0,0 +1,75 @@ +// Copyright 2023 Greptime Team +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +use crate::error::{Error, Result}; +use crate::ir::select_expr::SelectExpr; +use crate::translator::DslTranslator; + +pub struct SelectExprTranslator; + +impl DslTranslator for SelectExprTranslator { + type Error = Error; + + fn translate(&self, input: &SelectExpr) -> Result { + let columns = input + .columns + .iter() + .map(|c| c.name.as_str()) + .collect::>() + .join(", ") + .to_string(); + + let order_by = input + .order_by + .iter() + .map(|c| c.as_str()) + .collect::>() + .join(", ") + .to_string(); + + Ok(format!( + "SELECT {} FROM {} ORDER BY {} {};", + columns, input.table_name, order_by, input.direction, + )) + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use rand::SeedableRng; + + use super::SelectExprTranslator; + use crate::generator::select_expr::SelectExprGeneratorBuilder; + use crate::generator::Generator; + use crate::test_utils; + use crate::translator::DslTranslator; + + #[test] + fn test_select_expr_translator() { + let mut rng = rand_chacha::ChaCha8Rng::seed_from_u64(0); + + let test_ctx = test_utils::new_test_ctx(); + let select_expr_generator = SelectExprGeneratorBuilder::default() + .table_ctx(Arc::new(test_ctx)) + .build() + .unwrap(); + + let select_expr = select_expr_generator.generate(&mut rng).unwrap(); + let output = SelectExprTranslator.translate(&select_expr).unwrap(); + let expected = r#"SELECT memory_util, ts, cpu_util, disk_util FROM test ORDER BY cpu_util, disk_util DESC;"#; + assert_eq!(output, expected); + } +} diff --git a/tests-fuzz/src/translator/postgres/alter_expr.rs b/tests-fuzz/src/translator/postgres/alter_expr.rs index 6be23e72d05d..6f067c0e137d 100644 --- a/tests-fuzz/src/translator/postgres/alter_expr.rs +++ b/tests-fuzz/src/translator/postgres/alter_expr.rs @@ -30,11 +30,11 @@ impl DslTranslator for AlterTableExprTranslator { fn translate(&self, input: &AlterTableExpr) -> Result { Ok(match &input.alter_options { AlterTableOperation::AddColumn { column, .. } => { - Self::format_add_column(&input.name, column) + Self::format_add_column(&input.table_name, column) } - AlterTableOperation::DropColumn { name } => Self::format_drop(&input.name, name), + AlterTableOperation::DropColumn { name } => Self::format_drop(&input.table_name, name), AlterTableOperation::RenameTable { new_table_name } => { - Self::format_rename(&input.name, new_table_name) + Self::format_rename(&input.table_name, new_table_name) } }) } @@ -116,7 +116,7 @@ mod tests { #[test] fn test_alter_table_expr() { let alter_expr = AlterTableExpr { - name: "test".to_string(), + table_name: "test".to_string(), alter_options: AlterTableOperation::AddColumn { column: Column { name: "host".to_string(), @@ -132,7 +132,7 @@ mod tests { assert_eq!("ALTER TABLE test ADD COLUMN host STRING;", output); let alter_expr = AlterTableExpr { - name: "test".to_string(), + table_name: "test".to_string(), alter_options: AlterTableOperation::RenameTable { new_table_name: "foo".to_string(), }, @@ -142,7 +142,7 @@ mod tests { assert_eq!("ALTER TABLE test RENAME TO foo;", output); let alter_expr = AlterTableExpr { - name: "test".to_string(), + table_name: "test".to_string(), alter_options: AlterTableOperation::DropColumn { name: "foo".to_string(), }, diff --git a/tests-fuzz/src/translator/postgres/create_expr.rs b/tests-fuzz/src/translator/postgres/create_expr.rs index d44bd9383a7b..0de021a44e51 100644 --- a/tests-fuzz/src/translator/postgres/create_expr.rs +++ b/tests-fuzz/src/translator/postgres/create_expr.rs @@ -30,7 +30,7 @@ impl DslTranslator for CreateTableExprTranslator { Ok(format!( "CREATE TABLE{}{}(\n{}\n);", Self::create_if_not_exists(input), - input.name, + input.table_name, Self::format_columns(input), )) }