1use crate::error::Result;
8use async_trait::async_trait;
9use serde::{Deserialize, Serialize};
10use std::fmt::{Debug, Display, Formatter};
11
12use super::ast::*;
13
14#[async_trait]
19pub trait CqlParser: Debug + Send + Sync {
20 async fn parse(&self, input: &str) -> Result<CqlStatement>;
22
23 async fn parse_type(&self, input: &str) -> Result<CqlDataType>;
25
26 async fn parse_expression(&self, input: &str) -> Result<CqlExpression>;
28
29 async fn parse_identifier(&self, input: &str) -> Result<CqlIdentifier>;
31
32 async fn parse_literal(&self, input: &str) -> Result<CqlLiteral>;
34
35 async fn parse_column_definitions(&self, input: &str) -> Result<Vec<CqlColumnDef>>;
37
38 async fn parse_table_options(&self, input: &str) -> Result<CqlTableOptions>;
40
41 fn validate_syntax(&self, input: &str) -> bool;
43
44 fn backend_info(&self) -> ParserBackendInfo;
46}
47
48pub trait CqlVisitor<T>: Debug {
53 fn visit_statement(&mut self, statement: &CqlStatement) -> Result<T>;
54 fn visit_select(&mut self, select: &CqlSelect) -> Result<T>;
55 fn visit_insert(&mut self, insert: &CqlInsert) -> Result<T>;
56 fn visit_update(&mut self, update: &CqlUpdate) -> Result<T>;
57 fn visit_delete(&mut self, delete: &CqlDelete) -> Result<T>;
58 fn visit_create_table(&mut self, create: &CqlCreateTable) -> Result<T>;
59 fn visit_drop_table(&mut self, drop: &CqlDropTable) -> Result<T>;
60 fn visit_create_index(&mut self, create: &CqlCreateIndex) -> Result<T>;
61 fn visit_alter_table(&mut self, alter: &CqlAlterTable) -> Result<T>;
62 fn visit_data_type(&mut self, data_type: &CqlDataType) -> Result<T>;
63 fn visit_expression(&mut self, expression: &CqlExpression) -> Result<T>;
64 fn visit_identifier(&mut self, identifier: &CqlIdentifier) -> Result<T>;
65 fn visit_literal(&mut self, literal: &CqlLiteral) -> Result<T>;
66}
67
68#[derive(Debug, Clone, PartialEq)]
70pub struct ParserBackendInfo {
71 pub name: String,
73 pub version: String,
75 pub features: Vec<ParserFeature>,
77 pub performance: PerformanceCharacteristics,
79}
80
81#[derive(Debug, Clone, PartialEq)]
83pub enum ParserFeature {
84 Incremental,
85 ErrorRecovery,
86 SyntaxHighlighting,
87 CodeCompletion,
88 AstTransformation,
89 CustomOperators,
90 Streaming,
91 Parallel,
92 Caching,
93}
94
95#[derive(Debug, Clone, PartialEq)]
97pub struct PerformanceCharacteristics {
98 pub statements_per_second: u32,
100 pub memory_per_statement: u32,
102 pub startup_time_ms: u32,
104 pub async_support: bool,
106}
107
108#[derive(Debug, Clone)]
110pub struct ValidationContext {
111 pub schemas: std::collections::HashMap<String, crate::schema::TableSchema>,
113 pub udts: std::collections::HashMap<String, crate::types::UdtTypeDef>,
115 pub current_keyspace: Option<String>,
117 pub strictness: ValidationStrictness,
119}
120
121#[derive(Debug, Clone, PartialEq)]
123pub enum ValidationStrictness {
124 Strict,
126 Lenient,
128 Permissive,
130}
131
132impl ValidationContext {
133 pub fn new() -> Self {
135 Self {
136 schemas: std::collections::HashMap::new(),
137 udts: std::collections::HashMap::new(),
138 current_keyspace: None,
139 strictness: ValidationStrictness::Strict,
140 }
141 }
142}
143
144impl Default for ValidationContext {
145 fn default() -> Self {
146 Self::new()
147 }
148}
149
150pub trait CqlParserFactory: Debug + Send + Sync {
154 fn create_parser(&self) -> Result<Box<dyn CqlParser>>;
156
157 fn create_parser_with_config(
159 &self,
160 config: super::config::ParserConfig,
161 ) -> Result<Box<dyn CqlParser>>;
162
163 fn factory_info(&self) -> FactoryInfo;
165}
166
167#[derive(Debug, Clone)]
169pub struct FactoryInfo {
170 pub name: String,
172 pub supported_backends: Vec<String>,
174 pub default_backend: String,
176}
177
178#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
180pub struct SourcePosition {
181 pub line: u32,
183 pub column: u32,
185 pub offset: u32,
187 pub length: u32,
189}
190
191impl SourcePosition {
192 pub fn new(line: u32, column: u32, offset: u32, length: u32) -> Self {
194 Self {
195 line,
196 column,
197 offset,
198 length,
199 }
200 }
201
202 pub fn start() -> Self {
204 Self::new(1, 1, 0, 0)
205 }
206}
207
208impl Display for SourcePosition {
209 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
210 write!(f, "line {}, column {}", self.line, self.column)
211 }
212}
213
214#[cfg(test)]
215mod tests {
216 use super::*;
217
218 #[test]
219 fn test_validation_context_creation() {
220 let ctx = ValidationContext::new();
221 assert_eq!(ctx.strictness, ValidationStrictness::Strict);
222 assert!(ctx.schemas.is_empty());
223 assert!(ctx.udts.is_empty());
224 assert!(ctx.current_keyspace.is_none());
225 }
226
227 #[test]
228 fn test_source_position() {
229 let pos = SourcePosition::new(10, 5, 100, 20);
230 assert_eq!(pos.line, 10);
231 assert_eq!(pos.column, 5);
232 assert_eq!(pos.offset, 100);
233 assert_eq!(pos.length, 20);
234
235 let start_pos = SourcePosition::start();
236 assert_eq!(start_pos.line, 1);
237 assert_eq!(start_pos.column, 1);
238 assert_eq!(start_pos.offset, 0);
239 }
240
241 #[test]
242 fn test_parser_backend_info() {
243 let info = ParserBackendInfo {
244 name: "test".to_string(),
245 version: "1.0.0".to_string(),
246 features: vec![ParserFeature::Incremental, ParserFeature::ErrorRecovery],
247 performance: PerformanceCharacteristics {
248 statements_per_second: 1000,
249 memory_per_statement: 1024,
250 startup_time_ms: 10,
251 async_support: true,
252 },
253 };
254
255 assert_eq!(info.name, "test");
256 assert_eq!(info.features.len(), 2);
257 assert!(info.performance.async_support);
258 }
259}