diff --git a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java index e72d649710..a11db0575b 100644 --- a/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java +++ b/src/main/java/com/alibaba/druid/filter/stat/StatFilter.java @@ -436,6 +436,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { sqlStat.decrementRunningCount(); sqlStat.addExecuteTime(nanoSpan); + statement.setLastExecuteTimeNano(nanoSpan); long millis = nanoSpan / (1000 * 1000); if (millis >= slowSqlMillis) { @@ -530,6 +531,7 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { if (sqlStat != null) { sqlStat.error(error); sqlStat.addExecuteTime(nanoSpan); + statement.setLastExecuteTimeNano(nanoSpan); } super.statement_executeErrorAfter(statement, sql, error); @@ -560,7 +562,8 @@ public class StatFilter extends FilterEventAdapter implements StatFilterMBean { JdbcSqlStat sqlStat = resultSet.getSqlStat(); if (sqlStat != null) { sqlStat.addFetchRowCount(fetchCount); - sqlStat.addResultSetHoldTimeNano(nanoSpan); + long stmtExecuteNano = resultSet.getStatementProxy().getLastExecuteTimeNano(); + sqlStat.addResultSetHoldTimeNano(stmtExecuteNano, nanoSpan); } } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxy.java b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxy.java index 62e22e8683..3e8e517707 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxy.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxy.java @@ -40,5 +40,8 @@ public interface StatementProxy extends Statement, WrapperProxy { String getLastExecuteSql(); + long getLastExecuteTimeNano(); + void setLastExecuteTimeNano(long nano); + Map getParameters(); } diff --git a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java index 667be82cc1..afb6625933 100644 --- a/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java +++ b/src/main/java/com/alibaba/druid/proxy/jdbc/StatementProxyImpl.java @@ -38,13 +38,9 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro private final ConnectionProxy connection; private final Statement statement; - // 通过CounterEventListener来维护 - protected long lastExecuteStartTime; - protected long lastExecuteStartNano; - protected long lastExecuteCompleteTime; - protected long lastExecuteCompleteNano; protected String lastExecuteSql; - protected JdbcSqlStat sqlStat; + private long lastExecuteTimeNano; + protected JdbcSqlStat sqlStat; protected ArrayList batchSqlList; @@ -341,4 +337,11 @@ public class StatementProxyImpl extends WrapperProxyImpl implements StatementPro this.sqlStat = sqlStat; } + public long getLastExecuteTimeNano() { + return lastExecuteTimeNano; + } + + public void setLastExecuteTimeNano(long lastExecuteTimeNano) { + this.lastExecuteTimeNano = lastExecuteTimeNano; + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java index 20783f6c64..214daa10c0 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/parser/MySqlStatementParser.java @@ -31,6 +31,7 @@ import com.alibaba.druid.sql.ast.statement.SQLInsertStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; import com.alibaba.druid.sql.ast.statement.SQLTableSource; import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.CobarShowStatus; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlBinlogStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlCommitStatement; @@ -55,6 +56,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowStatusStatemen import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowTablesStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowWarningsStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionStatement; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.parser.Lexer; import com.alibaba.druid.sql.parser.ParserException; import com.alibaba.druid.sql.parser.SQLSelectParser; @@ -82,6 +84,37 @@ public class MySqlStatementParser extends SQLStatementParser { public SQLSelectStatement parseSelect() throws ParserException { return new SQLSelectStatement(new MySqlSelectParser(lexer).select()); } + + public SQLUpdateStatement parseUpdateStatement() throws ParserException { + MySqlUpdateStatement stmt = (MySqlUpdateStatement) super.parseUpdateStatement(); + + if (lexer.token() == Token.LIMIT) { + lexer.nextToken(); + + MySqlSelectQueryBlock.Limit limit = new MySqlSelectQueryBlock.Limit(); + + SQLExpr temp = this.exprParser.expr(); + if (lexer.token() == (Token.COMMA)) { + limit.setOffset(temp); + lexer.nextToken(); + limit.setRowCount(exprParser.expr()); + } else if (identifierEquals("OFFSET")) { + limit.setRowCount(temp); + lexer.nextToken(); + limit.setOffset(exprParser.expr()); + } else { + limit.setRowCount(temp); + } + + stmt.setLimit(limit); + } + + return stmt; + } + + protected MySqlUpdateStatement createUpdateStatement() { + return new MySqlUpdateStatement(); + } public MySqlDeleteStatement parseDeleteStatement() throws ParserException { MySqlDeleteStatement deleteStatement = new MySqlDeleteStatement(); diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java index 763b372b6c..6bf3cdfb98 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitor.java @@ -50,6 +50,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowTablesStatemen import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowWarningsStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitor; public interface MySqlASTVisitor extends SQLASTVisitor { @@ -201,4 +202,8 @@ public interface MySqlASTVisitor extends SQLASTVisitor { boolean visit(MySqlDescribeStatement x); void endVisit(MySqlDescribeStatement x); + + boolean visit(MySqlUpdateStatement x); + + void endVisit(MySqlUpdateStatement x); } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java index 70359fcfd1..7df300fe62 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlASTVisitorAdapter.java @@ -37,6 +37,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowTablesStatemen import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowWarningsStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTVisitorAdapter; public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements @@ -433,4 +434,14 @@ public class MySqlASTVisitorAdapter extends SQLASTVisitorAdapter implements } + @Override + public boolean visit(MySqlUpdateStatement x) { + return true; + } + + @Override + public void endVisit(MySqlUpdateStatement x) { + + } + } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java index eed536c3a3..48d98e9420 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlOutputVisitor.java @@ -28,6 +28,8 @@ import com.alibaba.druid.sql.ast.statement.SQLColumnConstraint; import com.alibaba.druid.sql.ast.statement.SQLColumnDefinition; import com.alibaba.druid.sql.ast.statement.SQLCreateTableStatement; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; +import com.alibaba.druid.sql.ast.statement.SQLUpdateSetItem; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBinaryExpr; @@ -68,6 +70,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowTablesStatemen import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowWarningsStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.visitor.SQLASTOutputVisitor; public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTVisitor { @@ -1376,4 +1379,19 @@ public class MySqlOutputVisitor extends SQLASTOutputVisitor implements MySqlASTV public void endVisit(MySqlDescribeStatement x) { } + + @Override + public boolean visit(MySqlUpdateStatement x) { + super.visit((SQLUpdateStatement) x); + if (x.getLimit() != null) { + println(); + x.getLimit().accept(this); + } + return false; + } + + @Override + public void endVisit(MySqlUpdateStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java index cd8876d508..b7d20efc91 100644 --- a/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java +++ b/src/main/java/com/alibaba/druid/sql/dialect/mysql/visitor/MySqlSchemaStatVisitor.java @@ -8,6 +8,7 @@ import com.alibaba.druid.sql.ast.statement.SQLDropTableStatement; import com.alibaba.druid.sql.ast.statement.SQLExprTableSource; import com.alibaba.druid.sql.ast.statement.SQLSelectQueryBlock; import com.alibaba.druid.sql.ast.statement.SQLSelectStatement; +import com.alibaba.druid.sql.ast.statement.SQLUpdateStatement; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlKey; import com.alibaba.druid.sql.dialect.mysql.ast.MySqlPrimaryKey; import com.alibaba.druid.sql.dialect.mysql.ast.expr.MySqlBinaryExpr; @@ -45,6 +46,7 @@ import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowTablesStatemen import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlShowWarningsStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlStartTransactionStatement; import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlTableIndex; +import com.alibaba.druid.sql.dialect.mysql.ast.statement.MySqlUpdateStatement; import com.alibaba.druid.sql.visitor.SchemaStatVisitor; import com.alibaba.druid.stat.TableStat; import com.alibaba.druid.stat.TableStat.Mode; @@ -493,4 +495,14 @@ public class MySqlSchemaStatVisitor extends SchemaStatVisitor implements MySqlAS public void endVisit(MySqlDescribeStatement x) { } + + @Override + public boolean visit(MySqlUpdateStatement x) { + return visit((SQLUpdateStatement) x); + } + + @Override + public void endVisit(MySqlUpdateStatement x) { + + } } diff --git a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java index 066ea18062..aeed53c8fe 100644 --- a/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java +++ b/src/main/java/com/alibaba/druid/sql/parser/SQLStatementParser.java @@ -365,7 +365,7 @@ public class SQLStatementParser extends SQLParser { } public SQLUpdateStatement parseUpdateStatement() throws ParserException { - SQLUpdateStatement udpateStatement = new SQLUpdateStatement(); + SQLUpdateStatement udpateStatement = createUpdateStatement(); if (lexer.token() == Token.UPDATE) { lexer.nextToken(); @@ -400,6 +400,10 @@ public class SQLStatementParser extends SQLParser { return udpateStatement; } + protected SQLUpdateStatement createUpdateStatement() { + return new SQLUpdateStatement(); + } + public SQLDeleteStatement parseDeleteStatement() throws ParserException { SQLDeleteStatement deleteStatement = new SQLDeleteStatement(); diff --git a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java index 6c2763b173..19ed5feb69 100644 --- a/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java +++ b/src/main/java/com/alibaba/druid/stat/JdbcSqlStat.java @@ -50,7 +50,8 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { private final AtomicLong runningCount = new AtomicLong(0L); private final AtomicLong concurrentMax = new AtomicLong(); private final AtomicLong resultSetHoldTimeNano = new AtomicLong(); - + private final AtomicLong executeAndResultSetHoldTime = new AtomicLong(); + private String name; private String file; private String dbType; @@ -66,6 +67,7 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { private final AtomicLong inTransactionCount = new AtomicLong(); + private String lastSlowParameters; private final Histogram histogram = new Histogram(new long[] { // @@ -183,6 +185,7 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { this.lastSlowParameters = null; inTransactionCount.set(0); resultSetHoldTimeNano.set(0); + executeAndResultSetHoldTime.set(0); } public long getConcurrentMax() { @@ -401,6 +404,7 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { new ArrayType(SimpleType.LONG, true), // SimpleType.STRING, // SimpleType.LONG, // + SimpleType.LONG // }; String[] indexNames = { @@ -442,7 +446,8 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { // 25 - "Histogram", // "LastSlowParameters", - "ResultSetHoldTime" + "ResultSetHoldTime", + "executeAndResultSetHoldTime" // }; String[] indexDescriptions = indexNames; @@ -505,6 +510,8 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { map.put("Histogram", this.histogram.toArray()); // 25 map.put("LastSlowParameters", lastSlowParameters); // 26 map.put("ResultSetHoldTime", getResultSetHoldTimeMilis()); // 26 + map.put("executeAndResultSetHoldTime", this.getExecuteAndResultSetHoldTimeMilis()); // 26 + return map; } @@ -528,12 +535,26 @@ public final class JdbcSqlStat implements JdbcSqlStatMBean { return getResultSetHoldTimeNano() / (1000 * 1000); } + public long getExecuteAndResultSetHoldTimeMilis() { + return getExecuteAndResultSetHoldTimeNano() / (1000 * 1000); + } + + + public long getResultSetHoldTimeNano() { return resultSetHoldTimeNano.get(); } + public long getExecuteAndResultSetHoldTimeNano() { + return executeAndResultSetHoldTime.get(); + } + public void addResultSetHoldTimeNano(long nano) { resultSetHoldTimeNano.addAndGet(nano); } + public void addResultSetHoldTimeNano(long statementExecuteNano, long resultHoldTimeNano) { + resultSetHoldTimeNano.addAndGet(resultHoldTimeNano); + executeAndResultSetHoldTime.addAndGet(statementExecuteNano+resultHoldTimeNano); + } }