sqlglot_rust/lib.rs
1//! # sqlglot-rust
2//!
3//! A SQL parser, optimizer, and transpiler library written in Rust,
4//! inspired by Python's [sqlglot](https://github.com/tobymao/sqlglot).
5//!
6//! ## Features
7//!
8//! - Parse SQL strings into a structured AST
9//! - Generate SQL from AST nodes
10//! - Transpile between SQL dialects (30 dialects including MySQL, PostgreSQL, BigQuery, Snowflake, DuckDB, Hive, Spark, Presto, Trino, T-SQL, Oracle, ClickHouse, Redshift, and more)
11//! - Optimize SQL queries
12//! - CTEs, subqueries, UNION/INTERSECT/EXCEPT
13//! - Window functions, CAST, EXTRACT, EXISTS
14//! - Pretty-print SQL output
15//! - AST traversal (walk, find, transform)
16//! - AST diff for semantic SQL comparison
17//!
18//! ## Quick Start
19//!
20//! ```rust
21//! use sqlglot_rust::{parse, generate, transpile, Dialect};
22//!
23//! // Parse a SQL query
24//! let ast = parse("SELECT a, b FROM t WHERE a > 1", Dialect::Ansi).unwrap();
25//!
26//! // Generate SQL for a specific dialect
27//! let sql = generate(&ast, Dialect::Postgres);
28//! assert_eq!(sql, "SELECT a, b FROM t WHERE a > 1");
29//!
30//! // One-step transpile between dialects
31//! let result = transpile("SELECT a, b FROM t", Dialect::Ansi, Dialect::Postgres).unwrap();
32//! ```
33
34pub mod ast;
35pub mod builder;
36pub mod dialects;
37pub mod diff;
38pub mod errors;
39pub mod executor;
40pub mod generator;
41pub mod optimizer;
42pub mod parser;
43pub mod schema;
44pub mod tokens;
45
46pub use ast::{Expr, MergeClauseKind, QuoteStyle, Statement};
47pub use builder::{
48 ConditionBuilder,
49 SelectBuilder,
50 // Arithmetic helpers
51 add,
52 alias,
53 and_all,
54 between,
55 boolean,
56 // Operators and expressions
57 cast,
58 // Expression factory functions
59 column,
60 // Builders
61 condition,
62 condition_dialect,
63 div,
64 // Comparison helpers
65 eq,
66 exists,
67 func,
68 func_distinct,
69 gt,
70 gte,
71 in_list,
72 in_subquery,
73 is_not_null,
74 is_null,
75 like,
76 literal,
77 lt,
78 lte,
79 mul,
80 neq,
81 not,
82 not_in_list,
83 null,
84 or_all,
85 parse_condition,
86 parse_condition_dialect,
87 // Parse helpers
88 parse_expr,
89 parse_expr_dialect,
90 qualified_star,
91 select,
92 select_all,
93 select_distinct,
94 // Other helpers
95 star,
96 string_literal,
97 sub,
98 subquery,
99 table,
100 table_full,
101};
102pub use dialects::Dialect;
103pub use dialects::time::{
104 FormatConversionResult, TimeFormatStyle, TsqlStyleCode, format_time, format_time_dialect,
105 format_time_with_warnings,
106};
107pub use diff::{AstNode, ChangeAction, diff as diff_ast, diff_sql};
108pub use errors::SqlglotError;
109pub use generator::{generate, generate_pretty};
110pub use optimizer::annotate_types::{TypeAnnotations, annotate_types};
111pub use optimizer::lineage::{
112 LineageConfig, LineageError, LineageGraph, LineageNode, lineage, lineage_sql,
113};
114pub use optimizer::pushdown_predicates::pushdown_predicates;
115pub use optimizer::scope_analysis::{Scope, ScopeType, build_scope, find_all_in_scope};
116pub use parser::parse;
117
118/// Transpile a SQL string from one dialect to another.
119///
120/// This is the primary high-level API, corresponding to Python sqlglot's
121/// `sqlglot.transpile()`.
122///
123/// # Example
124///
125/// ```rust
126/// use sqlglot_rust::{transpile, Dialect};
127///
128/// let result = transpile(
129/// "SELECT CAST(x AS INT) FROM t",
130/// Dialect::Ansi,
131/// Dialect::Postgres,
132/// ).unwrap();
133/// ```
134///
135/// # Errors
136///
137/// Returns a [`SqlglotError`] if parsing fails.
138pub fn transpile(
139 sql: &str,
140 read_dialect: Dialect,
141 write_dialect: Dialect,
142) -> errors::Result<String> {
143 let ast = parse(sql, read_dialect)?;
144 let transformed = dialects::transform(&ast, read_dialect, write_dialect);
145 Ok(generate(&transformed, write_dialect))
146}
147
148/// Transpile a SQL string, returning multiple statements if the input
149/// contains semicolons.
150///
151/// # Errors
152///
153/// Returns a [`SqlglotError`] if parsing fails.
154pub fn transpile_statements(
155 sql: &str,
156 read_dialect: Dialect,
157 write_dialect: Dialect,
158) -> errors::Result<Vec<String>> {
159 let stmts = parser::parse_statements(sql, read_dialect)?;
160 let mut results = Vec::with_capacity(stmts.len());
161 for stmt in &stmts {
162 let transformed = dialects::transform(stmt, read_dialect, write_dialect);
163 results.push(generate(&transformed, write_dialect));
164 }
165 Ok(results)
166}