| Crates.io | pg-parser-rs |
| lib.rs | pg-parser-rs |
| version | 0.0.2 |
| created_at | 2026-01-25 13:14:37.581837+00 |
| updated_at | 2026-01-25 14:09:24.007836+00 |
| description | PostgreSQL SQL parser based on tree-sitter, with a Rust AST layer |
| homepage | https://github.com/caicancai/tree-sitter-pg |
| repository | https://github.com/caicancai/tree-sitter-pg |
| max_upload_size | |
| id | 2068703 |
| size | 64,067,212 |
PostgreSQL-flavored SQL parser based on tree-sitter, with a Rust AST layer.
Language for tree-sitterparse helper and a PgParser wrapperexamples/ corpuslet mut parser = tree_sitter::Parser::new();
parser.set_language(&pg_parser_rs::language())?;
let tree = parser.parse("SELECT 1;", None).unwrap();
Or use the wrapper for a simpler API:
let mut parser = pg_parser_rs::PgParser::new()?;
let tree = parser.parse("SELECT 1;").unwrap();
let queries = pg_parser_rs::parse_statements("SELECT 1;");
ast_builder walks the CST and produces a typed AST in src/ast.rs.Statement::Unknown.#[non_exhaustive] on key enums and Unknown variants allow incremental support.use pg_parser_rs::{parse_statements, Expr, SelectItem, Statement};
fn main() {
let sql = "SELECT a, b + 1 AS c FROM t WHERE b > 10 ORDER BY c DESC";
let statements = parse_statements(sql);
for stmt in statements {
if let Statement::Query(query) = stmt {
if let pg_parser_rs::SetExpr::Select(select) = query.body {
for item in select.projection {
match item {
SelectItem::UnnamedExpr(expr) | SelectItem::ExprWithAlias { expr, .. } => {
if let Expr::Identifier(ident) = expr {
println!("select column: {}", ident.value);
}
}
_ => {}
}
}
}
}
}
}
tests/parse_examples.rs: parses every examples/*.sqltests/select_precision.rs: ensures select-related examples do not fall back to unknown_statementtests/simple_select.rs: sanity check for a minimal SELECTtests/ast_builder_select_examples.rs: ensures select examples build AST successfullytests/ast_builder_dml_examples.rs: ensures insert/update/delete examples build AST successfullyRun all tests:
cargo test
The grammar lives under grammar/ and is compiled via build.rs.
Generated sources (grammar/src/parser.c, grammar/src/node-types.json,
grammar/src/grammar.json) are not checked into the repo.
This crate runs tree-sitter generate during build. Install the CLI:
cargo install tree-sitter-cli
You can also point TREE_SITTER_CLI to a custom binary.
After changing grammar/grammar.js or grammar/src/scanner.cc, regenerate:
tree-sitter generate
Then sync generated sources into generated/ for builds and packaging:
mkdir -p generated/tree_sitter
cp grammar/src/parser.c generated/
cp grammar/src/scanner.cc generated/
cp grammar/src/node-types.json generated/
cp grammar/src/grammar.json generated/
cp grammar/src/tree_sitter/parser.h generated/tree_sitter/