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