risingwave_sqlsmith/sql_gen/
scalar.rs1use std::time::{Duration, SystemTime};
16
17use chrono::{DateTime, Utc};
18use rand::Rng;
19use rand::distr::Alphanumeric;
20use rand::prelude::IndexedRandom;
21use risingwave_common::types::{DataType, ListType};
22use risingwave_sqlparser::ast::{Array, DataType as AstDataType, Expr, Value};
23
24use crate::sql_gen::SqlGenerator;
25use crate::sql_gen::expr::typed_null;
26
27impl<R: Rng> SqlGenerator<'_, R> {
28 pub(super) fn gen_range_scalar(
32 &mut self,
33 typ: &DataType,
34 start: i64,
35 end: i64,
36 ) -> Option<Expr> {
37 use DataType as T;
38 let value = self.rng.random_range(start..end).to_string();
39 match *typ {
40 T::Int64 => Some(Expr::TypedString {
41 data_type: AstDataType::BigInt,
42 value,
43 }),
44 T::Int32 => Some(Expr::TypedString {
45 data_type: AstDataType::Int,
46 value,
47 }),
48 T::Int16 => Some(Expr::TypedString {
49 data_type: AstDataType::SmallInt,
50 value,
51 }),
52 _ => None,
53 }
54 }
55
56 pub(super) fn gen_simple_scalar(&mut self, typ: &DataType) -> Expr {
57 use DataType as T;
58 if self.rng.random_bool(0.0) {
62 return typed_null(typ);
66 }
67 match *typ {
72 T::Int64 => Expr::Nested(Box::new(Expr::TypedString {
73 data_type: AstDataType::BigInt,
74 value: self.gen_int(i64::MIN as _, i64::MAX as _),
75 })),
76 T::Int32 => Expr::Nested(Box::new(Expr::TypedString {
77 data_type: AstDataType::Int,
78 value: self.gen_int(i32::MIN as _, i32::MAX as _),
79 })),
80 T::Int16 => Expr::Nested(Box::new(Expr::TypedString {
81 data_type: AstDataType::SmallInt,
82 value: self.gen_int(i16::MIN as _, i16::MAX as _),
83 })),
84 T::Varchar => Expr::Cast {
85 expr: Box::new(Expr::Value(Value::SingleQuotedString(
87 (0..10)
88 .map(|_| self.rng.sample(Alphanumeric) as char)
89 .collect(),
90 ))),
91 data_type: AstDataType::Varchar,
92 },
93 T::Decimal => Expr::Nested(Box::new(Expr::Value(Value::Number(self.gen_float())))),
94 T::Float64 => Expr::Nested(Box::new(Expr::TypedString {
95 data_type: AstDataType::Float(None),
96 value: self.gen_float(),
97 })),
98 T::Float32 => Expr::Nested(Box::new(Expr::TypedString {
99 data_type: AstDataType::Real,
100 value: self.gen_float(),
101 })),
102 T::Boolean => Expr::Value(Value::Boolean(self.rng.random_bool(0.5))),
103 T::Date => Expr::TypedString {
104 data_type: AstDataType::Date,
105 value: self.gen_temporal_scalar(typ),
106 },
107 T::Time => Expr::TypedString {
108 data_type: AstDataType::Time(false),
109 value: self.gen_temporal_scalar(typ),
110 },
111 T::Timestamp => Expr::TypedString {
112 data_type: AstDataType::Timestamp(false),
113 value: self.gen_temporal_scalar(typ),
114 },
115 T::Timestamptz => Expr::TypedString {
116 data_type: AstDataType::Timestamp(true),
117 value: self.gen_temporal_scalar(typ),
118 },
119 T::Interval => Expr::Nested(Box::new(Expr::TypedString {
120 data_type: AstDataType::Interval,
121 value: self.gen_temporal_scalar(typ),
122 })),
123 T::List(ref list) => {
124 let n = self.rng.random_range(1..=4);
125 Expr::Array(Array {
126 elem: self.gen_simple_scalar_list(list, n),
127 named: true,
128 })
129 }
130 _ => typed_null(typ),
139 }
140 }
141
142 fn gen_simple_scalar_list(&mut self, list: &ListType, n: usize) -> Vec<Expr> {
144 (0..n)
145 .map(|_| self.gen_simple_scalar(list.elem()))
146 .collect()
147 }
148
149 fn gen_int(&mut self, min: i64, max: i64) -> String {
150 let n = match self.rng.random_range(1..=100) {
153 1..=5 => 0,
154 6..=10 => 1,
155 11..=15 => max,
156 16..=20 => min,
157 21..=25 => self.rng.random_range(min + 1..0),
158 26..=30 => self.rng.random_range(1000..max),
159 31..=100 => self.rng.random_range(2..1000),
160 _ => unreachable!(),
161 };
162 n.to_string()
163 }
164
165 fn gen_float(&mut self) -> String {
166 let n = match self.rng.random_range(1..=100) {
169 1..=5 => 0.0,
170 6..=10 => 1.0,
171 11..=15 => i32::MAX as f64,
172 16..=20 => i32::MIN as f64,
173 21..=25 => self.rng.random_range(i32::MIN + 1..0) as f64,
174 26..=30 => self.rng.random_range(1000..i32::MAX) as f64,
175 31..=100 => self.rng.random_range(2..1000) as f64,
176 _ => unreachable!(),
177 };
178 n.to_string()
179 }
180
181 fn gen_temporal_scalar(&mut self, typ: &DataType) -> String {
182 use DataType as T;
183
184 let minute = 60;
185 let hour = 60 * minute;
186 let day = 24 * hour;
187 let week = 7 * day;
188 let choices = [0, 1, minute, hour, day, week];
189
190 let secs = match self.rng.random_range(1..=100) {
191 1..=30 => *choices.choose(&mut self.rng).unwrap(),
192 31..=100 => self.rng.random_range(2..100) as u64,
193 _ => unreachable!(),
194 };
195
196 let tm = DateTime::<Utc>::from(SystemTime::now() - Duration::from_secs(secs));
197 match typ {
198 T::Date => tm.format("%F").to_string(),
199 T::Timestamp | T::Timestamptz => tm.format("%Y-%m-%d %H:%M:%S").to_string(),
200 T::Time => tm.format("%T").to_string(),
207 T::Interval => {
208 if self.rng.random_bool(0.5) {
209 (-(secs as i64)).to_string()
210 } else {
211 secs.to_string()
212 }
213 }
214 _ => unreachable!(),
215 }
216 }
217}