sql_cli/data/
virtual_table_generator.rs

1use anyhow::{anyhow, Result};
2use std::collections::HashMap;
3use std::sync::Arc;
4
5use crate::data::datatable::{DataColumn, DataRow, DataTable, DataType, DataValue};
6
7pub struct VirtualTableGenerator;
8
9impl VirtualTableGenerator {
10    pub fn generate_range(
11        start: i64,
12        end: i64,
13        step: Option<i64>,
14        column_name: Option<String>,
15    ) -> Result<Arc<DataTable>> {
16        let step = step.unwrap_or(1);
17        let column_name = column_name.unwrap_or_else(|| "value".to_string());
18
19        if step == 0 {
20            return Err(anyhow!("RANGE step cannot be zero"));
21        }
22
23        if (step > 0 && start > end) || (step < 0 && start < end) {
24            return Err(anyhow!(
25                "RANGE parameters invalid: start={}, end={}, step={}",
26                start,
27                end,
28                step
29            ));
30        }
31
32        let mut table = DataTable::new("range_table");
33
34        let column = DataColumn {
35            name: column_name,
36            data_type: DataType::Integer,
37            nullable: false,
38            unique_values: Some(0),
39            null_count: 0,
40            metadata: HashMap::new(),
41            qualified_name: None,
42            source_table: None,
43        };
44        table.add_column(column);
45
46        let mut current = start;
47        while (step > 0 && current <= end) || (step < 0 && current >= end) {
48            let row = DataRow {
49                values: vec![DataValue::Integer(current)],
50            };
51            table.add_row(row);
52            current += step;
53        }
54
55        Ok(Arc::new(table))
56    }
57
58    pub fn generate_series(count: i64, start: Option<i64>) -> Result<Arc<DataTable>> {
59        let start = start.unwrap_or(1);
60        Self::generate_range(start, start + count - 1, Some(1), Some("index".to_string()))
61    }
62
63    /// Generate a virtual table from a split string
64    pub fn generate_split(
65        text: &str,
66        delimiter: Option<&str>,
67        column_name: Option<String>,
68    ) -> Result<Arc<DataTable>> {
69        let delimiter = delimiter.unwrap_or(" ");
70        let column_name = column_name.unwrap_or_else(|| "value".to_string());
71
72        let mut table = DataTable::new("split_table");
73
74        let column = DataColumn {
75            name: column_name,
76            data_type: DataType::String,
77            nullable: false,
78            unique_values: Some(0),
79            null_count: 0,
80            metadata: HashMap::new(),
81            qualified_name: None,
82            source_table: None,
83        };
84        table.add_column(column);
85
86        // Add index column for position tracking
87        let index_column = DataColumn {
88            name: "index".to_string(),
89            data_type: DataType::Integer,
90            nullable: false,
91            unique_values: Some(0),
92            null_count: 0,
93            metadata: HashMap::new(),
94            qualified_name: None,
95            source_table: None,
96        };
97        table.add_column(index_column);
98
99        // Split the string and create rows
100        let parts: Vec<String> = if delimiter.is_empty() {
101            // If delimiter is empty, split into individual characters
102            text.chars().map(|c| c.to_string()).collect()
103        } else {
104            text.split(delimiter).map(|s| s.to_string()).collect()
105        };
106
107        for (i, part) in parts.iter().enumerate() {
108            // Skip empty parts unless they're meaningful
109            if part.is_empty() && delimiter != "" {
110                continue;
111            }
112
113            let row = DataRow {
114                values: vec![
115                    DataValue::String(part.clone()),
116                    DataValue::Integer((i + 1) as i64),
117                ],
118            };
119            table.add_row(row);
120        }
121
122        Ok(Arc::new(table))
123    }
124}