Skip to content

Commit

Permalink
feat(sqlsmith): Support generate cast expr
Browse files Browse the repository at this point in the history
  • Loading branch information
b41sh committed Oct 13, 2023
1 parent bdf4581 commit 831afcd
Show file tree
Hide file tree
Showing 5 changed files with 118 additions and 61 deletions.
2 changes: 1 addition & 1 deletion src/tests/sqlsmith/src/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@ pub struct Args {
pass: String,

/// The number of test cases to generate.
#[clap(long, default_value = "100")]
#[clap(long, default_value = "500")]
count: usize,
}

Expand Down
15 changes: 10 additions & 5 deletions src/tests/sqlsmith/src/runner.rs
Original file line number Diff line number Diff line change
Expand Up @@ -137,7 +137,7 @@ impl Runner {
let table_stmts = generator.gen_base_tables();
let tables = self.create_base_table(table_stmts).await.unwrap();
let conn = self.client.get_conn().await.unwrap();
let row_count = 50;
let row_count = 10;

async fn check_timeout<F>(future: F, sql: String)
where F: Future {
Expand Down Expand Up @@ -207,9 +207,12 @@ impl Runner {
async {
if let Err(e) = conn.exec(&query_sql).await {
if let Error::Api(ClientError::InvalidResponse(err)) = &e {
// TODO: handle Syntax and Semantic errors
err_code = err.code;
if err_code == 1005 || err_code == 1065 {
// TODO: handle Syntax, Semantic and InvalidArgument errors
if err.code == 1005
|| err.code == 1065
|| err.code == 2004
|| err.code == 1010
{
return;
}
if KNOWN_ERRORS
Expand All @@ -218,6 +221,7 @@ impl Runner {
{
return;
}
err_code = err.code;
}
err = format!("error: {}", e);
try_reduce = true;
Expand All @@ -227,8 +231,9 @@ impl Runner {
)
.await;
if try_reduce {
tracing::info!("query_sql: {}", query_sql);
let reduced_query = try_reduce_query(conn.clone(), err_code, query).await;
tracing::info!("query_sql: {}", reduced_query.to_string());
tracing::info!("reduced query_sql: {}", reduced_query.to_string());
tracing::error!(err);
}
}
Expand Down
70 changes: 26 additions & 44 deletions src/tests/sqlsmith/src/sql_gen/ddl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,9 @@ use common_ast::ast::Engine;
use common_ast::ast::Identifier;
use common_ast::ast::NullableConstraint;
use common_ast::ast::TypeName;
use rand::distributions::Alphanumeric;
use rand::Rng;

use super::Table;
use crate::sql_gen::SqlGenerator;

const BASE_TABLE_NAMES: [&str; 4] = ["t1", "t2", "t3", "t4"];
Expand Down Expand Up @@ -88,29 +88,23 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
}

fn gen_nested_type(&mut self, depth: u8) -> TypeName {
let ty = if depth == 0 {
// TODO: generate nullable type for inner type
if depth == 0 {
let i = self.rng.gen_range(0..=17);
SIMPLE_COLUMN_TYPES[i].clone()
// replace bitmap with string, as generated bitmap value can't display
if i == 16 {
TypeName::String
} else {
SIMPLE_COLUMN_TYPES[i].clone()
}
} else {
match self.rng.gen_range(0..=2) {
0 => {
let inner_ty = self.gen_nested_type(depth - 1);
TypeName::Array(Box::new(inner_ty))
}
1 => {
let key_type = match self.rng.gen_range(0..=6) {
0 => TypeName::String,
1 => TypeName::UInt64,
2 => TypeName::Int64,
3 => TypeName::Float64,
4 => TypeName::Decimal {
precision: 15,
scale: 2,
},
5 => TypeName::Date,
6 => TypeName::Timestamp,
_ => unreachable!(),
};
let key_type = TypeName::String;
let val_type = self.gen_nested_type(depth - 1);

TypeName::Map {
Expand Down Expand Up @@ -142,16 +136,17 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
}
_ => unreachable!(),
}
};
if self.rng.gen_bool(0.3) {
TypeName::Nullable(Box::new(ty))
} else {
ty
}
}

pub fn gen_data_type_name(&mut self) -> (TypeName, Option<NullableConstraint>) {
let i = self.rng.gen_range(0..=36);
pub fn gen_data_type_name(
&mut self,
idx: Option<usize>,
) -> (TypeName, Option<NullableConstraint>) {
let i = match idx {
Some(i) => i,
None => self.rng.gen_range(0..38),
};
if i <= 17 {
(
SIMPLE_COLUMN_TYPES[i].clone(),
Expand All @@ -163,16 +158,17 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
Some(NullableConstraint::Null),
)
} else {
// TODO: add nested data types
let depth = self.rng.gen_range(1..=3);
(self.gen_nested_type(depth), None)
}
}

pub fn gen_new_column(&mut self, table: &Table) -> ColumnDefinition {
let field_num = table.schema.num_fields();
pub fn gen_new_column(&mut self) -> ColumnDefinition {
let field_num: String = (0..5)
.map(|_| self.rng.sample(Alphanumeric) as char)
.collect();
let new_column_name = Identifier::from_name(format!("cc{:?}", field_num));
let (data_type, nullable_constraint) = self.gen_data_type_name();
let (data_type, nullable_constraint) = self.gen_data_type_name(None);
ColumnDefinition {
name: new_column_name,
data_type,
Expand All @@ -183,25 +179,11 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
}

fn gen_table_source(&mut self) -> CreateTableSource {
let mut column_defs = Vec::with_capacity(40);
let mut column_defs = Vec::with_capacity(38);

for i in 0..36 {
for i in 0..38 {
let name = format!("c{}", i);
let (data_type, nullable_constraint) = if i <= 17 {
(
SIMPLE_COLUMN_TYPES[i].clone(),
Some(NullableConstraint::NotNull),
)
} else if i <= 35 {
(
SIMPLE_COLUMN_TYPES[i - 18].clone(),
Some(NullableConstraint::Null),
)
} else {
// TODO: add nested data types
let depth = self.rng.gen_range(1..=3);
(self.gen_nested_type(depth), None)
};
let (data_type, nullable_constraint) = self.gen_data_type_name(Some(i));

let column_def = ColumnDefinition {
name: Identifier::from_name(name),
Expand Down
9 changes: 5 additions & 4 deletions src/tests/sqlsmith/src/sql_gen/dml.rs
Original file line number Diff line number Diff line change
Expand Up @@ -145,7 +145,7 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
}

fn random_select_field(&mut self, table: &Table) -> TableField {
let field_index = self.rng.gen_range(0..=table.schema.num_fields());
let field_index = self.rng.gen_range(0..table.schema.num_fields());
table.schema.fields[field_index].clone()
}

Expand All @@ -158,6 +158,7 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
if self.rng.gen_bool(0.3) {
return None;
}

let (action, new_column) = match self.rng.gen_range(0..=4) {
0 => {
let new_table = format!("{}_{}", table.name, self.rng.gen_range(0..10));
Expand All @@ -169,7 +170,7 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
)
}
1 => {
let column = self.gen_new_column(table);
let column = self.gen_new_column();
let option = match self.rng.gen_range(0..=2) {
0 => AddColumnOption::End,
1 => AddColumnOption::First,
Expand All @@ -191,7 +192,7 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
2 => {
let field = self.random_select_field(table);
let old_column = Identifier::from_name(field.name);
let new_column = self.gen_new_column(table).name;
let new_column = self.gen_new_column().name;
(
AlterTableAction::RenameColumn {
old_column,
Expand All @@ -203,7 +204,7 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
3 => {
let field = self.random_select_field(table);
let name = Identifier::from_name(field.name);
let (data_type, nullable_constraint) = self.gen_data_type_name();
let (data_type, nullable_constraint) = self.gen_data_type_name(None);
let new_column = ColumnDefinition {
name,
data_type,
Expand Down
83 changes: 76 additions & 7 deletions src/tests/sqlsmith/src/sql_gen/expr.rs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ use common_ast::ast::Literal;
use common_ast::ast::MapAccessor;
use common_ast::ast::SubqueryModifier;
use common_ast::ast::TrimWhere;
use common_ast::ast::TypeName;
use common_ast::ast::UnaryOperator;
use common_expression::types::DataType;
use common_expression::types::DecimalDataType;
Expand All @@ -34,13 +35,13 @@ use crate::sql_gen::SqlGenerator;

impl<'a, R: Rng> SqlGenerator<'a, R> {
pub(crate) fn gen_expr(&mut self, ty: &DataType) -> Expr {
match self.rng.gen_range(0..=10) {
0..=3 => self.gen_column(ty),
4..=6 => self.gen_scalar_value(ty),
7 => self.gen_scalar_func(ty),
8 => self.gen_factory_scalar_func(ty),
9 => self.gen_window_func(ty),
10 => self.gen_other_expr(ty),
match self.rng.gen_range(0..=13) {
0..=8 => self.gen_simple_expr(ty),
9 => self.gen_scalar_func(ty),
10 => self.gen_factory_scalar_func(ty),
11 => self.gen_window_func(ty),
12 => self.gen_other_expr(ty),
13 => self.gen_cast_expr(ty),
_ => unreachable!(),
}
}
Expand Down Expand Up @@ -637,4 +638,72 @@ impl<'a, R: Rng> SqlGenerator<'a, R> {
}
}
}

fn gen_cast_expr(&mut self, ty: &DataType) -> Expr {
// can't cast to nested types
if matches!(
ty.remove_nullable(),
DataType::Null
| DataType::EmptyArray
| DataType::EmptyMap
| DataType::Array(_)
| DataType::Map(_)
| DataType::Tuple(_)
| DataType::Generic(_)
) {
return self.gen_other_expr(ty);
}

let source_type = self.gen_data_type();
let source_expr = self.gen_expr(&source_type);
let target_type = convert_to_type_name(ty);

if self.rng.gen_bool(0.5) {
Expr::Cast {
span: None,
expr: Box::new(source_expr),
target_type,
pg_style: self.rng.gen_bool(0.5),
}
} else {
Expr::TryCast {
span: None,
expr: Box::new(source_expr),
target_type,
}
}
}
}

fn convert_to_type_name(ty: &DataType) -> TypeName {
match ty {
DataType::Boolean => TypeName::Boolean,
DataType::Number(NumberDataType::UInt8) => TypeName::UInt8,
DataType::Number(NumberDataType::UInt16) => TypeName::UInt16,
DataType::Number(NumberDataType::UInt32) => TypeName::UInt32,
DataType::Number(NumberDataType::UInt64) => TypeName::UInt64,
DataType::Number(NumberDataType::Int8) => TypeName::Int8,
DataType::Number(NumberDataType::Int16) => TypeName::Int16,
DataType::Number(NumberDataType::Int32) => TypeName::Int32,
DataType::Number(NumberDataType::Int64) => TypeName::Int64,
DataType::Number(NumberDataType::Float32) => TypeName::Float32,
DataType::Number(NumberDataType::Float64) => TypeName::Float64,
DataType::Decimal(DecimalDataType::Decimal128(size)) => TypeName::Decimal {
precision: size.precision,
scale: size.scale,
},
DataType::Decimal(DecimalDataType::Decimal256(size)) => TypeName::Decimal {
precision: size.precision,
scale: size.scale,
},
DataType::Date => TypeName::Date,
DataType::Timestamp => TypeName::Timestamp,
DataType::String => TypeName::String,
DataType::Bitmap => TypeName::Bitmap,
DataType::Variant => TypeName::Variant,
DataType::Nullable(box inner_ty) => {
TypeName::Nullable(Box::new(convert_to_type_name(inner_ty)))
}
_ => unreachable!(),
}
}

0 comments on commit 831afcd

Please sign in to comment.