diff --git a/Cargo.lock b/Cargo.lock index 6a48189586d8..a7feb579c60a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2856,6 +2856,12 @@ dependencies = [ "syn 1.0.109", ] +[[package]] +name = "deunicode" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3ae2a35373c5c74340b79ae6780b498b2b183915ec5dacf263aac5a099bf485a" + [[package]] name = "diff" version = "0.1.13" @@ -3129,6 +3135,17 @@ dependencies = [ "rand", ] +[[package]] +name = "faker_rand" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "300d2ddbf2245b5b5e723995e0961033121b4fc2be9045fb661af82bd739ffb6" +dependencies = [ + "deunicode", + "lazy_static", + "rand", +] + [[package]] name = "fallible-iterator" version = "0.2.0" @@ -9486,6 +9503,18 @@ name = "tests-fuzz" version = "0.6.0" dependencies = [ "async-trait", + "common-error", + "common-macro", + "common-query", + "datatypes", + "derive_builder 0.12.0", + "faker_rand", + "lazy_static", + "partition", + "rand", + "serde", + "snafu", + "sql", ] [[package]] diff --git a/src/partition/src/partition.rs b/src/partition/src/partition.rs index ea2d52090078..1d63277a9fd1 100644 --- a/src/partition/src/partition.rs +++ b/src/partition/src/partition.rs @@ -50,7 +50,7 @@ pub enum PartitionBound { MaxValue, } -#[derive(Debug)] +#[derive(Debug, Clone, Serialize, Deserialize)] pub struct PartitionDef { partition_columns: Vec, partition_bounds: Vec, diff --git a/tests-fuzz/Cargo.toml b/tests-fuzz/Cargo.toml index c522adda88fe..9e388029efe1 100644 --- a/tests-fuzz/Cargo.toml +++ b/tests-fuzz/Cargo.toml @@ -6,3 +6,15 @@ license.workspace = true [dependencies] async-trait = { workspace = true } +common-error = { workspace = true } +common-macro = { workspace = true } +common-query = { workspace = true } +datatypes = { workspace = true } +derive_builder = { workspace = true } +faker_rand = "0.1" +lazy_static = { workspace = true } +partition = { workspace = true } +rand = { workspace = true } +serde = { workspace = true } +snafu = { workspace = true } +sql = { workspace = true } diff --git a/tests-fuzz/src/context.rs b/tests-fuzz/src/context.rs index 59f3388c4861..b7dd014aa46a 100644 --- a/tests-fuzz/src/context.rs +++ b/tests-fuzz/src/context.rs @@ -11,3 +11,40 @@ // 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::sync::Arc; + +use partition::partition::PartitionDef; + +use crate::ir::{Column, CreateTableExpr}; + +pub type TableContextRef = Arc; + +/// TableContext stores table info. +pub struct TableContext { + pub name: String, + pub columns: Vec, + + // GreptimeDB specific options + pub partitions: Vec, + pub primary_keys: Vec, +} + +impl From<&CreateTableExpr> for TableContext { + fn from( + CreateTableExpr { + name, + columns, + partitions, + primary_keys, + .. + }: &CreateTableExpr, + ) -> Self { + Self { + name: name.to_string(), + columns: columns.clone(), + partitions: partitions.clone(), + primary_keys: primary_keys.clone(), + } + } +} diff --git a/tests-fuzz/src/error.rs b/tests-fuzz/src/error.rs new file mode 100644 index 000000000000..89fdf127716a --- /dev/null +++ b/tests-fuzz/src/error.rs @@ -0,0 +1,41 @@ +// 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 common_macro::stack_trace_debug; +use snafu::{Location, Snafu}; + +use crate::ir::create_expr::CreateTableExprBuilderError; + +pub type Result = std::result::Result; + +#[derive(Snafu)] +#[snafu(visibility(pub))] +#[stack_trace_debug] +pub enum Error { + #[snafu(display("Unexpected, violated: {violated}"))] + Unexpected { + violated: String, + location: Location, + }, + + #[snafu(display("Failed to build create table expr"))] + BuildCreateTableExpr { + #[snafu(source)] + error: CreateTableExprBuilderError, + location: Location, + }, + + #[snafu(display("No droppable columns"))] + DroppableColumns { location: Location }, +} diff --git a/tests-fuzz/src/generator.rs b/tests-fuzz/src/generator.rs index 93e8227ea753..2a10fc4e147b 100644 --- a/tests-fuzz/src/generator.rs +++ b/tests-fuzz/src/generator.rs @@ -12,11 +12,21 @@ // See the License for the specific language governing permissions and // limitations under the License. +pub mod alter_expr; +pub mod create_expr; + use std::fmt; -#[async_trait::async_trait] +use crate::error::Error; +use crate::ir::{AlterTableExpr, CreateTableExpr}; + +pub type CreateTableExprGenerator = + Box + Sync + Send>; + +pub type AlterTableExprGenerator = Box + Sync + Send>; + pub(crate) trait Generator { type Error: Sync + Send + fmt::Debug; - async fn generate(&self) -> Result; + fn generate(&self) -> Result; } diff --git a/tests-fuzz/src/generator/alter_expr.rs b/tests-fuzz/src/generator/alter_expr.rs new file mode 100644 index 000000000000..6b98443b8c99 --- /dev/null +++ b/tests-fuzz/src/generator/alter_expr.rs @@ -0,0 +1,168 @@ +// 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::f64::consts::E; +use std::sync::Arc; + +use common_query::AddColumnLocation; +use faker_rand::lorem::Word; +use rand::{random, Rng}; +use snafu::ensure; + +use crate::context::TableContextRef; +use crate::error::{self, Error, Result}; +use crate::generator::Generator; +use crate::ir::alter_expr::{AlterTableExpr, AlterTableOperation}; +use crate::ir::{droppable_columns, Column}; + +/// Generates the [AlterTableOperation::AddColumn] of [AlterTableExpr]. +pub struct AlterExprAddColumnGenerator { + table_ctx: TableContextRef, + location: bool, +} + +impl AlterExprAddColumnGenerator { + /// Returns an [AlterExprAddColumnGenerator]. + pub fn new(table_ctx: &TableContextRef) -> Self { + Self { + table_ctx: table_ctx.clone(), + location: false, + } + } + + /// Sets true to generate alter expr with a specific location. + pub fn with_location(mut self, v: bool) -> Self { + self.location = v; + self + } +} + +impl Generator for AlterExprAddColumnGenerator { + type Error = Error; + + fn generate(&self) -> Result { + let mut rng = rand::thread_rng(); + let with_location = self.location && rng.gen::(); + let location = if with_location { + let use_first = rng.gen::(); + let location = if use_first { + AddColumnLocation::First + } else { + AddColumnLocation::After { + column_name: self.table_ctx.columns + [rng.gen_range(0..self.table_ctx.columns.len())] + .name + .to_string(), + } + }; + Some(location) + } else { + None + }; + + let column = rng.gen::(); + Ok(AlterTableExpr { + name: self.table_ctx.name.to_string(), + alter_options: AlterTableOperation::AddColumn { column, location }, + }) + } +} + +/// Generates the [AlterTableOperation::DropColumn] of [AlterTableExpr]. +pub struct AlterExprDropColumnGenerator { + table_ctx: TableContextRef, +} + +impl AlterExprDropColumnGenerator { + /// Returns an [AlterExprDropColumnGenerator]. + pub fn new(table_ctx: &TableContextRef) -> Self { + Self { + table_ctx: table_ctx.clone(), + } + } +} + +impl Generator for AlterExprDropColumnGenerator { + type Error = Error; + + fn generate(&self) -> Result { + let mut rng = rand::thread_rng(); + 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(); + Ok(AlterTableExpr { + name: self.table_ctx.name.to_string(), + alter_options: AlterTableOperation::DropColumn { name }, + }) + } +} + +pub struct AlterExprRenameGenerator { + table_ctx: TableContextRef, +} + +impl AlterExprRenameGenerator { + /// Returns an [AlterExprRenameGenerator]. + pub fn new(table_ctx: &TableContextRef) -> Self { + Self { + table_ctx: table_ctx.clone(), + } + } +} + +impl Generator for AlterExprRenameGenerator { + type Error = Error; + + fn generate(&self) -> Result { + let mut rng = rand::thread_rng(); + let mut new_table_name = rng.gen::().to_string(); + Ok(AlterTableExpr { + name: self.table_ctx.name.to_string(), + alter_options: AlterTableOperation::RenameTable { new_table_name }, + }) + } +} + +#[cfg(test)] +mod tests { + use std::sync::Arc; + + use super::*; + use crate::context::TableContext; + use crate::generator::create_expr::CreateTableExprGenerator; + use crate::generator::Generator; + + #[test] + fn test_alter_table_expr_generator() { + let create_expr = CreateTableExprGenerator::default() + .columns(10) + .generate() + .unwrap(); + let table_ctx = Arc::new(TableContext::from(&create_expr)); + + let alter_expr = AlterExprAddColumnGenerator::new(&table_ctx) + .generate() + .unwrap(); + + let alter_expr = AlterExprRenameGenerator::new(&table_ctx) + .generate() + .unwrap(); + + let alter_expr = AlterExprDropColumnGenerator::new(&table_ctx) + .generate() + .unwrap(); + } +} diff --git a/tests-fuzz/src/generator/create_expr.rs b/tests-fuzz/src/generator/create_expr.rs new file mode 100644 index 000000000000..0b4c2a3c81eb --- /dev/null +++ b/tests-fuzz/src/generator/create_expr.rs @@ -0,0 +1,182 @@ +// 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 faker_rand::lorem::Word; +use partition::partition::{PartitionBound, PartitionDef}; +use rand::seq::SliceRandom; +use rand::Rng; +use snafu::{ensure, ResultExt}; + +use super::Generator; +use crate::error::{self, Error, Result}; +use crate::ir::create_expr::{ColumnOption, CreateTableExprBuilder}; +use crate::ir::{ + self, generate_random_value, Column, CreateTableExpr, PartibleColumn, TsColumn, + PARTIBLE_DATA_TYPES, +}; + +pub struct CreateTableExprGenerator { + columns: usize, + engine: String, + partition: usize, + if_not_exists: bool, +} + +const DEFAULT_ENGINE: &str = "mito"; + +impl Default for CreateTableExprGenerator { + fn default() -> Self { + Self { + columns: 0, + engine: DEFAULT_ENGINE.to_string(), + if_not_exists: false, + partition: 0, + } + } +} + +impl CreateTableExprGenerator { + /// Sets column num. + pub fn columns(mut self, columns: usize) -> Self { + self.columns = columns; + self + } + + /// Sets the `if_not_exists`. + pub fn create_is_not_exists(mut self, v: bool) -> Self { + self.if_not_exists = v; + self + } + + /// Sets the `engine`. + pub fn engine(mut self, engine: &str) -> Self { + self.engine = engine.to_string(); + self + } + + /// Sets the partition num. + /// If there is no primary key column, + /// it appends a primary key atomically. + pub fn partitions(mut self, partition: usize) -> Self { + self.partition = partition; + self + } + + /// Generates the [CreateTableExpr]. + pub fn generate(&self) -> Result { + ensure!( + self.columns != 0, + error::UnexpectedSnafu { + violated: "The columns must larger than zero" + } + ); + + let mut builder = CreateTableExprBuilder::default(); + let mut columns = Vec::with_capacity(self.columns + 1); + let mut primary_keys = vec![]; + let mut rng = rand::thread_rng(); + + // Generates columns. + for i in 0..self.columns { + let mut column = rng.gen::(); + let is_primary_key = column + .options + .iter() + .any(|option| option == &ColumnOption::PrimaryKey); + if is_primary_key { + primary_keys.push(i); + } + columns.push(column); + } + + // Shuffles the primary keys. + primary_keys.shuffle(&mut rng); + let partitions = if self.partition > 1 { + // Finds a partible primary keys. + let partible_primary_keys = primary_keys + .iter() + .flat_map(|i| { + if PARTIBLE_DATA_TYPES.contains(&columns[*i].column_type) { + Some(*i) + } else { + None + } + }) + .collect::>(); + + // Generates the partitions. + if partible_primary_keys.is_empty() { + columns.push(rng.gen::().0); + primary_keys.push(columns.len() - 1); + } + let primary_key_idx = primary_keys[rng.gen_range(0..primary_keys.len())]; + let primary_column = &columns[primary_key_idx]; + + // Generates partition bounds. + let mut partition_bounds = Vec::with_capacity(self.partition); + for _ in 0..self.partition - 1 { + partition_bounds.push(PartitionBound::Value(generate_random_value( + &primary_column.column_type, + ))); + partition_bounds.sort(); + } + partition_bounds.push(PartitionBound::MaxValue); + + vec![PartitionDef::new( + vec![primary_column.name.to_string()], + partition_bounds, + )] + } else { + vec![] + }; + // Generates ts column. + columns.push(rng.gen::().0); + + builder.columns(columns); + builder.primary_keys(primary_keys); + builder.engine(self.engine.to_string()); + builder.if_not_exists(self.if_not_exists); + builder.name(rng.gen::().to_string()); + builder.partitions(partitions); + builder.build().context(error::BuildCreateTableExprSnafu) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_create_table_expr_generator() { + let expr = CreateTableExprGenerator::default() + .columns(10) + .partitions(3) + .create_is_not_exists(true) + .engine("mito2") + .generate() + .unwrap(); + assert_eq!(expr.engine, "mito2"); + assert!(expr.if_not_exists); + assert!(expr.columns.len() >= 11); + assert_eq!(expr.partitions[0].partition_bounds().len(), 3); + + let expr = CreateTableExprGenerator::default() + .columns(10) + .partitions(1) + .generate() + .unwrap(); + assert_eq!(expr.columns.len(), 11); + assert_eq!(expr.partitions.len(), 0); + } +} diff --git a/tests-fuzz/src/ir.rs b/tests-fuzz/src/ir.rs new file mode 100644 index 000000000000..b84cedbf13ff --- /dev/null +++ b/tests-fuzz/src/ir.rs @@ -0,0 +1,189 @@ +// 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. + +//! The intermediate representation + +pub(crate) mod alter_expr; +pub(crate) mod create_expr; + +pub use alter_expr::AlterTableExpr; +pub use create_expr::CreateTableExpr; +use datatypes::data_type::ConcreteDataType; +use datatypes::value::Value; +use derive_builder::Builder; +use faker_rand::lorem::Word; +use lazy_static::lazy_static; +use rand::distributions::{Distribution, Standard}; +use serde::{Deserialize, Serialize}; + +use crate::ir::create_expr::ColumnOption; + +lazy_static! { + static ref DATA_TYPES: Vec = vec![ + ConcreteDataType::boolean_datatype(), + ConcreteDataType::int16_datatype(), + ConcreteDataType::int32_datatype(), + ConcreteDataType::int64_datatype(), + ConcreteDataType::float32_datatype(), + ConcreteDataType::float64_datatype(), + ]; + static ref TS_DATA_TYPES: Vec = vec![ + ConcreteDataType::timestamp_nanosecond_datatype(), + ConcreteDataType::timestamp_microsecond_datatype(), + ConcreteDataType::timestamp_millisecond_datatype(), + ConcreteDataType::timestamp_second_datatype(), + ]; + pub static ref PARTIBLE_DATA_TYPES: Vec = vec![ + ConcreteDataType::int16_datatype(), + ConcreteDataType::int32_datatype(), + ConcreteDataType::int64_datatype(), + ConcreteDataType::float32_datatype(), + ConcreteDataType::float64_datatype(), + ConcreteDataType::string_datatype(), + ConcreteDataType::date_datatype(), + ConcreteDataType::datetime_datatype(), + ]; +} + +/// Generates a random [Value]. +pub fn generate_random_value(datatype: &ConcreteDataType) -> Value { + match datatype { + &ConcreteDataType::Boolean(_) => Value::from(rand::random::()), + ConcreteDataType::Int16(_) => Value::from(rand::random::()), + ConcreteDataType::Int32(_) => Value::from(rand::random::()), + ConcreteDataType::Int64(_) => Value::from(rand::random::()), + ConcreteDataType::Float32(_) => Value::from(rand::random::()), + ConcreteDataType::Float64(_) => Value::from(rand::random::()), + ConcreteDataType::String(_) => Value::from(rand::random::().to_string()), + ConcreteDataType::Date(_) => Value::from(rand::random::()), + ConcreteDataType::DateTime(_) => Value::from(rand::random::()), + + _ => unimplemented!("unsupported type: {datatype}"), + } +} + +/// The IR column. +#[derive(Debug, Builder, Clone, Serialize, Deserialize)] +pub struct Column { + #[builder(setter(into))] + pub name: String, + pub column_type: ConcreteDataType, + #[builder(default, setter(into))] + pub options: Vec, +} + +/// Returns droppable columns. i.e., non-primary key columns, non-ts columns. +pub fn droppable_columns(columns: &[Column]) -> Vec<&Column> { + columns + .iter() + .filter(|column| { + !column.options.iter().any(|option| { + option == &ColumnOption::PrimaryKey || option == &ColumnOption::TimeIndex + }) + }) + .collect::>() +} + +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> Column { + let column_type = DATA_TYPES[rng.gen_range(0..DATA_TYPES.len())].clone(); + // 0 -> NULL + // 1 -> NOT NULL + // 2 -> DEFAULT VALUE + // 3 -> PRIMARY KEY + // 4 -> EMPTY + let option_idx = rng.gen_range(0..5); + let options = match option_idx { + 0 => vec![ColumnOption::Null], + 1 => vec![ColumnOption::NotNull], + 2 => vec![ColumnOption::DefaultValue(generate_random_value( + &column_type, + ))], + 3 => vec![ColumnOption::PrimaryKey], + _ => vec![], + }; + + Column { + name: rng.gen::().to_string(), + column_type, + options, + } + } +} + +/// The IR ts column. +pub struct TsColumn(pub Column); + +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> TsColumn { + let column_type = TS_DATA_TYPES[rng.gen_range(0..TS_DATA_TYPES.len())].clone(); + TsColumn(Column { + name: rng.gen::().to_string(), + column_type, + options: vec![], + }) + } +} + +/// The IR partible column. +pub struct PartibleColumn(pub Column); + +impl Distribution for Standard { + fn sample(&self, rng: &mut R) -> PartibleColumn { + let column_type = PARTIBLE_DATA_TYPES[rng.gen_range(0..PARTIBLE_DATA_TYPES.len())].clone(); + PartibleColumn(Column { + name: rng.gen::().to_string(), + column_type, + options: vec![], + }) + } +} + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_droppable_columns() { + let columns = vec![ + Column { + name: "hi".to_string(), + column_type: ConcreteDataType::uint64_datatype(), + options: vec![ColumnOption::PrimaryKey], + }, + Column { + name: "foo".to_string(), + column_type: ConcreteDataType::uint64_datatype(), + options: vec![ColumnOption::TimeIndex], + }, + ]; + let droppable = droppable_columns(&columns); + assert!(droppable.is_empty()); + + let columns = vec![ + Column { + name: "hi".to_string(), + column_type: ConcreteDataType::uint64_datatype(), + options: vec![], + }, + Column { + name: "foo".to_string(), + column_type: ConcreteDataType::uint64_datatype(), + options: vec![], + }, + ]; + let droppable = droppable_columns(&columns); + assert_eq!(droppable.len(), 2); + } +} diff --git a/tests-fuzz/src/ir/alter_expr.rs b/tests-fuzz/src/ir/alter_expr.rs new file mode 100644 index 000000000000..728901ce693f --- /dev/null +++ b/tests-fuzz/src/ir/alter_expr.rs @@ -0,0 +1,38 @@ +// 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 common_query::AddColumnLocation; +use derive_builder::Builder; +use serde::{Deserialize, Serialize}; + +use crate::ir::Column; + +#[derive(Debug, Builder, Clone)] +pub struct AlterTableExpr { + pub name: String, + pub alter_options: AlterTableOperation, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub enum AlterTableOperation { + /// `ADD [ COLUMN ] [location]` + AddColumn { + column: Column, + location: Option, + }, + /// `DROP COLUMN ` + DropColumn { name: String }, + /// `RENAME ` + RenameTable { new_table_name: String }, +} diff --git a/tests-fuzz/src/ir/create_expr.rs b/tests-fuzz/src/ir/create_expr.rs new file mode 100644 index 000000000000..9a32d39beec4 --- /dev/null +++ b/tests-fuzz/src/ir/create_expr.rs @@ -0,0 +1,64 @@ +// 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::collections::HashMap; +use std::fmt::Display; + +use datatypes::value::Value; +use derive_builder::Builder; +use partition::partition::PartitionDef; +use serde::{Deserialize, Serialize}; + +use crate::ir::Column; + +// The column options +#[derive(Debug, Clone, PartialEq, Eq, Serialize, Deserialize)] +pub enum ColumnOption { + Null, + NotNull, + DefaultValue(Value), + DefaultFn(String), + TimeIndex, + PrimaryKey, +} + +impl Display for ColumnOption { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + ColumnOption::Null => write!(f, "NULL"), + ColumnOption::NotNull => write!(f, "NOT NULL"), + ColumnOption::DefaultFn(s) => write!(f, "DEFAULT {}", s), + ColumnOption::DefaultValue(s) => write!(f, "DEFAULT {}", s), + ColumnOption::TimeIndex => write!(f, "TIME INDEX"), + ColumnOption::PrimaryKey => write!(f, "PRIMARY KEY"), + } + } +} + +/// A naive create table expr builder. +#[derive(Debug, Builder, Clone, Serialize, Deserialize)] +pub struct CreateTableExpr { + pub name: String, + pub columns: Vec, + #[builder(default)] + pub if_not_exists: bool, + + // GreptimeDB specific options + #[builder(default, setter(into))] + pub partitions: Vec, + pub engine: String, + #[builder(default, setter(into))] + pub options: HashMap, + pub primary_keys: Vec, +} diff --git a/tests-fuzz/src/lib.rs b/tests-fuzz/src/lib.rs index 4615527a0a7b..fda4def9bd7e 100644 --- a/tests-fuzz/src/lib.rs +++ b/tests-fuzz/src/lib.rs @@ -13,7 +13,11 @@ // limitations under the License. pub(crate) mod context; +pub(crate) mod error; pub(crate) mod executor; +// TODO(weny): removes it. +#[allow(unused)] pub(crate) mod generator; +pub(crate) mod ir; pub(crate) mod table_creator; pub(crate) mod translator;