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(_) => ValidationResult::success(),
180 Err(e) => {
181 let error = match &e {
182 Error::Syntax {
183 message,
184 line,
185 column,
186 } => ValidationError::error(message.clone(), "E001").with_location(*line, *column),
187 Error::Tokenize {
188 message,
189 line,
190 column,
191 } => ValidationError::error(message.clone(), "E002").with_location(*line, *column),
192 Error::Parse(msg) => ValidationError::error(msg.clone(), "E003"),
193 _ => ValidationError::error(e.to_string(), "E000"),
194 };
195 ValidationResult::with_errors(vec![error])
196 }
197 }
198}
199
200pub fn transpile_by_name(sql: &str, read: &str, write: &str) -> Result<Vec<String>> {
213 let read_dialect = Dialect::get_by_name(read)
214 .ok_or_else(|| Error::parse(format!("Unknown dialect: {}", read)))?;
215 let write_dialect = Dialect::get_by_name(write)
216 .ok_or_else(|| Error::parse(format!("Unknown dialect: {}", write)))?;
217
218 let expressions = read_dialect.parse(sql)?;
219
220 expressions
221 .into_iter()
222 .map(|expr| {
223 let transformed = write_dialect.transform(expr)?;
224 write_dialect.generate(&transformed)
225 })
226 .collect()
227}
228
229pub fn parse_by_name(sql: &str, dialect: &str) -> Result<Vec<Expression>> {
233 let d = Dialect::get_by_name(dialect)
234 .ok_or_else(|| Error::parse(format!("Unknown dialect: {}", dialect)))?;
235 d.parse(sql)
236}
237
238pub fn generate_by_name(expression: &Expression, dialect: &str) -> Result<String> {
242 let d = Dialect::get_by_name(dialect)
243 .ok_or_else(|| Error::parse(format!("Unknown dialect: {}", dialect)))?;
244 d.generate(expression)
245}