1pub mod builder;
16pub mod dialects;
17pub mod diff;
18pub mod error;
19pub mod expressions;
20pub mod generator;
21pub mod helper;
22pub mod lineage;
23pub mod optimizer;
24pub mod parser;
25pub mod planner;
26pub mod resolver;
27pub mod schema;
28pub mod scope;
29pub mod time;
30pub mod tokens;
31pub mod transforms;
32pub mod traversal;
33pub mod trie;
34
35pub use dialects::{Dialect, DialectType};
36pub use error::{Error, Result, ValidationError, ValidationResult, ValidationSeverity};
37pub use expressions::Expression;
38pub use generator::Generator;
39pub use helper::{
40 csv, find_new_name, is_date_unit, is_float, is_int, is_iso_date, is_iso_datetime,
41 merge_ranges, name_sequence, seq_get, split_num_words, tsort, while_changing, DATE_UNITS,
42};
43pub use parser::Parser;
44pub use resolver::{is_column_ambiguous, resolve_column, Resolver, ResolverError, ResolverResult};
45pub use schema::{ensure_schema, from_simple_map, normalize_name, MappingSchema, Schema, SchemaError};
46pub use scope::{
47 build_scope, find_all_in_scope, find_in_scope, traverse_scope, walk_in_scope, ColumnRef, Scope,
48 ScopeType, SourceInfo,
49};
50pub use time::{format_time, is_valid_timezone, subsecond_precision, TIMEZONES};
51pub use tokens::{Token, TokenType, Tokenizer};
52pub use traversal::{
53 contains_aggregate, contains_subquery, contains_window_function, find_ancestor, find_parent,
54 get_columns, get_tables, is_aggregate, is_column, is_function, is_literal, is_select,
55 is_subquery, is_window_function, transform, transform_map, BfsIter, DfsIter, ExpressionWalk,
56 ParentInfo, TreeContext,
57};
58pub use trie::{new_trie, new_trie_from_keys, Trie, TrieResult};
59pub use optimizer::{annotate_types, TypeAnnotator, TypeCoercionClass};
60
61pub fn transpile(sql: &str, read: DialectType, write: DialectType) -> Result<Vec<String>> {
82 let read_dialect = Dialect::get(read);
83 let write_dialect = Dialect::get(write);
84
85 let expressions = read_dialect.parse(sql)?;
86
87 expressions
88 .into_iter()
89 .map(|expr| {
90 let transformed = write_dialect.transform(expr)?;
91 write_dialect.generate(&transformed)
92 })
93 .collect()
94}
95
96pub fn parse(sql: &str, dialect: DialectType) -> Result<Vec<Expression>> {
105 let d = Dialect::get(dialect);
106 d.parse(sql)
107}
108
109pub fn parse_one(sql: &str, dialect: DialectType) -> Result<Expression> {
118 let mut expressions = parse(sql, dialect)?;
119
120 if expressions.len() != 1 {
121 return Err(Error::Parse(format!(
122 "Expected 1 statement, found {}",
123 expressions.len()
124 )));
125 }
126
127 Ok(expressions.remove(0))
128}
129
130pub fn generate(expression: &Expression, dialect: DialectType) -> Result<String> {
139 let d = Dialect::get(dialect);
140 d.generate(expression)
141}
142
143pub fn validate(sql: &str, dialect: DialectType) -> ValidationResult {
152 let d = Dialect::get(dialect);
153 match d.parse(sql) {
154 Ok(_) => ValidationResult::success(),
155 Err(e) => {
156 let error = match &e {
157 Error::Syntax {
158 message,
159 line,
160 column,
161 } => ValidationError::error(message.clone(), "E001").with_location(*line, *column),
162 Error::Tokenize {
163 message,
164 line,
165 column,
166 } => ValidationError::error(message.clone(), "E002").with_location(*line, *column),
167 Error::Parse(msg) => ValidationError::error(msg.clone(), "E003"),
168 _ => ValidationError::error(e.to_string(), "E000"),
169 };
170 ValidationResult::with_errors(vec![error])
171 }
172 }
173}