Apache License 2.0

项目介绍

JSQLParser/JSqlParser 是一个托管在 GitHub 上的开源项目,主要使用 Java 编写,采用 Apache License 2.0 许可证,目前获得 6.0k 个 Star、1.4k 次 Fork。

仓库全名
JSQLParser/JSqlParser
开源许可证
Apache License 2.0
Star 数
6.0k
Fork 数
1.4k
未关闭 Issue
5

README 摘要

JSqlParser Turn any SQL statement into a traversable tree of Java objects -- and back again. An RDBMS-agnostic SQL parser for the JVM: one grammar, twelve dialects, no native extensions. Website · Samples · Syntax · Change Log · Contributing What it does Give it SQL. Get an AST you can walk, rewrite, and print back out. The tree is traversable with the Visitor pattern, and the same object model works in reverse…

完整内容见 GitHub 原始 README 或本页 。

常见问题

JSqlParser 用什么语言开发?

主要使用 Java 编写,采用 Apache License 2.0 许可证,目前有 6.0k 个 Star。

JSqlParser 可以免费商用吗?

仓库采用 Apache License 2.0 许可证,可免费使用与修改,商业使用请遵守许可证条款(例如保留版权声明与许可声明)。

如何获取 JSqlParser 的源码?

可以直接克隆仓库:git clone https://github.com/JSQLParser/JSqlParser.git,默认分支为 master;安装与运行步骤见仓库 README。

JSqlParser 最近还在维护吗?

仓库最近一次更新为 2 天前,当前有 5 个未关闭 Issue;Star 数为 6.0k,可作为社区活跃度的参考。

简要分析

热度分
9039
价值分
4033
活跃状态
活跃

语言占比

CSS
Java
PLSQL
PLpgSQL
Python
XSLT

Release

README

JSqlParser

Turn any SQL statement into a traversable tree of Java objects -- and back again.

An RDBMS-agnostic SQL parser for the JVM:
one grammar, twelve dialects, no native extensions.

JSqlParser

CI Coverage Status Codacy Badge Manticore Build Maven Central Javadocs GitHub Stars Gitter

Website · Samples · Syntax · Change Log · Contributing


What it does

Give it SQL. Get an AST you can walk, rewrite, and print back out.

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
String sqlStr = "select 1 from dual where a=b";

PlainSelect select = (PlainSelect) CCJSqlParserUtil.parse(sqlStr);

SelectItem selectItem = select.getSelectItems().get(0);
Assertions.assertEquals(new LongValue(1), selectItem.getExpression());

Table table = (Table) select.getFromItem();
Assertions.assertEquals("dual", table.getName());

EqualsTo equalsTo = (EqualsTo) select.getWhere();
Column a = (Column) equalsTo.getLeftExpression();
Column b = (Column) equalsTo.getRightExpression();
Assertions.assertEquals("a", a.getColumnName());
        Assertions.assertEquals("b", b.getColumnName());

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.

Install

Use the stable Manticore builds. They are released continuously from the current development line and carry all of the performance and grammar work described below. The upstream com.github.jsqlparser release on Maven Central is considerably older.

<dependency>
    <groupId>com.manticore-projects.jsqlformatter</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>[5.3.218,)</version>
</dependency>
implementation("com.manticore-projects.jsqlformatter:jsqlparser:+")
Upstream release and snapshots
<dependency>
    <groupId>com.github.jsqlparser</groupId>
    <artifactId>jsqlparser</artifactId>
    <version>5.3</version>
</dependency>

Snapshot coordinates and repository setup are on the build dependencies 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. And the community kept sending performance improvements since. Thank you everyone!

Benchmark                                     (version)  Mode  Cnt    Score   Error  Units
JSQLParserBenchmark.parseSQLStatements           latest  avgt   15   21.138 ± 0.557  ms/op <-- Community sponsored improvements!
JSQLParserBenchmark.parseSQLStatements              5.4  avgt   15   32.528 ± 0.666  ms/op
JSQLParserBenchmark.parseSQLStatements              5.3  avgt   15  983.459 ± 8.197  ms/op
JSQLParserBenchmark.parseSQLStatements              5.1  avgt   15  319.601 ± 4.081  ms/op

Methodology and the full cross-parser comparison against SQLGlot, sqlglot[c] and polyglot-sql: jsqlparser-bench.

What it parses

JSqlParser targets the SQL standard plus all major RDBMS. One grammar covers all of them, and 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 SELECT · WITH … · Piped SQL
ksqlDB windows JOIN WITHIN, window GRACE PERIOD, and EMIT CHANGES/FINAL
ClickHouse column selection COLUMNS('regexp') select items with chained APPLY, EXCEPT, and REPLACE transformers
DML INSERT · UPDATE · UPSERT · MERGE · DELETE · TRUNCATE TABLE
Oracle RETURNING Named output binds (INTO :name), JDBC output parameters (INTO ?), and BULK COLLECT INTO
DDL CREATE … · ALTER … · DROP …
Oracle vector types VECTOR(*, *) · VECTOR(*, FLOAT32) · VECTOR(3, *), including dense and sparse storage formats
PostgreSQL ownership DROP OWNED · REASSIGN OWNED
MySQL table maintenance ANALYZE · CHECK · CHECKSUM · OPTIMIZE · REPAIR TABLE
PostgreSQL maintenance VACUUM · ANALYZE · CLUSTER · CHECKPOINT
MySQL locks LOCK TABLES · UNLOCK TABLES · LOCK INSTANCE FOR BACKUP · UNLOCK INSTANCE
MySQL account management CREATE/ALTER/RENAME USER · CREATE ROLE · SET ROLE · SET DEFAULT ROLE · SET PASSWORD
Tablespaces MySQL and PostgreSQL CREATE TABLESPACE · ALTER TABLESPACE
PostgreSQL RLS CREATE POLICY · ALTER TABLE … ENABLE/DISABLE/FORCE/NO FORCE ROW LEVEL SECURITY
Routine changes ALTER FUNCTION · ALTER PROCEDURE · ALTER ROUTINE · PostgreSQL ALTER TRIGGER
MySQL metadata statements SHOW [FULL] COLUMNS/FIELDS · SHOW TABLE STATUS · SHOW CREATE TABLE/VIEW/PROCEDURE/FUNCTION/TRIGGER/EVENT/DATABASE/USER
PostgreSQL administration CREATE/ALTER EVENT TRIGGER · REINDEX · SECURITY LABEL
Informix constraints ALTER TABLE … ADD CONSTRAINT with trailing constraint names for primary, unique, foreign and check constraints; enable with parser.withDialect(Dialect.INFORMIX)
Salesforce SOQL INCLUDES · EXCLUDES

Beyond statement shapes, the grammar handles nested sub-selects, bind parameters (?, :name), window and analytic functions, Oracle hints, and the T-SQL square-bracket versus array-literal ambiguity. The complete reference is on the syntax page.

PostgreSQL dollar-quoted strings, including $tag$…$tag$, retain their delimiter and literal body in StringValue. Tagged quotes are disabled by default to preserve identifier parsing. Enable them with parser.withDialect(Dialect.POSTGRESQL) or parser.withDollarQuotedStringTags(true). Untagged $$…$$ literals remain enabled.

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:

SQL returns rows modifies data
SELECT * FROM t yes no
INSERT INTO x SELECT * FROM t no yes
DELETE FROM t RETURNING * yes yes
WITH c AS (DELETE FROM t RETURNING *) SELECT * FROM c yes yes
SELECT nextval('s') yes unproven

Features are not mutually exclusive, and each is three-valued: proven, not excludable, or ruled out. is() answers “did the grammar prove it”, may() answers “could it be ruled out” — so a guard uses may() and a dispatcher uses is(). Function volatility is not a syntactic property, so anything the caller has not declared pure stays unproven and is listed by name.

Legacy MySQL GROUP BY ... ASC/DESC is available with Dialect.MYSQL and the explicit withLegacyMySqlGroupBy(true) option; modern/default parsing keeps it disabled.

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.

ODBC {fn TIMESTAMPADD(...)} and {fn TIMESTAMPDIFF(...)} expose standard SQL_TSI_* interval arguments as time-unit expressions, preserving column traversal.

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 the Migration Guide
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

Alternatives

The dual-licensed JOOQ ships a hand-written parser with broad RDBMS support, cross-dialect translation, SQL transformation, and a JDBC proxy mode. Worth a look if translation between dialects is your primary need rather than AST access.

A huge thank you to Starlake.ai, who simplify data ingestion, transformation and orchestration for faster delivery of high-quality data. Starlake has been instrumental in providing Piped SQL support and a large number of test cases for BigQuery, Redshift, Databricks and DuckDB. If JSqlParser is useful to you, visit Starlake.ai and give them a star.

Documentation

  1. Samples
  2. Build instructions and Maven artifact
  3. Contribution guide
  4. Change log
  5. Issues

License

Dual licensed under LGPL 2.1 or the Apache License, Version 2.0. Take your pick.

评论

暂无评论