1pub mod ast_transforms;
16pub mod builder;
17pub mod dialects;
18pub mod diff;
19pub mod error;
20pub mod expressions;
21pub mod generator;
22pub mod helper;
23pub mod lineage;
24pub mod optimizer;
25pub mod parser;
26pub mod planner;
27pub mod resolver;
28pub mod schema;
29pub mod scope;
30pub mod time;
31pub mod tokens;
32pub mod transforms;
33pub mod traversal;
34pub mod trie;
35
36pub use dialects::{Dialect, DialectType, CustomDialectBuilder, unregister_custom_dialect};
37pub use error::{Error, Result, ValidationError, ValidationResult, ValidationSeverity};
38pub use expressions::Expression;
39pub use generator::Generator;
40pub use helper::{
41 csv, find_new_name, is_date_unit, is_float, is_int, is_iso_date, is_iso_datetime,
42 merge_ranges, name_sequence, seq_get, split_num_words, tsort, while_changing, DATE_UNITS,
43};
44pub use parser::Parser;
45pub use resolver::{is_column_ambiguous, resolve_column, Resolver, ResolverError, ResolverResult};
46pub use schema::{ensure_schema, from_simple_map, normalize_name, MappingSchema, Schema, SchemaError};
47pub use scope::{
48 build_scope, find_all_in_scope, find_in_scope, traverse_scope, walk_in_scope, ColumnRef, Scope,
49 ScopeType, SourceInfo,
50};
51pub use time::{format_time, is_valid_timezone, subsecond_precision, TIMEZONES};
52pub use tokens::{Token, TokenType, Tokenizer};
53pub use traversal::{
54 contains_aggregate, contains_subquery, contains_window_function, find_ancestor, find_parent,
55 get_columns, get_tables, is_aggregate, is_column, is_function, is_literal, is_select,
56 is_subquery, is_window_function, transform, transform_map, BfsIter, DfsIter, ExpressionWalk,
57 ParentInfo, TreeContext,
58 is_insert, is_update, is_delete, is_union, is_intersect, is_except,
60 is_boolean, is_null_literal, is_star, is_identifier, is_table,
61 is_eq, is_neq, is_lt, is_lte, is_gt, is_gte, is_like, is_ilike,
62 is_add, is_sub, is_mul, is_div, is_mod, is_concat,
63 is_and, is_or, is_not,
64 is_in, is_between, is_is_null, is_exists,
65 is_count, is_sum, is_avg, is_min_func, is_max_func, is_coalesce, is_null_if,
66 is_cast, is_try_cast, is_safe_cast, is_case,
67 is_from, is_join, is_where, is_group_by, is_having, is_order_by, is_limit, is_offset,
68 is_with, is_cte, is_alias, is_paren, is_ordered,
69 is_create_table, is_drop_table, is_alter_table, is_create_index, is_drop_index,
70 is_create_view, is_drop_view,
71 is_query, is_set_operation, is_comparison, is_arithmetic, is_logical, is_ddl,
73};
74pub use ast_transforms::{
75 add_select_columns, remove_select_columns, set_distinct,
76 add_where, remove_where,
77 set_limit, set_offset, remove_limit_offset,
78 rename_columns, rename_tables, qualify_columns,
79 replace_nodes, replace_by_type, remove_nodes,
80 get_column_names, get_table_names, get_identifiers, get_functions, get_literals,
81 get_subqueries, get_aggregate_functions, get_window_functions, node_count,
82};
83pub use trie::{new_trie, new_trie_from_keys, Trie, TrieResult};
84pub use optimizer::{annotate_types, TypeAnnotator, TypeCoercionClass};
85
86pub fn transpile(sql: &str, read: DialectType, write: DialectType) -> Result<Vec<String>> {
107 let read_dialect = Dialect::get(read);
108 let write_dialect = Dialect::get(write);
109
110 let expressions = read_dialect.parse(sql)?;
111
112 expressions
113 .into_iter()
114 .map(|expr| {
115 let transformed = write_dialect.transform(expr)?;
116 write_dialect.generate(&transformed)
117 })
118 .collect()
119}
120
121pub fn parse(sql: &str, dialect: DialectType) -> Result<Vec<Expression>> {
130 let d = Dialect::get(dialect);
131 d.parse(sql)
132}
133
134pub fn parse_one(sql: &str, dialect: DialectType) -> Result<Expression> {
143 let mut expressions = parse(sql, dialect)?;
144
145 if expressions.len() != 1 {
146 return Err(Error::Parse(format!(
147 "Expected 1 statement, found {}",
148 expressions.len()
149 )));
150 }
151
152 Ok(expressions.remove(0))
153}
154
155pub fn generate(expression: &Expression, dialect: DialectType) -> Result<String> {
164 let d = Dialect::get(dialect);
165 d.generate(expression)
166}
167
168pub fn validate(sql: &str, dialect: DialectType) -> ValidationResult {
177 let d = Dialect::get(dialect);
178 match d.parse(sql) {
179 Ok(expressions) => {
180 for expr in &expressions {
184 if !expr.is_statement() {
185 let msg = format!("Invalid expression / Unexpected token");
186 return ValidationResult::with_errors(vec![
187 ValidationError::error(msg, "E004"),
188 ]);
189 }
190 }
191 ValidationResult::success()
192 }
193 Err(e) => {
194 let error = match &e {
195 Error::Syntax {
196 message,
197 line,
198 column,
199 } => ValidationError::error(message.clone(), "E001").with_location(*line, *column),
200 Error::Tokenize {
201 message,
202 line,
203 column,
204 } => ValidationError::error(message.clone(), "E002").with_location(*line, *column),
205 Error::Parse(msg) => ValidationError::error(msg.clone(), "E003"),
206 _ => ValidationError::error(e.to_string(), "E000"),
207 };
208 ValidationResult::with_errors(vec![error])
209 }
210 }
211}
212
213pub fn transpile_by_name(sql: &str, read: &str, write: &str) -> Result<Vec<String>> {
226 let read_dialect = Dialect::get_by_name(read)
227 .ok_or_else(|| Error::parse(format!("Unknown dialect: {}", read)))?;
228 let write_dialect = Dialect::get_by_name(write)
229 .ok_or_else(|| Error::parse(format!("Unknown dialect: {}", write)))?;
230
231 let expressions = read_dialect.parse(sql)?;
232
233 expressions
234 .into_iter()
235 .map(|expr| {
236 let transformed = write_dialect.transform(expr)?;
237 write_dialect.generate(&transformed)
238 })
239 .collect()
240}
241
242pub fn parse_by_name(sql: &str, dialect: &str) -> Result<Vec<Expression>> {
246 let d = Dialect::get_by_name(dialect)
247 .ok_or_else(|| Error::parse(format!("Unknown dialect: {}", dialect)))?;
248 d.parse(sql)
249}
250
251pub fn generate_by_name(expression: &Expression, dialect: &str) -> Result<String> {
255 let d = Dialect::get_by_name(dialect)
256 .ok_or_else(|| Error::parse(format!("Unknown dialect: {}", dialect)))?;
257 d.generate(expression)
258}