Commit 12a28d12 authored by Barry Lind's avatar Barry Lind

patch to add support for callable statements to the jdbc driver. The patch...

patch to add support for callable statements to the jdbc driver.  The patch was submitted by Paul Bethe pmbethe@yahoo.com
parent 33086553
...@@ -83,3 +83,11 @@ postgresql.updateable.afterlastdelete:After end of result set. Can not call dele ...@@ -83,3 +83,11 @@ postgresql.updateable.afterlastdelete:After end of result set. Can not call dele
postgresql.updateable.notoninsertrow:Not on insert row. postgresql.updateable.notoninsertrow:Not on insert row.
postgresql.updateable.inputstream:Input Stream is null. postgresql.updateable.inputstream:Input Stream is null.
postgresql.updateable.ioerror:Input Stream Error. postgresql.updateable.ioerror:Input Stream Error.
postgresql.call.noreturntype:A CallableStatement Function was declared but no call to 'registerOutParameter (1, <some_type>)' was made.
postgresql.call.noinout:PostgreSQL only supports function return value [@ 1] (no OUT or INOUT arguments)
postgresql.call.procasfunc:This Statement [{0}] defines a procedure call (needs ?= call <stmt> to be considered a function.
postgresql.call.malformed:Malformed stmt [{0}] usage : {1}
postgresql.call.funcover:Cannot execute Query a call to setXXX (1, ..) was made where argument 1 is the return value of a function.
postgresql.call.wrongget:Parameter of type {0} was registered but call to get{1} (sqltype={2}) was made.
postgresql.call.noreturnval:A CallableStatement Function was executed with nothing returned.
postgresql.call.wrongrtntype:A CallableStatement Function was executed and the return was of type ({0}) however type={1} was registered.
...@@ -17,7 +17,7 @@ import org.postgresql.largeobject.*; ...@@ -17,7 +17,7 @@ import org.postgresql.largeobject.*;
import org.postgresql.util.*; import org.postgresql.util.*;
/* /*
* $Id: Connection.java,v 1.19 2002/06/11 02:55:16 barry Exp $ * $Id: Connection.java,v 1.20 2002/06/24 06:16:27 barry Exp $
* *
* A Connection represents a session with a specific database. Within the * A Connection represents a session with a specific database. Within the
* context of a Connection, SQL statements are executed and results are * context of a Connection, SQL statements are executed and results are
...@@ -135,11 +135,10 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co ...@@ -135,11 +135,10 @@ public class Connection extends org.postgresql.Connection implements java.sql.Co
public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{ {
throw new PSQLException("postgresql.con.call"); CallableStatement s = new CallableStatement(this,sql);
//CallableStatement s = new CallableStatement(this,sql); s.setResultSetType(resultSetType);
//s.setResultSetType(resultSetType); s.setResultSetConcurrency(resultSetConcurrency);
//s.setResultSetConcurrency(resultSetConcurrency); return s;
//return s;
} }
/* /*
......
...@@ -58,13 +58,16 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -58,13 +58,16 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
{ {
super(connection); super(connection);
this.sql = sql;
this.connection = connection;
parseSqlStmt (); // this allows Callable stmt to override
}
protected void parseSqlStmt () throws SQLException {
Vector v = new Vector(); Vector v = new Vector();
boolean inQuotes = false; boolean inQuotes = false;
int lastParmEnd = 0, i; int lastParmEnd = 0, i;
this.sql = sql;
this.connection = connection;
for (i = 0; i < sql.length(); ++i) for (i = 0; i < sql.length(); ++i)
{ {
int c = sql.charAt(i); int c = sql.charAt(i);
...@@ -118,7 +121,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -118,7 +121,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* This is identical to toString() except it throws an exception if a * This is identical to toString() except it throws an exception if a
* parameter is unused. * parameter is unused.
*/ */
private synchronized String compileQuery() protected synchronized String compileQuery()
throws SQLException throws SQLException
{ {
sbuf.setLength(0); sbuf.setLength(0);
...@@ -818,7 +821,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -818,7 +821,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* @param s a string to be stored * @param s a string to be stored
* @exception SQLException if something goes wrong * @exception SQLException if something goes wrong
*/ */
private void set(int paramIndex, String s) throws SQLException protected void set(int paramIndex, String s) throws SQLException
{ {
if (paramIndex < 1 || paramIndex > inStrings.length) if (paramIndex < 1 || paramIndex > inStrings.length)
throw new PSQLException("postgresql.prep.range"); throw new PSQLException("postgresql.prep.range");
......
...@@ -226,8 +226,9 @@ public class JDBC2Tests extends TestSuite ...@@ -226,8 +226,9 @@ public class JDBC2Tests extends TestSuite
// Fastpath/LargeObject // Fastpath/LargeObject
suite.addTestSuite(BlobTest.class); suite.addTestSuite(BlobTest.class);
suite.addTestSuite( UpdateableResultTest.class ); suite.addTestSuite( UpdateableResultTest.class );
suite.addTestSuite( CallableStmtTest.class );
// That's all folks // That's all folks
return suite; return suite;
} }
......
package org.postgresql.test.jdbc2;
import org.postgresql.test.JDBC2Tests;
import junit.framework.TestCase;
import java.io.*;
import java.sql.*;
/*
* CallableStatement tests.
* @author Paul Bethe
*/
public class CallableStmtTest extends TestCase
{
private Connection con;
public CallableStmtTest (String name)
{
super(name);
}
protected void setUp() throws Exception
{
con = JDBC2Tests.openDB();
Statement stmt = con.createStatement ();
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getString (varchar) " +
"RETURNS varchar AS ' DECLARE inString alias for $1; begin "+
"return ''bob''; end; ' LANGUAGE 'plpgsql';");
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getDouble (float) " +
"RETURNS float AS ' DECLARE inString alias for $1; begin " +
"return 42.42; end; ' LANGUAGE 'plpgsql';");
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getInt (int) RETURNS int " +
" AS 'DECLARE inString alias for $1; begin " +
"return 42; end;' LANGUAGE 'plpgsql';");
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getNumeric (numeric) " +
"RETURNS numeric AS ' DECLARE inString alias for $1; " +
"begin return 42; end; ' LANGUAGE 'plpgsql';");
stmt.close ();
}
protected void tearDown() throws Exception
{
Statement stmt = con.createStatement ();
stmt.execute ("drop FUNCTION testspg__getString (varchar);");
stmt.execute ("drop FUNCTION testspg__getDouble (float);");
stmt.execute ("drop FUNCTION testspg__getInt (int);");
stmt.execute ("drop FUNCTION testspg__getNumeric (numeric);");
JDBC2Tests.closeDB(con);
}
final String func = "{ ? = call ";
final String pkgName = "testspg__";
// protected void runTest () throws Throwable {
//testGetString ();
//}
public void testGetDouble () throws Throwable {
// System.out.println ("Testing CallableStmt Types.DOUBLE");
CallableStatement call = con.prepareCall (func + pkgName + "getDouble (?) }");
call.setDouble (2, (double)3.04);
call.registerOutParameter (1, Types.DOUBLE);
call.execute ();
double result = call.getDouble (1);
assertTrue ("correct return from getString ()", result == 42.42);
}
public void testGetInt () throws Throwable {
// System.out.println ("Testing CallableStmt Types.INTEGER");
CallableStatement call = con.prepareCall (func + pkgName + "getInt (?) }");
call.setInt (2, 4);
call.registerOutParameter (1, Types.INTEGER);
call.execute ();
int result = call.getInt (1);
assertTrue ("correct return from getString ()", result == 42);
}
public void testGetNumeric () throws Throwable {
// System.out.println ("Testing CallableStmt Types.NUMERIC");
CallableStatement call = con.prepareCall (func + pkgName + "getNumeric (?) }");
call.setBigDecimal (2, new java.math.BigDecimal(4));
call.registerOutParameter (1, Types.NUMERIC);
call.execute ();
java.math.BigDecimal result = call.getBigDecimal (1);
assertTrue ("correct return from getString ()",
result.equals (new java.math.BigDecimal(42)));
}
public void testGetString () throws Throwable {
// System.out.println ("Testing CallableStmt Types.VARCHAR");
CallableStatement call = con.prepareCall (func + pkgName + "getString (?) }");
call.setString (2, "foo");
call.registerOutParameter (1, Types.VARCHAR);
call.execute ();
String result = call.getString (1);
assertTrue ("correct return from getString ()", result.equals ("bob"));
}
public void testBadStmt () throws Throwable {
tryOneBadStmt ("{ ?= " + pkgName + "getString (?) }");
tryOneBadStmt ("{ ?= call getString (?) ");
tryOneBadStmt ("{ = ? call getString (?); }");
}
protected void tryOneBadStmt (String sql) throws Throwable {
boolean wasCaught = false;
try {
CallableStatement call = con.prepareCall (sql);
} catch (SQLException e) {
wasCaught = true; // good -> this statement was missing something
}
assertTrue ("bad statment ('"+sql+"')was not caught", wasCaught);
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment