{"id":49482204,"url":"https://github.com/protegrity/sql-glot-rust","last_synced_at":"2026-05-28T20:00:52.017Z","repository":{"id":344852397,"uuid":"1182424498","full_name":"protegrity/sql-glot-rust","owner":"protegrity","description":"A SQL parser, optimizer, and transpiler library written in Rust","archived":false,"fork":false,"pushed_at":"2026-05-27T03:24:05.000Z","size":439,"stargazers_count":14,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2026-05-27T05:17:10.408Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Rust","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/protegrity.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-03-15T14:02:41.000Z","updated_at":"2026-05-27T03:23:34.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/protegrity/sql-glot-rust","commit_stats":null,"previous_names":["protegrity/sql-glot-rust"],"tags_count":29,"template":false,"template_full_name":null,"purl":"pkg:github/protegrity/sql-glot-rust","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/protegrity%2Fsql-glot-rust","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/protegrity%2Fsql-glot-rust/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/protegrity%2Fsql-glot-rust/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/protegrity%2Fsql-glot-rust/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/protegrity","download_url":"https://codeload.github.com/protegrity/sql-glot-rust/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/protegrity%2Fsql-glot-rust/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33624221,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-05-28T02:00:06.440Z","response_time":99,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-04-30T23:00:42.000Z","updated_at":"2026-05-28T20:00:51.986Z","avatar_url":"https://github.com/protegrity.png","language":"Rust","funding_links":[],"categories":[],"sub_categories":[],"readme":"# sqlglot-rust\n\nA SQL parser, optimizer, and transpiler library written in Rust, inspired by Python's [sqlglot](https://github.com/tobymao/sqlglot).\n\n## Features\n\n- **Parse** SQL strings into a structured AST\n- **Generate** SQL from AST nodes\n- **Transpile** between 30 SQL dialects\n- **C/C++ FFI** — shared \u0026 static libraries with a C header for integration from C, C++, or any language with C ABI support\n- **CLI** — command-line interface for transpiling, parsing, and formatting SQL\n- **Expression Builder API** — fluent builders for programmatic SQL construction\n- **Typed function expressions** — 72+ functions across 8 categories with dialect-specific generation\n- **LIMIT / TOP / FETCH FIRST** transpilation across dialects\n- **Quoted identifier** preservation and cross-dialect conversion (`\"id\"` ↔ `` `id` `` ↔ `[id]`)\n- **Optimize** SQL queries (constant folding, boolean simplification, subquery unnesting, predicate pushdown, column qualification)\n- **Scope analysis** — track query scopes, sources, columns, and correlations across nested queries\n- **Schema management** — dialect-aware table/column registration and type lookup\n- **AST traversal** — walk, find, transform expressions\n- **AST Diff** — semantic comparison of SQL statements with structural change detection\n- **SQL Execution Engine** — in-memory query execution against Rust data structures for testing and validation\n- CTEs, subqueries, set operations (UNION / INTERSECT / EXCEPT)\n- Window functions with frames and filters\n- CAST, TRY_CAST, EXTRACT, INTERVAL, EXISTS, ANY/ALL/SOME\n- Full DDL support (CREATE TABLE, ALTER TABLE, DROP TABLE, CREATE VIEW, etc.)\n- Serde serialization for AST nodes\n\n## Supported Dialects\n\nAll 30 dialects from Python's sqlglot are supported, with function name mapping,\ndata type mapping, and ILIKE rewriting between dialects.\n\n### Official Dialects\n\n| Dialect | Description |\n| --- | --- |\n| ANSI SQL | Base SQL standard |\n| Athena | AWS Athena (Presto-based) |\n| BigQuery | Google BigQuery |\n| ClickHouse | ClickHouse |\n| Databricks | Databricks (Spark-based) |\n| DuckDB | DuckDB |\n| Hive | Apache Hive |\n| MySQL | MySQL |\n| Oracle | Oracle Database |\n| PostgreSQL | PostgreSQL |\n| Presto | Presto |\n| Redshift | Amazon Redshift (Postgres-based) |\n| Snowflake | Snowflake |\n| Spark | Apache Spark SQL |\n| SQLite | SQLite |\n| StarRocks | StarRocks (MySQL-compatible) |\n| Trino | Trino (Presto successor) |\n| T-SQL | Microsoft SQL Server |\n\n### Community Dialects\n\n| Dialect | Description |\n| --- | --- |\n| Doris | Apache Doris (MySQL-compatible) |\n| Dremio | Dremio |\n| Drill | Apache Drill |\n| Druid | Apache Druid |\n| Exasol | Exasol |\n| Fabric | Microsoft Fabric (T-SQL variant) |\n| Materialize | Materialize (Postgres-compatible) |\n| PRQL | Pipelined Relational Query Language |\n| RisingWave | RisingWave (Postgres-compatible) |\n| SingleStore | SingleStore (MySQL-compatible) |\n| Tableau | Tableau |\n| Teradata | Teradata |\n\n### Dialect Transform Rules\n\nThe transpiler applies dialect-specific rewrite rules when converting between dialects:\n\n| Rule | Example |\n| --- | --- |\n| Function name mapping | `NOW()` → `CURRENT_TIMESTAMP()`, `GETDATE()` |\n| `SUBSTR` ↔ `SUBSTRING` | Postgres uses `SUBSTRING`, MySQL uses `SUBSTR` |\n| `CEIL` → `CEILING` | T-SQL uses `CEILING` |\n| `POW` → `POWER` | T-SQL/Oracle use `POWER` |\n| `DATE_TRUNC` → `DATETRUNC`/`TRUNC` | T-SQL uses `DATETRUNC`, Oracle uses `TRUNC` |\n| `ARRAY_AGG` → `LIST`/`COLLECT_LIST` | DuckDB uses `LIST`, Hive/Spark use `COLLECT_LIST` |\n| `HEX`/`UNHEX` → `TO_HEX`/`FROM_HEX` | Presto/Trino naming convention |\n| `IFNULL` → `COALESCE` | MySQL `IFNULL` → ANSI `COALESCE` |\n| `IFNULL` → `ISNULL` | MySQL `IFNULL` → T-SQL `ISNULL` |\n| `NVL` → `COALESCE` | Oracle `NVL` → standard `COALESCE` |\n| `LEN` ↔ `LENGTH` | T-SQL `LEN` ↔ standard `LENGTH` |\n| `RAND` ↔ `RANDOM` | MySQL `RAND` ↔ Postgres `RANDOM` |\n| `ILIKE` → `LOWER`/`LIKE` | Rewritten for dialects without native ILIKE |\n| `LIMIT` ↔ `TOP` | `LIMIT 10` → `TOP 10` for T-SQL |\n| `LIMIT` → `FETCH FIRST` | `LIMIT 10` → `FETCH FIRST 10 ROWS ONLY` (Oracle) |\n| Quoted identifiers | `\"id\"` ↔ `` `id` `` ↔ `[id]` per dialect |\n| Data type mapping | `TEXT` ↔ `STRING`, `INT` → `BIGINT` (BigQuery) |\n| `BYTEA` ↔ `BLOB` | Postgres `BYTEA` ↔ MySQL `BLOB` |\n\n## Quick Start\n\nAdd to your `Cargo.toml`:\n\n```toml\n[dependencies]\nsqlglot-rust = \"0.9.37\"\n```\n\n### Parse and generate SQL\n\n```rust\nuse sqlglot_rust::{parse, generate, Dialect};\n\nfn main() {\n    // Parse a SQL query\n    let ast = parse(\"SELECT a, b FROM t WHERE a \u003e 1\", Dialect::Ansi).unwrap();\n\n    // Generate SQL (roundtrip)\n    let sql = generate(\u0026ast, Dialect::Ansi);\n    assert_eq!(sql, \"SELECT a, b FROM t WHERE a \u003e 1\");\n}\n```\n\n### Transpile between dialects\n\n```rust\nuse sqlglot_rust::{transpile, Dialect};\n\nfn main() {\n    // Postgres → BigQuery: NOW() becomes CURRENT_TIMESTAMP()\n    let sql = transpile(\n        \"SELECT NOW(), SUBSTRING(name, 1, 3) FROM users\",\n        Dialect::Postgres,\n        Dialect::BigQuery,\n    ).unwrap();\n    // → \"SELECT CURRENT_TIMESTAMP(), SUBSTRING(name, 1, 3) FROM users\"\n\n    // Oracle → T-SQL: NVL becomes ISNULL\n    let sql = transpile(\n        \"SELECT NVL(a, b) FROM t\",\n        Dialect::Oracle,\n        Dialect::Tsql,\n    ).unwrap();\n    // → \"SELECT ISNULL(a, b) FROM t\"\n}\n```\n\n### Parse a dialect name from a string\n\n```rust\nuse sqlglot_rust::Dialect;\n\nlet d = Dialect::from_str(\"postgres\").unwrap();\nassert_eq!(d, Dialect::Postgres);\n\n// Multiple aliases are supported\nassert_eq!(Dialect::from_str(\"tsql\"), Some(Dialect::Tsql));\nassert_eq!(Dialect::from_str(\"mssql\"), Some(Dialect::Tsql));\nassert_eq!(Dialect::from_str(\"sqlserver\"), Some(Dialect::Tsql));\n```\n\n### Build SQL with the Expression Builder API\n\n```rust\nuse sqlglot_rust::builder::{select, condition, column, literal};\nuse sqlglot_rust::{generate, Dialect};\n\nfn main() {\n    // Fluent SELECT builder\n    let query = select(\u0026[\"u.id\", \"u.name\", \"COUNT(o.id) AS order_count\"])\n        .from(\"users\")\n        .left_join(\"orders\", \"u.id = o.user_id\")\n        .where_clause(\"u.active = true\")\n        .and_where(\"o.created_at \u003e '2024-01-01'\")\n        .group_by(\u0026[\"u.id\", \"u.name\"])\n        .having(\"COUNT(o.id) \u003e 0\")\n        .order_by(\u0026[\"order_count DESC\"])\n        .limit(10)\n        .build();\n\n    let sql = generate(\u0026query, Dialect::Postgres);\n    // =\u003e \"SELECT u.id, u.name, COUNT(o.id) AS order_count FROM users LEFT JOIN orders ON u.id = o.user_id WHERE u.active = true AND o.created_at \u003e '2024-01-01' GROUP BY u.id, u.name HAVING COUNT(o.id) \u003e 0 ORDER BY order_count DESC LIMIT 10\"\n\n    // Condition builder\n    let cond = condition(\"x = 1\")\n        .and(\"y = 2\")\n        .or(\"z = 3\")\n        .build();\n\n    // Expression factory functions\n    let col = column(\"name\", Some(\"users\"));  // users.name\n    let num = literal(42);                     // 42\n}\n```\n\n### Supported Statements\n\n- `SELECT` (with JOINs, WHERE, GROUP BY, HAVING, ORDER BY, LIMIT, OFFSET, TOP, FETCH FIRST, QUALIFY)\n- `INSERT INTO ... VALUES` / `INSERT INTO ... SELECT`\n- `UPDATE ... SET ... WHERE` (with RETURNING)\n- `DELETE FROM ... WHERE` (with USING)\n- `MERGE INTO ... USING ... WHEN MATCHED / WHEN NOT MATCHED` (with dialect extensions)\n- `CREATE TABLE` (with constraints, IF NOT EXISTS, TEMPORARY, AS SELECT)\n- `DROP TABLE` (with IF EXISTS)\n- `ALTER TABLE` (ADD COLUMN, DROP COLUMN, RENAME COLUMN, RENAME TO, ALTER TYPE)\n- `CREATE VIEW` / `DROP VIEW`\n- `TRUNCATE TABLE`\n- `BEGIN` / `COMMIT` / `ROLLBACK`\n- `EXPLAIN`\n- `USE`\n\n### Expression Support\n\n- Column references (qualified and unqualified) with quote-style metadata\n- Numeric, string, boolean, and NULL literals\n- Binary operators (`+`, `-`, `*`, `/`, `%`, `=`, `\u003c\u003e`, `\u003c`, `\u003e`, `\u003c=`, `\u003e=`, `AND`, `OR`, `||`)\n- Unary operators (`NOT`, `-`, `+`)\n- Bitwise operators (`\u0026`, `|`, `^`, `\u003c\u003c`, `\u003e\u003e`)\n- Function calls (with DISTINCT, FILTER, OVER support)\n- Typed function expressions (72+ functions: date/time, string, aggregate, array, JSON, window, math, conversion)\n- `BETWEEN`, `IN`, `IS NULL`, `LIKE`, `ILIKE`\n- `CASE ... WHEN ... THEN ... ELSE ... END`\n- `CAST`, `TRY_CAST`, PostgreSQL `::` cast\n- `EXTRACT(field FROM expr)` for all date/time fields\n- `INTERVAL` expressions\n- `EXISTS`, `IN (subquery)`\n- Array literals (`ARRAY[1, 2, 3]`)\n- Window functions with frames (`ROWS`, `RANGE`, `GROUPS`)\n- Common Table Expressions (WITH / WITH RECURSIVE)\n- Set operations (UNION, INTERSECT, EXCEPT with ALL)\n- Parenthesized sub-expressions and subqueries\n\n## CLI\n\nThe CLI is built with the `cli` feature flag and provides three commands:\n\n### Install\n\n```bash\ncargo install sqlglot-rust --features cli\n```\n\n### Transpile\n\nTranspile SQL between dialects:\n\n```bash\n# From stdin\necho \"SELECT CAST(x AS INT) FROM t\" | sqlglot transpile --read mysql --write postgres\n\n# With pretty-printing\necho \"SELECT a, b FROM t WHERE x \u003e 1\" | sqlglot transpile --pretty\n\n# With optimizer\necho \"SELECT * FROM t WHERE 1 = 1 AND a \u003e 5\" | sqlglot transpile --optimize\n\n# From file to file\nsqlglot transpile --read mysql --write postgres --input query.sql --output result.sql\n```\n\n### Parse\n\nParse SQL and output the AST as JSON:\n\n```bash\necho \"SELECT a FROM t\" | sqlglot parse --pretty\n```\n\n### Format\n\nPretty-print SQL:\n\n```bash\necho \"select a,b from t where x\u003e1\" | sqlglot format\n```\n\n### Options\n\n| Option | Description |\n| --- | --- |\n| `--read \u003cdialect\u003e` | Source dialect (default: ansi) |\n| `--write \u003cdialect\u003e` | Target dialect (default: ansi) |\n| `--pretty` | Pretty-print output |\n| `--input \u003cfile\u003e` | Read from file instead of stdin |\n| `--output \u003cfile\u003e` | Write to file instead of stdout |\n| `--optimize` | Run optimizer before generation (transpile only) |\n\n## C/C++ FFI\n\nsqlglot-rust can be built as a shared library (`.so` / `.dylib` / `.dll`) or a static library (`.a`) for use from C, C++, or any language that supports the C ABI.\n\n### Build the FFI libraries\n\n```bash\n# Build for the current host\nmake ffi\n\n# Build for a specific target\nmake ffi-macos-arm64    # aarch64-apple-darwin\nmake ffi-macos-amd64    # x86_64-apple-darwin\nmake ffi-linux-amd64    # x86_64-unknown-linux-gnu\nmake ffi-linux-arm64    # aarch64-unknown-linux-gnu\n\n# Build all four targets\nmake ffi-all\n```\n\nOutput goes to `target/ffi/` with the C header at `target/ffi/include/sqlglot.h`.\n\n### C API\n\n```c\n#include \"sqlglot.h\"\n\nconst char *sqlglot_version(void);\nchar *sqlglot_parse(const char *sql, const char *dialect);\nchar *sqlglot_transpile(const char *sql, const char *from_dialect, const char *to_dialect);\nchar *sqlglot_generate(const char *ast_json, const char *dialect);\nvoid  sqlglot_free(char *ptr);   /* must be called on every non-NULL return */\n```\n\n### C usage example\n\n```c\n#include \u003cstdio.h\u003e\n#include \"sqlglot.h\"\n\nint main(void) {\n    char *result = sqlglot_transpile(\"SELECT * FROM t LIMIT 10\", \"mysql\", \"tsql\");\n    if (result) {\n        printf(\"%s\\n\", result);   /* → SELECT TOP 10 * FROM t */\n        sqlglot_free(result);\n    }\n    return 0;\n}\n```\n\nSee [`examples/ffi_example.c`](examples/ffi_example.c) and [`examples/ffi_example.cpp`](examples/ffi_example.cpp) for complete examples.\n\n### Link against the library\n\n```bash\n# macOS\ngcc example.c -Itarget/ffi/include -Ltarget/release -lsqlglot_rust -o example\n\n# Linux\ngcc example.c -Itarget/ffi/include -Ltarget/release -lsqlglot_rust -lpthread -ldl -lm -o example\nLD_LIBRARY_PATH=target/release ./example\n```\n\n## Documentation\n\n- **[Installation](docs/installation.md)** — Dependency setup and verification\n- **[Developer Guide](docs/developer-guide.md)** — Parsing, generating, transpiling, AST traversal, optimization, and serialization with full code examples\n- **[API Reference](docs/reference.md)** — Complete type catalog, function signatures, dialect tables, and error variants\n\n## Architecture\n\n```text\nsrc/\n├── ast/          # AST node definitions (~40 expression types, 15 statement types)\n├── bin/          # CLI binary (sqlglot) — feature-gated behind \"cli\"\n├── ffi.rs        # C-compatible FFI bindings (extern \"C\" API)\n├── tokens/       # Token types (~200+ variants) and tokenizer\n├── parser/       # Recursive-descent SQL parser\n├── generator/    # SQL code generator\n├── dialects/     # 30 dialect definitions with transform rules\n├── optimizer/    # Query optimization and scope analysis\n├── planner/      # Logical query planner (execution plan DAG)\n├── executor/     # In-memory SQL execution engine\n├── schema/       # Schema management (MappingSchema, dialect-aware lookups)\n├── errors/       # Error types\n└── lib.rs        # Public API (parse, generate, transpile)\n```\n\n## Development\n\n```bash\n# Build\ncargo build\n\n# Build with CLI\ncargo build --features cli\n\n# Run tests (500+ tests)\ncargo test\n\n# Run CLI tests\ncargo test --features cli --test test_cli\n\n# Run benchmarks\ncargo bench\n\n# Lint\ncargo clippy\n\n# Format\ncargo fmt\n```\n\nA `Makefile` is provided for convenience:\n\n```bash\nmake build          # cargo build\nmake test           # cargo test\nmake lint           # cargo clippy\nmake fmt            # cargo fmt\nmake sbom           # Generate SPDX SBOM (see below)\nmake bump-version   # Update version across all files (see below)\nmake ffi            # Build FFI libraries for the current host\nmake ffi-all        # Build FFI libraries for all 4 targets (macOS/Linux × arm64/amd64)\nmake all            # build + sbom\n```\n\n## SBOM (Software Bill of Materials)\n\nThe project supports generating an SBOM in [SPDX](https://spdx.dev/) 2.3 JSON format using [`cargo-sbom`](https://crates.io/crates/cargo-sbom).\n\n### Prerequisites\n\nInstall `cargo-sbom`:\n\n```bash\ncargo install cargo-sbom\n```\n\n### Generate the SBOM\n\n```bash\nmake sbom\n```\n\nThis writes the SBOM to `target/sbom/sqlglot-rust.spdx.json`. You can also run the command directly:\n\n```bash\ncargo sbom --output-format spdx_json_2_3 \u003e target/sbom/sqlglot-rust.spdx.json\n```\n\nThe generated SBOM includes all dependency packages with license information, download locations, and [Package URLs (PURLs)](https://github.com/package-url/purl-spec).\n\n## Updating the Version\n\nUse the `bump-version` Makefile target to update the version consistently across\nall configuration and documentation files:\n\n```bash\nmake bump-version VERSION=1.0.0\n```\n\nThis updates:\n\n- `Cargo.toml` — package version\n- `README.md` — dependency snippet\n- `docs/installation.md` — dependency snippet\n- `Cargo.lock` — regenerated automatically\n\nThe `VERSION` parameter is required and must be a full semantic version (e.g. `1.0.0`, `0.10.1`).\n\n## Acknowledgements\n\nThis project is inspired by and derived from [sqlglot](https://github.com/tobymao/sqlglot) by Toby Mao, licensed under the MIT License. The original sqlglot license is included in this repository as required by the MIT License terms. A copy of the original license can also be found [in the polyglot repository](https://github.com/tobilg/polyglot/tree/main/licenses).\n\n## License\n\nThis project is licensed under the MIT License — see the [LICENSE](LICENSE) file for details.\n\nThis project includes code and concepts derived from [sqlglot](https://github.com/tobymao/sqlglot), which is also licensed under the MIT License. The original copyright notice and permission notice are reproduced below:\n\n```text\nMIT License\n\nCopyright (c) 2023 Toby Mao\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprotegrity%2Fsql-glot-rust","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fprotegrity%2Fsql-glot-rust","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fprotegrity%2Fsql-glot-rust/lists"}