未验证 提交 58eecb90 编写于 作者: L lorne 提交者: GitHub

Merge pull request #543 from BigBlackSheep/dev6.0

#501 结构优化
......@@ -14,4 +14,9 @@ com.codingapi.txlcn.tc.reporter.ReporterConfiguration,\
com.codingapi.txlcn.tc.resolver.ResolverConfiguration,\
com.codingapi.txlcn.tc.runner.TcRunnerConfiguration,\
com.codingapi.txlcn.tc.rpc.RpcTransactionConfiguration,\
com.codingapi.txlcn.tc.TCAutoConfiguration
\ No newline at end of file
com.codingapi.txlcn.tc.TCAutoConfiguration,\
com.codingapi.txlcn.tc.jdbc.sql.strategy.MysqlInsertAnalyseStrategy,\
com.codingapi.txlcn.tc.jdbc.sql.strategy.MysqlSqlDeleteAnalyseStrategy,\
com.codingapi.txlcn.tc.jdbc.sql.strategy.MysqlUpdateAnalyseStrategy,\
com.codingapi.txlcn.tc.jdbc.sql.strategy.AnalyseStrategryFactory,\
com.codingapi.txlcn.tc.jdbc.sql.analyse.MysqlAnalyse
\ No newline at end of file
package com.codingapi.txlcn.tc.jdbc.database;
import com.codingapi.txlcn.tc.utils.ListUtil;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.select.Join;
import java.sql.JDBCType;
import java.util.*;
import java.util.stream.Collectors;
/**
* @author Gz.
* @description: sql分析助手类
* @date 2020-08-17 23:26:01
*/
@Slf4j
public class SqlAnalyseHelper {
/**
* 检查是否包含主键
* @param table
* @param tableList
* @return
*/
public static boolean checkTableContainsPk(Table table, TableList tableList ) {
TableInfo tableInfo = tableList.getTable(table.getName());
if(ListUtil.isNotEmpty(tableInfo.getPrimaryKeys())){
return true;
}
return false;
}
public static boolean checkWhereContainsPk(Table table,TableList tableList,String whereSql){
TableInfo tableInfo = tableList.getTable(table.getName());
return whereSql.toUpperCase().contains(tableInfo.getPrimaryKeys().get(0).toUpperCase());
}
// public static SqlAnalyseInfo sqlAnalyseSingleTable(TableList tableList, Table table, Expression where, List<Join> joinList) {
// SqlAnalyseInfo sqlAnalyseInfo = new SqlAnalyseInfo();
// //单表操作
// StringBuilder querySql = new StringBuilder("select ");
// TableInfo tableInfo = tableList.getTable(table.getName());
// String primaryKey = tableInfo.getPrimaryKeys().get(0);
// String select = "";
// StringBuilder tableName = new StringBuilder();
// if(null != table.getAlias()){
// select = table.getAlias().getName().concat(".").concat(primaryKey);
// tableName.append(table.getName()).append(" ").append(table.getAlias());
// }else {
// select = primaryKey;
// tableName.append(table.getName());
// }
//
// for (Join join : joinList) {
// Table table1 = (Table)join.getRightItem();
// if(table1.getAlias()!=null){
// tableName.append(",").append(table1.getName()).append(" ").append(table1.getAlias());
// }else {
// tableName.append(",").append(table1.getName());
// }
// }
//
// querySql = querySql.append(select).append(" from ").append(tableName).append(" where ").append(where.toString());
// log.info("update Sql Analyse =[{}]",querySql);
// JDBCType type = tableInfo.getColumnInfos().stream().filter(m -> m.getName().equals(primaryKey)).findFirst().get().getType();
//
// sqlAnalyseInfo.setSelect(select);
// sqlAnalyseInfo.setQuerySql(querySql.toString());
// sqlAnalyseInfo.setPrimaryKey(primaryKey);
// sqlAnalyseInfo.setPrimaryKeyType(type);
// return sqlAnalyseInfo;
// }
// public static SqlAnalyseInfo sqlAnalyseMultiTable(TableList tableList, Table table, Expression where) {
// SqlAnalyseInfo sqlAnalyseInfo = new SqlAnalyseInfo();
//
// StringBuilder querySql = new StringBuilder("select ");
// String select = null;
// Set<String> s2 = new TreeSet<>();
//
// TableInfo tableInfo = tableList.getTable(table.getName());
// if(ListUtil.isNotEmpty(tableInfo.getPrimaryKeys())){
// //TODO sql中没有别名的情况
// if(StringUtils.isBlank(select)){
// select = table.getAlias().getName().concat(".").concat(tableInfo.getPrimaryKeys().get(0));
// String pk = tableInfo.getPrimaryKeys().get(0);
// JDBCType type = tableInfo.getColumnInfos().stream().filter(m -> m.getName().equals(pk)).findFirst().get().getType();
// sqlAnalyseInfo.setPrimaryKey(pk);
// sqlAnalyseInfo.setPrimaryKeyType(type);
// }
// String tableName = table.getName().concat(" ").concat(table.getAlias().getName());
// s2.add(tableName);
// }
//
// String from = s2.stream().collect(Collectors.joining(","));
// querySql.append(select).append(" from ").append(from).append(" where ").append(where.toString());
// log.info("update Sql Analyse =[{}]",querySql.toString());
//
// sqlAnalyseInfo.setSelect(select);
// sqlAnalyseInfo.setQuerySql(querySql.toString());
//
// return sqlAnalyseInfo;
// }
// public static String getNewSql(String sql, SqlAnalyseInfo sqlAnalyseInfo, List<Map<String, Object>> query) {
// String select = sqlAnalyseInfo.getSelect();
// String primaryKey = sqlAnalyseInfo.getPrimaryKey();
// JDBCType primaryKeyType = sqlAnalyseInfo.getPrimaryKeyType();
// sql = sql.concat(" and ").concat(select).concat(" in ( ");
// int size = query.size();
// for (int i = 0; i < query.size(); i++) {
// if(JDBCType.VARCHAR.getName().equals(primaryKeyType.getName())
// ||JDBCType.NVARCHAR.getName().equals(primaryKeyType.getName())
// ||JDBCType.CHAR.getName().equals(primaryKeyType.getName())
//
// ){
// sql = sql.concat("'").concat((String) query.get(i).get(primaryKey)).concat("'");
// }
// else if(JDBCType.INTEGER.getName().equals(primaryKeyType.getName())
// ||JDBCType.SMALLINT.getName().equals(primaryKeyType.getName())
// ||JDBCType.TINYINT.getName().equals(primaryKeyType.getName())
// ){
// sql = sql.concat(Integer.toString((Integer) query.get(i).get(primaryKey)));
// }
// else if(JDBCType.BIGINT.getName().equals(primaryKeyType.getName())){
// sql = sql.concat(Long.toString((Long) query.get(i).get(primaryKey)));
// }else{
// sql = sql.concat("'").concat((String) query.get(i).get(primaryKey)).concat("'");
// }
//
// if(i + 1 < size){
// sql = sql.concat(" , ");
// }
//
// }
// sql = sql.concat(")");
// return sql;
// }
}
package com.codingapi.txlcn.tc.jdbc.sql;
import com.codingapi.txlcn.p6spy.common.StatementInformation;
import com.codingapi.txlcn.tc.jdbc.database.DataBaseContext;
import com.codingapi.txlcn.tc.jdbc.database.TableInfo;
import com.codingapi.txlcn.tc.jdbc.database.TableList;
import com.codingapi.txlcn.tc.jdbc.sql.strategy.MysqlAnalyseContextEnum;
import com.codingapi.txlcn.tc.jdbc.sql.strategy.AnalyseStrategryFactory;
import com.codingapi.txlcn.tc.jdbc.sql.strategy.MysqlAnalyseEnum;
import lombok.SneakyThrows;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.update.Update;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.SQLException;
......@@ -29,12 +31,21 @@ public class MysqlSqlAnalyse implements SqlAnalyse {
@SneakyThrows
@Override
public String analyse(String sql,StatementInformation statementInformation) throws SQLException {
log.debug("mysql analyse:{}",sql);
Connection connection = statementInformation.getConnectionInformation().getConnection();
//todo sql.toUpperCase().substring(0,6) 这样实现有风险
return MysqlAnalyseContextEnum.valueOf(sql.toUpperCase().substring(0,6)).executeStrategry(sql,connection);
log.debug("mysql analyse:{}", sql);
Connection connection = statementInformation.getConnectionInformation().getConnection();
// sql.toUpperCase().substring(0,6) 这样实现有风险
// if else 实现并不是很优雅
CCJSqlParserManager parser = new CCJSqlParserManager();
Statement stmt = parser.parse(new StringReader(sql));
if (stmt instanceof Insert) {
return AnalyseStrategryFactory.getInvokeStrategy(MysqlAnalyseEnum.INSERT.name()).mysqlAnalyseStrategy(sql,connection,stmt);
} else if (stmt instanceof Update) {
return AnalyseStrategryFactory.getInvokeStrategy(MysqlAnalyseEnum.UPDATE.name()).mysqlAnalyseStrategy(sql,connection,stmt);
} else if (stmt instanceof Delete) {
return AnalyseStrategryFactory.getInvokeStrategy(MysqlAnalyseEnum.DELETE.name()).mysqlAnalyseStrategy(sql,connection,stmt);
}
return sql;
}
@Override
public boolean preAnalyse(String sql) {
// SQL类型检查,只有对CUD(CURD)操作做处理
......
package com.codingapi.txlcn.tc.jdbc.sql.strategy;
package com.codingapi.txlcn.tc.jdbc.sql.analyse;
import com.codingapi.txlcn.tc.jdbc.database.SqlAnalyseInfo;
import com.codingapi.txlcn.tc.jdbc.database.TableInfo;
import com.codingapi.txlcn.tc.jdbc.database.TableList;
import com.codingapi.txlcn.tc.utils.ListUtil;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.ExpressionList;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.expression.operators.relational.MultiExpressionList;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Join;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
import java.sql.Connection;
import java.sql.JDBCType;
import java.util.*;
import java.util.stream.Collectors;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
/**
* @author Gz.
* @description: sql分析助手类
* @date 2020-08-17 23:26:01
* todo 指责有点乱,SCP原则,若定位是SqlAnalyseHelper应该划分在com.codingapi.txlcn.tc.jdbc.database包下。
*/
@Slf4j
public class SqlAnalyseHelper {
public class MysqlAnalyse implements SqlDetailAnalyse{
@Override
public boolean singleInsertAnalyse(String sql, Connection connection, Insert statement, ItemsList itemsList, String pk, int pkIndex) throws SQLException {
if (itemsList instanceof ExpressionList) {
ExpressionList expressionList = (ExpressionList) itemsList;
if(pkIndex > -1){
String defaultValue = expressionList.getExpressions().get(pkIndex).toString();
if(!"NULL".equals(defaultValue.toUpperCase())){
return true;
}
expressionList.getExpressions().remove(pkIndex);
statement.getColumns().remove(pkIndex);
}
QueryRunner queryRunner = new QueryRunner();
List<Map<String, Object>> insert = queryRunner.insert(connection, sql, new MapListHandler());
/**
* 检查是否包含主键
* @param table
* @param tableList
* @return
*/
public static boolean checkTableContainsPk(Table table, TableList tableList ) {
TableInfo tableInfo = tableList.getTable(table.getName());
if(tableInfo==null){
return false;
}
if(ListUtil.isNotEmpty(tableInfo.getPrimaryKeys())){
return true;
statement.getColumns().add(new Column(pk));
expressionList.getExpressions().add(new StringValue(insert.get(0).get("GENERATED_KEY").toString()));
}
return false;
}
public static boolean checkWhereContainsPk(Table table,TableList tableList,String whereSql){
TableInfo tableInfo = tableList.getTable(table.getName());
return whereSql.toUpperCase().contains(tableInfo.getPrimaryKeys().get(0).toUpperCase());
}
@Override
public boolean multiInsertAnalyse(String sql, Connection connection, Insert statement, ItemsList itemsList, String pk, int pkIndex) throws SQLException {
if (itemsList instanceof MultiExpressionList) {
MultiExpressionList multiExpressionList = (MultiExpressionList) itemsList;
if(pkIndex > -1){
for (ExpressionList expressionList : multiExpressionList.getExprList()) {
String defaultValue = expressionList.getExpressions().get(pkIndex).toString();
if(!"NULL".equals(defaultValue.toUpperCase())){
return true;
}
expressionList.getExpressions().remove(pkIndex);
statement.getColumns().remove(pkIndex);
}
}
QueryRunner queryRunner = new QueryRunner();
List<Map<String, Object>> insert = queryRunner.insert(connection, sql, new MapListHandler());
/**
* sql分析
* @param tableList
* @param tables
* @param where
* @return
*/
// public static SqlAnalyseInfo sqlAnalyse(TableList tableList, Table tables, Expression where){
// SqlAnalyseInfo sqlAnalyseInfo ;
// if(tables.size() == 1){
// sqlAnalyseInfo = SqlAnalyseHelper.sqlAnalyseSingleTable(tableList, tables,where);
// }else {
// sqlAnalyseInfo = SqlAnalyseHelper.sqlAnalyseMultiTable(tableList, tables,where);
// }
// return SqlAnalyseHelper.sqlAnalyseSingleTable(tableList, tables,where);
// }
statement.getColumns().add(new Column(pk));
for (int i = 0; i < multiExpressionList.getExprList().size(); i++) {
multiExpressionList.getExprList().get(i).getExpressions().add(new StringValue(insert.get(i).get("GENERATED_KEY").toString()));
}
}
return false;
}
public static SqlAnalyseInfo sqlAnalyseSingleTable(TableList tableList, Table table, Expression where, List<Join> joinList) {
@Override
public SqlAnalyseInfo sqlAnalyseSingleTable(TableList tableList, Table table, Expression where, List<Join> joinList) {
SqlAnalyseInfo sqlAnalyseInfo = new SqlAnalyseInfo();
//单表操作
StringBuilder querySql = new StringBuilder("select ");
......@@ -97,39 +108,8 @@ public class SqlAnalyseHelper {
return sqlAnalyseInfo;
}
public static SqlAnalyseInfo sqlAnalyseMultiTable(TableList tableList, Table table, Expression where) {
SqlAnalyseInfo sqlAnalyseInfo = new SqlAnalyseInfo();
StringBuilder querySql = new StringBuilder("select ");
String select = null;
Set<String> s2 = new TreeSet<>();
TableInfo tableInfo = tableList.getTable(table.getName());
if(ListUtil.isNotEmpty(tableInfo.getPrimaryKeys())){
//TODO sql中没有别名的情况
if(StringUtils.isBlank(select)){
select = table.getAlias().getName().concat(".").concat(tableInfo.getPrimaryKeys().get(0));
String pk = tableInfo.getPrimaryKeys().get(0);
JDBCType type = tableInfo.getColumnInfos().stream().filter(m -> m.getName().equals(pk)).findFirst().get().getType();
sqlAnalyseInfo.setPrimaryKey(pk);
sqlAnalyseInfo.setPrimaryKeyType(type);
}
String tableName = table.getName().concat(" ").concat(table.getAlias().getName());
s2.add(tableName);
}
String from = s2.stream().collect(Collectors.joining(","));
querySql.append(select).append(" from ").append(from).append(" where ").append(where.toString());
log.info("update Sql Analyse =[{}]",querySql.toString());
sqlAnalyseInfo.setSelect(select);
sqlAnalyseInfo.setQuerySql(querySql.toString());
return sqlAnalyseInfo;
}
public static String getNewSql(String sql, SqlAnalyseInfo sqlAnalyseInfo, List<Map<String, Object>> query) {
@Override
public String splicingNewSql(String sql, SqlAnalyseInfo sqlAnalyseInfo, List<Map<String, Object>> query) {
String select = sqlAnalyseInfo.getSelect();
String primaryKey = sqlAnalyseInfo.getPrimaryKey();
JDBCType primaryKeyType = sqlAnalyseInfo.getPrimaryKeyType();
......
package com.codingapi.txlcn.tc.jdbc.sql.analyse;
import com.codingapi.txlcn.tc.jdbc.database.SqlAnalyseInfo;
import com.codingapi.txlcn.tc.jdbc.database.TableList;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.Join;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
public interface SqlDetailAnalyse {
/**
* 单表插入分析
* @param sql
* @param connection
* @param statement
* @param itemsList
* @param pk
* @param pkIndex
* @return
* @throws SQLException
*/
boolean singleInsertAnalyse(String sql, Connection connection, Insert statement, ItemsList itemsList, String pk, int pkIndex) throws SQLException;
/**
* 多表插入分析
* @param sql
* @param connection
* @param statement
* @param itemsList
* @param pk
* @param pkIndex
* @return
* @throws SQLException
*/
boolean multiInsertAnalyse(String sql, Connection connection, Insert statement, ItemsList itemsList, String pk, int pkIndex) throws SQLException;
/**
*
* @param tableList
* @param table
* @param where
* @param joinList
* @return
*/
SqlAnalyseInfo sqlAnalyseSingleTable(TableList tableList, Table table, Expression where, List<Join> joinList);
/**
* 拼接新SQL
* @param sql
* @param sqlAnalyseInfo
* @param query
* @return
*/
String splicingNewSql(String sql, SqlAnalyseInfo sqlAnalyseInfo, List<Map<String, Object>> query);
}
package com.codingapi.txlcn.tc.jdbc.sql.strategy;
import com.google.common.collect.Maps;
import org.springframework.context.annotation.Configuration;
import org.springframework.util.StringUtils;
import javax.annotation.PostConstruct;
import java.util.Map;
/**
* @author Gz.
* @description:
* @date 2020-09-02 22:51:37
*/
public class AnalyseStrategryFactory {
private static Map<String, SqlSqlAnalyseHandler> strategyMap = Maps.newHashMap();
public static SqlSqlAnalyseHandler getInvokeStrategy(String name) {
return strategyMap.get(name);
}
public static void register(String name, SqlSqlAnalyseHandler handler) {
if (StringUtils.isEmpty(name) || null == handler) {
return;
}
strategyMap.put(name, handler);
}
}
package com.codingapi.txlcn.tc.jdbc.sql.strategy;
import net.sf.jsqlparser.JSQLParserException;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @author Gz.
* @description: 策略模式聚合类
* @date 2020-08-13 23:08:26
* todo 建议通过策略模式优化该类
*/
public enum MysqlAnalyseContextEnum {
DELETE(){
private MysqlSqlAnalyseStrategry strategry = new MysqlDeleteAnalyseStrategry();
@Override
public String executeStrategry(String sql, Connection connection) throws SQLException, JSQLParserException {
return strategry.mysqlAnalyseStrategry(sql,connection);
}
},
INSERT(){
private MysqlSqlAnalyseStrategry strategry = new MysqlInsertAnalyseStrategry();
@Override
public String executeStrategry(String sql, Connection connection) throws SQLException, JSQLParserException {
return strategry.mysqlAnalyseStrategry(sql,connection);
}
},
UPDATE(){
private MysqlSqlAnalyseStrategry strategry = new MysqlUpdateAnalyseStrategry();
@Override
public String executeStrategry(String sql, Connection connection) throws SQLException, JSQLParserException {
return strategry.mysqlAnalyseStrategry(sql,connection);
}
};
public abstract String executeStrategry(String sql, Connection connection) throws SQLException, JSQLParserException;
}
package com.codingapi.txlcn.tc.jdbc.sql.strategy;
import net.sf.jsqlparser.JSQLParserException;
import java.sql.Connection;
import java.sql.SQLException;
/**
* @author Gz.
* @description: 策略模式聚合类
* @date 2020-08-13 23:08:26
*/
public enum MysqlAnalyseEnum {
DELETE(),
INSERT(),
UPDATE(),;
}
package com.codingapi.txlcn.tc.jdbc.sql.strategy;
import com.codingapi.txlcn.p6spy.common.StatementInformation;
import com.codingapi.txlcn.tc.jdbc.database.DataBaseContext;
import com.codingapi.txlcn.tc.jdbc.database.JdbcAnalyseUtils;
import com.codingapi.txlcn.tc.jdbc.database.SqlAnalyseHelper;
import com.codingapi.txlcn.tc.jdbc.database.TableInfo;
import com.codingapi.txlcn.tc.jdbc.database.TableList;
import com.codingapi.txlcn.tc.jdbc.sql.analyse.SqlDetailAnalyse;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.expression.NullValue;
import net.sf.jsqlparser.expression.StringValue;
import net.sf.jsqlparser.expression.operators.relational.*;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Column;
import net.sf.jsqlparser.expression.operators.relational.ItemsList;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.select.SubSelect;
import net.sf.jsqlparser.statement.update.Update;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.ArrayHandler;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.apache.commons.dbutils.handlers.ScalarHandler;
import org.springframework.stereotype.Component;
import java.math.BigInteger;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
import java.util.stream.IntStream;
/**
......@@ -38,17 +23,23 @@ import java.util.stream.IntStream;
* @date 2020-08-13 23:08:26
*/
@Slf4j
public class MysqlInsertAnalyseStrategry implements MysqlSqlAnalyseStrategry {
@Component
public class MysqlInsertAnalyseStrategy implements SqlSqlAnalyseHandler {
private SqlDetailAnalyse sqlDetailAnalyse;
public MysqlInsertAnalyseStrategy(SqlDetailAnalyse sqlDetailAnalyse){
this.sqlDetailAnalyse = sqlDetailAnalyse;
}
@Override
public String mysqlAnalyseStrategry(String sql, Connection connection) throws SQLException, JSQLParserException {
public String mysqlAnalyseStrategy(String sql, Connection connection,Statement stmt) throws SQLException, JSQLParserException {
boolean defaultAutoCommit = connection.getAutoCommit();
connection.setAutoCommit(false);
String catalog = connection.getCatalog();
DataBaseContext.getInstance().push(catalog, JdbcAnalyseUtils.analyse(connection));
TableList tableList = DataBaseContext.getInstance().get(catalog);
Insert statement = (Insert) CCJSqlParserUtil.parse(sql);
Insert statement = (Insert) stmt;
Table table = statement.getTable();
ItemsList itemsList = statement.getItemsList();
......@@ -69,9 +60,9 @@ public class MysqlInsertAnalyseStrategry implements MysqlSqlAnalyseStrategry {
}
}
if (multiInsertAnalyse(sql, connection, statement, itemsList, pk, pkIndex)) return sql;
if (sqlDetailAnalyse.multiInsertAnalyse(sql, connection, statement, itemsList, pk, pkIndex)) return sql;
if (singleInsertAnalyse(sql, connection, statement, itemsList, pk, pkIndex)) return sql;
if (sqlDetailAnalyse.singleInsertAnalyse(sql, connection, statement, itemsList, pk, pkIndex)) return sql;
connection.rollback();
connection.setAutoCommit(defaultAutoCommit);
......@@ -79,47 +70,8 @@ public class MysqlInsertAnalyseStrategry implements MysqlSqlAnalyseStrategry {
return statement.toString();
}
private boolean singleInsertAnalyse(String sql, Connection connection, Insert statement, ItemsList itemsList, String pk, int pkIndex) throws SQLException {
if (itemsList instanceof ExpressionList) {
ExpressionList expressionList = (ExpressionList) itemsList;
if(pkIndex > -1){
String defaultValue = expressionList.getExpressions().get(pkIndex).toString();
if(!"NULL".equals(defaultValue.toUpperCase())){
return true;
}
expressionList.getExpressions().remove(pkIndex);
statement.getColumns().remove(pkIndex);
}
QueryRunner queryRunner = new QueryRunner();
List<Map<String, Object>> insert = queryRunner.insert(connection, sql, new MapListHandler());
statement.getColumns().add(new Column(pk));
expressionList.getExpressions().add(new StringValue(insert.toString()));
}
return false;
}
private boolean multiInsertAnalyse(String sql, Connection connection, Insert statement, ItemsList itemsList, String pk, int pkIndex) throws SQLException {
if (itemsList instanceof MultiExpressionList) {
MultiExpressionList multiExpressionList = (MultiExpressionList) itemsList;
if(pkIndex > -1){
for (ExpressionList expressionList : multiExpressionList.getExprList()) {
String defaultValue = expressionList.getExpressions().get(pkIndex).toString();
if(!"NULL".equals(defaultValue.toUpperCase())){
return true;
}
expressionList.getExpressions().remove(pkIndex);
statement.getColumns().remove(pkIndex);
}
}
QueryRunner queryRunner = new QueryRunner();
List<Map<String, Object>> insert = queryRunner.insert(connection, sql, new MapListHandler());
statement.getColumns().add(new Column(pk));
for (int i = 0; i < multiExpressionList.getExprList().size(); i++) {
multiExpressionList.getExprList().get(i).getExpressions().add(new StringValue(insert.get(i).get("GENERATED_KEY").toString()));
}
}
return false;
@Override
public void afterPropertiesSet() {
AnalyseStrategryFactory.register(MysqlAnalyseEnum.INSERT.name(), this);
}
}
package com.codingapi.txlcn.tc.jdbc.sql.strategy;
import com.codingapi.txlcn.p6spy.common.StatementInformation;
import com.codingapi.txlcn.tc.jdbc.database.DataBaseContext;
import com.codingapi.txlcn.tc.jdbc.database.JdbcAnalyseUtils;
import com.codingapi.txlcn.tc.jdbc.database.TableInfo;
import com.codingapi.txlcn.tc.jdbc.database.SqlAnalyseHelper;
import com.codingapi.txlcn.tc.jdbc.database.SqlAnalyseInfo;
import com.codingapi.txlcn.tc.jdbc.database.TableList;
import com.codingapi.txlcn.tc.jdbc.sql.analyse.MysqlAnalyse;
import com.codingapi.txlcn.tc.jdbc.sql.analyse.SqlDetailAnalyse;
import com.codingapi.txlcn.tc.utils.ListUtil;
import com.google.common.collect.Lists;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.update.Update;
import org.aopalliance.intercept.MethodInvocation;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import java.sql.JDBCType;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
......@@ -32,18 +29,20 @@ import java.util.Map;
* @date 2020-08-13 23:08:26
*/
@Slf4j
public class MysqlDeleteAnalyseStrategry implements MysqlSqlAnalyseStrategry {
@Component
public class MysqlSqlDeleteAnalyseStrategy implements SqlSqlAnalyseHandler {
private SqlDetailAnalyse sqlDetailAnalyse;
public MysqlSqlDeleteAnalyseStrategy(SqlDetailAnalyse sqlDetailAnalyse){
this.sqlDetailAnalyse = sqlDetailAnalyse;
}
@Override
public String mysqlAnalyseStrategry(String sql, Connection connection) throws SQLException, JSQLParserException {
public String mysqlAnalyseStrategy(String sql, Connection connection,Statement stmt) throws SQLException, JSQLParserException {
String catalog = connection.getCatalog();
/**
* todo JdbcAnalyseUtils.analyse(connection) 不能在此使用
* JdbcAnalyseUtils.analyse(connection) 是系统启动的时候获取数据的,而非在执行sql的时候做数据处理 {@link com.codingapi.txlcn.tc.aspect.TxDataSourceInterceptor#invoke(MethodInvocation)}
*/
DataBaseContext.getInstance().push(catalog, JdbcAnalyseUtils.analyse(connection));
TableList tableList = DataBaseContext.getInstance().get(catalog);
Delete statement = (Delete) CCJSqlParserUtil.parse(sql);
Delete statement = (Delete) stmt;
Table table = statement.getTable();
if(!SqlAnalyseHelper.checkTableContainsPk(table, tableList)){
return sql;
......@@ -51,18 +50,22 @@ public class MysqlDeleteAnalyseStrategry implements MysqlSqlAnalyseStrategry {
if(SqlAnalyseHelper.checkWhereContainsPk(table, tableList,statement.getWhere().toString())){
return sql;
}
SqlAnalyseInfo sqlAnalyseInfo = SqlAnalyseHelper.sqlAnalyseSingleTable(tableList, table, statement.getWhere(),statement.getJoins());
SqlAnalyseInfo sqlAnalyseInfo = sqlDetailAnalyse.sqlAnalyseSingleTable(tableList, table, statement.getWhere(),statement.getJoins());
QueryRunner queryRunner = new QueryRunner();
List<Map<String, Object>> query = queryRunner.query(connection, sqlAnalyseInfo.getQuerySql(), new MapListHandler());
if(ListUtil.isEmpty(query)){
return sql;
}
sql = SqlAnalyseHelper.getNewSql(sql, sqlAnalyseInfo, query);
sql = sqlDetailAnalyse.splicingNewSql(sql, sqlAnalyseInfo, query);
log.info("newSql=[{}]",sql);
return sql;
}
@Override
public void afterPropertiesSet() {
AnalyseStrategryFactory.register(MysqlAnalyseEnum.DELETE.name(), this);
}
}
package com.codingapi.txlcn.tc.jdbc.sql.strategy;
import com.codingapi.txlcn.p6spy.common.StatementInformation;
import com.codingapi.txlcn.tc.jdbc.database.DataBaseContext;
import com.codingapi.txlcn.tc.jdbc.database.JdbcAnalyseUtils;
import com.codingapi.txlcn.tc.jdbc.database.TableInfo;
import com.codingapi.txlcn.tc.jdbc.database.SqlAnalyseHelper;
import com.codingapi.txlcn.tc.jdbc.database.SqlAnalyseInfo;
import com.codingapi.txlcn.tc.jdbc.database.TableList;
import com.codingapi.txlcn.tc.jdbc.sql.analyse.MysqlAnalyse;
import com.codingapi.txlcn.tc.jdbc.sql.analyse.SqlDetailAnalyse;
import com.codingapi.txlcn.tc.utils.ListUtil;
import io.micrometer.core.instrument.util.StringUtils;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.expression.Expression;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.schema.Table;
import net.sf.jsqlparser.statement.Statement;
import net.sf.jsqlparser.statement.update.Update;
import org.apache.commons.dbutils.QueryRunner;
import org.apache.commons.dbutils.handlers.MapListHandler;
import org.springframework.stereotype.Component;
import org.springframework.stereotype.Service;
import java.sql.Connection;
import java.sql.JDBCType;
import java.sql.SQLException;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeSet;
import java.util.stream.Collectors;
/**
......@@ -32,14 +29,20 @@ import java.util.stream.Collectors;
* @date 2020-08-13 23:08:26
*/
@Slf4j
public class MysqlUpdateAnalyseStrategry implements MysqlSqlAnalyseStrategry {
@Component
public class MysqlUpdateAnalyseStrategy implements SqlSqlAnalyseHandler {
private SqlDetailAnalyse sqlDetailAnalyse;
public MysqlUpdateAnalyseStrategy(SqlDetailAnalyse sqlDetailAnalyse){
this.sqlDetailAnalyse = sqlDetailAnalyse;
}
@Override
public String mysqlAnalyseStrategry(String sql, Connection connection) throws SQLException, JSQLParserException {
public String mysqlAnalyseStrategy(String sql, Connection connection , Statement stmt) throws SQLException, JSQLParserException {
String catalog = connection.getCatalog();
DataBaseContext.getInstance().push(catalog, JdbcAnalyseUtils.analyse(connection));
TableList tableList = DataBaseContext.getInstance().get(catalog);
Update statement = (Update) CCJSqlParserUtil.parse(sql);
Update statement = (Update) stmt;
Table table = statement.getTable();
if(!SqlAnalyseHelper.checkTableContainsPk(table, tableList)){
return sql;
......@@ -48,16 +51,20 @@ public class MysqlUpdateAnalyseStrategry implements MysqlSqlAnalyseStrategry {
return sql;
}
//TODO now() 之类的函数有待分析
SqlAnalyseInfo sqlAnalyseInfo = SqlAnalyseHelper.sqlAnalyseSingleTable(tableList, table, statement.getWhere(),statement.getStartJoins());
SqlAnalyseInfo sqlAnalyseInfo = sqlDetailAnalyse.sqlAnalyseSingleTable(tableList, table, statement.getWhere(),statement.getStartJoins());
QueryRunner queryRunner = new QueryRunner();
List<Map<String, Object>> query = queryRunner.query(connection, sqlAnalyseInfo.getQuerySql(), new MapListHandler());
if(ListUtil.isEmpty(query)){
return sql;
}
sql = SqlAnalyseHelper.getNewSql(sql, sqlAnalyseInfo, query);
sql = sqlDetailAnalyse.splicingNewSql(sql, sqlAnalyseInfo, query);
log.info("newSql=[{}]",sql);
return sql;
}
@Override
public void afterPropertiesSet() {
AnalyseStrategryFactory.register(MysqlAnalyseEnum.UPDATE.name(), this);
}
}
......@@ -2,6 +2,8 @@ package com.codingapi.txlcn.tc.jdbc.sql.strategy;
import com.codingapi.txlcn.p6spy.common.StatementInformation;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.statement.Statement;
import org.springframework.beans.factory.InitializingBean;
import java.sql.Connection;
import java.sql.SQLException;
......@@ -11,7 +13,7 @@ import java.sql.SQLException;
* @description: SQL分析则略接口
* @date 2020-08-13 23:08:26
*/
public interface MysqlSqlAnalyseStrategry {
public interface SqlSqlAnalyseHandler extends InitializingBean {
String mysqlAnalyseStrategry(String sql , Connection connection) throws JSQLParserException, SQLException;
String mysqlAnalyseStrategy(String sql,Connection connection,Statement stmt) throws JSQLParserException, SQLException;
}
lcn.datasource.jdbc-url=jdbc:mysql://127.0.0.1:3306/test?serverTimezone=Asia/Shanghai
lcn.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
lcn.datasource.username=root
lcn.datasource.password=
lcn.datasource.password=
\ No newline at end of file
......@@ -13,14 +13,14 @@ import org.springframework.context.annotation.Configuration;
public class DataSourceConfiguration {
@Bean
public HikariDataSource dataSource(LcnTestDataSourceConfig config){
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(config.getJdbcUrl());
dataSource.setUsername(config.getUsername());
dataSource.setPassword(config.getPassword());
dataSource.setDriverClassName(config.getDriverClassName());
return dataSource;
}
public HikariDataSource dataSource(LcnTestDataSourceConfig config){
HikariDataSource dataSource = new HikariDataSource();
dataSource.setJdbcUrl(config.getJdbcUrl());
dataSource.setUsername(config.getUsername());
dataSource.setPassword(config.getPassword());
dataSource.setDriverClassName(config.getDriverClassName());
return dataSource;
}
@Bean
public LcnTestDataSourceConfig lcnTestDataSourceConfig(){
......
......@@ -5,18 +5,27 @@ import com.codingapi.txlcn.tc.jdbc.database.DataBaseContext;
import com.codingapi.txlcn.tc.jdbc.database.JdbcAnalyseUtils;
import com.codingapi.txlcn.tc.jdbc.database.TableInfo;
import com.codingapi.txlcn.tc.jdbc.database.TableList;
import com.codingapi.txlcn.tc.jdbc.sql.strategy.MysqlAnalyseContextEnum;
import com.codingapi.txlcn.tc.jdbc.sql.analyse.MysqlAnalyse;
import com.codingapi.txlcn.tc.jdbc.sql.analyse.SqlDetailAnalyse;
import com.codingapi.txlcn.tc.jdbc.sql.strategy.*;
import lombok.extern.slf4j.Slf4j;
import net.sf.jsqlparser.JSQLParserException;
import net.sf.jsqlparser.parser.CCJSqlParserManager;
import net.sf.jsqlparser.parser.CCJSqlParserUtil;
import net.sf.jsqlparser.statement.*;
import net.sf.jsqlparser.statement.delete.Delete;
import net.sf.jsqlparser.statement.insert.Insert;
import net.sf.jsqlparser.statement.update.Update;
import org.apache.commons.dbutils.DbUtils;
import org.apache.commons.dbutils.QueryRunner;
import org.aspectj.lang.annotation.Before;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import javax.sql.DataSource;
import java.io.StringReader;
import java.sql.Connection;
import java.sql.SQLException;
......@@ -34,6 +43,10 @@ public class MysqlSqlAnalyseTest {
@Autowired
private DataSource dataSource;
@Test
public void analyse() throws SQLException, JSQLParserException {
String sql = "insert into lcn_demo(name,module) values('123','tc-c')";
......@@ -60,7 +73,17 @@ public class MysqlSqlAnalyseTest {
String sql = "DELETE t2,t3 FROM lcn_sql_parse_test2 t2 ,lcn_sql_parse_test3 t3 where t3.job = t2.dept_name AND t2.dept_name = 'test' and t3.name = 'a' ";
sql = "update lcn_sql_parse_test3 t3 ,lcn_sql_parse_test2 t2 set t3.age = 56 ,t2.dept_name = 'dev' where t3.job = t2.dept_name and t2.dept_name = 'test'";
Connection connection = dataSource.getConnection();
MysqlAnalyseContextEnum.valueOf(sql.toUpperCase().substring(0,6)).executeStrategry(sql,connection);
String catalog = connection.getCatalog();
DataBaseContext.getInstance().push(catalog, JdbcAnalyseUtils.analyse(connection));
CCJSqlParserManager parser = new CCJSqlParserManager();
Statement stmt = parser.parse(new StringReader(sql));
if (stmt instanceof Update) {
MysqlUpdateAnalyseStrategy mysqlInsertAnalyseStrategy = new MysqlUpdateAnalyseStrategy(new MysqlAnalyse());
mysqlInsertAnalyseStrategy.mysqlAnalyseStrategy(sql, connection, stmt);
} else if (stmt instanceof Delete) {
MysqlSqlDeleteAnalyseStrategy mysqlInsertAnalyseStrategy = new MysqlSqlDeleteAnalyseStrategy(new MysqlAnalyse());
mysqlInsertAnalyseStrategy.mysqlAnalyseStrategy(sql, connection, stmt);
}
}
@Test
......@@ -69,6 +92,16 @@ public class MysqlSqlAnalyseTest {
sql = "insert into lcn_sql_parse_test1 (id, name, sex, job, home_address, age, dept_id) values (null,'gz','1','test','bjc',12,1)";
sql = "INSERT INTO lcn_sql_parse_test1 (name, sex, job, home_address, age, dept_id) VALUES ('gz', '1', 'test', 'bjc', 12, 4),('gz', '1', 'test', 'bjc', 12, 5),('gz', '1', 'test', 'bjc', 12, 6)";
Connection connection = dataSource.getConnection();
MysqlAnalyseContextEnum.valueOf(sql.toUpperCase().substring(0,6)).executeStrategry(sql,connection);
String catalog = connection.getCatalog();
DataBaseContext.getInstance().push(catalog, JdbcAnalyseUtils.analyse(connection));
CCJSqlParserManager parser = new CCJSqlParserManager();
Statement stmt = parser.parse(new StringReader(sql));
if (stmt instanceof Insert) {
MysqlInsertAnalyseStrategy mysqlInsertAnalyseStrategy = new MysqlInsertAnalyseStrategy(new MysqlAnalyse());
String s = mysqlInsertAnalyseStrategy.mysqlAnalyseStrategy(sql, connection, stmt);
System.out.println(s);
}
}
}
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册