Skip to main content

cqlite_core/cql/
traits.rs

1//! Core parser trait definitions for CQLite
2//!
3//! This module defines the fundamental traits that abstract over different
4//! parser implementations (nom, ANTLR, etc.), allowing the system to switch
5//! between backends transparently.
6
7use crate::error::Result;
8use async_trait::async_trait;
9use serde::{Deserialize, Serialize};
10use std::fmt::{Debug, Display, Formatter};
11
12use super::ast::*;
13
14/// Main trait for CQL parsing operations.
15///
16/// Abstracts over different parser backends (nom, ANTLR) and provides a
17/// unified interface for parsing CQL statements.
18#[async_trait]
19pub trait CqlParser: Debug + Send + Sync {
20    /// Parse a complete CQL statement from input text.
21    async fn parse(&self, input: &str) -> Result<CqlStatement>;
22
23    /// Parse a CQL data type specification (e.g., `list<text>`, `map<uuid, bigint>`).
24    async fn parse_type(&self, input: &str) -> Result<CqlDataType>;
25
26    /// Parse a CQL expression (e.g., `id = ? AND name LIKE 'test%'`).
27    async fn parse_expression(&self, input: &str) -> Result<CqlExpression>;
28
29    /// Parse a CQL identifier (table name, column name, etc.).
30    async fn parse_identifier(&self, input: &str) -> Result<CqlIdentifier>;
31
32    /// Parse a literal value (e.g., `'hello'`, `42`, `true`).
33    async fn parse_literal(&self, input: &str) -> Result<CqlLiteral>;
34
35    /// Parse a list of column definitions (for CREATE TABLE).
36    async fn parse_column_definitions(&self, input: &str) -> Result<Vec<CqlColumnDef>>;
37
38    /// Parse CREATE TABLE options (e.g., `WITH comment = 'test'`).
39    async fn parse_table_options(&self, input: &str) -> Result<CqlTableOptions>;
40
41    /// Lightweight check that input appears to be valid CQL syntax.
42    fn validate_syntax(&self, input: &str) -> bool;
43
44    /// Get parser backend information.
45    fn backend_info(&self) -> ParserBackendInfo;
46}
47
48/// Trait for visiting and transforming AST nodes.
49///
50/// Implements the visitor pattern for AST traversal, allowing for analysis,
51/// transformation, and code generation.
52pub 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/// Information about a parser backend.
69#[derive(Debug, Clone, PartialEq)]
70pub struct ParserBackendInfo {
71    /// Backend name (e.g., "nom", "antlr").
72    pub name: String,
73    /// Backend version.
74    pub version: String,
75    /// Supported features.
76    pub features: Vec<ParserFeature>,
77    /// Performance characteristics.
78    pub performance: PerformanceCharacteristics,
79}
80
81/// Parser backend features.
82#[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/// Performance characteristics of a parser backend.
96#[derive(Debug, Clone, PartialEq)]
97pub struct PerformanceCharacteristics {
98    /// Average parsing speed (statements per second).
99    pub statements_per_second: u32,
100    /// Memory usage per statement (bytes).
101    pub memory_per_statement: u32,
102    /// Startup time (milliseconds).
103    pub startup_time_ms: u32,
104    /// Supports async parsing.
105    pub async_support: bool,
106}
107
108/// Context for semantic validation.
109#[derive(Debug, Clone)]
110pub struct ValidationContext {
111    /// Available table schemas.
112    pub schemas: std::collections::HashMap<String, crate::schema::TableSchema>,
113    /// Available UDT definitions.
114    pub udts: std::collections::HashMap<String, crate::types::UdtTypeDef>,
115    /// Current keyspace.
116    pub current_keyspace: Option<String>,
117    /// Validation strictness level.
118    pub strictness: ValidationStrictness,
119}
120
121/// Validation strictness levels.
122#[derive(Debug, Clone, PartialEq)]
123pub enum ValidationStrictness {
124    /// All references must be valid.
125    Strict,
126    /// Allow unknown references.
127    Lenient,
128    /// Minimal validation.
129    Permissive,
130}
131
132impl ValidationContext {
133    /// Create a new validation context with strict validation.
134    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
150/// Trait for parser factories.
151///
152/// Allows creation of parser instances with different configurations.
153pub trait CqlParserFactory: Debug + Send + Sync {
154    /// Create a new parser instance.
155    fn create_parser(&self) -> Result<Box<dyn CqlParser>>;
156
157    /// Create a parser with specific configuration.
158    fn create_parser_with_config(
159        &self,
160        config: super::config::ParserConfig,
161    ) -> Result<Box<dyn CqlParser>>;
162
163    /// Get factory information.
164    fn factory_info(&self) -> FactoryInfo;
165}
166
167/// Information about a parser factory.
168#[derive(Debug, Clone)]
169pub struct FactoryInfo {
170    /// Factory name.
171    pub name: String,
172    /// Supported backends.
173    pub supported_backends: Vec<String>,
174    /// Default backend.
175    pub default_backend: String,
176}
177
178/// Source position information for error reporting.
179#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
180pub struct SourcePosition {
181    /// Line number (1-based).
182    pub line: u32,
183    /// Column number (1-based).
184    pub column: u32,
185    /// Byte offset in input.
186    pub offset: u32,
187    /// Length of the parsed element.
188    pub length: u32,
189}
190
191impl SourcePosition {
192    /// Create a new source position.
193    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    /// Create a position at the start of input.
203    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}