mirror of https://github.com/postgres/postgres
(agollapudi@demandsolutions.com). Also applied the RefCursor support patch by Nic Ferrier. This patch allows you too return a get a result set from a function that returns a refcursor. For example: call.registerOutParameter(1, Types.OTHER); call.execute(); ResultSet rs = (ResultSet) call.getObject(1); Modified Files: jdbc/org/postgresql/core/BaseStatement.java jdbc/org/postgresql/jdbc1/AbstractJdbc1ResultSet.java jdbc/org/postgresql/jdbc1/AbstractJdbc1Statement.java jdbc/org/postgresql/jdbc1/Jdbc1CallableStatement.java jdbc/org/postgresql/jdbc1/Jdbc1PreparedStatement.java jdbc/org/postgresql/jdbc1/Jdbc1Statement.java jdbc/org/postgresql/jdbc2/AbstractJdbc2ResultSet.java jdbc/org/postgresql/jdbc2/Jdbc2CallableStatement.java jdbc/org/postgresql/jdbc2/Jdbc2PreparedStatement.java jdbc/org/postgresql/jdbc2/Jdbc2Statement.java jdbc/org/postgresql/jdbc3/Jdbc3CallableStatement.java jdbc/org/postgresql/jdbc3/Jdbc3PreparedStatement.java jdbc/org/postgresql/jdbc3/Jdbc3Statement.java Added Files: jdbc/org/postgresql/PGRefCursorResultSet.java jdbc/org/postgresql/jdbc1/Jdbc1RefCursorResultSet.java jdbc/org/postgresql/jdbc2/Jdbc2RefCursorResultSet.java jdbc/org/postgresql/jdbc3/Jdbc3RefCursorResultSet.java jdbc/org/postgresql/test/jdbc2/RefCursorTest.javaWIN32_DEV
parent
721996d889
commit
5295fffc26
@ -0,0 +1,25 @@ |
|||||||
|
/*------------------------------------------------------------------------- |
||||||
|
* |
||||||
|
* PGRefCursorResultSet.java |
||||||
|
* Describes a PLPGSQL refcursor type. |
||||||
|
* |
||||||
|
* Copyright (c) 2003, PostgreSQL Global Development Group |
||||||
|
* |
||||||
|
* IDENTIFICATION |
||||||
|
* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGRefCursorResultSet.java,v 1.1 2003/05/03 20:40:45 barry Exp $ |
||||||
|
* |
||||||
|
*------------------------------------------------------------------------- |
||||||
|
*/ |
||||||
|
package org.postgresql; |
||||||
|
|
||||||
|
|
||||||
|
/** A ref cursor based result set. |
||||||
|
*/ |
||||||
|
public interface PGRefCursorResultSet |
||||||
|
{ |
||||||
|
|
||||||
|
/** return the name of the cursor. |
||||||
|
*/ |
||||||
|
public String getRefCursor (); |
||||||
|
|
||||||
|
} |
||||||
@ -0,0 +1,44 @@ |
|||||||
|
package org.postgresql.jdbc1; |
||||||
|
|
||||||
|
import java.sql.SQLException; |
||||||
|
import org.postgresql.core.QueryExecutor; |
||||||
|
import org.postgresql.core.BaseStatement; |
||||||
|
import org.postgresql.PGRefCursorResultSet; |
||||||
|
|
||||||
|
/** A real result set based on a ref cursor. |
||||||
|
* |
||||||
|
* @author Nic Ferrier <nferrier@tapsellferrier.co.uk> |
||||||
|
*/ |
||||||
|
public class Jdbc1RefCursorResultSet extends Jdbc1ResultSet |
||||||
|
implements PGRefCursorResultSet |
||||||
|
{ |
||||||
|
|
||||||
|
// The name of the cursor being used.
|
||||||
|
String refCursorHandle; |
||||||
|
|
||||||
|
// Indicates when the result set has activaly bound to the cursor.
|
||||||
|
boolean isInitialized = false; |
||||||
|
|
||||||
|
|
||||||
|
Jdbc1RefCursorResultSet(BaseStatement statement, String refCursorName) |
||||||
|
{ |
||||||
|
super(statement, null, null, null, -1, 0L, false); |
||||||
|
this.refCursorHandle = refCursorName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRefCursor () |
||||||
|
{ |
||||||
|
return refCursorHandle; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean next () throws SQLException |
||||||
|
{ |
||||||
|
if (isInitialized) |
||||||
|
return super.next(); |
||||||
|
// Initialize this res set with the rows from the cursor.
|
||||||
|
String[] toExec = { "FETCH ALL IN \"" + refCursorHandle + "\";" }; |
||||||
|
QueryExecutor.execute(toExec, new String[0], this); |
||||||
|
isInitialized = true; |
||||||
|
return super.next(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,43 @@ |
|||||||
|
package org.postgresql.jdbc2; |
||||||
|
|
||||||
|
|
||||||
|
import org.postgresql.core.QueryExecutor; |
||||||
|
import org.postgresql.core.BaseStatement; |
||||||
|
import org.postgresql.PGRefCursorResultSet; |
||||||
|
|
||||||
|
|
||||||
|
/** A real result set based on a ref cursor. |
||||||
|
* |
||||||
|
* @author Nic Ferrier <nferrier@tapsellferrier.co.uk> |
||||||
|
*/ |
||||||
|
public class Jdbc2RefCursorResultSet extends Jdbc2ResultSet |
||||||
|
implements PGRefCursorResultSet |
||||||
|
{ |
||||||
|
|
||||||
|
String refCursorHandle; |
||||||
|
|
||||||
|
// Indicates when the result set has activaly bound to the cursor.
|
||||||
|
boolean isInitialized = false; |
||||||
|
|
||||||
|
Jdbc2RefCursorResultSet(BaseStatement statement, String refCursorName) throws java.sql.SQLException |
||||||
|
{ |
||||||
|
super(statement, null, null, null, -1, 0L, false); |
||||||
|
this.refCursorHandle = refCursorName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRefCursor () |
||||||
|
{ |
||||||
|
return refCursorHandle; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean next () throws java.sql.SQLException |
||||||
|
{ |
||||||
|
if (isInitialized) |
||||||
|
return super.next(); |
||||||
|
// Initialize this res set with the rows from the cursor.
|
||||||
|
String[] toExec = { "FETCH ALL IN \"" + refCursorHandle + "\";" }; |
||||||
|
QueryExecutor.execute(toExec, new String[0], this); |
||||||
|
isInitialized = true; |
||||||
|
return super.next(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,47 @@ |
|||||||
|
package org.postgresql.jdbc3; |
||||||
|
|
||||||
|
import org.postgresql.core.QueryExecutor; |
||||||
|
import org.postgresql.core.Field; |
||||||
|
import org.postgresql.core.BaseStatement; |
||||||
|
import java.util.Vector; |
||||||
|
import org.postgresql.PGConnection; |
||||||
|
import org.postgresql.PGRefCursorResultSet; |
||||||
|
|
||||||
|
/** A real result set based on a ref cursor. |
||||||
|
* |
||||||
|
* @author Nic Ferrier <nferrier@tapsellferrier.co.uk> |
||||||
|
*/ |
||||||
|
public class Jdbc3RefCursorResultSet extends Jdbc3ResultSet implements PGRefCursorResultSet |
||||||
|
{ |
||||||
|
|
||||||
|
String refCursorHandle; |
||||||
|
|
||||||
|
// Indicates when the result set has activaly bound to the cursor.
|
||||||
|
boolean isInitialized = false; |
||||||
|
|
||||||
|
Jdbc3RefCursorResultSet(java.sql.Statement statement, String refCursorName) throws java.sql.SQLException |
||||||
|
{ |
||||||
|
// This casting is a GCJ requirement.
|
||||||
|
super((BaseStatement)statement, |
||||||
|
(Field[])null, |
||||||
|
(Vector)null, |
||||||
|
(String)null, -1, 0L, false); |
||||||
|
this.refCursorHandle = refCursorName; |
||||||
|
} |
||||||
|
|
||||||
|
public String getRefCursor () |
||||||
|
{ |
||||||
|
return refCursorHandle; |
||||||
|
} |
||||||
|
|
||||||
|
public boolean next () throws java.sql.SQLException |
||||||
|
{ |
||||||
|
if (isInitialized) |
||||||
|
return super.next(); |
||||||
|
// Initialize this res set with the rows from the cursor.
|
||||||
|
String[] toExec = { "FETCH ALL IN \"" + refCursorHandle + "\";" }; |
||||||
|
QueryExecutor.execute(toExec, new String[0], this); |
||||||
|
isInitialized = true; |
||||||
|
return super.next(); |
||||||
|
} |
||||||
|
} |
||||||
@ -0,0 +1,100 @@ |
|||||||
|
package org.postgresql.test.jdbc2; |
||||||
|
|
||||||
|
import org.postgresql.test.TestUtil; |
||||||
|
import junit.framework.TestCase; |
||||||
|
import java.io.*; |
||||||
|
import java.sql.*; |
||||||
|
|
||||||
|
/* |
||||||
|
* RefCursor ResultSet tests. |
||||||
|
* This test case is basically the same as the ResultSet test case. |
||||||
|
* |
||||||
|
* @author Nic Ferrier <nferrier@tapsellferrier.co.uk> |
||||||
|
*/ |
||||||
|
public class RefCursorTest extends TestCase |
||||||
|
{ |
||||||
|
private Connection con; |
||||||
|
|
||||||
|
public RefCursorTest(String name) |
||||||
|
{ |
||||||
|
super(name); |
||||||
|
} |
||||||
|
|
||||||
|
protected void setUp() throws Exception |
||||||
|
{ |
||||||
|
// this is the same as the ResultSet setup.
|
||||||
|
con = TestUtil.openDB(); |
||||||
|
Statement stmt = con.createStatement(); |
||||||
|
|
||||||
|
TestUtil.createTable(con, "testrs", "id integer"); |
||||||
|
|
||||||
|
stmt.executeUpdate("INSERT INTO testrs VALUES (1)"); |
||||||
|
stmt.executeUpdate("INSERT INTO testrs VALUES (2)"); |
||||||
|
stmt.executeUpdate("INSERT INTO testrs VALUES (3)"); |
||||||
|
stmt.executeUpdate("INSERT INTO testrs VALUES (4)"); |
||||||
|
stmt.executeUpdate("INSERT INTO testrs VALUES (6)"); |
||||||
|
stmt.executeUpdate("INSERT INTO testrs VALUES (9)"); |
||||||
|
|
||||||
|
|
||||||
|
// Create the functions.
|
||||||
|
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getRefcursor () RETURNS refcursor AS '" |
||||||
|
+ "declare v_resset; begin open v_resset for select id from testrs order by id; " |
||||||
|
+ "return v_resset; end;' LANGUAGE 'plpgsql';"); |
||||||
|
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getEmptyRefcursor () RETURNS refcursor AS '" |
||||||
|
+ "declare v_resset; begin open v_resset for select id from testrs where id < 1 order by id; " |
||||||
|
+ "return v_resset; end;' LANGUAGE 'plpgsql';"); |
||||||
|
stmt.close(); |
||||||
|
} |
||||||
|
|
||||||
|
protected void tearDown() throws Exception |
||||||
|
{ |
||||||
|
Statement stmt = con.createStatement (); |
||||||
|
stmt.execute ("drop FUNCTION testspg__getRefcursor ();"); |
||||||
|
stmt.execute ("drop FUNCTION testspg__getEmptyRefcursor ();"); |
||||||
|
TestUtil.dropTable(con, "testrs"); |
||||||
|
TestUtil.closeDB(con); |
||||||
|
} |
||||||
|
|
||||||
|
public void testResult() throws Exception |
||||||
|
{ |
||||||
|
CallableStatement call = con.prepareCall("{ ? = call testspg__getRefcursor () }"); |
||||||
|
call.registerOutParameter(1, Types.OTHER); |
||||||
|
call.execute(); |
||||||
|
ResultSet rs = (ResultSet) call.getObject(1); |
||||||
|
|
||||||
|
assertTrue(rs.next()); |
||||||
|
assertTrue(rs.getInt(1) == 1); |
||||||
|
|
||||||
|
assertTrue(rs.next()); |
||||||
|
assertTrue(rs.getInt(1) == 2); |
||||||
|
|
||||||
|
assertTrue(rs.next()); |
||||||
|
assertTrue(rs.getInt(1) == 3); |
||||||
|
|
||||||
|
assertTrue(rs.next()); |
||||||
|
assertTrue(rs.getInt(1) == 4); |
||||||
|
|
||||||
|
assertTrue(rs.next()); |
||||||
|
assertTrue(rs.getInt(1) == 6); |
||||||
|
|
||||||
|
assertTrue(rs.next()); |
||||||
|
assertTrue(rs.getInt(1) == 9); |
||||||
|
|
||||||
|
assertTrue(!rs.next()); |
||||||
|
|
||||||
|
call.close(); |
||||||
|
} |
||||||
|
|
||||||
|
|
||||||
|
public void testEmptyResult() throws Exception |
||||||
|
{ |
||||||
|
CallableStatement call = con.prepareCall("{ ? = call testspg__getRefcursor () }"); |
||||||
|
call.registerOutParameter(1, Types.OTHER); |
||||||
|
call.execute(); |
||||||
|
|
||||||
|
ResultSet rs = (ResultSet) call.getObject(1); |
||||||
|
assertTrue(!rs.next()); |
||||||
|
|
||||||
|
call.close(); |
||||||
|
} |
||||||
|
} |
||||||
Loading…
Reference in new issue