diff --git a/arex-instrumentation-api/pom.xml b/arex-instrumentation-api/pom.xml
index ce6ae7772..c0cbf5049 100644
--- a/arex-instrumentation-api/pom.xml
+++ b/arex-instrumentation-api/pom.xml
@@ -32,7 +32,6 @@
com.fasterxml.jackson.core
jackson-databind
${jackson.version}
- test
com.google.code.gson
diff --git a/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/util/MockUtils.java b/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/util/MockUtils.java
index fdc0f4c94..eada95d41 100644
--- a/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/util/MockUtils.java
+++ b/arex-instrumentation-api/src/main/java/io/arex/inst/runtime/util/MockUtils.java
@@ -1,5 +1,6 @@
package io.arex.inst.runtime.util;
+import com.fasterxml.jackson.databind.JsonNode;
import io.arex.agent.bootstrap.model.ArexMocker;
import io.arex.agent.bootstrap.model.MockCategoryType;
import io.arex.agent.bootstrap.model.MockStrategyEnum;
@@ -7,6 +8,8 @@
import io.arex.agent.bootstrap.model.Mocker.Target;
import io.arex.agent.bootstrap.util.MapUtils;
import io.arex.agent.bootstrap.util.StringUtil;
+import io.arex.agent.thirdparty.util.parse.sqlparse.SqlParseManager;
+import io.arex.agent.thirdparty.util.parse.sqlparse.constants.DbParseConstants;
import io.arex.inst.runtime.log.LogManager;
import io.arex.inst.runtime.config.Config;
import io.arex.inst.runtime.context.ArexContext;
@@ -17,6 +20,8 @@
import io.arex.inst.runtime.service.DataService;
import io.arex.inst.runtime.util.sizeof.AgentSizeOf;
+import java.util.Map;
+
public final class MockUtils {
private static final String EMPTY_JSON = "{}";
@@ -48,6 +53,25 @@ public static ArexMocker createDatabase(String method) {
return create(MockCategoryType.DATABASE, method);
}
+ public static ArexMocker createDatabase(String method, String sql, String dbName) {
+ StringBuilder operationName = new StringBuilder();
+ try {
+ String[] splitSql = sql.split(";");
+ for (String s : splitSql) {
+ Map tableAndAction = SqlParseManager.getInstance().parseTableAndAction(s);
+ if (tableAndAction != null && !tableAndAction.isEmpty()) {
+ String action = tableAndAction.getOrDefault(DbParseConstants.ACTION, StringUtil.EMPTY);
+ String tableName = tableAndAction.getOrDefault(DbParseConstants.TABLE, StringUtil.EMPTY);
+ operationName.append(dbName).append("-").append(tableName).append("-").append(action).append(";");
+ }
+ }
+ } catch (Exception e) {
+ LogManager.warn("createDatabase", "parse sql error", e);
+ operationName.append(method);
+ }
+ return createDatabase(operationName.toString());
+ }
+
public static ArexMocker createRedis(String method) {
return create(MockCategoryType.REDIS, method);
}
diff --git a/arex-instrumentation-api/src/test/java/io/arex/inst/runtime/util/MockUtilsTest.java b/arex-instrumentation-api/src/test/java/io/arex/inst/runtime/util/MockUtilsTest.java
index 5284b0977..28e9a7d24 100644
--- a/arex-instrumentation-api/src/test/java/io/arex/inst/runtime/util/MockUtilsTest.java
+++ b/arex-instrumentation-api/src/test/java/io/arex/inst/runtime/util/MockUtilsTest.java
@@ -178,6 +178,9 @@ void createMocker() {
actualResult = MockUtils.createNettyProvider("query");
assertEquals(MockCategoryType.NETTY_PROVIDER, actualResult.getCategoryType());
+
+ actualResult = MockUtils.createDatabase("query", "select * from test", "testDB");
+ assertEquals(MockCategoryType.DATABASE, actualResult.getCategoryType());
}
@Test
diff --git a/arex-instrumentation/database/arex-database-common/src/main/java/io/arex/inst/database/common/DatabaseExtractor.java b/arex-instrumentation/database/arex-database-common/src/main/java/io/arex/inst/database/common/DatabaseExtractor.java
index 3e8976513..9403a49f1 100644
--- a/arex-instrumentation/database/arex-database-common/src/main/java/io/arex/inst/database/common/DatabaseExtractor.java
+++ b/arex-instrumentation/database/arex-database-common/src/main/java/io/arex/inst/database/common/DatabaseExtractor.java
@@ -116,7 +116,7 @@ public MockResult replay(String serializer) {
}
private Mocker makeMocker(Object response, String serializer) {
- Mocker mocker = MockUtils.createDatabase(this.methodName);
+ Mocker mocker = MockUtils.createDatabase(this.methodName, this.sql, this.dbName);
mocker.getTargetRequest().setBody(this.sql);
mocker.getTargetRequest().setAttribute("dbName", this.dbName);
mocker.getTargetRequest().setAttribute("parameters", this.parameters);
diff --git a/arex-third-party/pom.xml b/arex-third-party/pom.xml
index 0f89cec99..5e78fd883 100644
--- a/arex-third-party/pom.xml
+++ b/arex-third-party/pom.xml
@@ -7,7 +7,59 @@
io.arex
${revision}
+
+
+ com.fasterxml.jackson.core
+ jackson-databind
+ ${jackson.version}
+
+
+ com.github.jsqlparser
+ jsqlparser
+ ${jsqlparser.version}
+
+
4.0.0
arex-third-party
+ jar
+
+
+
+
+ org.apache.maven.plugins
+ maven-shade-plugin
+ ${maven-shade-plugin.version}
+
+
+ package
+
+ shade
+
+
+
+
+ com.github.jsqlparser
+ shaded.com.github.jsqlparser
+
+
+ com.fasterxml.jackson.core
+ shaded.com.fasterxml.jackson.core
+
+
+
+
+
+
+
+
+ com.github.jsqlparser:jsqlparser
+ com.fasterxml.jackson.core:jackson-databind
+ io.arex:arex-third-party
+
+
+
+
+
+
\ No newline at end of file
diff --git a/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/JacksonHelperUtil.java b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/JacksonHelperUtil.java
new file mode 100644
index 000000000..229b35439
--- /dev/null
+++ b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/JacksonHelperUtil.java
@@ -0,0 +1,23 @@
+package io.arex.agent.thirdparty.util;
+
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.fasterxml.jackson.databind.node.ArrayNode;
+import com.fasterxml.jackson.databind.node.ObjectNode;
+
+/**
+ * @author niyan
+ * @date 2024/4/3
+ * @since 1.0.0
+ */
+public class JacksonHelperUtil {
+
+ public static ObjectMapper objectMapper = new ObjectMapper();
+
+ public static ObjectNode getObjectNode() {
+ return objectMapper.createObjectNode();
+ }
+
+ public static ArrayNode getArrayNode() {
+ return objectMapper.createArrayNode();
+ }
+}
diff --git a/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/SqlParseManager.java b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/SqlParseManager.java
new file mode 100644
index 000000000..212b0a852
--- /dev/null
+++ b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/SqlParseManager.java
@@ -0,0 +1,88 @@
+package io.arex.agent.thirdparty.util.parse.sqlparse;
+
+import com.fasterxml.jackson.databind.JsonNode;
+import io.arex.agent.thirdparty.util.parse.sqlparse.action.AbstractParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.action.ActionFactory;
+import io.arex.agent.thirdparty.util.parse.sqlparse.constants.DbParseConstants;
+import net.sf.jsqlparser.JSQLParserException;
+import net.sf.jsqlparser.parser.CCJSqlParserUtil;
+import net.sf.jsqlparser.statement.Statement;
+import net.sf.jsqlparser.statement.delete.Delete;
+import net.sf.jsqlparser.statement.execute.Execute;
+import net.sf.jsqlparser.statement.insert.Insert;
+import net.sf.jsqlparser.statement.replace.Replace;
+import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.update.Update;
+import net.sf.jsqlparser.util.TablesNamesFinder;
+
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * sql parse
+ *
+ * @author niyan
+ * @date 2024/4/3
+ * @since 1.0.0
+ */
+public class SqlParseManager {
+
+ private static SqlParseManager INSTANCE;
+
+ private SqlParseManager() {
+ }
+
+ public static SqlParseManager getInstance() {
+ if (INSTANCE == null) {
+ INSTANCE = new SqlParseManager();
+ }
+ return INSTANCE;
+ }
+
+ public JsonNode parse(String sql) throws JSQLParserException {
+ if (sql == null || sql.isEmpty()) {
+ return null;
+ }
+
+ Statement statement = CCJSqlParserUtil.parse(sql);
+ AbstractParse parse = ActionFactory.selectParse(statement);
+ return parse.parse(statement);
+ }
+
+ public Map parseTableAndAction(String sql) throws JSQLParserException {
+ if (sql == null || sql.isEmpty()) {
+ return null;
+ }
+
+ Map result = new HashMap<>(2);
+
+ Statement statement = CCJSqlParserUtil.parse(sql);
+ result.put(DbParseConstants.ACTION, getAction(statement));
+
+ TablesNamesFinder tablesNamesFinder = new TablesNamesFinder();
+ List tableNames = tablesNamesFinder.getTableList(statement);
+ if (tableNames != null && !tableNames.isEmpty()) {
+ result.put(DbParseConstants.TABLE, String.join(",", tableNames));
+ }
+ return result;
+ }
+
+ private String getAction(Statement statement) {
+ if (statement instanceof Select) {
+ return DbParseConstants.SELECT;
+ } else if (statement instanceof Execute) {
+ return DbParseConstants.EXECUTE;
+ } else if (statement instanceof Delete) {
+ return DbParseConstants.DELETE;
+ } else if (statement instanceof Insert) {
+ return DbParseConstants.INSERT;
+ } else if (statement instanceof Replace) {
+ return DbParseConstants.REPLACE;
+ } else if (statement instanceof Update) {
+ return DbParseConstants.UPDATE;
+ } else {
+ return "";
+ }
+ }
+}
diff --git a/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/AbstractParse.java b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/AbstractParse.java
new file mode 100644
index 000000000..8fb495f42
--- /dev/null
+++ b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/AbstractParse.java
@@ -0,0 +1,26 @@
+package io.arex.agent.thirdparty.util.parse.sqlparse.action;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.arex.agent.thirdparty.util.JacksonHelperUtil;
+import io.arex.agent.thirdparty.util.parse.sqlparse.constants.DbParseConstants;
+
+/**
+ * @author niyan
+ * @date 2024/4/8
+ * @since 1.0.0
+ */
+public abstract class AbstractParse {
+
+ protected final ObjectNode sqlObjectNode;
+
+ public AbstractParse() {
+ sqlObjectNode = JacksonHelperUtil.getObjectNode();
+ }
+
+ public AbstractParse(String action) {
+ this();
+ sqlObjectNode.put(DbParseConstants.ACTION, action);
+ }
+
+ public abstract ObjectNode parse(T parseObj);
+}
diff --git a/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/ActionFactory.java b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/ActionFactory.java
new file mode 100644
index 000000000..08c6d61a4
--- /dev/null
+++ b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/ActionFactory.java
@@ -0,0 +1,36 @@
+package io.arex.agent.thirdparty.util.parse.sqlparse.action;
+
+import net.sf.jsqlparser.statement.delete.Delete;
+import net.sf.jsqlparser.statement.execute.Execute;
+import net.sf.jsqlparser.statement.insert.Insert;
+import net.sf.jsqlparser.statement.replace.Replace;
+import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.update.Update;
+
+import net.sf.jsqlparser.statement.Statement;
+
+
+/**
+ * @author niyan
+ * @date 2024/4/3
+ * @since 1.0.0
+ */
+public class ActionFactory {
+ public static AbstractParse extends Statement> selectParse(Statement statement) {
+ if (statement instanceof Select) {
+ return new SelectParse();
+ } else if (statement instanceof Execute) {
+ return new ExecuteParse();
+ } else if (statement instanceof Delete) {
+ return new DeleteParse();
+ } else if (statement instanceof Insert) {
+ return new InsertParse();
+ } else if (statement instanceof Replace) {
+ return new ReplaceParse();
+ } else if (statement instanceof Update) {
+ return new UpdateParse();
+ } else {
+ throw new UnsupportedOperationException("not support");
+ }
+ }
+}
diff --git a/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/DeleteParse.java b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/DeleteParse.java
new file mode 100644
index 000000000..4c3a371ae
--- /dev/null
+++ b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/DeleteParse.java
@@ -0,0 +1,42 @@
+package io.arex.agent.thirdparty.util.parse.sqlparse.action;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.CommonParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.ExpressionParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.JoinParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.OrderByParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.TableParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.constants.DbParseConstants;
+import net.sf.jsqlparser.statement.delete.Delete;
+
+/**
+ * @author niyan
+ * @date 2024/4/3
+ * @since 1.0.0
+ */
+public class DeleteParse extends AbstractParse {
+
+ public DeleteParse() {
+ super(DbParseConstants.DELETE);
+ }
+ @Override
+ public ObjectNode parse(Delete parseObj) {
+
+ // tables parse
+ TableParse.parseDelTable(parseObj.getTables(), parseObj.getTable(), sqlObjectNode);
+
+ // join parse
+ JoinParse.parse(parseObj.getJoins(), sqlObjectNode);
+
+ // where parse
+ ExpressionParse.parseWhere(parseObj.getWhere(), sqlObjectNode);
+
+ // orderBy parse
+ OrderByParse.parse(parseObj.getOrderByElements(), sqlObjectNode);
+
+ // limit parse
+ CommonParse.parseLimit(parseObj.getLimit(), sqlObjectNode);
+
+ return sqlObjectNode;
+ }
+}
diff --git a/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/ExecuteParse.java b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/ExecuteParse.java
new file mode 100644
index 000000000..f023c2c08
--- /dev/null
+++ b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/ExecuteParse.java
@@ -0,0 +1,31 @@
+package io.arex.agent.thirdparty.util.parse.sqlparse.action;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.CommonParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.ExpressionParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.constants.DbParseConstants;
+import net.sf.jsqlparser.statement.execute.Execute;
+
+/**
+ * @author niyan
+ * @date 2024/4/3
+ * @since 1.0.0
+ */
+public class ExecuteParse extends AbstractParse {
+
+ public ExecuteParse() {
+ super(DbParseConstants.EXECUTE);
+ }
+
+ @Override
+ public ObjectNode parse(Execute parseObj) {
+
+ // execute name parse
+ CommonParse.parseName(parseObj.getName(), sqlObjectNode);
+
+ // expressions parse
+ ExpressionParse.parse(parseObj.getExprList(), sqlObjectNode);
+
+ return sqlObjectNode;
+ }
+}
diff --git a/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/InsertParse.java b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/InsertParse.java
new file mode 100644
index 000000000..1265effb0
--- /dev/null
+++ b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/InsertParse.java
@@ -0,0 +1,32 @@
+package io.arex.agent.thirdparty.util.parse.sqlparse.action;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.ColumnParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.TableParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.constants.DbParseConstants;
+import net.sf.jsqlparser.statement.insert.Insert;
+
+/**
+ * @author niyan
+ * @date 2024/4/3
+ * @since 1.0.0
+ */
+public class InsertParse extends AbstractParse {
+
+ public InsertParse() {
+ super(DbParseConstants.INSERT);
+ }
+ @Override
+ public ObjectNode parse(Insert parseObj) {
+ // table parse
+ TableParse.parse(parseObj.getTable(), sqlObjectNode);
+
+ // columns parse
+ ColumnParse.parse(parseObj.getColumns(), parseObj.getItemsList(), sqlObjectNode);
+
+ // setColumns parse
+ ColumnParse.parseSetColumns(parseObj.getSetColumns(), parseObj.getSetExpressionList(), sqlObjectNode);
+
+ return sqlObjectNode;
+ }
+}
diff --git a/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/ReplaceParse.java b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/ReplaceParse.java
new file mode 100644
index 000000000..e1d3ff617
--- /dev/null
+++ b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/ReplaceParse.java
@@ -0,0 +1,33 @@
+package io.arex.agent.thirdparty.util.parse.sqlparse.action;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.ColumnParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.ExpressionParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.parse.TableParse;
+import io.arex.agent.thirdparty.util.parse.sqlparse.constants.DbParseConstants;
+import net.sf.jsqlparser.statement.replace.Replace;
+
+/**
+ * @author niyan
+ * @date 2024/4/3
+ * @since 1.0.0
+ */
+public class ReplaceParse extends AbstractParse {
+
+ public ReplaceParse() {
+ super(DbParseConstants.REPLACE);
+ }
+ @Override
+ public ObjectNode parse(Replace parseObj) {
+ // table parse
+ TableParse.parse(parseObj.getTable(), sqlObjectNode);
+
+ // columns parse
+ ColumnParse.parse(parseObj.getColumns(), parseObj.getItemsList(), sqlObjectNode);
+
+ // expressions parse
+ ExpressionParse.parse(parseObj.getExpressions(), parseObj.getColumns(), sqlObjectNode);
+
+ return sqlObjectNode;
+ }
+}
diff --git a/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/SelectParse.java b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/SelectParse.java
new file mode 100644
index 000000000..a3fb48cf8
--- /dev/null
+++ b/arex-third-party/src/main/java/io/arex/agent/thirdparty/util/parse/sqlparse/action/SelectParse.java
@@ -0,0 +1,29 @@
+package io.arex.agent.thirdparty.util.parse.sqlparse.action;
+
+import com.fasterxml.jackson.databind.node.ObjectNode;
+import io.arex.agent.thirdparty.util.parse.sqlparse.adapter.ArexSelectVisitorAdapter;
+import io.arex.agent.thirdparty.util.parse.sqlparse.constants.DbParseConstants;
+import net.sf.jsqlparser.statement.select.Select;
+import net.sf.jsqlparser.statement.select.SelectBody;
+
+/**
+ * @author niyan
+ * @date 2024/4/3
+ * @since 1.0.0
+ */
+public class SelectParse extends AbstractParse