sql_cli/sql/functions/
random.rs1use anyhow::{anyhow, Result};
2use rand::Rng;
3
4use crate::data::datatable::DataValue;
5use crate::sql::functions::{ArgCount, FunctionCategory, FunctionSignature, SqlFunction};
6
7pub struct RandRangeFunction;
9
10impl SqlFunction for RandRangeFunction {
11 fn signature(&self) -> FunctionSignature {
12 FunctionSignature {
13 name: "RAND_RANGE",
14 category: FunctionCategory::Mathematical,
15 arg_count: ArgCount::Fixed(3),
16 description: "Generate N random numbers between lower and upper bounds",
17 returns: "TABLE",
18 examples: vec![
19 "SELECT * FROM RAND_RANGE(10, 1, 100)", "SELECT * FROM RAND_RANGE(5, 0.0, 1.0)", "SELECT AVG(value) FROM RAND_RANGE(1000, 1, 6)", ],
23 }
24 }
25
26 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
27 self.validate_args(args)?;
28
29 let count = match &args[0] {
30 DataValue::Integer(n) if *n > 0 => *n as usize,
31 DataValue::Float(f) if *f > 0.0 => *f as usize,
32 _ => return Err(anyhow!("RAND_RANGE count must be a positive number")),
33 };
34
35 let (lower, upper, use_float) = match (&args[1], &args[2]) {
36 (DataValue::Integer(l), DataValue::Integer(u)) => (*l as f64, *u as f64, false),
37 (DataValue::Float(l), DataValue::Float(u)) => (*l, *u, true),
38 (DataValue::Integer(l), DataValue::Float(u)) => (*l as f64, *u, true),
39 (DataValue::Float(l), DataValue::Integer(u)) => (*l, *u as f64, true),
40 _ => return Err(anyhow!("RAND_RANGE bounds must be numeric")),
41 };
42
43 if lower > upper {
44 return Err(anyhow!("RAND_RANGE lower bound must be <= upper bound"));
45 }
46
47 let mut rng = rand::thread_rng();
49 let mut values = Vec::with_capacity(count);
50
51 for _ in 0..count {
52 if use_float {
53 let value = rng.gen_range(lower..=upper);
54 values.push(DataValue::Float(value));
55 } else {
56 let value = rng.gen_range(lower as i64..=upper as i64);
57 values.push(DataValue::Integer(value));
58 }
59 }
60
61 if values.is_empty() {
64 Ok(DataValue::Null)
65 } else {
66 Ok(values[0].clone())
67 }
68 }
69}
70
71pub struct RandomFunction;
73
74impl SqlFunction for RandomFunction {
75 fn signature(&self) -> FunctionSignature {
76 FunctionSignature {
77 name: "RANDOM",
78 category: FunctionCategory::Mathematical,
79 arg_count: ArgCount::Fixed(0),
80 description: "Generate a random float between 0 and 1",
81 returns: "FLOAT",
82 examples: vec![
83 "SELECT RANDOM()",
84 "SELECT ROUND(RANDOM() * 100, 0)", ],
86 }
87 }
88
89 fn evaluate(&self, _args: &[DataValue]) -> Result<DataValue> {
90 let mut rng = rand::thread_rng();
91 Ok(DataValue::Float(rng.gen_range(0.0..1.0)))
92 }
93}
94
95pub struct RandIntFunction;
97
98impl SqlFunction for RandIntFunction {
99 fn signature(&self) -> FunctionSignature {
100 FunctionSignature {
101 name: "RAND_INT",
102 category: FunctionCategory::Mathematical,
103 arg_count: ArgCount::Fixed(2),
104 description: "Generate a random integer between lower and upper bounds (inclusive)",
105 returns: "INTEGER",
106 examples: vec![
107 "SELECT RAND_INT(1, 6)", "SELECT RAND_INT(1, 100)", "SELECT RAND_INT(0, 255)", ],
111 }
112 }
113
114 fn evaluate(&self, args: &[DataValue]) -> Result<DataValue> {
115 self.validate_args(args)?;
116
117 let lower = match &args[0] {
118 DataValue::Integer(n) => *n,
119 DataValue::Float(f) => *f as i64,
120 _ => return Err(anyhow!("RAND_INT lower bound must be numeric")),
121 };
122
123 let upper = match &args[1] {
124 DataValue::Integer(n) => *n,
125 DataValue::Float(f) => *f as i64,
126 _ => return Err(anyhow!("RAND_INT upper bound must be numeric")),
127 };
128
129 if lower > upper {
130 return Err(anyhow!("RAND_INT lower bound must be <= upper bound"));
131 }
132
133 let mut rng = rand::thread_rng();
134 Ok(DataValue::Integer(rng.gen_range(lower..=upper)))
135 }
136}