Skip to main content

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 generator;
40pub mod optimizer;
41pub mod parser;
42pub mod schema;
43pub mod tokens;
44
45pub use ast::{Expr, MergeClauseKind, QuoteStyle, Statement};
46pub use builder::{
47    ConditionBuilder,
48    SelectBuilder,
49    // Arithmetic helpers
50    add,
51    alias,
52    and_all,
53    between,
54    boolean,
55    // Operators and expressions
56    cast,
57    // Expression factory functions
58    column,
59    // Builders
60    condition,
61    condition_dialect,
62    div,
63    // Comparison helpers
64    eq,
65    exists,
66    func,
67    func_distinct,
68    gt,
69    gte,
70    in_list,
71    in_subquery,
72    is_not_null,
73    is_null,
74    like,
75    literal,
76    lt,
77    lte,
78    mul,
79    neq,
80    not,
81    not_in_list,
82    null,
83    or_all,
84    parse_condition,
85    parse_condition_dialect,
86    // Parse helpers
87    parse_expr,
88    parse_expr_dialect,
89    qualified_star,
90    select,
91    select_all,
92    select_distinct,
93    // Other helpers
94    star,
95    string_literal,
96    sub,
97    subquery,
98    table,
99    table_full,
100};
101pub use dialects::Dialect;
102pub use dialects::time::{
103    FormatConversionResult, TimeFormatStyle, TsqlStyleCode, format_time, format_time_dialect,
104    format_time_with_warnings,
105};
106pub use diff::{AstNode, ChangeAction, diff as diff_ast, diff_sql};
107pub use errors::SqlglotError;
108pub use generator::{generate, generate_pretty};
109pub use optimizer::annotate_types::{TypeAnnotations, annotate_types};
110pub use optimizer::lineage::{
111    LineageConfig, LineageError, LineageGraph, LineageNode, lineage, lineage_sql,
112};
113pub use optimizer::pushdown_predicates::pushdown_predicates;
114pub use optimizer::scope_analysis::{Scope, ScopeType, build_scope, find_all_in_scope};
115pub use parser::parse;
116
117/// Transpile a SQL string from one dialect to another.
118///
119/// This is the primary high-level API, corresponding to Python sqlglot's
120/// `sqlglot.transpile()`.
121///
122/// # Example
123///
124/// ```rust
125/// use sqlglot_rust::{transpile, Dialect};
126///
127/// let result = transpile(
128///     "SELECT CAST(x AS INT) FROM t",
129///     Dialect::Ansi,
130///     Dialect::Postgres,
131/// ).unwrap();
132/// ```
133///
134/// # Errors
135///
136/// Returns a [`SqlglotError`] if parsing fails.
137pub fn transpile(
138    sql: &str,
139    read_dialect: Dialect,
140    write_dialect: Dialect,
141) -> errors::Result<String> {
142    let ast = parse(sql, read_dialect)?;
143    let transformed = dialects::transform(&ast, read_dialect, write_dialect);
144    Ok(generate(&transformed, write_dialect))
145}
146
147/// Transpile a SQL string, returning multiple statements if the input
148/// contains semicolons.
149///
150/// # Errors
151///
152/// Returns a [`SqlglotError`] if parsing fails.
153pub fn transpile_statements(
154    sql: &str,
155    read_dialect: Dialect,
156    write_dialect: Dialect,
157) -> errors::Result<Vec<String>> {
158    let stmts = parser::parse_statements(sql, read_dialect)?;
159    let mut results = Vec::with_capacity(stmts.len());
160    for stmt in &stmts {
161        let transformed = dialects::transform(stmt, read_dialect, write_dialect);
162        results.push(generate(&transformed, write_dialect));
163    }
164    Ok(results)
165}