reddb_server/storage/query/
analyzer.rs1use std::collections::HashSet;
2
3use super::CreateTableQuery;
4use crate::storage::schema::{DataType, SqlTypeName};
5
6#[derive(Debug, Clone)]
7pub enum AnalysisError {
8 DuplicateColumn(String),
9 UnsupportedType(String),
10}
11
12impl std::fmt::Display for AnalysisError {
13 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
14 match self {
15 Self::DuplicateColumn(name) => write!(f, "duplicate column name: {name}"),
16 Self::UnsupportedType(name) => write!(f, "unsupported SQL type: {name}"),
17 }
18 }
19}
20
21impl std::error::Error for AnalysisError {}
22
23#[derive(Debug, Clone)]
24pub struct AnalyzedCreateTableQuery {
25 pub name: String,
26 pub columns: Vec<AnalyzedColumnDef>,
27 pub if_not_exists: bool,
28 pub default_ttl_ms: Option<u64>,
29 pub context_index_fields: Vec<String>,
30 pub timestamps: bool,
31}
32
33#[derive(Debug, Clone)]
34pub struct AnalyzedColumnDef {
35 pub name: String,
36 pub declared_type: SqlTypeName,
37 pub storage_type: DataType,
38 pub not_null: bool,
39 pub default: Option<String>,
40 pub primary_key: bool,
41 pub unique: bool,
42}
43
44pub fn analyze_create_table(
45 query: &CreateTableQuery,
46) -> Result<AnalyzedCreateTableQuery, AnalysisError> {
47 let mut seen = HashSet::new();
48 let mut columns = Vec::with_capacity(query.columns.len());
49
50 for column in &query.columns {
51 if !seen.insert(column.name.to_ascii_lowercase()) {
52 return Err(AnalysisError::DuplicateColumn(column.name.clone()));
53 }
54
55 columns.push(AnalyzedColumnDef {
56 name: column.name.clone(),
57 declared_type: column.sql_type.clone(),
58 storage_type: resolve_sql_type_name(&column.sql_type)?,
59 not_null: column.not_null,
60 default: column.default.clone(),
61 primary_key: column.primary_key,
62 unique: column.unique,
63 });
64 }
65
66 Ok(AnalyzedCreateTableQuery {
67 name: query.name.clone(),
68 columns,
69 if_not_exists: query.if_not_exists,
70 default_ttl_ms: query.default_ttl_ms,
71 context_index_fields: query.context_index_fields.clone(),
72 timestamps: query.timestamps,
73 })
74}
75
76pub fn resolve_declared_data_type(declared: &str) -> Result<DataType, AnalysisError> {
77 resolve_sql_type_name(&SqlTypeName::parse_declared(declared))
78}
79
80pub fn resolve_sql_type_name(sql_type: &SqlTypeName) -> Result<DataType, AnalysisError> {
81 DataType::from_sql_type_name(sql_type)
82 .ok_or_else(|| AnalysisError::UnsupportedType(sql_type.base_name()))
83}