postgresql-jdbc.git / summary / log / commit / refs

commit    4ab5ccb7a299cfcec8a5b1cddf612d3f828fa157
Author:   Philippe Marschall <philippe.marschall@gmail.com>
Commit:   Vladimir Sitnikov <sitnikov.vladimir@gmail.com>
Date:     Sat Apr 08 15:01:13 2017 +0000

    feat: support fetching a REF_CURSOR using getObject
    
    Since DatabaseMetaData#supportsRefCursors now reports true
    frameworks like Hibernate now use
    callableStatement.getObject(int, ResultSet.class) to fetch the
    REF_CURSOR.
    
    Only support ResultSet.class as an argument to keep the patch simple.
    
    Closes: #794


.../org/postgresql/jdbc/PgCallableStatement.java | 6 +- .../test/jdbc42/Jdbc42CallableStatementTest.java | 94 ++++++++++++++++++++++ .../postgresql/test/jdbc42/Jdbc42TestSuite.java | 1 + 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/pgjdbc/src/main/java/org/postgresql/jdbc/PgCallableStatement.java b/pgjdbc/src/main/java/org/postgresql/jdbc/PgCallableStatement.java index ba655537..85a987ae 100644 --- a/pgjdbc/src/main/java/org/postgresql/jdbc/PgCallableStatement.java +++ b/pgjdbc/src/main/java/org/postgresql/jdbc/PgCallableStatement.java @@ -691,7 +691,11 @@ class PgCallableStatement extends PgPreparedStatement implements CallableStateme } public <T> T getObject(int parameterIndex, Class<T> type) throws SQLException { - throw Driver.notImplemented(this.getClass(), "getObject(int, Class<T>)"); + if (type == ResultSet.class) { + return type.cast(getObject(parameterIndex)); + } + throw new PSQLException(GT.tr("Unsupported type conversion to {1}.", type), + PSQLState.INVALID_PARAMETER_VALUE); } public <T> T getObject(String parameterName, Class<T> type) throws SQLException { diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc42/Jdbc42CallableStatementTest.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc42/Jdbc42CallableStatementTest.java new file mode 100644 index 00000000..db277a52 --- /dev/null +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc42/Jdbc42CallableStatementTest.java @@ -0,0 +1,94 @@ +/* + * Copyright (c) 2017, PostgreSQL Global Development Group + * See the LICENSE file in the project root for more information. + */ + +package org.postgresql.test.jdbc42; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.fail; + +import org.postgresql.test.jdbc2.BaseTest4; + +import org.junit.Test; + +import java.sql.CallableStatement; +import java.sql.ResultSet; +import java.sql.ResultSetMetaData; +import java.sql.SQLException; +import java.sql.Statement; +import java.sql.Types; +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + + +/** + * Tests for JDBC 4.2 features in {@link org.postgresql.jdbc.PgCallableStatement}. + */ +public class Jdbc42CallableStatementTest extends BaseTest4 { + + @Override + public void setUp() throws Exception { + super.setUp(); + + try (Statement stmt = con.createStatement();) { + stmt.execute( + "CREATE OR REPLACE FUNCTION testspg__getResultSetWithoutArg() " + + "RETURNS refcursor AS ' " + + "declare ref refcursor;" + + "begin OPEN ref FOR SELECT 1; RETURN ref; end; ' LANGUAGE plpgsql;"); + } + } + + + final String func = "{ ? = call "; + final String pkgName = "testspg__"; + + @Override + public void tearDown() throws SQLException { + try (Statement stmt = con.createStatement()) { + stmt.execute("drop FUNCTION testspg__getResultSetWithoutArg ();"); + } + super.tearDown(); + } + + @Test + public void testGetResultSetWithoutArg() throws SQLException { + assumeCallableStatementsSupported(); + try (CallableStatement call = con.prepareCall(func + pkgName + "getResultSetWithoutArg () }")) { + con.setAutoCommit(false); // ref cursors only work if auto commit is off + call.registerOutParameter(1, Types.REF_CURSOR); + call.execute(); + List<Integer> values = new ArrayList<>(1); + try (ResultSet rs = call.getObject(1, ResultSet.class)) { + while (rs.next()) { + values.add(rs.getInt(1)); + } + } + assertEquals(Collections.singletonList(1), values); + } finally { + con.setAutoCommit(true); + } + } + + @Test + public void testGetResultSetWithoutArgUnsupportedConversion() throws SQLException { + assumeCallableStatementsSupported(); + try (CallableStatement call = con.prepareCall(func + pkgName + "getResultSetWithoutArg () }")) { + con.setAutoCommit(false); // ref cursors only work if auto commit is off + call.registerOutParameter(1, Types.REF_CURSOR); + call.execute(); + try { + // this should never be allowed even if more types will be implemented in the future + call.getObject(1, ResultSetMetaData.class); + fail("conversion from ResultSet to ResultSetMetaData should not be supported"); + } catch (SQLException e) { + // should reach + } + } finally { + con.setAutoCommit(true); + } + } + +} diff --git a/pgjdbc/src/test/java/org/postgresql/test/jdbc42/Jdbc42TestSuite.java b/pgjdbc/src/test/java/org/postgresql/test/jdbc42/Jdbc42TestSuite.java index 4610bf47..d5b0d303 100644 --- a/pgjdbc/src/test/java/org/postgresql/test/jdbc42/Jdbc42TestSuite.java +++ b/pgjdbc/src/test/java/org/postgresql/test/jdbc42/Jdbc42TestSuite.java @@ -15,6 +15,7 @@ import org.junit.runners.Suite.SuiteClasses; CustomizeDefaultFetchSizeTest.class, GetObject310Test.class, PreparedStatementTest.class, + Jdbc42CallableStatementTest.class, GetObject310BinaryTest.class, SetObject310Test.class}) public class Jdbc42TestSuite { [parent: 170d9c278103]