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]