sql_cli/sql/generators/
mod.rs1use crate::data::datatable::{DataColumn, DataRow, DataTable, DataValue};
2use anyhow::Result;
3use std::sync::Arc;
4
5pub mod ascii_art;
6pub mod literal_generators;
7pub mod math_generators;
8pub mod prime_generators;
9pub mod random_generators;
10pub mod sequence_generators;
11pub mod string_generators;
12
13pub trait TableGenerator: Send + Sync {
15 fn name(&self) -> &str;
17
18 fn columns(&self) -> Vec<DataColumn>;
20
21 fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>>;
24
25 fn description(&self) -> &str;
27
28 fn arg_count(&self) -> usize;
30}
31
32pub struct GeneratorRegistry {
34 generators: std::collections::HashMap<String, Box<dyn TableGenerator>>,
35}
36
37impl GeneratorRegistry {
38 pub fn new() -> Self {
39 let mut registry = Self {
40 generators: std::collections::HashMap::new(),
41 };
42 registry.register_default_generators();
43 registry
44 }
45
46 fn register_default_generators(&mut self) {
47 use ascii_art::{AsciiArt, Banner, BigText};
48 use literal_generators::{Array, Values};
49 use math_generators::{Collatz, Factorials, PascalTriangle, Squares, TriangularNumbers};
50 use prime_generators::{Fibonacci, GeneratePrimes, PrimeFactors};
51 use random_generators::{GenerateUUIDs, RandomFloats, RandomIntegers};
52 use sequence_generators::{Dates, Range, Series};
53 use string_generators::{Chars, Lines, Split, Tokenize};
54
55 self.register(Box::new(Values));
57 self.register(Box::new(Array));
58
59 self.register(Box::new(Range));
61 self.register(Box::new(Series));
62 self.register(Box::new(Dates));
63
64 self.register(Box::new(Split));
66 self.register(Box::new(Tokenize));
67 self.register(Box::new(Chars));
68 self.register(Box::new(Lines));
69
70 self.register(Box::new(GeneratePrimes));
72 self.register(Box::new(PrimeFactors));
73 self.register(Box::new(Fibonacci));
74
75 self.register(Box::new(Collatz));
77 self.register(Box::new(PascalTriangle));
78 self.register(Box::new(TriangularNumbers));
79 self.register(Box::new(Squares));
80 self.register(Box::new(Factorials));
81
82 self.register(Box::new(RandomIntegers));
84 self.register(Box::new(RandomFloats));
85 self.register(Box::new(GenerateUUIDs));
86
87 self.register(Box::new(AsciiArt));
89 self.register(Box::new(BigText));
90 self.register(Box::new(Banner));
91 }
92
93 pub fn register(&mut self, generator: Box<dyn TableGenerator>) {
94 self.generators
95 .insert(generator.name().to_uppercase(), generator);
96 }
97
98 pub fn get(&self, name: &str) -> Option<&Box<dyn TableGenerator>> {
99 self.generators.get(&name.to_uppercase())
100 }
101
102 pub fn list(&self) -> Vec<&str> {
103 let mut names: Vec<&str> = self.generators.keys().map(|s| s.as_str()).collect();
104 names.sort();
105 names
106 }
107
108 pub fn list_generators_formatted(&self) -> String {
109 let mut output = String::new();
110 output.push_str("=== Available Generator Functions ===\n\n");
111
112 let mut sequence_gens = Vec::new();
114 let mut string_gens = Vec::new();
115 let mut math_gens = Vec::new();
116 let mut random_gens = Vec::new();
117 let mut utility_gens = Vec::new();
118 let mut ascii_gens = Vec::new();
119
120 for (name, gen) in &self.generators {
121 let entry = format!(" {} - {}", name, gen.description());
122
123 if name == "RANGE" || name == "SERIES" || name == "DATES" {
124 sequence_gens.push(entry);
125 } else if name == "SPLIT" || name == "TOKENIZE" || name == "CHARS" || name == "LINES" {
126 string_gens.push(entry);
127 } else if name == "ASCII_ART" || name == "BIG_TEXT" || name == "BANNER" {
128 ascii_gens.push(entry);
129 } else if name.starts_with("RANDOM_") {
130 random_gens.push(entry);
131 } else if name == "GENERATE_UUID" {
132 utility_gens.push(entry);
133 } else {
134 math_gens.push(entry);
135 }
136 }
137
138 if !sequence_gens.is_empty() {
139 sequence_gens.sort();
140 output.push_str("Sequence Generators:\n");
141 for entry in sequence_gens {
142 output.push_str(&format!("{}\n", entry));
143 }
144 output.push('\n');
145 }
146
147 if !string_gens.is_empty() {
148 string_gens.sort();
149 output.push_str("String Generators:\n");
150 for entry in string_gens {
151 output.push_str(&format!("{}\n", entry));
152 }
153 output.push('\n');
154 }
155
156 if !math_gens.is_empty() {
157 math_gens.sort();
158 output.push_str("Mathematical Generators:\n");
159 for entry in math_gens {
160 output.push_str(&format!("{}\n", entry));
161 }
162 output.push('\n');
163 }
164
165 if !random_gens.is_empty() {
166 random_gens.sort();
167 output.push_str("Random Generators:\n");
168 for entry in random_gens {
169 output.push_str(&format!("{}\n", entry));
170 }
171 output.push('\n');
172 }
173
174 if !ascii_gens.is_empty() {
175 ascii_gens.sort();
176 output.push_str("ASCII Art Generators:\n");
177 for entry in ascii_gens {
178 output.push_str(&format!("{}\n", entry));
179 }
180 output.push('\n');
181 }
182
183 if !utility_gens.is_empty() {
184 utility_gens.sort();
185 output.push_str("Utility Generators:\n");
186 for entry in utility_gens {
187 output.push_str(&format!("{}\n", entry));
188 }
189 output.push('\n');
190 }
191
192 output.push_str("Use: SELECT * FROM <generator>(<args>)\n");
193 output.push_str("Example: SELECT * FROM GENERATE_PRIMES(100)\n");
194 output
195 }
196
197 pub fn get_generator_help(&self, name: &str) -> Option<String> {
198 self.generators.get(&name.to_uppercase()).map(|gen| {
199 let mut help = String::new();
200 help.push_str(&format!("=== {} ===\n\n", name.to_uppercase()));
201 help.push_str(&format!("Description: {}\n", gen.description()));
202 help.push_str(&format!(
203 "Arguments: {} argument(s) expected\n",
204 gen.arg_count()
205 ));
206 help.push_str("\nColumns:\n");
207 for col in gen.columns() {
208 help.push_str(&format!(" - {}\n", col.name));
209 }
210 help.push_str("\nExample:\n");
211 help.push_str(&format!(" SELECT * FROM {}(", name.to_uppercase()));
212
213 match name.to_uppercase().as_str() {
215 "GENERATE_PRIMES" => help.push_str("100"),
216 "FIBONACCI" => help.push_str("20"),
217 "PRIME_FACTORS" => help.push_str("1260"),
218 "COLLATZ" => help.push_str("7"),
219 "PASCAL_TRIANGLE" => help.push_str("5"),
220 "TRIANGULAR" | "SQUARES" | "FACTORIALS" => help.push_str("10"),
221 "RANDOM_INT" => help.push_str("10, 1, 100, 42"),
222 "RANDOM_FLOAT" => help.push_str("10, 0, 1, 42"),
223 "GENERATE_UUID" => help.push_str("5"),
224 "ASCII_ART" | "BIG_TEXT" => help.push_str("'SQL-CLI'"),
225 "BANNER" => help.push_str("'HELLO', '*'"),
226 _ => help.push_str("..."),
227 }
228 help.push_str(");\n");
229 help
230 })
231 }
232}
233
234pub fn create_single_column_table(
236 name: &str,
237 column_name: &str,
238 values: Vec<DataValue>,
239) -> Arc<DataTable> {
240 let mut table = DataTable::new(name);
241 table.add_column(DataColumn::new(column_name));
242
243 for value in values {
244 table.add_row(DataRow::new(vec![value])).unwrap();
245 }
246
247 Arc::new(table)
248}
249
250pub fn create_two_column_table(
252 name: &str,
253 col1_name: &str,
254 col2_name: &str,
255 rows: Vec<(DataValue, DataValue)>,
256) -> Arc<DataTable> {
257 let mut table = DataTable::new(name);
258 table.add_column(DataColumn::new(col1_name));
259 table.add_column(DataColumn::new(col2_name));
260
261 for (val1, val2) in rows {
262 table.add_row(DataRow::new(vec![val1, val2])).unwrap();
263 }
264
265 Arc::new(table)
266}