diff --git a/agent/pom.xml b/agent/pom.xml index e68db91..a25dd04 100644 --- a/agent/pom.xml +++ b/agent/pom.xml @@ -76,13 +76,26 @@ test - + + org.junit.jupiter junit-jupiter-engine - 5.4.0 + 5.9.0 test + + + + + org.junit.platform + junit-platform-suite-engine + 1.9.0 + test + + + + \ No newline at end of file diff --git a/agent/src/main/java/com/fanruan/AgentStarter.java b/agent/src/main/java/com/fanruan/AgentStarter.java index e68b393..f65d283 100644 --- a/agent/src/main/java/com/fanruan/AgentStarter.java +++ b/agent/src/main/java/com/fanruan/AgentStarter.java @@ -16,6 +16,7 @@ import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; import java.net.URI; +import java.util.List; import java.util.Properties; import java.util.concurrent.TimeUnit; @@ -37,7 +38,6 @@ public class AgentStarter { dispatcherImpl = new DispatcherImpl(); try { createSocket(DBs); - } catch (Exception e) { e.printStackTrace(); } @@ -94,6 +94,13 @@ public class AgentStarter { } } + public void shutDown(){ + List sockets = DispatcherImpl.CACHE.getSockets(); + for(Socket socket : sockets){ + socket.close(); + } + } + private void configDefaultSocket(Socket socket) throws IOException { socket.on(Socket.EVENT_CONNECT, objects -> { logger.info("default-socket connected!"); diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentArray.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentArray.java new file mode 100644 index 0000000..c8af6c6 --- /dev/null +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentArray.java @@ -0,0 +1,73 @@ +package com.fanruan.agent.jdbc; + +import java.sql.Array; +import java.sql.ResultSet; +import java.sql.SQLException; +import java.util.Map; + +/** + * @author Yichen Dai + * @date 2022/8/31 16:52 + */ +public class AgentArray implements Array { + Array array; + + AgentArray(Array array){ + this.array = array; + } + + @Override + public String getBaseTypeName() throws SQLException { + return array.getBaseTypeName(); + } + + @Override + public int getBaseType() throws SQLException { + return array.getBaseType(); + } + + @Override + public Object getArray() throws SQLException { + return array.getArray(); + } + + @Override + public Object getArray(Map> map) throws SQLException { + return array.getArray(map); + } + + @Override + public Object getArray(long index, int count) throws SQLException { + return array.getArray(index, count); + } + + @Override + public Object getArray(long index, int count, Map> map) throws SQLException { + return array.getArray(index, count, map); + } + + @Override + public ResultSet getResultSet() throws SQLException { + return array.getResultSet(); + } + + @Override + public ResultSet getResultSet(Map> map) throws SQLException { + return array.getResultSet(map); + } + + @Override + public ResultSet getResultSet(long index, int count) throws SQLException { + return array.getResultSet(index, count); + } + + @Override + public ResultSet getResultSet(long index, int count, Map> map) throws SQLException { + return array.getResultSet(index, count, map); + } + + @Override + public void free() throws SQLException { + array.free(); + } +} diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentBlob.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentBlob.java new file mode 100644 index 0000000..16f2b78 --- /dev/null +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentBlob.java @@ -0,0 +1,73 @@ +package com.fanruan.agent.jdbc; + +import java.io.InputStream; +import java.io.OutputStream; +import java.sql.Blob; +import java.sql.SQLException; + +/** + * @author Yichen Dai + * @date 2022/8/29 20:33 + */ +public class AgentBlob implements Blob { + private Blob blob; + + AgentBlob(Blob blob){ + this.blob = blob; + } + + @Override + public long length() throws SQLException { + return blob.length(); + } + + @Override + public byte[] getBytes(long pos, int length) throws SQLException { + return blob.getBytes(pos, length); + } + + @Override + public InputStream getBinaryStream() throws SQLException { + return blob.getBinaryStream(); + } + + @Override + public long position(byte[] pattern, long start) throws SQLException { + return blob.position(pattern, start); + } + + @Override + public long position(Blob pattern, long start) throws SQLException { + return blob.position(pattern, start); + } + + @Override + public int setBytes(long pos, byte[] bytes) throws SQLException { + return blob.setBytes(pos, bytes); + } + + @Override + public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { + return blob.setBytes(pos, bytes, offset, len); + } + + @Override + public OutputStream setBinaryStream(long pos) throws SQLException { + return blob.setBinaryStream(pos); + } + + @Override + public void truncate(long len) throws SQLException { + blob.truncate(len); + } + + @Override + public void free() throws SQLException { + blob.free(); + } + + @Override + public InputStream getBinaryStream(long pos, long length) throws SQLException { + return blob.getBinaryStream(pos, length); + } +} diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentClob.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentClob.java new file mode 100644 index 0000000..604bd74 --- /dev/null +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentClob.java @@ -0,0 +1,85 @@ +package com.fanruan.agent.jdbc; + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.sql.Clob; +import java.sql.SQLException; + +/** + * @author Yichen Dai + * @date 2022/8/29 20:34 + */ +public class AgentClob implements Clob { + private Clob clob; + + AgentClob(Clob clob){ + this.clob = clob; + } + + @Override + public long length() throws SQLException { + return clob.length(); + } + + @Override + public String getSubString(long pos, int length) throws SQLException { + return clob.getSubString(pos, length); + } + + @Override + public Reader getCharacterStream() throws SQLException { + return clob.getCharacterStream(); + } + + @Override + public InputStream getAsciiStream() throws SQLException { + return clob.getAsciiStream(); + } + + @Override + public long position(String searchstr, long start) throws SQLException { + return clob.position(searchstr, start); + } + + @Override + public long position(Clob searchstr, long start) throws SQLException { + return clob.position(searchstr, start); + } + + @Override + public int setString(long pos, String str) throws SQLException { + return clob.setString(pos, str); + } + + @Override + public int setString(long pos, String str, int offset, int len) throws SQLException { + return clob.setString(pos, str, offset, len); + } + + @Override + public OutputStream setAsciiStream(long pos) throws SQLException { + return clob.setAsciiStream(pos); + } + + @Override + public Writer setCharacterStream(long pos) throws SQLException { + return clob.setCharacterStream(pos); + } + + @Override + public void truncate(long len) throws SQLException { + clob.truncate(len); + } + + @Override + public void free() throws SQLException { + clob.free(); + } + + @Override + public Reader getCharacterStream(long pos, long length) throws SQLException { + return clob.getCharacterStream(pos, length); + } +} diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentDataBaseMetaData.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentDataBaseMetaData.java new file mode 100644 index 0000000..d9ff58b --- /dev/null +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentDataBaseMetaData.java @@ -0,0 +1,895 @@ +package com.fanruan.agent.jdbc; + +import java.sql.*; + +/** + * @author Yichen Dai + * @date 2022/8/25 11:22 + */ +public class AgentDataBaseMetaData implements DatabaseMetaData { + DatabaseMetaData metaData; + + public AgentDataBaseMetaData(DatabaseMetaData metaData){ + this.metaData = metaData; + } + + @Override + public boolean allProceduresAreCallable() throws SQLException { + return metaData.allProceduresAreCallable(); + } + + @Override + public boolean allTablesAreSelectable() throws SQLException { + return metaData.allTablesAreSelectable(); + } + + @Override + public String getURL() throws SQLException { + return metaData.getURL(); + } + + @Override + public String getUserName() throws SQLException { + return metaData.getUserName(); + } + + @Override + public boolean isReadOnly() throws SQLException { + return metaData.isReadOnly(); + } + + @Override + public boolean nullsAreSortedHigh() throws SQLException { + return metaData.nullsAreSortedHigh(); + } + + @Override + public boolean nullsAreSortedLow() throws SQLException { + return metaData.nullsAreSortedLow(); + } + + @Override + public boolean nullsAreSortedAtStart() throws SQLException { + return metaData.nullsAreSortedAtStart(); + } + + @Override + public boolean nullsAreSortedAtEnd() throws SQLException { + return metaData.nullsAreSortedAtStart(); + } + + @Override + public String getDatabaseProductName() throws SQLException { + return metaData.getDatabaseProductName(); + } + + @Override + public String getDatabaseProductVersion() throws SQLException { + return metaData.getDatabaseProductVersion(); + } + + @Override + public String getDriverName() throws SQLException { + return metaData.getDriverName(); + } + + @Override + public String getDriverVersion() throws SQLException { + return metaData.getDriverVersion(); + } + + @Override + public int getDriverMajorVersion() { + return metaData.getDriverMajorVersion(); + } + + @Override + public int getDriverMinorVersion() { + return metaData.getDriverMinorVersion(); + } + + @Override + public boolean usesLocalFiles() throws SQLException { + return metaData.usesLocalFiles(); + } + + @Override + public boolean usesLocalFilePerTable() throws SQLException { + return metaData.usesLocalFilePerTable(); + } + + @Override + public boolean supportsMixedCaseIdentifiers() throws SQLException { + return metaData.supportsMixedCaseIdentifiers(); + } + + @Override + public boolean storesUpperCaseIdentifiers() throws SQLException { + return metaData.storesUpperCaseIdentifiers(); + } + + @Override + public boolean storesLowerCaseIdentifiers() throws SQLException { + return metaData.storesLowerCaseIdentifiers(); + } + + @Override + public boolean storesMixedCaseIdentifiers() throws SQLException { + return metaData.supportsMixedCaseIdentifiers(); + } + + @Override + public boolean supportsMixedCaseQuotedIdentifiers() throws SQLException { + return metaData.supportsMixedCaseQuotedIdentifiers(); + } + + @Override + public boolean storesUpperCaseQuotedIdentifiers() throws SQLException { + return metaData.storesUpperCaseQuotedIdentifiers(); + } + + @Override + public boolean storesLowerCaseQuotedIdentifiers() throws SQLException { + return metaData.storesLowerCaseQuotedIdentifiers(); + } + + @Override + public boolean storesMixedCaseQuotedIdentifiers() throws SQLException { + return metaData.supportsMixedCaseQuotedIdentifiers(); + } + + @Override + public String getIdentifierQuoteString() throws SQLException { + return metaData.getIdentifierQuoteString(); + } + + @Override + public String getSQLKeywords() throws SQLException { + return metaData.getSQLKeywords(); + } + + @Override + public String getNumericFunctions() throws SQLException { + return metaData.getNumericFunctions(); + } + + @Override + public String getStringFunctions() throws SQLException { + return metaData.getStringFunctions(); + } + + @Override + public String getSystemFunctions() throws SQLException { + return metaData.getSystemFunctions(); + } + + @Override + public String getTimeDateFunctions() throws SQLException { + return metaData.getTimeDateFunctions(); + } + + @Override + public String getSearchStringEscape() throws SQLException { + return metaData.getSearchStringEscape(); + } + + @Override + public String getExtraNameCharacters() throws SQLException { + return metaData.getExtraNameCharacters(); + } + + @Override + public boolean supportsAlterTableWithAddColumn() throws SQLException { + return metaData.supportsAlterTableWithAddColumn(); + } + + @Override + public boolean supportsAlterTableWithDropColumn() throws SQLException { + return metaData.supportsAlterTableWithDropColumn(); + } + + @Override + public boolean supportsColumnAliasing() throws SQLException { + return metaData.supportsColumnAliasing(); + } + + @Override + public boolean nullPlusNonNullIsNull() throws SQLException { + return metaData.nullPlusNonNullIsNull(); + } + + @Override + public boolean supportsConvert() throws SQLException { + return metaData.supportsConvert(); + } + + @Override + public boolean supportsConvert(int fromType, int toType) throws SQLException { + return metaData.supportsConvert(); + } + + @Override + public boolean supportsTableCorrelationNames() throws SQLException { + return metaData.supportsTableCorrelationNames(); + } + + @Override + public boolean supportsDifferentTableCorrelationNames() throws SQLException { + return metaData.supportsDifferentTableCorrelationNames(); + } + + @Override + public boolean supportsExpressionsInOrderBy() throws SQLException { + return metaData.supportsExpressionsInOrderBy(); + } + + @Override + public boolean supportsOrderByUnrelated() throws SQLException { + return metaData.supportsOrderByUnrelated(); + } + + @Override + public boolean supportsGroupBy() throws SQLException { + return metaData.supportsGroupBy(); + } + + @Override + public boolean supportsGroupByUnrelated() throws SQLException { + return metaData.supportsGroupByUnrelated(); + } + + @Override + public boolean supportsGroupByBeyondSelect() throws SQLException { + return metaData.supportsGroupByBeyondSelect(); + } + + @Override + public boolean supportsLikeEscapeClause() throws SQLException { + return metaData.supportsLikeEscapeClause(); + } + + @Override + public boolean supportsMultipleResultSets() throws SQLException { + return metaData.supportsMultipleResultSets(); + } + + @Override + public boolean supportsMultipleTransactions() throws SQLException { + return metaData.supportsMultipleTransactions(); + } + + @Override + public boolean supportsNonNullableColumns() throws SQLException { + return metaData.supportsNonNullableColumns(); + } + + @Override + public boolean supportsMinimumSQLGrammar() throws SQLException { + return metaData.supportsMinimumSQLGrammar(); + } + + @Override + public boolean supportsCoreSQLGrammar() throws SQLException { + return metaData.supportsCoreSQLGrammar(); + } + + @Override + public boolean supportsExtendedSQLGrammar() throws SQLException { + return metaData.supportsExtendedSQLGrammar(); + } + + @Override + public boolean supportsANSI92EntryLevelSQL() throws SQLException { + return metaData.supportsANSI92EntryLevelSQL(); + } + + @Override + public boolean supportsANSI92IntermediateSQL() throws SQLException { + return metaData.supportsANSI92IntermediateSQL(); + } + + @Override + public boolean supportsANSI92FullSQL() throws SQLException { + return metaData.supportsANSI92FullSQL(); + } + + @Override + public boolean supportsIntegrityEnhancementFacility() throws SQLException { + return metaData.supportsIntegrityEnhancementFacility(); + } + + @Override + public boolean supportsOuterJoins() throws SQLException { + return metaData.supportsOuterJoins(); + } + + @Override + public boolean supportsFullOuterJoins() throws SQLException { + return metaData.supportsFullOuterJoins(); + } + + @Override + public boolean supportsLimitedOuterJoins() throws SQLException { + return metaData.supportsLimitedOuterJoins(); + } + + @Override + public String getSchemaTerm() throws SQLException { + return metaData.getSchemaTerm(); + } + + @Override + public String getProcedureTerm() throws SQLException { + return metaData.getProcedureTerm(); + } + + @Override + public String getCatalogTerm() throws SQLException { + return metaData.getCatalogTerm(); + } + + @Override + public boolean isCatalogAtStart() throws SQLException { + return metaData.isCatalogAtStart(); + } + + @Override + public String getCatalogSeparator() throws SQLException { + return metaData.getCatalogSeparator(); + } + + @Override + public boolean supportsSchemasInDataManipulation() throws SQLException { + return metaData.supportsSchemasInDataManipulation(); + } + + @Override + public boolean supportsSchemasInProcedureCalls() throws SQLException { + return metaData.supportsSchemasInProcedureCalls(); + } + + @Override + public boolean supportsSchemasInTableDefinitions() throws SQLException { + return metaData.supportsSchemasInTableDefinitions(); + } + + @Override + public boolean supportsSchemasInIndexDefinitions() throws SQLException { + return metaData.supportsSchemasInIndexDefinitions(); + } + + @Override + public boolean supportsSchemasInPrivilegeDefinitions() throws SQLException { + return metaData.supportsSchemasInPrivilegeDefinitions(); + } + + @Override + public boolean supportsCatalogsInDataManipulation() throws SQLException { + return metaData.supportsCatalogsInDataManipulation(); + } + + @Override + public boolean supportsCatalogsInProcedureCalls() throws SQLException { + return metaData.supportsCatalogsInProcedureCalls(); + } + + @Override + public boolean supportsCatalogsInTableDefinitions() throws SQLException { + return metaData.supportsCatalogsInTableDefinitions(); + } + + @Override + public boolean supportsCatalogsInIndexDefinitions() throws SQLException { + return metaData.supportsCatalogsInIndexDefinitions(); + } + + @Override + public boolean supportsCatalogsInPrivilegeDefinitions() throws SQLException { + return metaData.supportsCatalogsInPrivilegeDefinitions(); + } + + @Override + public boolean supportsPositionedDelete() throws SQLException { + return metaData.supportsPositionedDelete(); + } + + @Override + public boolean supportsPositionedUpdate() throws SQLException { + return metaData.supportsPositionedUpdate(); + } + + @Override + public boolean supportsSelectForUpdate() throws SQLException { + return metaData.supportsSelectForUpdate(); + } + + @Override + public boolean supportsStoredProcedures() throws SQLException { + return metaData.supportsStoredProcedures(); + } + + @Override + public boolean supportsSubqueriesInComparisons() throws SQLException { + return metaData.supportsSubqueriesInComparisons(); + } + + @Override + public boolean supportsSubqueriesInExists() throws SQLException { + return metaData.supportsSubqueriesInExists(); + } + + @Override + public boolean supportsSubqueriesInIns() throws SQLException { + return metaData.supportsSubqueriesInIns(); + } + + @Override + public boolean supportsSubqueriesInQuantifieds() throws SQLException { + return metaData.supportsSubqueriesInQuantifieds(); + } + + @Override + public boolean supportsCorrelatedSubqueries() throws SQLException { + return metaData.supportsCorrelatedSubqueries(); + } + + @Override + public boolean supportsUnion() throws SQLException { + return metaData.supportsUnion(); + } + + @Override + public boolean supportsUnionAll() throws SQLException { + return metaData.supportsUnionAll(); + } + + @Override + public boolean supportsOpenCursorsAcrossCommit() throws SQLException { + return metaData.supportsOpenCursorsAcrossCommit(); + } + + @Override + public boolean supportsOpenCursorsAcrossRollback() throws SQLException { + return metaData.supportsOpenCursorsAcrossRollback(); + } + + @Override + public boolean supportsOpenStatementsAcrossCommit() throws SQLException { + return metaData.supportsOpenStatementsAcrossCommit(); + } + + @Override + public boolean supportsOpenStatementsAcrossRollback() throws SQLException { + return metaData.supportsOpenStatementsAcrossRollback(); + } + + @Override + public int getMaxBinaryLiteralLength() throws SQLException { + return metaData.getMaxBinaryLiteralLength(); + } + + @Override + public int getMaxCharLiteralLength() throws SQLException { + return metaData.getMaxCharLiteralLength(); + } + + @Override + public int getMaxColumnNameLength() throws SQLException { + return metaData.getMaxColumnNameLength(); + } + + @Override + public int getMaxColumnsInGroupBy() throws SQLException { + return metaData.getMaxColumnsInGroupBy(); + } + + @Override + public int getMaxColumnsInIndex() throws SQLException { + return metaData.getMaxColumnsInIndex(); + } + + @Override + public int getMaxColumnsInOrderBy() throws SQLException { + return metaData.getMaxColumnsInOrderBy(); + } + + @Override + public int getMaxColumnsInSelect() throws SQLException { + return metaData.getMaxColumnsInSelect(); + } + + @Override + public int getMaxColumnsInTable() throws SQLException { + return metaData.getMaxColumnsInTable(); + } + + @Override + public int getMaxConnections() throws SQLException { + return metaData.getMaxConnections(); + } + + @Override + public int getMaxCursorNameLength() throws SQLException { + return metaData.getMaxCursorNameLength(); + } + + @Override + public int getMaxIndexLength() throws SQLException { + return metaData.getMaxIndexLength(); + } + + @Override + public int getMaxSchemaNameLength() throws SQLException { + return metaData.getMaxSchemaNameLength(); + } + + @Override + public int getMaxProcedureNameLength() throws SQLException { + return metaData.getMaxProcedureNameLength(); + } + + @Override + public int getMaxCatalogNameLength() throws SQLException { + return metaData.getMaxCatalogNameLength(); + } + + @Override + public int getMaxRowSize() throws SQLException { + return metaData.getMaxRowSize(); + } + + @Override + public boolean doesMaxRowSizeIncludeBlobs() throws SQLException { + return metaData.doesMaxRowSizeIncludeBlobs(); + } + + @Override + public int getMaxStatementLength() throws SQLException { + return metaData.getMaxStatementLength(); + } + + @Override + public int getMaxStatements() throws SQLException { + return metaData.getMaxStatements(); + } + + @Override + public int getMaxTableNameLength() throws SQLException { + return metaData.getMaxTableNameLength(); + } + + @Override + public int getMaxTablesInSelect() throws SQLException { + return metaData.getMaxTablesInSelect(); + } + + @Override + public int getMaxUserNameLength() throws SQLException { + return metaData.getMaxUserNameLength(); + } + + @Override + public int getDefaultTransactionIsolation() throws SQLException { + return metaData.getDefaultTransactionIsolation(); + } + + @Override + public boolean supportsTransactions() throws SQLException { + return metaData.supportsTransactions(); + } + + @Override + public boolean supportsTransactionIsolationLevel(int level) throws SQLException { + return metaData.supportsTransactionIsolationLevel(level); + } + + @Override + public boolean supportsDataDefinitionAndDataManipulationTransactions() throws SQLException { + return metaData.supportsDataDefinitionAndDataManipulationTransactions(); + } + + @Override + public boolean supportsDataManipulationTransactionsOnly() throws SQLException { + return metaData.supportsDataManipulationTransactionsOnly(); + } + + @Override + public boolean dataDefinitionCausesTransactionCommit() throws SQLException { + return metaData.dataDefinitionCausesTransactionCommit(); + } + + @Override + public boolean dataDefinitionIgnoredInTransactions() throws SQLException { + return metaData.dataDefinitionIgnoredInTransactions(); + } + + @Override + public ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException { + return metaData.getProcedures(catalog, schemaPattern, procedureNamePattern); + } + + @Override + public ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException { + return metaData.getProcedureColumns(catalog, schemaPattern, procedureNamePattern, columnNamePattern); + } + + @Override + public ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String[] types) throws SQLException { + return metaData.getTables(catalog, schemaPattern, tableNamePattern, types); + } + + @Override + public ResultSet getSchemas() throws SQLException { + return metaData.getSchemas(); + } + + @Override + public ResultSet getCatalogs() throws SQLException { + return metaData.getCatalogs(); + } + + @Override + public ResultSet getTableTypes() throws SQLException { + return metaData.getTableTypes(); + } + + @Override + public ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { + return metaData.getColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); + } + + @Override + public ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException { + return metaData.getColumnPrivileges(catalog, schema, table, columnNamePattern); + } + + @Override + public ResultSet getTablePrivileges(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { + return metaData.getTablePrivileges(catalog, schemaPattern, tableNamePattern); + } + + @Override + public ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException { + return metaData.getBestRowIdentifier(catalog, schema, table, scope, nullable); + } + + @Override + public ResultSet getVersionColumns(String catalog, String schema, String table) throws SQLException { + return metaData.getVersionColumns(catalog, schema, table); + } + + @Override + public ResultSet getPrimaryKeys(String catalog, String schema, String table) throws SQLException { + return metaData.getPrimaryKeys(catalog, schema, table); + } + + @Override + public ResultSet getImportedKeys(String catalog, String schema, String table) throws SQLException { + return metaData.getImportedKeys(catalog, schema, table); + } + + @Override + public ResultSet getExportedKeys(String catalog, String schema, String table) throws SQLException { + return metaData.getExportedKeys(catalog, schema, table); + } + + @Override + public ResultSet getCrossReference(String parentCatalog, String parentSchema, String parentTable, String foreignCatalog, String foreignSchema, String foreignTable) throws SQLException { + return metaData.getCrossReference(parentCatalog, parentSchema, parentTable, foreignCatalog, foreignSchema, foreignTable); + } + + @Override + public ResultSet getTypeInfo() throws SQLException { + return metaData.getTypeInfo(); + } + + @Override + public ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException { + return metaData.getIndexInfo(catalog, schema, table, unique, approximate); + } + + @Override + public boolean supportsResultSetType(int type) throws SQLException { + return metaData.supportsResultSetType(type); + } + + @Override + public boolean supportsResultSetConcurrency(int type, int concurrency) throws SQLException { + return metaData.supportsResultSetConcurrency(type, concurrency); + } + + @Override + public boolean ownUpdatesAreVisible(int type) throws SQLException { + return metaData.ownUpdatesAreVisible(type); + } + + @Override + public boolean ownDeletesAreVisible(int type) throws SQLException { + return metaData.ownDeletesAreVisible(type); + } + + @Override + public boolean ownInsertsAreVisible(int type) throws SQLException { + return metaData.ownInsertsAreVisible(type); + } + + @Override + public boolean othersUpdatesAreVisible(int type) throws SQLException { + return metaData.othersUpdatesAreVisible(type); + } + + @Override + public boolean othersDeletesAreVisible(int type) throws SQLException { + return metaData.othersDeletesAreVisible(type); + } + + @Override + public boolean othersInsertsAreVisible(int type) throws SQLException { + return metaData.othersInsertsAreVisible(type); + } + + @Override + public boolean updatesAreDetected(int type) throws SQLException { + return metaData.updatesAreDetected(type); + } + + @Override + public boolean deletesAreDetected(int type) throws SQLException { + return metaData.deletesAreDetected(type); + } + + @Override + public boolean insertsAreDetected(int type) throws SQLException { + return metaData.insertsAreDetected(type); + } + + @Override + public boolean supportsBatchUpdates() throws SQLException { + return metaData.supportsBatchUpdates(); + } + + @Override + public ResultSet getUDTs(String catalog, String schemaPattern, String typeNamePattern, int[] types) throws SQLException { + return metaData.getUDTs(catalog, schemaPattern, typeNamePattern, types); + } + + @Override + public Connection getConnection() throws SQLException { + return metaData.getConnection(); + } + + @Override + public boolean supportsSavepoints() throws SQLException { + return metaData.supportsSavepoints(); + } + + @Override + public boolean supportsNamedParameters() throws SQLException { + return metaData.supportsNamedParameters(); + } + + @Override + public boolean supportsMultipleOpenResults() throws SQLException { + return metaData.supportsMultipleOpenResults(); + } + + @Override + public boolean supportsGetGeneratedKeys() throws SQLException { + return metaData.supportsGetGeneratedKeys(); + } + + @Override + public ResultSet getSuperTypes(String catalog, String schemaPattern, String typeNamePattern) throws SQLException { + return metaData.getSuperTypes(catalog, schemaPattern, typeNamePattern); + } + + @Override + public ResultSet getSuperTables(String catalog, String schemaPattern, String tableNamePattern) throws SQLException { + return metaData.getSuperTypes(catalog, schemaPattern, tableNamePattern); + } + + @Override + public ResultSet getAttributes(String catalog, String schemaPattern, String typeNamePattern, String attributeNamePattern) throws SQLException { + return metaData.getAttributes(catalog, schemaPattern, typeNamePattern, attributeNamePattern); + } + + @Override + public boolean supportsResultSetHoldability(int holdability) throws SQLException { + return metaData.supportsResultSetHoldability(holdability); + } + + @Override + public int getResultSetHoldability() throws SQLException { + return metaData.getResultSetHoldability(); + } + + @Override + public int getDatabaseMajorVersion() throws SQLException { + return metaData.getDatabaseMajorVersion(); + } + + @Override + public int getDatabaseMinorVersion() throws SQLException { + return metaData.getDatabaseMinorVersion(); + } + + @Override + public int getJDBCMajorVersion() throws SQLException { + return metaData.getJDBCMajorVersion(); + } + + @Override + public int getJDBCMinorVersion() throws SQLException { + return metaData.getJDBCMinorVersion(); + } + + @Override + public int getSQLStateType() throws SQLException { + return metaData.getSQLStateType(); + } + + @Override + public boolean locatorsUpdateCopy() throws SQLException { + return metaData.locatorsUpdateCopy(); + } + + @Override + public boolean supportsStatementPooling() throws SQLException { + return metaData.supportsStatementPooling(); + } + + @Override + public RowIdLifetime getRowIdLifetime() throws SQLException { + return metaData.getRowIdLifetime(); + } + + @Override + public ResultSet getSchemas(String catalog, String schemaPattern) throws SQLException { + return metaData.getSchemas(catalog, schemaPattern); + } + + @Override + public boolean supportsStoredFunctionsUsingCallSyntax() throws SQLException { + return metaData.supportsStoredFunctionsUsingCallSyntax(); + } + + @Override + public boolean autoCommitFailureClosesAllResultSets() throws SQLException { + return metaData.autoCommitFailureClosesAllResultSets(); + } + + @Override + public ResultSet getClientInfoProperties() throws SQLException { + return metaData.getClientInfoProperties(); + } + + @Override + public ResultSet getFunctions(String catalog, String schemaPattern, String functionNamePattern) throws SQLException { + return metaData.getFunctions(catalog, schemaPattern, functionNamePattern); + } + + @Override + public ResultSet getFunctionColumns(String catalog, String schemaPattern, String functionNamePattern, String columnNamePattern) throws SQLException { + return metaData.getFunctionColumns(catalog, schemaPattern, functionNamePattern, columnNamePattern); + } + + @Override + public ResultSet getPseudoColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException { + return metaData.getPseudoColumns(catalog, schemaPattern, tableNamePattern, columnNamePattern); + } + + @Override + public boolean generatedKeyAlwaysReturned() throws SQLException { + return metaData.generatedKeyAlwaysReturned(); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return metaData.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return metaData.isWrapperFor(iface); + } +} diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentParameterMetaData.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentParameterMetaData.java new file mode 100644 index 0000000..9f32467 --- /dev/null +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentParameterMetaData.java @@ -0,0 +1,73 @@ +package com.fanruan.agent.jdbc; + +import java.sql.ParameterMetaData; +import java.sql.SQLException; + +/** + * @author Yichen Dai + * @date 2022/8/25 16:41 + */ + + +public class AgentParameterMetaData implements ParameterMetaData { + private ParameterMetaData metaData; + + public AgentParameterMetaData(ParameterMetaData metaData){ + this.metaData = metaData; + } + + @Override + public int getParameterCount() throws SQLException { + return metaData.getParameterCount(); + } + + @Override + public int isNullable(int param) throws SQLException { + return metaData.isNullable(param); + } + + @Override + public boolean isSigned(int param) throws SQLException { + return metaData.isSigned(param); + } + + @Override + public int getPrecision(int param) throws SQLException { + return metaData.getPrecision(param); + } + + @Override + public int getScale(int param) throws SQLException { + return metaData.getScale(param); + } + + @Override + public int getParameterType(int param) throws SQLException { + return metaData.getParameterType(param); + } + + @Override + public String getParameterTypeName(int param) throws SQLException { + return metaData.getParameterTypeName(param); + } + + @Override + public String getParameterClassName(int param) throws SQLException { + return metaData.getParameterClassName(param); + } + + @Override + public int getParameterMode(int param) throws SQLException { + return metaData.getParameterMode(param); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return metaData.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return metaData.isWrapperFor(iface); + } +} diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentStruct.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentStruct.java new file mode 100644 index 0000000..0fd76fb --- /dev/null +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentStruct.java @@ -0,0 +1,32 @@ +package com.fanruan.agent.jdbc; + +import java.sql.SQLException; +import java.sql.Struct; +import java.util.Map; + +/** + * @author Yichen Dai + * @date 2022/8/31 17:04 + */ +public class AgentStruct implements Struct { + Struct struct; + + AgentStruct(Struct struct){ + this.struct = struct; + } + + @Override + public String getSQLTypeName() throws SQLException { + return null; + } + + @Override + public Object[] getAttributes() throws SQLException { + return new Object[0]; + } + + @Override + public Object[] getAttributes(Map> map) throws SQLException { + return new Object[0]; + } +} diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/connection/AgentConnection.java b/agent/src/main/java/com/fanruan/agent/jdbc/connection/AgentConnection.java index 2b5516a..def727a 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/connection/AgentConnection.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/connection/AgentConnection.java @@ -1,5 +1,7 @@ package com.fanruan.agent.jdbc.connection; +import com.fanruan.agent.jdbc.AgentDataBaseMetaData; +import com.fanruan.agent.jdbc.statement.AgentCallableStatement; import com.fanruan.agent.jdbc.statement.AgentPreparedStatement; import com.fanruan.agent.jdbc.statement.AgentStatement; @@ -32,7 +34,8 @@ public class AgentConnection implements Connection { @Override public CallableStatement prepareCall(String sql) throws SQLException { - return conn.prepareCall(sql); + CallableStatement cst = this.conn.prepareCall(sql); + return new AgentCallableStatement(cst); } @Override @@ -72,7 +75,7 @@ public class AgentConnection implements Connection { @Override public DatabaseMetaData getMetaData() throws SQLException { - return conn.getMetaData(); + return new AgentDataBaseMetaData(conn.getMetaData()); } @Override @@ -117,17 +120,17 @@ public class AgentConnection implements Connection { @Override public Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException { - return conn.createStatement(resultSetType, resultSetConcurrency); + return new AgentStatement(conn.createStatement(resultSetType, resultSetConcurrency)); } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - return conn.prepareStatement(sql, resultSetType, resultSetConcurrency); + return new AgentPreparedStatement(conn.prepareStatement(sql, resultSetType, resultSetConcurrency)); } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException { - return conn.prepareCall(sql, resultSetType, resultSetConcurrency); + return new AgentCallableStatement(conn.prepareCall(sql, resultSetType, resultSetConcurrency)); } @Override @@ -172,32 +175,32 @@ public class AgentConnection implements Connection { @Override public Statement createStatement(int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability); + return new AgentStatement(conn.createStatement(resultSetType, resultSetConcurrency, resultSetHoldability)); } @Override public PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + return new AgentPreparedStatement(conn.prepareStatement(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); } @Override public CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency, int resultSetHoldability) throws SQLException { - return conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability); + return new AgentCallableStatement(conn.prepareCall(sql, resultSetType, resultSetConcurrency, resultSetHoldability)); } @Override public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys) throws SQLException { - return conn.prepareStatement(sql, autoGeneratedKeys); + return new AgentPreparedStatement(conn.prepareStatement(sql, autoGeneratedKeys)); } @Override public PreparedStatement prepareStatement(String sql, int[] columnIndexes) throws SQLException { - return conn.prepareStatement(sql, columnIndexes); + return new AgentPreparedStatement(conn.prepareStatement(sql, columnIndexes)); } @Override public PreparedStatement prepareStatement(String sql, String[] columnNames) throws SQLException { - return conn.prepareStatement(sql, columnNames); + return new AgentPreparedStatement(conn.prepareStatement(sql, columnNames)); } @Override diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentCallableStatement.java b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentCallableStatement.java new file mode 100644 index 0000000..1dd66e9 --- /dev/null +++ b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentCallableStatement.java @@ -0,0 +1,1084 @@ +package com.fanruan.agent.jdbc.statement; + +import com.fanruan.agent.jdbc.AgentParameterMetaData; + +import java.io.InputStream; +import java.io.Reader; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.util.Calendar; +import java.util.Map; + +/** + * @author Yichen Dai + * @date 2022/8/24 16:18 + */ +public class AgentCallableStatement implements java.sql.CallableStatement { + + final private CallableStatement cst; + + public AgentCallableStatement(CallableStatement callablestatement) { + this.cst = callablestatement; + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException { + cst.registerOutParameter(parameterIndex, sqlType); + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType, int scale) throws SQLException { + cst.registerOutParameter(parameterIndex, sqlType, scale); + } + + @Override + public boolean wasNull() throws SQLException { + return cst.wasNull(); + } + + @Override + public String getString(int parameterIndex) throws SQLException { + return cst.getString(parameterIndex); + } + + @Override + public boolean getBoolean(int parameterIndex) throws SQLException { + return cst.getBoolean(parameterIndex); + } + + @Override + public byte getByte(int parameterIndex) throws SQLException { + return cst.getByte(parameterIndex); + } + + @Override + public short getShort(int parameterIndex) throws SQLException { + return cst.getShort(parameterIndex); + } + + @Override + public int getInt(int parameterIndex) throws SQLException { + return cst.getInt(parameterIndex); + } + + @Override + public long getLong(int parameterIndex) throws SQLException { + return cst.getLong(parameterIndex); + } + + @Override + public float getFloat(int parameterIndex) throws SQLException { + return cst.getFloat(parameterIndex); + } + + @Override + public double getDouble(int parameterIndex) throws SQLException { + return cst.getDouble(parameterIndex); + } + + @Override + public BigDecimal getBigDecimal(int parameterIndex, int scale) throws SQLException { + return cst.getBigDecimal(parameterIndex, scale); + } + + @Override + public byte[] getBytes(int parameterIndex) throws SQLException { + return cst.getBytes(parameterIndex); + } + + @Override + public Date getDate(int parameterIndex) throws SQLException { + return cst.getDate(parameterIndex); + } + + @Override + public Time getTime(int parameterIndex) throws SQLException { + return cst.getTime(parameterIndex); + } + + @Override + public Timestamp getTimestamp(int parameterIndex) throws SQLException { + return cst.getTimestamp(parameterIndex); + } + + @Override + public Object getObject(int parameterIndex) throws SQLException { + return cst.getObject(parameterIndex); + } + + @Override + public BigDecimal getBigDecimal(int parameterIndex) throws SQLException { + return cst.getBigDecimal(parameterIndex); + } + + @Override + public Object getObject(int parameterIndex, Map> map) throws SQLException { + return cst.getObject(parameterIndex, map); + } + + @Override + public Ref getRef(int parameterIndex) throws SQLException { + return cst.getRef(parameterIndex); + } + + @Override + public Blob getBlob(int parameterIndex) throws SQLException { + return cst.getBlob(parameterIndex); + } + + @Override + public Clob getClob(int parameterIndex) throws SQLException { + return cst.getClob(parameterIndex); + } + + @Override + public Array getArray(int parameterIndex) throws SQLException { + return cst.getArray(parameterIndex); + } + + @Override + public Date getDate(int parameterIndex, Calendar cal) throws SQLException { + return cst.getDate(parameterIndex, cal); + } + + @Override + public Time getTime(int parameterIndex, Calendar cal) throws SQLException { + return cst.getTime(parameterIndex, cal); + } + + @Override + public Timestamp getTimestamp(int parameterIndex, Calendar cal) throws SQLException { + return cst.getTimestamp(parameterIndex, cal); + } + + @Override + public void registerOutParameter(int parameterIndex, int sqlType, String typeName) throws SQLException { + cst.registerOutParameter(parameterIndex, sqlType, typeName); + } + + @Override + public void registerOutParameter(String parameterName, int sqlType) throws SQLException { + cst.registerOutParameter(parameterName, sqlType); + } + + @Override + public void registerOutParameter(String parameterName, int sqlType, int scale) throws SQLException { + cst.registerOutParameter(parameterName, sqlType, scale); + } + + @Override + public void registerOutParameter(String parameterName, int sqlType, String typeName) throws SQLException { + cst.registerOutParameter(parameterName, sqlType, typeName); + } + + @Override + public URL getURL(int parameterIndex) throws SQLException { + return cst.getURL(parameterIndex); + } + + @Override + public void setURL(String parameterName, URL val) throws SQLException { + cst.setURL(parameterName, val); + } + + @Override + public void setNull(String parameterName, int sqlType) throws SQLException { + cst.setNull(parameterName, sqlType); + } + + @Override + public void setBoolean(String parameterName, boolean x) throws SQLException { + cst.setBoolean(parameterName, x); + } + + @Override + public void setByte(String parameterName, byte x) throws SQLException { + cst.setByte(parameterName, x); + } + + @Override + public void setShort(String parameterName, short x) throws SQLException { + cst.setShort(parameterName, x); + } + + @Override + public void setInt(String parameterName, int x) throws SQLException { + cst.setInt(parameterName, x); + } + + @Override + public void setLong(String parameterName, long x) throws SQLException { + cst.setLong(parameterName, x); + } + + @Override + public void setFloat(String parameterName, float x) throws SQLException { + cst.setFloat(parameterName, x); + } + + @Override + public void setDouble(String parameterName, double x) throws SQLException { + cst.setDouble(parameterName, x); + } + + @Override + public void setBigDecimal(String parameterName, BigDecimal x) throws SQLException { + cst.setBigDecimal(parameterName, x); + } + + @Override + public void setString(String parameterName, String x) throws SQLException { + cst.setString(parameterName, x); + } + + @Override + public void setBytes(String parameterName, byte[] x) throws SQLException { + cst.setBytes(parameterName, x); + } + + @Override + public void setDate(String parameterName, Date x) throws SQLException { + cst.setDate(parameterName, x); + } + + @Override + public void setTime(String parameterName, Time x) throws SQLException { + cst.setTime(parameterName, x); + } + + @Override + public void setTimestamp(String parameterName, Timestamp x) throws SQLException { + cst.setTimestamp(parameterName, x); + } + + @Override + public void setAsciiStream(String parameterName, InputStream x, int length) throws SQLException { + cst.setAsciiStream(parameterName, x, length); + } + + @Override + public void setBinaryStream(String parameterName, InputStream x, int length) throws SQLException { + cst.setBinaryStream(parameterName, x, length); + } + + @Override + public void setObject(String parameterName, Object x, int targetSqlType, int scale) throws SQLException { + cst.setObject(parameterName, x, targetSqlType, scale); + } + + @Override + public void setObject(String parameterName, Object x, int targetSqlType) throws SQLException { + cst.setObject(parameterName, x, targetSqlType); + } + + @Override + public void setObject(String parameterName, Object x) throws SQLException { + cst.setObject(parameterName, x); + } + + @Override + public void setCharacterStream(String parameterName, Reader reader, int length) throws SQLException { + cst.setCharacterStream(parameterName, reader, length); + } + + @Override + public void setDate(String parameterName, Date x, Calendar cal) throws SQLException { + cst.setDate(parameterName, x, cal); + } + + @Override + public void setTime(String parameterName, Time x, Calendar cal) throws SQLException { + cst.setTime(parameterName, x, cal); + } + + @Override + public void setTimestamp(String parameterName, Timestamp x, Calendar cal) throws SQLException { + cst.setTimestamp(parameterName, x, cal); + } + + @Override + public void setNull(String parameterName, int sqlType, String typeName) throws SQLException { + cst.setNull(parameterName, sqlType, typeName); + } + + @Override + public String getString(String parameterName) throws SQLException { + return cst.getString(parameterName); + } + + @Override + public boolean getBoolean(String parameterName) throws SQLException { + return cst.getBoolean(parameterName); + } + + @Override + public byte getByte(String parameterName) throws SQLException { + return cst.getByte(parameterName); + } + + @Override + public short getShort(String parameterName) throws SQLException { + return cst.getShort(parameterName); + } + + @Override + public int getInt(String parameterName) throws SQLException { + return cst.getInt(parameterName); + } + + @Override + public long getLong(String parameterName) throws SQLException { + return cst.getLong(parameterName); + } + + @Override + public float getFloat(String parameterName) throws SQLException { + return cst.getFloat(parameterName); + } + + @Override + public double getDouble(String parameterName) throws SQLException { + return cst.getDouble(parameterName); + } + + @Override + public byte[] getBytes(String parameterName) throws SQLException { + return cst.getBytes(parameterName); + } + + @Override + public Date getDate(String parameterName) throws SQLException { + return cst.getDate(parameterName); + } + + @Override + public Time getTime(String parameterName) throws SQLException { + return cst.getTime(parameterName); + } + + @Override + public Timestamp getTimestamp(String parameterName) throws SQLException { + return cst.getTimestamp(parameterName); + } + + @Override + public Object getObject(String parameterName) throws SQLException { + return cst.getObject(parameterName); + } + + @Override + public BigDecimal getBigDecimal(String parameterName) throws SQLException { + return cst.getBigDecimal(parameterName); + } + + @Override + public Object getObject(String parameterName, Map> map) throws SQLException { + return cst.getObject(parameterName, map); + } + + @Override + public Ref getRef(String parameterName) throws SQLException { + return cst.getRef(parameterName); + } + + @Override + public Blob getBlob(String parameterName) throws SQLException { + return cst.getBlob(parameterName); + } + + @Override + public Clob getClob(String parameterName) throws SQLException { + return cst.getClob(parameterName); + } + + @Override + public Array getArray(String parameterName) throws SQLException { + return cst.getArray(parameterName); + } + + @Override + public Date getDate(String parameterName, Calendar cal) throws SQLException { + return cst.getDate(parameterName, cal); + } + + @Override + public Time getTime(String parameterName, Calendar cal) throws SQLException { + return cst.getTime(parameterName, cal); + } + + @Override + public Timestamp getTimestamp(String parameterName, Calendar cal) throws SQLException { + return cst.getTimestamp(parameterName, cal); + } + + @Override + public URL getURL(String parameterName) throws SQLException { + return cst.getURL(parameterName); + } + + @Override + public RowId getRowId(int parameterIndex) throws SQLException { + return cst.getRowId(parameterIndex); + } + + @Override + public RowId getRowId(String parameterName) throws SQLException { + return cst.getRowId(parameterName); + } + + @Override + public void setRowId(String parameterName, RowId x) throws SQLException { + cst.setRowId(parameterName, x); + } + + @Override + public void setNString(String parameterName, String value) throws SQLException { + cst.setNString(parameterName, value); + } + + @Override + public void setNCharacterStream(String parameterName, Reader value, long length) throws SQLException { + cst.setNCharacterStream(parameterName, value, length); + } + + @Override + public void setNClob(String parameterName, NClob value) throws SQLException { + cst.setNClob(parameterName, value); + } + + @Override + public void setClob(String parameterName, Reader reader, long length) throws SQLException { + cst.setClob(parameterName, reader, length); + } + + @Override + public void setBlob(String parameterName, InputStream inputStream, long length) throws SQLException { + cst.setBlob(parameterName, inputStream, length); + } + + @Override + public void setNClob(String parameterName, Reader reader, long length) throws SQLException { + cst.setNClob(parameterName, reader, length); + } + + @Override + public NClob getNClob(int parameterIndex) throws SQLException { + return cst.getNClob(parameterIndex); + } + + @Override + public NClob getNClob(String parameterName) throws SQLException { + return cst.getNClob(parameterName); + } + + @Override + public void setSQLXML(String parameterName, SQLXML xmlObject) throws SQLException { + cst.setSQLXML(parameterName, xmlObject); + } + + @Override + public SQLXML getSQLXML(int parameterIndex) throws SQLException { + return cst.getSQLXML(parameterIndex); + } + + @Override + public SQLXML getSQLXML(String parameterName) throws SQLException { + return cst.getSQLXML(parameterName); + } + + @Override + public String getNString(int parameterIndex) throws SQLException { + return cst.getNString(parameterIndex); + } + + @Override + public String getNString(String parameterName) throws SQLException { + return cst.getNString(parameterName); + } + + @Override + public Reader getNCharacterStream(int parameterIndex) throws SQLException { + return cst.getNCharacterStream(parameterIndex); + } + + @Override + public Reader getNCharacterStream(String parameterName) throws SQLException { + return cst.getNCharacterStream(parameterName); + } + + @Override + public Reader getCharacterStream(int parameterIndex) throws SQLException { + return cst.getCharacterStream(parameterIndex); + } + + @Override + public Reader getCharacterStream(String parameterName) throws SQLException { + return cst.getCharacterStream(parameterName); + } + + @Override + public void setBlob(String parameterName, Blob x) throws SQLException { + cst.setBlob(parameterName, x); + } + + @Override + public void setClob(String parameterName, Clob x) throws SQLException { + cst.setClob(parameterName, x); + } + + @Override + public void setAsciiStream(String parameterName, InputStream x, long length) throws SQLException { + cst.setAsciiStream(parameterName, x, length); + } + + @Override + public void setBinaryStream(String parameterName, InputStream x, long length) throws SQLException { + cst.setBinaryStream(parameterName, x, length); + } + + @Override + public void setCharacterStream(String parameterName, Reader reader, long length) throws SQLException { + cst.setCharacterStream(parameterName, reader, length); + } + + @Override + public void setAsciiStream(String parameterName, InputStream x) throws SQLException { + cst.setAsciiStream(parameterName, x); + } + + @Override + public void setBinaryStream(String parameterName, InputStream x) throws SQLException { + cst.setBinaryStream(parameterName, x); + } + + @Override + public void setCharacterStream(String parameterName, Reader reader) throws SQLException { + cst.setCharacterStream(parameterName, reader); + } + + @Override + public void setNCharacterStream(String parameterName, Reader value) throws SQLException { + cst.setNCharacterStream(parameterName, value); + } + + @Override + public void setClob(String parameterName, Reader reader) throws SQLException { + cst.setClob(parameterName, reader); + } + + @Override + public void setBlob(String parameterName, InputStream inputStream) throws SQLException { + cst.setBlob(parameterName, inputStream); + } + + @Override + public void setNClob(String parameterName, Reader reader) throws SQLException { + cst.setNClob(parameterName, reader); + } + + @Override + public T getObject(int parameterIndex, Class type) throws SQLException { + return cst.getObject(parameterIndex, type); + } + + @Override + public T getObject(String parameterName, Class type) throws SQLException { + return cst.getObject(parameterName, type); + } + + @Override + public ResultSet executeQuery() throws SQLException { + return cst.executeQuery(); + } + + @Override + public int executeUpdate() throws SQLException { + return cst.executeUpdate(); + } + + @Override + public void setNull(int parameterIndex, int sqlType) throws SQLException { + cst.setNull(parameterIndex, sqlType); + } + + @Override + public void setBoolean(int parameterIndex, boolean x) throws SQLException { + cst.setBoolean(parameterIndex, x); + } + + @Override + public void setByte(int parameterIndex, byte x) throws SQLException { + cst.setByte(parameterIndex, x); + } + + @Override + public void setShort(int parameterIndex, short x) throws SQLException { + cst.setShort(parameterIndex, x); + } + + @Override + public void setInt(int parameterIndex, int x) throws SQLException { + cst.setInt(parameterIndex, x); + } + + @Override + public void setLong(int parameterIndex, long x) throws SQLException { + cst.setLong(parameterIndex, x); + } + + @Override + public void setFloat(int parameterIndex, float x) throws SQLException { + cst.setFloat(parameterIndex, x); + } + + @Override + public void setDouble(int parameterIndex, double x) throws SQLException { + cst.setDouble(parameterIndex, x); + } + + @Override + public void setBigDecimal(int parameterIndex, BigDecimal x) throws SQLException { + cst.setBigDecimal(parameterIndex, x); + } + + @Override + public void setString(int parameterIndex, String x) throws SQLException { + cst.setString(parameterIndex, x); + } + + @Override + public void setBytes(int parameterIndex, byte[] x) throws SQLException { + cst.setBytes(parameterIndex, x); + } + + @Override + public void setDate(int parameterIndex, Date x) throws SQLException { + cst.setDate(parameterIndex, x); + } + + @Override + public void setTime(int parameterIndex, Time x) throws SQLException { + cst.setTime(parameterIndex, x); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x) throws SQLException { + cst.setTimestamp(parameterIndex, x); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, int length) throws SQLException { + cst.setAsciiStream(parameterIndex, x, length); + } + + @Override + public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { + cst.setUnicodeStream(parameterIndex, x, length); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, int length) throws SQLException { + cst.setBinaryStream(parameterIndex, x, length); + } + + @Override + public void clearParameters() throws SQLException { + cst.clearParameters(); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType) throws SQLException { + cst.setObject(parameterIndex, x, targetSqlType); + } + + @Override + public void setObject(int parameterIndex, Object x) throws SQLException { + cst.setObject(parameterIndex, x); + } + + @Override + public boolean execute() throws SQLException { + return cst.execute(); + } + + @Override + public void addBatch() throws SQLException { + cst.addBatch(); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, int length) throws SQLException { + cst.setCharacterStream(parameterIndex, reader, length); + } + + @Override + public void setRef(int parameterIndex, Ref x) throws SQLException { + cst.setRef(parameterIndex, x); + } + + @Override + public void setBlob(int parameterIndex, Blob x) throws SQLException { + cst.setBlob(parameterIndex, x); + } + + @Override + public void setClob(int parameterIndex, Clob x) throws SQLException { + cst.setClob(parameterIndex, x); + } + + @Override + public void setArray(int parameterIndex, Array x) throws SQLException { + cst.setArray(parameterIndex, x); + } + + @Override + public ResultSetMetaData getMetaData() throws SQLException { + return cst.getMetaData(); + } + + @Override + public void setDate(int parameterIndex, Date x, Calendar cal) throws SQLException { + cst.setDate(parameterIndex, x, cal); + } + + @Override + public void setTime(int parameterIndex, Time x, Calendar cal) throws SQLException { + cst.setTime(parameterIndex, x, cal); + } + + @Override + public void setTimestamp(int parameterIndex, Timestamp x, Calendar cal) throws SQLException { + cst.setTimestamp(parameterIndex, x, cal); + } + + @Override + public void setNull(int parameterIndex, int sqlType, String typeName) throws SQLException { + cst.setNull(parameterIndex, sqlType, typeName); + } + + @Override + public void setURL(int parameterIndex, URL x) throws SQLException { + cst.setURL(parameterIndex, x); + } + + @Override + public ParameterMetaData getParameterMetaData() throws SQLException { + return new AgentParameterMetaData(cst.getParameterMetaData()); + } + + @Override + public void setRowId(int parameterIndex, RowId x) throws SQLException { + cst.setRowId(parameterIndex, x); + } + + @Override + public void setNString(int parameterIndex, String value) throws SQLException { + cst.setNString(parameterIndex, value); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value, long length) throws SQLException { + cst.setNCharacterStream(parameterIndex, value, length); + } + + @Override + public void setNClob(int parameterIndex, NClob value) throws SQLException { + cst.setNClob(parameterIndex, value); + } + + @Override + public void setClob(int parameterIndex, Reader reader, long length) throws SQLException { + cst.setClob(parameterIndex, reader, length); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream, long length) throws SQLException { + cst.setBlob(parameterIndex, inputStream, length); + } + + @Override + public void setNClob(int parameterIndex, Reader reader, long length) throws SQLException { + cst.setNClob(parameterIndex, reader, length); + } + + @Override + public void setSQLXML(int parameterIndex, SQLXML xmlObject) throws SQLException { + cst.setSQLXML(parameterIndex, xmlObject); + } + + @Override + public void setObject(int parameterIndex, Object x, int targetSqlType, int scaleOrLength) throws SQLException { + cst.setObject(parameterIndex, x, targetSqlType, scaleOrLength); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x, long length) throws SQLException { + cst.setAsciiStream(parameterIndex, x, length); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x, long length) throws SQLException { + cst.setBinaryStream(parameterIndex, x, length); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader, long length) throws SQLException { + cst.setCharacterStream(parameterIndex, reader, length); + } + + @Override + public void setAsciiStream(int parameterIndex, InputStream x) throws SQLException { + cst.setAsciiStream(parameterIndex, x); + } + + @Override + public void setBinaryStream(int parameterIndex, InputStream x) throws SQLException { + cst.setBinaryStream(parameterIndex, x); + } + + @Override + public void setCharacterStream(int parameterIndex, Reader reader) throws SQLException { + cst.setCharacterStream(parameterIndex, reader); + } + + @Override + public void setNCharacterStream(int parameterIndex, Reader value) throws SQLException { + cst.setNCharacterStream(parameterIndex, value); + } + + @Override + public void setClob(int parameterIndex, Reader reader) throws SQLException { + cst.setClob(parameterIndex, reader); + } + + @Override + public void setBlob(int parameterIndex, InputStream inputStream) throws SQLException { + cst.setBlob(parameterIndex, inputStream); + } + + @Override + public void setNClob(int parameterIndex, Reader reader) throws SQLException { + cst.setNClob(parameterIndex, reader); + } + + @Override + public ResultSet executeQuery(String sql) throws SQLException { + return cst.executeQuery(sql); + } + + @Override + public int executeUpdate(String sql) throws SQLException { + return cst.executeUpdate(sql); + } + + @Override + public void close() throws SQLException { + cst.close(); + } + + @Override + public int getMaxFieldSize() throws SQLException { + return cst.getMaxFieldSize(); + } + + @Override + public void setMaxFieldSize(int max) throws SQLException { + cst.setMaxFieldSize(max); + } + + @Override + public int getMaxRows() throws SQLException { + return cst.getMaxRows(); + } + + @Override + public void setMaxRows(int max) throws SQLException { + cst.setMaxRows(max); + } + + @Override + public void setEscapeProcessing(boolean enable) throws SQLException { + cst.setEscapeProcessing(enable); + } + + @Override + public int getQueryTimeout() throws SQLException { + return cst.getQueryTimeout(); + } + + @Override + public void setQueryTimeout(int seconds) throws SQLException { + cst.setQueryTimeout(seconds); + } + + @Override + public void cancel() throws SQLException { + cst.cancel(); + } + + @Override + public SQLWarning getWarnings() throws SQLException { + return cst.getWarnings(); + } + + @Override + public void clearWarnings() throws SQLException { + cst.clearWarnings(); + } + + @Override + public void setCursorName(String name) throws SQLException { + cst.setCursorName(name); + } + + @Override + public boolean execute(String sql) throws SQLException { + return cst.execute(sql); + } + + @Override + public ResultSet getResultSet() throws SQLException { + return cst.getResultSet(); + } + + @Override + public int getUpdateCount() throws SQLException { + return cst.getUpdateCount(); + } + + @Override + public boolean getMoreResults() throws SQLException { + return cst.getMoreResults(); + } + + @Override + public void setFetchDirection(int direction) throws SQLException { + cst.setFetchDirection(direction); + } + + @Override + public int getFetchDirection() throws SQLException { + return cst.getFetchDirection(); + } + + @Override + public void setFetchSize(int rows) throws SQLException { + cst.setFetchSize(rows); + } + + @Override + public int getFetchSize() throws SQLException { + return cst.getFetchSize(); + } + + @Override + public int getResultSetConcurrency() throws SQLException { + return cst.getResultSetConcurrency(); + } + + @Override + public int getResultSetType() throws SQLException { + return cst.getResultSetType(); + } + + @Override + public void addBatch(String sql) throws SQLException { + cst.addBatch(sql); + } + + @Override + public void clearBatch() throws SQLException { + cst.clearBatch(); + } + + @Override + public int[] executeBatch() throws SQLException { + return cst.executeBatch(); + } + + @Override + public Connection getConnection() throws SQLException { + return cst.getConnection(); + } + + @Override + public boolean getMoreResults(int current) throws SQLException { + return cst.getMoreResults(current); + } + + @Override + public ResultSet getGeneratedKeys() throws SQLException { + return cst.getGeneratedKeys(); + } + + @Override + public int executeUpdate(String sql, int autoGeneratedKeys) throws SQLException { + return cst.executeUpdate(sql, autoGeneratedKeys); + } + + @Override + public int executeUpdate(String sql, int[] columnIndexes) throws SQLException { + return cst.executeUpdate(sql, columnIndexes); + } + + @Override + public int executeUpdate(String sql, String[] columnNames) throws SQLException { + return cst.executeUpdate(sql, columnNames); + } + + @Override + public boolean execute(String sql, int autoGeneratedKeys) throws SQLException { + return cst.execute(sql, autoGeneratedKeys); + } + + @Override + public boolean execute(String sql, int[] columnIndexes) throws SQLException { + return cst.execute(sql, columnIndexes); + } + + @Override + public boolean execute(String sql, String[] columnNames) throws SQLException { + return cst.execute(sql, columnNames); + } + + @Override + public int getResultSetHoldability() throws SQLException { + return cst.getResultSetHoldability(); + } + + @Override + public boolean isClosed() throws SQLException { + return cst.isClosed(); + } + + @Override + public void setPoolable(boolean poolable) throws SQLException { + cst.setPoolable(poolable); + } + + @Override + public boolean isPoolable() throws SQLException { + return cst.isPoolable(); + } + + @Override + public void closeOnCompletion() throws SQLException { + cst.closeOnCompletion(); + } + + @Override + public boolean isCloseOnCompletion() throws SQLException { + return cst.isCloseOnCompletion(); + } + + @Override + public T unwrap(Class iface) throws SQLException { + return cst.unwrap(iface); + } + + @Override + public boolean isWrapperFor(Class iface) throws SQLException { + return cst.isWrapperFor(iface); + } +} diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentStatement.java b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentStatement.java index 3e64a4f..4bff6bc 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentStatement.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentStatement.java @@ -4,6 +4,9 @@ import com.fanruan.agent.jdbc.resultset.AgentResultSet; import java.sql.*; +/** + * @author Yichen Dai + */ public class AgentStatement implements Statement { final private Statement st; diff --git a/agent/src/main/java/com/fanruan/cache/BeanCache.java b/agent/src/main/java/com/fanruan/cache/BeanCache.java index de0d338..ae67152 100644 --- a/agent/src/main/java/com/fanruan/cache/BeanCache.java +++ b/agent/src/main/java/com/fanruan/cache/BeanCache.java @@ -31,4 +31,12 @@ public interface BeanCache { */ void cacheInstance(String ID, Object o); + /** + * verify whether the Instance is exit + * @param ID The unique num of a cache instance, It comes from the RPC request ID, + * which asked to create the instance. + * @return if it exits, true, otherwise false. + */ + boolean containsInstance(String ID); + } diff --git a/agent/src/main/java/com/fanruan/cache/BeanCacheImpl.java b/agent/src/main/java/com/fanruan/cache/BeanCacheImpl.java index 0926afb..ca723ac 100644 --- a/agent/src/main/java/com/fanruan/cache/BeanCacheImpl.java +++ b/agent/src/main/java/com/fanruan/cache/BeanCacheImpl.java @@ -38,4 +38,9 @@ public class BeanCacheImpl implements BeanCache{ public void cacheInstance(String ID, Object o){ CACHE.put(ID, o); } + + @Override + public boolean containsInstance(String ID) { + return CACHE.containsKey(ID); + } } diff --git a/agent/src/main/java/com/fanruan/cache/Cache.java b/agent/src/main/java/com/fanruan/cache/Cache.java index 7c03272..3b24709 100644 --- a/agent/src/main/java/com/fanruan/cache/Cache.java +++ b/agent/src/main/java/com/fanruan/cache/Cache.java @@ -2,6 +2,7 @@ package com.fanruan.cache; import io.socket.client.Socket; +import java.util.List; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; @@ -37,6 +38,12 @@ public interface Cache { */ Socket getSocket(String dbName); + /** + * get sockets + * @return a list of socket + */ + List getSockets(); + /** * register the socket of specific nameSpace/db * @param dbName the key of cache diff --git a/agent/src/main/java/com/fanruan/cache/CacheImpl.java b/agent/src/main/java/com/fanruan/cache/CacheImpl.java index 817b79f..dc7fa78 100644 --- a/agent/src/main/java/com/fanruan/cache/CacheImpl.java +++ b/agent/src/main/java/com/fanruan/cache/CacheImpl.java @@ -2,6 +2,10 @@ package com.fanruan.cache; import io.socket.client.Socket; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; + /** * @author Yichen Dai * @date 2022/8/16 16:13 @@ -22,6 +26,15 @@ public class CacheImpl implements Cache{ return socket; } + @Override + public List getSockets() { + List res = new ArrayList<>(); + for(Map.Entry e : SOCKET_MAP.entrySet()){ + res.add(e.getValue()); + } + return res; + } + @Override public void registerBeanCache(String dbName, BeanCacheImpl beanCache) { BEAN_CACHE.put(dbName, beanCache); diff --git a/agent/src/main/java/com/fanruan/handler/DispatcherHelper.java b/agent/src/main/java/com/fanruan/handler/DispatcherHelper.java index 6da14a7..0e03968 100644 --- a/agent/src/main/java/com/fanruan/handler/DispatcherHelper.java +++ b/agent/src/main/java/com/fanruan/handler/DispatcherHelper.java @@ -30,10 +30,25 @@ public class DispatcherHelper { "Statement", "PreparedStatement", "ResultSet", + "MetaData", + "Clob", + "Blob", + "Array", + "Struct" }; + public static boolean isInCacheList(Object obj){ + if(obj == null) { + return false; + } + return isInCacheList(obj.getClass().getName()); + } + public static boolean isInCacheList(String className){ + if (className == null){ + return false; + } for(String s : CACHE_LIST){ if(Pattern.matches(".*" + s + ".*", className)){ return true; @@ -43,6 +58,9 @@ public class DispatcherHelper { } public static boolean isWraps(Class clz){ + if(clz == null) { + return false; + } return WRAPPER_CLASS_MAP.containsKey(getClassName(clz.getName())); } @@ -51,15 +69,11 @@ public class DispatcherHelper { } public static String getClassName(String fullyQualifiedClassName){ - String[] arr = fullyQualifiedClassName.split("\\."); + String[] arr = fullyQualifiedClassName.trim().split("\\."); int n = arr.length; - if(n == 0) { - throw new RuntimeException("the class name invoked is wrong"); + if(n < 1) { + throw new RuntimeException("the class's name invoked is wrong"); } return arr[n-1]; } - - public static String transformName(String name){ - return name.replace("servicejdbc", "agentjdbc"); - } } diff --git a/agent/src/main/java/com/fanruan/handler/DispatcherImpl.java b/agent/src/main/java/com/fanruan/handler/DispatcherImpl.java index 4d196d0..2359ce5 100644 --- a/agent/src/main/java/com/fanruan/handler/DispatcherImpl.java +++ b/agent/src/main/java/com/fanruan/handler/DispatcherImpl.java @@ -6,6 +6,7 @@ import com.fanruan.pojo.message.RpcRequest; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -27,8 +28,8 @@ public class DispatcherImpl implements Dispatcher{ Object res = null; try { res = invokeAsRequest(rpcRequest, beanCache); - }catch (Exception e){ - RESPONSE_EMITTER_IMPL.sendError(CACHE.getSocket(dbName), rpcRequest, e); + }catch (Throwable t){ + RESPONSE_EMITTER_IMPL.sendError(CACHE.getSocket(dbName), rpcRequest, t); } if(res != null && !DispatcherHelper.isInCacheList(res.getClass().getName())){ @@ -39,7 +40,7 @@ public class DispatcherImpl implements Dispatcher{ } @Override - public Object invokeAsRequest(RpcRequest rpcRequest, BeanCacheImpl beanCache) throws Exception{ + public Object invokeAsRequest(RpcRequest rpcRequest, BeanCacheImpl beanCache) throws Throwable { String fullName = rpcRequest.getServiceClassName(); Class clazz = Class.forName(fullName); String methodName = rpcRequest.getMethodName(); @@ -80,28 +81,25 @@ public class DispatcherImpl implements Dispatcher{ } } method = clazz.getDeclaredMethod(methodName, argTypes); - - } + Object res = null; - Object res = method.invoke(calledClassInstance, args); - - if(CLOSE_NAME.equals(methodName)){ - beanCache.removeInstances(IDToInvoke); + try{ + res = method.invoke(calledClassInstance, args); + }catch (InvocationTargetException e){ + throw e.getCause(); } // Cached some instances need to be invoke later. - // Some method return null, so determine the value of `res` before referencing it. - if(res != null){ - String resClassName = res.getClass().getName(); - if(DispatcherHelper.isInCacheList(resClassName)) { - beanCache.cacheInstance(rpcRequest.getID(), res); - } - logger.debug("invoke" + className + "-" + methodName + " and return a instance of" + res.getClass().getName()); - }else{ - logger.debug("invoke" + className + "-" + methodName + " and no return value"); + // Some method return null + + if(DispatcherHelper.isInCacheList(res)) { + beanCache.cacheInstance(rpcRequest.getID(), res); } + + logger.debug("invoke" + className + "-" + methodName + " and return value : " + res); + return res; } diff --git a/agent/src/main/java/com/fanruan/handler/ResponseEmitter.java b/agent/src/main/java/com/fanruan/handler/ResponseEmitter.java index 45007b5..783b35e 100644 --- a/agent/src/main/java/com/fanruan/handler/ResponseEmitter.java +++ b/agent/src/main/java/com/fanruan/handler/ResponseEmitter.java @@ -20,9 +20,9 @@ public interface ResponseEmitter { * Send failure response when error occur while handle request. * @param socket * @param rpcRequest - * @param e Exception happened while handle request. + * @param t Exception happened while handle request. */ - void sendError(Socket socket, RpcRequest rpcRequest, Exception e); + void sendError(Socket socket, RpcRequest rpcRequest, Throwable t); /** * Send success response with data asked by request. diff --git a/agent/src/main/java/com/fanruan/handler/ResponseEmitterImpl.java b/agent/src/main/java/com/fanruan/handler/ResponseEmitterImpl.java index 56b5df0..b26edf8 100644 --- a/agent/src/main/java/com/fanruan/handler/ResponseEmitterImpl.java +++ b/agent/src/main/java/com/fanruan/handler/ResponseEmitterImpl.java @@ -22,11 +22,11 @@ public class ResponseEmitterImpl implements ResponseEmitter{ } @Override - public void sendError(Socket socket, RpcRequest rpcRequest, Exception e){ + public void sendError(Socket socket, RpcRequest rpcRequest, Throwable t){ RpcResponse rpcResponse = new RpcResponse(); rpcResponse.setResult("Some errors happened when AgentID: " + AgentStarter.AgentID + " " + rpcRequest.getMethodName() + " is being invoked!" + "\n" - + "Error Message: " + e.getMessage() + + "Error Message: " + t.getMessage() + " and check your code") .setID(rpcRequest.getID()) .setStatus(false); diff --git a/agent/src/main/java/com/fanruan/pojo/message/RpcRequest.java b/agent/src/main/java/com/fanruan/pojo/message/RpcRequest.java index 0389900..152a8eb 100644 --- a/agent/src/main/java/com/fanruan/pojo/message/RpcRequest.java +++ b/agent/src/main/java/com/fanruan/pojo/message/RpcRequest.java @@ -10,7 +10,6 @@ import lombok.experimental.Accessors; @Accessors(chain = true) public class RpcRequest { private String ID; -// private boolean binding; private String IDToInvoke; private String serviceClassName; private String methodName; diff --git a/agent/src/test/java/HSQLTest.java b/agent/src/test/java/HSQLTest.java index 370efd6..4e685c0 100644 --- a/agent/src/test/java/HSQLTest.java +++ b/agent/src/test/java/HSQLTest.java @@ -25,7 +25,7 @@ public class HSQLTest { void getConnection() throws SQLException { Connection conn = null; try { - conn = DriverManager.getConnection("jdbc:hsqldb:mem:test", "sa", ""); + conn = DriverManager.getConnection("jdbc:hsqldb:mem:test;sql.syntax_mys=true", "sa", ""); Assertions.assertNotNull(conn, "can't get connection"); } catch (SQLException e) { e.printStackTrace(); @@ -34,6 +34,29 @@ public class HSQLTest { } } + private static String createStoredProcedure ="CREATE PROCEDURE get_city_name(" + + "IN c_id INT, " + + "OUT city_name varchar(20)) " + + "READS SQL DATA " + + "BEGIN ATOMIC " + + " SELECT city.name INTO city_name FROM city WHERE id = c_id; " + + "END;"; + + @Test + public void test() throws SQLException { + Connection conn = DriverManager.getConnection("jdbc:hsqldb:mem:test;sql.syntax_mys=true", "sa", ""); + Statement statement = conn.createStatement(); + statement.executeUpdate("CREATE TABLE city (id INTEGER, name varchar(20)); "); + statement.executeUpdate("INSERT INTO city VALUES (1, '成都'), (2, '上海'); "); + + statement.execute(createStoredProcedure); + CallableStatement callableStatement = conn.prepareCall("{call get_city_name(?, ?)}"); + callableStatement.setInt(1, 2); + callableStatement.registerOutParameter(2, Types.VARCHAR); + callableStatement.execute(); + System.out.println(callableStatement.getString(2)); + } + /** * test to create statement instance and prepareStatement, create table, select form table, delete from table */ @@ -44,7 +67,7 @@ public class HSQLTest { PreparedStatement pst = null; ResultSet rs = null; try { - conn = DriverManager.getConnection("jdbc:hsqldb:mem:test", "sa", ""); + conn = DriverManager.getConnection("jdbc:hsqldb:mem:test;sql.syntax_mys=true", "sa", ""); st = conn.createStatement(); st.executeUpdate("DROP TABLE student IF EXISTS;"); @@ -82,6 +105,8 @@ public class HSQLTest { Assertions.assertEquals(rs.getString("student_address"), addressStrings[num-1]); num++; } + + } catch (Exception e) { e.printStackTrace(); } finally { diff --git a/agent/src/test/java/Test.java b/agent/src/test/java/Test.java index 90179e3..61e5763 100644 --- a/agent/src/test/java/Test.java +++ b/agent/src/test/java/Test.java @@ -2,6 +2,8 @@ import com.fanruan.AgentStarter; import com.fanruan.utils.DBProperties; import io.socket.client.Socket; +import java.util.HashMap; + public class Test { @@ -27,7 +29,6 @@ public class Test { Socket socket = AgentStarter.dispatcherImpl.CACHE.getSocket(DBProperties.HSQL[0]); socket.connect(); - } } diff --git a/agent/src/test/java/TestSuite.java b/agent/src/test/java/TestSuite.java new file mode 100644 index 0000000..c0b293c --- /dev/null +++ b/agent/src/test/java/TestSuite.java @@ -0,0 +1,14 @@ +import org.junit.platform.suite.api.IncludeClassNamePatterns; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.Suite; + +/** + * @author Yichen Dai + * @date 2022/8/23 15:04 + */ + +@SelectPackages({"com.fanruan"}) +@Suite +@IncludeClassNamePatterns(".*Test.*") +public class TestSuite { +} diff --git a/agent/src/test/java/com/fanruan/cache/BeanCacheImplTest.java b/agent/src/test/java/com/fanruan/cache/BeanCacheImplTest.java new file mode 100644 index 0000000..2853fdc --- /dev/null +++ b/agent/src/test/java/com/fanruan/cache/BeanCacheImplTest.java @@ -0,0 +1,24 @@ +package com.fanruan.cache; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Yichen Dai + * @date 2022/8/22 19:54 + */ +class BeanCacheImplTest { + + @Test + void getCachedInstances() { + } + + @Test + void removeInstances() { + } + + @Test + void cacheInstance() { + } +} \ No newline at end of file diff --git a/agent/src/test/java/com/fanruan/cache/CacheImplTest.java b/agent/src/test/java/com/fanruan/cache/CacheImplTest.java new file mode 100644 index 0000000..48f62d2 --- /dev/null +++ b/agent/src/test/java/com/fanruan/cache/CacheImplTest.java @@ -0,0 +1,44 @@ +package com.fanruan.cache; + +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * @author Yichen Dai + * @date 2022/8/22 19:54 + */ +class CacheImplTest { + + @Test + void registerSocket() { + } + + @Test + void getSocket() { + } + + @Test + void registerBeanCache() { + } + + @Test + void getBeanCache() { + } + + @Test + void testRegisterSocket() { + } + + @Test + void testGetSocket() { + } + + @Test + void testRegisterBeanCache() { + } + + @Test + void testGetBeanCache() { + } +} \ No newline at end of file diff --git a/agent/src/test/java/com/fanruan/handler/DispatcherHelperTest.java b/agent/src/test/java/com/fanruan/handler/DispatcherHelperTest.java new file mode 100644 index 0000000..d9e8940 --- /dev/null +++ b/agent/src/test/java/com/fanruan/handler/DispatcherHelperTest.java @@ -0,0 +1,71 @@ +package com.fanruan.handler; + +import com.fanruan.agent.jdbc.driver.AgentDriver; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + + + +/** + * @author Yichen Dai + * @date 2022/8/22 15:07 + */ +class DispatcherHelperTest{ + + + + @Test + void isInCacheList() { + Assertions.assertTrue(DispatcherHelper.isInCacheList(new AgentDriver())); + + Assertions.assertTrue(DispatcherHelper.isInCacheList("com.fanruan.agent.jdbc.agentDriver")); + Assertions.assertTrue(DispatcherHelper.isInCacheList("com.fanruan.agent.jdbc.agentConnection")); + Assertions.assertTrue(DispatcherHelper.isInCacheList("com.fanruan.agent.jdbc.agentStatement")); + Assertions.assertTrue(DispatcherHelper.isInCacheList("com.fanruan.agent.jdbc.agentPrepareStatement")); + Assertions.assertTrue(DispatcherHelper.isInCacheList("com.fanruan.agent.jdbc.agentResultSet")); + + Assertions.assertFalse(DispatcherHelper.isInCacheList("java.lang.String")); + Assertions.assertFalse(DispatcherHelper.isInCacheList("java.lang.Integer")); + Assertions.assertFalse(DispatcherHelper.isInCacheList("com.fanruan.agent.cache.BeanCache")); + Assertions.assertFalse(DispatcherHelper.isInCacheList("")); + Assertions.assertFalse(DispatcherHelper.isInCacheList(null)); + + } + + @Test + void isWraps() { + Assertions.assertTrue(DispatcherHelper.isWraps(java.lang.Byte.class)); + Assertions.assertTrue(DispatcherHelper.isWraps(java.lang.Character.class)); + Assertions.assertTrue(DispatcherHelper.isWraps(java.lang.Short.class)); + Assertions.assertTrue(DispatcherHelper.isWraps(java.lang.Integer.class)); + Assertions.assertTrue(DispatcherHelper.isWraps(java.lang.Long.class)); + Assertions.assertTrue(DispatcherHelper.isWraps(java.lang.Boolean.class)); + Assertions.assertTrue(DispatcherHelper.isWraps(java.lang.Float.class)); + Assertions.assertTrue(DispatcherHelper.isWraps(java.lang.Double.class)); + + Assertions.assertFalse(DispatcherHelper.isWraps(Integer.TYPE)); + Assertions.assertFalse(DispatcherHelper.isWraps(java.lang.String.class)); + Assertions.assertFalse(DispatcherHelper.isWraps(null)); + } + + @Test + void castToPrimitiveClass() { + Assertions.assertEquals(Byte.TYPE, DispatcherHelper.castToPrimitiveClass(Byte.class)); + Assertions.assertEquals(Character.TYPE, DispatcherHelper.castToPrimitiveClass(Character.class)); + Assertions.assertEquals(Short.TYPE, DispatcherHelper.castToPrimitiveClass(Short.class)); + Assertions.assertEquals(Integer.TYPE, DispatcherHelper.castToPrimitiveClass(Integer.class)); + Assertions.assertEquals(Long.TYPE, DispatcherHelper.castToPrimitiveClass(Long.class)); + Assertions.assertEquals(Boolean.TYPE, DispatcherHelper.castToPrimitiveClass(Boolean.class)); + Assertions.assertEquals(Float.TYPE, DispatcherHelper.castToPrimitiveClass(Float.class)); + Assertions.assertEquals(Double.TYPE, DispatcherHelper.castToPrimitiveClass(Double.class)); + } + + @Test + void getClassName() { + Assertions.assertEquals("agentDriver", DispatcherHelper.getClassName("com.fanruan.agent.jdbc.agentDriver")); + Assertions.assertEquals("agentDriver", DispatcherHelper.getClassName(" com.fanruan.agent.jdbc.agentDriver ")); + Assertions.assertEquals("fakeName", DispatcherHelper.getClassName("fakeName")); + Assertions.assertEquals("", DispatcherHelper.getClassName("")); + Assertions.assertThrows(RuntimeException.class, () -> DispatcherHelper.getClassName(null)); + } +} \ No newline at end of file diff --git a/agent/src/test/java/com/fanruan/handler/DispatcherImplTest.java b/agent/src/test/java/com/fanruan/handler/DispatcherImplTest.java new file mode 100644 index 0000000..314bca9 --- /dev/null +++ b/agent/src/test/java/com/fanruan/handler/DispatcherImplTest.java @@ -0,0 +1,27 @@ +package com.fanruan.handler; + +import org.junit.jupiter.api.Test; + +/** + * @author Yichen Dai + * @date 2022/8/22 14:47 + */ +class DispatcherImplTest { + + @Test + void doDispatch() { + + } + + @Test + void invokeAsRequest() { + } + + @Test + void testDoDispatch() { + } + + @Test + void testInvokeAsRequest() { + } +} \ No newline at end of file diff --git a/pic/project structure.jpg b/pic/project structure.jpg index b95ca74..e69de29 100644 Binary files a/pic/project structure.jpg and b/pic/project structure.jpg differ diff --git a/service/pom.xml b/service/pom.xml index 91a4083..c963489 100644 --- a/service/pom.xml +++ b/service/pom.xml @@ -69,11 +69,20 @@ 1.18.22 - + org.junit.jupiter junit-jupiter-engine - 5.4.0 + 5.9.0 + test + + + + + + org.junit.platform + junit-platform-suite-engine + 1.9.0 test diff --git a/service/src/main/java/com/fanruan/ServerStater.java b/service/src/main/java/com/fanruan/ServerStater.java index 724d483..4f4e099 100644 --- a/service/src/main/java/com/fanruan/ServerStater.java +++ b/service/src/main/java/com/fanruan/ServerStater.java @@ -58,6 +58,10 @@ public class ServerStater{ } + public void shutDown(){ + server.stop(); + } + private void addEvent(SocketIONamespace nameSpace){ logger.debug("配置事件监听"); nameSpace.addConnectListener(client -> { @@ -180,7 +184,7 @@ public class ServerStater{ client.disconnect(); } - // 缓存连接 + // remove client ClientCache.deleteClient(agentID, dbName); logger.info("agentID: " + agentID + "连接关闭"); logger.info("agentID: " + agentID + "连接已删除"); diff --git a/service/src/main/java/com/fanruan/pojo/message/RpcRequest.java b/service/src/main/java/com/fanruan/pojo/message/RpcRequest.java index 0990d43..ab38997 100644 --- a/service/src/main/java/com/fanruan/pojo/message/RpcRequest.java +++ b/service/src/main/java/com/fanruan/pojo/message/RpcRequest.java @@ -14,7 +14,6 @@ public class RpcRequest { * In the project, they are Drive( MyDriver ), Connection( MyConnection ), Statement( MyStatement ), * PreparedStatement( MyPreparedStatement ), ResultSet( MyResult ). */ -// private boolean binding; private String ID; private String IDToInvoke; private String serviceClassName; diff --git a/service/src/test/java/AutoStarter.java b/service/src/test/java/AutoStarter.java deleted file mode 100644 index fee30c7..0000000 --- a/service/src/test/java/AutoStarter.java +++ /dev/null @@ -1,22 +0,0 @@ -import com.fanruan.ServerStater; -import com.fanruan.utils.DBProperties; - -/** - * @author Yichen Dai - * @date 2022/8/18 9:54 - */ -public class AutoStarter { - - static { - String[][] DBs = new String[][]{ - DBProperties.HSQL, - }; - new ServerStater(DBs); - - try { - Class.forName("com.fanruan.service.jdbc.driver.ServiceDriver"); - } catch (ClassNotFoundException e) { - e.printStackTrace(); - } - } -} diff --git a/service/src/test/java/ServiceTest.java b/service/src/test/java/ServiceTest.java index d395f64..0b04e9e 100644 --- a/service/src/test/java/ServiceTest.java +++ b/service/src/test/java/ServiceTest.java @@ -15,7 +15,7 @@ import java.util.concurrent.FutureTask; * @author Yichen Dai * @date 2022/8/18 9:49 */ -public class ServiceTest extends AutoStarter{ +public class ServiceTest { @BeforeEach void listen() throws ExecutionException, InterruptedException { diff --git a/service/src/test/java/TestSuite.java b/service/src/test/java/TestSuite.java new file mode 100644 index 0000000..e5fe975 --- /dev/null +++ b/service/src/test/java/TestSuite.java @@ -0,0 +1,13 @@ +import org.junit.platform.suite.api.IncludeClassNamePatterns; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.Suite; + +/** + * @author Yichen Dai + * @date 2022/8/23 15:30 + */ +@SelectPackages({"com.fanruan"}) +@IncludeClassNamePatterns(".*Test.*") +@Suite +public class TestSuite { +} diff --git a/test/pom.xml b/test/pom.xml index 86cf656..0d5e5b6 100644 --- a/test/pom.xml +++ b/test/pom.xml @@ -29,14 +29,25 @@ 1.0-SNAPSHOT - + org.junit.jupiter junit-jupiter-engine - 5.4.0 + 5.9.0 test + + + + org.junit.platform + junit-platform-suite-engine + 1.9.0 + test + + + + org.apache.logging.log4j log4j-api diff --git a/test/src/test/java/TestSuite.java b/test/src/test/java/TestSuite.java new file mode 100644 index 0000000..3948c3b --- /dev/null +++ b/test/src/test/java/TestSuite.java @@ -0,0 +1,16 @@ +import org.junit.platform.suite.api.IncludeClassNamePatterns; +import org.junit.platform.suite.api.SelectPackages; +import org.junit.platform.suite.api.Suite; + +/** + * @author Yichen Dai + * @date 2022/8/23 14:39 + */ + +@SelectPackages({"com.fanruan"}) +@IncludeClassNamePatterns(".*Test.*") +@Suite +public class TestSuite { +} + + diff --git a/test/src/test/java/TestUtil.java b/test/src/test/java/TestUtil.java deleted file mode 100644 index a49a0db..0000000 --- a/test/src/test/java/TestUtil.java +++ /dev/null @@ -1,170 +0,0 @@ - -import com.fanruan.AgentStarter; -import com.fanruan.ServerStater; - -import com.fanruan.service.jdbc.driver.ServiceDriver; -import com.fanruan.proxy.ProxyFactory; -import com.fanruan.utils.DBProperties; -import org.junit.jupiter.api.*; - -import java.sql.*; -import java.util.Properties; - -/** - * @author Yichen Dai - * @date 2022/8/18 15:27 - */ - -public class TestUtil { - - static Connection conn = null; - static Statement st = null; - static PreparedStatement pst = null; - static ResultSet rs = null; - - static void configService(){ - String[][] DBs = new String[][]{ - DBProperties.HSQL, - }; - new ServerStater(DBs); - } - - static void configAgent(){ - String[][] DBs = new String[][]{ - DBProperties.HSQL, - }; - new AgentStarter(DBs); - } - - @BeforeAll - static void autoConfig(){ - configService(); - configAgent(); - try { - // 等待socket连接 - Thread.sleep(2000); - } catch (InterruptedException e) { - e.printStackTrace(); - } - } - - @Test - void testConnect() throws SQLException { - // 建立连接 - Properties info = new Properties(); - info.setProperty("user", "sa"); - info.setProperty("password", ""); - info.setProperty("agentID", "1001"); - info.setProperty("agentDBName", DBProperties.HSQL[0]); - - Driver driver = (ServiceDriver) ProxyFactory.getProxy(ServiceDriver.class, null); - conn = driver.connect("jdbc:hsqldb:mem:test", info); - } - - - - - @Test - void testCreateTable() throws SQLException { - testConnect(); - // 创建 statement - st = conn.createStatement(); - - // 创建表 - int num = st.executeUpdate("DROP TABLE student IF EXISTS;"); - - Assertions.assertEquals(0, num); - - - num = st.executeUpdate("CREATE TABLE student (" + - "student_id INTEGER GENERATED BY DEFAULT AS IDENTITY " + - "(START WITH 1, INCREMENT BY 1) NOT NULL," + - "student_name VARCHAR(100) NOT NULL," + - "student_address VARCHAR(100) NOT NULL," + - "PRIMARY KEY (student_id)" + - ");"); - - Assertions.assertEquals(0, num); - } - - @Test - void testInsert() throws SQLException { - testCreateTable(); - // 插入数据 - int num = st.executeUpdate("INSERT INTO student VALUES" + - "(1, '张三', '上海')," + - "(2, '李四', '北京')," + - "(3, '王五', '成都');"); - - Assertions.assertEquals(3, num); - } - - @Test - void testUpdate() throws SQLException { - testInsert(); - // 预查询语句 删除指定 ID - pst = conn.prepareStatement("UPDATE student" + - " SET student_name = '李华', student_address = '杭州'"+ - "WHERE student_id = ?"); - - Assertions.assertNotNull(pst); - - pst.setInt(1, 1); - - int num = pst.executeUpdate(); - - Assertions.assertEquals(1, num); - } - - @Test - void testDelete() throws SQLException { - testInsert(); - // 预查询语句 删除指定 ID - pst = conn.prepareStatement("delete from student where student_id = ?"); - - Assertions.assertNotNull(pst); - - pst.setInt(1, 1); - - int num = pst.executeUpdate(); - - Assertions.assertEquals(1, num); - } - - @Test - void testSelect() throws SQLException { - testInsert(); - rs = st.executeQuery("select * from student"); - - String[] nameStrings = new String[]{"张三", "李四", "王五"}; - String[] addressStrings = new String[]{"上海", "北京", "成都"}; - - // 结果集断言 - int num = 1; - while(rs.next()) { - Assertions.assertEquals(rs.getInt("student_id"), num); - Assertions.assertEquals(rs.getString("student_name"), nameStrings[num-1]); - Assertions.assertEquals(rs.getString("student_address"), addressStrings[num-1]); - num++; - } - } - - @AfterAll - static void close() throws SQLException { - if(rs!= null){ - rs.close(); - } - - if(pst != null){ - pst.close(); - } - - if(st != null){ - st.close(); - } - - if(conn != null){ - conn.close(); - } - } -} diff --git a/test/src/test/java/com/fanruan/AbstractDriverTest.java b/test/src/test/java/com/fanruan/AbstractDriverTest.java new file mode 100644 index 0000000..80fab3a --- /dev/null +++ b/test/src/test/java/com/fanruan/AbstractDriverTest.java @@ -0,0 +1,58 @@ +package com.fanruan; + +/** + * @author Yichen Dai + * @date 2022/8/23 15:49 + */ + +import com.fanruan.cache.ClientCache; +import com.fanruan.proxy.ProxyFactory; +import com.fanruan.service.jdbc.driver.ServiceDriver; +import com.fanruan.utils.DBProperties; + +import java.sql.*; +import java.util.Properties; + +/** Base test class with common constants, data structures and methods */ +public class AbstractDriverTest { + static final Properties info = new Properties(); + + static final String[][] dbNameAndDriver = new String[][]{ + DBProperties.HSQL + }; + + static final ServerStater server = new ServerStater(dbNameAndDriver); + static final AgentStarter agent = new AgentStarter(dbNameAndDriver); + + + static { + info.setProperty("user", "sa"); + info.setProperty("password", ""); + info.setProperty("agentID", "1001"); + info.setProperty("agentDBName", DBProperties.HSQL[0]); + } + + static void openSocket(){ + while(ClientCache.getClient( + info.getProperty("agentID"), + info.getProperty("agentDBName")) + == null){ + } + } + + void shutDown(){ + agent.shutDown(); + server.shutDown(); + } + + /** + * Gets a connection + * @return Connection a database connection + * @throws SQLException raised if any error occurs + */ + public static Connection getConnection() throws SQLException { + Driver driver = (ServiceDriver) ProxyFactory.getProxy(ServiceDriver.class, null); + Connection conn = driver.connect("jdbc:hsqldb:mem:test;sql.syntax_mys=true", info); + return conn; + } +} diff --git a/test/src/test/java/com/fanruan/AgentCallableStatementTest.java b/test/src/test/java/com/fanruan/AgentCallableStatementTest.java new file mode 100644 index 0000000..51b6fb5 --- /dev/null +++ b/test/src/test/java/com/fanruan/AgentCallableStatementTest.java @@ -0,0 +1,1171 @@ +package com.fanruan; + +import com.fanruan.cache.BeanCacheImpl; +import com.fanruan.handler.DispatcherImpl; +import com.fanruan.pojo.message.RpcRequest; +import com.fanruan.pojo.message.RpcResponse; +import com.fanruan.proxy.interceptor.InterceptorUtils; +import com.fanruan.service.jdbc.ServiceBlob; +import com.fanruan.service.jdbc.statement.ServiceCallableStatement; +import com.fanruan.utils.Commons; +import org.junit.jupiter.api.*; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import java.io.*; +import java.lang.reflect.InvocationTargetException; +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.sql.Date; +import java.util.*; + +/** + * @author Yichen Dai + * @date 2022/8/24 10:22 + */ + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class AgentCallableStatementTest extends BaseJDBCTest{ + + private Connection conn = null; + private Statement statement = null; + private CallableStatement callableStatement = null; + private Properties properties = null; + + private static String createStoredProcedure = "CREATE PROCEDURE get_city_name(" + + "IN c_id INT, " + + "OUT city_name varchar(20)) " + + "READS SQL DATA " + + "BEGIN ATOMIC " + + " SELECT city.name INTO city_name FROM city WHERE id = c_id; " + + "END;"; + + private static String callProcedure = + "{call get_city_name(?, ?) }"; + + private static String deleteStoredProcedure = + "DROP PROCEDURE IF EXISTS cnt_num;"; + + @BeforeAll + public void setUp() throws SQLException{ + openSocket(); + conn = getConnection(); + statement = conn.createStatement(); + statement.executeUpdate("CREATE TABLE city (id INTEGER, name varchar(20)); "); + statement.executeUpdate("INSERT INTO city VALUES (1, '成都'), (2, '上海'); "); + statement.execute(deleteStoredProcedure); + statement.execute(createStoredProcedure); + } + + @Test + @Order(1) + public void testPrepareCall() throws SQLException{ + callableStatement = conn.prepareCall(callProcedure); + ParameterMetaData parameterMetaData = callableStatement.getParameterMetaData(); + int num = parameterMetaData.getParameterCount(); + Assertions.assertEquals(2, num); + Assertions.assertEquals(Types.INTEGER, parameterMetaData.getParameterType(1)); + Assertions.assertEquals("INTEGER", parameterMetaData.getParameterTypeName(1)); + + callableStatement.setInt(1, 2); + callableStatement.registerOutParameter(2, Types.VARCHAR); + callableStatement.execute(); + Assertions.assertEquals("上海", callableStatement.getString(2)); + + + } + + @Test + @Order(2) + void testMethods() throws SQLException { + ServiceCallableStatement cstm = (ServiceCallableStatement) this.callableStatement; + String IDtoInvoke = cstm.getID(); + + DispatcherImpl dispatcher = agent.dispatcherImpl; + BeanCacheImpl beanCache = dispatcher.CACHE.getBeanCache(dbName); + ServiceCallableStatement cstm2 = (ServiceCallableStatement) ProxyFactoryIT.getProxy(ServiceCallableStatement.class, map); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.registerOutParameter(1, Types.INTEGER); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.registerOutParameter(1, Types.INTEGER, 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.registerOutParameter(1, Types.INTEGER, "int"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + Assertions.assertThrows(SQLException.class, () -> { + cstm2.registerOutParameter("param_name", Types.INTEGER); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + Assertions.assertThrows(SQLException.class, () -> { + cstm2.registerOutParameter("param_name", Types.INTEGER, 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + Assertions.assertThrows(SQLException.class, () -> { + cstm2.registerOutParameter("param_name", Types.INTEGER, "int"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getArray("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getArray(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getBigDecimal("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getBigDecimal(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getBlob("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getBlob(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getBoolean("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getBoolean(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getByte("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getByte(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getCharacterStream("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getCharacterStream(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getClob("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getClob(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getDate("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getDate(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getDouble("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getDouble(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getFloat("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getFloat(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getInt("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getInt(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getLong("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getLong(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getNCharacterStream("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getNCharacterStream(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getNClob("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getNClob(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setNClob("param_name", new FakeNClob()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setNClob("param_name", new FakeReader(), 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setNClob("param_name", new FakeReader()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getNString("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getNString(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getObject("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getObject(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getObject(1, String.class); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getRef("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getRef(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getRowId("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getRowId(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getShort("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getShort(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getSQLXML("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getSQLXML(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getString("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getString(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getTime("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getTime(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getTimestamp(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getTimestamp("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getURL("param_name"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getURL(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getString(1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBigDecimal("param_name", BigDecimal.ONE); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBoolean("param_name", true); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setByte("param_name", (byte) 6); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBytes("param_name", "bytes".getBytes()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBytes(1, "bytes".getBytes()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setDate("param_name", Date.valueOf("2019-07-07")); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setDouble("param_name", 3.0); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setFloat("param_name", 3.0f); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setInt("param_name", 3); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setLong("param_name", 3L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setNString("param_name", "test"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setNull("param_name", Types.NULL); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setNull("param_name", Types.NULL, "null"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setObject("param_name", new Object()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setObject("param_name", new Object(), Types.JAVA_OBJECT); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setObject("param_name", new Object(), Types.JAVA_OBJECT, 2); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setShort("param_name", (short) 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setString("param_name", "test"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setTime("param_name", new Time(50)); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setTimestamp("param_name", new Timestamp(50), Calendar.getInstance()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setTimestamp( + "param_name", new Timestamp(50), Calendar.getInstance()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setTimestamp("param_name", new Timestamp(50)); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setURL(1, new URL("http://localhost:8888")); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setAsciiStream("param_name", new FakeInputStream()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setAsciiStream("param_name", new FakeInputStream(), 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setAsciiStream("param_name", new FakeInputStream(), 5213L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBinaryStream("param_name", new FakeInputStream()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBinaryStream("param_name", new FakeInputStream(), 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBinaryStream("param_name", new FakeInputStream(), 5213L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBlob("param_name", new FakeInputStream()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBlob("param_name", new FakeInputStream(), 1L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setBlob("param_name", new ServiceBlob()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setCharacterStream("param_name", new FakeReader()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setCharacterStream("param_name", new FakeReader(), 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setCharacterStream("param_name", new FakeReader(), 1L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setClob("param_name", new FakeReader()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setClob("param_name", new FakeReader(), 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setClob("param_name", new FakeNClob()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setClob("param_name", new FakeNClob()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setDate( + "param_name", Date.valueOf("2019-07-07"), Calendar.getInstance()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getTime("param_name", Calendar.getInstance()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getTime(1, Calendar.getInstance()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getObject("param_name", String.class); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getObject("param_name", new HashMap<>()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getDate(1, Calendar.getInstance()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.getDate("param_name", Calendar.getInstance()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setRowId("param_name", new FakeRowId()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setSQLXML("param_name", new FakeSQLXML()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + cstm2.setSQLXML("param_name", new FakeSQLXML()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + + } + +} diff --git a/test/src/test/java/com/fanruan/BaseJDBCTest.java b/test/src/test/java/com/fanruan/BaseJDBCTest.java new file mode 100644 index 0000000..564074c --- /dev/null +++ b/test/src/test/java/com/fanruan/BaseJDBCTest.java @@ -0,0 +1,432 @@ +package com.fanruan; + +import com.fanruan.annotation.RemoteClass; +import com.fanruan.pojo.message.RpcRequest; +import com.fanruan.service.jdbc.AbstractBind; +import com.fanruan.utils.Commons; + +import javax.xml.transform.Result; +import javax.xml.transform.Source; +import java.io.*; +import java.sql.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * @author Yichen Dai + * @date 2022/8/23 15:47 + */ + + +public class BaseJDBCTest extends AbstractDriverTest{ + final String dbName = "hsql"; + final Map map = new HashMap(1); + + int getSizeOfResultSet(ResultSet rs) throws SQLException { + int count = 0; + while (rs.next()) { + count++; + } + return count; + } + + List getInfoBySQL(String sqlCmd) throws SQLException { + Connection con = getConnection(); + Statement st = con.createStatement(); + List result = new ArrayList<>(); + ResultSet rs = st.executeQuery(sqlCmd); + while (rs.next()) { + result.add(rs.getString(1)); + } + return result; + } + + public RpcRequest createRequest(AbstractBind bind, String methodName, Object[] args, Class[] argTypes) { + RpcRequest request = new RpcRequest(); + + request.setID(Commons.getID()) + .setIDToInvoke(bind.getID()) + .setMethodName(methodName) + .setArgs(args) + .setArgTypes(argTypes); + + Class clazz = bind.getClass(); + + if(clazz.isAnnotationPresent(RemoteClass.class)){ + RemoteClass annotation = (RemoteClass) clazz.getAnnotation(RemoteClass.class); + request.setServiceClassName(annotation.remoteClassName()); + }else{ + request.setServiceClassName(clazz.getName()); + } + return request; + } + + public boolean isEqualRequest(RpcRequest r1, RpcRequest r2){ + String[] s1 = new String[]{ + r1.getID(), + r1.getIDToInvoke(), + r1.getMethodName(), + r1.getServiceClassName() + }; + + String[] s2 = new String[]{ + r2.getID(), + r2.getIDToInvoke(), + r2.getMethodName(), + r2.getServiceClassName() + }; + + if(isNotEqualStringArray(s1, s2)){ + return false; + } + + Object[] o1 = r1.getArgs(); + Object[] o2 = r2.getArgs(); + int o1_len = o1.length; + int o2_len = o2.length; + String[] o1_sa = new String[o1_len]; + String[] o2_sa = new String[o2_len]; + + for(int i=0; i[] c1 = r1.getArgTypes(); + Class[] c2 = r2.getArgTypes(); + int c1_len = c1.length; + int c2_len = c2.length; + String[] c1_sa = new String[c1_len]; + String[] c2_sa = new String[c2_len]; + + for(int i=0; i T getSource(Class sourceClass) throws SQLException { + return null; + } + + @Override + public T setResult(Class resultClass) throws SQLException { + return null; + } +} + +class FakeBlob implements Blob { + @Override + public long length() throws SQLException { + return 0; + } + + @Override + public byte[] getBytes(long pos, int length) throws SQLException { + return new byte[0]; + } + + @Override + public InputStream getBinaryStream() throws SQLException { + return null; + } + + @Override + public long position(byte[] pattern, long start) throws SQLException { + return 0; + } + + @Override + public long position(Blob pattern, long start) throws SQLException { + return 0; + } + + @Override + public int setBytes(long pos, byte[] bytes) throws SQLException { + return 0; + } + + @Override + public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { + return 0; + } + + @Override + public OutputStream setBinaryStream(long pos) throws SQLException { + return null; + } + + @Override + public void truncate(long len) throws SQLException {} + + @Override + public void free() throws SQLException {} + + @Override + public InputStream getBinaryStream(long pos, long length) throws SQLException { + return null; + } +} + +class FakeArray implements Array { + @Override + public String getBaseTypeName() throws SQLException { + return null; + } + + @Override + public int getBaseType() throws SQLException { + return 0; + } + + @Override + public Object getArray() throws SQLException { + return null; + } + + @Override + public Object getArray(Map> map) throws SQLException { + return null; + } + + @Override + public Object getArray(long index, int count) throws SQLException { + return null; + } + + @Override + public Object getArray(long index, int count, Map> map) throws SQLException { + return null; + } + + @Override + public ResultSet getResultSet() throws SQLException { + return null; + } + + @Override + public ResultSet getResultSet(Map> map) throws SQLException { + return null; + } + + @Override + public ResultSet getResultSet(long index, int count) throws SQLException { + return null; + } + + @Override + public ResultSet getResultSet(long index, int count, Map> map) + throws SQLException { + return null; + } + + @Override + public void free() throws SQLException {} +} + +class FakeRowId implements RowId { + @Override + public byte[] getBytes() { + return new byte[0]; + } +} + +class FakeNClob implements NClob { + @Override + public long length() throws SQLException { + return 0; + } + + @Override + public String getSubString(long pos, int length) throws SQLException { + return null; + } + + @Override + public Reader getCharacterStream() throws SQLException { + return null; + } + + @Override + public InputStream getAsciiStream() throws SQLException { + return null; + } + + @Override + public long position(String searchstr, long start) throws SQLException { + return 0; + } + + @Override + public long position(Clob searchstr, long start) throws SQLException { + return 0; + } + + @Override + public int setString(long pos, String str) throws SQLException { + return 0; + } + + @Override + public int setString(long pos, String str, int offset, int len) throws SQLException { + return 0; + } + + @Override + public OutputStream setAsciiStream(long pos) throws SQLException { + return null; + } + + @Override + public Writer setCharacterStream(long pos) throws SQLException { + return null; + } + + @Override + public void truncate(long len) throws SQLException {} + + @Override + public void free() throws SQLException {} + + @Override + public Reader getCharacterStream(long pos, long length) throws SQLException { + return null; + } +} + +class FakeRef implements Ref { + + @Override + public String getBaseTypeName() throws SQLException { + return null; + } + + @Override + public Object getObject(Map> map) throws SQLException { + return null; + } + + @Override + public Object getObject() throws SQLException { + return null; + } + + @Override + public void setObject(Object value) throws SQLException {} +} + +class FakeSavepoint implements Savepoint{ + + @Override + public int getSavepointId() throws SQLException { + return 0; + } + + @Override + public String getSavepointName() throws SQLException { + return null; + } +} diff --git a/test/src/test/java/com/fanruan/ConnectionTest.java b/test/src/test/java/com/fanruan/ConnectionTest.java new file mode 100644 index 0000000..a4707fc --- /dev/null +++ b/test/src/test/java/com/fanruan/ConnectionTest.java @@ -0,0 +1,314 @@ +package com.fanruan; + +import com.fanruan.cache.BeanCacheImpl; +import com.fanruan.exception.NotImplementedException; +import com.fanruan.handler.DispatcherImpl; +import com.fanruan.pojo.message.RpcRequest; +import com.fanruan.service.jdbc.connection.ServiceConnection; +import org.junit.jupiter.api.*; + +import java.sql.*; +import java.util.Collections; +import java.util.HashMap; +import java.util.Properties; + +/** + * @author Yichen Dai + * @date 2022/8/30 10:23 + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +public class ConnectionTest extends BaseJDBCTest{ + + Connection connection = null; + String IDtoInvoke = ""; + BeanCacheImpl beanCache = null; + DispatcherImpl dispatcher = null; + ServiceConnection serviceConnection = null; + + @BeforeAll + public void setUp() throws SQLException { + openSocket(); + connection = getConnection(); + ServiceConnection conn = (ServiceConnection) connection; + IDtoInvoke = conn.getID(); + dispatcher = agent.dispatcherImpl; + beanCache = dispatcher.CACHE.getBeanCache(dbName); + serviceConnection = (ServiceConnection) ProxyFactoryIT.getProxy(ServiceConnection.class, map); + } + + @Test + public void testSetCatalogSchema() throws Throwable{ + String db = connection.getCatalog(); + String schema = connection.getSchema(); + connection.setCatalog(db); + connection.setSchema("PUBLIC"); + + // get the current schema + ResultSet rst = connection.createStatement().executeQuery("SELECT * " + + "FROM INFORMATION_SCHEMA.TABLES"); + Assertions.assertTrue(rst.next()); + Assertions.assertEquals("PUBLIC", rst.getString(1)); + Assertions.assertEquals(db, connection.getCatalog()); + Assertions.assertEquals("PUBLIC", connection.getSchema()); + + // get the current schema + connection.setSchema(schema); + rst = connection.createStatement().executeQuery("SELECT * " + + "FROM INFORMATION_SCHEMA.TABLES"); + Assertions.assertTrue(rst.next()); + Assertions.assertEquals(schema, rst.getString(1)); + rst.close(); + } + + @Test + public void testConnection() throws Throwable { + Properties property = connection.getClientInfo(); + Assertions.assertNull(property); + Properties clientInfo = new Properties(); + clientInfo.setProperty("name", "Peter"); + clientInfo.setProperty("description", "HSQLDB JDBC"); + + Assertions.assertThrows(SQLClientInfoException.class, () -> { + serviceConnection.setClientInfo("name", "peter"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + + Assertions.assertThrows(SQLClientInfoException.class, () -> { + serviceConnection.setClientInfo(clientInfo); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + } + + @Test + public void testNetworkTimeout() throws SQLException { + int millis = connection.getNetworkTimeout(); + Assertions.assertEquals(0, millis); + Assertions.assertThrows(SQLFeatureNotSupportedException.class, () -> { + serviceConnection.setNetworkTimeout(null, 200); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + } + + @Test + public void testAbort() throws SQLException { + Assertions.assertThrows(SQLException.class, () -> { + serviceConnection.abort(null); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + } + + @Test + public void testClose() throws SQLException { + Connection conn = getConnection(); + Assertions.assertFalse(conn.isClosed()); + conn.close(); + Assertions.assertTrue(conn.isClosed()); + } + + @Test + public void testHoldability() throws Throwable { + connection.setHoldability(ResultSet.CLOSE_CURSORS_AT_COMMIT); + Assertions.assertEquals(ResultSet.CLOSE_CURSORS_AT_COMMIT, connection.getHoldability()); + } + + @Test + public void testIsValid() throws Throwable { + Assertions.assertTrue(connection.isValid(10)); + } + + @Test + public void testUnwrapper() throws SQLException { + boolean canUnwrap = connection.isWrapperFor(Connection.class); + Assertions.assertTrue(canUnwrap); + Assertions.assertThrows(NotImplementedException.class, + () -> connection.unwrap(null)); + } + + @Test + public void testNativeSQL() throws SQLException { + Assertions.assertEquals("select 1", connection.nativeSQL("select 1")); + } + + @Test + public void testTypeMap() throws Throwable { + Assertions.assertEquals(Collections.emptyMap(), connection.getTypeMap()); + Assertions.assertThrows(SQLException.class, () -> { + serviceConnection.setTypeMap(new HashMap<>()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + } + + @Test + public void setReadOnly() throws SQLException { + Assertions.assertFalse(connection.isReadOnly()); + connection.setReadOnly(true); + Assertions.assertTrue(connection.isReadOnly()); + } + + @Test + public void setTransactionIsolation() throws SQLException { + Connection conn = getConnection(); + Assertions.assertEquals(Connection.TRANSACTION_READ_COMMITTED ,conn.getTransactionIsolation()); + conn.setTransactionIsolation(Connection.TRANSACTION_SERIALIZABLE); + Assertions.assertEquals(Connection.TRANSACTION_SERIALIZABLE, conn.getTransactionIsolation()); + closeSQLObjects(conn); + } + + @Test + public void testGetWarning() throws SQLException { + connection.clearWarnings(); + Assertions.assertNull(connection.getWarnings()); + } + + @Test + public void testCreateStatement() throws SQLException { + Statement st1 = connection.createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_FORWARD_ONLY); + Statement st2 = connection.createStatement( + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CLOSE_CURSORS_AT_COMMIT + ); + + closeSQLObjects(st1, st2); + } + + @Test + void testPrepareStatement() throws SQLException { + PreparedStatement pst1 = connection.prepareStatement( + "select 1", + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_FORWARD_ONLY + ); + + PreparedStatement pst2 = connection.prepareStatement( + "select 1", + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CLOSE_CURSORS_AT_COMMIT + ); + + PreparedStatement pst3 = connection.prepareStatement( + "select 2", + Statement.NO_GENERATED_KEYS + ); + + PreparedStatement pst4 = connection.prepareStatement( + "select 2", + new int[]{0} + ); + + PreparedStatement pst5 = connection.prepareStatement( + "select 2", + new String[]{"column_name"} + ); + + closeSQLObjects(pst1, pst2, pst3, pst4, pst5); + } + + @Test + void testCallableStatement() throws SQLException { + Statement statement = connection.createStatement(); + + statement.executeUpdate("CREATE TABLE city (id INTEGER, name varchar(20)); "); + statement.executeUpdate("INSERT INTO city VALUES (1, '成都'), (2, '上海'); "); + + CallableStatement cst1 = connection.prepareCall( + "CREATE PROCEDURE get_city_name(" + + "IN c_id INT, " + + "OUT city_name varchar(20)) " + + "READS SQL DATA " + + "BEGIN ATOMIC " + + " SELECT city.name INTO city_name FROM city WHERE id = c_id; " + + "END;", + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_FORWARD_ONLY + ); + + CallableStatement cst2 = connection.prepareCall( + "CREATE PROCEDURE get_city_name(" + + "IN c_id INT, " + + "OUT city_name varchar(20)) " + + "READS SQL DATA " + + "BEGIN ATOMIC " + + " SELECT city.name INTO city_name FROM city WHERE id = c_id; " + + "END;", + ResultSet.TYPE_SCROLL_INSENSITIVE, + ResultSet.TYPE_FORWARD_ONLY, + ResultSet.CLOSE_CURSORS_AT_COMMIT + ); + + closeSQLObjects(cst1, cst2); + } + + @Test + void testSavePoint() throws SQLException { + Assertions.assertThrows(SQLException.class, () -> { + serviceConnection.setSavepoint(); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + + Assertions.assertThrows(SQLException.class, () -> { + serviceConnection.setSavepoint("savePoint"); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + + Assertions.assertThrows(SQLException.class, () -> { + serviceConnection.rollback(new FakeSavepoint()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + + Assertions.assertThrows(SQLException.class, () -> { + serviceConnection.releaseSavepoint(new FakeSavepoint()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + } + + @Test + void testCreateArrayOf() throws SQLException { + Array array = connection.createArrayOf("DOUBLE", new Double[]{0.1, 0.2}); + } + + @Test + void testCreateStruct() throws SQLException{ + Assertions.assertThrows(SQLException.class, () -> { + serviceConnection.createStruct( "java.lang.String", new String[]{"hello"}); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest(request, beanCache); + }); + } + + @Test + void testAutoCommit() throws SQLException { + Connection conn = getConnection(); + Assertions.assertTrue(conn.getAutoCommit()); + conn.setAutoCommit(false); + Assertions.assertFalse(conn.getAutoCommit()); + } + + @Test + void testGetMetaData() throws SQLException { + DatabaseMetaData metaData = connection.getMetaData(); + } +} diff --git a/test/src/test/java/com/fanruan/DatabaseMetaDataTest.java b/test/src/test/java/com/fanruan/DatabaseMetaDataTest.java new file mode 100644 index 0000000..7423153 --- /dev/null +++ b/test/src/test/java/com/fanruan/DatabaseMetaDataTest.java @@ -0,0 +1,21 @@ +package com.fanruan; + +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; + +import java.sql.Connection; +import java.sql.DatabaseMetaData; +import java.sql.SQLException; + +/** + * @author Yichen Dai + * @date 2022/8/31 18:18 + */ +public class DatabaseMetaDataTest extends BaseJDBCTest{ + @Test + public void testGetConnection() throws SQLException { + Connection conn = getConnection(); + DatabaseMetaData metaData = conn.getMetaData(); + Assertions.assertEquals(conn, metaData.getConnection()); + } +} diff --git a/test/src/test/java/com/fanruan/InterceptorIT.java b/test/src/test/java/com/fanruan/InterceptorIT.java new file mode 100644 index 0000000..5e3eca6 --- /dev/null +++ b/test/src/test/java/com/fanruan/InterceptorIT.java @@ -0,0 +1,38 @@ +package com.fanruan; + +import com.fanruan.pojo.message.RpcRequest; +import com.fanruan.proxy.interceptor.InterceptorUtils; +import net.sf.cglib.proxy.MethodInterceptor; +import net.sf.cglib.proxy.MethodProxy; + +import java.lang.reflect.Method; +import java.util.Map; +import java.util.Properties; + +/** + * @author Yichen Dai + * @date 2022/8/29 11:11 + */ +public class InterceptorIT implements MethodInterceptor { + Class clazz; + Map map; + + + InterceptorIT(Class clazz, Map map){ + this.clazz = clazz; + this.map = map; + } + + @Override + public Object intercept(Object o, Method method, Object[] objects, MethodProxy methodProxy) throws Throwable { + if(InterceptorUtils.isNotImplemented(method) + || InterceptorUtils.isLocalMethod(method)){ + return methodProxy.invokeSuper(o, objects); + } + + RpcRequest request = InterceptorUtils.generateRequest(clazz, o, method, objects); + map.put(null, request); + + return methodProxy.invokeSuper(o, objects); + } +} diff --git a/test/src/test/java/com/fanruan/ProxyFactoryIT.java b/test/src/test/java/com/fanruan/ProxyFactoryIT.java new file mode 100644 index 0000000..f78cf83 --- /dev/null +++ b/test/src/test/java/com/fanruan/ProxyFactoryIT.java @@ -0,0 +1,23 @@ +package com.fanruan; + +import com.fanruan.pojo.message.RpcRequest; +import com.fanruan.proxy.interceptor.Interceptor; +import net.sf.cglib.proxy.Enhancer; + +import java.util.Map; +import java.util.Properties; + +/** + * @author Yichen Dai + * @date 2022/8/29 11:15 + */ +public class ProxyFactoryIT { + + public static Object getProxy(Class clazz, Map map){ + final Enhancer enhancer = new Enhancer(); + enhancer.setClassLoader(clazz.getClassLoader()); + enhancer.setSuperclass(clazz); + enhancer.setCallback(new InterceptorIT(clazz, map)); + return enhancer.create(); + } +} diff --git a/test/src/test/java/com/fanruan/TestUtil.java b/test/src/test/java/com/fanruan/TestUtil.java new file mode 100644 index 0000000..fcf4ead --- /dev/null +++ b/test/src/test/java/com/fanruan/TestUtil.java @@ -0,0 +1,183 @@ +package com.fanruan; + +import org.junit.jupiter.api.*; + +import java.sql.*; + + +/** + * @author Yichen Dai + * @date 2022/8/18 15:27 + */ + +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +@TestMethodOrder(MethodOrderer.OrderAnnotation.class) +@DisplayName("jdbc操作") +public class TestUtil extends BaseJDBCTest{ + + private Connection conn = null; + private Statement st = null; + private PreparedStatement pst = null; + + + @BeforeAll + void setup(){ + openSocket(); + } + + @Test + @Order(1) + void testConnect() throws SQLException { + conn = getConnection(); + } + + @Test + @Order(2) + void testCreateTable1() throws SQLException { + // 创建 statement + st = conn.createStatement(); + + // 创建表 + int num = st.executeUpdate("DROP TABLE student IF EXISTS;"); + + Assertions.assertEquals(0, num); + + + num = st.executeUpdate("CREATE TABLE student (" + + "student_id INTEGER GENERATED BY DEFAULT AS IDENTITY " + + "(START WITH 1, INCREMENT BY 1) NOT NULL," + + "student_name VARCHAR(100) NOT NULL," + + "student_address VARCHAR(100) NOT NULL," + + "PRIMARY KEY (student_id)" + + ");"); + + Assertions.assertEquals(0, num); + } + + @Test + @Order(3) + void testCreateTable2() throws SQLException { + // 创建表 + int num = st.executeUpdate("DROP TABLE student_score IF EXISTS;"); + + Assertions.assertEquals(0, num); + + + num = st.executeUpdate("CREATE TABLE score (" + + "student_id int(10) PRIMARY KEY NOT NULL," + + "score int(10) NOT NULL" + + ");" + ); + + Assertions.assertEquals(0, num); + } + + @Test + @Order(4) + void testInsert1() throws SQLException { + // 插入数据 + int num = st.executeUpdate("INSERT INTO student VALUES" + + "(1, '张三', '上海')," + + "(2, '李四', '北京')," + + "(3, '王五', '成都');"); + + Assertions.assertEquals(3, num); + } + + @Test + @Order(5) + void testInsert2() throws SQLException { + // 插入数据 + int num = st.executeUpdate("INSERT INTO score VALUES" + + "(1, 645)," + + "(2, 627)," + + "(3, 591);"); + + Assertions.assertEquals(3, num); + } + + @Test + @Order(6) + void testUpdate() throws SQLException { + // 预查询语句 删除指定 ID + pst = conn.prepareStatement("UPDATE student" + + " SET student_name = '李华', student_address = '杭州'"+ + "WHERE student_id = ?"); + + Assertions.assertNotNull(pst); + + pst.setInt(1, 1); + + int num = pst.executeUpdate(); + + Assertions.assertEquals(1, num); + } + + @Test + @Order(7) + void testDelete() throws SQLException { + // 预查询语句 删除指定 ID + pst = conn.prepareStatement("delete from student where student_id = ?"); + + Assertions.assertNotNull(pst); + + pst.setInt(1, 3); + + int num = pst.executeUpdate(); + + Assertions.assertEquals(1, num); + } + + @Test + @Order(8) + void testSelect() throws SQLException { + ResultSet rs = st.executeQuery("select * from student;"); + Assertions.assertEquals(2, getSizeOfResultSet(rs)); + closeSQLObjects(rs); + } + + @Test + @Order(9) + void testSubSelect() throws SQLException { + // 插入数据 + ResultSet rs = st.executeQuery( + "SELECT student_name FROM student " + + "WHERE student_id IN " + + "(SELECT student_id " + + "FROM score " + + "WHERE score > 600);" + ); + Assertions.assertEquals(2, getSizeOfResultSet(rs)); + closeSQLObjects(rs); + } + + @Test + @Order(10) + void testJoin() throws SQLException { + // 插入数据 + ResultSet rs = st.executeQuery( + "SELECT A.student_name " + + "FROM student A JOIN score B " + + "ON A.student_id = B.student_id " + + "WHERE score > 600;" + ); + + Assertions.assertEquals(2, getSizeOfResultSet(rs)); + closeSQLObjects(rs); + } + + @Test + @Order(10) + void testErrorQuery() throws SQLException { + // 插入数据 + ResultSet rs = st.executeQuery("SELECT * FROM TEACHER;"); + Assertions.assertFalse(rs.next()); + closeSQLObjects(rs); + } + + @AfterAll + void closeObject() throws SQLException { + closeSQLObjects(conn, st, pst); + } +} +