You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@seata.apache.org by ji...@apache.org on 2025/06/23 06:46:17 UTC
(incubator-seata) branch 2.x updated: optimize: Druid SQL parser throws ParserException for unsupported REPLACE statement (#7456)
This is an automated email from the ASF dual-hosted git repository.
jianbin pushed a commit to branch 2.x
in repository https://gitbox.apache.org/repos/asf/incubator-seata.git
The following commit(s) were added to refs/heads/2.x by this push:
new cbc6ac5ad0 optimize: Druid SQL parser throws ParserException for unsupported REPLACE statement (#7456)
cbc6ac5ad0 is described below
commit cbc6ac5ad0aa89e0085d06817f995b6bf949d767
Author: maple <gs...@163.com>
AuthorDate: Mon Jun 23 14:46:12 2025 +0800
optimize: Druid SQL parser throws ParserException for unsupported REPLACE statement (#7456)
---
changes/en-us/2.x.md | 1 +
changes/zh-cn/2.x.md | 1 +
.../druid/DruidSQLRecognizerFactoryImpl.java | 56 +++++++++++++++-------
.../druid/DruidSQLRecognizerFactoryTest.java | 8 +---
4 files changed, 43 insertions(+), 23 deletions(-)
diff --git a/changes/en-us/2.x.md b/changes/en-us/2.x.md
index 483bcd2b67..e78723e74f 100644
--- a/changes/en-us/2.x.md
+++ b/changes/en-us/2.x.md
@@ -61,6 +61,7 @@ Add changes here for all PR submitted to the 2.x branch.
- [[#7445](https://github.com/apache/incubator-seata/pull/7432)] separate the license from the server and namingserver
- [[#7426](https://github.com/apache/incubator-seata/pull/7426)] add some license header
- [[#7450](https://github.com/apache/incubator-seata/pull/7450)] Apply Spotless to the entire codebase
+- [[#7456](https://github.com/apache/incubator-seata/pull/7456)] Druid SQL parser throws ParserException for unsupported REPLACE statement
### security:
diff --git a/changes/zh-cn/2.x.md b/changes/zh-cn/2.x.md
index 29bb3d6c75..18bb174686 100644
--- a/changes/zh-cn/2.x.md
+++ b/changes/zh-cn/2.x.md
@@ -60,6 +60,7 @@
- [[#7445](https://github.com/apache/incubator-seata/pull/7432)] 分离license到server和namingserver
- [[#7426](https://github.com/apache/incubator-seata/pull/7426)] 添加 license header
- [[#7450](https://github.com/apache/incubator-seata/pull/7450)] 将 Spotless 应用于整个代码库
+- [[#7456](https://github.com/apache/incubator-seata/pull/7456)] Druid SQL 解析器因不支持的 REPLACE 语句而抛出 ParserException
### security:
diff --git a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/DruidSQLRecognizerFactoryImpl.java b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/DruidSQLRecognizerFactoryImpl.java
index d4ee5a5361..02d8ada742 100644
--- a/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/DruidSQLRecognizerFactoryImpl.java
+++ b/sqlparser/seata-sqlparser-druid/src/main/java/org/apache/seata/sqlparser/druid/DruidSQLRecognizerFactoryImpl.java
@@ -38,36 +38,48 @@ import java.util.List;
class DruidSQLRecognizerFactoryImpl implements SQLRecognizerFactory {
@Override
public List<SQLRecognizer> create(String sql, String dbType) {
- List<SQLStatement> asts = SQLUtils.parseStatements(sql, DruidDbTypeAdapter.getAdaptiveDbType(dbType));
- if (CollectionUtils.isEmpty(asts)) {
+ List<SQLStatement> sqlStatements;
+ try {
+ sqlStatements = SQLUtils.parseStatements(sql, DruidDbTypeAdapter.getAdaptiveDbType(dbType));
+ } catch (RuntimeException e) {
+ if (isParserException(e)) {
+ throw new NotSupportYetException(
+ "not support the sql syntax: " + sql
+ + "\nplease see the doc about SQL restrictions https://seata.apache.org/zh-cn/docs/user/sqlreference/dml",
+ e);
+ }
+ throw e;
+ }
+
+ if (CollectionUtils.isEmpty(sqlStatements)) {
throw new UnsupportedOperationException("Unsupported SQL: " + sql);
}
- if (asts.size() > 1
- && !(asts.stream().allMatch(statement -> statement instanceof SQLUpdateStatement)
- || asts.stream().allMatch(statement -> statement instanceof SQLDeleteStatement))) {
+ if (sqlStatements.size() > 1
+ && !(sqlStatements.stream().allMatch(statement -> statement instanceof SQLUpdateStatement)
+ || sqlStatements.stream().allMatch(statement -> statement instanceof SQLDeleteStatement))) {
throw new UnsupportedOperationException("ONLY SUPPORT SAME TYPE (UPDATE OR DELETE) MULTI SQL -" + sql);
}
List<SQLRecognizer> recognizers = null;
SQLRecognizer recognizer = null;
- for (SQLStatement ast : asts) {
+ for (SQLStatement sqlStatement : sqlStatements) {
SQLOperateRecognizerHolder recognizerHolder =
SQLOperateRecognizerHolderFactory.getSQLRecognizerHolder(dbType.toLowerCase());
- if (ast instanceof SQLInsertStatement) {
- recognizer = recognizerHolder.getInsertRecognizer(sql, ast);
- } else if (ast instanceof SQLUpdateStatement) {
- recognizer = recognizerHolder.getUpdateRecognizer(sql, ast);
- } else if (ast instanceof SQLDeleteStatement) {
- recognizer = recognizerHolder.getDeleteRecognizer(sql, ast);
- } else if (ast instanceof SQLSelectStatement) {
- recognizer = recognizerHolder.getSelectForUpdateRecognizer(sql, ast);
+ if (sqlStatement instanceof SQLInsertStatement) {
+ recognizer = recognizerHolder.getInsertRecognizer(sql, sqlStatement);
+ } else if (sqlStatement instanceof SQLUpdateStatement) {
+ recognizer = recognizerHolder.getUpdateRecognizer(sql, sqlStatement);
+ } else if (sqlStatement instanceof SQLDeleteStatement) {
+ recognizer = recognizerHolder.getDeleteRecognizer(sql, sqlStatement);
+ } else if (sqlStatement instanceof SQLSelectStatement) {
+ recognizer = recognizerHolder.getSelectForUpdateRecognizer(sql, sqlStatement);
}
// When recognizer is null, it indicates that recognizerHolder cannot allocate unsupported syntax, like
// merge and replace
- if (ast instanceof SQLReplaceStatement) {
+ if (sqlStatement instanceof SQLReplaceStatement) {
// just like:replace into t (id,dr) values (1,'2'), (2,'3')
throw new NotSupportYetException(
- "not support the sql syntax with ReplaceStatement:" + ast
+ "not support the sql syntax with ReplaceStatement:" + sqlStatement
+ "\nplease see the doc about SQL restrictions https://seata.apache.org/zh-cn/docs/user/sqlreference/dml");
}
@@ -80,4 +92,16 @@ class DruidSQLRecognizerFactoryImpl implements SQLRecognizerFactory {
}
return recognizers;
}
+
+ /**
+ * Check if the exception is a Druid ParserException
+ * Use class name comparison to avoid directly referencing the ParserException class
+ */
+ private boolean isParserException(Throwable e) {
+ if (e == null) {
+ return false;
+ }
+ String className = e.getClass().getName();
+ return "com.alibaba.druid.sql.parser.ParserException".equals(className);
+ }
}
diff --git a/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/DruidSQLRecognizerFactoryTest.java b/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/DruidSQLRecognizerFactoryTest.java
index 7666638813..741e411d90 100644
--- a/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/DruidSQLRecognizerFactoryTest.java
+++ b/sqlparser/seata-sqlparser-druid/src/test/java/org/apache/seata/sqlparser/druid/DruidSQLRecognizerFactoryTest.java
@@ -166,13 +166,7 @@ public class DruidSQLRecognizerFactoryTest {
NotSupportYetException.class, () -> recognizerFactory.create(sql3, JdbcConstants.MARIADB));
Assertions.assertThrows(
NotSupportYetException.class, () -> recognizerFactory.create(sql3, JdbcConstants.POLARDBX));
-
- // When dbtype are DM and SQLSERVER, druid cannot parse the sql syntax 'replace'
- try {
- recognizerFactory.create(sql3, JdbcConstants.DM);
- } catch (Exception e) {
- e.printStackTrace();
- }
+ Assertions.assertThrows(NotSupportYetException.class, () -> recognizerFactory.create(sql3, JdbcConstants.DM));
String sql5 = "insert into a select * from b";
Assertions.assertThrows(
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@seata.apache.org
For additional commands, e-mail: notifications-help@seata.apache.org