chore(project): 添加项目配置文件和忽略规则

- 添加 Babel 配置文件支持 ES6+ 语法转换
- 添加 ESLint 忽略规则和配置文件
- 添加 Git 忽略规则文件
- 添加 Travis CI 配置文件
- 添加 1.4.2 版本变更日志文件
- 添加 Helm 图表辅助模板文件
- 添加 Helm 忽略规则文件
This commit is contained in:
2026-03-27 17:36:48 +08:00
commit c2453d6434
1703 changed files with 277582 additions and 0 deletions

View 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>

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}

View File

@@ -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;
}
}

View File

@@ -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);
}

View File

@@ -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()));
}
}

View File

@@ -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;
}
}

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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());
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -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);
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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();
}
}

View File

@@ -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();
}
}

View File

@@ -0,0 +1 @@
io.seata.sqlparser.druid.DruidDelegatingSQLRecognizerFactory

View File

@@ -0,0 +1,3 @@
io.seata.sqlparser.druid.mysql.MySQLOperateRecognizerHolder
io.seata.sqlparser.druid.oracle.OracleOperateRecognizerHolder
io.seata.sqlparser.druid.postgresql.PostgresqlOperateRecognizerHolder

View File

@@ -0,0 +1 @@
io.seata.sqlparser.druid.DruidDelegatingDbTypeParser

View File

@@ -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();
}

View File

@@ -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));
}
}

View File

@@ -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());
}
}

View File

@@ -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);
}
}
}

View File

@@ -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());
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}

View File

@@ -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;
}
}