diff --git a/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDBIT.java b/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDBIT.java deleted file mode 100644 index 11748fe5c..000000000 --- a/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDBIT.java +++ /dev/null @@ -1,86 +0,0 @@ -package com.navercorp.pinpoint.plugin.jdbc.mariadb; - -import static com.navercorp.pinpoint.bootstrap.plugin.test.Expectations.*; -import static org.junit.Assert.*; - -import java.sql.Connection; -import java.sql.DriverManager; -import java.sql.PreparedStatement; -import java.sql.ResultSet; -import java.sql.Statement; -import java.util.Properties; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; -import org.junit.runner.RunWith; -import org.mariadb.jdbc.Driver; -import org.mariadb.jdbc.MariaDbConnection; -import org.mariadb.jdbc.MariaDbServerPreparedStatement; -import org.mariadb.jdbc.MariaDbStatement; - -import ch.vorburger.mariadb4j.DB; - -import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier; -import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifierHolder; -import com.navercorp.pinpoint.test.plugin.Dependency; -import com.navercorp.pinpoint.test.plugin.JvmVersion; -import com.navercorp.pinpoint.test.plugin.PinpointPluginTestSuite; -import com.navercorp.pinpoint.test.plugin.Repository; - -@RunWith(PinpointPluginTestSuite.class) -@JvmVersion(7) -@Repository("http://jcenter.bintray.com") -@Dependency({ "org.mariadb.jdbc:mariadb-java-client:[1.3.4,)", "ch.vorburger.mariaDB4j:mariaDB4j:2.1.3" }) -public class MariaDBIT { - - private static final String JDBC_URL = "jdbc:mariadb://127.0.0.1:13306/test"; - private static final String PREPARED_STATEMENT = "SELECT * FROM playground where id = ?"; - - private DB db; - - @Before - public void init() throws Exception { - db = DB.newEmbeddedDB(13306); - db.start(); - db.createDB("test"); - db.source("jdbc/mariadb/init.sql"); - } - - @Test - public void testConnection() throws Exception { - PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); - - Connection connection = DriverManager.getConnection(JDBC_URL, "root", null); - -// verifier.verifyTraceCount(1); - - Statement statement = connection.createStatement(); - ResultSet result = statement.executeQuery("SELECT count(1) FROM playground"); - result.first(); - assertEquals(3, result.getInt(1)); - - verifier.printCache(); - - verifier.verifyTraceCount(2); - verifier.verifyTrace(event("MARIADB", Driver.class.getMethod("connect", String.class, Properties.class), cachedArgs(JDBC_URL))); - verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", MariaDbStatement.class.getMethod("executeQuery", String.class), sql("SELECT count(0#) FROM playground", "1"))); - - PreparedStatement ps = connection.prepareStatement(PREPARED_STATEMENT); - ps.setInt(1, 3); - result = ps.executeQuery(); - result.first(); - assertEquals("THREE", result.getString(2)); - - verifier.printCache(); - verifier.verifyTraceCount(2); - verifier.verifyTrace(event("MARIADB", MariaDbConnection.class.getMethod("prepareStatement", String.class), sql(PREPARED_STATEMENT, null))); - verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", MariaDbServerPreparedStatement.class.getMethod("executeQuery"), sql(PREPARED_STATEMENT, null, "3"))); - } - - @After - public void cleanUp() throws Exception { - db.stop(); - } - -} diff --git a/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDB_1_3_x_IT.java b/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDB_1_3_x_IT.java new file mode 100644 index 000000000..8ceeee24d --- /dev/null +++ b/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDB_1_3_x_IT.java @@ -0,0 +1,104 @@ +package com.navercorp.pinpoint.plugin.jdbc.mariadb; + +import static com.navercorp.pinpoint.bootstrap.plugin.test.Expectations.*; + +import java.lang.reflect.Method; +import java.util.Properties; + +import org.junit.Test; +import org.junit.runner.RunWith; + +import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier; +import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifierHolder; +import com.navercorp.pinpoint.test.plugin.Dependency; +import com.navercorp.pinpoint.test.plugin.JvmVersion; +import com.navercorp.pinpoint.test.plugin.PinpointPluginTestSuite; +import com.navercorp.pinpoint.test.plugin.Repository; + +@RunWith(PinpointPluginTestSuite.class) +@JvmVersion(7) +@Repository("http://jcenter.bintray.com") +@Dependency({"org.mariadb.jdbc:mariadb-java-client:[1.3.0,1.3.max]", "ch.vorburger.mariaDB4j:mariaDB4j:2.1.3"}) +public class MariaDB_1_3_x_IT extends MariaDB_IT_Base { + + // see CallableParameterMetaData#queryMetaInfos + private static final String CALLABLE_QUERY_META_INFOS_QUERY = "select param_list,returns from mysql.proc where db=database() and name='0$'"; + + @Test + public void testStatement() throws Exception { + super.executeStatement(); + + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + verifier.printCache(); + verifier.verifyTraceCount(2); + + // Driver#connect(String, Properties) + Class driverClass = Class.forName("org.mariadb.jdbc.Driver"); + Method connect = driverClass.getDeclaredMethod("connect", String.class, Properties.class); + verifier.verifyTrace(event("MARIADB", connect, null, URL, DATABASE_NAME, cachedArgs(JDBC_URL))); + + // MariaDbStatement#executeQuery(String) + Class mariaDbStatementClass = Class.forName("org.mariadb.jdbc.MariaDbStatement"); + Method executeQuery = mariaDbStatementClass.getDeclaredMethod("executeQuery", String.class); + verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", executeQuery, null, URL, DATABASE_NAME, sql(STATEMENT_NORMALIZED_QUERY, "1"))); + } + + @Test + public void testPreparedStatement() throws Exception { + super.executePreparedStatement(); + + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + verifier.printCache(); + verifier.verifyTraceCount(3); + + // Driver#connect(String, Properties) + Class driverClass = Class.forName("org.mariadb.jdbc.Driver"); + Method connect = driverClass.getDeclaredMethod("connect", String.class, Properties.class); + verifier.verifyTrace(event("MARIADB", connect, null, URL, DATABASE_NAME, cachedArgs(JDBC_URL))); + + // MariaDbConnection#prepareStatement(String) + Class mariaDbConnectionClass = Class.forName("org.mariadb.jdbc.MariaDbConnection"); + Method prepareStatement = mariaDbConnectionClass.getDeclaredMethod("prepareStatement", String.class); + verifier.verifyTrace(event("MARIADB", prepareStatement, null, URL, DATABASE_NAME, sql(PREPARED_STATEMENT_QUERY, null))); + + // MariaDbServerPreparedStatement#executeQuery + Class mariaDbServerPreparedStatementClass = Class.forName("org.mariadb.jdbc.MariaDbServerPreparedStatement"); + Method executeQuery = mariaDbServerPreparedStatementClass.getDeclaredMethod("executeQuery"); + verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", executeQuery, null, URL, DATABASE_NAME, sql(PREPARED_STATEMENT_QUERY, null, "3"))); + } + + @Test + public void testCallableStatement() throws Exception { + super.executeCallableStatement(); + + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + verifier.printCache(); + verifier.verifyTraceCount(5); + + // Driver#connect(String, Properties) + Class driverClass = Class.forName("org.mariadb.jdbc.Driver"); + Method connect = driverClass.getDeclaredMethod("connect", String.class, Properties.class); + verifier.verifyTrace(event("MARIADB", connect, null, URL, DATABASE_NAME, cachedArgs(JDBC_URL))); + + // MariaDbConnection#prepareCall(String) + Class mariaDbConnectionClass = Class.forName("org.mariadb.jdbc.MariaDbConnection"); + Method prepareCall = mariaDbConnectionClass.getDeclaredMethod("prepareCall", String.class); + verifier.verifyTrace(event("MARIADB", prepareCall, null, URL, DATABASE_NAME, sql(CALLABLE_STATEMENT_QUERY, null))); + + // MariaDbClientCallableStatement#registerOutParameter(int, int) + Class mariaDbClientCallableStatementClass = Class.forName("org.mariadb.jdbc.MariaDbCallableStatement"); + Method registerOutParameter = mariaDbClientCallableStatementClass.getDeclaredMethod("registerOutParameter", int.class, int.class); + verifier.verifyTrace(event("MARIADB", registerOutParameter, null, URL, DATABASE_NAME, args(2, CALLABLE_STATMENT_OUTPUT_PARAM_TYPE))); + + // MariaDbCallableStatement#executeQuery + Class mariaDbCallableStatementClass = Class.forName("org.mariadb.jdbc.MariaDbCallableStatement"); + Method callableStatementExecuteQuery = mariaDbCallableStatementClass.getDeclaredMethod("executeQuery"); + verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", callableStatementExecuteQuery, null, URL, DATABASE_NAME, sql(CALLABLE_STATEMENT_QUERY, null, CALLABLE_STATEMENT_INPUT_PARAM))); + + // MariaDbStatement#executeQuery + Class mariaDbStatementClass = Class.forName("org.mariadb.jdbc.MariaDbStatement"); + Method statementExecuteQuery = mariaDbStatementClass.getDeclaredMethod("executeQuery", String.class); + verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", statementExecuteQuery, null, URL, DATABASE_NAME, sql(CALLABLE_QUERY_META_INFOS_QUERY, PROCEDURE_NAME))); + } + +} diff --git a/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDB_1_4_x_IT.java b/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDB_1_4_x_IT.java new file mode 100644 index 000000000..76fd14be8 --- /dev/null +++ b/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDB_1_4_x_IT.java @@ -0,0 +1,123 @@ +/* + * Copyright 2016 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.plugin.jdbc.mariadb; + +import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifier; +import com.navercorp.pinpoint.bootstrap.plugin.test.PluginTestVerifierHolder; +import com.navercorp.pinpoint.test.plugin.Dependency; +import com.navercorp.pinpoint.test.plugin.JvmVersion; +import com.navercorp.pinpoint.test.plugin.PinpointPluginTestSuite; +import com.navercorp.pinpoint.test.plugin.Repository; +import org.junit.Test; +import org.junit.runner.RunWith; + +import java.lang.reflect.Method; +import java.util.Properties; + +import static com.navercorp.pinpoint.bootstrap.plugin.test.Expectations.*; + +/** + * @author HyunGil Jeong + */ + +@RunWith(PinpointPluginTestSuite.class) +@JvmVersion(7) +@Repository("http://jcenter.bintray.com") +@Dependency({ "org.mariadb.jdbc:mariadb-java-client:[1.4.min,1.4.max]", "ch.vorburger.mariaDB4j:mariaDB4j:2.1.3" }) +public class MariaDB_1_4_x_IT extends MariaDB_IT_Base { + + // see CallableParameterMetaData#queryMetaInfos + private static final String CALLABLE_QUERY_META_INFOS_QUERY = "select param_list, returns, db, type from mysql.proc where db=DATABASE() and name=?"; + + @Test + public void testStatement() throws Exception { + super.executeStatement(); + + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + verifier.printCache(); + + // Driver#connect(String, Properties) + Class driverClass = Class.forName("org.mariadb.jdbc.Driver"); + Method connect = driverClass.getDeclaredMethod("connect", String.class, Properties.class); + verifier.verifyTrace(event("MARIADB", connect, null, URL, DATABASE_NAME, cachedArgs(JDBC_URL))); + + // MariaDbStatement#executeQuery(String) + Class mariaDbStatementClass = Class.forName("org.mariadb.jdbc.MariaDbStatement"); + Method executeQuery = mariaDbStatementClass.getDeclaredMethod("executeQuery", String.class); + verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", executeQuery, null, URL, DATABASE_NAME, sql(STATEMENT_NORMALIZED_QUERY, "1"))); + } + + @Test + public void testPreparedStatement() throws Exception { + super.executePreparedStatement(); + + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + verifier.printCache(); + verifier.verifyTraceCount(3); + + // Driver#connect(String, Properties) + Class driverClass = Class.forName("org.mariadb.jdbc.Driver"); + Method connect = driverClass.getDeclaredMethod("connect", String.class, Properties.class); + verifier.verifyTrace(event("MARIADB", connect, null, URL, DATABASE_NAME, cachedArgs(JDBC_URL))); + + // MariaDbConnection#prepareStatement(String) + Class mariaDbConnectionClass = Class.forName("org.mariadb.jdbc.MariaDbConnection"); + Method prepareStatement = mariaDbConnectionClass.getDeclaredMethod("prepareStatement", String.class); + verifier.verifyTrace(event("MARIADB", prepareStatement, null, URL, DATABASE_NAME, sql(PREPARED_STATEMENT_QUERY, null))); + + // MariaDbServerPreparedStatement#executeQuery + Class mariaDbServerPreparedStatementClass = Class.forName("org.mariadb.jdbc.MariaDbServerPreparedStatement"); + Method executeQuery = mariaDbServerPreparedStatementClass.getDeclaredMethod("executeQuery"); + verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", executeQuery, null, URL, DATABASE_NAME, sql(PREPARED_STATEMENT_QUERY, null, "3"))); + } + + @Test + public void testCallableStatement() throws Exception { + super.executeCallableStatement(); + + PluginTestVerifier verifier = PluginTestVerifierHolder.getInstance(); + verifier.printCache(); + verifier.verifyTraceCount(6); + + // Driver#connect(String, Properties) + Class driverClass = Class.forName("org.mariadb.jdbc.Driver"); + Method connect = driverClass.getDeclaredMethod("connect", String.class, Properties.class); + verifier.verifyTrace(event("MARIADB", connect, null, URL, DATABASE_NAME, cachedArgs(JDBC_URL))); + + // MariaDbConnection#prepareCall(String) + Class mariaDbConnectionClass = Class.forName("org.mariadb.jdbc.MariaDbConnection"); + Method prepareCall = mariaDbConnectionClass.getDeclaredMethod("prepareCall", String.class); + verifier.verifyTrace(event("MARIADB", prepareCall, null, URL, DATABASE_NAME, sql(CALLABLE_STATEMENT_QUERY, null))); + + // AbstractCallableProcedureStatement#registerOutParameter + Class abstractCallableProcedureStatementClass = Class.forName("org.mariadb.jdbc.AbstractCallableProcedureStatement"); + Method registerOutParameter = abstractCallableProcedureStatementClass.getMethod("registerOutParameter", int.class, int.class); + verifier.verifyTrace(event("MARIADB", registerOutParameter, null, URL, DATABASE_NAME, args(2, CALLABLE_STATMENT_OUTPUT_PARAM_TYPE))); + + // MariaDbServerPreparedStatement#executeQuery + Class mariaDbServerPreparedStatementClass = Class.forName("org.mariadb.jdbc.MariaDbServerPreparedStatement"); + Method executeQuery = mariaDbServerPreparedStatementClass.getDeclaredMethod("executeQuery"); + verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", executeQuery, null, URL, DATABASE_NAME, sql(CALLABLE_STATEMENT_QUERY, null, CALLABLE_STATEMENT_INPUT_PARAM))); + + // MariaDbConnection#prepareStatement(String) + Method prepareStatement = mariaDbConnectionClass.getDeclaredMethod("prepareStatement", String.class); + verifier.verifyTrace(event("MARIADB", prepareStatement, null, URL, DATABASE_NAME, sql(CALLABLE_QUERY_META_INFOS_QUERY, null))); + + // MariaDbServerPreparedStatement#executeQuery + verifier.verifyTrace(event("MARIADB_EXECUTE_QUERY", executeQuery, null, URL, DATABASE_NAME, sql(CALLABLE_QUERY_META_INFOS_QUERY, null, PROCEDURE_NAME))); + } +} diff --git a/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDB_IT_Base.java b/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDB_IT_Base.java new file mode 100644 index 000000000..f0fb3c4f0 --- /dev/null +++ b/agent/src/test/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDB_IT_Base.java @@ -0,0 +1,185 @@ +/* + * Copyright 2016 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.plugin.jdbc.mariadb; + +import ch.vorburger.mariadb4j.DB; +import org.junit.AfterClass; +import org.junit.BeforeClass; + +import java.sql.CallableStatement; +import java.sql.Connection; +import java.sql.DriverManager; +import java.sql.PreparedStatement; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +/** + * @author HyunGil Jeong + */ +public class MariaDB_IT_Base { + + private static final int PORT = 13306; + protected static final String URL = "127.0.0.1:" + PORT; + protected static final String DATABASE_NAME = "test"; + + protected static final String JDBC_URL = "jdbc:mariadb://" + URL + "/" + DATABASE_NAME; + + // for Statement + protected static final String STATEMENT_QUERY = "SELECT count(1) FROM playground"; + protected static final String STATEMENT_NORMALIZED_QUERY = "SELECT count(0#) FROM playground"; + + // for Prepared Statement + protected static final String PREPARED_STATEMENT_QUERY = "SELECT * FROM playground where id = ?"; + + // for Callable Statement + protected static final String PROCEDURE_NAME = "getPlaygroundByName"; + protected static final String CALLABLE_STATEMENT_QUERY = "{ CALL " + PROCEDURE_NAME + "(?, ?) }"; + protected static final String CALLABLE_STATEMENT_INPUT_PARAM = "TWO"; + protected static final int CALLABLE_STATMENT_OUTPUT_PARAM_TYPE = Types.INTEGER; + + private static DB TEST_DATABASE; + + @BeforeClass + public static void setUpBeforeClass() throws Exception { + TEST_DATABASE = DB.newEmbeddedDB(PORT); + TEST_DATABASE.start(); + TEST_DATABASE.createDB("test"); + TEST_DATABASE.source("jdbc/mariadb/init.sql"); + } + + protected final void executeStatement() throws Exception { + Connection connection = null; + try { + connection = DriverManager.getConnection(JDBC_URL, "root", null); + + Statement statement = null; + try { + statement = connection.createStatement(); + + ResultSet result = null; + try { + result = statement.executeQuery(STATEMENT_QUERY); + result.first(); + assertEquals(3, result.getInt(1)); + } finally { + closeResultSet(result); + } + } finally { + closeStatement(statement); + } + } finally { + closeConnection(connection); + } + } + + protected final void executePreparedStatement() throws Exception { + Connection connection = null; + try { + connection = DriverManager.getConnection(JDBC_URL, "root", null); + + PreparedStatement ps = null; + try { + ps = connection.prepareStatement(PREPARED_STATEMENT_QUERY); + ps.setInt(1, 3); + + ResultSet result = null; + try { + result = ps.executeQuery(); + result.first(); + assertEquals("THREE", result.getString(2)); + } finally { + closeResultSet(result); + } + } finally { + closeStatement(ps); + } + } finally { + closeConnection(connection); + } + } + + protected final void executeCallableStatement() throws Exception { + + final int expectedTotalCount = 3; + final int expectedMatchingCount = 1; + final int expectedMatchingId = 2; + final String outputParamCountName = "outputParamCount"; + + Connection conn = null; + try { + conn = DriverManager.getConnection(JDBC_URL, "root", null); + + CallableStatement cs = null; + try { + cs = conn.prepareCall(CALLABLE_STATEMENT_QUERY); + cs.setString(1, CALLABLE_STATEMENT_INPUT_PARAM); + cs.registerOutParameter(2, CALLABLE_STATMENT_OUTPUT_PARAM_TYPE); + + ResultSet rs = null; + try { + rs = cs.executeQuery(); + int matchingCount = 0; + while (rs.next()) { + ++matchingCount; + if (matchingCount > expectedMatchingCount) { + fail(); + } + assertEquals(expectedMatchingId, rs.getInt(1)); + assertEquals(CALLABLE_STATEMENT_INPUT_PARAM, rs.getString(2)); + } + assertEquals(expectedMatchingCount, matchingCount); + } finally { + closeResultSet(rs); + } + final int totalCount = cs.getInt(outputParamCountName); + assertEquals(expectedTotalCount, totalCount); + } finally { + closeStatement(cs); + } + } finally { + closeConnection(conn); + } + } + + private void closeConnection(Connection conn) throws SQLException { + if (conn != null) { + conn.close(); + } + } + + private void closeResultSet(ResultSet rs) throws SQLException { + if (rs != null) { + rs.close(); + } + } + + private void closeStatement(Statement statement) throws SQLException { + if (statement != null) { + statement.close(); + } + } + + @AfterClass + public static void tearDownAfterClass() throws Exception { + TEST_DATABASE.stop(); + } +} diff --git a/agent/src/test/resources/jdbc/mariadb/init.sql b/agent/src/test/resources/jdbc/mariadb/init.sql index 975d93386..0833e4865 100644 --- a/agent/src/test/resources/jdbc/mariadb/init.sql +++ b/agent/src/test/resources/jdbc/mariadb/init.sql @@ -2,4 +2,13 @@ USE test; CREATE TABLE IF NOT EXISTS playground (id int(5) NOT NULL, name varchar(50) DEFAULT NULL); INSERT INTO playground VALUES (1, 'ONE'); INSERT INTO playground VALUES (2, 'TWO'); -INSERT INTO playground VALUES (3, 'THREE'); \ No newline at end of file +INSERT INTO playground VALUES (3, 'THREE'); + +DELIMITER // +CREATE PROCEDURE getPlaygroundByName (IN inputParamName VARCHAR(50), OUT outputParamCount INT) + BEGIN + SELECT count(*) INTO outputParamCount FROM playground; + SELECT id, name FROM playground WHERE name = inputParamName ORDER BY id ASC; + END; +// +DELIMITER ; \ No newline at end of file diff --git a/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/CallableStatementBindVariableInterceptor.java b/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/CallableStatementBindVariableInterceptor.java new file mode 100644 index 000000000..1471633eb --- /dev/null +++ b/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/CallableStatementBindVariableInterceptor.java @@ -0,0 +1,32 @@ +/* + * Copyright 2016 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor; + +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.annotation.TargetFilter; + +/** + * @author HyunGil Jeong + */ +@TargetFilter(type = "com.navercorp.pinpoint.bootstrap.plugin.jdbc.PreparedStatementBindingMethodFilter", singleton = true) +public class CallableStatementBindVariableInterceptor extends PreparedStatementBindVariableInterceptor { + + public CallableStatementBindVariableInterceptor(TraceContext traceContext) { + super(traceContext); + } + +} diff --git a/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/CallableStatementExecuteQueryInterceptor.java b/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/CallableStatementExecuteQueryInterceptor.java new file mode 100644 index 000000000..0f1bad665 --- /dev/null +++ b/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/CallableStatementExecuteQueryInterceptor.java @@ -0,0 +1,42 @@ +/* + * Copyright 2016 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor; + +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.annotation.TargetMethod; +import com.navercorp.pinpoint.bootstrap.interceptor.annotation.TargetMethods; + +/** + * @author HyunGil Jeong + */ +@TargetMethods({ + @TargetMethod(name = "execute"), + @TargetMethod(name = "executeQuery"), + @TargetMethod(name = "executeUpdate") +}) +public class CallableStatementExecuteQueryInterceptor extends PreparedStatementExecuteQueryInterceptor { + + public CallableStatementExecuteQueryInterceptor(TraceContext traceContext, MethodDescriptor descriptor) { + super(traceContext, descriptor); + } + + public CallableStatementExecuteQueryInterceptor(TraceContext traceContext, MethodDescriptor descriptor, int maxSqlBindValue) { + super(traceContext, descriptor, maxSqlBindValue); + } + +} diff --git a/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/CallableStatementRegisterOutParameterInterceptor.java b/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/CallableStatementRegisterOutParameterInterceptor.java new file mode 100644 index 000000000..e21d6a264 --- /dev/null +++ b/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/CallableStatementRegisterOutParameterInterceptor.java @@ -0,0 +1,62 @@ +/* + * Copyright 2016 NAVER Corp. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor; + +import com.navercorp.pinpoint.bootstrap.context.DatabaseInfo; +import com.navercorp.pinpoint.bootstrap.context.MethodDescriptor; +import com.navercorp.pinpoint.bootstrap.context.SpanEventRecorder; +import com.navercorp.pinpoint.bootstrap.context.TraceContext; +import com.navercorp.pinpoint.bootstrap.interceptor.SpanEventSimpleAroundInterceptorForPlugin; +import com.navercorp.pinpoint.bootstrap.interceptor.annotation.TargetMethod; +import com.navercorp.pinpoint.bootstrap.interceptor.annotation.TargetMethods; +import com.navercorp.pinpoint.bootstrap.plugin.jdbc.DatabaseInfoAccessor; +import com.navercorp.pinpoint.bootstrap.plugin.jdbc.UnKnownDatabaseInfo; + +/** + * @author HyunGil Jeong + */ +@TargetMethods({ + @TargetMethod(name = "registerOutParameter", paramTypes = {"int", "int"}), + @TargetMethod(name = "registerOutParameter", paramTypes = {"int", "int", "int"}), + @TargetMethod(name = "registerOutParameter", paramTypes = {"int", "int", "java.lang.String"}) +}) +public class CallableStatementRegisterOutParameterInterceptor extends SpanEventSimpleAroundInterceptorForPlugin { + + public CallableStatementRegisterOutParameterInterceptor(TraceContext traceContext, MethodDescriptor descriptor) { + super(traceContext, descriptor); + } + + @Override + protected void doInBeforeTrace(SpanEventRecorder recorder, Object target, Object[] args) { + } + + @Override + protected void doInAfterTrace(SpanEventRecorder recorder, Object target, Object[] args, Object result, Throwable throwable) { + DatabaseInfo databaseInfo = (target instanceof DatabaseInfoAccessor) ? ((DatabaseInfoAccessor)target)._$PINPOINT$_getDatabaseInfo() : null; + + if (databaseInfo == null) { + databaseInfo = UnKnownDatabaseInfo.INSTANCE; + } + + recorder.recordServiceType(databaseInfo.getType()); + recorder.recordEndPoint(databaseInfo.getMultipleHost()); + recorder.recordDestinationId(databaseInfo.getDatabaseId()); + + recorder.recordApi(methodDescriptor, args); + recorder.recordException(throwable); + } +} diff --git a/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/PreparedStatementCreateInterceptor.java b/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/PreparedStatementCreateInterceptor.java index 47b317fbb..5cae250b0 100644 --- a/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/PreparedStatementCreateInterceptor.java +++ b/bootstrap-core/src/main/java/com/navercorp/pinpoint/bootstrap/plugin/jdbc/interceptor/PreparedStatementCreateInterceptor.java @@ -38,7 +38,10 @@ import com.navercorp.pinpoint.bootstrap.util.InterceptorUtils; @TargetMethod(name="prepareStatement", paramTypes={ "java.lang.String", "int[]" }), @TargetMethod(name="prepareStatement", paramTypes={ "java.lang.String", "java.lang.String[]" }), @TargetMethod(name="prepareStatement", paramTypes={ "java.lang.String", "int", "int" }), - @TargetMethod(name="prepareStatement", paramTypes={ "java.lang.String", "int", "int", "int" }) + @TargetMethod(name="prepareStatement", paramTypes={ "java.lang.String", "int", "int", "int" }), + @TargetMethod(name="prepareCall", paramTypes={ "java.lang.String" }), + @TargetMethod(name="prepareCall", paramTypes={ "java.lang.String", "int", "int" }), + @TargetMethod(name="prepareCall", paramTypes={ "java.lang.String", "int", "int", "int" }) }) public class PreparedStatementCreateInterceptor extends SpanEventSimpleAroundInterceptorForPlugin { diff --git a/plugins/cubrid-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/cubrid/CubridPlugin.java b/plugins/cubrid-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/cubrid/CubridPlugin.java index ee1b31a7a..1af6bd882 100644 --- a/plugins/cubrid-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/cubrid/CubridPlugin.java +++ b/plugins/cubrid-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/cubrid/CubridPlugin.java @@ -43,6 +43,7 @@ public class CubridPlugin implements ProfilerPlugin, TransformTemplateAware { addCUBRIDConnectionTransformer(config); addCUBRIDDriverTransformer(); addCUBRIDPreparedStatementTransformer(config); + addCUBRIDCallableStatementTransformer(); addCUBRIDStatementTransformer(); } @@ -113,6 +114,24 @@ public class CubridPlugin implements ProfilerPlugin, TransformTemplateAware { } }); } + + private void addCUBRIDCallableStatementTransformer() { + transformTemplate.transform("cubrid.jdbc.driver.CUBRIDCallableStatement", new TransformCallback() { + + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); + + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.DatabaseInfoAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.ParsingResultAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.BindValueAccessor"); + + target.addScopedInterceptor("com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementRegisterOutParameterInterceptor", CubridConstants.CUBRID_SCOPE); + + return target.toBytecode(); + } + }); + } private void addCUBRIDStatementTransformer() { transformTemplate.transform("cubrid.jdbc.driver.CUBRIDStatement", new TransformCallback() { diff --git a/plugins/jtds/src/main/java/com/navercorp/pinpoint/plugin/jdbc/jtds/JtdsPlugin.java b/plugins/jtds/src/main/java/com/navercorp/pinpoint/plugin/jdbc/jtds/JtdsPlugin.java index ff21ffd6a..477397592 100644 --- a/plugins/jtds/src/main/java/com/navercorp/pinpoint/plugin/jdbc/jtds/JtdsPlugin.java +++ b/plugins/jtds/src/main/java/com/navercorp/pinpoint/plugin/jdbc/jtds/JtdsPlugin.java @@ -42,6 +42,7 @@ public class JtdsPlugin implements ProfilerPlugin, TransformTemplateAware { addConnectionTransformer(config); addDriverTransformer(); addPreparedStatementTransformer(config); + addCallableStatementTransformer(); addStatementTransformer(); } @@ -115,6 +116,24 @@ public class JtdsPlugin implements ProfilerPlugin, TransformTemplateAware { }); } + private void addCallableStatementTransformer() { + transformTemplate.transform("net.sourceforge.jtds.jdbc.JtdsCallableStatement", new TransformCallback() { + + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); + + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.DatabaseInfoAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.ParsingResultAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.BindValueAccessor"); + + target.addScopedInterceptor("com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementRegisterOutParameterInterceptor", JtdsConstants.JTDS_SCOPE); + + return target.toBytecode(); + } + }); + } + private void addStatementTransformer() { transformTemplate.transform("net.sourceforge.jtds.jdbc.JtdsStatement", new TransformCallback() { diff --git a/plugins/mariadb-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDBPlugin.java b/plugins/mariadb-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDBPlugin.java index b594f217f..590c4abc5 100644 --- a/plugins/mariadb-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDBPlugin.java +++ b/plugins/mariadb-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/mariadb/MariaDBPlugin.java @@ -44,7 +44,12 @@ public class MariaDBPlugin implements ProfilerPlugin, TransformTemplateAware { addDriverTransformer(); addPreparedStatementTransformer(config); addPreparedStatementBindVariableTransformer(config); + addCallableStatementTransformer(); addStatementTransformer(); + + // MariaDb 1.3.x's CallableStatements are completely separated from PreparedStatements (similar to MySQL) + // Separate interceptors must be injected. + add_1_3_x_CallableStatementTransformer(config); } private void addConnectionTransformer(final MariaDBConfig config) { @@ -206,6 +211,54 @@ public class MariaDBPlugin implements ProfilerPlugin, TransformTemplateAware { } + private void addCallableStatementTransformer() { + TransformCallback transformer = new TransformCallback() { + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, + Class classBeingRedefined, ProtectionDomain protectionDomain, + byte[] classfileBuffer) throws InstrumentException { + InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); + + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.DatabaseInfoAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.ParsingResultAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.BindValueAccessor"); + + target.addScopedInterceptor("com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementRegisterOutParameterInterceptor", MariaDBConstants.MARIADB_SCOPE); + + return target.toBytecode(); + } + }; + + transformTemplate.transform("org.mariadb.jdbc.AbstractCallableProcedureStatement", transformer); + transformTemplate.transform("org.mariadb.jdbc.AbstractCallableFunctionStatement", transformer); + } + + private void add_1_3_x_CallableStatementTransformer(final MariaDBConfig config) { + transformTemplate.transform("org.mariadb.jdbc.MariaDbCallableStatement", new TransformCallback() { + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, + Class classBeingRedefined, ProtectionDomain protectionDomain, + byte[] classfileBuffer) throws InstrumentException { + InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); + + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.DatabaseInfoAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.ParsingResultAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.BindValueAccessor"); + + int maxBindValueSize = config.getMaxSqlBindValueSize(); + + target.addScopedInterceptor("com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementExecuteQueryInterceptor", va(maxBindValueSize), MariaDBConstants.MARIADB_SCOPE); + target.addScopedInterceptor("com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementRegisterOutParameterInterceptor", MariaDBConstants.MARIADB_SCOPE); + + if (config.isTraceSqlBindValue()) { + target.addScopedInterceptor("com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementBindVariableInterceptor", MariaDBConstants.MARIADB_SCOPE); + } + + return target.toBytecode(); + } + }); + } + @Override public void setTransformTemplate(TransformTemplate transformTemplate) { this.transformTemplate = transformTemplate; diff --git a/plugins/mysql-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/mysql/MySqlPlugin.java b/plugins/mysql-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/mysql/MySqlPlugin.java index ba7308589..58d668c4c 100644 --- a/plugins/mysql-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/mysql/MySqlPlugin.java +++ b/plugins/mysql-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/mysql/MySqlPlugin.java @@ -44,10 +44,12 @@ public class MySqlPlugin implements ProfilerPlugin, TransformTemplateAware { addDriverTransformer(); addStatementTransformer(); addPreparedStatementTransformer(config); + addCallableStatementTransformer(config); // From MySQL driver 5.1.x, backward compatibility is broken. // Driver returns not com.mysql.jdbc.Connection but com.mysql.jdbc.JDBC4Connection which extends com.mysql.jdbc.ConnectionImpl from 5.1.x addJDBC4PreparedStatementTransformer(config); + addJDBC4CallableStatementTransformer(config); } private void addConnectionTransformer(final MySqlConfig config) { @@ -127,6 +129,32 @@ public class MySqlPlugin implements ProfilerPlugin, TransformTemplateAware { }); } + private void addCallableStatementTransformer(final MySqlConfig config) { + transformTemplate.transform("com.mysql.jdbc.CallableStatement", new TransformCallback() { + + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); + + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.DatabaseInfoAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.ParsingResultAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.BindValueAccessor"); + + int maxBindValueSize = config.getMaxSqlBindValueSize(); + + target.addScopedInterceptor("com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementExecuteQueryInterceptor", va(maxBindValueSize), MySqlConstants.MYSQL_SCOPE); + target.addScopedInterceptor("com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementRegisterOutParameterInterceptor", MySqlConstants.MYSQL_SCOPE); + + if (config.isTraceSqlBindValue()) { + final PreparedStatementBindingMethodFilter excludes = PreparedStatementBindingMethodFilter.excludes("setRowId", "setNClob", "setSQLXML"); + target.addScopedInterceptor(excludes, "com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementBindVariableInterceptor", MySqlConstants.MYSQL_SCOPE, ExecutionPolicy.BOUNDARY); + } + + return target.toBytecode(); + } + }); + } + private void addJDBC4PreparedStatementTransformer(final MySqlConfig config) { transformTemplate.transform("com.mysql.jdbc.JDBC4PreparedStatement", new TransformCallback() { @@ -144,6 +172,22 @@ public class MySqlPlugin implements ProfilerPlugin, TransformTemplateAware { }); } + private void addJDBC4CallableStatementTransformer(final MySqlConfig config) { + transformTemplate.transform("com.mysql.jdbc.JDBC4CallableStatement", new TransformCallback() { + + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); + + if (config.isTraceSqlBindValue()) { + final PreparedStatementBindingMethodFilter includes = PreparedStatementBindingMethodFilter.includes("setRowId", "setNClob", "setSQLXML"); + target.addScopedInterceptor(includes, "com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementBindVariableInterceptor", MySqlConstants.MYSQL_SCOPE, ExecutionPolicy.BOUNDARY); + } + + return target.toBytecode(); + } + }); + } private void addStatementTransformer() { TransformCallback transformer = new TransformCallback() { diff --git a/plugins/oracle-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/oracle/OraclePlugin.java b/plugins/oracle-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/oracle/OraclePlugin.java index acd14910e..452a53a51 100644 --- a/plugins/oracle-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/oracle/OraclePlugin.java +++ b/plugins/oracle-jdbc/src/main/java/com/navercorp/pinpoint/plugin/jdbc/oracle/OraclePlugin.java @@ -37,6 +37,8 @@ public class OraclePlugin implements ProfilerPlugin, TransformTemplateAware { private static final String CLASS_STATEMENT = "oracle.jdbc.driver.OracleStatement"; private static final String CLASS_PREPARED_STATEMENT_WRAPPER = "oracle.jdbc.driver.OraclePreparedStatementWrapper"; private static final String CLASS_PREPARED_STATEMENT = "oracle.jdbc.driver.OraclePreparedStatement"; + private static final String CLASS_CALLABLE_STATEMENT_WRAPPER = "oracle.jdbc.driver.OracleCallableStatementWrapper"; + private static final String CLASS_CALLABLE_STATEMENT = "oracle.jdbc.driver.OracleCallableStatement"; private TransformTemplate transformTemplate; @@ -47,6 +49,7 @@ public class OraclePlugin implements ProfilerPlugin, TransformTemplateAware { addConnectionTransformer(config); addDriverTransformer(); addPreparedStatementTransformer(config); + addCallableStatementTransformer(); addStatementTransformer(); } @@ -128,6 +131,32 @@ public class OraclePlugin implements ProfilerPlugin, TransformTemplateAware { transformTemplate.transform(CLASS_PREPARED_STATEMENT_WRAPPER, transformer); } + private void addCallableStatementTransformer() { + TransformCallback transformer = new TransformCallback() { + + @Override + public byte[] doInTransform(Instrumentor instrumentor, ClassLoader loader, String className, Class classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws InstrumentException { + InstrumentClass target = instrumentor.getInstrumentClass(loader, className, classfileBuffer); + if (className.equals(CLASS_CALLABLE_STATEMENT)) { + if (instrumentor.exist(loader, CLASS_CALLABLE_STATEMENT_WRAPPER)) { + return null; + } + } + + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.DatabaseInfoAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.ParsingResultAccessor"); + target.addField("com.navercorp.pinpoint.bootstrap.plugin.jdbc.BindValueAccessor"); + + target.addScopedInterceptor("com.navercorp.pinpoint.bootstrap.plugin.jdbc.interceptor.CallableStatementRegisterOutParameterInterceptor", OracleConstants.ORACLE_SCOPE); + + return target.toBytecode(); + } + }; + + transformTemplate.transform(CLASS_CALLABLE_STATEMENT, transformer); + transformTemplate.transform(CLASS_CALLABLE_STATEMENT_WRAPPER, transformer); + } + private void addStatementTransformer() { TransformCallback transformer = new TransformCallback() {