chore(project): 添加项目配置文件和忽略规则
- 添加 Babel 配置文件支持 ES6+ 语法转换 - 添加 ESLint 忽略规则和配置文件 - 添加 Git 忽略规则文件 - 添加 Travis CI 配置文件 - 添加 1.4.2 版本变更日志文件 - 添加 Helm 图表辅助模板文件 - 添加 Helm 忽略规则文件
This commit is contained in:
35
sqlparser/pom.xml
Normal file
35
sqlparser/pom.xml
Normal file
@@ -0,0 +1,35 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 1999-2019 Seata.io Group.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-parent</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>seata-sqlparser</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>seata-sqlparser ${project.version}</name>
|
||||
|
||||
<modules>
|
||||
<module>seata-sqlparser-core</module>
|
||||
<module>seata-sqlparser-antlr</module>
|
||||
<module>seata-sqlparser-druid</module>
|
||||
</modules>
|
||||
</project>
|
||||
51
sqlparser/seata-sqlparser-antlr/pom.xml
Normal file
51
sqlparser/seata-sqlparser-antlr/pom.xml
Normal file
@@ -0,0 +1,51 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 1999-2019 Seata.io Group.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-sqlparser</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>seata-sqlparser-antlr</artifactId>
|
||||
<name>seata-sqlparser-antlr ${project.version}</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>seata-sqlparser-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.antlr</groupId>
|
||||
<artifactId>antlr4</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-checkstyle-plugin</artifactId>
|
||||
<configuration>
|
||||
<skip>true</skip>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr;
|
||||
|
||||
import io.seata.common.loader.LoadLevel;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.SQLRecognizerFactory;
|
||||
import io.seata.sqlparser.SqlParserType;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author zhihou
|
||||
*/
|
||||
@LoadLevel(name = SqlParserType.SQL_PARSER_TYPE_ANTLR)
|
||||
public class AntlrDelegatingSQLRecognizerFactory implements SQLRecognizerFactory {
|
||||
|
||||
private volatile SQLRecognizerFactory recognizerFactoryImpl;
|
||||
|
||||
public AntlrDelegatingSQLRecognizerFactory() {
|
||||
setClassLoader();
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for unit test
|
||||
*
|
||||
*/
|
||||
void setClassLoader() {
|
||||
try {
|
||||
Class<?> recognizerFactoryImplClass = ClassLoader.getSystemClassLoader().loadClass("io.seata.sqlparser.antlr.mysql.AntlrMySQLRecognizerFactory");
|
||||
Constructor<?> implConstructor = recognizerFactoryImplClass.getDeclaredConstructor();
|
||||
implConstructor.setAccessible(true);
|
||||
try {
|
||||
recognizerFactoryImpl = (SQLRecognizerFactory) implConstructor.newInstance();
|
||||
} finally {
|
||||
implConstructor.setAccessible(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new SQLParsingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SQLRecognizer> create(String sql, String dbType) {
|
||||
return recognizerFactoryImpl.create(sql, dbType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr;
|
||||
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
|
||||
/**
|
||||
* The interface SQLOperateRecognizerHolder
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public interface SQLOperateRecognizerHolder {
|
||||
|
||||
/**
|
||||
* Get delete recognizer
|
||||
*
|
||||
* @param sql the sql
|
||||
* @return the delete recognizer
|
||||
*/
|
||||
SQLRecognizer getDeleteRecognizer(String sql);
|
||||
|
||||
/**
|
||||
* Get insert recognizer
|
||||
*
|
||||
* @param sql the sql
|
||||
* @return the insert recognizer
|
||||
*/
|
||||
SQLRecognizer getInsertRecognizer(String sql);
|
||||
|
||||
/**
|
||||
* Get update recognizer
|
||||
*
|
||||
* @param sql the sql
|
||||
* @return the update recognizer
|
||||
*/
|
||||
SQLRecognizer getUpdateRecognizer(String sql);
|
||||
|
||||
/**
|
||||
* Get SelectForUpdate recognizer
|
||||
*
|
||||
* @param sql the sql
|
||||
* @return the SelectForUpdate recognizer
|
||||
*/
|
||||
SQLRecognizer getSelectForUpdateRecognizer(String sql);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr;
|
||||
|
||||
import io.seata.common.loader.EnhancedServiceLoader;
|
||||
import io.seata.common.util.CollectionUtils;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* The SQLOperateRecognizerHolderFactory
|
||||
*
|
||||
* @author: zhi hou
|
||||
*/
|
||||
public class SQLOperateRecognizerHolderFactory {
|
||||
|
||||
private static final Map<String, SQLOperateRecognizerHolder> RECOGNIZER_HOLDER_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
|
||||
/**
|
||||
* get SQLOperateRecognizer by db type
|
||||
*
|
||||
* @param dbType the db type
|
||||
* @return the SQLOperateRecognizer
|
||||
*/
|
||||
public static SQLOperateRecognizerHolder getSQLRecognizerHolder(String dbType) {
|
||||
return CollectionUtils.computeIfAbsent(RECOGNIZER_HOLDER_MAP, dbType, key -> EnhancedServiceLoader.load(SQLOperateRecognizerHolder.class, dbType, SQLOperateRecognizerHolderFactory.class.getClassLoader()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql;
|
||||
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLDeleteRecognizer;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.antlr.mysql.listener.DeleteSpecificationSqlListener;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlLexer;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.stream.ANTLRNoCaseStringStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AntlrMySQLDeleteRecognizer
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public class AntlrMySQLDeleteRecognizer implements SQLDeleteRecognizer {
|
||||
|
||||
private MySqlContext sqlContext;
|
||||
|
||||
public AntlrMySQLDeleteRecognizer(String sql) {
|
||||
MySqlLexer mySqlLexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
CommonTokenStream commonTokenStream = new CommonTokenStream(mySqlLexer);
|
||||
MySqlParser parser2 = new MySqlParser(commonTokenStream);
|
||||
MySqlParser.RootContext root = parser2.root();
|
||||
ParseTreeWalker walker2 = new ParseTreeWalker();
|
||||
sqlContext = new MySqlContext();
|
||||
sqlContext.setOriginalSQL(sql);
|
||||
walker2.walk(new DeleteSpecificationSqlListener(sqlContext), root);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(ParametersHolder parametersHolder, ArrayList<List<Object>> paramAppenderList) {
|
||||
return sqlContext.getWhereCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
return sqlContext.getWhereCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return sqlContext.tableAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
return sqlContext.tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalSQL() {
|
||||
|
||||
return sqlContext.getOriginalSQL();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,98 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql;
|
||||
|
||||
import io.seata.sqlparser.SQLInsertRecognizer;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlLexer;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.stream.ANTLRNoCaseStringStream;
|
||||
import io.seata.sqlparser.antlr.mysql.visit.InsertStatementSqlVisitor;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* AntlrMySQLInsertRecognizer
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public class AntlrMySQLInsertRecognizer implements SQLInsertRecognizer {
|
||||
|
||||
private MySqlContext sqlContext;
|
||||
|
||||
public AntlrMySQLInsertRecognizer(String sql) {
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
sqlContext = new MySqlContext();
|
||||
sqlContext.setOriginalSQL(sql);
|
||||
InsertStatementSqlVisitor visitor = new InsertStatementSqlVisitor(sqlContext);
|
||||
visitor.visit(rootContext);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.INSERT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return sqlContext.tableAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
return sqlContext.tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalSQL() {
|
||||
return sqlContext.getOriginalSQL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insertColumnsIsEmpty() {
|
||||
|
||||
List<MySqlContext.SQL> insertColumnNames = sqlContext.getInsertColumnNames();
|
||||
|
||||
if (insertColumnNames.isEmpty()) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getInsertColumns() {
|
||||
|
||||
List<MySqlContext.SQL> insertColumnNames = sqlContext.getInsertColumnNames();
|
||||
|
||||
if (insertColumnNames.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
return insertColumnNames.stream().map(insertColumns -> insertColumns.getColumnName()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql;
|
||||
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.SQLRecognizerFactory;
|
||||
import io.seata.sqlparser.antlr.SQLOperateRecognizerHolder;
|
||||
import io.seata.sqlparser.antlr.SQLOperateRecognizerHolderFactory;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlLexer;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.stream.ANTLRNoCaseStringStream;
|
||||
import io.seata.sqlparser.antlr.mysql.visit.StatementSqlVisitor;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AntlrMySQLRecognizerFactory
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
class AntlrMySQLRecognizerFactory implements SQLRecognizerFactory {
|
||||
|
||||
@Override
|
||||
public List<SQLRecognizer> create(String sqlData, String dbType) {
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sqlData));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.SqlStatementsContext sqlStatementsContext = parser.sqlStatements();
|
||||
|
||||
List<MySqlParser.SqlStatementContext> sqlStatementContexts = sqlStatementsContext.sqlStatement();
|
||||
|
||||
List<SQLRecognizer> recognizers = null;
|
||||
SQLRecognizer recognizer = null;
|
||||
|
||||
for (MySqlParser.SqlStatementContext sql : sqlStatementContexts) {
|
||||
|
||||
StatementSqlVisitor visitor = new StatementSqlVisitor();
|
||||
|
||||
String originalSQL = visitor.visit(sql).toString();
|
||||
|
||||
SQLOperateRecognizerHolder recognizerHolder =
|
||||
SQLOperateRecognizerHolderFactory.getSQLRecognizerHolder(dbType.toLowerCase());
|
||||
if (sql.dmlStatement().updateStatement() != null) {
|
||||
recognizer = recognizerHolder.getUpdateRecognizer(originalSQL);
|
||||
} else if (sql.dmlStatement().insertStatement() != null) {
|
||||
recognizer = recognizerHolder.getInsertRecognizer(originalSQL);
|
||||
} else if (sql.dmlStatement().deleteStatement() != null) {
|
||||
recognizer = recognizerHolder.getDeleteRecognizer(originalSQL);
|
||||
} else if (sql.dmlStatement().selectStatement() != null) {
|
||||
recognizer = recognizerHolder.getSelectForUpdateRecognizer(originalSQL);
|
||||
}
|
||||
|
||||
if (recognizer != null) {
|
||||
if (recognizers == null) {
|
||||
recognizers = new ArrayList<>();
|
||||
}
|
||||
recognizers.add(recognizer);
|
||||
}
|
||||
}
|
||||
return recognizers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,80 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql;
|
||||
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLSelectRecognizer;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.antlr.mysql.listener.SelectSpecificationSqlListener;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlLexer;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.stream.ANTLRNoCaseStringStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* AntlrMySQLSelectRecognizer
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public class AntlrMySQLSelectRecognizer implements SQLSelectRecognizer {
|
||||
|
||||
private MySqlContext sqlContext;
|
||||
|
||||
public AntlrMySQLSelectRecognizer(String sql) {
|
||||
MySqlLexer mySqlLexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
CommonTokenStream commonTokenStream = new CommonTokenStream(mySqlLexer);
|
||||
MySqlParser parser = new MySqlParser(commonTokenStream);
|
||||
MySqlParser.RootContext root = parser.root();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
sqlContext = new MySqlContext();
|
||||
sqlContext.setOriginalSQL(sql);
|
||||
walker.walk(new SelectSpecificationSqlListener(sqlContext), root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(ParametersHolder parametersHolder, ArrayList<List<Object>> paramAppenderList) {
|
||||
return sqlContext.getWhereCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
return sqlContext.getWhereCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.SELECT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return sqlContext.tableAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
return sqlContext.tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalSQL() {
|
||||
return sqlContext.getOriginalSQL();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,104 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql;
|
||||
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.SQLUpdateRecognizer;
|
||||
import io.seata.sqlparser.antlr.mysql.listener.UpdateSpecificationSqlListener;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlLexer;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.stream.ANTLRNoCaseStringStream;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* AntlrMySQLUpdateRecognizer
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public class AntlrMySQLUpdateRecognizer implements SQLUpdateRecognizer {
|
||||
|
||||
private MySqlContext sqlContext;
|
||||
|
||||
public AntlrMySQLUpdateRecognizer(String sql) {
|
||||
MySqlLexer mySqlLexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
CommonTokenStream commonTokenStream = new CommonTokenStream(mySqlLexer);
|
||||
MySqlParser parser2 = new MySqlParser(commonTokenStream);
|
||||
MySqlParser.RootContext root = parser2.root();
|
||||
ParseTreeWalker walker2 = new ParseTreeWalker();
|
||||
sqlContext = new MySqlContext();
|
||||
sqlContext.setOriginalSQL(sql);
|
||||
walker2.walk(new UpdateSpecificationSqlListener(sqlContext), root);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUpdateColumns() {
|
||||
|
||||
List<MySqlContext.SQL> updateFoColumnNames = sqlContext.getUpdateFoColumnNames();
|
||||
List<String> sqlList = new ArrayList<>();
|
||||
for (MySqlContext.SQL sql : updateFoColumnNames) {
|
||||
sqlList.add(sql.getUpdateColumn());
|
||||
}
|
||||
return sqlList;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getUpdateValues() {
|
||||
|
||||
List<MySqlContext.SQL> updateForValues = sqlContext.getUpdateForValues();
|
||||
|
||||
if (updateForValues.isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
return updateForValues.stream().map(updateValues -> updateValues.getUpdateValue()).collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(ParametersHolder parametersHolder, ArrayList<List<Object>> paramAppenderList) {
|
||||
return sqlContext.getWhereCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
return sqlContext.getWhereCondition();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return sqlContext.tableAlias;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
return sqlContext.tableName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalSQL() {
|
||||
return sqlContext.getOriginalSQL();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql;
|
||||
|
||||
import io.seata.common.loader.LoadLevel;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.antlr.SQLOperateRecognizerHolder;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
|
||||
/**
|
||||
* The class MySqlOperateRecognizerHolder
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
@LoadLevel(name = JdbcConstants.MYSQL)
|
||||
public class MySQLOperateRecognizerHolder implements SQLOperateRecognizerHolder {
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getDeleteRecognizer(String sql) {
|
||||
return new AntlrMySQLDeleteRecognizer(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getInsertRecognizer(String sql) {
|
||||
return new AntlrMySQLInsertRecognizer(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getUpdateRecognizer(String sql) {
|
||||
return new AntlrMySQLUpdateRecognizer(sql);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getSelectForUpdateRecognizer(String sql) {
|
||||
return new AntlrMySQLSelectRecognizer(sql);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* MySqlContext
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public class MySqlContext {
|
||||
|
||||
/**
|
||||
* Table Name
|
||||
*/
|
||||
public String tableName;
|
||||
|
||||
/**
|
||||
* Table Alias
|
||||
*/
|
||||
public String tableAlias;
|
||||
|
||||
/**
|
||||
* Number of inserts
|
||||
*/
|
||||
public Integer insertRows;
|
||||
|
||||
/**
|
||||
* Where condition
|
||||
*/
|
||||
private String whereCondition;
|
||||
|
||||
/**
|
||||
* Query column name collection
|
||||
*/
|
||||
public List<SQL> queryColumnNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Conditional query column name collection
|
||||
*/
|
||||
public List<SQL> queryWhereColumnNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Conditional query column name corresponding value collection
|
||||
*/
|
||||
public List<SQL> queryWhereValColumnNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Query column name collection
|
||||
*/
|
||||
public List<SQL> insertColumnNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Insert the value set corresponding to the column name
|
||||
*/
|
||||
public List<List<String>> insertForValColumnNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Delete condition column name set
|
||||
*/
|
||||
public List<SQL> deleteForWhereColumnNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Conditional delete column name object value collection
|
||||
*/
|
||||
public List<SQL> deleteForWhereValColumnNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Conditional update condition column name object collection
|
||||
*/
|
||||
public List<SQL> updateForWhereColumnNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Conditional update column name object value collection
|
||||
*/
|
||||
public List<SQL> updateForWhereValColumnNames = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* Update column name object value collection
|
||||
*/
|
||||
public List<SQL> updateFoColumnNames = new ArrayList<>();
|
||||
|
||||
|
||||
/**
|
||||
* Update object value collection
|
||||
*/
|
||||
public List<SQL> updateForValues = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* sql object information collection
|
||||
*/
|
||||
public List<SQL> sqlInfos = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* originalSQL
|
||||
*/
|
||||
private String originalSQL;
|
||||
|
||||
public void addSqlInfo(SQL sql) {
|
||||
sqlInfos.add(sql);
|
||||
}
|
||||
|
||||
public void addForInsertColumnName(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setInsertColumnName(columnName);
|
||||
insertColumnNames.add(sql);
|
||||
}
|
||||
|
||||
public void addForInsertValColumnName(List<String> columnName) {
|
||||
insertForValColumnNames.add(columnName);
|
||||
}
|
||||
|
||||
public void addQueryColumnNames(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setColumnName(columnName);
|
||||
queryColumnNames.add(sql);
|
||||
}
|
||||
|
||||
public void addQueryWhereColumnNames(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setQueryWhereColumnName(columnName);
|
||||
queryWhereColumnNames.add(sql);
|
||||
}
|
||||
|
||||
public void addQueryWhereValColumnNames(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setQueryWhereValColumnName(columnName);
|
||||
queryWhereValColumnNames.add(sql);
|
||||
}
|
||||
|
||||
public void addDeleteWhereColumnNames(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setDeleteWhereColumnName(columnName);
|
||||
deleteForWhereColumnNames.add(sql);
|
||||
}
|
||||
|
||||
public void addDeleteWhereValColumnNames(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setDeleteWhereValColumnName(columnName);
|
||||
deleteForWhereValColumnNames.add(sql);
|
||||
}
|
||||
|
||||
|
||||
public void addUpdateWhereValColumnNames(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setUpdateWhereValColumnName(columnName);
|
||||
updateForWhereValColumnNames.add(sql);
|
||||
}
|
||||
|
||||
|
||||
public void addUpdateWhereColumnNames(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setUpdateWhereColumnName(columnName);
|
||||
updateForWhereColumnNames.add(sql);
|
||||
}
|
||||
|
||||
public void addUpdateColumnNames(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setUpdateColumn(columnName);
|
||||
updateFoColumnNames.add(sql);
|
||||
}
|
||||
|
||||
public void addUpdateValues(String columnName) {
|
||||
SQL sql = new SQL();
|
||||
sql.setUpdateValue(columnName);
|
||||
updateForValues.add(sql);
|
||||
}
|
||||
|
||||
public static class SQL {
|
||||
private String columnName;
|
||||
private String tableName;
|
||||
private String queryWhereValColumnName;
|
||||
private String queryWhereColumnName;
|
||||
private String insertColumnName;
|
||||
private String deleteWhereValColumnName;
|
||||
private String deleteWhereColumnName;
|
||||
private String updateWhereValColumnName;
|
||||
private String updateWhereColumnName;
|
||||
private String updateColumn;
|
||||
private String updateValue;
|
||||
private Integer sqlType;
|
||||
private String sql;
|
||||
|
||||
public String getColumnName() {
|
||||
return columnName;
|
||||
}
|
||||
|
||||
public void setColumnName(String columnName) {
|
||||
this.columnName = columnName;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public String getQueryWhereValColumnName() {
|
||||
return queryWhereValColumnName;
|
||||
}
|
||||
|
||||
public void setQueryWhereValColumnName(String queryWhereValColumnName) {
|
||||
this.queryWhereValColumnName = queryWhereValColumnName;
|
||||
}
|
||||
|
||||
public String getQueryWhereColumnName() {
|
||||
return queryWhereColumnName;
|
||||
}
|
||||
|
||||
public void setQueryWhereColumnName(String queryWhereColumnName) {
|
||||
this.queryWhereColumnName = queryWhereColumnName;
|
||||
}
|
||||
|
||||
public String getInsertColumnName() {
|
||||
return insertColumnName;
|
||||
}
|
||||
|
||||
public void setInsertColumnName(String insertColumnName) {
|
||||
this.insertColumnName = insertColumnName;
|
||||
}
|
||||
|
||||
public String getDeleteWhereValColumnName() {
|
||||
return deleteWhereValColumnName;
|
||||
}
|
||||
|
||||
public void setDeleteWhereValColumnName(String deleteWhereValColumnName) {
|
||||
this.deleteWhereValColumnName = deleteWhereValColumnName;
|
||||
}
|
||||
|
||||
public String getDeleteWhereColumnName() {
|
||||
return deleteWhereColumnName;
|
||||
}
|
||||
|
||||
public void setDeleteWhereColumnName(String deleteWhereColumnName) {
|
||||
this.deleteWhereColumnName = deleteWhereColumnName;
|
||||
}
|
||||
|
||||
public String getUpdateWhereValColumnName() {
|
||||
return updateWhereValColumnName;
|
||||
}
|
||||
|
||||
public void setUpdateWhereValColumnName(String updateWhereValColumnName) {
|
||||
this.updateWhereValColumnName = updateWhereValColumnName;
|
||||
}
|
||||
|
||||
public String getUpdateWhereColumnName() {
|
||||
return updateWhereColumnName;
|
||||
}
|
||||
|
||||
public void setUpdateWhereColumnName(String updateWhereColumnName) {
|
||||
this.updateWhereColumnName = updateWhereColumnName;
|
||||
}
|
||||
|
||||
public String getUpdateColumn() {
|
||||
return updateColumn;
|
||||
}
|
||||
|
||||
public void setUpdateColumn(String updateColumn) {
|
||||
this.updateColumn = updateColumn;
|
||||
}
|
||||
|
||||
public String getUpdateValue() {
|
||||
return updateValue;
|
||||
}
|
||||
|
||||
public void setUpdateValue(String updateValue) {
|
||||
this.updateValue = updateValue;
|
||||
}
|
||||
|
||||
public Integer getSqlType() {
|
||||
return sqlType;
|
||||
}
|
||||
|
||||
public void setSqlType(Integer sqlType) {
|
||||
this.sqlType = sqlType;
|
||||
}
|
||||
|
||||
public String getSql() {
|
||||
return sql;
|
||||
}
|
||||
|
||||
public void setSql(String sql) {
|
||||
this.sql = sql;
|
||||
}
|
||||
}
|
||||
|
||||
public List<SQL> getQueryColumnNames() {
|
||||
return queryColumnNames;
|
||||
}
|
||||
|
||||
public List<SQL> getQueryWhereColumnNames() {
|
||||
return queryWhereColumnNames;
|
||||
}
|
||||
|
||||
public List<SQL> getQueryWhereValColumnNames() {
|
||||
return queryWhereValColumnNames;
|
||||
}
|
||||
|
||||
public List<SQL> getInsertColumnNames() {
|
||||
return insertColumnNames;
|
||||
}
|
||||
|
||||
public List<List<String>> getInsertForValColumnNames() {
|
||||
return insertForValColumnNames;
|
||||
}
|
||||
|
||||
public List<SQL> getDeleteForWhereColumnNames() {
|
||||
return deleteForWhereColumnNames;
|
||||
}
|
||||
|
||||
public List<SQL> getDeleteForWhereValColumnNames() {
|
||||
return deleteForWhereValColumnNames;
|
||||
}
|
||||
|
||||
public List<SQL> getUpdateForWhereColumnNames() {
|
||||
return updateForWhereColumnNames;
|
||||
}
|
||||
|
||||
public List<SQL> getUpdateForWhereValColumnNames() {
|
||||
return updateForWhereValColumnNames;
|
||||
}
|
||||
|
||||
public List<SQL> getUpdateFoColumnNames() {
|
||||
return updateFoColumnNames;
|
||||
}
|
||||
|
||||
public List<SQL> getUpdateForValues() {
|
||||
return updateForValues;
|
||||
}
|
||||
|
||||
public String getTableName() {
|
||||
return tableName;
|
||||
}
|
||||
|
||||
public void setTableName(String tableName) {
|
||||
this.tableName = tableName;
|
||||
}
|
||||
|
||||
public Integer getInsertRows() {
|
||||
return insertRows;
|
||||
}
|
||||
|
||||
public void setInsertRows(Integer insertRows) {
|
||||
this.insertRows = insertRows;
|
||||
}
|
||||
|
||||
public String getWhereCondition() {
|
||||
return whereCondition;
|
||||
}
|
||||
|
||||
public void setWhereCondition(String whereCondition) {
|
||||
this.whereCondition = whereCondition;
|
||||
}
|
||||
|
||||
public List<SQL> getSqlInfos() {
|
||||
return sqlInfos;
|
||||
}
|
||||
|
||||
public String getOriginalSQL() {
|
||||
return originalSQL;
|
||||
}
|
||||
|
||||
public void setOriginalSQL(String originalSQL) {
|
||||
this.originalSQL = originalSQL;
|
||||
}
|
||||
|
||||
public void setTableAlias(String tableAlias) {
|
||||
this.tableAlias = tableAlias;
|
||||
}
|
||||
|
||||
public String getTableAlias() {
|
||||
return tableAlias;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql.listener;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.MySqlContext;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParserBaseListener;
|
||||
import io.seata.sqlparser.antlr.mysql.visit.StatementSqlVisitor;
|
||||
|
||||
/**
|
||||
* @author houzhi
|
||||
*/
|
||||
public class DeleteSpecificationSqlListener extends MySqlParserBaseListener {
|
||||
|
||||
private MySqlContext sqlQueryContext;
|
||||
|
||||
public DeleteSpecificationSqlListener(MySqlContext sqlQueryContext) {
|
||||
this.sqlQueryContext = sqlQueryContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterAtomTableItem(MySqlParser.AtomTableItemContext ctx) {
|
||||
MySqlParser.TableNameContext tableNameContext = ctx.tableName();
|
||||
sqlQueryContext.setTableName(tableNameContext.getText());
|
||||
MySqlParser.UidContext uid = ctx.uid();
|
||||
sqlQueryContext.setTableAlias(uid.getText());
|
||||
super.enterAtomTableItem(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterConstantExpressionAtom(MySqlParser.ConstantExpressionAtomContext ctx) {
|
||||
sqlQueryContext.addDeleteWhereValColumnNames(ctx.getText());
|
||||
super.enterConstantExpressionAtom(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterFullColumnNameExpressionAtom(MySqlParser.FullColumnNameExpressionAtomContext ctx) {
|
||||
sqlQueryContext.addDeleteWhereColumnNames(ctx.getText());
|
||||
super.enterFullColumnNameExpressionAtom(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterSingleDeleteStatement(MySqlParser.SingleDeleteStatementContext ctx) {
|
||||
MySqlParser.TableNameContext tableNameContext = ctx.tableName();
|
||||
sqlQueryContext.setTableName(tableNameContext.getText());
|
||||
MySqlParser.ExpressionContext expression = ctx.expression();
|
||||
StatementSqlVisitor statementSqlVisitor = new StatementSqlVisitor();
|
||||
String text = statementSqlVisitor.visit(expression).toString();
|
||||
sqlQueryContext.setWhereCondition(text);
|
||||
super.enterSingleDeleteStatement(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterMultipleDeleteStatement(MySqlParser.MultipleDeleteStatementContext ctx) {
|
||||
MySqlParser.ExpressionContext expression = ctx.expression();
|
||||
StatementSqlVisitor statementSqlVisitor = new StatementSqlVisitor();
|
||||
String text = statementSqlVisitor.visit(expression).toString();
|
||||
sqlQueryContext.setWhereCondition(text);
|
||||
super.enterMultipleDeleteStatement(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterInPredicate(MySqlParser.InPredicateContext ctx) {
|
||||
StatementSqlVisitor statementSqlVisitor = new StatementSqlVisitor();
|
||||
String text = statementSqlVisitor.visit(ctx).toString();
|
||||
sqlQueryContext.setWhereCondition(text);
|
||||
super.enterInPredicate(ctx);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql.listener;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.MySqlContext;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParserBaseListener;
|
||||
import io.seata.sqlparser.antlr.mysql.visit.StatementSqlVisitor;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author houzhi
|
||||
*/
|
||||
public class SelectSpecificationSqlListener extends MySqlParserBaseListener {
|
||||
|
||||
private MySqlContext sqlQueryContext;
|
||||
|
||||
public SelectSpecificationSqlListener(MySqlContext sqlQueryContext) {
|
||||
this.sqlQueryContext = sqlQueryContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterTableName(MySqlParser.TableNameContext ctx) {
|
||||
|
||||
sqlQueryContext.setTableName(ctx.getText());
|
||||
super.enterTableName(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterAtomTableItem(MySqlParser.AtomTableItemContext ctx) {
|
||||
|
||||
MySqlParser.UidContext uid = ctx.uid();
|
||||
if (uid != null) {
|
||||
String text = uid.getText();
|
||||
if (!text.isEmpty()) {
|
||||
sqlQueryContext.setTableAlias(text);
|
||||
}
|
||||
}
|
||||
super.enterAtomTableItem(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterFromClause(MySqlParser.FromClauseContext ctx) {
|
||||
|
||||
MySqlParser.ExpressionContext whereExpr = ctx.whereExpr;
|
||||
StatementSqlVisitor statementSqlVisitor = new StatementSqlVisitor();
|
||||
String text = statementSqlVisitor.visit(whereExpr).toString();
|
||||
sqlQueryContext.setWhereCondition(text);
|
||||
super.enterFromClause(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterFullColumnNameExpressionAtom(MySqlParser.FullColumnNameExpressionAtomContext ctx) {
|
||||
|
||||
sqlQueryContext.addQueryWhereColumnNames(ctx.getText());
|
||||
super.enterFullColumnNameExpressionAtom(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterConstantExpressionAtom(MySqlParser.ConstantExpressionAtomContext ctx) {
|
||||
|
||||
sqlQueryContext.addQueryWhereValColumnNames(ctx.getText());
|
||||
super.enterConstantExpressionAtom(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterSelectElements(MySqlParser.SelectElementsContext ctx) {
|
||||
|
||||
List<MySqlParser.SelectElementContext> selectElementContexts = ctx.selectElement();
|
||||
for (MySqlParser.SelectElementContext selectElementContext : selectElementContexts) {
|
||||
sqlQueryContext.addQueryColumnNames(selectElementContext.getText());
|
||||
}
|
||||
super.enterSelectElements(ctx);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql.listener;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.MySqlContext;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParserBaseListener;
|
||||
import io.seata.sqlparser.antlr.mysql.visit.StatementSqlVisitor;
|
||||
|
||||
/**
|
||||
* @author houzhi
|
||||
*/
|
||||
public class UpdateSpecificationSqlListener extends MySqlParserBaseListener {
|
||||
|
||||
|
||||
private MySqlContext sqlQueryContext;
|
||||
|
||||
public UpdateSpecificationSqlListener(MySqlContext sqlQueryContext) {
|
||||
this.sqlQueryContext = sqlQueryContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterTableName(MySqlParser.TableNameContext ctx) {
|
||||
|
||||
sqlQueryContext.setTableName(ctx.getText());
|
||||
super.enterTableName(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterConstantExpressionAtomForUpdate(MySqlParser.ConstantExpressionAtomForUpdateContext ctx) {
|
||||
|
||||
sqlQueryContext.addUpdateWhereValColumnNames(ctx.getText());
|
||||
super.enterConstantExpressionAtomForUpdate(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterFullColumnNameExpressionAtomForUpdate(MySqlParser.FullColumnNameExpressionAtomForUpdateContext ctx) {
|
||||
|
||||
sqlQueryContext.addUpdateWhereColumnNames(ctx.getText());
|
||||
super.enterFullColumnNameExpressionAtomForUpdate(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterSingleUpdateStatement(MySqlParser.SingleUpdateStatementContext ctx) {
|
||||
|
||||
MySqlParser.ExpressionForUpdateContext expressionForUpdateContext = ctx.expressionForUpdate();
|
||||
StatementSqlVisitor statementSqlVisitor = new StatementSqlVisitor();
|
||||
String text = statementSqlVisitor.visit(expressionForUpdateContext).toString();
|
||||
sqlQueryContext.setWhereCondition(text);
|
||||
|
||||
MySqlParser.UidContext uid = ctx.uid();
|
||||
|
||||
if (uid != null) {
|
||||
String alias = uid.getText();
|
||||
if (!text.isEmpty()) {
|
||||
sqlQueryContext.setTableAlias(alias);
|
||||
}
|
||||
}
|
||||
super.enterSingleUpdateStatement(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void enterUpdatedElement(MySqlParser.UpdatedElementContext ctx) {
|
||||
|
||||
MySqlParser.ExpressionContext expression = ctx.expression();
|
||||
sqlQueryContext.addUpdateValues(expression.getText());
|
||||
|
||||
MySqlParser.FullColumnNameContext fullColumnNameContext = ctx.fullColumnName();
|
||||
sqlQueryContext.addUpdateColumnNames(fullColumnNameContext.getText());
|
||||
|
||||
super.enterUpdatedElement(ctx);
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql.stream;
|
||||
|
||||
import org.antlr.v4.runtime.ANTLRInputStream;
|
||||
import org.antlr.v4.runtime.IntStream;
|
||||
|
||||
/**
|
||||
* ANTLRNoCaseStringStream
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public class ANTLRNoCaseStringStream extends ANTLRInputStream {
|
||||
|
||||
public ANTLRNoCaseStringStream(String input) {
|
||||
super(input);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int LA(int i) {
|
||||
int la = super.LA(i);
|
||||
if (la == 0 || la == IntStream.EOF) {
|
||||
return la;
|
||||
} else {
|
||||
return Character.toUpperCase(la);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql.visit;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.MySqlContext;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParserBaseVisitor;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* InsertSpecificationSqlVisitor
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public class InsertSpecificationSqlVisitor extends MySqlParserBaseVisitor<MySqlContext> {
|
||||
|
||||
private MySqlContext mySqlContext;
|
||||
|
||||
public InsertSpecificationSqlVisitor(MySqlContext mySqlContext) {
|
||||
this.mySqlContext = mySqlContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MySqlContext visitInsertStatement(MySqlParser.InsertStatementContext ctx) {
|
||||
|
||||
MySqlParser.TableNameContext tableNameContext = ctx.tableName();
|
||||
|
||||
mySqlContext.setTableName(tableNameContext.getText());
|
||||
|
||||
MySqlParser.UidListContext columns = ctx.columns;
|
||||
|
||||
List<String> strings = Arrays.asList(columns.getText().split(","));
|
||||
|
||||
for (String insertColumnName : strings) {
|
||||
mySqlContext.addForInsertColumnName(insertColumnName);
|
||||
}
|
||||
|
||||
MySqlParser.InsertStatementValueContext insertStatementValueContext = ctx.insertStatementValue();
|
||||
List<MySqlParser.ExpressionsWithDefaultsContext> expressionsWithDefaultsContexts = insertStatementValueContext.expressionsWithDefaults();
|
||||
|
||||
for (MySqlParser.ExpressionsWithDefaultsContext expressions : expressionsWithDefaultsContexts) {
|
||||
|
||||
String text = expressions.getText();
|
||||
String str = null;
|
||||
if (text.contains("'")) {
|
||||
str = text.replace("'", "");
|
||||
} else if (text.contains("\"")) {
|
||||
str = text.replace("\"", "");
|
||||
} else {
|
||||
str = text;
|
||||
}
|
||||
if (!str.isEmpty() && !str.contains("'") && !str.contains("\"")) {
|
||||
mySqlContext.addForInsertValColumnName(Arrays.asList(str.split(",")));
|
||||
}
|
||||
}
|
||||
mySqlContext.setInsertRows(expressionsWithDefaultsContexts.size());
|
||||
return this.mySqlContext;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql.visit;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.MySqlContext;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParserBaseVisitor;
|
||||
|
||||
/**
|
||||
* InsertStatementSqlVisitor
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public class InsertStatementSqlVisitor extends MySqlParserBaseVisitor<MySqlContext> {
|
||||
|
||||
private MySqlContext mySqlContext;
|
||||
|
||||
public InsertStatementSqlVisitor(MySqlContext mySqlContext) {
|
||||
this.mySqlContext = mySqlContext;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MySqlContext visitInsertStatement(MySqlParser.InsertStatementContext ctx) {
|
||||
return new InsertSpecificationSqlVisitor(this.mySqlContext).visitInsertStatement(ctx);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr.mysql.visit;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParserBaseVisitor;
|
||||
import org.antlr.v4.runtime.tree.TerminalNode;
|
||||
|
||||
/**
|
||||
* StatementSqlVisitor
|
||||
*
|
||||
* @author zhihou
|
||||
*/
|
||||
public class StatementSqlVisitor extends MySqlParserBaseVisitor<StringBuilder> {
|
||||
|
||||
private StringBuilder sb = new StringBuilder();
|
||||
|
||||
@Override
|
||||
public StringBuilder visitTerminal(TerminalNode node) {
|
||||
String text = node.getText();
|
||||
if (text != null && !"".equals(text.trim())) {
|
||||
if (shouldAddSpace(text.trim())) {
|
||||
sb.append(" ");
|
||||
}
|
||||
sb.append(text);
|
||||
}
|
||||
return sb;
|
||||
}
|
||||
|
||||
private boolean shouldAddSpace(String text) {
|
||||
if (sb.length() == 0) {
|
||||
return false;
|
||||
}
|
||||
char lastChar = sb.charAt(sb.length() - 1);
|
||||
switch (lastChar) {
|
||||
case '.':
|
||||
case ',':
|
||||
case '(':
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
switch (text.charAt(0)) {
|
||||
case '.':
|
||||
case ',':
|
||||
case ')':
|
||||
return false;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
io.seata.sqlparser.antlr.AntlrDelegatingSQLRecognizerFactory
|
||||
@@ -0,0 +1 @@
|
||||
io.seata.sqlparser.antlr.mysql.MySQLOperateRecognizerHolder
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr;
|
||||
|
||||
import io.seata.common.loader.EnhancedServiceLoader;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.SQLRecognizerFactory;
|
||||
import io.seata.sqlparser.SqlParserType;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author zhihou
|
||||
*/
|
||||
public class AntlrIsolationTest {
|
||||
|
||||
String TEST_SQL = "SELECT name,phone FROM t1 WHERE id = 1 and username = '11' and age = 'a' or hz = '1' or aa = 1 FOR UPDATE";
|
||||
|
||||
@Test
|
||||
public void testAntlrIsolation() {
|
||||
AntlrDelegatingSQLRecognizerFactory recognizerFactory = (AntlrDelegatingSQLRecognizerFactory) EnhancedServiceLoader.load(SQLRecognizerFactory.class, SqlParserType.SQL_PARSER_TYPE_ANTLR);
|
||||
List<SQLRecognizer> sqlRecognizer = recognizerFactory.create(TEST_SQL, JdbcConstants.MYSQL);
|
||||
Assertions.assertNotNull(sqlRecognizer);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,175 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.MySqlContext;
|
||||
import io.seata.sqlparser.antlr.mysql.listener.DeleteSpecificationSqlListener;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlLexer;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.stream.ANTLRNoCaseStringStream;
|
||||
import io.seata.sqlparser.antlr.mysql.visit.StatementSqlVisitor;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author houzhi
|
||||
* @date 2020-7-10
|
||||
* @description
|
||||
*/
|
||||
public class MySQLDeleteRecognizerTest {
|
||||
|
||||
/**
|
||||
* base statementSql visitor test
|
||||
*/
|
||||
private String baseStatementSqlVisitor(String sql) {
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
MySqlParser.SqlStatementContext sqlStatementContext = parser.sqlStatement();
|
||||
StatementSqlVisitor sqlToStringVisitor = new StatementSqlVisitor();
|
||||
return sqlToStringVisitor.visit(sqlStatementContext).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recognizer test 0.
|
||||
*/
|
||||
@Test
|
||||
public void deleteRecognizerTest_0() {
|
||||
|
||||
String sql = "DELETE t FROM t1 as t WHERE t.id = 'id1'";
|
||||
|
||||
String visitorText = baseStatementSqlVisitor(sql);
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(visitorText));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new DeleteSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", mySqlContext.getTableName());
|
||||
Assertions.assertEquals("t.id = 'id1'", mySqlContext.getWhereCondition());
|
||||
Assertions.assertEquals("t", mySqlContext.getTableAlias());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void deleteRecognizerTest_1() {
|
||||
|
||||
String sql = "DELETE FROM t1 WHERE id = 'id1'";
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new DeleteSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("'id1'",
|
||||
mySqlContext.getDeleteForWhereValColumnNames().get(0).getDeleteWhereValColumnName());
|
||||
Assertions.assertEquals("id = 'id1'", mySqlContext.getWhereCondition());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void deleteRecognizerTest_2() {
|
||||
|
||||
String sql = "DELETE FROM t1 WHERE id = ?";
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new DeleteSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("?",
|
||||
mySqlContext.getDeleteForWhereValColumnNames().get(0).getDeleteWhereValColumnName());
|
||||
Assertions.assertEquals("id = ?", mySqlContext.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recognizer test 2.
|
||||
*/
|
||||
@Test
|
||||
public void deleteRecognizerTest_3() {
|
||||
|
||||
String sql = "DELETE FROM t1 WHERE id IN (1, 2)";
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new DeleteSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", mySqlContext.getTableName());
|
||||
Assertions.assertEquals("2", mySqlContext.getDeleteForWhereValColumnNames().get(1).getDeleteWhereValColumnName());
|
||||
Assertions.assertEquals("id IN (1,2)", mySqlContext.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recognizer test 3.
|
||||
*/
|
||||
@Test
|
||||
public void deleteRecognizerTest_4() {
|
||||
|
||||
String sql = "DELETE FROM t1 WHERE id between 1 AND 'id'";
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new DeleteSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("'id'", mySqlContext.getDeleteForWhereValColumnNames().get(1).getDeleteWhereValColumnName());
|
||||
Assertions.assertEquals("id between 1 AND 'id'", mySqlContext.getWhereCondition());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.MySqlContext;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlLexer;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.stream.ANTLRNoCaseStringStream;
|
||||
import io.seata.sqlparser.antlr.mysql.visit.InsertStatementSqlVisitor;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* @author houzhi
|
||||
* @date 2020-7-10
|
||||
* @description
|
||||
*/
|
||||
public class MySQLInsertRecognizerTest {
|
||||
|
||||
/**
|
||||
* Insert recognizer test 0.
|
||||
*/
|
||||
@Test
|
||||
public void insertRecognizerTest_0() {
|
||||
|
||||
String sql = "INSERT INTO t1 (id) VALUES (1)";
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext visitorSqlContext = new MySqlContext();
|
||||
InsertStatementSqlVisitor visitor = new InsertStatementSqlVisitor(visitorSqlContext);
|
||||
visitor.visit(rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", visitorSqlContext.tableName);
|
||||
Assertions.assertEquals(Collections.singletonList("id"), Arrays.asList(visitorSqlContext.getInsertColumnNames().get(0).getInsertColumnName()));
|
||||
Assertions.assertEquals(1, visitorSqlContext.insertRows);
|
||||
Assertions.assertEquals(Arrays.asList("1"), visitorSqlContext.getInsertForValColumnNames().get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void insertRecognizerTest_1() {
|
||||
|
||||
String sql = "INSERT INTO t1 (name1, name2) VALUES ('name1', 12)";
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext visitorSqlContext = new MySqlContext();
|
||||
InsertStatementSqlVisitor visitor = new InsertStatementSqlVisitor(visitorSqlContext);
|
||||
visitor.visit(rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", visitorSqlContext.tableName);
|
||||
Assertions.assertEquals(Arrays.asList("name1", "name2"), visitorSqlContext.getInsertColumnNames().stream().map(insert -> {
|
||||
return insert.getInsertColumnName();
|
||||
}).collect(Collectors.toList()));
|
||||
Assertions.assertEquals(1, visitorSqlContext.insertRows);
|
||||
Assertions.assertEquals(Arrays.asList("name1", "12"), visitorSqlContext.getInsertForValColumnNames().get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert recognizer test 3.
|
||||
*/
|
||||
@Test
|
||||
public void insertRecognizerTest_3() {
|
||||
|
||||
String sql = "INSERT INTO t1 (name1, name2) VALUES ('name1', 'name2'), ('name3', 'name4'), ('name5', 'name6')";
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext visitorSqlContext = new MySqlContext();
|
||||
InsertStatementSqlVisitor visitor = new InsertStatementSqlVisitor(visitorSqlContext);
|
||||
visitor.visit(rootContext);
|
||||
|
||||
|
||||
Assertions.assertEquals("t1", visitorSqlContext.tableName);
|
||||
Assertions.assertEquals("name2", visitorSqlContext.getInsertColumnNames().get(1).getInsertColumnName());
|
||||
|
||||
Integer insertRows = visitorSqlContext.insertRows;
|
||||
Assertions.assertEquals(3, insertRows);
|
||||
|
||||
Assertions.assertEquals(Arrays.asList("name1", "name2"), visitorSqlContext.getInsertForValColumnNames().get(0));
|
||||
Assertions.assertEquals(Arrays.asList("name3", "name4"), visitorSqlContext.getInsertForValColumnNames().get(1));
|
||||
Assertions.assertEquals(Arrays.asList("name5", "name6"), visitorSqlContext.getInsertForValColumnNames().get(2));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.MySqlContext;
|
||||
import io.seata.sqlparser.antlr.mysql.listener.SelectSpecificationSqlListener;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlLexer;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.stream.ANTLRNoCaseStringStream;
|
||||
import io.seata.sqlparser.antlr.mysql.visit.StatementSqlVisitor;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author houzhi
|
||||
* @date 2020-7-9
|
||||
* @description
|
||||
*/
|
||||
public class MySQLSelectForUpdateRecognizerForListenerTest {
|
||||
|
||||
/**
|
||||
* base statementSql visitor test
|
||||
*/
|
||||
private String baseStatementSqlVisitor(String sql) {
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
MySqlParser.SqlStatementContext sqlStatementContext = parser.sqlStatement();
|
||||
StatementSqlVisitor sqlToStringVisitor = new StatementSqlVisitor();
|
||||
return sqlToStringVisitor.visit(sqlStatementContext).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 0.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_0() {
|
||||
|
||||
String sql = "SELECT a FROM t1 b WHERE b.id = d FOR UPDATE";
|
||||
|
||||
String visitorText = baseStatementSqlVisitor(sql);
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(visitorText));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext listenerSqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new SelectSpecificationSqlListener(listenerSqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", listenerSqlContext.getTableName());
|
||||
Assertions.assertEquals("b.id = d", listenerSqlContext.getWhereCondition());
|
||||
Assertions.assertEquals("b", listenerSqlContext.getTableAlias());
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_1() {
|
||||
|
||||
String sql = "SELECT name,age,phone FROM t1 WHERE id = 'id1' FOR UPDATE";
|
||||
|
||||
String visitorText = baseStatementSqlVisitor(sql);
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(visitorText));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext listenerSqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new SelectSpecificationSqlListener(listenerSqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", listenerSqlContext.getTableName());
|
||||
Assertions.assertEquals("phone", listenerSqlContext.getQueryColumnNames().get(2).getColumnName());
|
||||
Assertions.assertEquals("id = 'id1'", listenerSqlContext.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_2() {
|
||||
|
||||
String sql = "SELECT name,age,phone FROM t2 WHERE id = 'id'FOR UPDATE";
|
||||
|
||||
String visitorText = baseStatementSqlVisitor(sql);
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(visitorText));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new SelectSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("t2", mySqlContext.getTableName());
|
||||
Assertions.assertEquals("phone", mySqlContext.getQueryColumnNames().get(2).getColumnName());
|
||||
Assertions.assertEquals("id = 'id'", mySqlContext.getWhereCondition());
|
||||
Assertions.assertEquals("id", mySqlContext.getQueryWhereColumnNames().get(0).getQueryWhereColumnName());
|
||||
Assertions.assertEquals("'id'", mySqlContext.getQueryWhereValColumnNames().get(0).getQueryWhereValColumnName());
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_3() {
|
||||
|
||||
String sql = "SELECT name,phone FROM t1 WHERE id = 1 and username = '11' and age = 'a' or hz = '1' or aa = 1 FOR UPDATE";
|
||||
|
||||
String visitorText = baseStatementSqlVisitor(sql);
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(visitorText));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new SelectSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
|
||||
Assertions.assertEquals("t1", mySqlContext.getTableName());
|
||||
Assertions.assertEquals("name", mySqlContext.getQueryColumnNames().get(0).getColumnName());
|
||||
Assertions.assertEquals("username", mySqlContext.getQueryWhereColumnNames().get(1).getQueryWhereColumnName());
|
||||
Assertions.assertEquals("'a'", mySqlContext.getQueryWhereValColumnNames().get(2).getQueryWhereValColumnName());
|
||||
Assertions.assertEquals("id = 1 and username = '11' and age = 'a' or hz = '1' or aa = 1", mySqlContext.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 4.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_4() {
|
||||
|
||||
String sql = "SELECT name1, name2 FROM t1 WHERE id IN (100,101) FOR UPDATE";
|
||||
|
||||
String visitorText = baseStatementSqlVisitor(sql);
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(visitorText));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new SelectSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", mySqlContext.getTableName());
|
||||
Assertions.assertEquals("name1", mySqlContext.getQueryColumnNames().get(0).getColumnName());
|
||||
Assertions.assertEquals("id", mySqlContext.getQueryWhereColumnNames().get(0).getQueryWhereColumnName());
|
||||
Assertions.assertEquals("101", mySqlContext.getQueryWhereValColumnNames().get(1).getQueryWhereValColumnName());
|
||||
Assertions.assertEquals("id IN (100,101)", mySqlContext.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 5.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_5() {
|
||||
|
||||
String sql = "SELECT name1, name2 FROM t1 WHERE name = 1 and id between 2 and 3 or img = '11' FOR UPDATE";
|
||||
|
||||
String visitorText = baseStatementSqlVisitor(sql);
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(visitorText));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new SelectSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", mySqlContext.getTableName());
|
||||
Assertions.assertEquals("name1", mySqlContext.getQueryColumnNames().get(0).getColumnName());
|
||||
Assertions.assertEquals("id", mySqlContext.getQueryWhereColumnNames().get(1).getQueryWhereColumnName());
|
||||
Assertions.assertEquals("3", mySqlContext.getQueryWhereValColumnNames().get(2).getQueryWhereValColumnName());
|
||||
Assertions.assertEquals("name = 1 and id between 2 and 3 or img = '11'", mySqlContext.getWhereCondition());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,190 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.antlr;
|
||||
|
||||
import io.seata.sqlparser.antlr.mysql.MySqlContext;
|
||||
import io.seata.sqlparser.antlr.mysql.listener.UpdateSpecificationSqlListener;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlLexer;
|
||||
import io.seata.sqlparser.antlr.mysql.parser.MySqlParser;
|
||||
import io.seata.sqlparser.antlr.mysql.stream.ANTLRNoCaseStringStream;
|
||||
import io.seata.sqlparser.antlr.mysql.visit.StatementSqlVisitor;
|
||||
import org.antlr.v4.runtime.CommonTokenStream;
|
||||
import org.antlr.v4.runtime.tree.ParseTreeWalker;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The type My sql update recognizer test.
|
||||
*/
|
||||
public class MySQLUpdateRecognizerTest {
|
||||
|
||||
/**
|
||||
* base statementSql visitor test
|
||||
*/
|
||||
private String baseStatementSqlVisitor(String sql) {
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
MySqlParser.SqlStatementContext sqlStatementContext = parser.sqlStatement();
|
||||
StatementSqlVisitor sqlToStringVisitor = new StatementSqlVisitor();
|
||||
return sqlToStringVisitor.visit(sqlStatementContext).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 0.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_0() {
|
||||
|
||||
String sql = "UPDATE t1 a SET a.name = 'name1' WHERE a.id = 'id1'";
|
||||
|
||||
String visitorText = baseStatementSqlVisitor(sql);
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(visitorText));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new UpdateSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", mySqlContext.getTableName());
|
||||
Assertions.assertEquals(1, mySqlContext.getUpdateForValues().size());
|
||||
Assertions.assertEquals("a.id", mySqlContext.getUpdateForWhereColumnNames().get(0).getUpdateWhereColumnName());
|
||||
Assertions.assertEquals("a.name", mySqlContext.getUpdateFoColumnNames().get(0).getUpdateColumn());
|
||||
Assertions.assertEquals("a.id = 'id1'", mySqlContext.getWhereCondition());
|
||||
Assertions.assertEquals("a", mySqlContext.getTableAlias());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_1() {
|
||||
|
||||
String sql = "UPDATE t1 SET name1 = name1, name2 = name2 WHERE id = 'id1'";
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new UpdateSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("t1", mySqlContext.getTableName());
|
||||
Assertions.assertEquals("name1", mySqlContext.getUpdateFoColumnNames().get(0).getUpdateColumn());
|
||||
Assertions.assertEquals("name1", mySqlContext.getUpdateForValues().get(0).getUpdateValue());
|
||||
Assertions.assertEquals("name2", mySqlContext.getUpdateFoColumnNames().get(1).getUpdateColumn());
|
||||
Assertions.assertEquals("name2", mySqlContext.getUpdateForValues().get(1).getUpdateValue());
|
||||
Assertions.assertEquals("id = 'id1'", mySqlContext.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 2.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_2() {
|
||||
|
||||
String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id = ?";
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new UpdateSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
List<MySqlContext.SQL> updateForWhereValColumnNames = mySqlContext.getUpdateForWhereValColumnNames();
|
||||
|
||||
System.out.println(updateForWhereValColumnNames);
|
||||
|
||||
Assertions.assertEquals("?", mySqlContext.getUpdateForWhereValColumnNames().get(0).getUpdateWhereValColumnName());
|
||||
Assertions.assertEquals("name1", mySqlContext.getUpdateFoColumnNames().get(0).getUpdateColumn());
|
||||
Assertions.assertEquals("name2", mySqlContext.getUpdateFoColumnNames().get(1).getUpdateColumn());
|
||||
Assertions.assertEquals("id = ?", mySqlContext.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 3.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_3() {
|
||||
|
||||
String sql = "UPDATE t1 as t SET t.name1 = 'name1', t.name2 = 'name2' WHERE id in (1, 2)";
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new UpdateSpecificationSqlListener(mySqlContext), rootContext);
|
||||
|
||||
Assertions.assertEquals("1", mySqlContext.getUpdateForWhereValColumnNames().get(0).getUpdateWhereValColumnName());
|
||||
Assertions.assertEquals("t1", mySqlContext.getTableName());
|
||||
Assertions.assertEquals("t.name1", mySqlContext.getUpdateFoColumnNames().get(0).getUpdateColumn());
|
||||
Assertions.assertEquals("'name1'", mySqlContext.getUpdateForValues().get(0).getUpdateValue());
|
||||
Assertions.assertEquals("t.name2", mySqlContext.getUpdateFoColumnNames().get(1).getUpdateColumn());
|
||||
Assertions.assertEquals("id in (1,2)", mySqlContext.getWhereCondition());
|
||||
Assertions.assertEquals("t", mySqlContext.getTableAlias());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 5.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_5() {
|
||||
|
||||
String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id between 1 and 2";
|
||||
|
||||
MySqlLexer lexer = new MySqlLexer(new ANTLRNoCaseStringStream(sql));
|
||||
|
||||
CommonTokenStream tokenStream = new CommonTokenStream(lexer);
|
||||
|
||||
MySqlParser parser = new MySqlParser(tokenStream);
|
||||
|
||||
MySqlParser.RootContext rootContext = parser.root();
|
||||
|
||||
MySqlContext mySqlContext = new MySqlContext();
|
||||
ParseTreeWalker walker = new ParseTreeWalker();
|
||||
walker.walk(new UpdateSpecificationSqlListener(mySqlContext), rootContext);
|
||||
Assertions.assertEquals("t1", mySqlContext.getTableName());
|
||||
Assertions.assertEquals("name1", mySqlContext.getUpdateFoColumnNames().get(0).getUpdateColumn());
|
||||
Assertions.assertEquals("'name1'", mySqlContext.getUpdateForValues().get(0).getUpdateValue());
|
||||
Assertions.assertEquals("name2", mySqlContext.getUpdateFoColumnNames().get(1).getUpdateColumn());
|
||||
Assertions.assertEquals("2", mySqlContext.getUpdateForWhereValColumnNames().get(1).getUpdateWhereValColumnName());
|
||||
Assertions.assertEquals("id between 1 and 2", mySqlContext.getWhereCondition());
|
||||
}
|
||||
}
|
||||
34
sqlparser/seata-sqlparser-core/pom.xml
Normal file
34
sqlparser/seata-sqlparser-core/pom.xml
Normal file
@@ -0,0 +1,34 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 1999-2019 Seata.io Group.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-sqlparser</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>seata-sqlparser-core</artifactId>
|
||||
<name>seata-sqlparser-core ${project.version}</name>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>seata-common</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* The interface Parameters holder.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public interface ParametersHolder {
|
||||
|
||||
/**
|
||||
* Get parameters array list [ ].
|
||||
*
|
||||
* @return the array list [ ]
|
||||
*/
|
||||
Map<Integer,ArrayList<Object>> getParameters();
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
/**
|
||||
* The interface Sql delete recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public interface SQLDeleteRecognizer extends WhereRecognizer {
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The interface Sql insert recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public interface SQLInsertRecognizer extends SQLRecognizer {
|
||||
|
||||
/**
|
||||
* insert columns is empty.
|
||||
* @return true: empty. false: not empty.
|
||||
*/
|
||||
boolean insertColumnsIsEmpty();
|
||||
|
||||
/**
|
||||
* Gets insert columns.
|
||||
*
|
||||
* @return the insert columns
|
||||
*/
|
||||
List<String> getInsertColumns();
|
||||
|
||||
/**
|
||||
* Gets insert rows.
|
||||
*
|
||||
* @param primaryKeyIndex insert sql primary key index.
|
||||
* @return the insert rows
|
||||
*/
|
||||
List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex);
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
/**
|
||||
* The type Sql parsing exception.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public class SQLParsingException extends RuntimeException {
|
||||
/**
|
||||
* Instantiates a new Sql parsing exception.
|
||||
*
|
||||
* @param message the message
|
||||
*/
|
||||
public SQLParsingException(String message) {
|
||||
super(message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Sql parsing exception.
|
||||
*
|
||||
* @param message the message
|
||||
* @param cause the cause
|
||||
*/
|
||||
public SQLParsingException(String message, Throwable cause) {
|
||||
super(message, cause);
|
||||
}
|
||||
|
||||
/**
|
||||
* Instantiates a new Sql parsing exception.
|
||||
*
|
||||
* @param cause the cause
|
||||
*/
|
||||
public SQLParsingException(Throwable cause) {
|
||||
super(cause);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
/**
|
||||
* The interface Sql recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public interface SQLRecognizer {
|
||||
|
||||
/**
|
||||
* Type of the SQL. INSERT/UPDATE/DELETE ...
|
||||
*
|
||||
* @return sql type
|
||||
*/
|
||||
SQLType getSQLType();
|
||||
|
||||
/**
|
||||
* TableRecords source related in the SQL, including alias if any.
|
||||
* SELECT id, name FROM user u WHERE ...
|
||||
* Alias should be 'u' for this SQL.
|
||||
*
|
||||
* @return table source.
|
||||
*/
|
||||
String getTableAlias();
|
||||
|
||||
/**
|
||||
* TableRecords name related in the SQL.
|
||||
* SELECT id, name FROM user u WHERE ...
|
||||
* TableRecords name should be 'user' for this SQL, without alias 'u'.
|
||||
*
|
||||
* @return table name.
|
||||
* @see #getTableAlias() #getTableAlias()#getTableAlias()
|
||||
*/
|
||||
String getTableName();
|
||||
|
||||
/**
|
||||
* Return the original SQL input by the upper application.
|
||||
*
|
||||
* @return The original SQL.
|
||||
*/
|
||||
String getOriginalSQL();
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
public interface SQLRecognizerFactory {
|
||||
List<SQLRecognizer> create(String sql, String dbType);
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
/**
|
||||
* The interface Sql select recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public interface SQLSelectRecognizer extends WhereRecognizer {
|
||||
}
|
||||
@@ -0,0 +1,245 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
/**
|
||||
* The enum Sql type.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public enum SQLType {
|
||||
|
||||
/**
|
||||
* Select sql type.
|
||||
*/
|
||||
SELECT(0),
|
||||
/**
|
||||
* Insert sql type.
|
||||
*/
|
||||
INSERT(1),
|
||||
/**
|
||||
* Update sql type.
|
||||
*/
|
||||
UPDATE(2),
|
||||
/**
|
||||
* Delete sql type.
|
||||
*/
|
||||
DELETE(3),
|
||||
/**
|
||||
* Select for update sql type.
|
||||
*/
|
||||
SELECT_FOR_UPDATE(4),
|
||||
/**
|
||||
* Replace sql type.
|
||||
*/
|
||||
REPLACE(5),
|
||||
/**
|
||||
* Truncate sql type.
|
||||
*/
|
||||
TRUNCATE(6),
|
||||
/**
|
||||
* Create sql type.
|
||||
*/
|
||||
CREATE(7),
|
||||
/**
|
||||
* Drop sql type.
|
||||
*/
|
||||
DROP(8),
|
||||
/**
|
||||
* Load sql type.
|
||||
*/
|
||||
LOAD(9),
|
||||
/**
|
||||
* Merge sql type.
|
||||
*/
|
||||
MERGE(10),
|
||||
/**
|
||||
* Show sql type.
|
||||
*/
|
||||
SHOW(11),
|
||||
/**
|
||||
* Alter sql type.
|
||||
*/
|
||||
ALTER(12),
|
||||
/**
|
||||
* Rename sql type.
|
||||
*/
|
||||
RENAME(13),
|
||||
/**
|
||||
* Dump sql type.
|
||||
*/
|
||||
DUMP(14),
|
||||
/**
|
||||
* Debug sql type.
|
||||
*/
|
||||
DEBUG(15),
|
||||
/**
|
||||
* Explain sql type.
|
||||
*/
|
||||
EXPLAIN(16),
|
||||
/**
|
||||
* Stored procedure
|
||||
*/
|
||||
PROCEDURE(17),
|
||||
/**
|
||||
* Desc sql type.
|
||||
*/
|
||||
DESC(18),
|
||||
/**
|
||||
* Select last insert id
|
||||
*/
|
||||
SELECT_LAST_INSERT_ID(19),
|
||||
/**
|
||||
* Select without table sql type.
|
||||
*/
|
||||
SELECT_WITHOUT_TABLE(20),
|
||||
/**
|
||||
* Create sequence sql type.
|
||||
*/
|
||||
CREATE_SEQUENCE(21),
|
||||
/**
|
||||
* Show sequences sql type.
|
||||
*/
|
||||
SHOW_SEQUENCES(22),
|
||||
/**
|
||||
* Get sequence sql type.
|
||||
*/
|
||||
GET_SEQUENCE(23),
|
||||
/**
|
||||
* Alter sequence sql type.
|
||||
*/
|
||||
ALTER_SEQUENCE(24),
|
||||
/**
|
||||
* Drop sequence sql type.
|
||||
*/
|
||||
DROP_SEQUENCE(25),
|
||||
/**
|
||||
* Tddl show sql type.
|
||||
*/
|
||||
TDDL_SHOW(26),
|
||||
/**
|
||||
* Set sql type.
|
||||
*/
|
||||
SET(27),
|
||||
/**
|
||||
* Reload sql type.
|
||||
*/
|
||||
RELOAD(28),
|
||||
/**
|
||||
* Select union sql type.
|
||||
*/
|
||||
SELECT_UNION(29),
|
||||
/**
|
||||
* Create table sql type.
|
||||
*/
|
||||
CREATE_TABLE(30),
|
||||
/**
|
||||
* Drop table sql type.
|
||||
*/
|
||||
DROP_TABLE(31),
|
||||
/**
|
||||
* Alter table sql type.
|
||||
*/
|
||||
ALTER_TABLE(32),
|
||||
/**
|
||||
* Save point sql type.
|
||||
*/
|
||||
SAVE_POINT(33),
|
||||
/**
|
||||
* Select from update sql type.
|
||||
*/
|
||||
SELECT_FROM_UPDATE(34),
|
||||
/**
|
||||
* multi delete/update
|
||||
*/
|
||||
MULTI_DELETE(35),
|
||||
/**
|
||||
* Multi update sql type.
|
||||
*/
|
||||
MULTI_UPDATE(36),
|
||||
/**
|
||||
* Create index sql type.
|
||||
*/
|
||||
CREATE_INDEX(37),
|
||||
/**
|
||||
* Drop index sql type.
|
||||
*/
|
||||
DROP_INDEX(38),
|
||||
/**
|
||||
* Kill sql type.
|
||||
*/
|
||||
KILL(39),
|
||||
/**
|
||||
* Release dblock sql type.
|
||||
*/
|
||||
RELEASE_DBLOCK(40),
|
||||
/**
|
||||
* Lock tables sql type.
|
||||
*/
|
||||
LOCK_TABLES(41),
|
||||
/**
|
||||
* Unlock tables sql type.
|
||||
*/
|
||||
UNLOCK_TABLES(42),
|
||||
/**
|
||||
* Check table sql type.
|
||||
*/
|
||||
CHECK_TABLE(43),
|
||||
|
||||
/**
|
||||
* Select found rows.
|
||||
*/
|
||||
SELECT_FOUND_ROWS(44),
|
||||
|
||||
/**
|
||||
* Insert ignore sql type.
|
||||
*/
|
||||
INSERT_IGNORE(101),
|
||||
/**
|
||||
* Insert on duplicate update sql type.
|
||||
*/
|
||||
INSERT_ON_DUPLICATE_UPDATE(102);
|
||||
|
||||
private int i;
|
||||
|
||||
private SQLType(int i) {
|
||||
this.i = i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value int.
|
||||
*
|
||||
* @return the int
|
||||
*/
|
||||
public int value() {
|
||||
return this.i;
|
||||
}
|
||||
|
||||
/**
|
||||
* Value of sql type.
|
||||
*
|
||||
* @param i the
|
||||
* @return the sql type
|
||||
*/
|
||||
public static SQLType valueOf(int i) {
|
||||
for (SQLType t : values()) {
|
||||
if (t.value() == i) {
|
||||
return t;
|
||||
}
|
||||
}
|
||||
throw new IllegalArgumentException("Invalid SQLType:" + i);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The interface Sql update recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public interface SQLUpdateRecognizer extends WhereRecognizer {
|
||||
|
||||
/**
|
||||
* Gets update columns.
|
||||
*
|
||||
* @return the update columns
|
||||
*/
|
||||
List<String> getUpdateColumns();
|
||||
|
||||
/**
|
||||
* Gets update values.
|
||||
*
|
||||
* @return the update values
|
||||
*/
|
||||
List<Object> getUpdateValues();
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
public interface SqlParserType {
|
||||
/**
|
||||
* The constant SQL_PARSER_TYPE_DRUID.
|
||||
*/
|
||||
String SQL_PARSER_TYPE_DRUID = "druid";
|
||||
|
||||
/**
|
||||
* The constant SQL_PARSER_TYPE_ANTLR.
|
||||
*/
|
||||
String SQL_PARSER_TYPE_ANTLR = "antlr";
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The interface Where recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public interface WhereRecognizer extends SQLRecognizer {
|
||||
|
||||
/**
|
||||
* Gets where condition.
|
||||
*
|
||||
* @param parametersHolder the parameters holder
|
||||
* @param paramAppenderList the param appender list
|
||||
* @return the where condition
|
||||
*/
|
||||
String getWhereCondition(ParametersHolder parametersHolder, ArrayList<List<Object>> paramAppenderList);
|
||||
|
||||
/**
|
||||
* Gets where condition.
|
||||
*
|
||||
* @return the where condition
|
||||
*/
|
||||
String getWhereCondition();
|
||||
|
||||
/**
|
||||
* Return the limit SQL
|
||||
*
|
||||
* @param parametersHolder the parameters holder
|
||||
* @param paramAppenderList the param appender list
|
||||
* @return The limit SQL.
|
||||
*/
|
||||
default String getLimit(ParametersHolder parametersHolder, ArrayList<List<Object>> paramAppenderList) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the order by SQL
|
||||
*
|
||||
* @return The order by SQL.
|
||||
*/
|
||||
default String getOrderBy() {
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.struct;
|
||||
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The default expr able.
|
||||
*
|
||||
* @author jsbxyyx
|
||||
*/
|
||||
public interface Defaultable {
|
||||
|
||||
/**
|
||||
* get primary key values by default keyword.
|
||||
*
|
||||
* @return pk values by default
|
||||
* @throws SQLException the sql exception
|
||||
*/
|
||||
List<Object> getPkValuesByDefault() throws SQLException;
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.struct;
|
||||
|
||||
/**
|
||||
* The not placeholder expression.
|
||||
* @author jsbxyyx
|
||||
*/
|
||||
public class NotPlaceholderExpr {
|
||||
|
||||
private static NotPlaceholderExpr instance = new NotPlaceholderExpr();
|
||||
|
||||
/**
|
||||
* Get NotPlaceholder.
|
||||
*
|
||||
* @return the NotPlaceholder
|
||||
*/
|
||||
public static NotPlaceholderExpr get() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private NotPlaceholderExpr() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NOT_PLACEHOLDER";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.struct;
|
||||
|
||||
/**
|
||||
* The type Null.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public class Null {
|
||||
private static Null instance = new Null();
|
||||
|
||||
/**
|
||||
* Get null.
|
||||
*
|
||||
* @return the null
|
||||
*/
|
||||
public static Null get() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private Null() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "NULL";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.struct;
|
||||
|
||||
/**
|
||||
* The sequence able.
|
||||
*
|
||||
* @author jsbxyyx
|
||||
*/
|
||||
public interface Sequenceable {
|
||||
|
||||
/**
|
||||
* get sequence sql.
|
||||
*
|
||||
* @param expr the expr
|
||||
* @return sequence sql
|
||||
*/
|
||||
String getSequenceSql(SqlSequenceExpr expr);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.struct;
|
||||
|
||||
/**
|
||||
* sql default expression
|
||||
* @author jsbxyyx
|
||||
*/
|
||||
public class SqlDefaultExpr {
|
||||
|
||||
private static SqlDefaultExpr instance = new SqlDefaultExpr();
|
||||
|
||||
/**
|
||||
* Get SqlDefaultExpr.
|
||||
*
|
||||
* @return the SqlDefaultExpr
|
||||
*/
|
||||
public static SqlDefaultExpr get() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private SqlDefaultExpr() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "DEFAULT";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.struct;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* sql method invoke expression
|
||||
* @author jsbxyyx
|
||||
*/
|
||||
public class SqlMethodExpr {
|
||||
|
||||
private static SqlMethodExpr instance = new SqlMethodExpr();
|
||||
|
||||
/**
|
||||
* Get SqlMethodExpr.
|
||||
*
|
||||
* @return the SqlMethodExpr
|
||||
*/
|
||||
public static SqlMethodExpr get() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private SqlMethodExpr() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "SQL_METHOD";
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.struct;
|
||||
|
||||
/**
|
||||
* TODO
|
||||
* sql sequence expression
|
||||
* @author jsbxyyx
|
||||
*/
|
||||
public class SqlSequenceExpr {
|
||||
|
||||
private String sequence;
|
||||
private String function;
|
||||
|
||||
public SqlSequenceExpr() {}
|
||||
|
||||
public SqlSequenceExpr(String sequence, String function) {
|
||||
this.sequence = sequence;
|
||||
this.function = function;
|
||||
}
|
||||
|
||||
public String getSequence() {
|
||||
return sequence;
|
||||
}
|
||||
|
||||
public void setSequence(String sequence) {
|
||||
this.sequence = sequence;
|
||||
}
|
||||
|
||||
public String getFunction() {
|
||||
return function;
|
||||
}
|
||||
|
||||
public void setFunction(String function) {
|
||||
this.function = function;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.util;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
public interface DbTypeParser {
|
||||
String parseFromJdbcUrl(String jdbcUrl);
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.util;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
public interface JdbcConstants {
|
||||
String ORACLE = "oracle";
|
||||
|
||||
String MYSQL = "mysql";
|
||||
|
||||
String DB2 = "db2";
|
||||
|
||||
String H2 = "h2";
|
||||
|
||||
String MARIADB = "mariadb";
|
||||
|
||||
String POSTGRESQL = "postgresql";
|
||||
}
|
||||
68
sqlparser/seata-sqlparser-druid/pom.xml
Normal file
68
sqlparser/seata-sqlparser-druid/pom.xml
Normal file
@@ -0,0 +1,68 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
~ Copyright 1999-2019 Seata.io Group.
|
||||
~
|
||||
~ Licensed under the Apache License, Version 2.0 (the "License");
|
||||
~ you may not use this file except in compliance with the License.
|
||||
~ You may obtain a copy of the License at
|
||||
~
|
||||
~ http://www.apache.org/licenses/LICENSE-2.0
|
||||
~
|
||||
~ Unless required by applicable law or agreed to in writing, software
|
||||
~ distributed under the License is distributed on an "AS IS" BASIS,
|
||||
~ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
~ See the License for the specific language governing permissions and
|
||||
~ limitations under the License.
|
||||
-->
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<parent>
|
||||
<groupId>io.seata</groupId>
|
||||
<artifactId>seata-sqlparser</artifactId>
|
||||
<version>${revision}</version>
|
||||
</parent>
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<artifactId>seata-sqlparser-druid</artifactId>
|
||||
<name>seata-sqlparser-druid ${project.version}</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>${project.groupId}</groupId>
|
||||
<artifactId>seata-sqlparser-core</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.alibaba</groupId>
|
||||
<artifactId>druid</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>3.0.2</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-druid</id>
|
||||
<phase>compile</phase>
|
||||
<goals>
|
||||
<goal>copy-dependencies</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<includeGroupIds>com.alibaba</includeGroupIds>
|
||||
<includeArtifactIds>druid</includeArtifactIds>
|
||||
<stripVersion>true</stripVersion>
|
||||
<outputDirectory>
|
||||
${project.build.outputDirectory}/lib/sqlparser
|
||||
</outputDirectory>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</project>
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBetweenExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLBinaryOpExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLExistsExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLInListExpr;
|
||||
import com.alibaba.druid.sql.visitor.SQLASTVisitor;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
|
||||
/**
|
||||
* The type Base recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public abstract class BaseRecognizer implements SQLRecognizer {
|
||||
|
||||
/**
|
||||
* The type V marker.
|
||||
*/
|
||||
public static class VMarker {
|
||||
@Override
|
||||
public String toString() {
|
||||
return "?";
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* The Original sql.
|
||||
*/
|
||||
protected String originalSQL;
|
||||
|
||||
/**
|
||||
* Instantiates a new Base recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
*/
|
||||
public BaseRecognizer(String originalSQL) {
|
||||
this.originalSQL = originalSQL;
|
||||
|
||||
}
|
||||
|
||||
public void executeVisit(SQLExpr where, SQLASTVisitor visitor) {
|
||||
if (where instanceof SQLBinaryOpExpr) {
|
||||
visitor.visit((SQLBinaryOpExpr) where);
|
||||
} else if (where instanceof SQLInListExpr) {
|
||||
visitor.visit((SQLInListExpr) where);
|
||||
} else if (where instanceof SQLBetweenExpr) {
|
||||
visitor.visit((SQLBetweenExpr) where);
|
||||
} else if (where instanceof SQLExistsExpr) {
|
||||
visitor.visit((SQLExistsExpr) where);
|
||||
} else {
|
||||
throw new IllegalArgumentException("unexpected WHERE expr: " + where.getClass().getSimpleName());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOriginalSQL() {
|
||||
return originalSQL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URL;
|
||||
import java.security.CodeSource;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
class DefaultDruidLoader implements DruidLoader {
|
||||
/**
|
||||
* Default druid location in classpath
|
||||
*/
|
||||
private final static String DRUID_LOCATION = "lib/sqlparser/druid.jar";
|
||||
|
||||
private final static DefaultDruidLoader DRUID_LOADER = new DefaultDruidLoader(DRUID_LOCATION);
|
||||
|
||||
private final URL druidUrl;
|
||||
|
||||
/**
|
||||
* @param druidLocation druid location in classpath
|
||||
*/
|
||||
private DefaultDruidLoader(String druidLocation) {
|
||||
if (druidLocation == null) {
|
||||
druidLocation = DRUID_LOCATION;
|
||||
}
|
||||
URL url = DefaultDruidLoader.class.getClassLoader().getResource(druidLocation);
|
||||
if (url != null) {
|
||||
try {
|
||||
// extract druid.jar to temp file
|
||||
// TODO use URLStreamHandler to handle nested jar loading in the future
|
||||
File tempFile = File.createTempFile("seata", "sqlparser");
|
||||
try (InputStream input = url.openStream(); OutputStream output = new FileOutputStream(tempFile)) {
|
||||
byte[] buf = new byte[1024];
|
||||
while (true) {
|
||||
int readCnt = input.read(buf);
|
||||
if (readCnt < 0) {
|
||||
break;
|
||||
}
|
||||
output.write(buf, 0, readCnt);
|
||||
}
|
||||
output.flush();
|
||||
}
|
||||
tempFile.deleteOnExit();
|
||||
druidUrl = tempFile.toURI().toURL();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
} else {
|
||||
// try to find druid in class code source if it's not in classpath which should usually happen in unit test
|
||||
Class<?> clazz = null;
|
||||
try {
|
||||
clazz = DefaultDruidLoader.class.getClassLoader().loadClass("com.alibaba.druid.util.StringUtils");
|
||||
} catch (ClassNotFoundException ignore) {
|
||||
}
|
||||
if (clazz != null) {
|
||||
CodeSource cs = clazz.getProtectionDomain().getCodeSource();
|
||||
if (cs == null) {
|
||||
throw new IllegalStateException("Can not find druid code source");
|
||||
}
|
||||
druidUrl = cs.getLocation();
|
||||
} else {
|
||||
druidUrl = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get default druid loader
|
||||
*
|
||||
* @return default druid loader
|
||||
*/
|
||||
static DruidLoader get() {
|
||||
return DRUID_LOADER;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URL getEmbeddedDruidLocation() {
|
||||
if (druidUrl == null) {
|
||||
throw new IllegalStateException("Can not find embedded druid");
|
||||
}
|
||||
return druidUrl;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import com.alibaba.druid.util.JdbcUtils;
|
||||
import io.seata.sqlparser.util.DbTypeParser;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
class DruidDbTypeParserImpl implements DbTypeParser {
|
||||
@Override
|
||||
public String parseFromJdbcUrl(String jdbcUrl) {
|
||||
return JdbcUtils.getDbType(jdbcUrl, null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import io.seata.common.loader.LoadLevel;
|
||||
import io.seata.sqlparser.SqlParserType;
|
||||
import io.seata.sqlparser.util.DbTypeParser;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
@LoadLevel(name = SqlParserType.SQL_PARSER_TYPE_DRUID)
|
||||
public class DruidDelegatingDbTypeParser implements DbTypeParser {
|
||||
private DbTypeParser dbTypeParserImpl;
|
||||
|
||||
public DruidDelegatingDbTypeParser() {
|
||||
setClassLoader(DruidIsolationClassLoader.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for unit test
|
||||
*
|
||||
* @param classLoader classLoader
|
||||
*/
|
||||
void setClassLoader(ClassLoader classLoader) {
|
||||
try {
|
||||
Class<?> druidDbTypeParserImplClass = classLoader.loadClass("io.seata.sqlparser.druid.DruidDbTypeParserImpl");
|
||||
Constructor<?> implConstructor = druidDbTypeParserImplClass.getDeclaredConstructor();
|
||||
implConstructor.setAccessible(true);
|
||||
try {
|
||||
dbTypeParserImpl = (DbTypeParser) implConstructor.newInstance();
|
||||
} finally {
|
||||
implConstructor.setAccessible(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String parseFromJdbcUrl(String jdbcUrl) {
|
||||
return dbTypeParserImpl.parseFromJdbcUrl(jdbcUrl);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import io.seata.common.loader.LoadLevel;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.SQLRecognizerFactory;
|
||||
import io.seata.sqlparser.SqlParserType;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
@LoadLevel(name = SqlParserType.SQL_PARSER_TYPE_DRUID)
|
||||
public class DruidDelegatingSQLRecognizerFactory implements SQLRecognizerFactory {
|
||||
private volatile SQLRecognizerFactory recognizerFactoryImpl;
|
||||
|
||||
public DruidDelegatingSQLRecognizerFactory() {
|
||||
setClassLoader(DruidIsolationClassLoader.get());
|
||||
}
|
||||
|
||||
/**
|
||||
* Only for unit test
|
||||
*
|
||||
* @param classLoader classLoader
|
||||
*/
|
||||
void setClassLoader(ClassLoader classLoader) {
|
||||
try {
|
||||
Class<?> recognizerFactoryImplClass = classLoader.loadClass("io.seata.sqlparser.druid.DruidSQLRecognizerFactoryImpl");
|
||||
Constructor<?> implConstructor = recognizerFactoryImplClass.getDeclaredConstructor();
|
||||
implConstructor.setAccessible(true);
|
||||
try {
|
||||
recognizerFactoryImpl = (SQLRecognizerFactory) implConstructor.newInstance();
|
||||
} finally {
|
||||
implConstructor.setAccessible(false);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new SQLParsingException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SQLRecognizer> create(String sql, String dbType) {
|
||||
return recognizerFactoryImpl.create(sql, dbType);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import java.net.URL;
|
||||
import java.net.URLClassLoader;
|
||||
import java.security.CodeSource;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Used for druid isolation.
|
||||
*
|
||||
* @author ggndnn
|
||||
*/
|
||||
class DruidIsolationClassLoader extends URLClassLoader {
|
||||
private final static String[] DRUID_CLASS_PREFIX = new String[]{"com.alibaba.druid.", "io.seata.sqlparser.druid."};
|
||||
|
||||
private final static DruidIsolationClassLoader INSTANCE = new DruidIsolationClassLoader(DefaultDruidLoader.get());
|
||||
|
||||
DruidIsolationClassLoader(DruidLoader druidLoader) {
|
||||
super(getDruidUrls(druidLoader), DruidIsolationClassLoader.class.getClassLoader());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
for (String prefix : DRUID_CLASS_PREFIX) {
|
||||
if (name.startsWith(prefix)) {
|
||||
return loadInternalClass(name, resolve);
|
||||
}
|
||||
}
|
||||
return super.loadClass(name, resolve);
|
||||
}
|
||||
|
||||
private Class<?> loadInternalClass(String name, boolean resolve) throws ClassNotFoundException {
|
||||
Class<?> c;
|
||||
synchronized (getClassLoadingLock(name)) {
|
||||
c = findLoadedClass(name);
|
||||
if (c == null) {
|
||||
c = findClass(name);
|
||||
}
|
||||
}
|
||||
if (c == null) {
|
||||
throw new ClassNotFoundException(name);
|
||||
}
|
||||
if (resolve) {
|
||||
resolveClass(c);
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
private static URL[] getDruidUrls(DruidLoader druidLoader) {
|
||||
List<URL> urls = new ArrayList<>();
|
||||
urls.add(findClassLocation(DruidIsolationClassLoader.class));
|
||||
urls.add(druidLoader.getEmbeddedDruidLocation());
|
||||
return urls.toArray(new URL[0]);
|
||||
}
|
||||
|
||||
private static URL findClassLocation(Class<?> clazz) {
|
||||
CodeSource cs = clazz.getProtectionDomain().getCodeSource();
|
||||
if (cs == null) {
|
||||
throw new IllegalStateException("Not a normal druid startup environment");
|
||||
}
|
||||
return cs.getLocation();
|
||||
}
|
||||
|
||||
static DruidIsolationClassLoader get() {
|
||||
return INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import java.net.URL;
|
||||
|
||||
/**
|
||||
* ggndnn
|
||||
*/
|
||||
interface DruidLoader {
|
||||
/**
|
||||
* Gets embedded druid.jar
|
||||
*
|
||||
* @return embedded druid.jar url
|
||||
*/
|
||||
URL getEmbeddedDruidLocation();
|
||||
}
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
import io.seata.common.util.CollectionUtils;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.SQLRecognizerFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* DruidSQLRecognizerFactoryImpl
|
||||
*
|
||||
* @author sharajava
|
||||
* @author ggndnn
|
||||
*/
|
||||
class DruidSQLRecognizerFactoryImpl implements SQLRecognizerFactory {
|
||||
@Override
|
||||
public List<SQLRecognizer> create(String sql, String dbType) {
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, dbType);
|
||||
if (CollectionUtils.isEmpty(asts)) {
|
||||
throw new UnsupportedOperationException("Unsupported SQL: " + sql);
|
||||
}
|
||||
if (asts.size() > 1 && !(asts.stream().allMatch(statement -> statement instanceof SQLUpdateStatement)
|
||||
|| asts.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) {
|
||||
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 (recognizer != null) {
|
||||
if (recognizers == null) {
|
||||
recognizers = new ArrayList<>();
|
||||
}
|
||||
recognizers.add(recognizer);
|
||||
}
|
||||
}
|
||||
return recognizers;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
|
||||
/**
|
||||
* The interface SQLOperateRecognizerHolder
|
||||
*
|
||||
* @author: Zhibei Hao
|
||||
*/
|
||||
public interface SQLOperateRecognizerHolder {
|
||||
|
||||
/**
|
||||
* Get delete recognizer
|
||||
*
|
||||
* @param sql the sql
|
||||
* @param ast the ast
|
||||
* @return the delete recognizer
|
||||
*/
|
||||
SQLRecognizer getDeleteRecognizer(String sql, SQLStatement ast);
|
||||
|
||||
/**
|
||||
* Get insert recognizer
|
||||
*
|
||||
* @param sql the sql
|
||||
* @param ast the ast
|
||||
* @return the insert recognizer
|
||||
*/
|
||||
SQLRecognizer getInsertRecognizer(String sql, SQLStatement ast);
|
||||
|
||||
/**
|
||||
* Get update recognizer
|
||||
*
|
||||
* @param sql the sql
|
||||
* @param ast the ast
|
||||
* @return the update recognizer
|
||||
*/
|
||||
SQLRecognizer getUpdateRecognizer(String sql, SQLStatement ast);
|
||||
|
||||
/**
|
||||
* Get SelectForUpdate recognizer
|
||||
*
|
||||
* @param sql the sql
|
||||
* @param ast the ast
|
||||
* @return the SelectForUpdate recognizer
|
||||
*/
|
||||
SQLRecognizer getSelectForUpdateRecognizer(String sql, SQLStatement ast);
|
||||
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
import io.seata.common.loader.EnhancedServiceLoader;
|
||||
import io.seata.common.util.CollectionUtils;
|
||||
|
||||
/**
|
||||
* The SQLOperateRecognizerHolderFactory
|
||||
*
|
||||
* @author: Zhibei Hao
|
||||
*/
|
||||
public class SQLOperateRecognizerHolderFactory {
|
||||
|
||||
private static final Map<String, SQLOperateRecognizerHolder> RECOGNIZER_HOLDER_MAP = new ConcurrentHashMap<>();
|
||||
|
||||
/**
|
||||
* get SQLOperateRecognizer by db type
|
||||
*
|
||||
* @param dbType the db type
|
||||
* @return the SQLOperateRecognizer
|
||||
*/
|
||||
public static SQLOperateRecognizerHolder getSQLRecognizerHolder(String dbType) {
|
||||
return CollectionUtils.computeIfAbsent(RECOGNIZER_HOLDER_MAP, dbType,
|
||||
key -> EnhancedServiceLoader.load(SQLOperateRecognizerHolder.class, dbType, SQLOperateRecognizerHolderFactory.class.getClassLoader()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,165 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.mysql;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLLimit;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderBy;
|
||||
import com.alibaba.druid.sql.ast.SQLOrderingSpecification;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIntegerExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectOrderByItem;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
||||
import io.seata.common.util.StringUtils;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.druid.BaseRecognizer;
|
||||
import io.seata.sqlparser.struct.Null;
|
||||
|
||||
/**
|
||||
* @author will
|
||||
*/
|
||||
public abstract class BaseMySQLRecognizer extends BaseRecognizer {
|
||||
|
||||
/**
|
||||
* Instantiates a new mysql base recognizer
|
||||
*
|
||||
* @param originalSql the original sql
|
||||
*/
|
||||
public BaseMySQLRecognizer(String originalSql) {
|
||||
super(originalSql);
|
||||
}
|
||||
|
||||
public MySqlOutputVisitor createOutputVisitor(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList,
|
||||
final StringBuilder sb) {
|
||||
return new MySqlOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLVariantRefExpr x) {
|
||||
if ("?".equals(x.getName())) {
|
||||
ArrayList<Object> oneParamValues = parametersHolder.getParameters().get(x.getIndex() + 1);
|
||||
if (paramAppenderList.isEmpty()) {
|
||||
oneParamValues.forEach(t -> paramAppenderList.add(new ArrayList<>()));
|
||||
}
|
||||
for (int i = 0; i < oneParamValues.size(); i++) {
|
||||
Object o = oneParamValues.get(i);
|
||||
paramAppenderList.get(i).add(o instanceof Null ? null : o);
|
||||
}
|
||||
}
|
||||
return super.visit(x);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String getWhereCondition(SQLExpr where, final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
if (Objects.isNull(where)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
executeVisit(where, createOutputVisitor(parametersHolder, paramAppenderList, sb));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getWhereCondition(SQLExpr where) {
|
||||
if (Objects.isNull(where)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
executeVisit(where, new MySqlOutputVisitor(sb));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
protected String getLimit(SQLStatement sqlStatement, SQLType sqlType, ParametersHolder parametersHolder, ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLLimit limit = null;
|
||||
if (SQLType.UPDATE == sqlType) {
|
||||
limit = ((MySqlUpdateStatement)sqlStatement).getLimit();
|
||||
} else if (SQLType.DELETE == sqlType) {
|
||||
limit = ((MySqlDeleteStatement)sqlStatement).getLimit();
|
||||
}
|
||||
if (limit != null) {
|
||||
StringBuilder builder = new StringBuilder(" LIMIT ");
|
||||
SQLIntegerExpr expr;
|
||||
if (limit.getOffset() != null) {
|
||||
if (limit.getOffset() instanceof SQLVariantRefExpr) {
|
||||
builder.append("?,");
|
||||
Map<Integer, ArrayList<Object>> parameters = parametersHolder.getParameters();
|
||||
paramAppenderList.add(parameters.get(parameters.size() - 1));
|
||||
} else {
|
||||
expr = (SQLIntegerExpr)limit.getOffset();
|
||||
builder.append(expr.getNumber()).append(",");
|
||||
}
|
||||
}
|
||||
if (limit.getRowCount() != null) {
|
||||
if (limit.getRowCount() instanceof SQLVariantRefExpr) {
|
||||
builder.append("?");
|
||||
Map<Integer, ArrayList<Object>> parameters = parametersHolder.getParameters();
|
||||
paramAppenderList.add(parameters.get(parameters.size()));
|
||||
} else {
|
||||
expr = (SQLIntegerExpr)limit.getRowCount();
|
||||
builder.append(expr.getNumber());
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
protected String getOrderBy(SQLStatement sqlStatement, SQLType sqlType) {
|
||||
SQLOrderBy orderBy = null;
|
||||
if (SQLType.UPDATE == sqlType) {
|
||||
orderBy = ((MySqlUpdateStatement)sqlStatement).getOrderBy();
|
||||
} else if (SQLType.DELETE == sqlType) {
|
||||
orderBy = ((MySqlDeleteStatement)sqlStatement).getOrderBy();
|
||||
}
|
||||
if (orderBy != null) {
|
||||
String space = " ";
|
||||
String comma = ",";
|
||||
StringBuilder builder = new StringBuilder(space).append("ORDER BY").append(space);
|
||||
List<SQLSelectOrderByItem> items = orderBy.getItems();
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
SQLSelectOrderByItem item = items.get(i);
|
||||
SQLIdentifierExpr expr = (SQLIdentifierExpr)item.getExpr();
|
||||
builder.append(expr.getName());
|
||||
SQLOrderingSpecification specification = item.getType();
|
||||
if (specification != null) {
|
||||
builder.append(space);
|
||||
builder.append(specification.name);
|
||||
}
|
||||
if (i + 1 != items.size()) {
|
||||
builder.append(comma);
|
||||
}
|
||||
}
|
||||
return builder.toString();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,123 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.mysql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlDeleteStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
||||
|
||||
import io.seata.common.exception.NotSupportYetException;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLDeleteRecognizer;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The type My sql delete recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public class MySQLDeleteRecognizer extends BaseMySQLRecognizer implements SQLDeleteRecognizer {
|
||||
|
||||
private final MySqlDeleteStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new My sql delete recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public MySQLDeleteRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (MySqlDeleteStatement)ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
if (ast.getFrom() == null) {
|
||||
return ast.getTableSource().getAlias();
|
||||
}
|
||||
return ast.getFrom().getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
MySqlOutputVisitor visitor = new MySqlOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLJoinTableSource x) {
|
||||
throw new NotSupportYetException("not support the syntax of delete with join table");
|
||||
}
|
||||
};
|
||||
SQLTableSource tableSource;
|
||||
if (ast.getFrom() == null) {
|
||||
tableSource = ast.getTableSource();
|
||||
} else {
|
||||
tableSource = ast.getFrom();
|
||||
}
|
||||
|
||||
if (tableSource instanceof SQLExprTableSource) {
|
||||
visitor.visit((SQLExprTableSource) tableSource);
|
||||
} else if (tableSource instanceof SQLJoinTableSource) {
|
||||
visitor.visit((SQLJoinTableSource) tableSource);
|
||||
} else {
|
||||
throw new NotSupportYetException("not support the syntax of delete with unknow");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where, parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLimit(ParametersHolder parametersHolder, ArrayList<List<Object>> paramAppenderList) {
|
||||
return super.getLimit(ast, getSQLType(), parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOrderBy() {
|
||||
return super.getOrderBy(ast, getSQLType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,138 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.mysql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
||||
|
||||
import io.seata.common.util.CollectionUtils;
|
||||
import io.seata.sqlparser.SQLInsertRecognizer;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.struct.NotPlaceholderExpr;
|
||||
import io.seata.sqlparser.struct.Null;
|
||||
import io.seata.sqlparser.struct.SqlMethodExpr;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The type My sql insert recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public class MySQLInsertRecognizer extends BaseMySQLRecognizer implements SQLInsertRecognizer {
|
||||
|
||||
private final MySqlInsertStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new My sql insert recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public MySQLInsertRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (MySqlInsertStatement)ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.INSERT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return ast.getTableSource().getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
MySqlOutputVisitor visitor = new MySqlOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
};
|
||||
visitor.visit(ast.getTableSource());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insertColumnsIsEmpty() {
|
||||
return CollectionUtils.isEmpty(ast.getColumns());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getInsertColumns() {
|
||||
List<SQLExpr> columnSQLExprs = ast.getColumns();
|
||||
if (columnSQLExprs.isEmpty()) {
|
||||
// INSERT INTO ta VALUES (...), without fields clarified
|
||||
return null;
|
||||
}
|
||||
List<String> list = new ArrayList<>(columnSQLExprs.size());
|
||||
for (SQLExpr expr : columnSQLExprs) {
|
||||
if (expr instanceof SQLIdentifierExpr) {
|
||||
list.add(((SQLIdentifierExpr)expr).getName());
|
||||
} else {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex) {
|
||||
List<SQLInsertStatement.ValuesClause> valuesClauses = ast.getValuesList();
|
||||
List<List<Object>> rows = new ArrayList<>(valuesClauses.size());
|
||||
for (SQLInsertStatement.ValuesClause valuesClause : valuesClauses) {
|
||||
List<SQLExpr> exprs = valuesClause.getValues();
|
||||
List<Object> row = new ArrayList<>(exprs.size());
|
||||
rows.add(row);
|
||||
for (int i = 0, len = exprs.size(); i < len; i++) {
|
||||
SQLExpr expr = exprs.get(i);
|
||||
if (expr instanceof SQLNullExpr) {
|
||||
row.add(Null.get());
|
||||
} else if (expr instanceof SQLValuableExpr) {
|
||||
row.add(((SQLValuableExpr) expr).getValue());
|
||||
} else if (expr instanceof SQLVariantRefExpr) {
|
||||
row.add(((SQLVariantRefExpr) expr).getName());
|
||||
} else if (expr instanceof SQLMethodInvokeExpr) {
|
||||
row.add(SqlMethodExpr.get());
|
||||
} else {
|
||||
if (primaryKeyIndex.contains(i)) {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
row.add(NotPlaceholderExpr.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.mysql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import io.seata.common.loader.LoadLevel;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.druid.SQLOperateRecognizerHolder;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
|
||||
/**
|
||||
* The class MySqlOperateRecognizerHolder
|
||||
*
|
||||
* @author: Zhibei Hao
|
||||
*/
|
||||
@LoadLevel(name = JdbcConstants.MYSQL)
|
||||
public class MySQLOperateRecognizerHolder implements SQLOperateRecognizerHolder {
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getDeleteRecognizer(String sql, SQLStatement ast) {
|
||||
return new MySQLDeleteRecognizer(sql, ast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getInsertRecognizer(String sql, SQLStatement ast) {
|
||||
return new MySQLInsertRecognizer(sql, ast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getUpdateRecognizer(String sql, SQLStatement ast) {
|
||||
return new MySQLUpdateRecognizer(sql, ast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getSelectForUpdateRecognizer(String sql, SQLStatement ast) {
|
||||
if (((SQLSelectStatement) ast).getSelect().getFirstQueryBlock().isForUpdate()) {
|
||||
return new MySQLSelectForUpdateRecognizer(sql, ast);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.mysql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLSelectRecognizer;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The type My sql select for update recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public class MySQLSelectForUpdateRecognizer extends BaseMySQLRecognizer implements SQLSelectRecognizer {
|
||||
|
||||
private final SQLSelectStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new My sql select for update recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public MySQLSelectForUpdateRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (SQLSelectStatement)ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.SELECT_FOR_UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLExpr where = selectQueryBlock.getWhere();
|
||||
return super.getWhereCondition(where, parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLExpr where = selectQueryBlock.getWhere();
|
||||
return super.getWhereCondition(where);
|
||||
}
|
||||
|
||||
private SQLSelectQueryBlock getSelect() {
|
||||
SQLSelect select = ast.getSelect();
|
||||
if (select == null) {
|
||||
throw new SQLParsingException("should never happen!");
|
||||
}
|
||||
SQLSelectQueryBlock selectQueryBlock = select.getQueryBlock();
|
||||
if (selectQueryBlock == null) {
|
||||
throw new SQLParsingException("should never happen!");
|
||||
}
|
||||
return selectQueryBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLTableSource tableSource = selectQueryBlock.getFrom();
|
||||
return tableSource.getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLTableSource tableSource = selectQueryBlock.getFrom();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
MySqlOutputVisitor visitor = new MySqlOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
};
|
||||
visitor.visit((SQLExprTableSource)tableSource);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,162 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.mysql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.visitor.MySqlOutputVisitor;
|
||||
|
||||
import io.seata.common.exception.NotSupportYetException;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.SQLUpdateRecognizer;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The type My sql update recognizer.
|
||||
*
|
||||
* @author sharajava
|
||||
*/
|
||||
public class MySQLUpdateRecognizer extends BaseMySQLRecognizer implements SQLUpdateRecognizer {
|
||||
|
||||
private MySqlUpdateStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new My sql update recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public MySQLUpdateRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (MySqlUpdateStatement)ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUpdateColumns() {
|
||||
List<SQLUpdateSetItem> updateSetItems = ast.getItems();
|
||||
List<String> list = new ArrayList<>(updateSetItems.size());
|
||||
for (SQLUpdateSetItem updateSetItem : updateSetItems) {
|
||||
SQLExpr expr = updateSetItem.getColumn();
|
||||
if (expr instanceof SQLIdentifierExpr) {
|
||||
list.add(((SQLIdentifierExpr)expr).getName());
|
||||
} else if (expr instanceof SQLPropertyExpr) {
|
||||
// This is alias case, like UPDATE xxx_tbl a SET a.name = ? WHERE a.id = ?
|
||||
SQLExpr owner = ((SQLPropertyExpr)expr).getOwner();
|
||||
if (owner instanceof SQLIdentifierExpr) {
|
||||
list.add(((SQLIdentifierExpr)owner).getName() + "." + ((SQLPropertyExpr)expr).getName());
|
||||
//This is table Field Full path, like update xxx_database.xxx_tbl set xxx_database.xxx_tbl.xxx_field...
|
||||
} else if (((SQLPropertyExpr)expr).getOwnernName().split("\\.").length > 1) {
|
||||
list.add(((SQLPropertyExpr)expr).getOwnernName() + "." + ((SQLPropertyExpr)expr).getName());
|
||||
}
|
||||
} else {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getUpdateValues() {
|
||||
List<SQLUpdateSetItem> updateSetItems = ast.getItems();
|
||||
List<Object> list = new ArrayList<>(updateSetItems.size());
|
||||
for (SQLUpdateSetItem updateSetItem : updateSetItems) {
|
||||
SQLExpr expr = updateSetItem.getValue();
|
||||
if (expr instanceof SQLValuableExpr) {
|
||||
list.add(((SQLValuableExpr)expr).getValue());
|
||||
} else if (expr instanceof SQLVariantRefExpr) {
|
||||
list.add(new VMarker());
|
||||
} else {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where, parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return ast.getTableSource().getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
MySqlOutputVisitor visitor = new MySqlOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLJoinTableSource x) {
|
||||
throw new NotSupportYetException("not support the syntax of update with join table");
|
||||
}
|
||||
};
|
||||
|
||||
SQLTableSource tableSource = ast.getTableSource();
|
||||
if (tableSource instanceof SQLExprTableSource) {
|
||||
visitor.visit((SQLExprTableSource) tableSource);
|
||||
} else if (tableSource instanceof SQLJoinTableSource) {
|
||||
visitor.visit((SQLJoinTableSource) tableSource);
|
||||
} else {
|
||||
throw new NotSupportYetException("not support the syntax of update with unknow");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getLimit(ParametersHolder parametersHolder, ArrayList<List<Object>> paramAppenderList) {
|
||||
return super.getLimit(ast, getSQLType(), parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getOrderBy() {
|
||||
return super.getOrderBy(ast, getSQLType());
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.oracle;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor;
|
||||
import io.seata.common.util.StringUtils;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.druid.BaseRecognizer;
|
||||
import io.seata.sqlparser.struct.Null;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author will
|
||||
*/
|
||||
public abstract class BaseOracleRecognizer extends BaseRecognizer {
|
||||
|
||||
/**
|
||||
* Instantiates a new oracle base recognizer
|
||||
*
|
||||
* @param originalSql the original sql
|
||||
*/
|
||||
public BaseOracleRecognizer(String originalSql) {
|
||||
super(originalSql);
|
||||
}
|
||||
|
||||
public OracleOutputVisitor createOutputVisitor(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList,
|
||||
final StringBuilder sb) {
|
||||
|
||||
return new OracleOutputVisitor(sb) {
|
||||
@Override
|
||||
public boolean visit(SQLVariantRefExpr x) {
|
||||
if ("?".equals(x.getName())) {
|
||||
ArrayList<Object> oneParamValues = parametersHolder.getParameters().get(x.getIndex() + 1);
|
||||
if (paramAppenderList.isEmpty()) {
|
||||
oneParamValues.forEach(t -> paramAppenderList.add(new ArrayList<>()));
|
||||
}
|
||||
for (int i = 0; i < oneParamValues.size(); i++) {
|
||||
Object o = oneParamValues.get(i);
|
||||
paramAppenderList.get(i).add(o instanceof Null ? null : o);
|
||||
}
|
||||
}
|
||||
return super.visit(x);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
public String getWhereCondition(SQLExpr where, final ParametersHolder parametersHolder, final ArrayList<List<Object>> paramAppenderList) {
|
||||
if (Objects.isNull(where)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
executeVisit(where, createOutputVisitor(parametersHolder, paramAppenderList, sb));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getWhereCondition(SQLExpr where) {
|
||||
if (Objects.isNull(where)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
executeVisit(where, new OracleOutputVisitor(sb));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.oracle;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleDeleteStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor;
|
||||
|
||||
import io.seata.common.exception.NotSupportYetException;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLDeleteRecognizer;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The type oracle delete recognizer.
|
||||
*
|
||||
* @author ccg
|
||||
*/
|
||||
public class OracleDeleteRecognizer extends BaseOracleRecognizer implements SQLDeleteRecognizer {
|
||||
|
||||
private final OracleDeleteStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new My sql delete recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public OracleDeleteRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (OracleDeleteStatement)ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return ast.getTableSource().getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
OracleOutputVisitor visitor = new OracleOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLJoinTableSource x) {
|
||||
throw new NotSupportYetException("not support the syntax of delete with join table");
|
||||
}
|
||||
};
|
||||
SQLTableSource tableSource;
|
||||
if (ast.getFrom() == null) {
|
||||
tableSource = ast.getTableSource();
|
||||
} else {
|
||||
tableSource = ast.getFrom();
|
||||
}
|
||||
|
||||
if (tableSource instanceof SQLExprTableSource) {
|
||||
visitor.visit((SQLExprTableSource) tableSource);
|
||||
} else if (tableSource instanceof SQLJoinTableSource) {
|
||||
visitor.visit((SQLJoinTableSource) tableSource);
|
||||
} else {
|
||||
throw new NotSupportYetException("not support the syntax of delete with unknow");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where, parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.oracle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLSequenceExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor;
|
||||
import io.seata.common.util.CollectionUtils;
|
||||
import io.seata.sqlparser.SQLInsertRecognizer;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.struct.NotPlaceholderExpr;
|
||||
import io.seata.sqlparser.struct.Null;
|
||||
import io.seata.sqlparser.struct.SqlMethodExpr;
|
||||
import io.seata.sqlparser.struct.SqlSequenceExpr;
|
||||
|
||||
/**
|
||||
* The type oracle insert recognizer.
|
||||
*
|
||||
* @author ccg
|
||||
*/
|
||||
public class OracleInsertRecognizer extends BaseOracleRecognizer implements SQLInsertRecognizer {
|
||||
|
||||
private final OracleInsertStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new My sql insert recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public OracleInsertRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (OracleInsertStatement)ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.INSERT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return ast.getTableSource().getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
OracleOutputVisitor visitor = new OracleOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
};
|
||||
visitor.visit(ast.getTableSource());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insertColumnsIsEmpty() {
|
||||
return CollectionUtils.isEmpty(ast.getColumns());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getInsertColumns() {
|
||||
List<SQLExpr> columnSQLExprs = ast.getColumns();
|
||||
if (columnSQLExprs.isEmpty()) {
|
||||
// INSERT INTO ta VALUES (...), without fields clarified
|
||||
return null;
|
||||
}
|
||||
List<String> list = new ArrayList<>(columnSQLExprs.size());
|
||||
for (SQLExpr expr : columnSQLExprs) {
|
||||
if (expr instanceof SQLIdentifierExpr) {
|
||||
list.add(((SQLIdentifierExpr)expr).getName());
|
||||
} else {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex) {
|
||||
List<SQLInsertStatement.ValuesClause> valuesClauses = ast.getValuesList();
|
||||
List<List<Object>> rows = new ArrayList<>(valuesClauses.size());
|
||||
for (SQLInsertStatement.ValuesClause valuesClause : valuesClauses) {
|
||||
List<SQLExpr> exprs = valuesClause.getValues();
|
||||
List<Object> row = new ArrayList<>(exprs.size());
|
||||
rows.add(row);
|
||||
for (int i = 0, len = exprs.size(); i < len; i++) {
|
||||
SQLExpr expr = exprs.get(i);
|
||||
if (expr instanceof SQLNullExpr) {
|
||||
row.add(Null.get());
|
||||
} else if (expr instanceof SQLValuableExpr) {
|
||||
row.add(((SQLValuableExpr) expr).getValue());
|
||||
} else if (expr instanceof SQLVariantRefExpr) {
|
||||
row.add(((SQLVariantRefExpr) expr).getName());
|
||||
} else if (expr instanceof SQLMethodInvokeExpr) {
|
||||
row.add(SqlMethodExpr.get());
|
||||
} else if (expr instanceof SQLSequenceExpr) {
|
||||
SQLSequenceExpr sequenceExpr = (SQLSequenceExpr) expr;
|
||||
String sequence = sequenceExpr.getSequence().getSimpleName();
|
||||
String function = sequenceExpr.getFunction().name;
|
||||
row.add(new SqlSequenceExpr(sequence, function));
|
||||
} else {
|
||||
if (primaryKeyIndex.contains(i)) {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
row.add(NotPlaceholderExpr.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.oracle;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import io.seata.common.loader.LoadLevel;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.druid.SQLOperateRecognizerHolder;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
|
||||
/**
|
||||
* The Type OracleOperateRecognizerHolder
|
||||
*
|
||||
* @author: Zhibei Hao
|
||||
*/
|
||||
@LoadLevel(name = JdbcConstants.ORACLE)
|
||||
public class OracleOperateRecognizerHolder implements SQLOperateRecognizerHolder {
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getDeleteRecognizer(String sql, SQLStatement ast) {
|
||||
return new OracleDeleteRecognizer(sql, ast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getInsertRecognizer(String sql, SQLStatement ast) {
|
||||
return new OracleInsertRecognizer(sql, ast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getUpdateRecognizer(String sql, SQLStatement ast) {
|
||||
return new OracleUpdateRecognizer(sql, ast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getSelectForUpdateRecognizer(String sql, SQLStatement ast) {
|
||||
if (((SQLSelectStatement) ast).getSelect().getFirstQueryBlock().isForUpdate()) {
|
||||
return new OracleSelectForUpdateRecognizer(sql, ast);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.oracle;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor;
|
||||
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLSelectRecognizer;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The type oracle select for update recognizer.
|
||||
*
|
||||
* @author ccg
|
||||
*/
|
||||
public class OracleSelectForUpdateRecognizer extends BaseOracleRecognizer implements SQLSelectRecognizer {
|
||||
|
||||
private final SQLSelectStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new My sql select for update recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public OracleSelectForUpdateRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (SQLSelectStatement)ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.SELECT_FOR_UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLExpr where = selectQueryBlock.getWhere();
|
||||
return super.getWhereCondition(where, parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLExpr where = selectQueryBlock.getWhere();
|
||||
return super.getWhereCondition(where);
|
||||
}
|
||||
|
||||
private SQLSelectQueryBlock getSelect() {
|
||||
SQLSelect select = ast.getSelect();
|
||||
if (select == null) {
|
||||
throw new SQLParsingException("should never happen!");
|
||||
}
|
||||
SQLSelectQueryBlock selectQueryBlock = select.getQueryBlock();
|
||||
if (selectQueryBlock == null) {
|
||||
throw new SQLParsingException("should never happen!");
|
||||
}
|
||||
return selectQueryBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLTableSource tableSource = selectQueryBlock.getFrom();
|
||||
return tableSource.getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLTableSource tableSource = selectQueryBlock.getFrom();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
OracleOutputVisitor visitor = new OracleOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
};
|
||||
visitor.visit((SQLExprTableSource)tableSource);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,151 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.oracle;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
|
||||
import com.alibaba.druid.sql.dialect.oracle.ast.stmt.OracleUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.oracle.visitor.OracleOutputVisitor;
|
||||
|
||||
import io.seata.common.exception.NotSupportYetException;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.SQLUpdateRecognizer;
|
||||
|
||||
/**
|
||||
* The type oracle update recognizer.
|
||||
*
|
||||
* @author ccg
|
||||
*/
|
||||
public class OracleUpdateRecognizer extends BaseOracleRecognizer implements SQLUpdateRecognizer {
|
||||
|
||||
private OracleUpdateStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new My sql update recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public OracleUpdateRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (OracleUpdateStatement)ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUpdateColumns() {
|
||||
List<SQLUpdateSetItem> updateSetItems = ast.getItems();
|
||||
List<String> list = new ArrayList<>(updateSetItems.size());
|
||||
for (SQLUpdateSetItem updateSetItem : updateSetItems) {
|
||||
SQLExpr expr = updateSetItem.getColumn();
|
||||
if (expr instanceof SQLIdentifierExpr) {
|
||||
list.add(((SQLIdentifierExpr)expr).getName());
|
||||
} else if (expr instanceof SQLPropertyExpr) {
|
||||
// This is alias case, like UPDATE xxx_tbl a SET a.name = ? WHERE a.id = ?
|
||||
SQLExpr owner = ((SQLPropertyExpr)expr).getOwner();
|
||||
if (owner instanceof SQLIdentifierExpr) {
|
||||
list.add(((SQLIdentifierExpr)owner).getName() + "." + ((SQLPropertyExpr)expr).getName());
|
||||
//This is table Field Full path, like update xxx_database.xxx_tbl set xxx_database.xxx_tbl.xxx_field...
|
||||
} else if (((SQLPropertyExpr) expr).getOwnernName().split("\\.").length > 1) {
|
||||
list.add(((SQLPropertyExpr)expr).getOwnernName() + "." + ((SQLPropertyExpr)expr).getName());
|
||||
}
|
||||
} else {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getUpdateValues() {
|
||||
List<SQLUpdateSetItem> updateSetItems = ast.getItems();
|
||||
List<Object> list = new ArrayList<>(updateSetItems.size());
|
||||
for (SQLUpdateSetItem updateSetItem : updateSetItems) {
|
||||
SQLExpr expr = updateSetItem.getValue();
|
||||
if (expr instanceof SQLValuableExpr) {
|
||||
list.add(((SQLValuableExpr)expr).getValue());
|
||||
} else if (expr instanceof SQLVariantRefExpr) {
|
||||
list.add(new VMarker());
|
||||
} else {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where, parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return ast.getTableSource().getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
OracleOutputVisitor visitor = new OracleOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLJoinTableSource x) {
|
||||
throw new NotSupportYetException("not support the syntax of update with join table");
|
||||
}
|
||||
};
|
||||
SQLTableSource tableSource = ast.getTableSource();
|
||||
if (tableSource instanceof SQLExprTableSource) {
|
||||
visitor.visit((SQLExprTableSource) tableSource);
|
||||
} else if (tableSource instanceof SQLJoinTableSource) {
|
||||
visitor.visit((SQLJoinTableSource) tableSource);
|
||||
} else {
|
||||
throw new NotSupportYetException("not support the syntax of update with unknow");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.postgresql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;
|
||||
import io.seata.common.util.StringUtils;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.druid.BaseRecognizer;
|
||||
import io.seata.sqlparser.struct.Null;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author will
|
||||
*/
|
||||
public abstract class BasePostgresqlRecognizer extends BaseRecognizer {
|
||||
|
||||
/**
|
||||
* Instantiates a new postgresql base recognizer
|
||||
*
|
||||
* @param originalSql the original sql
|
||||
*/
|
||||
public BasePostgresqlRecognizer(String originalSql) {
|
||||
super(originalSql);
|
||||
}
|
||||
|
||||
public PGOutputVisitor createOutputVisitor(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList, final StringBuilder sb) {
|
||||
PGOutputVisitor visitor = new PGOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLVariantRefExpr x) {
|
||||
if ("?".equals(x.getName())) {
|
||||
ArrayList<Object> oneParamValues = parametersHolder.getParameters().get(x.getIndex() + 1);
|
||||
if (paramAppenderList.size() == 0) {
|
||||
oneParamValues.forEach(t -> paramAppenderList.add(new ArrayList<>()));
|
||||
}
|
||||
for (int i = 0; i < oneParamValues.size(); i++) {
|
||||
Object o = oneParamValues.get(i);
|
||||
paramAppenderList.get(i).add(o instanceof Null ? null : o);
|
||||
}
|
||||
|
||||
}
|
||||
return super.visit(x);
|
||||
}
|
||||
};
|
||||
return visitor;
|
||||
}
|
||||
|
||||
public String getWhereCondition(SQLExpr where, final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
if (Objects.isNull(where)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
StringBuilder sb = new StringBuilder();
|
||||
executeVisit(where, createOutputVisitor(parametersHolder, paramAppenderList, sb));
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public String getWhereCondition(SQLExpr where) {
|
||||
if (Objects.isNull(where)) {
|
||||
return StringUtils.EMPTY;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
executeVisit(where, new PGOutputVisitor(sb));
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.postgresql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGDeleteStatement;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;
|
||||
import io.seata.common.exception.NotSupportYetException;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLDeleteRecognizer;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author japsercloud
|
||||
*/
|
||||
public class PostgresqlDeleteRecognizer extends BasePostgresqlRecognizer implements SQLDeleteRecognizer {
|
||||
|
||||
private final PGDeleteStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new Postgresql delete recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public PostgresqlDeleteRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (PGDeleteStatement) ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.DELETE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return ast.getTableSource().getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
PGOutputVisitor visitor = new PGOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLJoinTableSource x) {
|
||||
throw new NotSupportYetException("not support the syntax of delete with join table");
|
||||
}
|
||||
};
|
||||
SQLTableSource tableSource;
|
||||
if (ast.getFrom() == null) {
|
||||
tableSource = ast.getTableSource();
|
||||
} else {
|
||||
tableSource = ast.getFrom();
|
||||
}
|
||||
|
||||
if (tableSource instanceof SQLExprTableSource) {
|
||||
visitor.visit((SQLExprTableSource) tableSource);
|
||||
} else if (tableSource instanceof SQLJoinTableSource) {
|
||||
visitor.visit((SQLJoinTableSource) tableSource);
|
||||
} else {
|
||||
throw new NotSupportYetException("not support the syntax of delete with unknow");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where, parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,153 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.postgresql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLDefaultExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLMethodInvokeExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLNullExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLSequenceExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;
|
||||
import io.seata.common.util.CollectionUtils;
|
||||
import io.seata.common.util.StringUtils;
|
||||
import io.seata.sqlparser.SQLInsertRecognizer;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.struct.NotPlaceholderExpr;
|
||||
import io.seata.sqlparser.struct.Null;
|
||||
import io.seata.sqlparser.struct.SqlDefaultExpr;
|
||||
import io.seata.sqlparser.struct.SqlMethodExpr;
|
||||
import io.seata.sqlparser.struct.SqlSequenceExpr;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author japsercloud
|
||||
*/
|
||||
public class PostgresqlInsertRecognizer extends BasePostgresqlRecognizer implements SQLInsertRecognizer {
|
||||
|
||||
private final PGInsertStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new Postgresql insert recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public PostgresqlInsertRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (PGInsertStatement) ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.INSERT;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return ast.getTableSource().getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
PGOutputVisitor visitor = new PGOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
};
|
||||
visitor.visit(ast.getTableSource());
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean insertColumnsIsEmpty() {
|
||||
return CollectionUtils.isEmpty(ast.getColumns());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getInsertColumns() {
|
||||
List<SQLExpr> columnSQLExprs = ast.getColumns();
|
||||
if (columnSQLExprs.size() == 0) {
|
||||
// INSERT INTO ta VALUES (...), without fields clarified
|
||||
return null;
|
||||
}
|
||||
List<String> list = new ArrayList<>(columnSQLExprs.size());
|
||||
for (SQLExpr expr : columnSQLExprs) {
|
||||
if (expr instanceof SQLIdentifierExpr) {
|
||||
list.add(((SQLIdentifierExpr) expr).getName());
|
||||
} else {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<List<Object>> getInsertRows(Collection<Integer> primaryKeyIndex) {
|
||||
List<SQLInsertStatement.ValuesClause> valuesClauses = ast.getValuesList();
|
||||
List<List<Object>> rows = new ArrayList<>(valuesClauses.size());
|
||||
for (SQLInsertStatement.ValuesClause valuesClause : valuesClauses) {
|
||||
List<SQLExpr> exprs = valuesClause.getValues();
|
||||
List<Object> row = new ArrayList<>(exprs.size());
|
||||
rows.add(row);
|
||||
for (int i = 0, len = exprs.size(); i < len; i++) {
|
||||
SQLExpr expr = exprs.get(i);
|
||||
if (expr instanceof SQLNullExpr) {
|
||||
row.add(Null.get());
|
||||
} else if (expr instanceof SQLValuableExpr) {
|
||||
row.add(((SQLValuableExpr) expr).getValue());
|
||||
} else if (expr instanceof SQLVariantRefExpr) {
|
||||
row.add(((SQLVariantRefExpr) expr).getName());
|
||||
} else if (expr instanceof SQLMethodInvokeExpr) {
|
||||
SQLMethodInvokeExpr sqlMethodInvokeExpr = (SQLMethodInvokeExpr) expr;
|
||||
String function = sqlMethodInvokeExpr.getMethodName();
|
||||
if (StringUtils.equalsIgnoreCase(function, "nextval")) {
|
||||
String sequence = sqlMethodInvokeExpr.getParameters().get(0).toString();
|
||||
row.add(new SqlSequenceExpr(sequence, function));
|
||||
} else {
|
||||
row.add(SqlMethodExpr.get());
|
||||
}
|
||||
} else if (expr instanceof SQLSequenceExpr) {
|
||||
SQLSequenceExpr sequenceExpr = (SQLSequenceExpr) expr;
|
||||
String sequence = sequenceExpr.getSequence().getSimpleName();
|
||||
String function = sequenceExpr.getFunction().name;
|
||||
row.add(new SqlSequenceExpr(sequence, function));
|
||||
} else if (expr instanceof SQLDefaultExpr) {
|
||||
row.add(SqlDefaultExpr.get());
|
||||
} else {
|
||||
if (primaryKeyIndex.contains(i)) {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
row.add(NotPlaceholderExpr.get());
|
||||
}
|
||||
}
|
||||
}
|
||||
return rows;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.postgresql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGSelectQueryBlock;
|
||||
import io.seata.common.loader.LoadLevel;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.druid.SQLOperateRecognizerHolder;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
|
||||
/**
|
||||
* The type PostgresqlOperateRecognizerHolder
|
||||
*
|
||||
* @author will.zjw
|
||||
*/
|
||||
@LoadLevel(name = JdbcConstants.POSTGRESQL)
|
||||
public class PostgresqlOperateRecognizerHolder implements SQLOperateRecognizerHolder {
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getDeleteRecognizer(String sql, SQLStatement ast) {
|
||||
return new PostgresqlDeleteRecognizer(sql, ast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getInsertRecognizer(String sql, SQLStatement ast) {
|
||||
return new PostgresqlInsertRecognizer(sql, ast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getUpdateRecognizer(String sql, SQLStatement ast) {
|
||||
return new PostgresqlUpdateRecognizer(sql, ast);
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLRecognizer getSelectForUpdateRecognizer(String sql, SQLStatement ast) {
|
||||
PGSelectQueryBlock selectQueryBlock = (PGSelectQueryBlock) ((SQLSelectStatement) ast).getSelect().getFirstQueryBlock();
|
||||
if (selectQueryBlock.getForClause() != null && selectQueryBlock.getForClause().getOption().equals(PGSelectQueryBlock.ForClause.Option.UPDATE)) {
|
||||
return new PostgresqlSelectForUpdateRecognizer(sql, ast);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.postgresql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelect;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLSelectRecognizer;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author japsercloud
|
||||
*/
|
||||
public class PostgresqlSelectForUpdateRecognizer extends BasePostgresqlRecognizer implements SQLSelectRecognizer {
|
||||
|
||||
private final SQLSelectStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new Postgresql select for update recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public PostgresqlSelectForUpdateRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (SQLSelectStatement) ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.SELECT_FOR_UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLExpr where = selectQueryBlock.getWhere();
|
||||
return super.getWhereCondition(where, parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLExpr where = selectQueryBlock.getWhere();
|
||||
return super.getWhereCondition(where);
|
||||
}
|
||||
|
||||
private SQLSelectQueryBlock getSelect() {
|
||||
SQLSelect select = ast.getSelect();
|
||||
if (select == null) {
|
||||
throw new SQLParsingException("should never happen!");
|
||||
}
|
||||
SQLSelectQueryBlock selectQueryBlock = select.getQueryBlock();
|
||||
if (selectQueryBlock == null) {
|
||||
throw new SQLParsingException("should never happen!");
|
||||
}
|
||||
return selectQueryBlock;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLTableSource tableSource = selectQueryBlock.getFrom();
|
||||
return tableSource.getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
SQLSelectQueryBlock selectQueryBlock = getSelect();
|
||||
SQLTableSource tableSource = selectQueryBlock.getFrom();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
PGOutputVisitor visitor = new PGOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
};
|
||||
visitor.visit((SQLExprTableSource) tableSource);
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,147 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid.postgresql;
|
||||
|
||||
import com.alibaba.druid.sql.ast.SQLExpr;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLIdentifierExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLPropertyExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLValuableExpr;
|
||||
import com.alibaba.druid.sql.ast.expr.SQLVariantRefExpr;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLExprTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLJoinTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLTableSource;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.ast.stmt.PGUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.postgresql.visitor.PGOutputVisitor;
|
||||
import io.seata.common.exception.NotSupportYetException;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.SQLUpdateRecognizer;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author japsercloud
|
||||
*/
|
||||
public class PostgresqlUpdateRecognizer extends BasePostgresqlRecognizer implements SQLUpdateRecognizer {
|
||||
|
||||
private PGUpdateStatement ast;
|
||||
|
||||
/**
|
||||
* Instantiates a new Postgresql update recognizer.
|
||||
*
|
||||
* @param originalSQL the original sql
|
||||
* @param ast the ast
|
||||
*/
|
||||
public PostgresqlUpdateRecognizer(String originalSQL, SQLStatement ast) {
|
||||
super(originalSQL);
|
||||
this.ast = (PGUpdateStatement) ast;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLType getSQLType() {
|
||||
return SQLType.UPDATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getUpdateColumns() {
|
||||
List<SQLUpdateSetItem> updateSetItems = ast.getItems();
|
||||
List<String> list = new ArrayList<>(updateSetItems.size());
|
||||
for (SQLUpdateSetItem updateSetItem : updateSetItems) {
|
||||
SQLExpr expr = updateSetItem.getColumn();
|
||||
if (expr instanceof SQLIdentifierExpr) {
|
||||
list.add(((SQLIdentifierExpr) expr).getName());
|
||||
} else if (expr instanceof SQLPropertyExpr) {
|
||||
// This is alias case, like UPDATE xxx_tbl a SET a.name = ? WHERE a.id = ?
|
||||
SQLExpr owner = ((SQLPropertyExpr) expr).getOwner();
|
||||
if (owner instanceof SQLIdentifierExpr) {
|
||||
list.add(((SQLIdentifierExpr) owner).getName() + "." + ((SQLPropertyExpr) expr).getName());
|
||||
//This is table Field Full path, like update xxx_database.xxx_tbl set xxx_database.xxx_tbl.xxx_field...
|
||||
} else if (((SQLPropertyExpr) expr).getOwnernName().split("\\.").length > 1) {
|
||||
list.add(((SQLPropertyExpr)expr).getOwnernName() + "." + ((SQLPropertyExpr)expr).getName());
|
||||
}
|
||||
} else {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> getUpdateValues() {
|
||||
List<SQLUpdateSetItem> updateSetItems = ast.getItems();
|
||||
List<Object> list = new ArrayList<>(updateSetItems.size());
|
||||
for (SQLUpdateSetItem updateSetItem : updateSetItems) {
|
||||
SQLExpr expr = updateSetItem.getValue();
|
||||
if (expr instanceof SQLValuableExpr) {
|
||||
list.add(((SQLValuableExpr) expr).getValue());
|
||||
} else if (expr instanceof SQLVariantRefExpr) {
|
||||
list.add(new VMarker());
|
||||
} else {
|
||||
throw new SQLParsingException("Unknown SQLExpr: " + expr.getClass() + " " + expr);
|
||||
}
|
||||
}
|
||||
return list;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition(final ParametersHolder parametersHolder,
|
||||
final ArrayList<List<Object>> paramAppenderList) {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where, parametersHolder, paramAppenderList);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getWhereCondition() {
|
||||
SQLExpr where = ast.getWhere();
|
||||
return super.getWhereCondition(where);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableAlias() {
|
||||
return ast.getTableSource().getAlias();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getTableName() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
PGOutputVisitor visitor = new PGOutputVisitor(sb) {
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLExprTableSource x) {
|
||||
printTableSourceExpr(x.getExpr());
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean visit(SQLJoinTableSource x) {
|
||||
throw new NotSupportYetException("not support the syntax of update with join table");
|
||||
}
|
||||
};
|
||||
SQLTableSource tableSource = ast.getTableSource();
|
||||
if (tableSource instanceof SQLExprTableSource) {
|
||||
visitor.visit((SQLExprTableSource) tableSource);
|
||||
} else if (tableSource instanceof SQLJoinTableSource) {
|
||||
visitor.visit((SQLJoinTableSource) tableSource);
|
||||
} else {
|
||||
throw new NotSupportYetException("not support the syntax of update with unknow");
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
io.seata.sqlparser.druid.DruidDelegatingSQLRecognizerFactory
|
||||
@@ -0,0 +1,3 @@
|
||||
io.seata.sqlparser.druid.mysql.MySQLOperateRecognizerHolder
|
||||
io.seata.sqlparser.druid.oracle.OracleOperateRecognizerHolder
|
||||
io.seata.sqlparser.druid.postgresql.PostgresqlOperateRecognizerHolder
|
||||
@@ -0,0 +1 @@
|
||||
io.seata.sqlparser.druid.DruidDelegatingDbTypeParser
|
||||
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
|
||||
/**
|
||||
* The type Abstract my sql recognizer test.
|
||||
*
|
||||
* @author hanwen created at 2019-01-25
|
||||
*/
|
||||
public abstract class AbstractRecognizerTest {
|
||||
|
||||
/**
|
||||
* Gets sql statement.
|
||||
*
|
||||
* @param sql the sql
|
||||
* @return the sql statement
|
||||
*/
|
||||
public SQLStatement getSQLStatement(String sql) {
|
||||
List<SQLStatement> stats = SQLUtils.parseStatements(sql, getDbType());
|
||||
return stats.get(0);
|
||||
}
|
||||
|
||||
public abstract String getDbType();
|
||||
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import io.seata.common.loader.EnhancedServiceLoader;
|
||||
import io.seata.sqlparser.SqlParserType;
|
||||
import io.seata.sqlparser.util.DbTypeParser;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
public class DruidDbTypeParserTest {
|
||||
@Test
|
||||
public void testDruidDbTypeParserLoading() {
|
||||
String jdbcUrl = "jdbc:mysql://127.0.0.1:3306/seata";
|
||||
DruidDelegatingDbTypeParser dbTypeParser = (DruidDelegatingDbTypeParser) EnhancedServiceLoader.load(DbTypeParser.class, SqlParserType.SQL_PARSER_TYPE_DRUID);
|
||||
Assertions.assertNotNull(dbTypeParser);
|
||||
Assertions.assertEquals(DruidDelegatingDbTypeParser.class, dbTypeParser.getClass());
|
||||
String dbType = dbTypeParser.parseFromJdbcUrl(jdbcUrl);
|
||||
Assertions.assertEquals("mysql", dbType);
|
||||
|
||||
DruidLoader druidLoaderForTest = new DruidLoaderForTest();
|
||||
dbTypeParser.setClassLoader(new DruidIsolationClassLoader(druidLoaderForTest));
|
||||
Assertions.assertThrows(NoClassDefFoundError.class, () -> dbTypeParser.parseFromJdbcUrl(jdbcUrl));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import io.seata.common.loader.EnhancedServiceLoader;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.SQLRecognizerFactory;
|
||||
import io.seata.sqlparser.SqlParserType;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
import org.junit.jupiter.api.AfterAll;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author ggndnn
|
||||
*/
|
||||
public class DruidIsolationTest {
|
||||
private final static String TEST_SQL = "insert into t_table_1 values(?, ?)";
|
||||
|
||||
@Test
|
||||
public void testDruidIsolation() throws Exception {
|
||||
DruidDelegatingSQLRecognizerFactory recognizerFactory = (DruidDelegatingSQLRecognizerFactory) EnhancedServiceLoader.load(SQLRecognizerFactory.class, SqlParserType.SQL_PARSER_TYPE_DRUID);
|
||||
Assertions.assertNotNull(recognizerFactory);
|
||||
List<SQLRecognizer> sqlRecognizer = recognizerFactory.create(TEST_SQL, JdbcConstants.MYSQL);
|
||||
Assertions.assertNotNull(sqlRecognizer);
|
||||
DruidLoader druidLoaderForTest = new DruidLoaderForTest();
|
||||
recognizerFactory.setClassLoader(new DruidIsolationClassLoader(druidLoaderForTest));
|
||||
// because druid-test.jar not exists, so NoClassDefFoundError should be threw
|
||||
Assertions.assertThrows(NoClassDefFoundError.class, () -> recognizerFactory.create(TEST_SQL, JdbcConstants.MYSQL));
|
||||
}
|
||||
|
||||
@AfterAll
|
||||
public static void afterClass(){
|
||||
DruidDelegatingSQLRecognizerFactory recognizerFactory = (DruidDelegatingSQLRecognizerFactory) EnhancedServiceLoader.load(SQLRecognizerFactory.class,
|
||||
SqlParserType.SQL_PARSER_TYPE_DRUID);
|
||||
recognizerFactory.setClassLoader(DruidIsolationTest.class.getClassLoader());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URI;
|
||||
import java.net.URL;
|
||||
|
||||
class DruidLoaderForTest implements DruidLoader {
|
||||
@Override
|
||||
public URL getEmbeddedDruidLocation() {
|
||||
try {
|
||||
return URI.create("file://druid-test.jar").toURL();
|
||||
} catch (MalformedURLException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import io.seata.common.loader.EnhancedServiceLoader;
|
||||
import io.seata.sqlparser.SQLRecognizer;
|
||||
import io.seata.sqlparser.SQLRecognizerFactory;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.SqlParserType;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class DruidSQLRecognizerFactoryTest {
|
||||
@Test
|
||||
public void testSqlRecognizerCreation() {
|
||||
SQLRecognizerFactory recognizerFactory = EnhancedServiceLoader.load(SQLRecognizerFactory.class, SqlParserType.SQL_PARSER_TYPE_DRUID);
|
||||
Assertions.assertNotNull(recognizerFactory);
|
||||
List<SQLRecognizer> recognizers = recognizerFactory.create("delete from t1", JdbcConstants.MYSQL);
|
||||
Assertions.assertNotNull(recognizers);
|
||||
Assertions.assertEquals(recognizers.size(),1);
|
||||
Assertions.assertEquals(SQLType.DELETE, recognizers.get(0).getSQLType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,342 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLDeleteStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.druid.mysql.MySQLDeleteRecognizer;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* The type My sql delete recognizer test.
|
||||
*
|
||||
* @author hanwen created at 2019-01-25
|
||||
*/
|
||||
public class MySQLDeleteRecognizerTest extends AbstractRecognizerTest {
|
||||
|
||||
@Test
|
||||
public void testVMarker() {
|
||||
Assertions.assertEquals("?", new BaseRecognizer.VMarker().toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recognizer test 0.
|
||||
*/
|
||||
@Test
|
||||
public void deleteRecognizerTest_0() {
|
||||
ParametersHolder parametersHolder = new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
return Collections.EMPTY_MAP;
|
||||
}
|
||||
};
|
||||
|
||||
String sql = "DELETE FROM t1 WHERE id = 'id1' order by id asc,name desc limit 1,2";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
|
||||
MySQLDeleteRecognizer mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
|
||||
String orderBy = mySQLDeleteRecognizer.getOrderBy();
|
||||
Assertions.assertTrue(orderBy.equalsIgnoreCase(" ORDER BY id asc,name desc"));
|
||||
Assertions.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
|
||||
Assertions.assertEquals("id = 'id1'", mySQLDeleteRecognizer.getWhereCondition());
|
||||
String limit = mySQLDeleteRecognizer.getLimit(parametersHolder, paramAppenderList);
|
||||
Assertions.assertEquals(" LIMIT 1,2", limit);
|
||||
sql = "DELETE FROM t1 WHERE id > 1 order by id ,name desc limit 1";
|
||||
statement = getSQLStatement(sql);
|
||||
mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
|
||||
orderBy = mySQLDeleteRecognizer.getOrderBy();
|
||||
Assertions.assertTrue(orderBy.equalsIgnoreCase(" order by id,name desc"));
|
||||
Assertions.assertEquals(" LIMIT 1", mySQLDeleteRecognizer.getLimit(parametersHolder, paramAppenderList));
|
||||
sql = "DELETE FROM t1 WHERE id > 1";
|
||||
statement = getSQLStatement(sql);
|
||||
mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
|
||||
Assertions.assertEquals(null, mySQLDeleteRecognizer.getLimit(parametersHolder, paramAppenderList));
|
||||
orderBy = mySQLDeleteRecognizer.getOrderBy();
|
||||
Assertions.assertEquals(null, mySQLDeleteRecognizer.getOrderBy());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void deleteRecognizerTest_1() {
|
||||
|
||||
String sql = "DELETE FROM t1 WHERE id = ?";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLDeleteRecognizer mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
|
||||
|
||||
// test overflow parameters
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLDeleteRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> idParam = new ArrayList<>();
|
||||
idParam.add("id1");
|
||||
Map result = new HashMap<>();
|
||||
result.put(1,idParam);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Collections.singletonList("id1")), paramAppenderList);
|
||||
Assertions.assertEquals("id = ?", whereCondition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recognizer test 2.
|
||||
*/
|
||||
@Test
|
||||
public void deleteRecognizerTest_2() {
|
||||
|
||||
String sql = "DELETE FROM t1 WHERE id IN (?, ?)";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLDeleteRecognizer mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
|
||||
|
||||
// test overflow parameters
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLDeleteRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> idParam = new ArrayList<>();
|
||||
idParam.add("id1");
|
||||
ArrayList<Object> id2Param = new ArrayList<>();
|
||||
id2Param.add("id2");
|
||||
Map result = new HashMap();
|
||||
result.put(1, idParam);
|
||||
result.put(2, id2Param);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Arrays.asList(Arrays.asList("id1", "id2")), paramAppenderList);
|
||||
Assertions.assertEquals("id IN (?, ?)", whereCondition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete recognizer test 3.
|
||||
*/
|
||||
@Test
|
||||
public void deleteRecognizerTest_3() {
|
||||
|
||||
String sql = "DELETE FROM t1 WHERE id between ? AND ?";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLDeleteRecognizer mySQLDeleteRecognizer = new MySQLDeleteRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLDeleteRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLDeleteRecognizer.getTableName());
|
||||
|
||||
// test overflow parameters
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLDeleteRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> idParam = new ArrayList<>();
|
||||
idParam.add("id1");
|
||||
ArrayList<Object> id2Param = new ArrayList<>();
|
||||
id2Param.add("id2");
|
||||
Map result = new HashMap();
|
||||
result.put(1, idParam);
|
||||
result.put(2, id2Param);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Arrays.asList("id1", "id2")), paramAppenderList);
|
||||
Assertions.assertEquals("id BETWEEN ? AND ?", whereCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSqlType() {
|
||||
String sql = "delete from t where id = ?";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLDeleteRecognizer recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
Assertions.assertEquals(recognizer.getSQLType(), SQLType.DELETE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTableAlias() {
|
||||
String sql = "delete from t where id = ?";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLDeleteRecognizer recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
Assertions.assertNull(recognizer.getTableAlias());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetWhereCondition_0() {
|
||||
String sql = "delete from t";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLDeleteRecognizer recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
String whereCondition = recognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
return null;
|
||||
}
|
||||
}, new ArrayList<>());
|
||||
|
||||
//test for no condition
|
||||
Assertions.assertEquals("", whereCondition);
|
||||
|
||||
sql = "delete from t where id = ?";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
whereCondition = recognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> idParam = new ArrayList<>();
|
||||
idParam.add(1);
|
||||
Map result = new HashMap();
|
||||
result.put(1, idParam);
|
||||
return result;
|
||||
}
|
||||
}, new ArrayList<>());
|
||||
|
||||
//test for normal sql
|
||||
Assertions.assertEquals("id = ?", whereCondition);
|
||||
|
||||
sql = "delete from t where id in (?)";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
whereCondition = recognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> idParam = new ArrayList<>();
|
||||
idParam.add(1);
|
||||
Map result = new HashMap();
|
||||
result.put(1, idParam);
|
||||
return result;
|
||||
}
|
||||
}, new ArrayList<>());
|
||||
|
||||
//test for sql with in
|
||||
Assertions.assertEquals("id IN (?)", whereCondition);
|
||||
|
||||
sql = "delete from t where id between ? and ?";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
whereCondition = recognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> idParam = new ArrayList<>();
|
||||
idParam.add(1);
|
||||
ArrayList<Object> idParam2 = new ArrayList<>();
|
||||
idParam.add(2);
|
||||
Map result = new HashMap();
|
||||
result.put(1, idParam);
|
||||
result.put(2, idParam2);
|
||||
return result;
|
||||
}
|
||||
}, new ArrayList<>());
|
||||
//test for sql with in
|
||||
Assertions.assertEquals("id BETWEEN ? AND ?", whereCondition);
|
||||
|
||||
//test for exception
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> {
|
||||
String s = "delete from t where id in (?)";
|
||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL);
|
||||
SQLDeleteStatement deleteAst = (SQLDeleteStatement) sqlStatements.get(0);
|
||||
deleteAst.setWhere(new MySqlOrderingExpr());
|
||||
new MySQLDeleteRecognizer(s, deleteAst).getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
return new HashMap();
|
||||
}
|
||||
}, new ArrayList<>());
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetWhereCondition_1() {
|
||||
|
||||
String sql = "delete from t";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLDeleteRecognizer recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
String whereCondition = recognizer.getWhereCondition();
|
||||
|
||||
//test for no condition
|
||||
Assertions.assertEquals("", whereCondition);
|
||||
|
||||
sql = "delete from t where id = 1";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
whereCondition = recognizer.getWhereCondition();
|
||||
|
||||
//test for normal sql
|
||||
Assertions.assertEquals("id = 1", whereCondition);
|
||||
|
||||
sql = "delete from t where id in (1)";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
whereCondition = recognizer.getWhereCondition();
|
||||
|
||||
//test for sql with in
|
||||
Assertions.assertEquals("id IN (1)", whereCondition);
|
||||
|
||||
sql = "delete from t where id between 1 and 2";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
recognizer = new MySQLDeleteRecognizer(sql, asts.get(0));
|
||||
whereCondition = recognizer.getWhereCondition();
|
||||
//test for sql with in
|
||||
Assertions.assertEquals("id BETWEEN 1 AND 2", whereCondition);
|
||||
|
||||
//test for exception
|
||||
Assertions.assertThrows(IllegalArgumentException.class, () -> {
|
||||
String s = "delete from t where id in (1)";
|
||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL);
|
||||
SQLDeleteStatement deleteAst = (SQLDeleteStatement) sqlStatements.get(0);
|
||||
deleteAst.setWhere(new MySqlOrderingExpr());
|
||||
new MySQLDeleteRecognizer(s, deleteAst).getWhereCondition();
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDbType() {
|
||||
return JdbcConstants.MYSQL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLInsertStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;
|
||||
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.druid.mysql.MySQLInsertRecognizer;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* The type My sql insert recognizer test.
|
||||
*
|
||||
* @author hanwen created at 2019-01-25
|
||||
*/
|
||||
public class MySQLInsertRecognizerTest extends AbstractRecognizerTest {
|
||||
|
||||
private final int pkIndex = 0;
|
||||
|
||||
/**
|
||||
* Insert recognizer test 0.
|
||||
*/
|
||||
@Test
|
||||
public void insertRecognizerTest_0() {
|
||||
|
||||
String sql = "INSERT INTO t1 (name) VALUES ('name1')";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLInsertRecognizer mySQLInsertRecognizer = new MySQLInsertRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLInsertRecognizer.getTableName());
|
||||
Assertions.assertEquals(Collections.singletonList("name"), mySQLInsertRecognizer.getInsertColumns());
|
||||
Assertions.assertEquals(1, mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).size());
|
||||
Assertions.assertEquals(Collections.singletonList("name1"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void insertRecognizerTest_1() {
|
||||
|
||||
String sql = "INSERT INTO t1 (name1, name2) VALUES ('name1', 'name2')";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLInsertRecognizer mySQLInsertRecognizer = new MySQLInsertRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLInsertRecognizer.getTableName());
|
||||
Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertColumns());
|
||||
Assertions.assertEquals(1, mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).size());
|
||||
Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(0));
|
||||
}
|
||||
|
||||
/**
|
||||
* Insert recognizer test 3.
|
||||
*/
|
||||
@Test
|
||||
public void insertRecognizerTest_3() {
|
||||
|
||||
String sql = "INSERT INTO t1 (name1, name2) VALUES ('name1', 'name2'), ('name3', 'name4'), ('name5', 'name6')";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLInsertRecognizer mySQLInsertRecognizer = new MySQLInsertRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLInsertRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLInsertRecognizer.getTableName());
|
||||
Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertColumns());
|
||||
Assertions.assertEquals(3, mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).size());
|
||||
Assertions.assertEquals(Arrays.asList("name1", "name2"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(0));
|
||||
Assertions.assertEquals(Arrays.asList("name3", "name4"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(1));
|
||||
Assertions.assertEquals(Arrays.asList("name5", "name6"), mySQLInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex)).get(2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSqlType() {
|
||||
String sql = "insert into t(id) values (?)";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLInsertRecognizer recognizer = new MySQLInsertRecognizer(sql, asts.get(0));
|
||||
Assertions.assertEquals(recognizer.getSQLType(), SQLType.INSERT);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTableAlias() {
|
||||
String sql = "insert into t(id) values (?)";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLInsertRecognizer recognizer = new MySQLInsertRecognizer(sql, asts.get(0));
|
||||
Assertions.assertNull(recognizer.getTableAlias());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInsertColumns() {
|
||||
|
||||
//test for no column
|
||||
String sql = "insert into t values (?)";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLInsertRecognizer recognizer = new MySQLInsertRecognizer(sql, asts.get(0));
|
||||
List<String> insertColumns = recognizer.getInsertColumns();
|
||||
Assertions.assertNull(insertColumns);
|
||||
|
||||
//test for normal
|
||||
sql = "insert into t(a) values (?)";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
recognizer = new MySQLInsertRecognizer(sql, asts.get(0));
|
||||
insertColumns = recognizer.getInsertColumns();
|
||||
Assertions.assertEquals(1, insertColumns.size());
|
||||
|
||||
//test for exception
|
||||
Assertions.assertThrows(SQLParsingException.class, () -> {
|
||||
String s = "insert into t(a) values (?)";
|
||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL);
|
||||
SQLInsertStatement sqlInsertStatement = (SQLInsertStatement)sqlStatements.get(0);
|
||||
sqlInsertStatement.getColumns().add(new MySqlOrderingExpr());
|
||||
|
||||
MySQLInsertRecognizer oracleInsertRecognizer = new MySQLInsertRecognizer(s, sqlInsertStatement);
|
||||
oracleInsertRecognizer.getInsertColumns();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetInsertRows() {
|
||||
//test for null value
|
||||
String sql = "insert into t(id, no, name, age, time) values (1, null, 'a', ?, now())";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLInsertRecognizer recognizer = new MySQLInsertRecognizer(sql, asts.get(0));
|
||||
List<List<Object>> insertRows = recognizer.getInsertRows(Collections.singletonList(pkIndex));
|
||||
Assertions.assertEquals(1, insertRows.size());
|
||||
|
||||
//test for exception
|
||||
Assertions.assertThrows(SQLParsingException.class, () -> {
|
||||
String s = "insert into t(a) values (?)";
|
||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL);
|
||||
SQLInsertStatement sqlInsertStatement = (SQLInsertStatement)sqlStatements.get(0);
|
||||
sqlInsertStatement.getValuesList().get(0).getValues().set(pkIndex, new MySqlOrderingExpr());
|
||||
|
||||
MySQLInsertRecognizer mysqlInsertRecognizer = new MySQLInsertRecognizer(s, sqlInsertStatement);
|
||||
mysqlInsertRecognizer.getInsertRows(Collections.singletonList(pkIndex));
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDbType() {
|
||||
return JdbcConstants.MYSQL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,241 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLSelectStatement;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.druid.mysql.MySQLSelectForUpdateRecognizer;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* The type My sql select for update recognizer test.
|
||||
*/
|
||||
public class MySQLSelectForUpdateRecognizerTest extends AbstractRecognizerTest {
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 0.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_0() {
|
||||
|
||||
String sql = "SELECT name FROM t1 WHERE id = 'id1' FOR UPDATE";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
Assertions.assertEquals("id = 'id1'", mySQLUpdateRecognizer.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_1() {
|
||||
|
||||
String sql = "SELECT name FROM t1 WHERE id = ? FOR UPDATE";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> idParam = new ArrayList<>();
|
||||
idParam.add("id1");
|
||||
Map result = new HashMap();
|
||||
result.put(1, idParam);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Collections.singletonList("id1")), paramAppenderList);
|
||||
Assertions.assertEquals("id = ?", whereCondition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 3.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_3() {
|
||||
|
||||
String sql = "SELECT name1, name2 FROM t1 WHERE id = ? FOR UPDATE";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
|
||||
// test overflow parameters
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> id1Param = new ArrayList<>();
|
||||
id1Param.add("id1");
|
||||
Map result = new HashMap();
|
||||
result.put(1, id1Param);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Collections.singletonList("id1")), paramAppenderList);
|
||||
Assertions.assertEquals("id = ?", whereCondition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 4.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_4() {
|
||||
|
||||
String sql = "SELECT name1, name2 FROM t1 WHERE id IN (?,?) FOR UPDATE";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
|
||||
// test overflow parameters
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> id1Param = new ArrayList<>();
|
||||
id1Param.add("id1");
|
||||
ArrayList<Object> id2Param = new ArrayList<>();
|
||||
id2Param.add("id2");
|
||||
Map result = new HashMap();
|
||||
result.put(1, id1Param);
|
||||
result.put(2, id2Param);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Arrays.asList("id1", "id2")), paramAppenderList);
|
||||
Assertions.assertEquals("id IN (?, ?)", whereCondition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Select for update recognizer test 5.
|
||||
*/
|
||||
@Test
|
||||
public void selectForUpdateRecognizerTest_5() {
|
||||
|
||||
String sql = "SELECT name1, name2 FROM t1 WHERE id between ? and ? FOR UPDATE";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLSelectForUpdateRecognizer mySQLUpdateRecognizer = new MySQLSelectForUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
|
||||
// test overflow parameters
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> id1Param = new ArrayList<>();
|
||||
id1Param.add("id1");
|
||||
ArrayList<Object> id2Param = new ArrayList<>();
|
||||
id2Param.add("id2");
|
||||
Map result = new HashMap();
|
||||
result.put(1, id1Param);
|
||||
result.put(2, id2Param);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Arrays.asList("id1", "id2")), paramAppenderList);
|
||||
Assertions.assertEquals("id BETWEEN ? AND ?", whereCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetWhereCondition_1() {
|
||||
String sql = "select * from t for update";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLSelectForUpdateRecognizer recognizer = new MySQLSelectForUpdateRecognizer(sql, asts.get(0));
|
||||
String whereCondition = recognizer.getWhereCondition();
|
||||
|
||||
Assertions.assertEquals("", whereCondition);
|
||||
|
||||
//test for select was null
|
||||
Assertions.assertThrows(SQLParsingException.class, () -> {
|
||||
String s = "select * from t for update";
|
||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL);
|
||||
SQLSelectStatement selectAst = (SQLSelectStatement) sqlStatements.get(0);
|
||||
selectAst.setSelect(null);
|
||||
new MySQLSelectForUpdateRecognizer(s, selectAst).getWhereCondition();
|
||||
});
|
||||
|
||||
//test for query was null
|
||||
Assertions.assertThrows(SQLParsingException.class, () -> {
|
||||
String s = "select * from t";
|
||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL);
|
||||
SQLSelectStatement selectAst = (SQLSelectStatement) sqlStatements.get(0);
|
||||
selectAst.getSelect().setQuery(null);
|
||||
new MySQLSelectForUpdateRecognizer(s, selectAst).getWhereCondition();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSqlType() {
|
||||
String sql = "select * from t where id = ? for update";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLSelectForUpdateRecognizer recognizer = new MySQLSelectForUpdateRecognizer(sql, asts.get(0));
|
||||
Assertions.assertEquals(recognizer.getSQLType(), SQLType.SELECT_FOR_UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTableAlias() {
|
||||
String sql = "select * from t where id = ? for update";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLSelectForUpdateRecognizer recognizer = new MySQLSelectForUpdateRecognizer(sql, asts.get(0));
|
||||
Assertions.assertNull(recognizer.getTableAlias());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDbType() {
|
||||
return JdbcConstants.MYSQL;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,357 @@
|
||||
/*
|
||||
* Copyright 1999-2019 Seata.io Group.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package io.seata.sqlparser.druid;
|
||||
|
||||
import com.alibaba.druid.sql.SQLUtils;
|
||||
import com.alibaba.druid.sql.ast.SQLStatement;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem;
|
||||
import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlCharExpr;
|
||||
import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlOrderingExpr;
|
||||
import io.seata.sqlparser.ParametersHolder;
|
||||
import io.seata.sqlparser.SQLParsingException;
|
||||
import io.seata.sqlparser.SQLType;
|
||||
import io.seata.sqlparser.druid.mysql.MySQLUpdateRecognizer;
|
||||
import io.seata.sqlparser.util.JdbcConstants;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import org.junit.jupiter.api.Assertions;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
/**
|
||||
* The type My sql update recognizer test.
|
||||
*/
|
||||
public class MySQLUpdateRecognizerTest extends AbstractRecognizerTest {
|
||||
|
||||
/**
|
||||
* Update recognizer test 0.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_0() {
|
||||
|
||||
String sql = "UPDATE t1 SET name = 'name1' WHERE id = 'id1'";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
Assertions.assertEquals(1, mySQLUpdateRecognizer.getUpdateColumns().size());
|
||||
Assertions.assertEquals("name", mySQLUpdateRecognizer.getUpdateColumns().get(0));
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
|
||||
Assertions.assertEquals("id = 'id1'", mySQLUpdateRecognizer.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 1.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_1() {
|
||||
|
||||
String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id = 'id1'";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
|
||||
Assertions.assertEquals("id = 'id1'", mySQLUpdateRecognizer.getWhereCondition());
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 2.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_2() {
|
||||
|
||||
String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id = ?";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
|
||||
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> idParam = new ArrayList<>();
|
||||
idParam.add("id1");
|
||||
Map result = new HashMap();
|
||||
result.put(1, idParam);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Collections.singletonList("id1")), paramAppenderList);
|
||||
|
||||
Assertions.assertEquals("id = ?", whereCondition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 3.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_3() {
|
||||
|
||||
String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id in (?, ?)";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
|
||||
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> id1Param = new ArrayList<>();
|
||||
id1Param.add("id1");
|
||||
ArrayList<Object> id2Param = new ArrayList<>();
|
||||
id2Param.add("id2");
|
||||
Map result = new HashMap();
|
||||
result.put(1, id1Param);
|
||||
result.put(2, id2Param);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Arrays.asList("id1", "id2")), paramAppenderList);
|
||||
|
||||
Assertions.assertEquals("id IN (?, ?)", whereCondition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 4.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_4() {
|
||||
|
||||
String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id in (?, ?) and name1 = ?";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
|
||||
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> id1Param = new ArrayList<>();
|
||||
id1Param.add("id1");
|
||||
ArrayList<Object> id2Param = new ArrayList<>();
|
||||
id2Param.add("id2");
|
||||
ArrayList<Object> name1Param = new ArrayList<>();
|
||||
name1Param.add("name");
|
||||
Map result = new HashMap();
|
||||
result.put(1, id1Param);
|
||||
result.put(2, id2Param);
|
||||
result.put(3, name1Param);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Arrays.asList("id1", "id2", "name")), paramAppenderList);
|
||||
|
||||
Assertions.assertEquals("id IN (?, ?)\nAND name1 = ?", whereCondition);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update recognizer test 5.
|
||||
*/
|
||||
@Test
|
||||
public void updateRecognizerTest_5() {
|
||||
|
||||
String sql = "UPDATE t1 SET name1 = 'name1', name2 = 'name2' WHERE id between ? and ?";
|
||||
|
||||
SQLStatement statement = getSQLStatement(sql);
|
||||
|
||||
MySQLUpdateRecognizer mySQLUpdateRecognizer = new MySQLUpdateRecognizer(sql, statement);
|
||||
|
||||
Assertions.assertEquals(sql, mySQLUpdateRecognizer.getOriginalSQL());
|
||||
Assertions.assertEquals("t1", mySQLUpdateRecognizer.getTableName());
|
||||
Assertions.assertEquals(2, mySQLUpdateRecognizer.getUpdateColumns().size());
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateColumns().get(0));
|
||||
Assertions.assertEquals("name1", mySQLUpdateRecognizer.getUpdateValues().get(0));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateColumns().get(1));
|
||||
Assertions.assertEquals("name2", mySQLUpdateRecognizer.getUpdateValues().get(1));
|
||||
|
||||
ArrayList<List<Object>> paramAppenderList = new ArrayList<>();
|
||||
String whereCondition = mySQLUpdateRecognizer.getWhereCondition(new ParametersHolder() {
|
||||
@Override
|
||||
public Map<Integer,ArrayList<Object>> getParameters() {
|
||||
ArrayList<Object> id1Param = new ArrayList<>();
|
||||
id1Param.add("id1");
|
||||
ArrayList<Object> id2Param = new ArrayList<>();
|
||||
id2Param.add("id2");
|
||||
Map result = new HashMap();
|
||||
result.put(1, id1Param);
|
||||
result.put(2, id2Param);
|
||||
return result;
|
||||
}
|
||||
}, paramAppenderList);
|
||||
|
||||
Assertions.assertEquals(Collections.singletonList(Arrays.asList("id1", "id2")), paramAppenderList);
|
||||
Assertions.assertEquals("id BETWEEN ? AND ?", whereCondition);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetSqlType() {
|
||||
String sql = "update t set n = ?";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0));
|
||||
Assertions.assertEquals(recognizer.getSQLType(), SQLType.UPDATE);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUpdateColumns() {
|
||||
// test with normal
|
||||
String sql = "update t set a = ?, b = ?, c = ?";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0));
|
||||
List<String> updateColumns = recognizer.getUpdateColumns();
|
||||
Assertions.assertEquals(updateColumns.size(), 3);
|
||||
|
||||
// test with alias
|
||||
sql = "update t set a.a = ?, a.b = ?, a.c = ?";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
recognizer = new MySQLUpdateRecognizer(sql, asts.get(0));
|
||||
updateColumns = recognizer.getUpdateColumns();
|
||||
Assertions.assertEquals(updateColumns.size(), 3);
|
||||
|
||||
//test with error
|
||||
Assertions.assertThrows(SQLParsingException.class, () -> {
|
||||
String s = "update t set a = a";
|
||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL);
|
||||
SQLUpdateStatement sqlUpdateStatement = (SQLUpdateStatement) sqlStatements.get(0);
|
||||
List<SQLUpdateSetItem> updateSetItems = sqlUpdateStatement.getItems();
|
||||
for (SQLUpdateSetItem updateSetItem : updateSetItems) {
|
||||
updateSetItem.setColumn(new MySqlCharExpr());
|
||||
}
|
||||
MySQLUpdateRecognizer oracleUpdateRecognizer = new MySQLUpdateRecognizer(s, sqlUpdateStatement);
|
||||
oracleUpdateRecognizer.getUpdateColumns();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetUpdateDatabaseNameColumns() {
|
||||
// test with normal
|
||||
String sql = "update d.t set d.t.a = ?, d.t.b = ?, d.t.c = ?";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0));
|
||||
List<String> updateColumns = recognizer.getUpdateColumns();
|
||||
Assertions.assertEquals(updateColumns.size(), 3);
|
||||
|
||||
// test with alias
|
||||
sql = "update t set a.a = ?, a.b = ?, a.c = ?";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
recognizer = new MySQLUpdateRecognizer(sql, asts.get(0));
|
||||
updateColumns = recognizer.getUpdateColumns();
|
||||
Assertions.assertEquals(updateColumns.size(), 3);
|
||||
|
||||
//test with error
|
||||
Assertions.assertThrows(SQLParsingException.class, () -> {
|
||||
String s = "update t set a = a";
|
||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL);
|
||||
SQLUpdateStatement sqlUpdateStatement = (SQLUpdateStatement) sqlStatements.get(0);
|
||||
List<SQLUpdateSetItem> updateSetItems = sqlUpdateStatement.getItems();
|
||||
for (SQLUpdateSetItem updateSetItem : updateSetItems) {
|
||||
updateSetItem.setColumn(new MySqlCharExpr());
|
||||
}
|
||||
MySQLUpdateRecognizer oracleUpdateRecognizer = new MySQLUpdateRecognizer(s, sqlUpdateStatement);
|
||||
oracleUpdateRecognizer.getUpdateColumns();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetUpdateValues() {
|
||||
// test with normal
|
||||
String sql = "update t set a = ?, b = ?, c = ?";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0));
|
||||
List<Object> updateValues = recognizer.getUpdateValues();
|
||||
Assertions.assertEquals(updateValues.size(), 3);
|
||||
|
||||
// test with values
|
||||
sql = "update t set a = 1, b = 2, c = 3";
|
||||
asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
recognizer = new MySQLUpdateRecognizer(sql, asts.get(0));
|
||||
updateValues = recognizer.getUpdateValues();
|
||||
Assertions.assertEquals(updateValues.size(), 3);
|
||||
|
||||
// test with error
|
||||
Assertions.assertThrows(SQLParsingException.class, () -> {
|
||||
String s = "update t set a = ?";
|
||||
List<SQLStatement> sqlStatements = SQLUtils.parseStatements(s, JdbcConstants.MYSQL);
|
||||
SQLUpdateStatement sqlUpdateStatement = (SQLUpdateStatement)sqlStatements.get(0);
|
||||
List<SQLUpdateSetItem> updateSetItems = sqlUpdateStatement.getItems();
|
||||
for (SQLUpdateSetItem updateSetItem : updateSetItems) {
|
||||
updateSetItem.setValue(new MySqlOrderingExpr());
|
||||
}
|
||||
MySQLUpdateRecognizer oracleUpdateRecognizer = new MySQLUpdateRecognizer(s, sqlUpdateStatement);
|
||||
oracleUpdateRecognizer.getUpdateValues();
|
||||
});
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetTableAlias() {
|
||||
String sql = "update t set a = ?, b = ?, c = ?";
|
||||
List<SQLStatement> asts = SQLUtils.parseStatements(sql, JdbcConstants.MYSQL);
|
||||
|
||||
MySQLUpdateRecognizer recognizer = new MySQLUpdateRecognizer(sql, asts.get(0));
|
||||
Assertions.assertNull(recognizer.getTableAlias());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDbType() {
|
||||
return JdbcConstants.MYSQL;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user