Java源码示例:com.alibaba.druid.sql.dialect.mysql.parser.MySqlStatementParser
示例1
private static String changeCreateTable(SchemaConfig schema,String tableName,String sql) {
if (schema.getTables().containsKey(tableName)) {
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement insertStatement = parser.parseStatement();
if (insertStatement instanceof MySqlCreateTableStatement) {
TableConfig tableConfig = schema.getTables().get(tableName);
AbstractPartitionAlgorithm algorithm = tableConfig.getRule().getRuleAlgorithm();
if (algorithm instanceof SlotFunction) {
SQLColumnDefinition column = new SQLColumnDefinition();
column.setDataType(new SQLCharacterDataType("int"));
column.setName(new SQLIdentifierExpr("_slot"));
column.setComment(new SQLCharExpr("自动迁移算法slot,禁止修改"));
((SQLCreateTableStatement) insertStatement).getTableElementList().add(column);
return insertStatement.toString();
}
}
}
return sql;
}
示例2
private static boolean isSupportSelect(String stmt) {
SQLStatementParser parser = new MySqlStatementParser(stmt);
SQLStatement statement = parser.parseStatement();
if (!(statement instanceof SQLSelectStatement)) {
return false;
}
SQLSelectQuery sqlSelectQuery = ((SQLSelectStatement) statement).getSelect().getQuery();
if (!(sqlSelectQuery instanceof MySqlSelectQueryBlock)) {
return false;
}
MySqlSelectQueryBlock selectQueryBlock = (MySqlSelectQueryBlock) sqlSelectQuery;
SQLTableSource mysqlFrom = selectQueryBlock.getFrom();
if (mysqlFrom != null) {
return false;
}
for (SQLSelectItem item : selectQueryBlock.getSelectList()) {
SQLExpr selectItem = item.getExpr();
if (!isVariantRef(selectItem)) {
return false;
}
}
return true;
}
示例3
private static boolean isInsertSeq(ServerConnection c, String stmt, SchemaConfig schema) throws SQLException {
SQLStatementParser parser = new MySqlStatementParser(stmt);
MySqlInsertStatement statement = (MySqlInsertStatement) parser.parseStatement();
String schemaName = schema == null ? null : schema.getName();
SQLExprTableSource tableSource = statement.getTableSource();
SchemaUtil.SchemaInfo schemaInfo = SchemaUtil.getSchemaInfo(c.getUser(), schemaName, tableSource);
String tableName = schemaInfo.getTable();
schema = schemaInfo.getSchemaConfig();
TableConfig tableConfig = schema.getTables().get(tableName);
if (tableConfig == null) {
return false;
} else if (tableConfig.isAutoIncrement()) {
return true;
}
return false;
}
示例4
@Override
public SQLStatement parserSQL(String originSql) throws SQLSyntaxErrorException {
SQLStatementParser parser = new MySqlStatementParser(originSql);
/**
* thrown SQL SyntaxError if parser error
*/
try {
List<SQLStatement> list = parser.parseStatementList();
if (list.size() > 1) {
throw new SQLSyntaxErrorException("MultiQueries is not supported,use single query instead ");
}
return list.get(0);
} catch (Exception t) {
LOGGER.info("routeNormalSqlWithAST", t);
if (t.getMessage() != null) {
throw new SQLSyntaxErrorException(t.getMessage());
} else {
throw new SQLSyntaxErrorException(t);
}
}
}
示例5
public void test(String sql) throws Exception {
MySqlStatementParser parser = new MySqlStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SqlVisitor visitor = new SqlVisitor(null);
statementList.get(0).accept(visitor);
System.out.println();
System.out.println(sql);
System.out.println("Tables : " + visitor.getTables());
System.out.println("fields : " + visitor.getColumns());
System.out.println("alias : " + visitor.getAliasMap());
System.out.println("conditions : " + visitor.getConditions());
System.out.println("columns : " + visitor.getColumns());
}
示例6
private List<List<TableStat.Condition>> test(String sql){
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement statemen = parser.parseStatement();
List<Object> parameters = new ArrayList<Object>();
parameters.add(10);
OrVisitor visitor = new OrVisitor();
OrVisitor.OrEntity orEntity = new OrVisitor.OrEntity(visitor, statemen);
List<List<TableStat.Condition>> conditions = orEntity.getOrConditions();
System.out.println();
System.out.println(sql);
System.out.println(conditions);
System.out.println();
return conditions;
}
示例7
public void test(String sql, String logicName, String targetName){
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement statement = parser.parseStatement();
ReplaceTableNameVisitor replaceVisitor = new ReplaceTableNameVisitor(logicName, targetName);
StringBuilder out = new StringBuilder();
MySqlOutputVisitor outPutVisitor = new MySqlOutputVisitor(out);
// 替换表名
statement.accept(replaceVisitor);
// 输出sql
statement.accept(outPutVisitor);
System.out.println();
System.out.println(sql);
System.out.println(out.toString());
// 输出sql后要还原statement以便下次替换表名
replaceVisitor.reset();
}
示例8
@Override
public String getCountSql(String sql) {
SQLStatementParser parser = new MySqlStatementParser(sql);
List<SQLStatement> stmtList = parser.parseStatementList();
// 将AST通过visitor输出
StringBuilder out = new StringBuilder();
MysqlCountOutputVisitor visitor = new MysqlCountOutputVisitor(out);
for (SQLStatement stmt : stmtList) {
if (stmt instanceof SQLSelectStatement) {
stmt.accept(visitor);
out.append(";");
}
}
return out.toString();
}
示例9
protected CommitInfo parse(StatementAdapter statementAdapter) throws SQLException {
CommitInfo commitInfo = new CommitInfo();
String sql = statementAdapter.getSql();
T sqlParseStatement = (T)new MySqlStatementParser(sql).parseStatement();
commitInfo.setSqlType(getSqlType());
commitInfo.setWhere(getWhere(sqlParseStatement));
commitInfo.setSql(sql);
if (statementAdapter instanceof PreparedStatementAdapter) {
PreparedStatementAdapter preparedStatementAdapter = (PreparedStatementAdapter)statementAdapter;
commitInfo.setSqlParams(preparedStatementAdapter.getParamsList());
commitInfo.setWhereParams(getWhereParams(preparedStatementAdapter.getParamsList(), sqlParseStatement));
}
TableMetaInfo tableMetaInfo =
TableMetaUtils.getTableMetaInfo(statementAdapter.getConnection(), getTableName(sqlParseStatement));
if (CollectionUtils.isEmpty(tableMetaInfo.getPrimaryKeyName())) {
return null;
}
TableDataInfo originValue =
getOriginValue(commitInfo.getWhereParams(), sqlParseStatement, statementAdapter, tableMetaInfo);
commitInfo.setOriginalValue(originValue);
TableDataInfo presentValue =
getPresentValue(commitInfo.getSqlParams(), sqlParseStatement, statementAdapter, tableMetaInfo);
commitInfo.setPresentValue(presentValue);
return commitInfo;
}
示例10
@Override
protected boolean canRollback(CommitInfo commitInfo, Connection connection) throws SQLException {
String sql = commitInfo.getSql();
SQLUpdateStatement sqlParseStatement = (SQLUpdateStatement)new MySqlStatementParser(sql).parseStatement();
TableMetaInfo tableMetaInfo =
TableMetaUtils.getTableMetaInfo(connection, sqlParseStatement.getTableName().getSimpleName());
TableDataInfo dbValue = UpdateParser.getInstance().getOriginValue(commitInfo.getWhereParams(),
sqlParseStatement, connection, tableMetaInfo);
if (commitInfo.getOriginalValue().getLine().size() == 0) {
return false;
}
for (TxcLine txcLine : dbValue.getLine()) {
txcLine.setPrimaryKeyValues(commitInfo.getPresentValue().getLine().get(0).getPrimaryKeyValues());
boolean diff = DiffUtils.diff(commitInfo.getPresentValue().getLine().get(0), txcLine);
if (!diff) {
try {
logger.error("data conflict, before:{},after:{}",
DiffUtils.getObjectMapper().writeValueAsString(commitInfo.getPresentValue().getLine().get(0)),
DiffUtils.getObjectMapper().writeValueAsString(txcLine));
} catch (Exception e) {
logger.error(e.getMessage(), e);
}
return false;
}
}
return true;
}
示例11
@Override
public void prepareCompensationAfterExecuting(PreparedStatement delegate, String executeSql, Map<String, Object> standbyParams) throws SQLException {
String globalTxId = CurrentThreadOmegaContext.getGlobalTxIdFromCurThread();
if (globalTxId == null || globalTxId.length() == 0) {
return;
}
String localTxId = CurrentThreadOmegaContext.getLocalTxIdFromCurThread();
if (localTxId == null || localTxId.length() == 0) {
return;
}
// To parse SQL by SQLParser tools from Druid.
MySqlStatementParser parser = new MySqlStatementParser(executeSql);
SQLStatement sqlStatement = parser.parseStatement();
if (sqlStatement instanceof MySqlSelectIntoStatement) {
return;
}
if (standbyParams == null) {
standbyParams = new HashMap<>(8);
}
String server = CurrentThreadOmegaContext.getServiceNameFromCurThread();
// To set a relationship between localTxId and datSourceInfo, in order to determine to use the relative dataSource for localTxId when it need be compensated.
DatabaseMetaData databaseMetaData = delegate.getConnection().getMetaData();
String dburl = databaseMetaData.getURL(), dbusername = databaseMetaData.getUserName(), dbdrivername = databaseMetaData.getDriverName();
DataSourceMappingCache.putLocalTxIdAndDataSourceInfo(localTxId, dburl, dbusername, dbdrivername);
// To construct kafka message.
standbyParams.put("dbdrivername", dbdrivername);
standbyParams.put("dburl", dburl);
standbyParams.put("dbusername", dbusername);
if (sqlStatement instanceof MySqlInsertStatement) {
AutoCompensateInsertHandler.newInstance().prepareCompensationAfterInserting(delegate, sqlStatement, executeSql, globalTxId, localTxId, server, standbyParams);
} else if (sqlStatement instanceof MySqlUpdateStatement) {
AutoCompensateUpdateHandler.newInstance().prepareCompensationAfterUpdating(delegate, sqlStatement, executeSql, globalTxId, localTxId, server, standbyParams);
}
}
示例12
public static boolean isInsertSql(String sql){
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement statement = parser.parseStatement();
if(statement instanceof SQLInsertStatement){
SQLInsertStatement insert =(SQLInsertStatement) statement;
tableName = insert.getTableName().toString();
return true;
}else if(statement instanceof SQLUpdateStatement){
SQLUpdateStatement update =(SQLUpdateStatement) statement;
tableName = update.getTableName().toString();
return true;
}
return false;
}
示例13
public void route(SystemConfig sysConfig, SchemaConfig schema,int sqlType, String realSQL, String charset, ServerConnection sc, LayerCachePool cachePool) {
int rs = ServerParse.parse(realSQL);
this.sqltype = rs & 0xff;
this.sysConfig=sysConfig;
this.schema=schema;
this.charset=charset;
this.sc=sc;
this.cachePool=cachePool;
try {
// RouteStrategy routes=RouteStrategyFactory.getRouteStrategy();
// rrs =RouteStrategyFactory.getRouteStrategy().route(sysConfig, schema, sqlType2, realSQL,charset, sc, cachePool);
MySqlStatementParser parser = new MySqlStatementParser(realSQL);
SQLStatement statement = parser.parseStatement();
if(statement instanceof SQLSelectStatement) {
SQLSelectStatement st=(SQLSelectStatement)statement;
SQLSelectQuery sqlSelectQuery =st.getSelect().getQuery();
if(sqlSelectQuery instanceof MySqlSelectQueryBlock) {
MySqlSelectQueryBlock mysqlSelectQuery = (MySqlSelectQueryBlock)sqlSelectQuery;
joinParser=new JoinParser(mysqlSelectQuery,realSQL);
joinParser.parser();
}
}
/*
if (routes instanceof DruidMysqlRouteStrategy) {
SQLSelectStatement st=((DruidMysqlRouteStrategy) routes).getSQLStatement();
SQLSelectQuery sqlSelectQuery =st.getSelect().getQuery();
if(sqlSelectQuery instanceof MySqlSelectQueryBlock) {
MySqlSelectQueryBlock mysqlSelectQuery = (MySqlSelectQueryBlock)st.getSelect().getQuery();
joinParser=new JoinParser(mysqlSelectQuery,realSQL);
joinParser.parser();
}
}
*/
} catch (Exception e) {
}
}
示例14
private static boolean isMycatSeq(String stmt, SchemaConfig schema)
{
if(pattern.matcher(stmt).find()) {
return true;
}
SQLStatementParser parser =new MySqlStatementParser(stmt);
MySqlInsertStatement statement = (MySqlInsertStatement) parser.parseStatement();
String tableName= statement.getTableName().getSimpleName();
TableConfig tableConfig= schema.getTables().get(tableName.toUpperCase());
if(tableConfig==null) {
return false;
}
if(tableConfig.isAutoIncrement())
{
boolean isHasIdInSql=false;
String primaryKey = tableConfig.getPrimaryKey();
List<SQLExpr> columns = statement.getColumns();
for (SQLExpr column : columns)
{
String columnName = column.toString();
if(primaryKey.equalsIgnoreCase(columnName))
{
isHasIdInSql = true;
break;
}
}
if(!isHasIdInSql) {
return true;
}
}
return false;
}
示例15
/**
* 解析 SQL 获取指定表及条件列的值
*
* @param sql
* @param tableName
* @param colnumName
* @return
*/
public List<Object> parseConditionValues(String sql, String tableName, String colnumName) {
List<Object> values = null;
if ( sql != null && tableName != null && columnName != null ) {
values = new ArrayList<Object>();
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatement();
MySqlSchemaStatVisitor visitor = new MySqlSchemaStatVisitor();
stmt.accept(visitor);
String currentTable = visitor.getCurrentTable();
if ( tableName.equalsIgnoreCase( currentTable ) ) {
List<Condition> conditions = visitor.getConditions();
for(Condition condition: conditions) {
String ccN = condition.getColumn().getName();
ccN = fixName(ccN);
if ( colnumName.equalsIgnoreCase( ccN ) ) {
List<Object> ccVL = condition.getValues();
values.addAll( ccVL );
}
}
}
}
return values;
}
示例16
public void throwExceptionParse(String sql, boolean throwException) throws NoSuchMethodException {
MySqlStatementParser parser = new MySqlStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement sqlStatement = statementList.get(0);
MySqlUpdateStatement update = (MySqlUpdateStatement) sqlStatement;
SchemaConfig schemaConfig = mock(SchemaConfig.class);
Map<String, TableConfig> tables = mock(Map.class);
TableConfig tableConfig = mock(TableConfig.class);
String tableName = "hotnews";
when((schemaConfig).getTables()).thenReturn(tables);
when(tables.get(tableName)).thenReturn(tableConfig);
when(tableConfig.getParentTC()).thenReturn(null);
RouteResultset routeResultset = new RouteResultset(sql, 11);
Class c = DruidUpdateParser.class;
Method method = c.getDeclaredMethod("confirmShardColumnNotUpdated", new Class[]{SQLUpdateStatement.class, SchemaConfig.class, String.class, String.class, String.class, RouteResultset.class});
method.setAccessible(true);
try {
method.invoke(c.newInstance(), update, schemaConfig, tableName, "ID", "", routeResultset);
if (throwException) {
System.out.println("未抛异常,解析通过则不对!");
Assert.assertTrue(false);
} else {
System.out.println("未抛异常,解析通过,此情况分片字段可能在update语句中但是实际不会被更新");
Assert.assertTrue(true);
}
} catch (Exception e) {
if (throwException) {
System.out.println(e.getCause().getClass());
Assert.assertTrue(e.getCause() instanceof SQLNonTransientException);
System.out.println("抛异常原因为SQLNonTransientException则正确");
} else {
System.out.println("抛异常,需要检查");
Assert.assertTrue(false);
}
}
}
示例17
private boolean isInsertHasSlot(String sql)
{
MySqlStatementParser parser = new MySqlStatementParser(sql);
MySqlInsertStatement insertStatement= (MySqlInsertStatement)parser.parseStatement();
List<SQLExpr> cc= insertStatement.getColumns();
for (SQLExpr sqlExpr : cc) {
SQLIdentifierExpr c= (SQLIdentifierExpr) sqlExpr;
if("_slot".equalsIgnoreCase(c.getName()) &&cc.size()==insertStatement.getValues().getValues().size()) return true;
}
return false;
}
示例18
public void testModifySQLLimit() throws Exception {
final SchemaConfig schema = schemaMap.get("TESTDB");
String sql = null;
RouteResultset rrs = null;
//SQL span multi datanode
sql = "select * from orders limit 2,3";
rrs = routeStrategy.route(new SystemConfig(), schema, ServerParse.SELECT, sql, null, null, cachePool);
Assert.assertEquals(true, rrs.isCacheAble());
Map<String, RouteResultsetNode> nodeMap = getNodeMap(rrs, 2);
NodeNameAsserter nameAsserter = new NodeNameAsserter("dn2",
"dn1");
nameAsserter.assertRouteNodeNames(nodeMap.keySet());
Assert.assertEquals(3, rrs.getLimitSize());
MySqlStatementParser parser = new MySqlStatementParser("SELECT * FROM orders LIMIT 0,5");
SQLStatement statement = parser.parseStatement();
Assert.assertEquals(statement.toString(), rrs.getNodes()[0].getStatement());
//SQL not span multi datanode
sql = "select * from customer where id=10000 limit 2,3";
rrs = routeStrategy.route(new SystemConfig(), schema, ServerParse.SELECT, sql, null, null, cachePool);
Assert.assertEquals(true, rrs.isCacheAble());
nodeMap = getNodeMap(rrs, 1);
nameAsserter = new NodeNameAsserter("dn1");
nameAsserter.assertRouteNodeNames(nodeMap.keySet());
Assert.assertEquals(3, rrs.getLimitSize());
Assert.assertEquals("select * from customer where id=10000 limit 2,3", rrs.getNodes()[0].getStatement());
}
示例19
private static SQLStatement parseSQL(String stmt) throws SQLSyntaxErrorException {
SQLStatementParser parser = new MySqlStatementParser(stmt);
try {
return parser.parseStatement();
} catch (Exception t) {
if (t.getMessage() != null) {
throw new SQLSyntaxErrorException(t.getMessage());
} else {
throw new SQLSyntaxErrorException(t);
}
}
}
示例20
/**
* parseConditionValues
*
* @param sql
* @param table
* @param column
* @return
*/
public List<Object> parseConditionValues(String sql, String table, String column) {
List<Object> values = null;
if (sql != null && table != null && QueryConditionAnalyzer.this.columnName != null) {
values = new ArrayList<>();
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatement();
ServerSchemaStatVisitor visitor = new ServerSchemaStatVisitor();
stmt.accept(visitor);
String currentTable = visitor.getCurrentTable();
if (table.equalsIgnoreCase(currentTable)) {
List<Condition> conditions = visitor.getConditions();
for (Condition condition : conditions) {
String ccN = condition.getColumn().getName();
ccN = fixName(ccN);
if (column.equalsIgnoreCase(ccN)) {
List<Object> ccVL = condition.getValues();
values.addAll(ccVL);
}
}
}
}
return values;
}
示例21
public void throwExceptionParse(String sql, boolean throwException) throws NoSuchMethodException {
MySqlStatementParser parser = new MySqlStatementParser(sql);
List<SQLStatement> statementList = parser.parseStatementList();
SQLStatement sqlStatement = statementList.get(0);
MySqlUpdateStatement update = (MySqlUpdateStatement) sqlStatement;
SchemaConfig schemaConfig = mock(SchemaConfig.class);
Map<String, TableConfig> tables = mock(Map.class);
TableConfig tableConfig = mock(TableConfig.class);
String tableName = "hotnews";
when((schemaConfig).getTables()).thenReturn(tables);
when(tables.get(tableName)).thenReturn(tableConfig);
when(tableConfig.getParentTC()).thenReturn(null);
RouteResultset routeResultset = new RouteResultset(sql, 11);
Class c = DruidUpdateParser.class;
Method method = c.getDeclaredMethod("confirmShardColumnNotUpdated", new Class[]{SQLUpdateStatement.class, SchemaConfig.class, String.class, String.class, String.class, RouteResultset.class});
method.setAccessible(true);
try {
method.invoke(c.newInstance(), update, schemaConfig, tableName, "ID", "", routeResultset);
if (throwException) {
System.out.println("Not passed without exception is not correct");
Assert.assertTrue(false);
} else {
System.out.println("Passed without exception. Maybe the partition key exists in update statement,but not update in fact");
Assert.assertTrue(true);
}
} catch (Exception e) {
if (throwException) {
System.out.println(e.getCause().getClass());
Assert.assertTrue(e.getCause() instanceof SQLNonTransientException);
System.out.println("SQLNonTransientException is expected");
} else {
System.out.println("need checked");
Assert.assertTrue(false);
}
}
}
示例22
private List<WhereUnit> getAllWhereUnit(String sql) {
SQLStatementParser parser = new MySqlStatementParser(sql);
ServerSchemaStatVisitor visitor;
//throw exception
try {
SQLStatement statement = parser.parseStatement();
visitor = new ServerSchemaStatVisitor();
statement.accept(visitor);
return visitor.getAllWhereUnit();
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
示例23
private PlanNode getPlanNode(String sql) {
SQLStatementParser parser = new MySqlStatementParser(sql);
SQLSelectStatement ast = (SQLSelectStatement) parser.parseStatement();
MySQLPlanNodeVisitor visitor = new MySQLPlanNodeVisitor("TESTDB", 33, null, true, null);
visitor.visit(ast);
return visitor.getTableNode();
}
示例24
private boolean isInsertHasSlot(String sql) {
MySqlStatementParser parser = new MySqlStatementParser(sql);
MySqlInsertStatement insertStatement = (MySqlInsertStatement) parser.parseStatement();
List<SQLExpr> cc = insertStatement.getColumns();
for (SQLExpr sqlExpr : cc) {
SQLIdentifierExpr c = (SQLIdentifierExpr) sqlExpr;
if ("_slot".equalsIgnoreCase(c.getName()) && cc.size() == insertStatement.getValues().getValues().size())
return true;
}
return false;
}
示例25
public void testModifySQLLimit() throws Exception {
final SchemaConfig schema = schemaMap.get("TESTDB");
String sql = null;
RouteResultset rrs = null;
//SQL span multi datanode
sql = "select * from orders limit 2,3";
rrs = routeStrategy.route(schema, ServerParse.SELECT, sql, null, cachePool);
Assert.assertEquals(true, rrs.isSqlRouteCacheAble());
Map<String, RouteResultsetNode> nodeMap = getNodeMap(rrs, 2);
NodeNameAsserter nameAsserter = new NodeNameAsserter("dn2",
"dn1");
nameAsserter.assertRouteNodeNames(nodeMap.keySet());
Assert.assertEquals(3, rrs.getLimitSize());
MySqlStatementParser parser = new MySqlStatementParser("SELECT * FROM orders LIMIT 0,5");
SQLStatement statement = parser.parseStatement();
Assert.assertEquals(statement.toString(), rrs.getNodes()[0].getStatement());
//SQL not span multi datanode
sql = "select * from customer where id=10000 limit 2,3";
rrs = routeStrategy.route(schema, ServerParse.SELECT, sql, null, cachePool);
Assert.assertEquals(true, rrs.isSqlRouteCacheAble());
nodeMap = getNodeMap(rrs, 1);
nameAsserter = new NodeNameAsserter("dn1");
nameAsserter.assertRouteNodeNames(nodeMap.keySet());
Assert.assertEquals(3, rrs.getLimitSize());
Assert.assertEquals("select * from customer where id=10000 limit 2,3", rrs.getNodes()[0].getStatement());
}
示例26
@Override
public void init(String sql, List<Object> parameters) {
this.parser = new MySqlStatementParser(sql);
this.visitor = new SqlVisitor(parameters);
this.parameters = parameters;
this.sql = sql;
}
示例27
public String rewrite(String sql, List<ParamContext> countParams) {
MySqlStatementParser parser = new MySqlStatementParser(sql);
SQLStatement stmt = parser.parseStatement();
RewriteSqlToCountSqlVisitor visitor = new RewriteSqlToCountSqlVisitor(countParams);
stmt.accept(visitor);
return stmt.toString();
}
示例28
public static SQLType parse(StatementAdapter txcStatement) throws SQLException {
long start = System.currentTimeMillis();
SQLType sqlType = SQLType.SELECT;
try {
DbRuntimeContext txcRuntimeContext = txcStatement.getConnection().getConnectionRuntimeContext();
String sql = txcStatement.getSql();
SQLStatement sqlParseStatement = new MySqlStatementParser(sql).parseStatement();
CommitInfo commitInfo = null;
if (sqlParseStatement instanceof MySqlUpdateStatement) {
commitInfo = UpdateParser.getInstance().parse(txcStatement);
sqlType = SQLType.UPDATE;
if (!Objects.isNull(commitInfo)&&!CollectionUtils.isEmpty(commitInfo.getOriginalValue().getLine())) {
txcRuntimeContext.getInfo().add(commitInfo);
fillDbMetaAndLockRow(txcStatement, commitInfo);
}
} else if (sqlParseStatement instanceof MySqlInsertStatement) {
sqlType = SQLType.INSERT;
} else if (sqlParseStatement instanceof MySqlDeleteStatement) {
commitInfo = DeleteParser.getInstance().parse(txcStatement);
sqlType = SQLType.DELETE;
if (!Objects.isNull(commitInfo) && !CollectionUtils.isEmpty(commitInfo.getOriginalValue().getLine())) {
txcRuntimeContext.getInfo().add(commitInfo);
fillDbMetaAndLockRow(txcStatement, commitInfo);
}
} else if (sqlParseStatement instanceof SQLSelectStatement) {
SQLSelectQueryBlock selectQueryBlock =
((SQLSelectStatement)sqlParseStatement).getSelect().getQueryBlock();
if (selectQueryBlock.getFrom() != null) {
SelectParser.getInstance().parse(txcStatement);
sqlType = SQLType.SELECT;
}
}
} catch (Exception e) {
logger.error("parse sql error", e);
if (e instanceof SQLException || e instanceof RuntimeException) {
throw e;
} else {
throw new SQLException(e);
}
} finally {
long cost = System.currentTimeMillis() - start;
if (sqlType != SQLType.SELECT || cost > 50) {
logger.debug("parser sql:{}, cost:{}ms", txcStatement.getSql(), cost);
}
}
return sqlType;
}
示例29
private boolean checkDataConsistency(String compensateSql, String globalTxId, String localTxId) throws NoSuchAlgorithmException, IOException {
MySqlStatementParser parser = new MySqlStatementParser(compensateSql);
SQLStatement sqlStatement = parser.parseStatement();
if (sqlStatement instanceof MySqlUpdateStatement || sqlStatement instanceof MySqlInsertStatement) {
MySqlUpdateStatement deleteStatement = (MySqlUpdateStatement) sqlStatement;
String tableName = deleteStatement.getTableName().toString().toLowerCase();
String schema = TxleConstants.APP_NAME;
String txleBackupTableName = "backup_new_" + tableName;
int backupDataCount = autoCompensateDao.executeQueryCount("SELECT count(*) FROM " + schema + "." + txleBackupTableName + " T WHERE T.globalTxId = ? AND T.localTxId = ? FOR UPDATE", globalTxId, localTxId);
if (backupDataCount > 0) {
String pkName = this.parsePrimaryKeyColumnName(tableName);
int currentDataCount = autoCompensateDao.executeQueryCount("SELECT count(*) FROM " + tableName + " T WHERE T.id IN (SELECT T1.id FROM " + schema + "." + txleBackupTableName + " T1 WHERE T1.globalTxId = ? AND T1.localTxId = ?)", globalTxId, localTxId);
// in case of updating many times for some same data, to delete the previous changes, so it only has one backup for any data.
if (backupDataCount == currentDataCount) {
List<Map<String, Object>> columnList = autoCompensateDao.executeQuery(
"SELECT GROUP_CONCAT(COLUMN_NAME) COLUMN_NAMES FROM INFORMATION_SCHEMA.COLUMNS WHERE TABLE_SCHEMA = '" + schema + "' AND TABLE_NAME = '" + txleBackupTableName + "' AND COLUMN_NAME NOT IN ('globalTxId', 'localTxId')");
if (columnList != null && !columnList.isEmpty()) {
StringBuilder columnNames = new StringBuilder();
String[] columnArr = columnList.get(0).get("COLUMN_NAMES").toString().split(",");
for (String column : columnArr) {
if (columnNames.length() == 0) {
columnNames.append("T." + column);
} else {
columnNames.append(",T." + column);
}
}
String backupDataSql = "SELECT " + columnNames + " FROM " + schema + "." + txleBackupTableName + " T WHERE T.globalTxId = '" + globalTxId + "' AND T.localTxId = '" + localTxId + "'";
String currentDataSql = "SELECT " + columnNames + " FROM " + tableName + " T, " + schema + "." + txleBackupTableName + " T1 WHERE T." + pkName + " = T1." + pkName + " AND T1.globalTxId = '" + globalTxId + "' AND T1.localTxId = '" + localTxId + "'";
String backupDataMD5 = getMD5Digest(backupDataSql, backupDataCount);
String currentDataMD5 = getMD5Digest(currentDataSql, currentDataCount);
if (backupDataMD5.equals(currentDataMD5)) {
return true;
}
}
}
}
throw new RuntimeException("That's not consistent between backup data and current data.");
}
return true;
}
示例30
@Override
public void prepareCompensationBeforeExecuting(PreparedStatement delegate, String executeSql, Map<String, Object> standbyParams) throws SQLException {
String globalTxId = CurrentThreadOmegaContext.getGlobalTxIdFromCurThread();
if (globalTxId == null || globalTxId.length() == 0) {
return;
}
String localTxId = CurrentThreadOmegaContext.getLocalTxIdFromCurThread();
if (localTxId == null || localTxId.length() == 0) {
return;
}
// To parse SQL by SQLParser tools from Druid.
MySqlStatementParser parser = new MySqlStatementParser(executeSql);
SQLStatement sqlStatement = parser.parseStatement();
if (sqlStatement instanceof MySqlSelectIntoStatement) {
return;
}
if (standbyParams == null) {
standbyParams = new HashMap<>(8);
}
String server = CurrentThreadOmegaContext.getServiceNameFromCurThread();
// To set a relationship between localTxId and datSourceInfo, in order to determine to use the relative dataSource for localTxId when it need be compensated.
DatabaseMetaData databaseMetaData = delegate.getConnection().getMetaData();
String dburl = databaseMetaData.getURL(), dbusername = databaseMetaData.getUserName(), dbdrivername = databaseMetaData.getDriverName();
DataSourceMappingCache.putLocalTxIdAndDataSourceInfo(localTxId, dburl, dbusername, dbdrivername);
// To construct kafka message.
standbyParams.put("dbdrivername", dbdrivername);
standbyParams.put("dburl", dburl);
standbyParams.put("dbusername", dbusername);
if (sqlStatement instanceof MySqlInsertStatement) {
return;
} else if (sqlStatement instanceof MySqlUpdateStatement) {
AutoCompensateUpdateHandler.newInstance().prepareCompensationBeforeUpdating(delegate, sqlStatement, executeSql, globalTxId, localTxId, server, standbyParams);
} else if (sqlStatement instanceof MySqlDeleteStatement) {
AutoCompensateDeleteHandler.newInstance().prepareCompensationBeforeDeleting(delegate, sqlStatement, executeSql, globalTxId, localTxId, server, standbyParams);
} else {
standbyParams.clear();
// Default is closed, means that just does record, if it's open, then program will throw an exception about current special SQL, just for auto-compensation.
boolean checkSpecialSql = TxleStaticConfig.getBooleanConfig("txle.transaction.auto-compensation.check-special-sql", false);
if (checkSpecialSql) {
throw new SQLException(TxleConstants.logErrorPrefixWithTime() + "Do not support sql [" + executeSql + "] to auto-compensation.");
} else {
LOG.debug(TxleConstants.logDebugPrefixWithTime() + "Do not support sql [{}] to auto-compensation, but it has been executed due to the switch 'checkSpecialSql' is closed.", executeSql);
}
}
}