From a36a46581bc9076229906d534bbe3f5e699b4a5a Mon Sep 17 00:00:00 2001 From: yichen Date: Wed, 7 Sep 2022 10:43:34 +0800 Subject: [PATCH] =?UTF-8?q?integration=20testing=20:=20PrepareStatement?= =?UTF-8?q?=E3=80=81ResultsetMetaData=E3=80=81ParameterMetaData?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- ...aData.java => AgentResultSetMetaData.java} | 4 +- .../statement/AgentPreparedStatement.java | 7 +- agent/src/test/java/HSQLTest.java | 31 +- .../proxy/interceptor/Interceptor.java | 6 +- .../jdbc/ServiceParameterMetaData.java | 6 +- .../jdbc/ServiceResultSetMetaData.java | 6 +- .../statement/ServiceCallableStatement.java | 3 +- .../statement/ServicePreparedStatement.java | 26 +- .../test/java/com/fanruan/BaseJDBCTest.java | 70 +- ...ntTest.java => CallableStatementTest.java} | 4 +- .../com/fanruan/DatabaseMetaDataTest.java | 3 +- .../com/fanruan/PrepareStatementTest.java | 646 ++++++++++++++++++ 12 files changed, 787 insertions(+), 25 deletions(-) rename agent/src/main/java/com/fanruan/agent/jdbc/{AgentResultMetaData.java => AgentResultSetMetaData.java} (96%) rename test/src/test/java/com/fanruan/{AgentCallableStatementTest.java => CallableStatementTest.java} (99%) create mode 100644 test/src/test/java/com/fanruan/PrepareStatementTest.java diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/AgentResultMetaData.java b/agent/src/main/java/com/fanruan/agent/jdbc/AgentResultSetMetaData.java similarity index 96% rename from agent/src/main/java/com/fanruan/agent/jdbc/AgentResultMetaData.java rename to agent/src/main/java/com/fanruan/agent/jdbc/AgentResultSetMetaData.java index 8432d1a..bf84091 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/AgentResultMetaData.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/AgentResultSetMetaData.java @@ -7,10 +7,10 @@ import java.sql.SQLException; * @author Yichen Dai * @date 2022/9/1 14:45 */ -public class AgentResultMetaData implements ResultSetMetaData { +public class AgentResultSetMetaData implements ResultSetMetaData { private ResultSetMetaData metaData; - AgentResultMetaData(ResultSetMetaData metaData){ + public AgentResultSetMetaData(ResultSetMetaData metaData){ this.metaData = metaData; } diff --git a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentPreparedStatement.java b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentPreparedStatement.java index b9d32d2..56c5e83 100644 --- a/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentPreparedStatement.java +++ b/agent/src/main/java/com/fanruan/agent/jdbc/statement/AgentPreparedStatement.java @@ -1,6 +1,8 @@ package com.fanruan.agent.jdbc.statement; +import com.fanruan.agent.jdbc.AgentParameterMetaData; +import com.fanruan.agent.jdbc.AgentResultSetMetaData; import com.fanruan.agent.jdbc.resultset.AgentResultSet; import java.io.InputStream; @@ -108,6 +110,7 @@ public class AgentPreparedStatement implements PreparedStatement { @Override public void setUnicodeStream(int parameterIndex, InputStream x, int length) throws SQLException { + pst.setUnicodeStream(parameterIndex, x, length); } @Override @@ -167,7 +170,7 @@ public class AgentPreparedStatement implements PreparedStatement { @Override public ResultSetMetaData getMetaData() throws SQLException { - return pst.getMetaData(); + return new AgentResultSetMetaData(pst.getMetaData()); } @Override @@ -197,7 +200,7 @@ public class AgentPreparedStatement implements PreparedStatement { @Override public ParameterMetaData getParameterMetaData() throws SQLException { - return pst.getParameterMetaData(); + return new AgentParameterMetaData(pst.getParameterMetaData()); } @Override diff --git a/agent/src/test/java/HSQLTest.java b/agent/src/test/java/HSQLTest.java index 4e685c0..2886889 100644 --- a/agent/src/test/java/HSQLTest.java +++ b/agent/src/test/java/HSQLTest.java @@ -12,7 +12,7 @@ import java.sql.*; public class HSQLTest { @BeforeEach - void startHSQL(){ + void startHSQL() { try { Class.forName(DBProperties.HSQL[1]); Thread.sleep(1000); @@ -29,11 +29,38 @@ public class HSQLTest { Assertions.assertNotNull(conn, "can't get connection"); } catch (SQLException e) { e.printStackTrace(); - }finally { + } finally { conn.close(); } } + @Test + public void testPrepareDDL() throws SQLException { + Connection connection = DriverManager.getConnection("jdbc:hsqldb:mem:test;sql.syntax_mys=true", "sa", ""); + try { + try (PreparedStatement prepStatement = + connection.prepareStatement("CREATE TABLE city (id INTEGER, name varchar(20)); ")) { + prepStatement.execute(); + } + + try (ResultSet resultSet = + connection.createStatement().executeQuery("SELECT \n" + + "TABLE_NAME\n" + + "FROM INFORMATION_SCHEMA.TABLES\n" + + "where TABLE_NAME like 'CITY';")) { + // result should only have one row since table is created + while(resultSet.next()){ + System.out.println(resultSet.getString(1)); + } + } + } finally { + connection.createStatement().execute("drop table if exists city"); + } + } + + + + private static String createStoredProcedure ="CREATE PROCEDURE get_city_name(" + "IN c_id INT, " + "OUT city_name varchar(20)) " + diff --git a/service/src/main/java/com/fanruan/proxy/interceptor/Interceptor.java b/service/src/main/java/com/fanruan/proxy/interceptor/Interceptor.java index 7de75e0..ea7749f 100644 --- a/service/src/main/java/com/fanruan/proxy/interceptor/Interceptor.java +++ b/service/src/main/java/com/fanruan/proxy/interceptor/Interceptor.java @@ -84,6 +84,9 @@ public class Interceptor implements MethodInterceptor { ServerStater.threadPool.submit(futureTask); Object res = futureTask.get(); + // get return value of original method + Object returnObj = methodProxy.invokeSuper(o, objects); + // res is not null, it indicates the response carries data. // if the type of res is primitive type, An error will occur when using cast(), just return them directly. // And the data carried by response will never be the instance need to be bound. @@ -94,14 +97,11 @@ public class Interceptor implements MethodInterceptor { return res; } - Object returnObj = methodProxy.invokeSuper(o, objects); - // If the return instance is corresponding with another instance in agent, set the binding ID. if (InterceptorUtils.isInBindList(returnObj)){ AbstractBind ab = (AbstractBind) returnObj; ab.setID(rpcRequest.getID()); } - return returnObj; } } \ No newline at end of file diff --git a/service/src/main/java/com/fanruan/service/jdbc/ServiceParameterMetaData.java b/service/src/main/java/com/fanruan/service/jdbc/ServiceParameterMetaData.java index 1d3786e..6511fd5 100644 --- a/service/src/main/java/com/fanruan/service/jdbc/ServiceParameterMetaData.java +++ b/service/src/main/java/com/fanruan/service/jdbc/ServiceParameterMetaData.java @@ -1,5 +1,7 @@ package com.fanruan.service.jdbc; +import com.fanruan.annotation.LocalMethod; +import com.fanruan.annotation.NotImplemented; import com.fanruan.annotation.RemoteClass; import java.sql.ParameterMetaData; @@ -58,8 +60,10 @@ public class ServiceParameterMetaData extends BasedBind implements ParameterMeta } @Override + @LocalMethod + @NotImplemented public T unwrap(Class iface) throws SQLException { - return null; + throw new SQLException("Not Implement!"); } @Override diff --git a/service/src/main/java/com/fanruan/service/jdbc/ServiceResultSetMetaData.java b/service/src/main/java/com/fanruan/service/jdbc/ServiceResultSetMetaData.java index 859bfde..e98751e 100644 --- a/service/src/main/java/com/fanruan/service/jdbc/ServiceResultSetMetaData.java +++ b/service/src/main/java/com/fanruan/service/jdbc/ServiceResultSetMetaData.java @@ -1,5 +1,7 @@ package com.fanruan.service.jdbc; +import com.fanruan.annotation.LocalMethod; +import com.fanruan.annotation.NotImplemented; import com.fanruan.annotation.RemoteClass; import java.sql.ResultSetMetaData; @@ -118,8 +120,10 @@ public class ServiceResultSetMetaData extends BasedBind implements ResultSetMeta } @Override + @NotImplemented + @LocalMethod public T unwrap(Class iface) throws SQLException { - return null; + throw new SQLException("Not Implement"); } @Override diff --git a/service/src/main/java/com/fanruan/service/jdbc/statement/ServiceCallableStatement.java b/service/src/main/java/com/fanruan/service/jdbc/statement/ServiceCallableStatement.java index 8ff96af..41f01df 100644 --- a/service/src/main/java/com/fanruan/service/jdbc/statement/ServiceCallableStatement.java +++ b/service/src/main/java/com/fanruan/service/jdbc/statement/ServiceCallableStatement.java @@ -5,6 +5,7 @@ import com.fanruan.proxy.ProxyFactory; import com.fanruan.service.jdbc.AbstractBind; import com.fanruan.service.jdbc.BasedBind; import com.fanruan.service.jdbc.ServiceParameterMetaData; +import com.fanruan.service.jdbc.ServiceResultSetMetaData; import com.fanruan.service.jdbc.resultset.ServiceResultSet; import java.io.InputStream; @@ -740,7 +741,7 @@ public class ServiceCallableStatement extends BasedBind implements CallableState @Override public ResultSetMetaData getMetaData() throws SQLException { - return null; + return (ResultSetMetaData) ProxyFactory.getProxy(ServiceResultSetMetaData.class, info); } @Override diff --git a/service/src/main/java/com/fanruan/service/jdbc/statement/ServicePreparedStatement.java b/service/src/main/java/com/fanruan/service/jdbc/statement/ServicePreparedStatement.java index 0a2ca29..25f97fb 100644 --- a/service/src/main/java/com/fanruan/service/jdbc/statement/ServicePreparedStatement.java +++ b/service/src/main/java/com/fanruan/service/jdbc/statement/ServicePreparedStatement.java @@ -1,8 +1,11 @@ package com.fanruan.service.jdbc.statement; +import com.fanruan.annotation.LocalMethod; +import com.fanruan.annotation.NotImplemented; import com.fanruan.annotation.RemoteClass; -import com.fanruan.service.jdbc.AbstractBind; import com.fanruan.service.jdbc.BasedBind; +import com.fanruan.service.jdbc.ServiceParameterMetaData; +import com.fanruan.service.jdbc.ServiceResultSetMetaData; import com.fanruan.service.jdbc.resultset.ServiceResultSet; import com.fanruan.proxy.ProxyFactory; @@ -169,7 +172,7 @@ public class ServicePreparedStatement extends BasedBind implements PreparedState @Override public ResultSetMetaData getMetaData() throws SQLException { - return null; + return (ResultSetMetaData) ProxyFactory.getProxy(ServiceResultSetMetaData.class, info); } @Override @@ -199,7 +202,7 @@ public class ServicePreparedStatement extends BasedBind implements PreparedState @Override public ParameterMetaData getParameterMetaData() throws SQLException { - return null; + return (ParameterMetaData) ProxyFactory.getProxy(ServiceParameterMetaData.class, info); } @Override @@ -299,7 +302,9 @@ public class ServicePreparedStatement extends BasedBind implements PreparedState @Override public ResultSet executeQuery(String sql) throws SQLException { - return null; + ServiceResultSet rs = (ServiceResultSet) ProxyFactory.getProxy(ServiceResultSet.class, info); + rs.setInfo(info); + return rs; } @Override @@ -374,7 +379,9 @@ public class ServicePreparedStatement extends BasedBind implements PreparedState @Override public ResultSet getResultSet() throws SQLException { - return null; + ServiceResultSet rs = (ServiceResultSet) ProxyFactory.getProxy(ServiceResultSet.class, info); + rs.setInfo(info); + return rs; } @Override @@ -444,7 +451,9 @@ public class ServicePreparedStatement extends BasedBind implements PreparedState @Override public ResultSet getGeneratedKeys() throws SQLException { - return null; + ServiceResultSet rs = (ServiceResultSet) ProxyFactory.getProxy(ServiceResultSet.class, info); + rs.setInfo(info); + return rs; } @Override @@ -489,7 +498,6 @@ public class ServicePreparedStatement extends BasedBind implements PreparedState @Override public void setPoolable(boolean poolable) throws SQLException { - } @Override @@ -508,8 +516,10 @@ public class ServicePreparedStatement extends BasedBind implements PreparedState } @Override + @NotImplemented + @LocalMethod public T unwrap(Class iface) throws SQLException { - return null; + throw new SQLException("Not Implemented!"); } @Override diff --git a/test/src/test/java/com/fanruan/BaseJDBCTest.java b/test/src/test/java/com/fanruan/BaseJDBCTest.java index 564074c..5fb2b92 100644 --- a/test/src/test/java/com/fanruan/BaseJDBCTest.java +++ b/test/src/test/java/com/fanruan/BaseJDBCTest.java @@ -161,7 +161,7 @@ public class BaseJDBCTest extends AbstractDriverTest{ class FakeInputStream extends InputStream { @Override public int read() throws IOException { - return 0; + return -1; } } @@ -430,3 +430,71 @@ class FakeSavepoint implements Savepoint{ return null; } } + +class FakeClob implements Clob{ + + @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; + } +} diff --git a/test/src/test/java/com/fanruan/AgentCallableStatementTest.java b/test/src/test/java/com/fanruan/CallableStatementTest.java similarity index 99% rename from test/src/test/java/com/fanruan/AgentCallableStatementTest.java rename to test/src/test/java/com/fanruan/CallableStatementTest.java index 51b6fb5..c48a32e 100644 --- a/test/src/test/java/com/fanruan/AgentCallableStatementTest.java +++ b/test/src/test/java/com/fanruan/CallableStatementTest.java @@ -27,7 +27,7 @@ import java.util.*; @TestInstance(TestInstance.Lifecycle.PER_CLASS) @TestMethodOrder(MethodOrderer.OrderAnnotation.class) -public class AgentCallableStatementTest extends BaseJDBCTest{ +public class CallableStatementTest extends BaseJDBCTest{ private Connection conn = null; private Statement statement = null; @@ -73,8 +73,6 @@ public class AgentCallableStatementTest extends BaseJDBCTest{ callableStatement.registerOutParameter(2, Types.VARCHAR); callableStatement.execute(); Assertions.assertEquals("上海", callableStatement.getString(2)); - - } @Test diff --git a/test/src/test/java/com/fanruan/DatabaseMetaDataTest.java b/test/src/test/java/com/fanruan/DatabaseMetaDataTest.java index 1be3d53..f33fbc3 100644 --- a/test/src/test/java/com/fanruan/DatabaseMetaDataTest.java +++ b/test/src/test/java/com/fanruan/DatabaseMetaDataTest.java @@ -27,7 +27,8 @@ public class DatabaseMetaDataTest extends BaseJDBCTest{ } @Test - public void testNotImplemented() throws SQLException{ + public void testWrap() throws SQLException{ + Assertions.assertFalse(metaData.isWrapperFor(null)); Assertions.assertThrows(SQLException.class, () -> metaData.unwrap(null)); } diff --git a/test/src/test/java/com/fanruan/PrepareStatementTest.java b/test/src/test/java/com/fanruan/PrepareStatementTest.java new file mode 100644 index 0000000..e978a32 --- /dev/null +++ b/test/src/test/java/com/fanruan/PrepareStatementTest.java @@ -0,0 +1,646 @@ +package com.fanruan; + +import com.fanruan.cache.BeanCacheImpl; +import com.fanruan.handler.DispatcherImpl; +import com.fanruan.pojo.message.RpcRequest; +import com.fanruan.service.jdbc.ServiceArray; +import com.fanruan.service.jdbc.ServiceResultSetMetaData; +import com.fanruan.service.jdbc.statement.ServiceCallableStatement; +import com.fanruan.service.jdbc.statement.ServicePreparedStatement; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.BeforeAll; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.TestInstance; + +import java.math.BigDecimal; +import java.net.URL; +import java.sql.*; +import java.util.Arrays; +import java.util.Calendar; + +/** + * @author Yichen Dai + * @date 2022/9/6 9:17 + */ +@TestInstance(TestInstance.Lifecycle.PER_CLASS) +public class PrepareStatementTest extends BaseJDBCTest{ + + private Connection connection = null; + private PreparedStatement preparedStatement = null; + + + @BeforeAll + void setup() throws SQLException { + openSocket(); + this.connection = getConnection(); + Statement statement = connection.createStatement(); + statement.executeUpdate("CREATE TABLE city (id INTEGER, name varchar(20)); "); + + this.preparedStatement = connection.prepareStatement( + "INSERT INTO city VALUES (1, '成都');" + ); + } + + @Test + public void testPrepareDDL() throws SQLException { + try { + try (PreparedStatement prepStatement = + connection.prepareStatement("CREATE TABLE testPrepareDDL (id INTEGER);")) { + prepStatement.execute(); + } + + // HSQLDB treats unquoted identifiers as case insensitive and stores them in upper case. + try (ResultSet resultSet = + connection.createStatement().executeQuery("SELECT \n" + + "*\n" + + "FROM INFORMATION_SCHEMA.TABLES\n" + + "WHERE TABLE_NAME LIKE 'TESTPREPAREDDL';")) { + // result should only have one row since table is created + Assertions.assertEquals(1, getSizeOfResultSet(resultSet)); + } + } finally { + connection.createStatement().execute("drop table if exists TESTPREPAREDDL"); + } + } + + @Test + public void testWrap() throws SQLException { + Assertions.assertFalse(preparedStatement.isWrapperFor(null)); + Assertions.assertThrows(SQLException.class, () -> preparedStatement.unwrap(null)); + } + + @Test + public void testMethodsThrow() throws SQLException{ + ServicePreparedStatement pstm = (ServicePreparedStatement) this.preparedStatement; + String IDtoInvoke = pstm.getID(); + + DispatcherImpl dispatcher = agent.dispatcherImpl; + BeanCacheImpl beanCache = dispatcher.CACHE.getBeanCache(dbName); + + ServicePreparedStatement pstm2 = (ServicePreparedStatement) ProxyFactoryIT.getProxy(ServicePreparedStatement.class, map); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setNClob(1, new FakeNClob()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setNull(1, Types.INTEGER); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setObject(1, null); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setRef(1, null); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setRowId(1, null); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setShort(1, Short.parseShort("0")); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setSQLXML(1, new FakeSQLXML()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setArray(1, null); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setAsciiStream(1, new FakeInputStream()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setAsciiStream(1, new FakeInputStream(), 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setAsciiStream(1, new FakeInputStream(), 1L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setBigDecimal(1, new BigDecimal(0)); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> { + pstm2.setBinaryStream(0, new FakeInputStream()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> { + pstm2.setBinaryStream(1, new FakeInputStream(), 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> { + pstm2.setBinaryStream(1, new FakeInputStream(), 1L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setBlob(1, new FakeBlob()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> { + pstm2.setBlob(1, new FakeInputStream()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> { + pstm2.setBlob(1, new FakeInputStream(), 1L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setBoolean(1, false); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setByte(1, Byte.parseByte("0")); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setBytes(1, new byte[]{}); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setCharacterStream(1, new FakeReader()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> { + pstm2.setCharacterStream(1, new FakeReader(), 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> { + pstm2.setCharacterStream(1, new FakeReader(), 1L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setClob(1, new FakeClob()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setClob(1, new FakeReader()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(ArrayIndexOutOfBoundsException.class, () -> { + pstm2.setClob(1, new FakeReader(), 1L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setDate(1, new Date(1)); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setDate(1, new Date(0), Calendar.getInstance()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setDouble(1, 0.0); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setFloat(1, 0.0f); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setInt(1, 0); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setLong(1, 0L); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setTimestamp(1, new Timestamp(50)); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setTimestamp(1, new Timestamp(50), Calendar.getInstance()); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setUnicodeStream(1, new FakeInputStream(), 1); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(SQLException.class, () -> { + pstm2.setURL(1, new URL("http://localhost:8888")); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(UnsupportedOperationException.class, () -> { + pstm2.executeLargeBatch(); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + Assertions.assertThrows(UnsupportedOperationException.class, () -> { + pstm2.getLargeUpdateCount(); + RpcRequest request = map.get(null); + request.setIDToInvoke(IDtoInvoke); + dispatcher.invokeAsRequest( + request, + beanCache); + } + ); + + pstm.setEscapeProcessing(false); + + + + + + pstm.setCursorName("name"); + + pstm.setPoolable(false); + + pstm.setQueryTimeout(2000); + } + + @Test + public void testFildSize() throws SQLException{ + preparedStatement.setMaxFieldSize(1000); + + // HSQLDB always returns zero, meaning there is no limit. + Assertions.assertEquals(0, preparedStatement.getMaxFieldSize()); + } + + @Test + public void testDirection() throws SQLException { + // Starting with 2.0, HSQLDB accepts any valid value. + preparedStatement.setFetchDirection(ResultSet.FETCH_FORWARD); + + Assertions.assertEquals(ResultSet.FETCH_FORWARD, preparedStatement.getFetchDirection()); + } + + @Test + public void testFectchSize() throws SQLException{ + preparedStatement.setFetchSize(0); + + Assertions.assertEquals(0, preparedStatement.getFetchSize()); + } + + @Test + public void testMaxRows() throws SQLException{ + preparedStatement.setMaxRows(1000); + + Assertions.assertEquals(1000, preparedStatement.getMaxRows()); + } + + @Test + public void testGet() throws SQLException{ + /** + * Retrieves the maximum number of rows that a ResultSet object produced by this Statement object can contain. If this limit is exceeded, the excess rows are silently dropped. + * This method should be used when the returned row limit may exceed Integer.MAX_VALUE. + * + * The default implementation will return 0 + */ + Assertions.assertEquals(0, preparedStatement.getLargeMaxRows()); + } + + @Test + public void testExecuteBatch() throws SQLException{ + + String SQL_INSERT = "INSERT INTO EMPLOYEE VALUES ?;"; + + String SQL_CREATE = "CREATE TABLE EMPLOYEE (NAME varchar(100));"; + + PreparedStatement psDDL = connection.prepareStatement(SQL_CREATE); + psDDL.execute(); + + PreparedStatement psInsert = connection.prepareStatement(SQL_INSERT); + + // Run list of insert commands + psInsert.setString(1, "mkyong"); + psInsert.addBatch(); + + psInsert.setString(1, "kungfu"); + psInsert.addBatch(); + + psInsert.setString(1, "james"); + psInsert.addBatch(); + + int[] rows = psInsert.executeBatch(); + Assertions.assertEquals(3, rows.length); + } + + @Test + public void testResultMetaData() throws SQLException { + PreparedStatement psmt = connection.prepareStatement("SELECT * FROM city WHERE id = ?"); + ResultSetMetaData metaData = psmt.getMetaData(); + + Assertions.assertEquals(2, metaData.getColumnCount()); + + Assertions.assertEquals("PUBLIC", metaData.getCatalogName(1)); + + Assertions.assertEquals("PUBLIC", metaData.getSchemaName(1)); + + // This reports the SQL type code of the column. + // For time and timestamp types that are WITH TIME ZONE, the values as the SQL Standard CLI codes. + Assertions.assertEquals(Types.INTEGER, metaData.getColumnType(1)); + + Assertions.assertEquals("INTEGER", metaData.getColumnTypeName(1)); + + Assertions.assertEquals(Integer.class.getName(), metaData.getColumnClassName(1)); + + Assertions.assertFalse(metaData.isAutoIncrement(1)); + + // This method returns true for any column whose data type is a character type, with the exception of VARCHAR_IGNORECASE for which it returns false. + // It also returns false for any column whose data type is a not a character data type. + Assertions.assertTrue(metaData.isCaseSensitive(2)); + + // If the column in question is a database table or view column, + // and the type of the column allows searching, then returns true, otherwise false. + Assertions.assertTrue(metaData.isSearchable(1)); + + // HSQLDB 2.0 fully supports this feature and returns true for NUMERIC and DECIMAL columns. + Assertions.assertFalse(metaData.isCurrency(1)); + + Assertions.assertEquals(ResultSetMetaData.columnNullable, metaData.isNullable(1)); + + Assertions.assertTrue(metaData.isSigned(1)); + + // If the result set column is a direct pass through of a table column value and column size was declared, + // then the declared value is returned. + Assertions.assertEquals(20, metaData.getColumnDisplaySize(2)); + + Assertions.assertEquals("NAME", metaData.getColumnLabel(2)); + + Assertions.assertEquals("ID", metaData.getColumnName(1)); + + // For character data, this is the [maximum] length in characters. + Assertions.assertEquals(20, metaData.getPrecision(2)); + + // The reported scale for INTEGER, BIGINT and DOUBLE is 0 + Assertions.assertEquals(0, metaData.getScale(1)); + + Assertions.assertEquals("CITY", metaData.getTableName(1)); + + // From 2.0 this method returns true if the ResultSet is not updatable or the column in question is not updatable. + Assertions.assertFalse(metaData.isReadOnly(1)); + + // From 2.0 this method returns false if the ResultSet is not updatable or the column in question is not updatable. + Assertions.assertFalse(metaData.isWritable(2)); + + // From 2.0 this method returns false if the ResultSet is not updatable or the column in question is not updatable. + Assertions.assertFalse(metaData.isDefinitelyWritable(1)); + + Assertions.assertFalse(metaData.isWrapperFor(null)); + + Assertions.assertThrows(SQLException.class, () -> metaData.unwrap(null)); + } + + @Test + public void testParameterMetaData() throws SQLException { + PreparedStatement psmt = connection.prepareStatement("SELECT * FROM city WHERE id = ?"); + ParameterMetaData metaData = psmt.getParameterMetaData(); + + Assertions.assertEquals(1, metaData.getParameterCount()); + + Assertions.assertEquals(ParameterMetaData.parameterNullableUnknown, metaData.isNullable(1)); + + Assertions.assertTrue(metaData.isSigned(1)); + + Assertions.assertEquals(10, metaData.getPrecision(1)); + + Assertions.assertEquals(0, metaData.getScale(1)); + + Assertions.assertEquals(Types.INTEGER, metaData.getParameterType(1)); + + Assertions.assertEquals("INTEGER", metaData.getParameterTypeName(1)); + + Assertions.assertEquals(Integer.class.getName(), metaData.getParameterClassName(1)); + + Assertions.assertEquals(ParameterMetaData.parameterModeIn, metaData.getParameterMode(1)); + + Assertions.assertFalse(metaData.isWrapperFor(null)); + + Assertions.assertThrows(SQLException.class, () -> metaData.unwrap(null)); + } + +}