sql_cli/sql/generators/
mod.rs

1use crate::data::datatable::{DataColumn, DataRow, DataTable, DataValue};
2use anyhow::Result;
3use std::sync::Arc;
4
5pub mod math_generators;
6pub mod prime_generators;
7pub mod random_generators;
8
9/// Trait for table-generating functions that produce rows dynamically
10pub trait TableGenerator: Send + Sync {
11    /// Get the name of the generator function (e.g., "GENERATE_PRIMES")
12    fn name(&self) -> &str;
13
14    /// Get the column definitions for the generated table
15    fn columns(&self) -> Vec<DataColumn>;
16
17    /// Generate the table based on the provided arguments
18    /// Arguments are evaluated expressions from the SQL query
19    fn generate(&self, args: Vec<DataValue>) -> Result<Arc<DataTable>>;
20
21    /// Get a description of what this generator does
22    fn description(&self) -> &str;
23
24    /// Get the expected number of arguments
25    fn arg_count(&self) -> usize;
26}
27
28/// Registry for table generator functions
29pub struct GeneratorRegistry {
30    generators: std::collections::HashMap<String, Box<dyn TableGenerator>>,
31}
32
33impl GeneratorRegistry {
34    pub fn new() -> Self {
35        let mut registry = Self {
36            generators: std::collections::HashMap::new(),
37        };
38        registry.register_default_generators();
39        registry
40    }
41
42    fn register_default_generators(&mut self) {
43        use math_generators::{Collatz, Factorials, PascalTriangle, Squares, TriangularNumbers};
44        use prime_generators::{Fibonacci, GeneratePrimes, PrimeFactors};
45        use random_generators::{GenerateUUIDs, RandomFloats, RandomIntegers};
46
47        // Prime and number theory generators
48        self.register(Box::new(GeneratePrimes));
49        self.register(Box::new(PrimeFactors));
50        self.register(Box::new(Fibonacci));
51
52        // Mathematical sequence generators
53        self.register(Box::new(Collatz));
54        self.register(Box::new(PascalTriangle));
55        self.register(Box::new(TriangularNumbers));
56        self.register(Box::new(Squares));
57        self.register(Box::new(Factorials));
58
59        // Random generators
60        self.register(Box::new(RandomIntegers));
61        self.register(Box::new(RandomFloats));
62        self.register(Box::new(GenerateUUIDs));
63    }
64
65    pub fn register(&mut self, generator: Box<dyn TableGenerator>) {
66        self.generators
67            .insert(generator.name().to_uppercase(), generator);
68    }
69
70    pub fn get(&self, name: &str) -> Option<&Box<dyn TableGenerator>> {
71        self.generators.get(&name.to_uppercase())
72    }
73
74    pub fn list(&self) -> Vec<&str> {
75        let mut names: Vec<&str> = self.generators.keys().map(|s| s.as_str()).collect();
76        names.sort();
77        names
78    }
79
80    pub fn list_generators_formatted(&self) -> String {
81        let mut output = String::new();
82        output.push_str("=== Available Generator Functions ===\n\n");
83
84        // Group generators by category
85        let mut math_gens = Vec::new();
86        let mut random_gens = Vec::new();
87        let mut utility_gens = Vec::new();
88
89        for (name, gen) in &self.generators {
90            let entry = format!("  {} - {}", name, gen.description());
91
92            if name.starts_with("RANDOM_") {
93                random_gens.push(entry);
94            } else if name == "GENERATE_UUID" {
95                utility_gens.push(entry);
96            } else {
97                math_gens.push(entry);
98            }
99        }
100
101        if !math_gens.is_empty() {
102            math_gens.sort();
103            output.push_str("Mathematical Generators:\n");
104            for entry in math_gens {
105                output.push_str(&format!("{}\n", entry));
106            }
107            output.push('\n');
108        }
109
110        if !random_gens.is_empty() {
111            random_gens.sort();
112            output.push_str("Random Generators:\n");
113            for entry in random_gens {
114                output.push_str(&format!("{}\n", entry));
115            }
116            output.push('\n');
117        }
118
119        if !utility_gens.is_empty() {
120            utility_gens.sort();
121            output.push_str("Utility Generators:\n");
122            for entry in utility_gens {
123                output.push_str(&format!("{}\n", entry));
124            }
125            output.push('\n');
126        }
127
128        output.push_str("Use: SELECT * FROM <generator>(<args>)\n");
129        output.push_str("Example: SELECT * FROM GENERATE_PRIMES(100)\n");
130        output
131    }
132
133    pub fn get_generator_help(&self, name: &str) -> Option<String> {
134        self.generators.get(&name.to_uppercase()).map(|gen| {
135            let mut help = String::new();
136            help.push_str(&format!("=== {} ===\n\n", name.to_uppercase()));
137            help.push_str(&format!("Description: {}\n", gen.description()));
138            help.push_str(&format!(
139                "Arguments: {} argument(s) expected\n",
140                gen.arg_count()
141            ));
142            help.push_str("\nColumns:\n");
143            for col in gen.columns() {
144                help.push_str(&format!("  - {}\n", col.name));
145            }
146            help.push_str("\nExample:\n");
147            help.push_str(&format!("  SELECT * FROM {}(", name.to_uppercase()));
148
149            // Add example arguments based on the generator
150            match name.to_uppercase().as_str() {
151                "GENERATE_PRIMES" => help.push_str("100"),
152                "FIBONACCI" => help.push_str("20"),
153                "PRIME_FACTORS" => help.push_str("1260"),
154                "COLLATZ" => help.push_str("7"),
155                "PASCAL_TRIANGLE" => help.push_str("5"),
156                "TRIANGULAR" | "SQUARES" | "FACTORIALS" => help.push_str("10"),
157                "RANDOM_INT" => help.push_str("10, 1, 100, 42"),
158                "RANDOM_FLOAT" => help.push_str("10, 0, 1, 42"),
159                "GENERATE_UUID" => help.push_str("5"),
160                _ => help.push_str("..."),
161            }
162            help.push_str(");\n");
163            help
164        })
165    }
166}
167
168/// Helper function to create a single-column table
169pub fn create_single_column_table(
170    name: &str,
171    column_name: &str,
172    values: Vec<DataValue>,
173) -> Arc<DataTable> {
174    let mut table = DataTable::new(name);
175    table.add_column(DataColumn::new(column_name));
176
177    for value in values {
178        table.add_row(DataRow::new(vec![value])).unwrap();
179    }
180
181    Arc::new(table)
182}
183
184/// Helper function to create a two-column table
185pub fn create_two_column_table(
186    name: &str,
187    col1_name: &str,
188    col2_name: &str,
189    rows: Vec<(DataValue, DataValue)>,
190) -> Arc<DataTable> {
191    let mut table = DataTable::new(name);
192    table.add_column(DataColumn::new(col1_name));
193    table.add_column(DataColumn::new(col2_name));
194
195    for (val1, val2) in rows {
196        table.add_row(DataRow::new(vec![val1, val2])).unwrap();
197    }
198
199    Arc::new(table)
200}