Java SQL Parser Library¶
Turn any SQL statement into a traversable tree of Java objects — and back again.
JSQLParser is an RDBMS-agnostic SQL parser for the JVM, built with JavaCC: one grammar, all major dialects, no native extensions. Give it SQL, get an AST you can walk, rewrite and print back out.
Latest stable release: JSQLParser-5.3.340.jar
Development version: JSQLParser-5.4.340-SNAPSHOT.jar
Note
Since the 5.0 release JSQLParser requires Java 11 and has introduced new Visitors. Please see the Migration to 5.0 guide.
What it does¶
SELECT 1 FROM dual WHERE a = b
SQL Text
└─Statements: statement.select.PlainSelect
├─selectItems: statement.select.SelectItem
│ └─LongValue: 1
├─Table: dual
└─where: expression.operators.relational.EqualsTo
├─Column: a
└─Column: b
PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse("select 1 from dual where a=b");
Table table = (Table) select.getFromItem();
Assertions.assertEquals("dual", table.getName());
The tree is traversable with the Visitor pattern, and the same object model works in reverse: build statements from Java with a fluent API and render them as SQL text. See How to use it.
Install¶
Use the Manticore builds. They are immutable, versioned releases cut continuously from the current development line, and carry the grammar and performance work described below. The upstream com.github.jsqlparser release is considerably older.
<dependency>
<groupId>com.manticore-projects.jsqlformatter</groupId>
<artifactId>jsqlparser</artifactId>
<version>[5.3.218,)</version>
</dependency>
Upstream coordinates, snapshots and Gradle are on the Add JSQLParser to your Project page.
Performance¶
11× faster than 5.3, and the fastest parser on real-world SQL of any of the parsers tested, in any language — 19× ahead of sqlglot[c] on JSQLParser’s own SELECT test suite.
Benchmark (version) Mode Cnt Score Error Units
JSQLParserBenchmark.parseSQLStatements latest avgt 15 7.602 ± 0.135 ms/op
JSQLParserBenchmark.parseSQLStatements 5.3 avgt 15 84.687 ± 3.321 ms/op
Methodology and the full cross-parser comparison against SQLGlot, sqlglot[c] and polyglot-sql: jsqlparser-bench.
What it parses¶
One grammar covers the SQL standard plus all major RDBMS. Missing syntax gets added on demand — open an issue.
BigQuery · Snowflake · DuckDB · Redshift · Oracle · MS SQL Server · Sybase · PostgreSQL · MySQL · MariaDB · DB2 · H2 · HSQLDB · Derby · SQLite
Statements |
|
|---|---|
Queries |
|
DML |
|
DDL |
|
PostgreSQL RLS |
|
Salesforce SOQL |
|
Beyond statement shapes: nested sub-selects, bind parameters (?, :name), window and analytic functions, Oracle hints, the old Oracle JOIN (+), PostgreSQL implicit CAST ::, and the T-SQL square-bracket versus array-literal ambiguity. The complete reference is on the SQL Syntax 5.3.340 page; the gaps are on Unsupported Grammar of various RDBMS.
Statement classification¶
Any parsed statement can say what it actually does — no second parse, no visitor to write:
StatementFeatures features = CCJSqlParserUtil.parse(sqlStr).getFeatures();
// safeguard a read-only client before anything reaches the database
if (connection.isReadOnly() && features.mayModifyData()) {
throw new SQLException("rejected: " + features.getUnresolvedReferences());
}
// dispatch correctly
if (features.returnsResultSet()) { statement.executeQuery(sqlStr); }
else { statement.executeUpdate(sqlStr); }
This is not sqlStr.startsWith("SELECT") with extra steps: RETURNING turns DML into a row source, a data-modifying CTE hides a DELETE inside a SELECT, and INSERT INTO x SELECT .. contains a query but returns nothing. See Classify a Statement.
Piped SQL¶
Support is progressing for Piped SQL, which writes queries in the order they actually execute rather than the order SQL historically demanded.
FROM Produce
|> WHERE
item != 'bananas'
AND category IN ('fruit', 'nut')
|> AGGREGATE COUNT(*) AS num_items, SUM(sales) AS total_sales
GROUP BY item
|> ORDER BY item DESC;
Background reading: the Google research paper, BigQuery pipe syntax and DuckDB FROM-first syntax.
Java version¶
JSQLParser |
Runtime |
Notes |
|---|---|---|
4.9 |
JDK 8 |
last JDK 8 compatible release |
5.0 and later |
JDK 11 |
breaking changes to the AST Visitors, see Migration to 5.0 |
5.1 and later |
JDK 11 |
building requires a JDK 17 toolchain (plugin requirement) |
5.4 and later |
JDK 11 |
parser generated with JavaCC 8 |
Sister projects¶
JSQLFormatter — pretty-printing and formatting of SQL text
JSQLTranspiler — dialect-specific rewriting, column resolution and lineage, by Starlake.ai
Sponsor¶
A huge thank you to our sponsor, Starlake.ai, who simplify data ingestion, transformation and orchestration, enabling faster delivery of high-quality data. Starlake has been instrumental in providing Piped SQL support and numerous test cases for BigQuery, Redshift, Databricks and DuckDB. Show your support for ongoing development by visiting Starlake.ai and giving them a star.
License¶
Dual licensed under LGPL 2.1 or the Apache License, Version 2.0. Take your pick.