1
0
mirror of https://github.com/postgres/postgres.git synced 2025-06-26 12:21:12 +03:00

Run pgjindent for Java folks.

This commit is contained in:
Bruce Momjian
2002-09-06 21:23:06 +00:00
parent b4295d052e
commit f37c1c486a
71 changed files with 8582 additions and 7709 deletions

View File

@ -233,7 +233,7 @@ public class Unicode
catch (ClassNotFoundException cnfe) catch (ClassNotFoundException cnfe)
{ {
log("Unable to load driver", cnfe); log("Unable to load driver", cnfe);
return; return ;
} }
try try
{ {

View File

@ -6,7 +6,7 @@ import java.text.*;
/* /*
* *
* $Id: basic.java,v 1.12 2002/07/23 03:59:54 barry Exp $ * $Id: basic.java,v 1.13 2002/09/06 21:23:05 momjian Exp $
* *
* This example tests the basic components of the JDBC driver, and shows * This example tests the basic components of the JDBC driver, and shows
* how even the simplest of queries can be implemented. * how even the simplest of queries can be implemented.
@ -137,6 +137,7 @@ public class basic
// result if you don't know what column number a value is in // result if you don't know what column number a value is in
System.out.println("performing another query"); System.out.println("performing another query");
rs = st.executeQuery("select * from basic where b>1"); rs = st.executeQuery("select * from basic where b>1");
if (rs != null) if (rs != null)
@ -164,6 +165,7 @@ public class basic
// Now test maxrows by setting it to 3 rows // Now test maxrows by setting it to 3 rows
st.setMaxRows(3); st.setMaxRows(3);
System.out.println("performing a query limited to " + st.getMaxRows()); System.out.println("performing a query limited to " + st.getMaxRows());
rs = st.executeQuery("select a, b from basic"); rs = st.executeQuery("select a, b from basic");

View File

@ -9,7 +9,7 @@ import org.omg.CosNaming.*;
* *
* It has no GUI, just a text frontend to keep it simple. * It has no GUI, just a text frontend to keep it simple.
* *
* $Id: StockClient.java,v 1.5 2001/11/19 23:19:20 momjian Exp $ * $Id: StockClient.java,v 1.6 2002/09/06 21:23:05 momjian Exp $
*/ */
public class StockClient public class StockClient
{ {
@ -35,14 +35,14 @@ public class StockClient
if (nameServiceObj == null) if (nameServiceObj == null)
{ {
System.err.println("nameServiceObj == null"); System.err.println("nameServiceObj == null");
return; return ;
} }
nameService = org.omg.CosNaming.NamingContextHelper.narrow(nameServiceObj); nameService = org.omg.CosNaming.NamingContextHelper.narrow(nameServiceObj);
if (nameService == null) if (nameService == null)
{ {
System.err.println("nameService == null"); System.err.println("nameService == null");
return; return ;
} }
// Resolve the dispenser // Resolve the dispenser
@ -53,7 +53,7 @@ public class StockClient
if (dispenser == null) if (dispenser == null)
{ {
System.err.println("dispenser == null"); System.err.println("dispenser == null");
return; return ;
} }
// Now run the front end. // Now run the front end.

View File

@ -5,7 +5,7 @@ import org.omg.CosNaming.*;
/* /*
* This class implements the server side of the example. * This class implements the server side of the example.
* *
* $Id: StockDispenserImpl.java,v 1.4 2001/11/19 23:19:20 momjian Exp $ * $Id: StockDispenserImpl.java,v 1.5 2002/09/06 21:23:05 momjian Exp $
*/ */
public class StockDispenserImpl extends stock._StockDispenserImplBase public class StockDispenserImpl extends stock._StockDispenserImplBase
{ {
@ -67,11 +67,11 @@ public class StockDispenserImpl extends stock._StockDispenserImplBase
{ {
stock[i].inUse = false; stock[i].inUse = false;
System.out.println("Releasing slot " + i); System.out.println("Releasing slot " + i);
return; return ;
} }
} }
System.out.println("Reserved object not a member of this dispenser"); System.out.println("Reserved object not a member of this dispenser");
return; return ;
} }
/* /*

View File

@ -5,7 +5,7 @@ import org.omg.CosNaming.*;
/* /*
* This class implements the server side of the example. * This class implements the server side of the example.
* *
* $Id: StockServer.java,v 1.4 2001/11/19 23:19:20 momjian Exp $ * $Id: StockServer.java,v 1.5 2002/09/06 21:23:05 momjian Exp $
*/ */
public class StockServer public class StockServer
{ {
@ -29,14 +29,14 @@ public class StockServer
if (nameServiceObj == null) if (nameServiceObj == null)
{ {
System.err.println("nameServiceObj = null"); System.err.println("nameServiceObj = null");
return; return ;
} }
org.omg.CosNaming.NamingContext nameService = org.omg.CosNaming.NamingContextHelper.narrow(nameServiceObj); org.omg.CosNaming.NamingContext nameService = org.omg.CosNaming.NamingContextHelper.narrow(nameServiceObj);
if (nameService == null) if (nameService == null)
{ {
System.err.println("nameService = null"); System.err.println("nameService = null");
return; return ;
} }
// bind the dispenser into the naming service // bind the dispenser into the naming service

View File

@ -82,7 +82,7 @@ public class psql
if (line.startsWith("\\")) if (line.startsWith("\\"))
{ {
processSlashCommand(line); processSlashCommand(line);
return; return ;
} }
boolean type = st.execute(line); boolean type = st.execute(line);

View File

@ -31,8 +31,8 @@ public class Driver implements java.sql.Driver
public static final int DEBUG = 2; public static final int DEBUG = 2;
public static final int INFO = 1; public static final int INFO = 1;
public static boolean logDebug = false; public static boolean logDebug = false;
public static boolean logInfo = false; public static boolean logInfo = false;
static static
{ {
@ -70,11 +70,11 @@ public class Driver implements java.sql.Driver
* to/from the database to unicode. If multibyte is enabled on the * to/from the database to unicode. If multibyte is enabled on the
* server then the character set of the database is used as the default, * server then the character set of the database is used as the default,
* otherwise the jvm character encoding is used as the default. * otherwise the jvm character encoding is used as the default.
* loglevel - (optional) Enable logging of messages from the driver. * loglevel - (optional) Enable logging of messages from the driver.
* The value is an integer from 1 to 2 where: * The value is an integer from 1 to 2 where:
* INFO = 1, DEBUG = 2 * INFO = 1, DEBUG = 2
* The output is sent to DriverManager.getPrintWriter() if set, * The output is sent to DriverManager.getPrintWriter() if set,
* otherwise it is sent to System.out. * otherwise it is sent to System.out.
* compatible - (optional) This is used to toggle * compatible - (optional) This is used to toggle
* between different functionality as it changes across different releases * between different functionality as it changes across different releases
* of the jdbc driver code. The values here are versions of the jdbc * of the jdbc driver code. The values here are versions of the jdbc
@ -109,12 +109,14 @@ public class Driver implements java.sql.Driver
{ {
if ((props = parseURL(url, info)) == null) if ((props = parseURL(url, info)) == null)
{ {
if (Driver.logDebug) Driver.debug("Error in url" + url); if (Driver.logDebug)
Driver.debug("Error in url" + url);
return null; return null;
} }
try try
{ {
if (Driver.logDebug) Driver.debug("connect " + url); if (Driver.logDebug)
Driver.debug("connect " + url);
@JDBCCONNECTCLASS@ con = (@JDBCCONNECTCLASS@)(Class.forName("@JDBCCONNECTCLASS@").newInstance()); @JDBCCONNECTCLASS@ con = (@JDBCCONNECTCLASS@)(Class.forName("@JDBCCONNECTCLASS@").newInstance());
con.openConnection (host(), port(), props, database(), url, this); con.openConnection (host(), port(), props, database(), url, this);
@ -122,7 +124,8 @@ public class Driver implements java.sql.Driver
} }
catch (ClassNotFoundException ex) catch (ClassNotFoundException ex)
{ {
if (Driver.logDebug) Driver.debug("error", ex); if (Driver.logDebug)
Driver.debug("error", ex);
throw new PSQLException("postgresql.jvm.version", ex); throw new PSQLException("postgresql.jvm.version", ex);
} }
catch (PSQLException ex1) catch (PSQLException ex1)
@ -133,7 +136,8 @@ public class Driver implements java.sql.Driver
} }
catch (Exception ex2) catch (Exception ex2)
{ {
if (Driver.logDebug) Driver.debug("error", ex2); if (Driver.logDebug)
Driver.debug("error", ex2);
throw new PSQLException("postgresql.unusual", ex2); throw new PSQLException("postgresql.unusual", ex2);
} }
} }
@ -177,7 +181,7 @@ public class Driver implements java.sql.Driver
*/ */
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
{ {
//This method isn't really implemented //This method isn't really implemented
Properties p = parseURL(url, info); Properties p = parseURL(url, info);
return new DriverPropertyInfo[0]; return new DriverPropertyInfo[0];
} }
@ -385,16 +389,16 @@ public class Driver implements java.sql.Driver
} }
/** /**
* used to turn logging on to a certain level, can be called * used to turn logging on to a certain level, can be called
* by specifying fully qualified class ie org.postgresql.Driver.setLogLevel() * by specifying fully qualified class ie org.postgresql.Driver.setLogLevel()
* @param int logLevel sets the level which logging will respond to * @param int logLevel sets the level which logging will respond to
* INFO being almost no messages * INFO being almost no messages
* DEBUG most verbose * DEBUG most verbose
*/ */
public static void setLogLevel(int logLevel) public static void setLogLevel(int logLevel)
{ {
logDebug = (logLevel >= DEBUG) ? true : false; logDebug = (logLevel >= DEBUG) ? true : false;
logInfo = (logLevel >= INFO) ? true : false; logInfo = (logLevel >= INFO) ? true : false;
} }
/* /*
* logging message at the debug level * logging message at the debug level
@ -441,7 +445,7 @@ public class Driver implements java.sql.Driver
} }
} }
//The build number should be incremented for every new build //The build number should be incremented for every new build
private static int m_buildNumber = 104; private static int m_buildNumber = 104;
} }

View File

@ -7,74 +7,74 @@ import org.postgresql.core.Encoding;
import org.postgresql.fastpath.Fastpath; import org.postgresql.fastpath.Fastpath;
import org.postgresql.largeobject.LargeObjectManager; import org.postgresql.largeobject.LargeObjectManager;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGConnection.java,v 1.2 2002/09/02 03:07:36 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGConnection.java,v 1.3 2002/09/06 21:23:05 momjian Exp $
* This interface defines PostgreSQL extentions to the java.sql.Connection interface. * This interface defines PostgreSQL extentions to the java.sql.Connection interface.
* Any java.sql.Connection object returned by the driver will also implement this * Any java.sql.Connection object returned by the driver will also implement this
* interface * interface
*/ */
public interface PGConnection public interface PGConnection
{ {
/* /*
* Get the character encoding to use for this connection. * Get the character encoding to use for this connection.
*/ */
public Encoding getEncoding() throws SQLException; public Encoding getEncoding() throws SQLException;
/* /*
* This method returns the java.sql.Types type for a postgres datatype name * This method returns the java.sql.Types type for a postgres datatype name
*/ */
public int getSQLType(String pgTypeName) throws SQLException; public int getSQLType(String pgTypeName) throws SQLException;
/* /*
* This returns the java.sql.Types type for a postgres datatype OID * This returns the java.sql.Types type for a postgres datatype OID
*/ */
public int getSQLType(int oid) throws SQLException; public int getSQLType(int oid) throws SQLException;
/* /*
* This returns the postgres datatype name from the * This returns the postgres datatype name from the
* postgres datatype OID * postgres datatype OID
*/ */
public String getPGType(int oid) throws SQLException; public String getPGType(int oid) throws SQLException;
/* /*
* This returns the postgres datatype OID from the * This returns the postgres datatype OID from the
* postgres datatype name * postgres datatype name
*/ */
public int getPGType(String typeName) throws SQLException; public int getPGType(String typeName) throws SQLException;
/* /*
* This returns the LargeObject API for the current connection. * This returns the LargeObject API for the current connection.
*/ */
public LargeObjectManager getLargeObjectAPI() throws SQLException; public LargeObjectManager getLargeObjectAPI() throws SQLException;
/* /*
* This returns the Fastpath API for the current connection. * This returns the Fastpath API for the current connection.
*/ */
public Fastpath getFastpathAPI() throws SQLException; public Fastpath getFastpathAPI() throws SQLException;
/* /*
* This method is used internally to return an object based around * This method is used internally to return an object based around
* org.postgresql's more unique data types. * org.postgresql's more unique data types.
* *
* <p>It uses an internal Hashtable to get the handling class. If the * <p>It uses an internal Hashtable to get the handling class. If the
* type is not supported, then an instance of org.postgresql.util.PGobject * type is not supported, then an instance of org.postgresql.util.PGobject
* is returned. * is returned.
* *
* You can use the getValue() or setValue() methods to handle the returned * You can use the getValue() or setValue() methods to handle the returned
* object. Custom objects can have their own methods. * object. Custom objects can have their own methods.
* *
* @return PGobject for this type, and set to value * @return PGobject for this type, and set to value
* @exception SQLException if value is not correct for this type * @exception SQLException if value is not correct for this type
* @see org.postgresql.util.Serialize * @see org.postgresql.util.Serialize
*/ */
public Object getObject(String type, String value) throws SQLException; public Object getObject(String type, String value) throws SQLException;
/* /*
* This method returns any notifications that have been received * This method returns any notifications that have been received
* since the last call to this method. * since the last call to this method.
* Returns null if there have been no notifications. * Returns null if there have been no notifications.
*/ */
public PGNotification[] getNotifications(); public PGNotification[] getNotifications();
} }

View File

@ -1,20 +1,20 @@
package org.postgresql; package org.postgresql;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGNotification.java,v 1.1 2002/09/02 03:07:36 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGNotification.java,v 1.2 2002/09/06 21:23:05 momjian Exp $
* This interface defines PostgreSQL extention for Notifications * This interface defines PostgreSQL extention for Notifications
*/ */
public interface PGNotification public interface PGNotification
{ {
/* /*
* Returns name of this notification * Returns name of this notification
*/ */
public String getName(); public String getName();
/* /*
* Returns the process id of the backend process making this notification * Returns the process id of the backend process making this notification
*/ */
public int getPID(); public int getPID();
} }

View File

@ -3,23 +3,23 @@ package org.postgresql;
import java.sql.*; import java.sql.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGStatement.java,v 1.4 2002/09/02 03:07:36 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/Attic/PGStatement.java,v 1.5 2002/09/06 21:23:05 momjian Exp $
* This interface defines PostgreSQL extentions to the java.sql.Statement interface. * This interface defines PostgreSQL extentions to the java.sql.Statement interface.
* Any java.sql.Statement object returned by the driver will also implement this * Any java.sql.Statement object returned by the driver will also implement this
* interface * interface
*/ */
public interface PGStatement public interface PGStatement
{ {
/* /*
* Returns the Last inserted/updated oid. * Returns the Last inserted/updated oid.
* @return OID of last insert * @return OID of last insert
* @since 7.3 * @since 7.3
*/ */
public long getLastOID() throws SQLException; public long getLastOID() throws SQLException;
public void setUseServerPrepare(boolean flag); public void setUseServerPrepare(boolean flag);
public boolean isUseServerPrepare(); public boolean isUseServerPrepare();
} }

View File

@ -8,7 +8,7 @@ import org.postgresql.util.*;
/* /*
* Converts to and from the character encoding used by the backend. * Converts to and from the character encoding used by the backend.
* *
* $Id: Encoding.java,v 1.5 2002/03/19 02:48:45 momjian Exp $ * $Id: Encoding.java,v 1.6 2002/09/06 21:23:05 momjian Exp $
*/ */
public class Encoding public class Encoding
@ -42,14 +42,14 @@ public class Encoding
encodings.put("EUC_KR", new String[] { "EUC_KR" }); encodings.put("EUC_KR", new String[] { "EUC_KR" });
encodings.put("JOHAB", new String[] { "Johab" }); encodings.put("JOHAB", new String[] { "Johab" });
encodings.put("EUC_TW", new String[] { "EUC_TW" }); encodings.put("EUC_TW", new String[] { "EUC_TW" });
encodings.put("SJIS", new String[] { "MS932","SJIS" }); encodings.put("SJIS", new String[] { "MS932", "SJIS" });
encodings.put("BIG5", new String[] { "Big5","MS950","Cp950" }); encodings.put("BIG5", new String[] { "Big5", "MS950", "Cp950" });
encodings.put("GBK", new String[] { "GBK","MS936" }); encodings.put("GBK", new String[] { "GBK", "MS936" });
encodings.put("UHC", new String[] { "MS949","Cp949","Cp949C" }); encodings.put("UHC", new String[] { "MS949", "Cp949", "Cp949C" });
encodings.put("TCVN", new String[] { "Cp1258" }); encodings.put("TCVN", new String[] { "Cp1258" });
encodings.put("WIN1256", new String[] { "Cp1256" }); encodings.put("WIN1256", new String[] { "Cp1256" });
encodings.put("WIN1250", new String[] { "Cp1250" }); encodings.put("WIN1250", new String[] { "Cp1250" });
encodings.put("WIN874", new String[] { "MS874","Cp874" }); encodings.put("WIN874", new String[] { "MS874", "Cp874" });
encodings.put("WIN", new String[] { "Cp1251" }); encodings.put("WIN", new String[] { "Cp1251" });
encodings.put("ALT", new String[] { "Cp866" }); encodings.put("ALT", new String[] { "Cp866" });
// We prefer KOI8-U, since it is a superset of KOI8-R. // We prefer KOI8-U, since it is a superset of KOI8-R.

View File

@ -1,32 +1,35 @@
package org.postgresql.core; package org.postgresql.core;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Notification.java,v 1.1 2002/09/02 03:07:36 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/core/Attic/Notification.java,v 1.2 2002/09/06 21:23:05 momjian Exp $
* This is the implementation of the PGNotification interface * This is the implementation of the PGNotification interface
*/ */
public class Notification implements org.postgresql.PGNotification public class Notification implements org.postgresql.PGNotification
{ {
public Notification(String p_name, int p_pid) { public Notification(String p_name, int p_pid)
m_name = p_name; {
m_pid = p_pid; m_name = p_name;
} m_pid = p_pid;
}
/* /*
* Returns name of this notification * Returns name of this notification
*/ */
public String getName() { public String getName()
return m_name; {
} return m_name;
}
/* /*
* Returns the process id of the backend process making this notification * Returns the process id of the backend process making this notification
*/ */
public int getPID() { public int getPID()
return m_pid; {
} return m_pid;
}
private String m_name; private String m_name;
private int m_pid; private int m_pid;
} }

View File

@ -13,208 +13,209 @@ import org.postgresql.util.PSQLException;
* <p>The lifetime of a QueryExecutor object is from sending the query * <p>The lifetime of a QueryExecutor object is from sending the query
* until the response has been received from the backend. * until the response has been received from the backend.
* *
* $Id: QueryExecutor.java,v 1.15 2002/09/02 03:07:36 barry Exp $ * $Id: QueryExecutor.java,v 1.16 2002/09/06 21:23:05 momjian Exp $
*/ */
public class QueryExecutor public class QueryExecutor
{ {
private final String[] m_sqlFrags; private final String[] m_sqlFrags;
private final Object[] m_binds; private final Object[] m_binds;
private final java.sql.Statement statement; private final java.sql.Statement statement;
private final PG_Stream pg_stream; private final PG_Stream pg_stream;
private final org.postgresql.jdbc1.AbstractJdbc1Connection connection; private final org.postgresql.jdbc1.AbstractJdbc1Connection connection;
public QueryExecutor(String[] p_sqlFrags, Object[] p_binds, public QueryExecutor(String[] p_sqlFrags, Object[] p_binds,
java.sql.Statement statement, java.sql.Statement statement,
PG_Stream pg_stream, PG_Stream pg_stream,
java.sql.Connection connection) java.sql.Connection connection)
throws SQLException throws SQLException
{ {
this.m_sqlFrags = p_sqlFrags; this.m_sqlFrags = p_sqlFrags;
this.m_binds = p_binds; this.m_binds = p_binds;
this.statement = statement; this.statement = statement;
this.pg_stream = pg_stream; this.pg_stream = pg_stream;
this.connection = (org.postgresql.jdbc1.AbstractJdbc1Connection)connection; this.connection = (org.postgresql.jdbc1.AbstractJdbc1Connection)connection;
if (statement != null) if (statement != null)
maxRows = statement.getMaxRows(); maxRows = statement.getMaxRows();
else else
maxRows = 0; maxRows = 0;
} }
private Field[] fields = null; private Field[] fields = null;
private Vector tuples = new Vector(); private Vector tuples = new Vector();
private boolean binaryCursor = false; private boolean binaryCursor = false;
private String status = null; private String status = null;
private int update_count = 1; private int update_count = 1;
private long insert_oid = 0; private long insert_oid = 0;
private int maxRows; private int maxRows;
/* /*
* Execute a query on the backend. * Execute a query on the backend.
*/ */
public java.sql.ResultSet execute() throws SQLException public java.sql.ResultSet execute() throws SQLException
{ {
StringBuffer errorMessage = null; StringBuffer errorMessage = null;
synchronized (pg_stream) synchronized (pg_stream)
{ {
sendQuery(); sendQuery();
int c; int c;
boolean l_endQuery = false; boolean l_endQuery = false;
while (!l_endQuery) while (!l_endQuery)
{ {
c = pg_stream.ReceiveChar(); c = pg_stream.ReceiveChar();
switch (c) switch (c)
{ {
case 'A': // Asynchronous Notify case 'A': // Asynchronous Notify
int pid = pg_stream.ReceiveInteger(4); int pid = pg_stream.ReceiveInteger(4);
String msg = pg_stream.ReceiveString(connection.getEncoding()); String msg = pg_stream.ReceiveString(connection.getEncoding());
connection.addNotification(new org.postgresql.core.Notification(msg, pid)); connection.addNotification(new org.postgresql.core.Notification(msg, pid));
break; break;
case 'B': // Binary Data Transfer case 'B': // Binary Data Transfer
receiveTuple(true); receiveTuple(true);
break; break;
case 'C': // Command Status case 'C': // Command Status
receiveCommandStatus(); receiveCommandStatus();
break; break;
case 'D': // Text Data Transfer case 'D': // Text Data Transfer
receiveTuple(false); receiveTuple(false);
break; break;
case 'E': // Error Message case 'E': // Error Message
// it's possible to get more than one error message for a query // it's possible to get more than one error message for a query
// see libpq comments wrt backend closing a connection // see libpq comments wrt backend closing a connection
// so, append messages to a string buffer and keep processing // so, append messages to a string buffer and keep processing
// check at the bottom to see if we need to throw an exception // check at the bottom to see if we need to throw an exception
if ( errorMessage == null ) if ( errorMessage == null )
errorMessage = new StringBuffer(); errorMessage = new StringBuffer();
errorMessage.append(pg_stream.ReceiveString(connection.getEncoding())); errorMessage.append(pg_stream.ReceiveString(connection.getEncoding()));
// keep processing // keep processing
break; break;
case 'I': // Empty Query case 'I': // Empty Query
int t = pg_stream.ReceiveChar(); int t = pg_stream.ReceiveChar();
break; break;
case 'N': // Error Notification case 'N': // Error Notification
connection.addWarning(pg_stream.ReceiveString(connection.getEncoding())); connection.addWarning(pg_stream.ReceiveString(connection.getEncoding()));
break; break;
case 'P': // Portal Name case 'P': // Portal Name
String pname = pg_stream.ReceiveString(connection.getEncoding()); String pname = pg_stream.ReceiveString(connection.getEncoding());
break; break;
case 'T': // MetaData Field Description case 'T': // MetaData Field Description
receiveFields(); receiveFields();
break; break;
case 'Z': case 'Z':
l_endQuery = true; l_endQuery = true;
break; break;
default: default:
throw new PSQLException("postgresql.con.type", throw new PSQLException("postgresql.con.type",
new Character((char) c)); new Character((char) c));
} }
} }
// did we get an error during this query? // did we get an error during this query?
if ( errorMessage != null ) if ( errorMessage != null )
throw new SQLException( errorMessage.toString() ); throw new SQLException( errorMessage.toString() );
return connection.getResultSet(statement, fields, tuples, status, update_count, insert_oid, binaryCursor); return connection.getResultSet(statement, fields, tuples, status, update_count, insert_oid, binaryCursor);
} }
} }
/* /*
* Send a query to the backend. * Send a query to the backend.
*/ */
private void sendQuery() throws SQLException private void sendQuery() throws SQLException
{ {
try try
{ {
pg_stream.SendChar('Q'); pg_stream.SendChar('Q');
for (int i = 0 ; i < m_binds.length ; ++i) { for (int i = 0 ; i < m_binds.length ; ++i)
if (m_binds[i] == null) {
throw new PSQLException("postgresql.prep.param", new Integer(i + 1)); if (m_binds[i] == null)
pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[i])); throw new PSQLException("postgresql.prep.param", new Integer(i + 1));
pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString())); pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[i]));
} pg_stream.Send(connection.getEncoding().encode(m_binds[i].toString()));
pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[m_binds.length])); }
pg_stream.SendChar(0); pg_stream.Send(connection.getEncoding().encode(m_sqlFrags[m_binds.length]));
pg_stream.flush(); pg_stream.SendChar(0);
pg_stream.flush();
} }
catch (IOException e) catch (IOException e)
{ {
throw new PSQLException("postgresql.con.ioerror", e); throw new PSQLException("postgresql.con.ioerror", e);
} }
} }
/* /*
* Receive a tuple from the backend. * Receive a tuple from the backend.
* *
* @param isBinary set if the tuple should be treated as binary data * @param isBinary set if the tuple should be treated as binary data
*/ */
private void receiveTuple(boolean isBinary) throws SQLException private void receiveTuple(boolean isBinary) throws SQLException
{ {
if (fields == null) if (fields == null)
throw new PSQLException("postgresql.con.tuple"); throw new PSQLException("postgresql.con.tuple");
Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary); Object tuple = pg_stream.ReceiveTuple(fields.length, isBinary);
if (isBinary) if (isBinary)
binaryCursor = true; binaryCursor = true;
if (maxRows == 0 || tuples.size() < maxRows) if (maxRows == 0 || tuples.size() < maxRows)
tuples.addElement(tuple); tuples.addElement(tuple);
} }
/* /*
* Receive command status from the backend. * Receive command status from the backend.
*/ */
private void receiveCommandStatus() throws SQLException private void receiveCommandStatus() throws SQLException
{ {
status = pg_stream.ReceiveString(connection.getEncoding()); status = pg_stream.ReceiveString(connection.getEncoding());
try try
{ {
// Now handle the update count correctly. // Now handle the update count correctly.
if (status.startsWith("INSERT") || status.startsWith("UPDATE") || status.startsWith("DELETE") || status.startsWith("MOVE")) if (status.startsWith("INSERT") || status.startsWith("UPDATE") || status.startsWith("DELETE") || status.startsWith("MOVE"))
{ {
update_count = Integer.parseInt(status.substring(1 + status.lastIndexOf(' '))); update_count = Integer.parseInt(status.substring(1 + status.lastIndexOf(' ')));
} }
if (status.startsWith("INSERT")) if (status.startsWith("INSERT"))
{ {
insert_oid = Long.parseLong(status.substring(1 + status.indexOf(' '), insert_oid = Long.parseLong(status.substring(1 + status.indexOf(' '),
status.lastIndexOf(' '))); status.lastIndexOf(' ')));
} }
} }
catch (NumberFormatException nfe) catch (NumberFormatException nfe)
{ {
throw new PSQLException("postgresql.con.fathom", status); throw new PSQLException("postgresql.con.fathom", status);
} }
} }
/* /*
* Receive the field descriptions from the back end. * Receive the field descriptions from the back end.
*/ */
private void receiveFields() throws SQLException private void receiveFields() throws SQLException
{ {
if (fields != null) if (fields != null)
throw new PSQLException("postgresql.con.multres"); throw new PSQLException("postgresql.con.multres");
int size = pg_stream.ReceiveIntegerR(2); int size = pg_stream.ReceiveIntegerR(2);
fields = new Field[size]; fields = new Field[size];
for (int i = 0; i < fields.length; i++) for (int i = 0; i < fields.length; i++)
{ {
String typeName = pg_stream.ReceiveString(connection.getEncoding()); String typeName = pg_stream.ReceiveString(connection.getEncoding());
int typeOid = pg_stream.ReceiveIntegerR(4); int typeOid = pg_stream.ReceiveIntegerR(4);
int typeLength = pg_stream.ReceiveIntegerR(2); int typeLength = pg_stream.ReceiveIntegerR(2);
int typeModifier = pg_stream.ReceiveIntegerR(4); int typeModifier = pg_stream.ReceiveIntegerR(4);
fields[i] = new Field(connection, typeName, typeOid, typeLength, typeModifier); fields[i] = new Field(connection, typeName, typeOid, typeLength, typeModifier);
} }
} }
} }

View File

@ -6,7 +6,7 @@ import java.io.IOException;
/** /**
* Sent to the backend to initialize a newly created connection. * Sent to the backend to initialize a newly created connection.
* *
* $Id: StartupPacket.java,v 1.1 2002/03/21 02:40:03 davec Exp $ * $Id: StartupPacket.java,v 1.2 2002/09/06 21:23:05 momjian Exp $
*/ */
public class StartupPacket public class StartupPacket
@ -22,15 +22,16 @@ public class StartupPacket
private String user; private String user;
private String database; private String database;
public StartupPacket(int protocolMajor, int protocolMinor, String user, String database) { public StartupPacket(int protocolMajor, int protocolMinor, String user, String database)
{
this.protocolMajor = protocolMajor; this.protocolMajor = protocolMajor;
this.protocolMinor = protocolMinor; this.protocolMinor = protocolMinor;
this.user = user; this.user = user;
this.database = database; this.database = database;
} }
public void writeTo(PG_Stream stream) throws IOException public void writeTo(PG_Stream stream) throws IOException
{ {
stream.SendInteger(4 + 4 + SM_DATABASE + SM_USER + SM_OPTIONS + SM_UNUSED + SM_TTY, 4); stream.SendInteger(4 + 4 + SM_DATABASE + SM_USER + SM_OPTIONS + SM_UNUSED + SM_TTY, 4);
stream.SendInteger(protocolMajor, 2); stream.SendInteger(protocolMajor, 2);
stream.SendInteger(protocolMinor, 2); stream.SendInteger(protocolMinor, 2);

View File

@ -24,268 +24,272 @@ import org.postgresql.util.*;
*/ */
public class Fastpath public class Fastpath
{ {
// This maps the functions names to their id's (possible unique just // This maps the functions names to their id's (possible unique just
// to a connection). // to a connection).
protected Hashtable func = new Hashtable(); protected Hashtable func = new Hashtable();
protected org.postgresql.PGConnection conn; // our connection protected org.postgresql.PGConnection conn; // our connection
protected org.postgresql.PG_Stream stream; // the network stream protected org.postgresql.PG_Stream stream; // the network stream
/* /*
* Initialises the fastpath system * Initialises the fastpath system
* *
* <p><b>Important Notice</b> * <p><b>Important Notice</b>
* <br>This is called from org.postgresql.Connection, and should not be called * <br>This is called from org.postgresql.Connection, and should not be called
* from client code. * from client code.
* *
* @param conn org.postgresql.Connection to attach to * @param conn org.postgresql.Connection to attach to
* @param stream The network stream to the backend * @param stream The network stream to the backend
*/ */
public Fastpath(org.postgresql.PGConnection conn, org.postgresql.PG_Stream stream) public Fastpath(org.postgresql.PGConnection conn, org.postgresql.PG_Stream stream)
{ {
this.conn = conn; this.conn = conn;
this.stream = stream; this.stream = stream;
} }
/* /*
* Send a function call to the PostgreSQL backend * Send a function call to the PostgreSQL backend
* *
* @param fnid Function id * @param fnid Function id
* @param resulttype True if the result is an integer, false for other results * @param resulttype True if the result is an integer, false for other results
* @param args FastpathArguments to pass to fastpath * @param args FastpathArguments to pass to fastpath
* @return null if no data, Integer if an integer result, or byte[] otherwise * @return null if no data, Integer if an integer result, or byte[] otherwise
* @exception SQLException if a database-access error occurs. * @exception SQLException if a database-access error occurs.
*/ */
public Object fastpath(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException public Object fastpath(int fnid, boolean resulttype, FastpathArg[] args) throws SQLException
{ {
// added Oct 7 1998 to give us thread safety // added Oct 7 1998 to give us thread safety
synchronized (stream) synchronized (stream)
{ {
// send the function call // send the function call
try try
{ {
// 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding // 70 is 'F' in ASCII. Note: don't use SendChar() here as it adds padding
// that confuses the backend. The 0 terminates the command line. // that confuses the backend. The 0 terminates the command line.
stream.SendInteger(70, 1); stream.SendInteger(70, 1);
stream.SendInteger(0, 1); stream.SendInteger(0, 1);
stream.SendInteger(fnid, 4); stream.SendInteger(fnid, 4);
stream.SendInteger(args.length, 4); stream.SendInteger(args.length, 4);
for (int i = 0;i < args.length;i++) for (int i = 0;i < args.length;i++)
args[i].send(stream); args[i].send(stream);
// This is needed, otherwise data can be lost // This is needed, otherwise data can be lost
stream.flush(); stream.flush();
} }
catch (IOException ioe) catch (IOException ioe)
{ {
throw new PSQLException("postgresql.fp.send", new Integer(fnid), ioe); throw new PSQLException("postgresql.fp.send", new Integer(fnid), ioe);
} }
// Now handle the result // Now handle the result
// Now loop, reading the results // Now loop, reading the results
Object result = null; // our result Object result = null; // our result
StringBuffer errorMessage = null; StringBuffer errorMessage = null;
int c; int c;
boolean l_endQuery = false; boolean l_endQuery = false;
while (!l_endQuery) while (!l_endQuery)
{ {
c = stream.ReceiveChar(); c = stream.ReceiveChar();
switch (c) switch (c)
{ {
case 'A': // Asynchronous Notify case 'A': // Asynchronous Notify
int pid = stream.ReceiveInteger(4); int pid = stream.ReceiveInteger(4);
String msg = stream.ReceiveString(conn.getEncoding()); String msg = stream.ReceiveString(conn.getEncoding());
break; break;
//------------------------------ //------------------------------
// Error message returned // Error message returned
case 'E': case 'E':
if ( errorMessage == null ) if ( errorMessage == null )
errorMessage = new StringBuffer(); errorMessage = new StringBuffer();
errorMessage.append(stream.ReceiveString(conn.getEncoding())); errorMessage.append(stream.ReceiveString(conn.getEncoding()));
break; break;
//------------------------------ //------------------------------
// Notice from backend // Notice from backend
case 'N': case 'N':
((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).addWarning(stream.ReceiveString(conn.getEncoding())); ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).addWarning(stream.ReceiveString(conn.getEncoding()));
break; break;
case 'V': case 'V':
int l_nextChar = stream.ReceiveChar(); int l_nextChar = stream.ReceiveChar();
if (l_nextChar == 'G') { if (l_nextChar == 'G')
int sz = stream.ReceiveIntegerR(4); {
// Return an Integer if int sz = stream.ReceiveIntegerR(4);
if (resulttype) // Return an Integer if
result = new Integer(stream.ReceiveIntegerR(sz)); if (resulttype)
else result = new Integer(stream.ReceiveIntegerR(sz));
{ else
byte buf[] = new byte[sz]; {
stream.Receive(buf, 0, sz); byte buf[] = new byte[sz];
result = buf; stream.Receive(buf, 0, sz);
} result = buf;
//There should be a trailing '0' }
int l_endChar = stream.ReceiveChar(); //There should be a trailing '0'
} else { int l_endChar = stream.ReceiveChar();
//it must have been a '0', thus no results }
} else
break; {
//it must have been a '0', thus no results
}
break;
case 'Z': case 'Z':
l_endQuery = true; l_endQuery = true;
break; break;
default: default:
throw new PSQLException("postgresql.fp.protocol", new Character((char)c)); throw new PSQLException("postgresql.fp.protocol", new Character((char)c));
} }
} }
if ( errorMessage != null ) if ( errorMessage != null )
throw new PSQLException("postgresql.fp.error", errorMessage.toString()); throw new PSQLException("postgresql.fp.error", errorMessage.toString());
return result; return result;
} }
} }
/* /*
* Send a function call to the PostgreSQL backend by name. * Send a function call to the PostgreSQL backend by name.
* *
* Note: the mapping for the procedure name to function id needs to exist, * Note: the mapping for the procedure name to function id needs to exist,
* usually to an earlier call to addfunction(). * usually to an earlier call to addfunction().
* *
* This is the prefered method to call, as function id's can/may change * This is the prefered method to call, as function id's can/may change
* between versions of the backend. * between versions of the backend.
* *
* For an example of how this works, refer to org.postgresql.LargeObject * For an example of how this works, refer to org.postgresql.LargeObject
* *
* @param name Function name * @param name Function name
* @param resulttype True if the result is an integer, false for other * @param resulttype True if the result is an integer, false for other
* results * results
* @param args FastpathArguments to pass to fastpath * @param args FastpathArguments to pass to fastpath
* @return null if no data, Integer if an integer result, or byte[] otherwise * @return null if no data, Integer if an integer result, or byte[] otherwise
* @exception SQLException if name is unknown or if a database-access error * @exception SQLException if name is unknown or if a database-access error
* occurs. * occurs.
* @see org.postgresql.LargeObject * @see org.postgresql.LargeObject
*/ */
public Object fastpath(String name, boolean resulttype, FastpathArg[] args) throws SQLException public Object fastpath(String name, boolean resulttype, FastpathArg[] args) throws SQLException
{ {
if (Driver.logDebug) Driver.debug("Fastpath: calling "+name); if (Driver.logDebug)
return fastpath(getID(name), resulttype, args); Driver.debug("Fastpath: calling " + name);
} return fastpath(getID(name), resulttype, args);
}
/* /*
* This convenience method assumes that the return value is an Integer * This convenience method assumes that the return value is an Integer
* @param name Function name * @param name Function name
* @param args Function arguments * @param args Function arguments
* @return integer result * @return integer result
* @exception SQLException if a database-access error occurs or no result * @exception SQLException if a database-access error occurs or no result
*/ */
public int getInteger(String name, FastpathArg[] args) throws SQLException public int getInteger(String name, FastpathArg[] args) throws SQLException
{ {
Integer i = (Integer)fastpath(name, true, args); Integer i = (Integer)fastpath(name, true, args);
if (i == null) if (i == null)
throw new PSQLException("postgresql.fp.expint", name); throw new PSQLException("postgresql.fp.expint", name);
return i.intValue(); return i.intValue();
} }
/* /*
* This convenience method assumes that the return value is an Integer * This convenience method assumes that the return value is an Integer
* @param name Function name * @param name Function name
* @param args Function arguments * @param args Function arguments
* @return byte[] array containing result * @return byte[] array containing result
* @exception SQLException if a database-access error occurs or no result * @exception SQLException if a database-access error occurs or no result
*/ */
public byte[] getData(String name, FastpathArg[] args) throws SQLException public byte[] getData(String name, FastpathArg[] args) throws SQLException
{ {
return (byte[])fastpath(name, false, args); return (byte[])fastpath(name, false, args);
} }
/* /*
* This adds a function to our lookup table. * This adds a function to our lookup table.
* *
* <p>User code should use the addFunctions method, which is based upon a * <p>User code should use the addFunctions method, which is based upon a
* query, rather than hard coding the oid. The oid for a function is not * query, rather than hard coding the oid. The oid for a function is not
* guaranteed to remain static, even on different servers of the same * guaranteed to remain static, even on different servers of the same
* version. * version.
* *
* @param name Function name * @param name Function name
* @param fnid Function id * @param fnid Function id
*/ */
public void addFunction(String name, int fnid) public void addFunction(String name, int fnid)
{ {
func.put(name, new Integer(fnid)); func.put(name, new Integer(fnid));
} }
/* /*
* This takes a ResultSet containing two columns. Column 1 contains the * This takes a ResultSet containing two columns. Column 1 contains the
* function name, Column 2 the oid. * function name, Column 2 the oid.
* *
* <p>It reads the entire ResultSet, loading the values into the function * <p>It reads the entire ResultSet, loading the values into the function
* table. * table.
* *
* <p><b>REMEMBER</b> to close() the resultset after calling this!! * <p><b>REMEMBER</b> to close() the resultset after calling this!!
* *
* <p><b><em>Implementation note about function name lookups:</em></b> * <p><b><em>Implementation note about function name lookups:</em></b>
* *
* <p>PostgreSQL stores the function id's and their corresponding names in * <p>PostgreSQL stores the function id's and their corresponding names in
* the pg_proc table. To speed things up locally, instead of querying each * the pg_proc table. To speed things up locally, instead of querying each
* function from that table when required, a Hashtable is used. Also, only * function from that table when required, a Hashtable is used. Also, only
* the function's required are entered into this table, keeping connection * the function's required are entered into this table, keeping connection
* times as fast as possible. * times as fast as possible.
* *
* <p>The org.postgresql.LargeObject class performs a query upon it's startup, * <p>The org.postgresql.LargeObject class performs a query upon it's startup,
* and passes the returned ResultSet to the addFunctions() method here. * and passes the returned ResultSet to the addFunctions() method here.
* *
* <p>Once this has been done, the LargeObject api refers to the functions by * <p>Once this has been done, the LargeObject api refers to the functions by
* name. * name.
* *
* <p>Dont think that manually converting them to the oid's will work. Ok, * <p>Dont think that manually converting them to the oid's will work. Ok,
* they will for now, but they can change during development (there was some * they will for now, but they can change during development (there was some
* discussion about this for V7.0), so this is implemented to prevent any * discussion about this for V7.0), so this is implemented to prevent any
* unwarranted headaches in the future. * unwarranted headaches in the future.
* *
* @param rs ResultSet * @param rs ResultSet
* @exception SQLException if a database-access error occurs. * @exception SQLException if a database-access error occurs.
* @see org.postgresql.LargeObjectManager * @see org.postgresql.LargeObjectManager
*/ */
public void addFunctions(ResultSet rs) throws SQLException public void addFunctions(ResultSet rs) throws SQLException
{ {
while (rs.next()) while (rs.next())
{ {
func.put(rs.getString(1), new Integer(rs.getInt(2))); func.put(rs.getString(1), new Integer(rs.getInt(2)));
} }
} }
/* /*
* This returns the function id associated by its name * This returns the function id associated by its name
* *
* <p>If addFunction() or addFunctions() have not been called for this name, * <p>If addFunction() or addFunctions() have not been called for this name,
* then an SQLException is thrown. * then an SQLException is thrown.
* *
* @param name Function name to lookup * @param name Function name to lookup
* @return Function ID for fastpath call * @return Function ID for fastpath call
* @exception SQLException is function is unknown. * @exception SQLException is function is unknown.
*/ */
public int getID(String name) throws SQLException public int getID(String name) throws SQLException
{ {
Integer id = (Integer)func.get(name); Integer id = (Integer)func.get(name);
// may be we could add a lookup to the database here, and store the result // may be we could add a lookup to the database here, and store the result
// in our lookup table, throwing the exception if that fails. // in our lookup table, throwing the exception if that fails.
// We must, however, ensure that if we do, any existing ResultSet is // We must, however, ensure that if we do, any existing ResultSet is
// unaffected, otherwise we could break user code. // unaffected, otherwise we could break user code.
// //
// so, until we know we can do this (needs testing, on the TODO list) // so, until we know we can do this (needs testing, on the TODO list)
// for now, we throw the exception and do no lookups. // for now, we throw the exception and do no lookups.
if (id == null) if (id == null)
throw new PSQLException("postgresql.fp.unknown", name); throw new PSQLException("postgresql.fp.unknown", name);
return id.intValue(); return id.intValue();
} }
} }

View File

@ -13,7 +13,7 @@ import org.postgresql.largeobject.*;
import org.postgresql.util.PGbytea; import org.postgresql.util.PGbytea;
import org.postgresql.util.PSQLException; import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.5 2002/09/02 03:07:36 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/AbstractJdbc1ResultSet.java,v 1.6 2002/09/06 21:23:06 momjian Exp $
* This class defines methods of the jdbc1 specification. This class is * This class defines methods of the jdbc1 specification. This class is
* extended by org.postgresql.jdbc2.AbstractJdbc2ResultSet which adds the jdbc2 * extended by org.postgresql.jdbc2.AbstractJdbc2ResultSet which adds the jdbc2
* methods. The real ResultSet class (for jdbc1) is org.postgresql.jdbc1.Jdbc1ResultSet * methods. The real ResultSet class (for jdbc1) is org.postgresql.jdbc1.Jdbc1ResultSet
@ -22,7 +22,7 @@ public abstract class AbstractJdbc1ResultSet
{ {
protected Vector rows; // The results protected Vector rows; // The results
protected Statement statement; protected Statement statement;
protected Field fields[]; // The field descriptions protected Field fields[]; // The field descriptions
protected String status; // Status of the result protected String status; // Status of the result
protected boolean binaryCursor = false; // is the data binary or Strings protected boolean binaryCursor = false; // is the data binary or Strings
@ -39,13 +39,13 @@ public abstract class AbstractJdbc1ResultSet
protected ResultSet next = null; protected ResultSet next = null;
protected StringBuffer sbuf = null; protected StringBuffer sbuf = null;
public byte[][] rowBuffer=null; public byte[][] rowBuffer = null;
public AbstractJdbc1ResultSet(org.postgresql.PGConnection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) public AbstractJdbc1ResultSet(org.postgresql.PGConnection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
{ {
this.connection = conn; this.connection = conn;
this.statement = statement; this.statement = statement;
this.fields = fields; this.fields = fields;
this.rows = tuples; this.rows = tuples;
this.status = status; this.status = status;
@ -59,16 +59,16 @@ public abstract class AbstractJdbc1ResultSet
public boolean next() throws SQLException public boolean next() throws SQLException
{ {
if (rows == null) if (rows == null)
throw new PSQLException("postgresql.con.closed"); throw new PSQLException("postgresql.con.closed");
if (++current_row >= rows.size()) if (++current_row >= rows.size())
return false; return false;
this_row = (byte [][])rows.elementAt(current_row); this_row = (byte [][])rows.elementAt(current_row);
rowBuffer=new byte[this_row.length][]; rowBuffer = new byte[this_row.length][];
System.arraycopy(this_row,0,rowBuffer,0,this_row.length); System.arraycopy(this_row, 0, rowBuffer, 0, this_row.length);
return true; return true;
} }
@ -230,12 +230,12 @@ public abstract class AbstractJdbc1ResultSet
public Time getTime(int columnIndex) throws SQLException public Time getTime(int columnIndex) throws SQLException
{ {
return toTime( getString(columnIndex), (java.sql.ResultSet)this, fields[columnIndex-1].getPGType() ); return toTime( getString(columnIndex), (java.sql.ResultSet)this, fields[columnIndex - 1].getPGType() );
} }
public Timestamp getTimestamp(int columnIndex) throws SQLException public Timestamp getTimestamp(int columnIndex) throws SQLException
{ {
return toTimestamp( getString(columnIndex), (java.sql.ResultSet)this, fields[columnIndex-1].getPGType() ); return toTimestamp( getString(columnIndex), (java.sql.ResultSet)this, fields[columnIndex - 1].getPGType() );
} }
public InputStream getAsciiStream(int columnIndex) throws SQLException public InputStream getAsciiStream(int columnIndex) throws SQLException
@ -423,11 +423,12 @@ public abstract class AbstractJdbc1ResultSet
warnings = null; warnings = null;
} }
public void addWarnings(SQLWarning warnings) { public void addWarnings(SQLWarning warnings)
if ( this.warnings != null ) {
this.warnings.setNextWarning(warnings); if ( this.warnings != null )
else this.warnings.setNextWarning(warnings);
this.warnings = warnings; else
this.warnings = warnings;
} }
public String getCursorName() throws SQLException public String getCursorName() throws SQLException
@ -612,18 +613,18 @@ public abstract class AbstractJdbc1ResultSet
/* /*
* returns the OID of the last inserted row. Deprecated in 7.2 because * returns the OID of the last inserted row. Deprecated in 7.2 because
* range for OID values is greater than java signed int. * range for OID values is greater than java signed int.
* @deprecated Replaced by getLastOID() in 7.2 * @deprecated Replaced by getLastOID() in 7.2
*/ */
public int getInsertedOID() public int getInsertedOID()
{ {
return (int) getLastOID(); return (int) getLastOID();
} }
/* /*
* returns the OID of the last inserted row * returns the OID of the last inserted row
* @since 7.2 * @since 7.2
*/ */
public long getLastOID() public long getLastOID()
{ {
@ -660,8 +661,10 @@ public abstract class AbstractJdbc1ResultSet
protected void checkResultSet( int column ) throws SQLException protected void checkResultSet( int column ) throws SQLException
{ {
if ( this_row == null ) throw new PSQLException("postgresql.res.nextrequired"); if ( this_row == null )
if ( column < 1 || column > fields.length ) throw new PSQLException("postgresql.res.colrange" ); throw new PSQLException("postgresql.res.nextrequired");
if ( column < 1 || column > fields.length )
throw new PSQLException("postgresql.res.colrange" );
} }
//----------------- Formatting Methods ------------------- //----------------- Formatting Methods -------------------
@ -789,26 +792,34 @@ public abstract class AbstractJdbc1ResultSet
return null; // SQL NULL return null; // SQL NULL
try try
{ {
if (s.length() == 8) { if (s.length() == 8)
//value is a time value {
return java.sql.Time.valueOf(s); //value is a time value
} else if (s.indexOf(".") == 8) { return java.sql.Time.valueOf(s);
//value is a time value with fractional seconds }
java.sql.Time l_time = java.sql.Time.valueOf(s.substring(0,8)); else if (s.indexOf(".") == 8)
String l_strMillis = s.substring(9); {
if (l_strMillis.length() > 3) //value is a time value with fractional seconds
l_strMillis = l_strMillis.substring(0,3); java.sql.Time l_time = java.sql.Time.valueOf(s.substring(0, 8));
int l_millis = Integer.parseInt(l_strMillis); String l_strMillis = s.substring(9);
if (l_millis < 10) { if (l_strMillis.length() > 3)
l_millis = l_millis * 100; l_strMillis = l_strMillis.substring(0, 3);
} else if (l_millis < 100) { int l_millis = Integer.parseInt(l_strMillis);
l_millis = l_millis * 10; if (l_millis < 10)
} {
return new java.sql.Time(l_time.getTime() + l_millis); l_millis = l_millis * 100;
} else { }
//value is a timestamp else if (l_millis < 100)
return new java.sql.Time(toTimestamp(s, resultSet, pgDataType).getTime()); {
} l_millis = l_millis * 10;
}
return new java.sql.Time(l_time.getTime() + l_millis);
}
else
{
//value is a timestamp
return new java.sql.Time(toTimestamp(s, resultSet, pgDataType).getTime());
}
} }
catch (NumberFormatException e) catch (NumberFormatException e)
{ {
@ -827,7 +838,7 @@ public abstract class AbstractJdbc1ResultSet
* From version 7.2 postgres returns fractional seconds to 6 places. * From version 7.2 postgres returns fractional seconds to 6 places.
* If available, we drop the last 3 digits. * If available, we drop the last 3 digits.
* *
* @param s The ISO formated date string to parse. * @param s The ISO formated date string to parse.
* @param resultSet The ResultSet this date is part of. * @param resultSet The ResultSet this date is part of.
* *
* @return null if s is null or a timestamp of the parsed string s. * @return null if s is null or a timestamp of the parsed string s.
@ -837,7 +848,7 @@ public abstract class AbstractJdbc1ResultSet
public static Timestamp toTimestamp(String s, java.sql.ResultSet resultSet, String pgDataType) public static Timestamp toTimestamp(String s, java.sql.ResultSet resultSet, String pgDataType)
throws SQLException throws SQLException
{ {
AbstractJdbc1ResultSet rs = (AbstractJdbc1ResultSet)resultSet; AbstractJdbc1ResultSet rs = (AbstractJdbc1ResultSet)resultSet;
if (s == null) if (s == null)
return null; return null;
@ -847,12 +858,14 @@ public abstract class AbstractJdbc1ResultSet
synchronized (rs) synchronized (rs)
{ {
SimpleDateFormat df = null; SimpleDateFormat df = null;
if ( org.postgresql.Driver.logDebug ) org.postgresql.Driver.debug("the data from the DB is "+s); if ( org.postgresql.Driver.logDebug )
org.postgresql.Driver.debug("the data from the DB is " + s);
// If first time, create the buffer, otherwise clear it. // If first time, create the buffer, otherwise clear it.
if (rs.sbuf == null) if (rs.sbuf == null)
rs.sbuf = new StringBuffer(32); rs.sbuf = new StringBuffer(32);
else { else
{
rs.sbuf.setLength(0); rs.sbuf.setLength(0);
} }
@ -880,7 +893,8 @@ public abstract class AbstractJdbc1ResultSet
if (i < 24) if (i < 24)
rs.sbuf.append(c); rs.sbuf.append(c);
c = s.charAt(i++); c = s.charAt(i++);
} while (i < slen && Character.isDigit(c)); }
while (i < slen && Character.isDigit(c));
// If there wasn't at least 3 digits we should add some zeros // If there wasn't at least 3 digits we should add some zeros
// to make up the 3 digits we tell java to expect. // to make up the 3 digits we tell java to expect.
@ -911,37 +925,43 @@ public abstract class AbstractJdbc1ResultSet
} }
else else
{ {
// Just found fractional seconds but no timezone. // Just found fractional seconds but no timezone.
//If timestamptz then we use GMT, else local timezone //If timestamptz then we use GMT, else local timezone
if (pgDataType.equals("timestamptz")) { if (pgDataType.equals("timestamptz"))
rs.sbuf.append(" GMT"); {
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z"); rs.sbuf.append(" GMT");
} else { df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS z");
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS"); }
} else
{
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss.SSS");
}
} }
} }
else if (slen == 19) else if (slen == 19)
{ {
// No tz or fractional second info. // No tz or fractional second info.
//If timestamptz then we use GMT, else local timezone //If timestamptz then we use GMT, else local timezone
if (pgDataType.equals("timestamptz")) { if (pgDataType.equals("timestamptz"))
rs.sbuf.append(" GMT"); {
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z"); rs.sbuf.append(" GMT");
} else { df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss z");
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); }
} else
{
df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
}
} }
else else
{ {
if (slen == 8 && s.equals("infinity")) if (slen == 8 && s.equals("infinity"))
//java doesn't have a concept of postgres's infinity //java doesn't have a concept of postgres's infinity
//so set to an arbitrary future date //so set to an arbitrary future date
s = "9999-01-01"; s = "9999-01-01";
if (slen == 9 && s.equals("-infinity")) if (slen == 9 && s.equals("-infinity"))
//java doesn't have a concept of postgres's infinity //java doesn't have a concept of postgres's infinity
//so set to an arbitrary old date //so set to an arbitrary old date
s = "0001-01-01"; s = "0001-01-01";
// We must just have a date. This case is // We must just have a date. This case is
// needed if this method is called on a date // needed if this method is called on a date
@ -952,7 +972,8 @@ public abstract class AbstractJdbc1ResultSet
try try
{ {
// All that's left is to parse the string and return the ts. // All that's left is to parse the string and return the ts.
if ( org.postgresql.Driver.logDebug ) org.postgresql.Driver.debug( "" + df.parse(rs.sbuf.toString()).getTime() ); if ( org.postgresql.Driver.logDebug )
org.postgresql.Driver.debug( "" + df.parse(rs.sbuf.toString()).getTime() );
return new Timestamp(df.parse(rs.sbuf.toString()).getTime()); return new Timestamp(df.parse(rs.sbuf.toString()).getTime());
} }

View File

@ -8,7 +8,7 @@ import org.postgresql.util.*;
import java.sql.SQLException; import java.sql.SQLException;
import java.sql.Types; import java.sql.Types;
public abstract class AbstractJdbc1ResultSetMetaData public abstract class AbstractJdbc1ResultSetMetaData
{ {
protected Vector rows; protected Vector rows;

View File

@ -6,9 +6,9 @@ import java.sql.*;
import org.postgresql.Field; import org.postgresql.Field;
import org.postgresql.util.PSQLException; import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.4 2002/07/26 05:29:35 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Connection.java,v 1.5 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.Connection interface for JDBC1. * This class implements the java.sql.Connection interface for JDBC1.
* However most of the implementation is really done in * However most of the implementation is really done in
* org.postgresql.jdbc1.AbstractJdbc1Connection * org.postgresql.jdbc1.AbstractJdbc1Connection
*/ */
public class Jdbc1Connection extends org.postgresql.jdbc1.AbstractJdbc1Connection implements java.sql.Connection public class Jdbc1Connection extends org.postgresql.jdbc1.AbstractJdbc1Connection implements java.sql.Connection

View File

@ -5,9 +5,9 @@ import java.sql.*;
import java.util.Vector; import java.util.Vector;
import org.postgresql.Field; import org.postgresql.Field;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1ResultSet.java,v 1.3 2002/07/26 05:29:35 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1ResultSet.java,v 1.4 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.ResultSet interface for JDBC1. * This class implements the java.sql.ResultSet interface for JDBC1.
* However most of the implementation is really done in * However most of the implementation is really done in
* org.postgresql.jdbc1.AbstractJdbc1ResultSet * org.postgresql.jdbc1.AbstractJdbc1ResultSet
*/ */
public class Jdbc1ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet implements java.sql.ResultSet public class Jdbc1ResultSet extends org.postgresql.jdbc1.AbstractJdbc1ResultSet implements java.sql.ResultSet

View File

@ -4,7 +4,7 @@ public class Jdbc1ResultSetMetaData extends AbstractJdbc1ResultSetMetaData imple
{ {
public Jdbc1ResultSetMetaData(java.util.Vector rows, org.postgresql.Field[] fields) public Jdbc1ResultSetMetaData(java.util.Vector rows, org.postgresql.Field[] fields)
{ {
super(rows, fields); super(rows, fields);
} }
} }

View File

@ -3,9 +3,9 @@ package org.postgresql.jdbc1;
import java.sql.*; import java.sql.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Statement.java,v 1.2 2002/07/24 22:08:40 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc1/Attic/Jdbc1Statement.java,v 1.3 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.Statement interface for JDBC1. * This class implements the java.sql.Statement interface for JDBC1.
* However most of the implementation is really done in * However most of the implementation is really done in
* org.postgresql.jdbc1.AbstractJdbc1Statement * org.postgresql.jdbc1.AbstractJdbc1Statement
*/ */
public class Jdbc1Statement extends org.postgresql.jdbc1.AbstractJdbc1Statement implements java.sql.Statement public class Jdbc1Statement extends org.postgresql.jdbc1.AbstractJdbc1Statement implements java.sql.Statement
@ -13,7 +13,7 @@ public class Jdbc1Statement extends org.postgresql.jdbc1.AbstractJdbc1Statement
public Jdbc1Statement (Jdbc1Connection c) public Jdbc1Statement (Jdbc1Connection c)
{ {
super(c); super(c);
} }
} }

View File

@ -6,194 +6,206 @@ import java.net.ConnectException;
import java.sql.*; import java.sql.*;
import org.postgresql.util.PSQLException; import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Connection.java,v 1.1 2002/07/23 03:59:55 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Connection.java,v 1.2 2002/09/06 21:23:06 momjian Exp $
* This class defines methods of the jdbc2 specification. This class extends * This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1Connection which provides the jdbc1 * org.postgresql.jdbc1.AbstractJdbc1Connection which provides the jdbc1
* methods. The real Connection class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Connection * methods. The real Connection class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Connection
*/ */
public abstract class AbstractJdbc2Connection extends org.postgresql.jdbc1.AbstractJdbc1Connection public abstract class AbstractJdbc2Connection extends org.postgresql.jdbc1.AbstractJdbc1Connection
{ {
/* /*
* The current type mappings * The current type mappings
*/ */
protected java.util.Map typemap; protected java.util.Map typemap;
public java.sql.Statement createStatement() throws SQLException public java.sql.Statement createStatement() throws SQLException
{ {
// The spec says default of TYPE_FORWARD_ONLY but everyone is used to // The spec says default of TYPE_FORWARD_ONLY but everyone is used to
// using TYPE_SCROLL_INSENSITIVE // using TYPE_SCROLL_INSENSITIVE
return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); return createStatement(java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
} }
public abstract java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException; public abstract java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException;
public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException public java.sql.PreparedStatement prepareStatement(String sql) throws SQLException
{ {
return prepareStatement(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); return prepareStatement(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
} }
public abstract java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException; public abstract java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException;
public java.sql.CallableStatement prepareCall(String sql) throws SQLException public java.sql.CallableStatement prepareCall(String sql) throws SQLException
{ {
return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY); return prepareCall(sql, java.sql.ResultSet.TYPE_SCROLL_INSENSITIVE, java.sql.ResultSet.CONCUR_READ_ONLY);
} }
public abstract java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException; public abstract java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException;
public java.util.Map getTypeMap() throws SQLException public java.util.Map getTypeMap() throws SQLException
{ {
return typemap; return typemap;
}
public void setTypeMap(java.util.Map map) throws SQLException
{
typemap = map;
}
public void cancelQuery() throws SQLException
{
org.postgresql.PG_Stream cancelStream = null;
try {
cancelStream = new org.postgresql.PG_Stream(PG_HOST, PG_PORT);
} catch (ConnectException cex) {
// Added by Peter Mount <peter@retep.org.uk>
// ConnectException is thrown when the connection cannot be made.
// we trap this an return a more meaningful message for the end user
throw new PSQLException ("postgresql.con.refused");
} catch (IOException e) {
throw new PSQLException ("postgresql.con.failed",e);
}
// Now we need to construct and send a cancel packet
try {
cancelStream.SendInteger(16, 4);
cancelStream.SendInteger(80877102, 4);
cancelStream.SendInteger(pid, 4);
cancelStream.SendInteger(ckey, 4);
cancelStream.flush();
}
catch(IOException e) {
throw new PSQLException("postgresql.con.failed",e);
}
finally {
try {
if(cancelStream != null)
cancelStream.close();
}
catch(IOException e) {} // Ignore
}
}
/*
* This overides the standard internal getObject method so that we can
* check the jdbc2 type map first
*/
public Object getObject(String type, String value) throws SQLException
{
if (typemap != null)
{
SQLData d = (SQLData) typemap.get(type);
if (d != null)
{
// Handle the type (requires SQLInput & SQLOutput classes to be implemented)
throw org.postgresql.Driver.notImplemented();
}
}
// Default to the original method
return super.getObject(type, value);
}
//Because the get/setLogStream methods are deprecated in JDBC2
//we use the get/setLogWriter methods here for JDBC2 by overriding
//the base version of this method
protected void enableDriverManagerLogging() {
if (DriverManager.getLogWriter() == null) {
DriverManager.setLogWriter(new PrintWriter(System.out));
}
} }
/* public void setTypeMap(java.util.Map map) throws SQLException
* This implemetation uses the jdbc2Types array to support the jdbc2 {
* datatypes. Basically jdbc1 and jdbc2 are the same, except that typemap = map;
* jdbc2 adds the Array types. }
*/
public int getSQLType(String pgTypeName)
{
int sqlType = Types.OTHER; // default value
for (int i = 0;i < jdbc2Types.length;i++)
{
if (pgTypeName.equals(jdbc2Types[i]))
{
sqlType = jdbc2Typei[i];
break;
}
}
return sqlType;
}
/* public void cancelQuery() throws SQLException
* This table holds the org.postgresql names for the types supported. {
* Any types that map to Types.OTHER (eg POINT) don't go into this table. org.postgresql.PG_Stream cancelStream = null;
* They default automatically to Types.OTHER try
* {
* Note: This must be in the same order as below. cancelStream = new org.postgresql.PG_Stream(PG_HOST, PG_PORT);
* }
* Tip: keep these grouped together by the Types. value catch (ConnectException cex)
*/ {
private static final String jdbc2Types[] = { // Added by Peter Mount <peter@retep.org.uk>
"int2", // ConnectException is thrown when the connection cannot be made.
"int4", "oid", // we trap this an return a more meaningful message for the end user
"int8", throw new PSQLException ("postgresql.con.refused");
"cash", "money", }
"numeric", catch (IOException e)
"float4", {
"float8", throw new PSQLException ("postgresql.con.failed", e);
"bpchar", "char", "char2", "char4", "char8", "char16", }
"varchar", "text", "name", "filename",
"bytea",
"bool",
"date",
"time",
"abstime", "timestamp", "timestamptz",
"_bool", "_char", "_int2", "_int4", "_text",
"_oid", "_varchar", "_int8", "_float4", "_float8",
"_abstime", "_date", "_time", "_timestamp", "_numeric",
"_bytea"
};
/* // Now we need to construct and send a cancel packet
* This table holds the JDBC type for each entry above. try
* {
* Note: This must be in the same order as above cancelStream.SendInteger(16, 4);
* cancelStream.SendInteger(80877102, 4);
* Tip: keep these grouped together by the Types. value cancelStream.SendInteger(pid, 4);
*/ cancelStream.SendInteger(ckey, 4);
private static final int jdbc2Typei[] = { cancelStream.flush();
Types.SMALLINT, }
Types.INTEGER, Types.INTEGER, catch (IOException e)
Types.BIGINT, {
Types.DOUBLE, Types.DOUBLE, throw new PSQLException("postgresql.con.failed", e);
Types.NUMERIC, }
Types.REAL, finally
Types.DOUBLE, {
Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, try
Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, {
Types.BINARY, if (cancelStream != null)
Types.BIT, cancelStream.close();
Types.DATE, }
Types.TIME, catch (IOException e)
Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP, {} // Ignore
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, }
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, }
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY
}; /*
* This overides the standard internal getObject method so that we can
* check the jdbc2 type map first
*/
public Object getObject(String type, String value) throws SQLException
{
if (typemap != null)
{
SQLData d = (SQLData) typemap.get(type);
if (d != null)
{
// Handle the type (requires SQLInput & SQLOutput classes to be implemented)
throw org.postgresql.Driver.notImplemented();
}
}
// Default to the original method
return super.getObject(type, value);
}
//Because the get/setLogStream methods are deprecated in JDBC2
//we use the get/setLogWriter methods here for JDBC2 by overriding
//the base version of this method
protected void enableDriverManagerLogging()
{
if (DriverManager.getLogWriter() == null)
{
DriverManager.setLogWriter(new PrintWriter(System.out));
}
}
/*
* This implemetation uses the jdbc2Types array to support the jdbc2
* datatypes. Basically jdbc1 and jdbc2 are the same, except that
* jdbc2 adds the Array types.
*/
public int getSQLType(String pgTypeName)
{
int sqlType = Types.OTHER; // default value
for (int i = 0;i < jdbc2Types.length;i++)
{
if (pgTypeName.equals(jdbc2Types[i]))
{
sqlType = jdbc2Typei[i];
break;
}
}
return sqlType;
}
/*
* This table holds the org.postgresql names for the types supported.
* Any types that map to Types.OTHER (eg POINT) don't go into this table.
* They default automatically to Types.OTHER
*
* Note: This must be in the same order as below.
*
* Tip: keep these grouped together by the Types. value
*/
private static final String jdbc2Types[] = {
"int2",
"int4", "oid",
"int8",
"cash", "money",
"numeric",
"float4",
"float8",
"bpchar", "char", "char2", "char4", "char8", "char16",
"varchar", "text", "name", "filename",
"bytea",
"bool",
"date",
"time",
"abstime", "timestamp", "timestamptz",
"_bool", "_char", "_int2", "_int4", "_text",
"_oid", "_varchar", "_int8", "_float4", "_float8",
"_abstime", "_date", "_time", "_timestamp", "_numeric",
"_bytea"
};
/*
* This table holds the JDBC type for each entry above.
*
* Note: This must be in the same order as above
*
* Tip: keep these grouped together by the Types. value
*/
private static final int jdbc2Typei[] = {
Types.SMALLINT,
Types.INTEGER, Types.INTEGER,
Types.BIGINT,
Types.DOUBLE, Types.DOUBLE,
Types.NUMERIC,
Types.REAL,
Types.DOUBLE,
Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR, Types.CHAR,
Types.VARCHAR, Types.VARCHAR, Types.VARCHAR, Types.VARCHAR,
Types.BINARY,
Types.BIT,
Types.DATE,
Types.TIME,
Types.TIMESTAMP, Types.TIMESTAMP, Types.TIMESTAMP,
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY, Types.ARRAY,
Types.ARRAY
};

View File

@ -13,7 +13,7 @@ public abstract class AbstractJdbc2DatabaseMetaData extends org.postgresql.jdbc1
public AbstractJdbc2DatabaseMetaData(AbstractJdbc2Connection conn) public AbstractJdbc2DatabaseMetaData(AbstractJdbc2Connection conn)
{ {
super(conn); super(conn);
} }
@ -61,18 +61,18 @@ public abstract class AbstractJdbc2DatabaseMetaData extends org.postgresql.jdbc1
/* lots of unsupported stuff... */ /* lots of unsupported stuff... */
public boolean ownUpdatesAreVisible(int type) throws SQLException public boolean ownUpdatesAreVisible(int type) throws SQLException
{ {
return true; return true;
} }
public boolean ownDeletesAreVisible(int type) throws SQLException public boolean ownDeletesAreVisible(int type) throws SQLException
{ {
return true; return true;
} }
public boolean ownInsertsAreVisible(int type) throws SQLException public boolean ownInsertsAreVisible(int type) throws SQLException
{ {
// indicates that // indicates that
return true; return true;
} }
public boolean othersUpdatesAreVisible(int type) throws SQLException public boolean othersUpdatesAreVisible(int type) throws SQLException
@ -117,10 +117,10 @@ public abstract class AbstractJdbc2DatabaseMetaData extends org.postgresql.jdbc1
* Return user defined types in a schema * Return user defined types in a schema
*/ */
public java.sql.ResultSet getUDTs(String catalog, public java.sql.ResultSet getUDTs(String catalog,
String schemaPattern, String schemaPattern,
String typeNamePattern, String typeNamePattern,
int[] types int[] types
) throws SQLException ) throws SQLException
{ {
throw org.postgresql.Driver.notImplemented(); throw org.postgresql.Driver.notImplemented();
} }

View File

@ -19,7 +19,7 @@ public abstract class AbstractJdbc2ResultSetMetaData extends org.postgresql.jdbc
*/ */
public AbstractJdbc2ResultSetMetaData(Vector rows, Field[] fields) public AbstractJdbc2ResultSetMetaData(Vector rows, Field[] fields)
{ {
super(rows, fields); super(rows, fields);
} }
/* /*
@ -459,53 +459,53 @@ public abstract class AbstractJdbc2ResultSetMetaData extends org.postgresql.jdbc
// This can hook into our PG_Object mechanism // This can hook into our PG_Object mechanism
/** /**
* Returns the fully-qualified name of the Java class whose instances * Returns the fully-qualified name of the Java class whose instances
* are manufactured if the method <code>ResultSet.getObject</code> * are manufactured if the method <code>ResultSet.getObject</code>
* is called to retrieve a value from the column. * is called to retrieve a value from the column.
* *
* <code>ResultSet.getObject</code> may return a subclass of the class * <code>ResultSet.getObject</code> may return a subclass of the class
* returned by this method. * returned by this method.
* *
* @param column the first column is 1, the second is 2, ... * @param column the first column is 1, the second is 2, ...
* @return the fully-qualified name of the class in the Java programming * @return the fully-qualified name of the class in the Java programming
* language that would be used by the method * language that would be used by the method
* <code>ResultSet.getObject</code> to retrieve the value in the specified * <code>ResultSet.getObject</code> to retrieve the value in the specified
* column. This is the class name used for custom mapping. * column. This is the class name used for custom mapping.
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
public String getColumnClassName(int column) throws SQLException public String getColumnClassName(int column) throws SQLException
{ {
/* /*
The following data type mapping came from ../Field.java. The following data type mapping came from ../Field.java.
"int2", "int2",
"int4","oid", "int4","oid",
"int8", "int8",
"cash","money", "cash","money",
"numeric", "numeric",
"float4", "float4",
"float8", "float8",
"bpchar","char","char2","char4","char8","char16", "bpchar","char","char2","char4","char8","char16",
"varchar","text","name","filename", "varchar","text","name","filename",
"bool", "bool",
"date", "date",
"time", "time",
"abstime","timestamp" "abstime","timestamp"
Types.SMALLINT, Types.SMALLINT,
Types.INTEGER,Types.INTEGER, Types.INTEGER,Types.INTEGER,
Types.BIGINT, Types.BIGINT,
Types.DOUBLE,Types.DOUBLE, Types.DOUBLE,Types.DOUBLE,
Types.NUMERIC, Types.NUMERIC,
Types.REAL, Types.REAL,
Types.DOUBLE, Types.DOUBLE,
Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR, Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,
Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR, Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,
Types.BIT, Types.BIT,
Types.DATE, Types.DATE,
Types.TIME, Types.TIME,
Types.TIMESTAMP,Types.TIMESTAMP Types.TIMESTAMP,Types.TIMESTAMP
*/ */
Field field = getField(column); Field field = getField(column);
int sql_type = field.getSQLType(); int sql_type = field.getSQLType();
@ -513,40 +513,40 @@ public abstract class AbstractJdbc2ResultSetMetaData extends org.postgresql.jdbc
switch (sql_type) switch (sql_type)
{ {
case Types.BIT: case Types.BIT:
return("java.lang.Boolean"); return ("java.lang.Boolean");
case Types.SMALLINT: case Types.SMALLINT:
return("java.lang.Short"); return ("java.lang.Short");
case Types.INTEGER: case Types.INTEGER:
return("java.lang.Integer"); return ("java.lang.Integer");
case Types.BIGINT: case Types.BIGINT:
return("java.lang.Long"); return ("java.lang.Long");
case Types.NUMERIC: case Types.NUMERIC:
return("java.math.BigDecimal"); return ("java.math.BigDecimal");
case Types.REAL: case Types.REAL:
return("java.lang.Float"); return ("java.lang.Float");
case Types.DOUBLE: case Types.DOUBLE:
return("java.lang.Double"); return ("java.lang.Double");
case Types.CHAR: case Types.CHAR:
case Types.VARCHAR: case Types.VARCHAR:
return("java.lang.String"); return ("java.lang.String");
case Types.DATE: case Types.DATE:
return("java.sql.Date"); return ("java.sql.Date");
case Types.TIME: case Types.TIME:
return("java.sql.Time"); return ("java.sql.Time");
case Types.TIMESTAMP: case Types.TIMESTAMP:
return("java.sql.Timestamp"); return ("java.sql.Timestamp");
case Types.BINARY: case Types.BINARY:
case Types.VARBINARY: case Types.VARBINARY:
return("[B"); return ("[B");
case Types.ARRAY: case Types.ARRAY:
return("java.sql.Array"); return ("java.sql.Array");
default: default:
String type = field.getPGType(); String type = field.getPGType();
if ("unknown".equals(type)) if ("unknown".equals(type))
{ {
return("java.lang.String"); return ("java.lang.String");
} }
return("java.lang.Object"); return ("java.lang.Object");
} }
} }
} }

View File

@ -8,7 +8,7 @@ import java.util.Vector;
import org.postgresql.largeobject.*; import org.postgresql.largeobject.*;
import org.postgresql.util.PSQLException; import org.postgresql.util.PSQLException;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.5 2002/09/02 03:07:36 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/AbstractJdbc2Statement.java,v 1.6 2002/09/06 21:23:06 momjian Exp $
* This class defines methods of the jdbc2 specification. This class extends * This class defines methods of the jdbc2 specification. This class extends
* org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1 * org.postgresql.jdbc1.AbstractJdbc1Statement which provides the jdbc1
* methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement * methods. The real Statement class (for jdbc2) is org.postgresql.jdbc2.Jdbc2Statement
@ -45,8 +45,8 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
*/ */
public boolean execute() throws SQLException public boolean execute() throws SQLException
{ {
boolean l_return = super.execute(); boolean l_return = super.execute();
//Now do the jdbc2 specific stuff //Now do the jdbc2 specific stuff
//required for ResultSet.getStatement() to work and updateable resultsets //required for ResultSet.getStatement() to work and updateable resultsets
((AbstractJdbc2ResultSet)result).setStatement((Statement)this); ((AbstractJdbc2ResultSet)result).setStatement((Statement)this);
@ -64,7 +64,7 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
public void clearBatch() throws SQLException public void clearBatch() throws SQLException
{ {
batch = null; batch = null;
} }
public int[] executeBatch() throws SQLException public int[] executeBatch() throws SQLException
@ -86,7 +86,7 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
PBatchUpdateException updex = PBatchUpdateException updex =
new PBatchUpdateException("postgresql.stat.batch.error", new PBatchUpdateException("postgresql.stat.batch.error",
new Integer(i), batch.elementAt(i), resultSucceeded); new Integer(i), batch.elementAt(i), resultSucceeded);
updex.setNextException(e); updex.setNextException(e);
throw updex; throw updex;
@ -183,12 +183,12 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
// is buffered internally anyhow, so there would be no performance // is buffered internally anyhow, so there would be no performance
// boost gained, if anything it would be worse! // boost gained, if anything it would be worse!
int bytesRemaining = (int)x.length(); int bytesRemaining = (int)x.length();
int numRead = l_inStream.read(buf,0,Math.min(buf.length,bytesRemaining)); int numRead = l_inStream.read(buf, 0, Math.min(buf.length, bytesRemaining));
while (numRead != -1 && bytesRemaining > 0) while (numRead != -1 && bytesRemaining > 0)
{ {
bytesRemaining -= numRead; bytesRemaining -= numRead;
los.write(buf,0,numRead); los.write(buf, 0, numRead);
numRead = l_inStream.read(buf,0,Math.min(buf.length,bytesRemaining)); numRead = l_inStream.read(buf, 0, Math.min(buf.length, bytesRemaining));
} }
los.close(); los.close();
} }
@ -384,9 +384,10 @@ public abstract class AbstractJdbc2Statement extends org.postgresql.jdbc1.Abstra
} }
//This is needed by AbstractJdbc2ResultSet to determine if the query is updateable or not //This is needed by AbstractJdbc2ResultSet to determine if the query is updateable or not
protected String[] getSqlFragments() { protected String[] getSqlFragments()
return m_sqlFragments; {
} return m_sqlFragments;
}
} }

View File

@ -27,7 +27,7 @@ public class Array implements java.sql.Array
{ {
private org.postgresql.PGConnection conn = null; private org.postgresql.PGConnection conn = null;
private org.postgresql.Field field = null; private org.postgresql.Field field = null;
private ResultSet rs; private ResultSet rs;
private int idx = 0; private int idx = 0;
private String rawString = null; private String rawString = null;
@ -44,7 +44,7 @@ public class Array implements java.sql.Array
{ {
this.conn = conn; this.conn = conn;
this.field = field; this.field = field;
this.rs = rs; this.rs = rs;
this.idx = idx; this.idx = idx;
this.rawString = ((AbstractJdbc2ResultSet)rs).getFixedString(idx); this.rawString = ((AbstractJdbc2ResultSet)rs).getFixedString(idx);
} }
@ -76,9 +76,9 @@ public class Array implements java.sql.Array
ArrayList array = new ArrayList(); ArrayList array = new ArrayList();
/* Check if the String is also not an empty array /* Check if the String is also not an empty array
* otherwise there will be an exception thrown below * otherwise there will be an exception thrown below
* in the ResultSet.toX with an empty string. * in the ResultSet.toX with an empty string.
* -- Doug Fields <dfields-pg-jdbc@pexicom.com> Feb 20, 2002 */ * -- Doug Fields <dfields-pg-jdbc@pexicom.com> Feb 20, 2002 */
if ( rawString != null && !rawString.equals("{}") ) if ( rawString != null && !rawString.equals("{}") )
{ {
@ -88,9 +88,9 @@ public class Array implements java.sql.Array
boolean insideString = false; boolean insideString = false;
for ( int i = 0; i < chars.length; i++ ) for ( int i = 0; i < chars.length; i++ )
{ {
if ( chars[i] == '\\' ) if ( chars[i] == '\\' )
//escape character that we need to skip //escape character that we need to skip
i++; i++;
if ( chars[i] == '{' ) if ( chars[i] == '{' )
{ {
if ( foundOpen ) // Only supports 1-D arrays for now if ( foundOpen ) // Only supports 1-D arrays for now

View File

@ -6,55 +6,55 @@ import java.util.Vector;
import java.util.Hashtable; import java.util.Hashtable;
import org.postgresql.Field; import org.postgresql.Field;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.4 2002/07/26 05:29:35 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Connection.java,v 1.5 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.Connection interface for JDBC2. * This class implements the java.sql.Connection interface for JDBC2.
* However most of the implementation is really done in * However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2Connection or one of it's parents * org.postgresql.jdbc2.AbstractJdbc2Connection or one of it's parents
*/ */
public class Jdbc2Connection extends org.postgresql.jdbc2.AbstractJdbc2Connection implements java.sql.Connection public class Jdbc2Connection extends org.postgresql.jdbc2.AbstractJdbc2Connection implements java.sql.Connection
{ {
public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
{ {
Jdbc2Statement s = new Jdbc2Statement(this); Jdbc2Statement s = new Jdbc2Statement(this);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc2PreparedStatement s = new Jdbc2PreparedStatement(this, sql);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc2CallableStatement s = new org.postgresql.jdbc2.Jdbc2CallableStatement(this,sql);
s.setResultSetType(resultSetType); s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency); s.setResultSetConcurrency(resultSetConcurrency);
return s; return s;
} }
public java.sql.DatabaseMetaData getMetaData() throws SQLException
{
if (metadata == null)
metadata = new org.postgresql.jdbc2.Jdbc2DatabaseMetaData(this);
return metadata;
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{ {
return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); Jdbc2PreparedStatement s = new Jdbc2PreparedStatement(this, sql);
} s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{ {
return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, 0, false); Jdbc2CallableStatement s = new org.postgresql.jdbc2.Jdbc2CallableStatement(this, sql);
} s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.DatabaseMetaData getMetaData() throws SQLException
{
if (metadata == null)
metadata = new org.postgresql.jdbc2.Jdbc2DatabaseMetaData(this);
return metadata;
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
{
return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException
{
return new Jdbc2ResultSet(this, statement, fields, tuples, status, updateCount, 0, false);
}
} }

View File

@ -5,9 +5,9 @@ import java.sql.*;
import java.util.Vector; import java.util.Vector;
import org.postgresql.Field; import org.postgresql.Field;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.4 2002/08/14 20:35:39 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2ResultSet.java,v 1.5 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.ResultSet interface for JDBC2. * This class implements the java.sql.ResultSet interface for JDBC2.
* However most of the implementation is really done in * However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2ResultSet or one of it's parents * org.postgresql.jdbc2.AbstractJdbc2ResultSet or one of it's parents
*/ */
public class Jdbc2ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet implements java.sql.ResultSet public class Jdbc2ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet implements java.sql.ResultSet
@ -23,13 +23,15 @@ public class Jdbc2ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet
return new Jdbc2ResultSetMetaData(rows, fields); return new Jdbc2ResultSetMetaData(rows, fields);
} }
public java.sql.Clob getClob(int i) throws SQLException { public java.sql.Clob getClob(int i) throws SQLException
return new org.postgresql.jdbc2.Jdbc2Clob(connection, getInt(i)); {
} return new org.postgresql.jdbc2.Jdbc2Clob(connection, getInt(i));
}
public java.sql.Blob getBlob(int i) throws SQLException { public java.sql.Blob getBlob(int i) throws SQLException
return new org.postgresql.jdbc2.Jdbc2Blob(connection, getInt(i)); {
} return new org.postgresql.jdbc2.Jdbc2Blob(connection, getInt(i));
}
} }

View File

@ -4,7 +4,7 @@ public class Jdbc2ResultSetMetaData extends AbstractJdbc2ResultSetMetaData imple
{ {
public Jdbc2ResultSetMetaData(java.util.Vector rows, org.postgresql.Field[] fields) public Jdbc2ResultSetMetaData(java.util.Vector rows, org.postgresql.Field[] fields)
{ {
super(rows, fields); super(rows, fields);
} }
} }

View File

@ -3,9 +3,9 @@ package org.postgresql.jdbc2;
import java.sql.*; import java.sql.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.2 2002/07/24 22:08:43 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc2/Attic/Jdbc2Statement.java,v 1.3 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.Statement interface for JDBC2. * This class implements the java.sql.Statement interface for JDBC2.
* However most of the implementation is really done in * However most of the implementation is really done in
* org.postgresql.jdbc2.AbstractJdbc2Statement or one of it's parents * org.postgresql.jdbc2.AbstractJdbc2Statement or one of it's parents
*/ */
public class Jdbc2Statement extends org.postgresql.jdbc2.AbstractJdbc2Statement implements java.sql.Statement public class Jdbc2Statement extends org.postgresql.jdbc2.AbstractJdbc2Statement implements java.sql.Statement

View File

@ -8,217 +8,249 @@ import java.sql.*;
* Base class for data sources and related classes. * Base class for data sources and related classes.
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public abstract class BaseDataSource implements Referenceable { public abstract class BaseDataSource implements Referenceable
// Load the normal driver, since we'll use it to actually connect to the {
// database. That way we don't have to maintain the connecting code in // Load the normal driver, since we'll use it to actually connect to the
// multiple places. // database. That way we don't have to maintain the connecting code in
static { // multiple places.
try { static {
Class.forName("org.postgresql.Driver"); try
} catch (ClassNotFoundException e) { {
System.err.println("PostgreSQL DataSource unable to load PostgreSQL JDBC Driver"); Class.forName("org.postgresql.Driver");
} }
} catch (ClassNotFoundException e)
{
System.err.println("PostgreSQL DataSource unable to load PostgreSQL JDBC Driver");
}
}
// Needed to implement the DataSource/ConnectionPoolDataSource interfaces // Needed to implement the DataSource/ConnectionPoolDataSource interfaces
private transient PrintWriter logger; private transient PrintWriter logger;
// Don't track loginTimeout, since we'd just ignore it anyway // Don't track loginTimeout, since we'd just ignore it anyway
// Standard properties, defined in the JDBC 2.0 Optional Package spec // Standard properties, defined in the JDBC 2.0 Optional Package spec
private String serverName = "localhost"; private String serverName = "localhost";
private String databaseName; private String databaseName;
private String user; private String user;
private String password; private String password;
private int portNumber; private int portNumber;
/** /**
* Gets a connection to the PostgreSQL database. The database is identified by the * Gets a connection to the PostgreSQL database. The database is identified by the
* DataSource properties serverName, databaseName, and portNumber. The user to * DataSource properties serverName, databaseName, and portNumber. The user to
* connect as is identified by the DataSource properties user and password. * connect as is identified by the DataSource properties user and password.
* *
* @return A valid database connection. * @return A valid database connection.
* @throws SQLException * @throws SQLException
* Occurs when the database connection cannot be established. * Occurs when the database connection cannot be established.
*/ */
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException
return getConnection(user, password); {
} return getConnection(user, password);
}
/** /**
* Gets a connection to the PostgreSQL database. The database is identified by the * Gets a connection to the PostgreSQL database. The database is identified by the
* DataAource properties serverName, databaseName, and portNumber. The user to * DataAource properties serverName, databaseName, and portNumber. The user to
* connect as is identified by the arguments user and password, which override * connect as is identified by the arguments user and password, which override
* the DataSource properties by the same name. * the DataSource properties by the same name.
* *
* @return A valid database connection. * @return A valid database connection.
* @throws SQLException * @throws SQLException
* Occurs when the database connection cannot be established. * Occurs when the database connection cannot be established.
*/ */
public Connection getConnection(String user, String password) throws SQLException { public Connection getConnection(String user, String password) throws SQLException
try { {
Connection con = DriverManager.getConnection(getUrl(), user, password); try
if (logger != null) { {
logger.println("Created a non-pooled connection for " + user + " at " + getUrl()); Connection con = DriverManager.getConnection(getUrl(), user, password);
} if (logger != null)
return con; {
} catch (SQLException e) { logger.println("Created a non-pooled connection for " + user + " at " + getUrl());
if (logger != null) { }
logger.println("Failed to create a non-pooled connection for " + user + " at " + getUrl() + ": " + e); return con;
} }
throw e; catch (SQLException e)
} {
} if (logger != null)
{
logger.println("Failed to create a non-pooled connection for " + user + " at " + getUrl() + ": " + e);
}
throw e;
}
}
/** /**
* This DataSource does not support a configurable login timeout. * This DataSource does not support a configurable login timeout.
* @return 0 * @return 0
*/ */
public int getLoginTimeout() throws SQLException { public int getLoginTimeout() throws SQLException
return 0; {
} return 0;
}
/** /**
* This DataSource does not support a configurable login timeout. Any value * This DataSource does not support a configurable login timeout. Any value
* provided here will be ignored. * provided here will be ignored.
*/ */
public void setLoginTimeout(int i) throws SQLException { public void setLoginTimeout(int i) throws SQLException
} {}
/** /**
* Gets the log writer used to log connections opened. * Gets the log writer used to log connections opened.
*/ */
public PrintWriter getLogWriter() throws SQLException { public PrintWriter getLogWriter() throws SQLException
return logger; {
} return logger;
}
/** /**
* The DataSource will note every connection opened to the provided log writer. * The DataSource will note every connection opened to the provided log writer.
*/ */
public void setLogWriter(PrintWriter printWriter) throws SQLException { public void setLogWriter(PrintWriter printWriter) throws SQLException
logger = printWriter; {
} logger = printWriter;
}
/** /**
* Gets the name of the host the PostgreSQL database is running on. * Gets the name of the host the PostgreSQL database is running on.
*/ */
public String getServerName() { public String getServerName()
return serverName; {
} return serverName;
}
/** /**
* Sets the name of the host the PostgreSQL database is running on. If this * Sets the name of the host the PostgreSQL database is running on. If this
* is changed, it will only affect future calls to getConnection. The default * is changed, it will only affect future calls to getConnection. The default
* value is <tt>localhost</tt>. * value is <tt>localhost</tt>.
*/ */
public void setServerName(String serverName) { public void setServerName(String serverName)
if(serverName == null || serverName.equals("")) { {
this.serverName = "localhost"; if (serverName == null || serverName.equals(""))
} else { {
this.serverName = serverName; this.serverName = "localhost";
} }
} else
{
this.serverName = serverName;
}
}
/** /**
* Gets the name of the PostgreSQL database, running on the server identified * Gets the name of the PostgreSQL database, running on the server identified
* by the serverName property. * by the serverName property.
*/ */
public String getDatabaseName() { public String getDatabaseName()
return databaseName; {
} return databaseName;
}
/** /**
* Sets the name of the PostgreSQL database, running on the server identified * Sets the name of the PostgreSQL database, running on the server identified
* by the serverName property. If this is changed, it will only affect * by the serverName property. If this is changed, it will only affect
* future calls to getConnection. * future calls to getConnection.
*/ */
public void setDatabaseName(String databaseName) { public void setDatabaseName(String databaseName)
this.databaseName = databaseName; {
} this.databaseName = databaseName;
}
/** /**
* Gets a description of this DataSource-ish thing. Must be customized by * Gets a description of this DataSource-ish thing. Must be customized by
* subclasses. * subclasses.
*/ */
public abstract String getDescription(); public abstract String getDescription();
/** /**
* Gets the user to connect as by default. If this is not specified, you must * Gets the user to connect as by default. If this is not specified, you must
* use the getConnection method which takes a user and password as parameters. * use the getConnection method which takes a user and password as parameters.
*/ */
public String getUser() { public String getUser()
return user; {
} return user;
}
/** /**
* Sets the user to connect as by default. If this is not specified, you must * Sets the user to connect as by default. If this is not specified, you must
* use the getConnection method which takes a user and password as parameters. * use the getConnection method which takes a user and password as parameters.
* If this is changed, it will only affect future calls to getConnection. * If this is changed, it will only affect future calls to getConnection.
*/ */
public void setUser(String user) { public void setUser(String user)
this.user = user; {
} this.user = user;
}
/** /**
* Gets the password to connect with by default. If this is not specified but a * Gets the password to connect with by default. If this is not specified but a
* password is needed to log in, you must use the getConnection method which takes * password is needed to log in, you must use the getConnection method which takes
* a user and password as parameters. * a user and password as parameters.
*/ */
public String getPassword() { public String getPassword()
return password; {
} return password;
}
/** /**
* Sets the password to connect with by default. If this is not specified but a * Sets the password to connect with by default. If this is not specified but a
* password is needed to log in, you must use the getConnection method which takes * password is needed to log in, you must use the getConnection method which takes
* a user and password as parameters. If this is changed, it will only affect * a user and password as parameters. If this is changed, it will only affect
* future calls to getConnection. * future calls to getConnection.
*/ */
public void setPassword(String password) { public void setPassword(String password)
this.password = password; {
} this.password = password;
}
/** /**
* Gets the port which the PostgreSQL server is listening on for TCP/IP * Gets the port which the PostgreSQL server is listening on for TCP/IP
* connections. * connections.
* *
* @return The port, or 0 if the default port will be used. * @return The port, or 0 if the default port will be used.
*/ */
public int getPortNumber() { public int getPortNumber()
return portNumber; {
} return portNumber;
}
/** /**
* Gets the port which the PostgreSQL server is listening on for TCP/IP * Gets the port which the PostgreSQL server is listening on for TCP/IP
* connections. Be sure the -i flag is passed to postmaster when PostgreSQL * connections. Be sure the -i flag is passed to postmaster when PostgreSQL
* is started. If this is not set, or set to 0, the default port will be used. * is started. If this is not set, or set to 0, the default port will be used.
*/ */
public void setPortNumber(int portNumber) { public void setPortNumber(int portNumber)
this.portNumber = portNumber; {
} this.portNumber = portNumber;
}
/** /**
* Generates a DriverManager URL from the other properties supplied. * Generates a DriverManager URL from the other properties supplied.
*/ */
private String getUrl() { private String getUrl()
return "jdbc:postgresql://"+serverName+(portNumber == 0 ? "" : ":"+portNumber)+"/"+databaseName; {
} return "jdbc:postgresql://" + serverName + (portNumber == 0 ? "" : ":" + portNumber) + "/" + databaseName;
}
public Reference getReference() throws NamingException { public Reference getReference() throws NamingException
Reference ref = new Reference(getClass().getName(), PGObjectFactory.class.getName(), null); {
ref.add(new StringRefAddr("serverName", serverName)); Reference ref = new Reference(getClass().getName(), PGObjectFactory.class.getName(), null);
if (portNumber != 0) { ref.add(new StringRefAddr("serverName", serverName));
ref.add(new StringRefAddr("portNumber", Integer.toString(portNumber))); if (portNumber != 0)
} {
ref.add(new StringRefAddr("databaseName", databaseName)); ref.add(new StringRefAddr("portNumber", Integer.toString(portNumber)));
if (user != null) { }
ref.add(new StringRefAddr("user", user)); ref.add(new StringRefAddr("databaseName", databaseName));
} if (user != null)
if (password != null) { {
ref.add(new StringRefAddr("password", password)); ref.add(new StringRefAddr("user", user));
} }
return ref; if (password != null)
} {
ref.add(new StringRefAddr("password", password));
}
return ref;
}
} }

View File

@ -21,56 +21,62 @@ import java.io.Serializable;
* <p>This implementation supports JDK 1.3 and higher.</p> * <p>This implementation supports JDK 1.3 and higher.</p>
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public class ConnectionPool extends BaseDataSource implements Serializable, ConnectionPoolDataSource { public class ConnectionPool extends BaseDataSource implements Serializable, ConnectionPoolDataSource
private boolean defaultAutoCommit = false; {
private boolean defaultAutoCommit = false;
/** /**
* Gets a description of this DataSource. * Gets a description of this DataSource.
*/ */
public String getDescription() { public String getDescription()
return "ConnectionPoolDataSource from "+org.postgresql.Driver.getVersion(); {
} return "ConnectionPoolDataSource from " + org.postgresql.Driver.getVersion();
}
/** /**
* Gets a connection which may be pooled by the app server or middleware * Gets a connection which may be pooled by the app server or middleware
* implementation of DataSource. * implementation of DataSource.
* *
* @throws java.sql.SQLException * @throws java.sql.SQLException
* Occurs when the physical database connection cannot be established. * Occurs when the physical database connection cannot be established.
*/ */
public PooledConnection getPooledConnection() throws SQLException { public PooledConnection getPooledConnection() throws SQLException
return new PooledConnectionImpl(getConnection(), defaultAutoCommit); {
} return new PooledConnectionImpl(getConnection(), defaultAutoCommit);
}
/** /**
* Gets a connection which may be pooled by the app server or middleware * Gets a connection which may be pooled by the app server or middleware
* implementation of DataSource. * implementation of DataSource.
* *
* @throws java.sql.SQLException * @throws java.sql.SQLException
* Occurs when the physical database connection cannot be established. * Occurs when the physical database connection cannot be established.
*/ */
public PooledConnection getPooledConnection(String user, String password) throws SQLException { public PooledConnection getPooledConnection(String user, String password) throws SQLException
return new PooledConnectionImpl(getConnection(user, password), defaultAutoCommit); {
} return new PooledConnectionImpl(getConnection(user, password), defaultAutoCommit);
}
/** /**
* Gets whether connections supplied by this pool will have autoCommit * Gets whether connections supplied by this pool will have autoCommit
* turned on by default. The default value is <tt>false</tt>, so that * turned on by default. The default value is <tt>false</tt>, so that
* autoCommit will be turned off by default. * autoCommit will be turned off by default.
*/ */
public boolean isDefaultAutoCommit() { public boolean isDefaultAutoCommit()
return defaultAutoCommit; {
} return defaultAutoCommit;
}
/** /**
* Sets whether connections supplied by this pool will have autoCommit * Sets whether connections supplied by this pool will have autoCommit
* turned on by default. The default value is <tt>false</tt>, so that * turned on by default. The default value is <tt>false</tt>, so that
* autoCommit will be turned off by default. * autoCommit will be turned off by default.
*/ */
public void setDefaultAutoCommit(boolean defaultAutoCommit) { public void setDefaultAutoCommit(boolean defaultAutoCommit)
this.defaultAutoCommit = defaultAutoCommit; {
} this.defaultAutoCommit = defaultAutoCommit;
}
} }

View File

@ -13,77 +13,96 @@ import java.util.Hashtable;
* consistent. * consistent.
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public class PGObjectFactory implements ObjectFactory { public class PGObjectFactory implements ObjectFactory
/** {
* Dereferences a PostgreSQL DataSource. Other types of references are /**
* ignored. * Dereferences a PostgreSQL DataSource. Other types of references are
*/ * ignored.
public Object getObjectInstance(Object obj, Name name, Context nameCtx, */
Hashtable environment) throws Exception { public Object getObjectInstance(Object obj, Name name, Context nameCtx,
Reference ref = (Reference)obj; Hashtable environment) throws Exception
if(ref.getClassName().equals(SimpleDataSource.class.getName())) { {
return loadSimpleDataSource(ref); Reference ref = (Reference)obj;
} else if (ref.getClassName().equals(ConnectionPool.class.getName())) { if (ref.getClassName().equals(SimpleDataSource.class.getName()))
return loadConnectionPool(ref); {
} else if (ref.getClassName().equals(PoolingDataSource.class.getName())) { return loadSimpleDataSource(ref);
return loadPoolingDataSource(ref); }
} else { else if (ref.getClassName().equals(ConnectionPool.class.getName()))
return null; {
} return loadConnectionPool(ref);
} }
else if (ref.getClassName().equals(PoolingDataSource.class.getName()))
{
return loadPoolingDataSource(ref);
}
else
{
return null;
}
}
private Object loadPoolingDataSource(Reference ref) { private Object loadPoolingDataSource(Reference ref)
// If DataSource exists, return it {
String name = getProperty(ref, "dataSourceName"); // If DataSource exists, return it
PoolingDataSource pds = PoolingDataSource.getDataSource(name); String name = getProperty(ref, "dataSourceName");
if(pds != null) { PoolingDataSource pds = PoolingDataSource.getDataSource(name);
return pds; if (pds != null)
} {
// Otherwise, create a new one return pds;
pds = new PoolingDataSource(); }
pds.setDataSourceName(name); // Otherwise, create a new one
loadBaseDataSource(pds, ref); pds = new PoolingDataSource();
String min = getProperty(ref, "initialConnections"); pds.setDataSourceName(name);
if (min != null) { loadBaseDataSource(pds, ref);
pds.setInitialConnections(Integer.parseInt(min)); String min = getProperty(ref, "initialConnections");
} if (min != null)
String max = getProperty(ref, "maxConnections"); {
if (max != null) { pds.setInitialConnections(Integer.parseInt(min));
pds.setMaxConnections(Integer.parseInt(max)); }
} String max = getProperty(ref, "maxConnections");
return pds; if (max != null)
} {
pds.setMaxConnections(Integer.parseInt(max));
}
return pds;
}
private Object loadSimpleDataSource(Reference ref) { private Object loadSimpleDataSource(Reference ref)
SimpleDataSource ds = new SimpleDataSource(); {
return loadBaseDataSource(ds, ref); SimpleDataSource ds = new SimpleDataSource();
} return loadBaseDataSource(ds, ref);
}
private Object loadConnectionPool(Reference ref) { private Object loadConnectionPool(Reference ref)
ConnectionPool cp = new ConnectionPool(); {
return loadBaseDataSource(cp, ref); ConnectionPool cp = new ConnectionPool();
} return loadBaseDataSource(cp, ref);
}
private Object loadBaseDataSource(BaseDataSource ds, Reference ref) { private Object loadBaseDataSource(BaseDataSource ds, Reference ref)
ds.setDatabaseName(getProperty(ref, "databaseName")); {
ds.setPassword(getProperty(ref, "password")); ds.setDatabaseName(getProperty(ref, "databaseName"));
String port = getProperty(ref, "portNumber"); ds.setPassword(getProperty(ref, "password"));
if(port != null) { String port = getProperty(ref, "portNumber");
ds.setPortNumber(Integer.parseInt(port)); if (port != null)
} {
ds.setServerName(getProperty(ref, "serverName")); ds.setPortNumber(Integer.parseInt(port));
ds.setUser(getProperty(ref, "user")); }
return ds; ds.setServerName(getProperty(ref, "serverName"));
} ds.setUser(getProperty(ref, "user"));
return ds;
}
private String getProperty(Reference ref, String s) { private String getProperty(Reference ref, String s)
RefAddr addr = ref.get(s); {
if(addr == null) { RefAddr addr = ref.get(s);
return null; if (addr == null)
} {
return (String)addr.getContent(); return null;
} }
return (String)addr.getContent();
}
} }

View File

@ -13,187 +13,244 @@ import java.lang.reflect.*;
* @see ConnectionPool * @see ConnectionPool
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public class PooledConnectionImpl implements PooledConnection { public class PooledConnectionImpl implements PooledConnection
private List listeners = new LinkedList(); {
private Connection con; private List listeners = new LinkedList();
private ConnectionHandler last; private Connection con;
private boolean autoCommit; private ConnectionHandler last;
private boolean autoCommit;
/** /**
* Creates a new PooledConnection representing the specified physical * Creates a new PooledConnection representing the specified physical
* connection. * connection.
*/ */
PooledConnectionImpl(Connection con, boolean autoCommit) { PooledConnectionImpl(Connection con, boolean autoCommit)
this.con = con; {
this.autoCommit = autoCommit; this.con = con;
} this.autoCommit = autoCommit;
}
/** /**
* Adds a listener for close or fatal error events on the connection * Adds a listener for close or fatal error events on the connection
* handed out to a client. * handed out to a client.
*/ */
public void addConnectionEventListener(ConnectionEventListener connectionEventListener) { public void addConnectionEventListener(ConnectionEventListener connectionEventListener)
listeners.add(connectionEventListener); {
} listeners.add(connectionEventListener);
}
/** /**
* Removes a listener for close or fatal error events on the connection * Removes a listener for close or fatal error events on the connection
* handed out to a client. * handed out to a client.
*/ */
public void removeConnectionEventListener(ConnectionEventListener connectionEventListener) { public void removeConnectionEventListener(ConnectionEventListener connectionEventListener)
listeners.remove(connectionEventListener); {
} listeners.remove(connectionEventListener);
}
/** /**
* Closes the physical database connection represented by this * Closes the physical database connection represented by this
* PooledConnection. If any client has a connection based on * PooledConnection. If any client has a connection based on
* this PooledConnection, it is forcibly closed as well. * this PooledConnection, it is forcibly closed as well.
*/ */
public void close() throws SQLException { public void close() throws SQLException
if(last != null) { {
last.close(); if (last != null)
if(!con.getAutoCommit()) { {
try {con.rollback();} catch (SQLException e) {} last.close();
} if (!con.getAutoCommit())
} {
try { try
con.close(); {
} finally { con.rollback();
con = null; }
} catch (SQLException e)
} {}
}
}
try
{
con.close();
}
finally
{
con = null;
}
}
/** /**
* Gets a handle for a client to use. This is a wrapper around the * Gets a handle for a client to use. This is a wrapper around the
* physical connection, so the client can call close and it will just * physical connection, so the client can call close and it will just
* return the connection to the pool without really closing the * return the connection to the pool without really closing the
* pgysical connection. * pgysical connection.
* *
* <p>According to the JDBC 2.0 Optional Package spec (6.2.3), only one * <p>According to the JDBC 2.0 Optional Package spec (6.2.3), only one
* client may have an active handle to the connection at a time, so if * client may have an active handle to the connection at a time, so if
* there is a previous handle active when this is called, the previous * there is a previous handle active when this is called, the previous
* one is forcibly closed and its work rolled back.</p> * one is forcibly closed and its work rolled back.</p>
*/ */
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException
if(con == null) { {
throw new SQLException("This PooledConnection has already been closed!"); if (con == null)
} {
// Only one connection can be open at a time from this PooledConnection. See JDBC 2.0 Optional Package spec section 6.2.3 throw new SQLException("This PooledConnection has already been closed!");
if(last != null) { }
last.close(); // Only one connection can be open at a time from this PooledConnection. See JDBC 2.0 Optional Package spec section 6.2.3
if(!con.getAutoCommit()) { if (last != null)
try {con.rollback();} catch(SQLException e) {} {
} last.close();
con.clearWarnings(); if (!con.getAutoCommit())
} {
con.setAutoCommit(autoCommit); try
ConnectionHandler handler = new ConnectionHandler(con); {
last = handler; con.rollback();
return (Connection)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Connection.class}, handler); }
} catch (SQLException e)
{}
}
con.clearWarnings();
}
con.setAutoCommit(autoCommit);
ConnectionHandler handler = new ConnectionHandler(con);
last = handler;
return (Connection)Proxy.newProxyInstance(getClass().getClassLoader(), new Class[]{Connection.class}, handler);
}
/** /**
* Used to fire a connection event to all listeners. * Used to fire a connection event to all listeners.
*/ */
void fireConnectionClosed() { void fireConnectionClosed()
ConnectionEvent evt = null; {
// Copy the listener list so the listener can remove itself during this method call ConnectionEvent evt = null;
ConnectionEventListener[] local = (ConnectionEventListener[]) listeners.toArray(new ConnectionEventListener[listeners.size()]); // Copy the listener list so the listener can remove itself during this method call
for (int i = 0; i < local.length; i++) { ConnectionEventListener[] local = (ConnectionEventListener[]) listeners.toArray(new ConnectionEventListener[listeners.size()]);
ConnectionEventListener listener = local[i]; for (int i = 0; i < local.length; i++)
if (evt == null) { {
evt = new ConnectionEvent(this); ConnectionEventListener listener = local[i];
} if (evt == null)
listener.connectionClosed(evt); {
} evt = new ConnectionEvent(this);
} }
listener.connectionClosed(evt);
}
}
/** /**
* Used to fire a connection event to all listeners. * Used to fire a connection event to all listeners.
*/ */
void fireConnectionFatalError(SQLException e) { void fireConnectionFatalError(SQLException e)
ConnectionEvent evt = null; {
// Copy the listener list so the listener can remove itself during this method call ConnectionEvent evt = null;
ConnectionEventListener[] local = (ConnectionEventListener[])listeners.toArray(new ConnectionEventListener[listeners.size()]); // Copy the listener list so the listener can remove itself during this method call
for (int i=0; i<local.length; i++) { ConnectionEventListener[] local = (ConnectionEventListener[])listeners.toArray(new ConnectionEventListener[listeners.size()]);
ConnectionEventListener listener = local[i]; for (int i = 0; i < local.length; i++)
if (evt == null) { {
evt = new ConnectionEvent(this, e); ConnectionEventListener listener = local[i];
} if (evt == null)
listener.connectionErrorOccurred(evt); {
} evt = new ConnectionEvent(this, e);
} }
listener.connectionErrorOccurred(evt);
}
}
/** /**
* Instead of declaring a class implementing Connection, which would have * Instead of declaring a class implementing Connection, which would have
* to be updated for every JDK rev, use a dynamic proxy to handle all * to be updated for every JDK rev, use a dynamic proxy to handle all
* calls through the Connection interface. This is the part that * calls through the Connection interface. This is the part that
* requires JDK 1.3 or higher, though JDK 1.2 could be supported with a * requires JDK 1.3 or higher, though JDK 1.2 could be supported with a
* 3rd-party proxy package. * 3rd-party proxy package.
*/ */
private class ConnectionHandler implements InvocationHandler { private class ConnectionHandler implements InvocationHandler
private Connection con; {
private boolean automatic = false; private Connection con;
private boolean automatic = false;
public ConnectionHandler(Connection con) { public ConnectionHandler(Connection con)
this.con = con; {
} this.con = con;
}
public Object invoke(Object proxy, Method method, Object[] args) public Object invoke(Object proxy, Method method, Object[] args)
throws Throwable { throws Throwable
// From Object {
if(method.getDeclaringClass().getName().equals("java.lang.Object")) { // From Object
if(method.getName().equals("toString")) { if (method.getDeclaringClass().getName().equals("java.lang.Object"))
return "Pooled connection wrapping physical connection "+con; {
} if (method.getName().equals("toString"))
if(method.getName().equals("hashCode")) { {
return new Integer(con.hashCode()); return "Pooled connection wrapping physical connection " + con;
} }
if(method.getName().equals("equals")) { if (method.getName().equals("hashCode"))
if(args[0] == null) { {
return Boolean.FALSE; return new Integer(con.hashCode());
} }
try { if (method.getName().equals("equals"))
return Proxy.isProxyClass(args[0].getClass()) && ((ConnectionHandler) Proxy.getInvocationHandler(args[0])).con == con ? Boolean.TRUE : Boolean.FALSE; {
} catch(ClassCastException e) { if (args[0] == null)
return Boolean.FALSE; {
} return Boolean.FALSE;
} }
return method.invoke(con, args); try
} {
// All the rest is from the Connection interface return Proxy.isProxyClass(args[0].getClass()) && ((ConnectionHandler) Proxy.getInvocationHandler(args[0])).con == con ? Boolean.TRUE : Boolean.FALSE;
if(method.getName().equals("isClosed")) { }
return con == null ? Boolean.TRUE : Boolean.FALSE; catch (ClassCastException e)
} {
if(con == null) { return Boolean.FALSE;
throw new SQLException(automatic ? "Connection has been closed automatically because a new connection was opened for the same PooledConnection or the PooledConnection has been closed" : "Connection has been closed"); }
} }
if(method.getName().equals("close")) { return method.invoke(con, args);
SQLException ex = null; }
if(!con.getAutoCommit()) { // All the rest is from the Connection interface
try {con.rollback();} catch(SQLException e) {ex = e;} if (method.getName().equals("isClosed"))
} {
con.clearWarnings(); return con == null ? Boolean.TRUE : Boolean.FALSE;
con = null; }
last = null; if (con == null)
fireConnectionClosed(); {
if(ex != null) { throw new SQLException(automatic ? "Connection has been closed automatically because a new connection was opened for the same PooledConnection or the PooledConnection has been closed" : "Connection has been closed");
throw ex; }
} if (method.getName().equals("close"))
return null; {
} else { SQLException ex = null;
return method.invoke(con, args); if (!con.getAutoCommit())
} {
} try
{
con.rollback();
}
catch (SQLException e)
{
ex = e;
}
}
con.clearWarnings();
con = null;
last = null;
fireConnectionClosed();
if (ex != null)
{
throw ex;
}
return null;
}
else
{
return method.invoke(con, args);
}
}
public void close() { public void close()
if(con != null) { {
automatic = true; if (con != null)
} {
con = null; automatic = true;
// No close event fired here: see JDBC 2.0 Optional Package spec section 6.3 }
} con = null;
} // No close event fired here: see JDBC 2.0 Optional Package spec section 6.3
}
}
} }

View File

@ -26,388 +26,454 @@ import java.sql.SQLException;
* *
* <p>If you put this DataSource in JNDI, and access it from different JVMs (or * <p>If you put this DataSource in JNDI, and access it from different JVMs (or
* otherwise load this class from different ClassLoaders), you'll end up with one * otherwise load this class from different ClassLoaders), you'll end up with one
* pool per ClassLoader or VM. This is another area where a server-specific * pool per ClassLoader or VM. This is another area where a server-specific
* implementation may provide advanced features, such as using a single pool * implementation may provide advanced features, such as using a single pool
* across all VMs in a cluster.</p> * across all VMs in a cluster.</p>
* *
* <p>This implementation supports JDK 1.3 and higher.</p> * <p>This implementation supports JDK 1.3 and higher.</p>
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public class PoolingDataSource extends BaseDataSource implements DataSource { public class PoolingDataSource extends BaseDataSource implements DataSource
private static Map dataSources = new HashMap(); {
private static Map dataSources = new HashMap();
static PoolingDataSource getDataSource(String name) { static PoolingDataSource getDataSource(String name)
return (PoolingDataSource)dataSources.get(name); {
} return (PoolingDataSource)dataSources.get(name);
}
// Additional Data Source properties // Additional Data Source properties
private String dataSourceName; private String dataSourceName;
private int initialConnections = 0; private int initialConnections = 0;
private int maxConnections = 0; private int maxConnections = 0;
// State variables // State variables
private boolean initialized = false; private boolean initialized = false;
private Stack available = new Stack(); private Stack available = new Stack();
private Stack used = new Stack(); private Stack used = new Stack();
private Object lock = new Object(); private Object lock = new Object();
private ConnectionPool source; private ConnectionPool source;
/** /**
* Gets a description of this DataSource. * Gets a description of this DataSource.
*/ */
public String getDescription() { public String getDescription()
return "Pooling DataSource '"+dataSourceName+" from "+org.postgresql.Driver.getVersion(); {
} return "Pooling DataSource '" + dataSourceName + " from " + org.postgresql.Driver.getVersion();
}
/** /**
* Ensures the DataSource properties are not changed after the DataSource has * Ensures the DataSource properties are not changed after the DataSource has
* been used. * been used.
* *
* @throws java.lang.IllegalStateException * @throws java.lang.IllegalStateException
* The Server Name cannot be changed after the DataSource has been * The Server Name cannot be changed after the DataSource has been
* used. * used.
*/ */
public void setServerName(String serverName) { public void setServerName(String serverName)
if (initialized) { {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); if (initialized)
} {
super.setServerName(serverName); throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
} }
super.setServerName(serverName);
}
/** /**
* Ensures the DataSource properties are not changed after the DataSource has * Ensures the DataSource properties are not changed after the DataSource has
* been used. * been used.
* *
* @throws java.lang.IllegalStateException * @throws java.lang.IllegalStateException
* The Database Name cannot be changed after the DataSource has been * The Database Name cannot be changed after the DataSource has been
* used. * used.
*/ */
public void setDatabaseName(String databaseName) { public void setDatabaseName(String databaseName)
if (initialized) { {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); if (initialized)
} {
super.setDatabaseName(databaseName); throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
} }
super.setDatabaseName(databaseName);
}
/** /**
* Ensures the DataSource properties are not changed after the DataSource has * Ensures the DataSource properties are not changed after the DataSource has
* been used. * been used.
* *
* @throws java.lang.IllegalStateException * @throws java.lang.IllegalStateException
* The User cannot be changed after the DataSource has been * The User cannot be changed after the DataSource has been
* used. * used.
*/ */
public void setUser(String user) { public void setUser(String user)
if (initialized) { {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); if (initialized)
} {
super.setUser(user); throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
} }
super.setUser(user);
}
/** /**
* Ensures the DataSource properties are not changed after the DataSource has * Ensures the DataSource properties are not changed after the DataSource has
* been used. * been used.
* *
* @throws java.lang.IllegalStateException * @throws java.lang.IllegalStateException
* The Password cannot be changed after the DataSource has been * The Password cannot be changed after the DataSource has been
* used. * used.
*/ */
public void setPassword(String password) { public void setPassword(String password)
if (initialized) { {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); if (initialized)
} {
super.setPassword(password); throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
} }
super.setPassword(password);
}
/** /**
* Ensures the DataSource properties are not changed after the DataSource has * Ensures the DataSource properties are not changed after the DataSource has
* been used. * been used.
* *
* @throws java.lang.IllegalStateException * @throws java.lang.IllegalStateException
* The Port Number cannot be changed after the DataSource has been * The Port Number cannot be changed after the DataSource has been
* used. * used.
*/ */
public void setPortNumber(int portNumber) { public void setPortNumber(int portNumber)
if (initialized) { {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); if (initialized)
} {
super.setPortNumber(portNumber); throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
} }
super.setPortNumber(portNumber);
}
/** /**
* Gets the number of connections that will be created when this DataSource * Gets the number of connections that will be created when this DataSource
* is initialized. If you do not call initialize explicitly, it will be * is initialized. If you do not call initialize explicitly, it will be
* initialized the first time a connection is drawn from it. * initialized the first time a connection is drawn from it.
*/ */
public int getInitialConnections() { public int getInitialConnections()
return initialConnections; {
} return initialConnections;
}
/** /**
* Sets the number of connections that will be created when this DataSource * Sets the number of connections that will be created when this DataSource
* is initialized. If you do not call initialize explicitly, it will be * is initialized. If you do not call initialize explicitly, it will be
* initialized the first time a connection is drawn from it. * initialized the first time a connection is drawn from it.
* *
* @throws java.lang.IllegalStateException * @throws java.lang.IllegalStateException
* The Initial Connections cannot be changed after the DataSource has been * The Initial Connections cannot be changed after the DataSource has been
* used. * used.
*/ */
public void setInitialConnections(int initialConnections) { public void setInitialConnections(int initialConnections)
if (initialized) { {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); if (initialized)
} {
this.initialConnections = initialConnections; throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
} }
this.initialConnections = initialConnections;
}
/** /**
* Gets the maximum number of connections that the pool will allow. If a request * Gets the maximum number of connections that the pool will allow. If a request
* comes in and this many connections are in use, the request will block until a * comes in and this many connections are in use, the request will block until a
* connection is available. Note that connections for a user other than the * connection is available. Note that connections for a user other than the
* default user will not be pooled and don't count against this limit. * default user will not be pooled and don't count against this limit.
* *
* @return The maximum number of pooled connection allowed, or 0 for no maximum. * @return The maximum number of pooled connection allowed, or 0 for no maximum.
*/ */
public int getMaxConnections() { public int getMaxConnections()
return maxConnections; {
} return maxConnections;
}
/** /**
* Sets the maximum number of connections that the pool will allow. If a request * Sets the maximum number of connections that the pool will allow. If a request
* comes in and this many connections are in use, the request will block until a * comes in and this many connections are in use, the request will block until a
* connection is available. Note that connections for a user other than the * connection is available. Note that connections for a user other than the
* default user will not be pooled and don't count against this limit. * default user will not be pooled and don't count against this limit.
* *
* @param maxConnections The maximum number of pooled connection to allow, or * @param maxConnections The maximum number of pooled connection to allow, or
* 0 for no maximum. * 0 for no maximum.
* *
* @throws java.lang.IllegalStateException * @throws java.lang.IllegalStateException
* The Maximum Connections cannot be changed after the DataSource has been * The Maximum Connections cannot be changed after the DataSource has been
* used. * used.
*/ */
public void setMaxConnections(int maxConnections) { public void setMaxConnections(int maxConnections)
if (initialized) { {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); if (initialized)
} {
this.maxConnections = maxConnections; throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
} }
this.maxConnections = maxConnections;
}
/** /**
* Gets the name of this DataSource. This uniquely identifies the DataSource. * Gets the name of this DataSource. This uniquely identifies the DataSource.
* You cannot use more than one DataSource in the same VM with the same name. * You cannot use more than one DataSource in the same VM with the same name.
*/ */
public String getDataSourceName() { public String getDataSourceName()
return dataSourceName; {
} return dataSourceName;
}
/** /**
* Sets the name of this DataSource. This is required, and uniquely identifies * Sets the name of this DataSource. This is required, and uniquely identifies
* the DataSource. You cannot create or use more than one DataSource in the * the DataSource. You cannot create or use more than one DataSource in the
* same VM with the same name. * same VM with the same name.
* *
* @throws java.lang.IllegalStateException * @throws java.lang.IllegalStateException
* The Data Source Name cannot be changed after the DataSource has been * The Data Source Name cannot be changed after the DataSource has been
* used. * used.
* @throws java.lang.IllegalArgumentException * @throws java.lang.IllegalArgumentException
* Another PoolingDataSource with the same dataSourceName already * Another PoolingDataSource with the same dataSourceName already
* exists. * exists.
*/ */
public void setDataSourceName(String dataSourceName) { public void setDataSourceName(String dataSourceName)
if(initialized) { {
throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used"); if (initialized)
} {
if(this.dataSourceName != null && dataSourceName != null && dataSourceName.equals(this.dataSourceName)) { throw new IllegalStateException("Cannot set Data Source properties after DataSource has been used");
return; }
} if (this.dataSourceName != null && dataSourceName != null && dataSourceName.equals(this.dataSourceName))
synchronized(dataSources) { {
if(getDataSource(dataSourceName) != null) { return ;
throw new IllegalArgumentException("DataSource with name '"+dataSourceName+"' already exists!"); }
} synchronized (dataSources)
if (this.dataSourceName != null) { {
dataSources.remove(this.dataSourceName); if (getDataSource(dataSourceName) != null)
} {
this.dataSourceName = dataSourceName; throw new IllegalArgumentException("DataSource with name '" + dataSourceName + "' already exists!");
dataSources.put(dataSourceName, this); }
} if (this.dataSourceName != null)
} {
dataSources.remove(this.dataSourceName);
}
this.dataSourceName = dataSourceName;
dataSources.put(dataSourceName, this);
}
}
/** /**
* Initializes this DataSource. If the initialConnections is greater than zero, * Initializes this DataSource. If the initialConnections is greater than zero,
* that number of connections will be created. After this method is called, * that number of connections will be created. After this method is called,
* the DataSource properties cannot be changed. If you do not call this * the DataSource properties cannot be changed. If you do not call this
* explicitly, it will be called the first time you get a connection from the * explicitly, it will be called the first time you get a connection from the
* Datasource. * Datasource.
* @throws java.sql.SQLException * @throws java.sql.SQLException
* Occurs when the initialConnections is greater than zero, but the * Occurs when the initialConnections is greater than zero, but the
* DataSource is not able to create enough physical connections. * DataSource is not able to create enough physical connections.
*/ */
public void initialize() throws SQLException { public void initialize() throws SQLException
synchronized (lock) { {
source = new ConnectionPool(); synchronized (lock)
source.setDatabaseName(getDatabaseName()); {
source.setPassword(getPassword()); source = new ConnectionPool();
source.setPortNumber(getPortNumber()); source.setDatabaseName(getDatabaseName());
source.setServerName(getServerName()); source.setPassword(getPassword());
source.setUser(getUser()); source.setPortNumber(getPortNumber());
while (available.size() < initialConnections) { source.setServerName(getServerName());
available.push(source.getPooledConnection()); source.setUser(getUser());
} while (available.size() < initialConnections)
initialized = true; {
} available.push(source.getPooledConnection());
} }
initialized = true;
}
}
/** /**
* Gets a <b>non-pooled</b> connection, unless the user and password are the * Gets a <b>non-pooled</b> connection, unless the user and password are the
* same as the default values for this connection pool. * same as the default values for this connection pool.
* *
* @return A pooled connection. * @return A pooled connection.
* @throws SQLException * @throws SQLException
* Occurs when no pooled connection is available, and a new physical * Occurs when no pooled connection is available, and a new physical
* connection cannot be created. * connection cannot be created.
*/ */
public Connection getConnection(String user, String password) throws SQLException { public Connection getConnection(String user, String password) throws SQLException
// If this is for the default user/password, use a pooled connection {
if(user == null || // If this is for the default user/password, use a pooled connection
(user.equals(getUser()) && ((password == null && getPassword() == null) || (password != null && password.equals(getPassword()))))) { if (user == null ||
return getConnection(); (user.equals(getUser()) && ((password == null && getPassword() == null) || (password != null && password.equals(getPassword())))))
} {
// Otherwise, use a non-pooled connection return getConnection();
if (!initialized) { }
initialize(); // Otherwise, use a non-pooled connection
} if (!initialized)
return super.getConnection(user, password); {
} initialize();
}
return super.getConnection(user, password);
}
/** /**
* Gets a connection from the connection pool. * Gets a connection from the connection pool.
* *
* @return A pooled connection. * @return A pooled connection.
* @throws SQLException * @throws SQLException
* Occurs when no pooled connection is available, and a new physical * Occurs when no pooled connection is available, and a new physical
* connection cannot be created. * connection cannot be created.
*/ */
public Connection getConnection() throws SQLException { public Connection getConnection() throws SQLException
if(!initialized) { {
initialize(); if (!initialized)
} {
return getPooledConnection(); initialize();
} }
return getPooledConnection();
}
/** /**
* Closes this DataSource, and all the pooled connections, whether in use or not. * Closes this DataSource, and all the pooled connections, whether in use or not.
*/ */
public void close() { public void close()
synchronized(lock) { {
while(available.size() > 0) { synchronized (lock)
PooledConnectionImpl pci = (PooledConnectionImpl)available.pop(); {
try { while (available.size() > 0)
pci.close(); {
} catch (SQLException e) { PooledConnectionImpl pci = (PooledConnectionImpl)available.pop();
} try
} {
available = null; pci.close();
while (used.size() > 0) { }
PooledConnectionImpl pci = (PooledConnectionImpl)used.pop(); catch (SQLException e)
pci.removeConnectionEventListener(connectionEventListener); {}
try { }
pci.close(); available = null;
} catch (SQLException e) { while (used.size() > 0)
} {
} PooledConnectionImpl pci = (PooledConnectionImpl)used.pop();
used = null; pci.removeConnectionEventListener(connectionEventListener);
} try
synchronized (dataSources) { {
dataSources.remove(dataSourceName); pci.close();
} }
} catch (SQLException e)
{}
}
used = null;
}
synchronized (dataSources)
{
dataSources.remove(dataSourceName);
}
}
/** /**
* Gets a connection from the pool. Will get an available one if * Gets a connection from the pool. Will get an available one if
* present, or create a new one if under the max limit. Will * present, or create a new one if under the max limit. Will
* block if all used and a new one would exceed the max. * block if all used and a new one would exceed the max.
*/ */
private Connection getPooledConnection() throws SQLException { private Connection getPooledConnection() throws SQLException
PooledConnection pc = null; {
synchronized(lock) { PooledConnection pc = null;
if (available == null) { synchronized (lock)
throw new SQLException("DataSource has been closed."); {
} if (available == null)
while(true) { {
if(available.size() > 0) { throw new SQLException("DataSource has been closed.");
pc = (PooledConnection)available.pop(); }
used.push(pc); while (true)
break; {
} if (available.size() > 0)
if(maxConnections == 0 || used.size() < maxConnections) { {
pc = source.getPooledConnection(); pc = (PooledConnection)available.pop();
used.push(pc); used.push(pc);
break; break;
} else { }
try { if (maxConnections == 0 || used.size() < maxConnections)
// Wake up every second at a minimum {
lock.wait(1000L); pc = source.getPooledConnection();
} catch(InterruptedException e) { used.push(pc);
} break;
} }
} else
} {
pc.addConnectionEventListener(connectionEventListener); try
return pc.getConnection(); {
} // Wake up every second at a minimum
lock.wait(1000L);
}
catch (InterruptedException e)
{}
}
}
}
pc.addConnectionEventListener(connectionEventListener);
return pc.getConnection();
}
/** /**
* Notified when a pooled connection is closed, or a fatal error occurs * Notified when a pooled connection is closed, or a fatal error occurs
* on a pooled connection. This is the only way connections are marked * on a pooled connection. This is the only way connections are marked
* as unused. * as unused.
*/ */
private ConnectionEventListener connectionEventListener = new ConnectionEventListener() { private ConnectionEventListener connectionEventListener = new ConnectionEventListener()
public void connectionClosed(ConnectionEvent event) { {
((PooledConnection)event.getSource()).removeConnectionEventListener(this); public void connectionClosed(ConnectionEvent event)
synchronized(lock) { {
if(available == null) { ((PooledConnection)event.getSource()).removeConnectionEventListener(this);
return; // DataSource has been closed synchronized (lock)
} {
boolean removed = used.remove(event.getSource()); if (available == null)
if(removed) { {
available.push(event.getSource()); return ; // DataSource has been closed
// There's now a new connection available }
lock.notify(); boolean removed = used.remove(event.getSource());
} else { if (removed)
// a connection error occured {
} available.push(event.getSource());
} // There's now a new connection available
} lock.notify();
}
else
{
// a connection error occured
}
}
}
/** /**
* This is only called for fatal errors, where the physical connection is * This is only called for fatal errors, where the physical connection is
* useless afterward and should be removed from the pool. * useless afterward and should be removed from the pool.
*/ */
public void connectionErrorOccurred(ConnectionEvent event) { public void connectionErrorOccurred(ConnectionEvent event)
((PooledConnection) event.getSource()).removeConnectionEventListener(this); {
synchronized(lock) { ((PooledConnection) event.getSource()).removeConnectionEventListener(this);
if (available == null) { synchronized (lock)
return; // DataSource has been closed {
} if (available == null)
used.remove(event.getSource()); {
// We're now at least 1 connection under the max return ; // DataSource has been closed
lock.notify(); }
} used.remove(event.getSource());
} // We're now at least 1 connection under the max
}; lock.notify();
}
}
};
/** /**
* Adds custom properties for this DataSource to the properties defined in * Adds custom properties for this DataSource to the properties defined in
* the superclass. * the superclass.
*/ */
public Reference getReference() throws NamingException { public Reference getReference() throws NamingException
Reference ref = super.getReference(); {
ref.add(new StringRefAddr("dataSourceName", dataSourceName)); Reference ref = super.getReference();
if (initialConnections > 0) { ref.add(new StringRefAddr("dataSourceName", dataSourceName));
ref.add(new StringRefAddr("initialConnections", Integer.toString(initialConnections))); if (initialConnections > 0)
} {
if (maxConnections > 0) { ref.add(new StringRefAddr("initialConnections", Integer.toString(initialConnections)));
ref.add(new StringRefAddr("maxConnections", Integer.toString(maxConnections))); }
} if (maxConnections > 0)
return ref; {
} ref.add(new StringRefAddr("maxConnections", Integer.toString(maxConnections)));
}
return ref;
}
} }

View File

@ -5,18 +5,20 @@ import java.io.Serializable;
/** /**
* Simple DataSource which does not perform connection pooling. In order to use * Simple DataSource which does not perform connection pooling. In order to use
* the DataSource, you must set the property databaseName. The settings for * the DataSource, you must set the property databaseName. The settings for
* serverName, portNumber, user, and password are optional. Note: these properties * serverName, portNumber, user, and password are optional. Note: these properties
* are declared in the superclass. * are declared in the superclass.
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public class SimpleDataSource extends BaseDataSource implements Serializable, DataSource { public class SimpleDataSource extends BaseDataSource implements Serializable, DataSource
/** {
* Gets a description of this DataSource. /**
*/ * Gets a description of this DataSource.
public String getDescription() { */
return "Non-Pooling DataSource from "+org.postgresql.Driver.getVersion(); public String getDescription()
} {
return "Non-Pooling DataSource from " + org.postgresql.Driver.getVersion();
}
} }

View File

@ -11,80 +11,84 @@ public abstract class AbstractJdbc3Blob extends org.postgresql.jdbc2.AbstractJdb
super(conn, oid); super(conn, oid);
} }
/** /**
* Writes the given array of bytes to the <code>BLOB</code> value that * Writes the given array of bytes to the <code>BLOB</code> value that
* this <code>Blob</code> object represents, starting at position * this <code>Blob</code> object represents, starting at position
* <code>pos</code>, and returns the number of bytes written. * <code>pos</code>, and returns the number of bytes written.
* *
* @param pos the position in the <code>BLOB</code> object at which * @param pos the position in the <code>BLOB</code> object at which
* to start writing * to start writing
* @param bytes the array of bytes to be written to the <code>BLOB</code> * @param bytes the array of bytes to be written to the <code>BLOB</code>
* value that this <code>Blob</code> object represents * value that this <code>Blob</code> object represents
* @return the number of bytes written * @return the number of bytes written
* @exception SQLException if there is an error accessing the * @exception SQLException if there is an error accessing the
* <code>BLOB</code> value * <code>BLOB</code> value
* @see #getBytes * @see #getBytes
* @since 1.4 * @since 1.4
*/ */
public int setBytes(long pos, byte[] bytes) throws SQLException { public int setBytes(long pos, byte[] bytes) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Writes all or part of the given <code>byte</code> array to the * Writes all or part of the given <code>byte</code> array to the
* <code>BLOB</code> value that this <code>Blob</code> object represents * <code>BLOB</code> value that this <code>Blob</code> object represents
* and returns the number of bytes written. * and returns the number of bytes written.
* Writing starts at position <code>pos</code> in the <code>BLOB</code> * Writing starts at position <code>pos</code> in the <code>BLOB</code>
* value; <code>len</code> bytes from the given byte array are written. * value; <code>len</code> bytes from the given byte array are written.
* *
* @param pos the position in the <code>BLOB</code> object at which * @param pos the position in the <code>BLOB</code> object at which
* to start writing * to start writing
* @param bytes the array of bytes to be written to this <code>BLOB</code> * @param bytes the array of bytes to be written to this <code>BLOB</code>
* object * object
* @param offset the offset into the array <code>bytes</code> at which * @param offset the offset into the array <code>bytes</code> at which
* to start reading the bytes to be set * to start reading the bytes to be set
* @param len the number of bytes to be written to the <code>BLOB</code> * @param len the number of bytes to be written to the <code>BLOB</code>
* value from the array of bytes <code>bytes</code> * value from the array of bytes <code>bytes</code>
* @return the number of bytes written * @return the number of bytes written
* @exception SQLException if there is an error accessing the * @exception SQLException if there is an error accessing the
* <code>BLOB</code> value * <code>BLOB</code> value
* @see #getBytes * @see #getBytes
* @since 1.4 * @since 1.4
*/ */
public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException { public int setBytes(long pos, byte[] bytes, int offset, int len) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves a stream that can be used to write to the <code>BLOB</code> * Retrieves a stream that can be used to write to the <code>BLOB</code>
* value that this <code>Blob</code> object represents. The stream begins * value that this <code>Blob</code> object represents. The stream begins
* at position <code>pos</code>. * at position <code>pos</code>.
* *
* @param pos the position in the <code>BLOB</code> value at which * @param pos the position in the <code>BLOB</code> value at which
* to start writing * to start writing
* @return a <code>java.io.OutputStream</code> object to which data can * @return a <code>java.io.OutputStream</code> object to which data can
* be written * be written
* @exception SQLException if there is an error accessing the * @exception SQLException if there is an error accessing the
* <code>BLOB</code> value * <code>BLOB</code> value
* @see #getBinaryStream * @see #getBinaryStream
* @since 1.4 * @since 1.4
*/ */
public java.io.OutputStream setBinaryStream(long pos) throws SQLException { public java.io.OutputStream setBinaryStream(long pos) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Truncates the <code>BLOB</code> value that this <code>Blob</code> * Truncates the <code>BLOB</code> value that this <code>Blob</code>
* object represents to be <code>len</code> bytes in length. * object represents to be <code>len</code> bytes in length.
* *
* @param len the length, in bytes, to which the <code>BLOB</code> value * @param len the length, in bytes, to which the <code>BLOB</code> value
* that this <code>Blob</code> object represents should be truncated * that this <code>Blob</code> object represents should be truncated
* @exception SQLException if there is an error accessing the * @exception SQLException if there is an error accessing the
* <code>BLOB</code> value * <code>BLOB</code> value
* @since 1.4 * @since 1.4
*/ */
public void truncate(long len) throws SQLException { public void truncate(long len) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
} }

View File

@ -11,97 +11,102 @@ public abstract class AbstractJdbc3Clob extends org.postgresql.jdbc2.AbstractJdb
super(conn, oid); super(conn, oid);
} }
/** /**
* Writes the given Java <code>String</code> to the <code>CLOB</code> * Writes the given Java <code>String</code> to the <code>CLOB</code>
* value that this <code>Clob</code> object designates at the position * value that this <code>Clob</code> object designates at the position
* <code>pos</code>. * <code>pos</code>.
* *
* @param pos the position at which to start writing to the <code>CLOB</code> * @param pos the position at which to start writing to the <code>CLOB</code>
* value that this <code>Clob</code> object represents * value that this <code>Clob</code> object represents
* @param str the string to be written to the <code>CLOB</code> * @param str the string to be written to the <code>CLOB</code>
* value that this <code>Clob</code> designates * value that this <code>Clob</code> designates
* @return the number of characters written * @return the number of characters written
* @exception SQLException if there is an error accessing the * @exception SQLException if there is an error accessing the
* <code>CLOB</code> value * <code>CLOB</code> value
* *
* @since 1.4 * @since 1.4
*/ */
public int setString(long pos, String str) throws SQLException { public int setString(long pos, String str) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Writes <code>len</code> characters of <code>str</code>, starting * Writes <code>len</code> characters of <code>str</code>, starting
* at character <code>offset</code>, to the <code>CLOB</code> value * at character <code>offset</code>, to the <code>CLOB</code> value
* that this <code>Clob</code> represents. * that this <code>Clob</code> represents.
* *
* @param pos the position at which to start writing to this * @param pos the position at which to start writing to this
* <code>CLOB</code> object * <code>CLOB</code> object
* @param str the string to be written to the <code>CLOB</code> * @param str the string to be written to the <code>CLOB</code>
* value that this <code>Clob</code> object represents * value that this <code>Clob</code> object represents
* @param offset the offset into <code>str</code> to start reading * @param offset the offset into <code>str</code> to start reading
* the characters to be written * the characters to be written
* @param len the number of characters to be written * @param len the number of characters to be written
* @return the number of characters written * @return the number of characters written
* @exception SQLException if there is an error accessing the * @exception SQLException if there is an error accessing the
* <code>CLOB</code> value * <code>CLOB</code> value
* *
* @since 1.4 * @since 1.4
*/ */
public int setString(long pos, String str, int offset, int len) throws SQLException { public int setString(long pos, String str, int offset, int len) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves a stream to be used to write Ascii characters to the * Retrieves a stream to be used to write Ascii characters to the
* <code>CLOB</code> value that this <code>Clob</code> object represents, * <code>CLOB</code> value that this <code>Clob</code> object represents,
* starting at position <code>pos</code>. * starting at position <code>pos</code>.
* *
* @param pos the position at which to start writing to this * @param pos the position at which to start writing to this
* <code>CLOB</code> object * <code>CLOB</code> object
* @return the stream to which ASCII encoded characters can be written * @return the stream to which ASCII encoded characters can be written
* @exception SQLException if there is an error accessing the * @exception SQLException if there is an error accessing the
* <code>CLOB</code> value * <code>CLOB</code> value
* @see #getAsciiStream * @see #getAsciiStream
* *
* @since 1.4 * @since 1.4
*/ */
public java.io.OutputStream setAsciiStream(long pos) throws SQLException { public java.io.OutputStream setAsciiStream(long pos) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves a stream to be used to write a stream of Unicode characters * Retrieves a stream to be used to write a stream of Unicode characters
* to the <code>CLOB</code> value that this <code>Clob</code> object * to the <code>CLOB</code> value that this <code>Clob</code> object
* represents, at position <code>pos</code>. * represents, at position <code>pos</code>.
* *
* @param pos the position at which to start writing to the * @param pos the position at which to start writing to the
* <code>CLOB</code> value * <code>CLOB</code> value
* *
* @return a stream to which Unicode encoded characters can be written * @return a stream to which Unicode encoded characters can be written
* @exception SQLException if there is an error accessing the * @exception SQLException if there is an error accessing the
* <code>CLOB</code> value * <code>CLOB</code> value
* @see #getCharacterStream * @see #getCharacterStream
* *
* @since 1.4 * @since 1.4
*/ */
public java.io.Writer setCharacterStream(long pos) throws SQLException { public java.io.Writer setCharacterStream(long pos) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Truncates the <code>CLOB</code> value that this <code>Clob</code> * Truncates the <code>CLOB</code> value that this <code>Clob</code>
* designates to have a length of <code>len</code> * designates to have a length of <code>len</code>
* characters. * characters.
* @param len the length, in bytes, to which the <code>CLOB</code> value * @param len the length, in bytes, to which the <code>CLOB</code> value
* should be truncated * should be truncated
* @exception SQLException if there is an error accessing the * @exception SQLException if there is an error accessing the
* <code>CLOB</code> value * <code>CLOB</code> value
* *
* @since 1.4 * @since 1.4
*/ */
public void truncate(long len) throws SQLException { public void truncate(long len) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
} }

View File

@ -2,7 +2,7 @@ package org.postgresql.jdbc3;
import java.sql.*; import java.sql.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/AbstractJdbc3Connection.java,v 1.1 2002/08/14 20:35:39 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/AbstractJdbc3Connection.java,v 1.2 2002/09/06 21:23:06 momjian Exp $
* This class defines methods of the jdbc3 specification. This class extends * This class defines methods of the jdbc3 specification. This class extends
* org.postgresql.jdbc2.AbstractJdbc2Connection which provides the jdbc2 * org.postgresql.jdbc2.AbstractJdbc2Connection which provides the jdbc2
* methods. The real Connection class (for jdbc3) is org.postgresql.jdbc3.Jdbc3Connection * methods. The real Connection class (for jdbc3) is org.postgresql.jdbc3.Jdbc3Connection
@ -10,359 +10,371 @@ import java.sql.*;
public abstract class AbstractJdbc3Connection extends org.postgresql.jdbc2.AbstractJdbc2Connection public abstract class AbstractJdbc3Connection extends org.postgresql.jdbc2.AbstractJdbc2Connection
{ {
/** /**
* Changes the holdability of <code>ResultSet</code> objects * Changes the holdability of <code>ResultSet</code> objects
* created using this <code>Connection</code> object to the given * created using this <code>Connection</code> object to the given
* holdability. * holdability.
* *
* @param holdability a <code>ResultSet</code> holdability constant; one of * @param holdability a <code>ResultSet</code> holdability constant; one of
* <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
* <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code> * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
* @throws SQLException if a database access occurs, the given parameter * @throws SQLException if a database access occurs, the given parameter
* is not a <code>ResultSet</code> constant indicating holdability, * is not a <code>ResultSet</code> constant indicating holdability,
* or the given holdability is not supported * or the given holdability is not supported
* @see #getHoldability * @see #getHoldability
* @see ResultSet * @see ResultSet
* @since 1.4 * @since 1.4
*/ */
public void setHoldability(int holdability) throws SQLException { public void setHoldability(int holdability) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves the current holdability of <code>ResultSet</code> objects * Retrieves the current holdability of <code>ResultSet</code> objects
* created using this <code>Connection</code> object. * created using this <code>Connection</code> object.
* *
* @return the holdability, one of * @return the holdability, one of
* <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
* <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code> * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
* @throws SQLException if a database access occurs * @throws SQLException if a database access occurs
* @see #setHoldability * @see #setHoldability
* @see ResultSet * @see ResultSet
* @since 1.4 * @since 1.4
*/ */
public int getHoldability() throws SQLException { public int getHoldability() throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/**
* Creates an unnamed savepoint in the current transaction and
* returns the new <code>Savepoint</code> object that represents it.
*
* @return the new <code>Savepoint</code> object
* @exception SQLException if a database access error occurs
* or this <code>Connection</code> object is currently in
* auto-commit mode
* @see Savepoint
* @since 1.4
*/
public Savepoint setSavepoint() throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/**
* Creates a savepoint with the given name in the current transaction
* and returns the new <code>Savepoint</code> object that represents it.
*
* @param name a <code>String</code> containing the name of the savepoint
* @return the new <code>Savepoint</code> object
* @exception SQLException if a database access error occurs
* or this <code>Connection</code> object is currently in
* auto-commit mode
* @see Savepoint
* @since 1.4
*/
public Savepoint setSavepoint(String name) throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/**
* Undoes all changes made after the given <code>Savepoint</code> object
* was set.
* <P>
* This method should be used only when auto-commit has been disabled.
*
* @param savepoint the <code>Savepoint</code> object to roll back to
* @exception SQLException if a database access error occurs,
* the <code>Savepoint</code> object is no longer valid,
* or this <code>Connection</code> object is currently in
* auto-commit mode
* @see Savepoint
* @see #rollback
* @since 1.4
*/
public void rollback(Savepoint savepoint) throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Removes the given <code>Savepoint</code> object from the current * Creates an unnamed savepoint in the current transaction and
* transaction. Any reference to the savepoint after it have been removed * returns the new <code>Savepoint</code> object that represents it.
* will cause an <code>SQLException</code> to be thrown. *
* * @return the new <code>Savepoint</code> object
* @param savepoint the <code>Savepoint</code> object to be removed * @exception SQLException if a database access error occurs
* @exception SQLException if a database access error occurs or * or this <code>Connection</code> object is currently in
* the given <code>Savepoint</code> object is not a valid * auto-commit mode
* savepoint in the current transaction * @see Savepoint
* @since 1.4 * @since 1.4
*/ */
public void releaseSavepoint(Savepoint savepoint) throws SQLException { public Savepoint setSavepoint() throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Creates a <code>Statement</code> object that will generate * Creates a savepoint with the given name in the current transaction
* <code>ResultSet</code> objects with the given type, concurrency, * and returns the new <code>Savepoint</code> object that represents it.
* and holdability. *
* This method is the same as the <code>createStatement</code> method * @param name a <code>String</code> containing the name of the savepoint
* above, but it allows the default result set * @return the new <code>Savepoint</code> object
* type, concurrency, and holdability to be overridden. * @exception SQLException if a database access error occurs
* * or this <code>Connection</code> object is currently in
* @param resultSetType one of the following <code>ResultSet</code> * auto-commit mode
* constants: * @see Savepoint
* <code>ResultSet.TYPE_FORWARD_ONLY</code>, * @since 1.4
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or */
* <code>ResultSet.TYPE_SCROLL_SENSITIVE</code> public Savepoint setSavepoint(String name) throws SQLException
* @param resultSetConcurrency one of the following <code>ResultSet</code> {
* constants: throw org.postgresql.Driver.notImplemented();
* <code>ResultSet.CONCUR_READ_ONLY</code> or }
* <code>ResultSet.CONCUR_UPDATABLE</code>
* @param resultSetHoldability one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
* <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
* @return a new <code>Statement</code> object that will generate
* <code>ResultSet</code> objects with the given type,
* concurrency, and holdability
* @exception SQLException if a database access error occurs
* or the given parameters are not <code>ResultSet</code>
* constants indicating type, concurrency, and holdability
* @see ResultSet
* @since 1.4
*/
public Statement createStatement(int resultSetType, int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Creates a <code>PreparedStatement</code> object that will generate * Undoes all changes made after the given <code>Savepoint</code> object
* <code>ResultSet</code> objects with the given type, concurrency, * was set.
* and holdability. * <P>
* <P> * This method should be used only when auto-commit has been disabled.
* This method is the same as the <code>prepareStatement</code> method *
* above, but it allows the default result set * @param savepoint the <code>Savepoint</code> object to roll back to
* type, concurrency, and holdability to be overridden. * @exception SQLException if a database access error occurs,
* * the <code>Savepoint</code> object is no longer valid,
* @param sql a <code>String</code> object that is the SQL statement to * or this <code>Connection</code> object is currently in
* be sent to the database; may contain one or more ? IN * auto-commit mode
* parameters * @see Savepoint
* @param resultSetType one of the following <code>ResultSet</code> * @see #rollback
* constants: * @since 1.4
* <code>ResultSet.TYPE_FORWARD_ONLY</code>, */
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or public void rollback(Savepoint savepoint) throws SQLException
* <code>ResultSet.TYPE_SCROLL_SENSITIVE</code> {
* @param resultSetConcurrency one of the following <code>ResultSet</code> throw org.postgresql.Driver.notImplemented();
* constants: }
* <code>ResultSet.CONCUR_READ_ONLY</code> or
* <code>ResultSet.CONCUR_UPDATABLE</code>
* @param resultSetHoldability one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
* <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
* @return a new <code>PreparedStatement</code> object, containing the
* pre-compiled SQL statement, that will generate
* <code>ResultSet</code> objects with the given type,
* concurrency, and holdability
* @exception SQLException if a database access error occurs
* or the given parameters are not <code>ResultSet</code>
* constants indicating type, concurrency, and holdability
* @see ResultSet
* @since 1.4
*/
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/**
* Creates a <code>CallableStatement</code> object that will generate
* <code>ResultSet</code> objects with the given type and concurrency.
* This method is the same as the <code>prepareCall</code> method
* above, but it allows the default result set
* type, result set concurrency type and holdability to be overridden.
*
* @param sql a <code>String</code> object that is the SQL statement to
* be sent to the database; may contain on or more ? parameters
* @param resultSetType one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.TYPE_FORWARD_ONLY</code>,
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
* <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
* @param resultSetConcurrency one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.CONCUR_READ_ONLY</code> or
* <code>ResultSet.CONCUR_UPDATABLE</code>
* @param resultSetHoldability one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
* <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
* @return a new <code>CallableStatement</code> object, containing the
* pre-compiled SQL statement, that will generate
* <code>ResultSet</code> objects with the given type,
* concurrency, and holdability
* @exception SQLException if a database access error occurs
* or the given parameters are not <code>ResultSet</code>
* constants indicating type, concurrency, and holdability
* @see ResultSet
* @since 1.4
*/
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Creates a default <code>PreparedStatement</code> object that has * Removes the given <code>Savepoint</code> object from the current
* the capability to retrieve auto-generated keys. The given constant * transaction. Any reference to the savepoint after it have been removed
* tells the driver whether it should make auto-generated keys * will cause an <code>SQLException</code> to be thrown.
* available for retrieval. This parameter is ignored if the SQL *
* statement is not an <code>INSERT</code> statement. * @param savepoint the <code>Savepoint</code> object to be removed
* <P> * @exception SQLException if a database access error occurs or
* <B>Note:</B> This method is optimized for handling * the given <code>Savepoint</code> object is not a valid
* parametric SQL statements that benefit from precompilation. If * savepoint in the current transaction
* the driver supports precompilation, * @since 1.4
* the method <code>prepareStatement</code> will send */
* the statement to the database for precompilation. Some drivers public void releaseSavepoint(Savepoint savepoint) throws SQLException
* may not support precompilation. In this case, the statement may {
* not be sent to the database until the <code>PreparedStatement</code> throw org.postgresql.Driver.notImplemented();
* object is executed. This has no direct effect on users; however, it does }
* affect which methods throw certain SQLExceptions.
* <P>
* Result sets created using the returned <code>PreparedStatement</code>
* object will by default be type <code>TYPE_FORWARD_ONLY</code>
* and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
*
* @param sql an SQL statement that may contain one or more '?' IN
* parameter placeholders
* @param autoGeneratedKeys a flag indicating whether auto-generated keys
* should be returned; one of the following <code>Statement</code>
* constants:
* @param autoGeneratedKeys a flag indicating that auto-generated keys should be returned, one of
* <code>Statement.RETURN_GENERATED_KEYS</code> or
* <code>Statement.NO_GENERATED_KEYS</code>.
* @return a new <code>PreparedStatement</code> object, containing the
* pre-compiled SQL statement, that will have the capability of
* returning auto-generated keys
* @exception SQLException if a database access error occurs
* or the given parameter is not a <code>Statement</code>
* constant indicating whether auto-generated keys should be
* returned
* @since 1.4
*/
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/**
* Creates a default <code>PreparedStatement</code> object capable
* of returning the auto-generated keys designated by the given array.
* This array contains the indexes of the columns in the target
* table that contain the auto-generated keys that should be made
* available. This array is ignored if the SQL
* statement is not an <code>INSERT</code> statement.
* <P>
* An SQL statement with or without IN parameters can be
* pre-compiled and stored in a <code>PreparedStatement</code> object. This
* object can then be used to efficiently execute this statement
* multiple times.
* <P>
* <B>Note:</B> This method is optimized for handling
* parametric SQL statements that benefit from precompilation. If
* the driver supports precompilation,
* the method <code>prepareStatement</code> will send
* the statement to the database for precompilation. Some drivers
* may not support precompilation. In this case, the statement may
* not be sent to the database until the <code>PreparedStatement</code>
* object is executed. This has no direct effect on users; however, it does
* affect which methods throw certain SQLExceptions.
* <P>
* Result sets created using the returned <code>PreparedStatement</code>
* object will by default be type <code>TYPE_FORWARD_ONLY</code>
* and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
*
* @param sql an SQL statement that may contain one or more '?' IN
* parameter placeholders
* @param columnIndexes an array of column indexes indicating the columns
* that should be returned from the inserted row or rows
* @return a new <code>PreparedStatement</code> object, containing the
* pre-compiled statement, that is capable of returning the
* auto-generated keys designated by the given array of column
* indexes
* @exception SQLException if a database access error occurs
*
* @since 1.4
*/
public PreparedStatement prepareStatement(String sql, int columnIndexes[])
throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Creates a default <code>PreparedStatement</code> object capable * Creates a <code>Statement</code> object that will generate
* of returning the auto-generated keys designated by the given array. * <code>ResultSet</code> objects with the given type, concurrency,
* This array contains the names of the columns in the target * and holdability.
* table that contain the auto-generated keys that should be returned. * This method is the same as the <code>createStatement</code> method
* This array is ignored if the SQL * above, but it allows the default result set
* statement is not an <code>INSERT</code> statement. * type, concurrency, and holdability to be overridden.
* <P> *
* An SQL statement with or without IN parameters can be * @param resultSetType one of the following <code>ResultSet</code>
* pre-compiled and stored in a <code>PreparedStatement</code> object. This * constants:
* object can then be used to efficiently execute this statement * <code>ResultSet.TYPE_FORWARD_ONLY</code>,
* multiple times. * <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
* <P> * <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
* <B>Note:</B> This method is optimized for handling * @param resultSetConcurrency one of the following <code>ResultSet</code>
* parametric SQL statements that benefit from precompilation. If * constants:
* the driver supports precompilation, * <code>ResultSet.CONCUR_READ_ONLY</code> or
* the method <code>prepareStatement</code> will send * <code>ResultSet.CONCUR_UPDATABLE</code>
* the statement to the database for precompilation. Some drivers * @param resultSetHoldability one of the following <code>ResultSet</code>
* may not support precompilation. In this case, the statement may * constants:
* not be sent to the database until the <code>PreparedStatement</code> * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
* object is executed. This has no direct effect on users; however, it does * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
* affect which methods throw certain SQLExceptions. * @return a new <code>Statement</code> object that will generate
* <P> * <code>ResultSet</code> objects with the given type,
* Result sets created using the returned <code>PreparedStatement</code> * concurrency, and holdability
* object will by default be type <code>TYPE_FORWARD_ONLY</code> * @exception SQLException if a database access error occurs
* and have a concurrency level of <code>CONCUR_READ_ONLY</code>. * or the given parameters are not <code>ResultSet</code>
* * constants indicating type, concurrency, and holdability
* @param sql an SQL statement that may contain one or more '?' IN * @see ResultSet
* parameter placeholders * @since 1.4
* @param columnNames an array of column names indicating the columns */
* that should be returned from the inserted row or rows public Statement createStatement(int resultSetType, int resultSetConcurrency,
* @return a new <code>PreparedStatement</code> object, containing the int resultSetHoldability) throws SQLException
* pre-compiled statement, that is capable of returning the {
* auto-generated keys designated by the given array of column throw org.postgresql.Driver.notImplemented();
* names }
* @exception SQLException if a database access error occurs
*
* @since 1.4 /**
*/ * Creates a <code>PreparedStatement</code> object that will generate
public PreparedStatement prepareStatement(String sql, String columnNames[]) * <code>ResultSet</code> objects with the given type, concurrency,
throws SQLException { * and holdability.
throw org.postgresql.Driver.notImplemented(); * <P>
} * This method is the same as the <code>prepareStatement</code> method
* above, but it allows the default result set
* type, concurrency, and holdability to be overridden.
*
* @param sql a <code>String</code> object that is the SQL statement to
* be sent to the database; may contain one or more ? IN
* parameters
* @param resultSetType one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.TYPE_FORWARD_ONLY</code>,
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
* <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
* @param resultSetConcurrency one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.CONCUR_READ_ONLY</code> or
* <code>ResultSet.CONCUR_UPDATABLE</code>
* @param resultSetHoldability one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
* <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
* @return a new <code>PreparedStatement</code> object, containing the
* pre-compiled SQL statement, that will generate
* <code>ResultSet</code> objects with the given type,
* concurrency, and holdability
* @exception SQLException if a database access error occurs
* or the given parameters are not <code>ResultSet</code>
* constants indicating type, concurrency, and holdability
* @see ResultSet
* @since 1.4
*/
public PreparedStatement prepareStatement(String sql, int resultSetType,
int resultSetConcurrency, int resultSetHoldability)
throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}
/**
* Creates a <code>CallableStatement</code> object that will generate
* <code>ResultSet</code> objects with the given type and concurrency.
* This method is the same as the <code>prepareCall</code> method
* above, but it allows the default result set
* type, result set concurrency type and holdability to be overridden.
*
* @param sql a <code>String</code> object that is the SQL statement to
* be sent to the database; may contain on or more ? parameters
* @param resultSetType one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.TYPE_FORWARD_ONLY</code>,
* <code>ResultSet.TYPE_SCROLL_INSENSITIVE</code>, or
* <code>ResultSet.TYPE_SCROLL_SENSITIVE</code>
* @param resultSetConcurrency one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.CONCUR_READ_ONLY</code> or
* <code>ResultSet.CONCUR_UPDATABLE</code>
* @param resultSetHoldability one of the following <code>ResultSet</code>
* constants:
* <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
* <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
* @return a new <code>CallableStatement</code> object, containing the
* pre-compiled SQL statement, that will generate
* <code>ResultSet</code> objects with the given type,
* concurrency, and holdability
* @exception SQLException if a database access error occurs
* or the given parameters are not <code>ResultSet</code>
* constants indicating type, concurrency, and holdability
* @see ResultSet
* @since 1.4
*/
public CallableStatement prepareCall(String sql, int resultSetType,
int resultSetConcurrency,
int resultSetHoldability) throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}
/**
* Creates a default <code>PreparedStatement</code> object that has
* the capability to retrieve auto-generated keys. The given constant
* tells the driver whether it should make auto-generated keys
* available for retrieval. This parameter is ignored if the SQL
* statement is not an <code>INSERT</code> statement.
* <P>
* <B>Note:</B> This method is optimized for handling
* parametric SQL statements that benefit from precompilation. If
* the driver supports precompilation,
* the method <code>prepareStatement</code> will send
* the statement to the database for precompilation. Some drivers
* may not support precompilation. In this case, the statement may
* not be sent to the database until the <code>PreparedStatement</code>
* object is executed. This has no direct effect on users; however, it does
* affect which methods throw certain SQLExceptions.
* <P>
* Result sets created using the returned <code>PreparedStatement</code>
* object will by default be type <code>TYPE_FORWARD_ONLY</code>
* and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
*
* @param sql an SQL statement that may contain one or more '?' IN
* parameter placeholders
* @param autoGeneratedKeys a flag indicating whether auto-generated keys
* should be returned; one of the following <code>Statement</code>
* constants:
* @param autoGeneratedKeys a flag indicating that auto-generated keys should be returned, one of
* <code>Statement.RETURN_GENERATED_KEYS</code> or
* <code>Statement.NO_GENERATED_KEYS</code>.
* @return a new <code>PreparedStatement</code> object, containing the
* pre-compiled SQL statement, that will have the capability of
* returning auto-generated keys
* @exception SQLException if a database access error occurs
* or the given parameter is not a <code>Statement</code>
* constant indicating whether auto-generated keys should be
* returned
* @since 1.4
*/
public PreparedStatement prepareStatement(String sql, int autoGeneratedKeys)
throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}
/**
* Creates a default <code>PreparedStatement</code> object capable
* of returning the auto-generated keys designated by the given array.
* This array contains the indexes of the columns in the target
* table that contain the auto-generated keys that should be made
* available. This array is ignored if the SQL
* statement is not an <code>INSERT</code> statement.
* <P>
* An SQL statement with or without IN parameters can be
* pre-compiled and stored in a <code>PreparedStatement</code> object. This
* object can then be used to efficiently execute this statement
* multiple times.
* <P>
* <B>Note:</B> This method is optimized for handling
* parametric SQL statements that benefit from precompilation. If
* the driver supports precompilation,
* the method <code>prepareStatement</code> will send
* the statement to the database for precompilation. Some drivers
* may not support precompilation. In this case, the statement may
* not be sent to the database until the <code>PreparedStatement</code>
* object is executed. This has no direct effect on users; however, it does
* affect which methods throw certain SQLExceptions.
* <P>
* Result sets created using the returned <code>PreparedStatement</code>
* object will by default be type <code>TYPE_FORWARD_ONLY</code>
* and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
*
* @param sql an SQL statement that may contain one or more '?' IN
* parameter placeholders
* @param columnIndexes an array of column indexes indicating the columns
* that should be returned from the inserted row or rows
* @return a new <code>PreparedStatement</code> object, containing the
* pre-compiled statement, that is capable of returning the
* auto-generated keys designated by the given array of column
* indexes
* @exception SQLException if a database access error occurs
*
* @since 1.4
*/
public PreparedStatement prepareStatement(String sql, int columnIndexes[])
throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}
/**
* Creates a default <code>PreparedStatement</code> object capable
* of returning the auto-generated keys designated by the given array.
* This array contains the names of the columns in the target
* table that contain the auto-generated keys that should be returned.
* This array is ignored if the SQL
* statement is not an <code>INSERT</code> statement.
* <P>
* An SQL statement with or without IN parameters can be
* pre-compiled and stored in a <code>PreparedStatement</code> object. This
* object can then be used to efficiently execute this statement
* multiple times.
* <P>
* <B>Note:</B> This method is optimized for handling
* parametric SQL statements that benefit from precompilation. If
* the driver supports precompilation,
* the method <code>prepareStatement</code> will send
* the statement to the database for precompilation. Some drivers
* may not support precompilation. In this case, the statement may
* not be sent to the database until the <code>PreparedStatement</code>
* object is executed. This has no direct effect on users; however, it does
* affect which methods throw certain SQLExceptions.
* <P>
* Result sets created using the returned <code>PreparedStatement</code>
* object will by default be type <code>TYPE_FORWARD_ONLY</code>
* and have a concurrency level of <code>CONCUR_READ_ONLY</code>.
*
* @param sql an SQL statement that may contain one or more '?' IN
* parameter placeholders
* @param columnNames an array of column names indicating the columns
* that should be returned from the inserted row or rows
* @return a new <code>PreparedStatement</code> object, containing the
* pre-compiled statement, that is capable of returning the
* auto-generated keys designated by the given array of column
* names
* @exception SQLException if a database access error occurs
*
* @since 1.4
*/
public PreparedStatement prepareStatement(String sql, String columnNames[])
throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}
} }

View File

@ -8,332 +8,348 @@ public abstract class AbstractJdbc3DatabaseMetaData extends org.postgresql.jdbc2
public AbstractJdbc3DatabaseMetaData(AbstractJdbc3Connection conn) public AbstractJdbc3DatabaseMetaData(AbstractJdbc3Connection conn)
{ {
super(conn); super(conn);
} }
/** /**
* Retrieves whether this database supports savepoints. * Retrieves whether this database supports savepoints.
* *
* @return <code>true</code> if savepoints are supported; * @return <code>true</code> if savepoints are supported;
* <code>false</code> otherwise * <code>false</code> otherwise
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public boolean supportsSavepoints() throws SQLException { public boolean supportsSavepoints() throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves whether this database supports named parameters to callable * Retrieves whether this database supports named parameters to callable
* statements. * statements.
* *
* @return <code>true</code> if named parameters are supported; * @return <code>true</code> if named parameters are supported;
* <code>false</code> otherwise * <code>false</code> otherwise
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public boolean supportsNamedParameters() throws SQLException { public boolean supportsNamedParameters() throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves whether it is possible to have multiple <code>ResultSet</code> objects * Retrieves whether it is possible to have multiple <code>ResultSet</code> objects
* returned from a <code>CallableStatement</code> object * returned from a <code>CallableStatement</code> object
* simultaneously. * simultaneously.
* *
* @return <code>true</code> if a <code>CallableStatement</code> object * @return <code>true</code> if a <code>CallableStatement</code> object
* can return multiple <code>ResultSet</code> objects * can return multiple <code>ResultSet</code> objects
* simultaneously; <code>false</code> otherwise * simultaneously; <code>false</code> otherwise
* @exception SQLException if a datanase access error occurs * @exception SQLException if a datanase access error occurs
* @since 1.4 * @since 1.4
*/ */
public boolean supportsMultipleOpenResults() throws SQLException { public boolean supportsMultipleOpenResults() throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves whether auto-generated keys can be retrieved after * Retrieves whether auto-generated keys can be retrieved after
* a statement has been executed. * a statement has been executed.
* *
* @return <code>true</code> if auto-generated keys can be retrieved * @return <code>true</code> if auto-generated keys can be retrieved
* after a statement has executed; <code>false</code> otherwise * after a statement has executed; <code>false</code> otherwise
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public boolean supportsGetGeneratedKeys() throws SQLException { public boolean supportsGetGeneratedKeys() throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves a description of the user-defined type (UDT) hierarchies defined in a * Retrieves a description of the user-defined type (UDT) hierarchies defined in a
* particular schema in this database. Only the immediate super type/ * particular schema in this database. Only the immediate super type/
* sub type relationship is modeled. * sub type relationship is modeled.
* <P> * <P>
* Only supertype information for UDTs matching the catalog, * Only supertype information for UDTs matching the catalog,
* schema, and type name is returned. The type name parameter * schema, and type name is returned. The type name parameter
* may be a fully-qualified name. When the UDT name supplied is a * may be a fully-qualified name. When the UDT name supplied is a
* fully-qualified name, the catalog and schemaPattern parameters are * fully-qualified name, the catalog and schemaPattern parameters are
* ignored. * ignored.
* <P> * <P>
* If a UDT does not have a direct super type, it is not listed here. * If a UDT does not have a direct super type, it is not listed here.
* A row of the <code>ResultSet</code> object returned by this method * A row of the <code>ResultSet</code> object returned by this method
* describes the designated UDT and a direct supertype. A row has the following * describes the designated UDT and a direct supertype. A row has the following
* columns: * columns:
* <OL> * <OL>
* <LI><B>TYPE_CAT</B> String => the UDT's catalog (may be <code>null</code>) * <LI><B>TYPE_CAT</B> String => the UDT's catalog (may be <code>null</code>)
* <LI><B>TYPE_SCHEM</B> String => UDT's schema (may be <code>null</code>) * <LI><B>TYPE_SCHEM</B> String => UDT's schema (may be <code>null</code>)
* <LI><B>TYPE_NAME</B> String => type name of the UDT * <LI><B>TYPE_NAME</B> String => type name of the UDT
* <LI><B>SUPERTYPE_CAT</B> String => the direct super type's catalog * <LI><B>SUPERTYPE_CAT</B> String => the direct super type's catalog
* (may be <code>null</code>) * (may be <code>null</code>)
* <LI><B>SUPERTYPE_SCHEM</B> String => the direct super type's schema * <LI><B>SUPERTYPE_SCHEM</B> String => the direct super type's schema
* (may be <code>null</code>) * (may be <code>null</code>)
* <LI><B>SUPERTYPE_NAME</B> String => the direct super type's name * <LI><B>SUPERTYPE_NAME</B> String => the direct super type's name
* </OL> * </OL>
* *
* <P><B>Note:</B> If the driver does not support type hierarchies, an * <P><B>Note:</B> If the driver does not support type hierarchies, an
* empty result set is returned. * empty result set is returned.
* *
* @param catalog a catalog name; "" retrieves those without a catalog; * @param catalog a catalog name; "" retrieves those without a catalog;
* <code>null</code> means drop catalog name from the selection criteria * <code>null</code> means drop catalog name from the selection criteria
* @param schemaPattern a schema name pattern; "" retrieves those * @param schemaPattern a schema name pattern; "" retrieves those
* without a schema * without a schema
* @param typeNamePattern a UDT name pattern; may be a fully-qualified * @param typeNamePattern a UDT name pattern; may be a fully-qualified
* name * name
* @return a <code>ResultSet</code> object in which a row gives information * @return a <code>ResultSet</code> object in which a row gives information
* about the designated UDT * about the designated UDT
* @throws SQLException if a database access error occurs * @throws SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public ResultSet getSuperTypes(String catalog, String schemaPattern, public ResultSet getSuperTypes(String catalog, String schemaPattern,
String typeNamePattern) throws SQLException { String typeNamePattern) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/**
* Retrieves a description of the table hierarchies defined in a particular
* schema in this database.
*
* <P>Only supertable information for tables matching the catalog, schema
* and table name are returned. The table name parameter may be a fully-
* qualified name, in which case, the catalog and schemaPattern parameters
* are ignored. If a table does not have a super table, it is not listed here.
* Supertables have to be defined in the same catalog and schema as the
* sub tables. Therefore, the type description does not need to include
* this information for the supertable.
*
* <P>Each type description has the following columns:
* <OL>
* <LI><B>TABLE_CAT</B> String => the type's catalog (may be <code>null</code>)
* <LI><B>TABLE_SCHEM</B> String => type's schema (may be <code>null</code>)
* <LI><B>TABLE_NAME</B> String => type name
* <LI><B>SUPERTABLE_NAME</B> String => the direct super type's name
* </OL>
*
* <P><B>Note:</B> If the driver does not support type hierarchies, an
* empty result set is returned.
*
* @param catalog a catalog name; "" retrieves those without a catalog;
* <code>null</code> means drop catalog name from the selection criteria
* @param schemaPattern a schema name pattern; "" retrieves those
* without a schema
* @param tableNamePattern a table name pattern; may be a fully-qualified
* name
* @return a <code>ResultSet</code> object in which each row is a type description
* @throws SQLException if a database access error occurs
* @since 1.4
*/
public ResultSet getSuperTables(String catalog, String schemaPattern,
String tableNamePattern) throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves a description of the given attribute of the given type * Retrieves a description of the table hierarchies defined in a particular
* for a user-defined type (UDT) that is available in the given schema * schema in this database.
* and catalog. *
* <P> * <P>Only supertable information for tables matching the catalog, schema
* Descriptions are returned only for attributes of UDTs matching the * and table name are returned. The table name parameter may be a fully-
* catalog, schema, type, and attribute name criteria. They are ordered by * qualified name, in which case, the catalog and schemaPattern parameters
* TYPE_SCHEM, TYPE_NAME and ORDINAL_POSITION. This description * are ignored. If a table does not have a super table, it is not listed here.
* does not contain inherited attributes. * Supertables have to be defined in the same catalog and schema as the
* <P> * sub tables. Therefore, the type description does not need to include
* The <code>ResultSet</code> object that is returned has the following * this information for the supertable.
* columns: *
* <OL> * <P>Each type description has the following columns:
* <LI><B>TYPE_CAT</B> String => type catalog (may be <code>null</code>) * <OL>
* <LI><B>TYPE_SCHEM</B> String => type schema (may be <code>null</code>) * <LI><B>TABLE_CAT</B> String => the type's catalog (may be <code>null</code>)
* <LI><B>TYPE_NAME</B> String => type name * <LI><B>TABLE_SCHEM</B> String => type's schema (may be <code>null</code>)
* <LI><B>ATTR_NAME</B> String => attribute name * <LI><B>TABLE_NAME</B> String => type name
* <LI><B>DATA_TYPE</B> short => attribute type SQL type from java.sql.Types * <LI><B>SUPERTABLE_NAME</B> String => the direct super type's name
* <LI><B>ATTR_TYPE_NAME</B> String => Data source dependent type name. * </OL>
* For a UDT, the type name is fully qualified. For a REF, the type name is *
* fully qualified and represents the target type of the reference type. * <P><B>Note:</B> If the driver does not support type hierarchies, an
* <LI><B>ATTR_SIZE</B> int => column size. For char or date * empty result set is returned.
* types this is the maximum number of characters; for numeric or *
* decimal types this is precision. * @param catalog a catalog name; "" retrieves those without a catalog;
* <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits * <code>null</code> means drop catalog name from the selection criteria
* <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2) * @param schemaPattern a schema name pattern; "" retrieves those
* <LI><B>NULLABLE</B> int => whether NULL is allowed * without a schema
* <UL> * @param tableNamePattern a table name pattern; may be a fully-qualified
* <LI> attributeNoNulls - might not allow NULL values * name
* <LI> attributeNullable - definitely allows NULL values * @return a <code>ResultSet</code> object in which each row is a type description
* <LI> attributeNullableUnknown - nullability unknown * @throws SQLException if a database access error occurs
* </UL> * @since 1.4
* <LI><B>REMARKS</B> String => comment describing column (may be <code>null</code>) */
* <LI><B>ATTR_DEF</B> String => default value (may be <code>null</code>) public ResultSet getSuperTables(String catalog, String schemaPattern,
* <LI><B>SQL_DATA_TYPE</B> int => unused String tableNamePattern) throws SQLException
* <LI><B>SQL_DATETIME_SUB</B> int => unused {
* <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the throw org.postgresql.Driver.notImplemented();
* maximum number of bytes in the column }
* <LI><B>ORDINAL_POSITION</B> int => index of column in table
* (starting at 1)
* <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
* does not allow NULL values; "YES" means the column might
* allow NULL values. An empty string means unknown.
* <LI><B>SCOPE_CATALOG</B> String => catalog of table that is the
* scope of a reference attribute (<code>null</code> if DATA_TYPE isn't REF)
* <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the
* scope of a reference attribute (<code>null</code> if DATA_TYPE isn't REF)
* <LI><B>SCOPE_TABLE</B> String => table name that is the scope of a
* reference attribute (<code>null</code> if the DATA_TYPE isn't REF)
* <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct type or user-generated
* Ref type,SQL type from java.sql.Types (<code>null</code> if DATA_TYPE
* isn't DISTINCT or user-generated REF)
* </OL>
* @param catalog a catalog name; must match the catalog name as it
* is stored in the database; "" retrieves those without a catalog;
* <code>null</code> means that the catalog name should not be used to narrow
* the search
* @param schemaPattern a schema name pattern; must match the schema name
* as it is stored in the database; "" retrieves those without a schema;
* <code>null</code> means that the schema name should not be used to narrow
* the search
* @param typeNamePattern a type name pattern; must match the
* type name as it is stored in the database
* @param attributeNamePattern an attribute name pattern; must match the attribute
* name as it is declared in the database
* @return a <code>ResultSet</code> object in which each row is an
* attribute description
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public ResultSet getAttributes(String catalog, String schemaPattern,
String typeNamePattern, String attributeNamePattern)
throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves whether this database supports the given result set holdability. * Retrieves a description of the given attribute of the given type
* * for a user-defined type (UDT) that is available in the given schema
* @param holdability one of the following constants: * and catalog.
* <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or * <P>
* <code>ResultSet.CLOSE_CURSORS_AT_COMMIT<code> * Descriptions are returned only for attributes of UDTs matching the
* @return <code>true</code> if so; <code>false</code> otherwise * catalog, schema, type, and attribute name criteria. They are ordered by
* @exception SQLException if a database access error occurs * TYPE_SCHEM, TYPE_NAME and ORDINAL_POSITION. This description
* @see Connection * does not contain inherited attributes.
* @since 1.4 * <P>
*/ * The <code>ResultSet</code> object that is returned has the following
public boolean supportsResultSetHoldability(int holdability) throws SQLException { * columns:
throw org.postgresql.Driver.notImplemented(); * <OL>
} * <LI><B>TYPE_CAT</B> String => type catalog (may be <code>null</code>)
* <LI><B>TYPE_SCHEM</B> String => type schema (may be <code>null</code>)
* <LI><B>TYPE_NAME</B> String => type name
* <LI><B>ATTR_NAME</B> String => attribute name
* <LI><B>DATA_TYPE</B> short => attribute type SQL type from java.sql.Types
* <LI><B>ATTR_TYPE_NAME</B> String => Data source dependent type name.
* For a UDT, the type name is fully qualified. For a REF, the type name is
* fully qualified and represents the target type of the reference type.
* <LI><B>ATTR_SIZE</B> int => column size. For char or date
* types this is the maximum number of characters; for numeric or
* decimal types this is precision.
* <LI><B>DECIMAL_DIGITS</B> int => the number of fractional digits
* <LI><B>NUM_PREC_RADIX</B> int => Radix (typically either 10 or 2)
* <LI><B>NULLABLE</B> int => whether NULL is allowed
* <UL>
* <LI> attributeNoNulls - might not allow NULL values
* <LI> attributeNullable - definitely allows NULL values
* <LI> attributeNullableUnknown - nullability unknown
* </UL>
* <LI><B>REMARKS</B> String => comment describing column (may be <code>null</code>)
* <LI><B>ATTR_DEF</B> String => default value (may be <code>null</code>)
* <LI><B>SQL_DATA_TYPE</B> int => unused
* <LI><B>SQL_DATETIME_SUB</B> int => unused
* <LI><B>CHAR_OCTET_LENGTH</B> int => for char types the
* maximum number of bytes in the column
* <LI><B>ORDINAL_POSITION</B> int => index of column in table
* (starting at 1)
* <LI><B>IS_NULLABLE</B> String => "NO" means column definitely
* does not allow NULL values; "YES" means the column might
* allow NULL values. An empty string means unknown.
* <LI><B>SCOPE_CATALOG</B> String => catalog of table that is the
* scope of a reference attribute (<code>null</code> if DATA_TYPE isn't REF)
* <LI><B>SCOPE_SCHEMA</B> String => schema of table that is the
* scope of a reference attribute (<code>null</code> if DATA_TYPE isn't REF)
* <LI><B>SCOPE_TABLE</B> String => table name that is the scope of a
* reference attribute (<code>null</code> if the DATA_TYPE isn't REF)
* <LI><B>SOURCE_DATA_TYPE</B> short => source type of a distinct type or user-generated
* Ref type,SQL type from java.sql.Types (<code>null</code> if DATA_TYPE
* isn't DISTINCT or user-generated REF)
* </OL>
* @param catalog a catalog name; must match the catalog name as it
* is stored in the database; "" retrieves those without a catalog;
* <code>null</code> means that the catalog name should not be used to narrow
* the search
* @param schemaPattern a schema name pattern; must match the schema name
* as it is stored in the database; "" retrieves those without a schema;
* <code>null</code> means that the schema name should not be used to narrow
* the search
* @param typeNamePattern a type name pattern; must match the
* type name as it is stored in the database
* @param attributeNamePattern an attribute name pattern; must match the attribute
* name as it is declared in the database
* @return a <code>ResultSet</code> object in which each row is an
* attribute description
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public ResultSet getAttributes(String catalog, String schemaPattern,
String typeNamePattern, String attributeNamePattern)
throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves the default holdability of this <code>ResultSet</code> * Retrieves whether this database supports the given result set holdability.
* object. *
* * @param holdability one of the following constants:
* @return the default holdability; either * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
* <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT<code>
* <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code> * @return <code>true</code> if so; <code>false</code> otherwise
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @see Connection
*/ * @since 1.4
public int getResultSetHoldability() throws SQLException { */
throw org.postgresql.Driver.notImplemented(); public boolean supportsResultSetHoldability(int holdability) throws SQLException
} {
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves the major version number of the underlying database. * Retrieves the default holdability of this <code>ResultSet</code>
* * object.
* @return the underlying database's major version *
* @exception SQLException if a database access error occurs * @return the default holdability; either
* @since 1.4 * <code>ResultSet.HOLD_CURSORS_OVER_COMMIT</code> or
*/ * <code>ResultSet.CLOSE_CURSORS_AT_COMMIT</code>
public int getDatabaseMajorVersion() throws SQLException { * @exception SQLException if a database access error occurs
throw org.postgresql.Driver.notImplemented(); * @since 1.4
} */
public int getResultSetHoldability() throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves the minor version number of the underlying database. * Retrieves the major version number of the underlying database.
* *
* @return underlying database's minor version * @return the underlying database's major version
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public int getDatabaseMinorVersion() throws SQLException { public int getDatabaseMajorVersion() throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves the major JDBC version number for this * Retrieves the minor version number of the underlying database.
* driver. *
* * @return underlying database's minor version
* @return JDBC version major number * @exception SQLException if a database access error occurs
* @exception SQLException if a database access error occurs * @since 1.4
* @since 1.4 */
*/ public int getDatabaseMinorVersion() throws SQLException
public int getJDBCMajorVersion() throws SQLException { {
throw org.postgresql.Driver.notImplemented(); throw org.postgresql.Driver.notImplemented();
} }
/** /**
* Retrieves the minor JDBC version number for this * Retrieves the major JDBC version number for this
* driver. * driver.
* *
* @return JDBC version minor number * @return JDBC version major number
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public int getJDBCMinorVersion() throws SQLException { public int getJDBCMajorVersion() throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Indicates whether the SQLSTATEs returned by <code>SQLException.getSQLState</code> * Retrieves the minor JDBC version number for this
* is X/Open (now known as Open Group) SQL CLI or SQL99. * driver.
* @return the type of SQLSTATEs, one of: *
* sqlStateXOpen or * @return JDBC version minor number
* sqlStateSQL99 * @exception SQLException if a database access error occurs
* @throws SQLException if a database access error occurs * @since 1.4
* @since 1.4 */
*/ public int getJDBCMinorVersion() throws SQLException
public int getSQLStateType() throws SQLException { {
throw org.postgresql.Driver.notImplemented(); throw org.postgresql.Driver.notImplemented();
} }
/** /**
* Indicates whether updates made to a LOB are made on a copy or directly * Indicates whether the SQLSTATEs returned by <code>SQLException.getSQLState</code>
* to the LOB. * is X/Open (now known as Open Group) SQL CLI or SQL99.
* @return <code>true</code> if updates are made to a copy of the LOB; * @return the type of SQLSTATEs, one of:
* <code>false</code> if updates are made directly to the LOB * sqlStateXOpen or
* @throws SQLException if a database access error occurs * sqlStateSQL99
* @since 1.4 * @throws SQLException if a database access error occurs
*/ * @since 1.4
public boolean locatorsUpdateCopy() throws SQLException { */
throw org.postgresql.Driver.notImplemented(); public int getSQLStateType() throws SQLException
} {
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves weather this database supports statement pooling. * Indicates whether updates made to a LOB are made on a copy or directly
* * to the LOB.
* @return <code>true</code> is so; * @return <code>true</code> if updates are made to a copy of the LOB;
<code>false</code> otherwise * <code>false</code> if updates are made directly to the LOB
* @throws SQLExcpetion if a database access error occurs * @throws SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public boolean supportsStatementPooling() throws SQLException { public boolean locatorsUpdateCopy() throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/**
* Retrieves weather this database supports statement pooling.
*
* @return <code>true</code> is so;
<code>false</code> otherwise
* @throws SQLExcpetion if a database access error occurs
* @since 1.4
*/
public boolean supportsStatementPooling() throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}
} }

View File

@ -4,178 +4,190 @@ package org.postgresql.jdbc3;
import java.sql.*; import java.sql.*;
import java.util.Vector; import java.util.Vector;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/AbstractJdbc3ResultSet.java,v 1.1 2002/08/14 20:35:39 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/AbstractJdbc3ResultSet.java,v 1.2 2002/09/06 21:23:06 momjian Exp $
* This class defines methods of the jdbc3 specification. This class extends * This class defines methods of the jdbc3 specification. This class extends
* org.postgresql.jdbc2.AbstractJdbc2ResultSet which provides the jdbc2 * org.postgresql.jdbc2.AbstractJdbc2ResultSet which provides the jdbc2
* methods. The real Statement class (for jdbc3) is org.postgresql.jdbc3.Jdbc3ResultSet * methods. The real Statement class (for jdbc3) is org.postgresql.jdbc3.Jdbc3ResultSet
*/ */
public abstract class AbstractJdbc3ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet { public abstract class AbstractJdbc3ResultSet extends org.postgresql.jdbc2.AbstractJdbc2ResultSet
{
public AbstractJdbc3ResultSet(org.postgresql.PGConnection conn, Statement statement, org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) { public AbstractJdbc3ResultSet(org.postgresql.PGConnection conn, Statement statement, org.postgresql.Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
super (conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); {
} super (conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
}
/** /**
* Retrieves the value of the designated column in the current row * Retrieves the value of the designated column in the current row
* of this <code>ResultSet</code> object as a <code>java.net.URL</code> * of this <code>ResultSet</code> object as a <code>java.net.URL</code>
* object in the Java programming language. * object in the Java programming language.
* *
* @param columnIndex the index of the column 1 is the first, 2 is the second,... * @param columnIndex the index of the column 1 is the first, 2 is the second,...
* @return the column value as a <code>java.net.URL</code> object; * @return the column value as a <code>java.net.URL</code> object;
* if the value is SQL <code>NULL</code>, * if the value is SQL <code>NULL</code>,
* the value returned is <code>null</code> in the Java programming language * the value returned is <code>null</code> in the Java programming language
* @exception SQLException if a database access error occurs, * @exception SQLException if a database access error occurs,
* or if a URL is malformed * or if a URL is malformed
* @since 1.4 * @since 1.4
*/ */
public java.net.URL getURL(int columnIndex) throws SQLException { public java.net.URL getURL(int columnIndex) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Retrieves the value of the designated column in the current row * Retrieves the value of the designated column in the current row
* of this <code>ResultSet</code> object as a <code>java.net.URL</code> * of this <code>ResultSet</code> object as a <code>java.net.URL</code>
* object in the Java programming language. * object in the Java programming language.
* *
* @param columnName the SQL name of the column * @param columnName the SQL name of the column
* @return the column value as a <code>java.net.URL</code> object; * @return the column value as a <code>java.net.URL</code> object;
* if the value is SQL <code>NULL</code>, * if the value is SQL <code>NULL</code>,
* the value returned is <code>null</code> in the Java programming language * the value returned is <code>null</code> in the Java programming language
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* or if a URL is malformed * or if a URL is malformed
* @since 1.4 * @since 1.4
*/ */
public java.net.URL getURL(String columnName) throws SQLException { public java.net.URL getURL(String columnName) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Updates the designated column with a <code>java.sql.Ref</code> value. * Updates the designated column with a <code>java.sql.Ref</code> value.
* The updater methods are used to update column values in the * The updater methods are used to update column values in the
* current row or the insert row. The updater methods do not * current row or the insert row. The updater methods do not
* update the underlying database; instead the <code>updateRow</code> or * update the underlying database; instead the <code>updateRow</code> or
* <code>insertRow</code> methods are called to update the database. * <code>insertRow</code> methods are called to update the database.
* *
* @param columnIndex the first column is 1, the second is 2, ... * @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value * @param x the new column value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public void updateRef(int columnIndex, java.sql.Ref x) throws SQLException { public void updateRef(int columnIndex, java.sql.Ref x) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/**
* Updates the designated column with a <code>java.sql.Ref</code> value.
* The updater methods are used to update column values in the
* current row or the insert row. The updater methods do not
* update the underlying database; instead the <code>updateRow</code> or
* <code>insertRow</code> methods are called to update the database.
*
* @param columnName the name of the column
* @param x the new column value
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public void updateRef(String columnName, java.sql.Ref x) throws SQLException {
throw org.postgresql.Driver.notImplemented();
}
/** /**
* Updates the designated column with a <code>java.sql.Blob</code> value. * Updates the designated column with a <code>java.sql.Ref</code> value.
* The updater methods are used to update column values in the * The updater methods are used to update column values in the
* current row or the insert row. The updater methods do not * current row or the insert row. The updater methods do not
* update the underlying database; instead the <code>updateRow</code> or * update the underlying database; instead the <code>updateRow</code> or
* <code>insertRow</code> methods are called to update the database. * <code>insertRow</code> methods are called to update the database.
* *
* @param columnIndex the first column is 1, the second is 2, ... * @param columnName the name of the column
* @param x the new column value * @param x the new column value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public void updateBlob(int columnIndex, java.sql.Blob x) throws SQLException { public void updateRef(String columnName, java.sql.Ref x) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Updates the designated column with a <code>java.sql.Blob</code> value. * Updates the designated column with a <code>java.sql.Blob</code> value.
* The updater methods are used to update column values in the * The updater methods are used to update column values in the
* current row or the insert row. The updater methods do not * current row or the insert row. The updater methods do not
* update the underlying database; instead the <code>updateRow</code> or * update the underlying database; instead the <code>updateRow</code> or
* <code>insertRow</code> methods are called to update the database. * <code>insertRow</code> methods are called to update the database.
* *
* @param columnName the name of the column * @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value * @param x the new column value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public void updateBlob(String columnName, java.sql.Blob x) throws SQLException { public void updateBlob(int columnIndex, java.sql.Blob x) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Updates the designated column with a <code>java.sql.Clob</code> value. * Updates the designated column with a <code>java.sql.Blob</code> value.
* The updater methods are used to update column values in the * The updater methods are used to update column values in the
* current row or the insert row. The updater methods do not * current row or the insert row. The updater methods do not
* update the underlying database; instead the <code>updateRow</code> or * update the underlying database; instead the <code>updateRow</code> or
* <code>insertRow</code> methods are called to update the database. * <code>insertRow</code> methods are called to update the database.
* *
* @param columnIndex the first column is 1, the second is 2, ... * @param columnName the name of the column
* @param x the new column value * @param x the new column value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public void updateClob(int columnIndex, java.sql.Clob x) throws SQLException { public void updateBlob(String columnName, java.sql.Blob x) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Updates the designated column with a <code>java.sql.Clob</code> value. * Updates the designated column with a <code>java.sql.Clob</code> value.
* The updater methods are used to update column values in the * The updater methods are used to update column values in the
* current row or the insert row. The updater methods do not * current row or the insert row. The updater methods do not
* update the underlying database; instead the <code>updateRow</code> or * update the underlying database; instead the <code>updateRow</code> or
* <code>insertRow</code> methods are called to update the database. * <code>insertRow</code> methods are called to update the database.
* *
* @param columnName the name of the column * @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value * @param x the new column value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public void updateClob(String columnName, java.sql.Clob x) throws SQLException { public void updateClob(int columnIndex, java.sql.Clob x) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Updates the designated column with a <code>java.sql.Array</code> value. * Updates the designated column with a <code>java.sql.Clob</code> value.
* The updater methods are used to update column values in the * The updater methods are used to update column values in the
* current row or the insert row. The updater methods do not * current row or the insert row. The updater methods do not
* update the underlying database; instead the <code>updateRow</code> or * update the underlying database; instead the <code>updateRow</code> or
* <code>insertRow</code> methods are called to update the database. * <code>insertRow</code> methods are called to update the database.
* *
* @param columnIndex the first column is 1, the second is 2, ... * @param columnName the name of the column
* @param x the new column value * @param x the new column value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public void updateArray(int columnIndex, java.sql.Array x) throws SQLException { public void updateClob(String columnName, java.sql.Clob x) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/** /**
* Updates the designated column with a <code>java.sql.Array</code> value. * Updates the designated column with a <code>java.sql.Array</code> value.
* The updater methods are used to update column values in the * The updater methods are used to update column values in the
* current row or the insert row. The updater methods do not * current row or the insert row. The updater methods do not
* update the underlying database; instead the <code>updateRow</code> or * update the underlying database; instead the <code>updateRow</code> or
* <code>insertRow</code> methods are called to update the database. * <code>insertRow</code> methods are called to update the database.
* *
* @param columnName the name of the column * @param columnIndex the first column is 1, the second is 2, ...
* @param x the new column value * @param x the new column value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @since 1.4 * @since 1.4
*/ */
public void updateArray(String columnName, java.sql.Array x) throws SQLException { public void updateArray(int columnIndex, java.sql.Array x) throws SQLException
throw org.postgresql.Driver.notImplemented(); {
} throw org.postgresql.Driver.notImplemented();
}
/**
* Updates the designated column with a <code>java.sql.Array</code> value.
* The updater methods are used to update column values in the
* current row or the insert row. The updater methods do not
* update the underlying database; instead the <code>updateRow</code> or
* <code>insertRow</code> methods are called to update the database.
*
* @param columnName the name of the column
* @param x the new column value
* @exception SQLException if a database access error occurs
* @since 1.4
*/
public void updateArray(String columnName, java.sql.Array x) throws SQLException
{
throw org.postgresql.Driver.notImplemented();
}
} }

View File

@ -5,11 +5,11 @@ import java.sql.*;
public class Jdbc3CallableStatement extends org.postgresql.jdbc3.AbstractJdbc3Statement implements java.sql.CallableStatement public class Jdbc3CallableStatement extends org.postgresql.jdbc3.AbstractJdbc3Statement implements java.sql.CallableStatement
{ {
public Jdbc3CallableStatement(Jdbc3Connection connection, String sql) throws SQLException public Jdbc3CallableStatement(Jdbc3Connection connection, String sql) throws SQLException
{ {
super(connection, sql); super(connection, sql);
} }
} }

View File

@ -6,56 +6,56 @@ import java.util.Vector;
import java.util.Hashtable; import java.util.Hashtable;
import org.postgresql.Field; import org.postgresql.Field;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3Connection.java,v 1.1 2002/08/14 20:35:40 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3Connection.java,v 1.2 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.Connection interface for JDBC3. * This class implements the java.sql.Connection interface for JDBC3.
* However most of the implementation is really done in * However most of the implementation is really done in
* org.postgresql.jdbc3.AbstractJdbc3Connection or one of it's parents * org.postgresql.jdbc3.AbstractJdbc3Connection or one of it's parents
*/ */
public class Jdbc3Connection extends org.postgresql.jdbc3.AbstractJdbc3Connection implements java.sql.Connection public class Jdbc3Connection extends org.postgresql.jdbc3.AbstractJdbc3Connection implements java.sql.Connection
{ {
public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc3Statement s = new Jdbc3Statement(this);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.Statement createStatement(int resultSetType, int resultSetConcurrency) throws SQLException
public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException {
{ Jdbc3Statement s = new Jdbc3Statement(this);
Jdbc3PreparedStatement s = new Jdbc3PreparedStatement(this, sql);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc3CallableStatement s = new Jdbc3CallableStatement(this,sql);
s.setResultSetType(resultSetType); s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency); s.setResultSetConcurrency(resultSetConcurrency);
return s; return s;
} }
public java.sql.DatabaseMetaData getMetaData() throws SQLException
{
if (metadata == null)
metadata = new Jdbc3DatabaseMetaData(this);
return metadata;
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException public java.sql.PreparedStatement prepareStatement(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{ {
return new Jdbc3ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); Jdbc3PreparedStatement s = new Jdbc3PreparedStatement(this, sql);
} s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.CallableStatement prepareCall(String sql, int resultSetType, int resultSetConcurrency) throws SQLException
{
Jdbc3CallableStatement s = new Jdbc3CallableStatement(this, sql);
s.setResultSetType(resultSetType);
s.setResultSetConcurrency(resultSetConcurrency);
return s;
}
public java.sql.DatabaseMetaData getMetaData() throws SQLException
{
if (metadata == null)
metadata = new Jdbc3DatabaseMetaData(this);
return metadata;
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) throws SQLException
{
return new Jdbc3ResultSet(this, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException
{
return new Jdbc3ResultSet(this, statement, fields, tuples, status, updateCount, 0, false);
}
public java.sql.ResultSet getResultSet(Statement statement, Field[] fields, Vector tuples, String status, int updateCount) throws SQLException
{
return new Jdbc3ResultSet(this, statement, fields, tuples, status, updateCount, 0, false);
}
} }

View File

@ -3,10 +3,10 @@ package org.postgresql.jdbc3;
public class Jdbc3DatabaseMetaData extends org.postgresql.jdbc3.AbstractJdbc3DatabaseMetaData implements java.sql.DatabaseMetaData public class Jdbc3DatabaseMetaData extends org.postgresql.jdbc3.AbstractJdbc3DatabaseMetaData implements java.sql.DatabaseMetaData
{ {
public Jdbc3DatabaseMetaData(Jdbc3Connection conn) public Jdbc3DatabaseMetaData(Jdbc3Connection conn)
{ {
super(conn); super(conn);
} }
} }

View File

@ -5,11 +5,11 @@ import java.sql.*;
public class Jdbc3PreparedStatement extends org.postgresql.jdbc3.AbstractJdbc3Statement implements java.sql.PreparedStatement public class Jdbc3PreparedStatement extends org.postgresql.jdbc3.AbstractJdbc3Statement implements java.sql.PreparedStatement
{ {
public Jdbc3PreparedStatement(Jdbc3Connection connection, String sql) throws SQLException public Jdbc3PreparedStatement(Jdbc3Connection connection, String sql) throws SQLException
{ {
super(connection, sql); super(connection, sql);
} }
} }

View File

@ -5,31 +5,33 @@ import java.sql.*;
import java.util.Vector; import java.util.Vector;
import org.postgresql.Field; import org.postgresql.Field;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3ResultSet.java,v 1.1 2002/08/14 20:35:40 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3ResultSet.java,v 1.2 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.ResultSet interface for JDBC3. * This class implements the java.sql.ResultSet interface for JDBC3.
* However most of the implementation is really done in * However most of the implementation is really done in
* org.postgresql.jdbc3.AbstractJdbc3ResultSet or one of it's parents * org.postgresql.jdbc3.AbstractJdbc3ResultSet or one of it's parents
*/ */
public class Jdbc3ResultSet extends org.postgresql.jdbc3.AbstractJdbc3ResultSet implements java.sql.ResultSet public class Jdbc3ResultSet extends org.postgresql.jdbc3.AbstractJdbc3ResultSet implements java.sql.ResultSet
{ {
public Jdbc3ResultSet(Jdbc3Connection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor) public Jdbc3ResultSet(Jdbc3Connection conn, Statement statement, Field[] fields, Vector tuples, String status, int updateCount, long insertOID, boolean binaryCursor)
{ {
super(conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor); super(conn, statement, fields, tuples, status, updateCount, insertOID, binaryCursor);
} }
public java.sql.ResultSetMetaData getMetaData() throws SQLException public java.sql.ResultSetMetaData getMetaData() throws SQLException
{ {
return new Jdbc3ResultSetMetaData(rows, fields); return new Jdbc3ResultSetMetaData(rows, fields);
} }
public java.sql.Clob getClob(int i) throws SQLException {
return new Jdbc3Clob(connection, getInt(i));
}
public java.sql.Blob getBlob(int i) throws SQLException { public java.sql.Clob getClob(int i) throws SQLException
return new Jdbc3Blob(connection, getInt(i)); {
} return new Jdbc3Clob(connection, getInt(i));
}
public java.sql.Blob getBlob(int i) throws SQLException
{
return new Jdbc3Blob(connection, getInt(i));
}
} }

View File

@ -2,11 +2,11 @@ package org.postgresql.jdbc3;
public class Jdbc3ResultSetMetaData extends org.postgresql.jdbc2.AbstractJdbc2ResultSetMetaData implements java.sql.ResultSetMetaData public class Jdbc3ResultSetMetaData extends org.postgresql.jdbc2.AbstractJdbc2ResultSetMetaData implements java.sql.ResultSetMetaData
{ {
public Jdbc3ResultSetMetaData(java.util.Vector rows, org.postgresql.Field[] fields) public Jdbc3ResultSetMetaData(java.util.Vector rows, org.postgresql.Field[] fields)
{ {
super(rows, fields); super(rows, fields);
} }
} }

View File

@ -3,17 +3,17 @@ package org.postgresql.jdbc3;
import java.sql.*; import java.sql.*;
/* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3Statement.java,v 1.1 2002/08/14 20:35:40 barry Exp $ /* $Header: /cvsroot/pgsql/src/interfaces/jdbc/org/postgresql/jdbc3/Attic/Jdbc3Statement.java,v 1.2 2002/09/06 21:23:06 momjian Exp $
* This class implements the java.sql.Statement interface for JDBC3. * This class implements the java.sql.Statement interface for JDBC3.
* However most of the implementation is really done in * However most of the implementation is really done in
* org.postgresql.jdbc3.AbstractJdbc3Statement or one of it's parents * org.postgresql.jdbc3.AbstractJdbc3Statement or one of it's parents
*/ */
public class Jdbc3Statement extends org.postgresql.jdbc3.AbstractJdbc3Statement implements java.sql.Statement public class Jdbc3Statement extends org.postgresql.jdbc3.AbstractJdbc3Statement implements java.sql.Statement
{ {
public Jdbc3Statement (Jdbc3Connection c) public Jdbc3Statement (Jdbc3Connection c)
{ {
super(c); super(c);
} }
} }

View File

@ -92,12 +92,12 @@ public class LargeObject
/* Release large object resources during garbage cleanup */ /* Release large object resources during garbage cleanup */
protected void finalize() throws SQLException protected void finalize() throws SQLException
{ {
//This code used to call close() however that was problematic //This code used to call close() however that was problematic
//because the scope of the fd is a transaction, thus if commit //because the scope of the fd is a transaction, thus if commit
//or rollback was called before garbage collection ran then //or rollback was called before garbage collection ran then
//the call to close would error out with an invalid large object //the call to close would error out with an invalid large object
//handle. So this method now does nothing and lets the server //handle. So this method now does nothing and lets the server
//handle cleanup when it ends the transaction. //handle cleanup when it ends the transaction.
} }
/* /*

View File

@ -104,21 +104,22 @@ public class LargeObjectManager
// This is an example of Fastpath.addFunctions(); // This is an example of Fastpath.addFunctions();
// //
ResultSet res = conn.createStatement().executeQuery("select proname, oid from pg_proc" + ResultSet res = conn.createStatement().executeQuery("select proname, oid from pg_proc" +
" where proname = 'lo_open'" + " where proname = 'lo_open'" +
" or proname = 'lo_close'" + " or proname = 'lo_close'" +
" or proname = 'lo_creat'" + " or proname = 'lo_creat'" +
" or proname = 'lo_unlink'" + " or proname = 'lo_unlink'" +
" or proname = 'lo_lseek'" + " or proname = 'lo_lseek'" +
" or proname = 'lo_tell'" + " or proname = 'lo_tell'" +
" or proname = 'loread'" + " or proname = 'loread'" +
" or proname = 'lowrite'"); " or proname = 'lowrite'");
if (res == null) if (res == null)
throw new PSQLException("postgresql.lo.init"); throw new PSQLException("postgresql.lo.init");
fp.addFunctions(res); fp.addFunctions(res);
res.close(); res.close();
if (Driver.logDebug) Driver.debug("Large Object initialised"); if (Driver.logDebug)
Driver.debug("Large Object initialised");
} }
/* /*

View File

@ -22,17 +22,17 @@ public class CallableStmtTest extends TestCase
{ {
con = TestUtil.openDB(); con = TestUtil.openDB();
Statement stmt = con.createStatement (); Statement stmt = con.createStatement ();
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getString (varchar) " + stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getString (varchar) " +
"RETURNS varchar AS ' DECLARE inString alias for $1; begin "+ "RETURNS varchar AS ' DECLARE inString alias for $1; begin " +
"return ''bob''; end; ' LANGUAGE 'plpgsql';"); "return ''bob''; end; ' LANGUAGE 'plpgsql';");
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getDouble (float) " + stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getDouble (float) " +
"RETURNS float AS ' DECLARE inString alias for $1; begin " + "RETURNS float AS ' DECLARE inString alias for $1; begin " +
"return 42.42; end; ' LANGUAGE 'plpgsql';"); "return 42.42; end; ' LANGUAGE 'plpgsql';");
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getInt (int) RETURNS int " + stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getInt (int) RETURNS int " +
" AS 'DECLARE inString alias for $1; begin " + " AS 'DECLARE inString alias for $1; begin " +
"return 42; end;' LANGUAGE 'plpgsql';"); "return 42; end;' LANGUAGE 'plpgsql';");
stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getNumeric (numeric) " + stmt.execute ("CREATE OR REPLACE FUNCTION testspg__getNumeric (numeric) " +
"RETURNS numeric AS ' DECLARE inString alias for $1; " + "RETURNS numeric AS ' DECLARE inString alias for $1; " +
"begin return 42; end; ' LANGUAGE 'plpgsql';"); "begin return 42; end; ' LANGUAGE 'plpgsql';");
stmt.close (); stmt.close ();
} }
@ -54,7 +54,8 @@ public class CallableStmtTest extends TestCase
//testGetString (); //testGetString ();
//} //}
public void testGetDouble () throws Throwable { public void testGetDouble () throws Throwable
{
// System.out.println ("Testing CallableStmt Types.DOUBLE"); // System.out.println ("Testing CallableStmt Types.DOUBLE");
CallableStatement call = con.prepareCall (func + pkgName + "getDouble (?) }"); CallableStatement call = con.prepareCall (func + pkgName + "getDouble (?) }");
call.setDouble (2, (double)3.04); call.setDouble (2, (double)3.04);
@ -64,7 +65,8 @@ public class CallableStmtTest extends TestCase
assertTrue ("correct return from getString ()", result == 42.42); assertTrue ("correct return from getString ()", result == 42.42);
} }
public void testGetInt () throws Throwable { public void testGetInt () throws Throwable
{
// System.out.println ("Testing CallableStmt Types.INTEGER"); // System.out.println ("Testing CallableStmt Types.INTEGER");
CallableStatement call = con.prepareCall (func + pkgName + "getInt (?) }"); CallableStatement call = con.prepareCall (func + pkgName + "getInt (?) }");
call.setInt (2, 4); call.setInt (2, 4);
@ -74,18 +76,20 @@ public class CallableStmtTest extends TestCase
assertTrue ("correct return from getString ()", result == 42); assertTrue ("correct return from getString ()", result == 42);
} }
public void testGetNumeric () throws Throwable { public void testGetNumeric () throws Throwable
{
// System.out.println ("Testing CallableStmt Types.NUMERIC"); // System.out.println ("Testing CallableStmt Types.NUMERIC");
CallableStatement call = con.prepareCall (func + pkgName + "getNumeric (?) }"); CallableStatement call = con.prepareCall (func + pkgName + "getNumeric (?) }");
call.setBigDecimal (2, new java.math.BigDecimal(4)); call.setBigDecimal (2, new java.math.BigDecimal(4));
call.registerOutParameter (1, Types.NUMERIC); call.registerOutParameter (1, Types.NUMERIC);
call.execute (); call.execute ();
java.math.BigDecimal result = call.getBigDecimal (1); java.math.BigDecimal result = call.getBigDecimal (1);
assertTrue ("correct return from getString ()", assertTrue ("correct return from getString ()",
result.equals (new java.math.BigDecimal(42))); result.equals (new java.math.BigDecimal(42)));
} }
public void testGetString () throws Throwable { public void testGetString () throws Throwable
{
// System.out.println ("Testing CallableStmt Types.VARCHAR"); // System.out.println ("Testing CallableStmt Types.VARCHAR");
CallableStatement call = con.prepareCall (func + pkgName + "getString (?) }"); CallableStatement call = con.prepareCall (func + pkgName + "getString (?) }");
call.setString (2, "foo"); call.setString (2, "foo");
@ -96,20 +100,25 @@ public class CallableStmtTest extends TestCase
} }
public void testBadStmt () throws Throwable { public void testBadStmt () throws Throwable
{
tryOneBadStmt ("{ ?= " + pkgName + "getString (?) }"); tryOneBadStmt ("{ ?= " + pkgName + "getString (?) }");
tryOneBadStmt ("{ ?= call getString (?) "); tryOneBadStmt ("{ ?= call getString (?) ");
tryOneBadStmt ("{ = ? call getString (?); }"); tryOneBadStmt ("{ = ? call getString (?); }");
} }
protected void tryOneBadStmt (String sql) throws Throwable { protected void tryOneBadStmt (String sql) throws Throwable
{
boolean wasCaught = false; boolean wasCaught = false;
try { try
{
CallableStatement call = con.prepareCall (sql); CallableStatement call = con.prepareCall (sql);
} catch (SQLException e) { }
catch (SQLException e)
{
wasCaught = true; // good -> this statement was missing something wasCaught = true; // good -> this statement was missing something
} }
assertTrue ("bad statment ('"+sql+"')was not caught", wasCaught); assertTrue ("bad statment ('" + sql + "')was not caught", wasCaught);
} }
} }

View File

@ -9,7 +9,7 @@ import java.sql.*;
* *
* PS: Do you know how difficult it is to type on a train? ;-) * PS: Do you know how difficult it is to type on a train? ;-)
* *
* $Id: DatabaseMetaDataTest.java,v 1.12 2002/08/23 20:45:49 barry Exp $ * $Id: DatabaseMetaDataTest.java,v 1.13 2002/09/06 21:23:06 momjian Exp $
*/ */
public class DatabaseMetaDataTest extends TestCase public class DatabaseMetaDataTest extends TestCase
@ -48,7 +48,7 @@ public class DatabaseMetaDataTest extends TestCase
ResultSet rs = dbmd.getTables( null, null, "test%", new String[] {"TABLE"}); ResultSet rs = dbmd.getTables( null, null, "test%", new String[] {"TABLE"});
assertTrue( rs.next() ); assertTrue( rs.next() );
String tableName = rs.getString("TABLE_NAME"); String tableName = rs.getString("TABLE_NAME");
assertTrue( tableName.equals("testmetadata") ); assertTrue( tableName.equals("testmetadata") );
rs.close(); rs.close();
@ -102,10 +102,10 @@ public class DatabaseMetaDataTest extends TestCase
assertTrue(dbmd.supportsMinimumSQLGrammar()); assertTrue(dbmd.supportsMinimumSQLGrammar());
assertTrue(!dbmd.supportsCoreSQLGrammar()); assertTrue(!dbmd.supportsCoreSQLGrammar());
assertTrue(!dbmd.supportsExtendedSQLGrammar()); assertTrue(!dbmd.supportsExtendedSQLGrammar());
if (((org.postgresql.jdbc1.AbstractJdbc1Connection)con).haveMinimumServerVersion("7.3")) if (((org.postgresql.jdbc1.AbstractJdbc1Connection)con).haveMinimumServerVersion("7.3"))
assertTrue(dbmd.supportsANSI92EntryLevelSQL()); assertTrue(dbmd.supportsANSI92EntryLevelSQL());
else else
assertTrue(!dbmd.supportsANSI92EntryLevelSQL()); assertTrue(!dbmd.supportsANSI92EntryLevelSQL());
assertTrue(!dbmd.supportsANSI92IntermediateSQL()); assertTrue(!dbmd.supportsANSI92IntermediateSQL());
assertTrue(!dbmd.supportsANSI92FullSQL()); assertTrue(!dbmd.supportsANSI92FullSQL());
@ -232,124 +232,124 @@ public class DatabaseMetaDataTest extends TestCase
} }
} }
public void testCrossReference() public void testCrossReference()
{ {
try try
{ {
Connection con1 = TestUtil.openDB(); Connection con1 = TestUtil.openDB();
TestUtil.createTable( con1, "vv", "a int not null, b int not null, primary key ( a, b )" ); TestUtil.createTable( con1, "vv", "a int not null, b int not null, primary key ( a, b )" );
TestUtil.createTable( con1, "ww", "m int not null, n int not null, primary key ( m, n ), foreign key ( m, n ) references vv ( a, b )" ); TestUtil.createTable( con1, "ww", "m int not null, n int not null, primary key ( m, n ), foreign key ( m, n ) references vv ( a, b )" );
DatabaseMetaData dbmd = con.getMetaData(); DatabaseMetaData dbmd = con.getMetaData();
assertNotNull(dbmd); assertNotNull(dbmd);
ResultSet rs = dbmd.getCrossReference(null, "", "vv", null, "", "ww" ); ResultSet rs = dbmd.getCrossReference(null, "", "vv", null, "", "ww" );
for (int j=1; rs.next(); j++ ) for (int j = 1; rs.next(); j++ )
{ {
String pkTableName = rs.getString( "PKTABLE_NAME" ); String pkTableName = rs.getString( "PKTABLE_NAME" );
assertTrue ( pkTableName.equals("vv") ); assertTrue ( pkTableName.equals("vv") );
String pkColumnName = rs.getString( "PKCOLUMN_NAME" ); String pkColumnName = rs.getString( "PKCOLUMN_NAME" );
assertTrue( pkColumnName.equals("a") || pkColumnName.equals("b")); assertTrue( pkColumnName.equals("a") || pkColumnName.equals("b"));
String fkTableName = rs.getString( "FKTABLE_NAME" ); String fkTableName = rs.getString( "FKTABLE_NAME" );
assertTrue( fkTableName.equals( "ww" ) ); assertTrue( fkTableName.equals( "ww" ) );
String fkColumnName = rs.getString( "FKCOLUMN_NAME" ); String fkColumnName = rs.getString( "FKCOLUMN_NAME" );
assertTrue( fkColumnName.equals( "m" ) || fkColumnName.equals( "n" ) ) ; assertTrue( fkColumnName.equals( "m" ) || fkColumnName.equals( "n" ) ) ;
String fkName = rs.getString( "FK_NAME" ); String fkName = rs.getString( "FK_NAME" );
assertTrue( fkName.equals( "<unnamed>") ); assertTrue( fkName.equals( "<unnamed>") );
String pkName = rs.getString( "PK_NAME" ); String pkName = rs.getString( "PK_NAME" );
assertTrue( pkName.equals("vv_pkey") ); assertTrue( pkName.equals("vv_pkey") );
int keySeq = rs.getInt( "KEY_SEQ" ); int keySeq = rs.getInt( "KEY_SEQ" );
assertTrue( keySeq == j ); assertTrue( keySeq == j );
} }
TestUtil.dropTable( con1, "vv" ); TestUtil.dropTable( con1, "vv" );
TestUtil.dropTable( con1, "ww" ); TestUtil.dropTable( con1, "ww" );
} }
catch (SQLException ex) catch (SQLException ex)
{ {
fail(ex.getMessage()); fail(ex.getMessage());
} }
} }
public void testForeignKeys() public void testForeignKeys()
{ {
try try
{ {
Connection con1 = TestUtil.openDB(); Connection con1 = TestUtil.openDB();
TestUtil.createTable( con1, "people", "id int4 primary key, name text" ); TestUtil.createTable( con1, "people", "id int4 primary key, name text" );
TestUtil.createTable( con1, "policy", "id int4 primary key, name text" ); TestUtil.createTable( con1, "policy", "id int4 primary key, name text" );
TestUtil.createTable( con1, "users", "id int4 primary key, people_id int4, policy_id int4,"+ TestUtil.createTable( con1, "users", "id int4 primary key, people_id int4, policy_id int4," +
"CONSTRAINT people FOREIGN KEY (people_id) references people(id),"+ "CONSTRAINT people FOREIGN KEY (people_id) references people(id)," +
"constraint policy FOREIGN KEY (policy_id) references policy(id)" ); "constraint policy FOREIGN KEY (policy_id) references policy(id)" );
DatabaseMetaData dbmd = con.getMetaData(); DatabaseMetaData dbmd = con.getMetaData();
assertNotNull(dbmd); assertNotNull(dbmd);
ResultSet rs = dbmd.getImportedKeys(null, "", "users" ); ResultSet rs = dbmd.getImportedKeys(null, "", "users" );
int j = 0; int j = 0;
for (; rs.next(); j++ ) for (; rs.next(); j++ )
{ {
String pkTableName = rs.getString( "PKTABLE_NAME" ); String pkTableName = rs.getString( "PKTABLE_NAME" );
assertTrue ( pkTableName.equals("people") || pkTableName.equals("policy") ); assertTrue ( pkTableName.equals("people") || pkTableName.equals("policy") );
String pkColumnName = rs.getString( "PKCOLUMN_NAME" ); String pkColumnName = rs.getString( "PKCOLUMN_NAME" );
assertTrue( pkColumnName.equals("id") ); assertTrue( pkColumnName.equals("id") );
String fkTableName = rs.getString( "FKTABLE_NAME" ); String fkTableName = rs.getString( "FKTABLE_NAME" );
assertTrue( fkTableName.equals( "users" ) ); assertTrue( fkTableName.equals( "users" ) );
String fkColumnName = rs.getString( "FKCOLUMN_NAME" ); String fkColumnName = rs.getString( "FKCOLUMN_NAME" );
assertTrue( fkColumnName.equals( "people_id" ) || fkColumnName.equals( "policy_id" ) ) ; assertTrue( fkColumnName.equals( "people_id" ) || fkColumnName.equals( "policy_id" ) ) ;
String fkName = rs.getString( "FK_NAME" ); String fkName = rs.getString( "FK_NAME" );
assertTrue( fkName.equals( "people") || fkName.equals( "policy" ) ); assertTrue( fkName.equals( "people") || fkName.equals( "policy" ) );
String pkName = rs.getString( "PK_NAME" ); String pkName = rs.getString( "PK_NAME" );
assertTrue( pkName.equals( "people_pkey") || pkName.equals( "policy_pkey" ) ); assertTrue( pkName.equals( "people_pkey") || pkName.equals( "policy_pkey" ) );
} }
assertTrue ( j== 2 ); assertTrue ( j == 2 );
rs = dbmd.getExportedKeys( null, "", "people" ); rs = dbmd.getExportedKeys( null, "", "people" );
// this is hacky, but it will serve the purpose // this is hacky, but it will serve the purpose
assertTrue ( rs.next() ); assertTrue ( rs.next() );
assertTrue( rs.getString( "PKTABLE_NAME" ).equals( "people" ) ); assertTrue( rs.getString( "PKTABLE_NAME" ).equals( "people" ) );
assertTrue( rs.getString( "PKCOLUMN_NAME" ).equals( "id" ) ); assertTrue( rs.getString( "PKCOLUMN_NAME" ).equals( "id" ) );
assertTrue( rs.getString( "FKTABLE_NAME" ).equals( "users" ) ); assertTrue( rs.getString( "FKTABLE_NAME" ).equals( "users" ) );
assertTrue( rs.getString( "FKCOLUMN_NAME" ).equals( "people_id" ) ); assertTrue( rs.getString( "FKCOLUMN_NAME" ).equals( "people_id" ) );
assertTrue( rs.getString( "FK_NAME" ).equals( "people" ) ); assertTrue( rs.getString( "FK_NAME" ).equals( "people" ) );
TestUtil.dropTable( con1, "users" ); TestUtil.dropTable( con1, "users" );
TestUtil.dropTable( con1, "people" ); TestUtil.dropTable( con1, "people" );
TestUtil.dropTable( con1, "policy" ); TestUtil.dropTable( con1, "policy" );
} }
catch (SQLException ex) catch (SQLException ex)
{ {
fail(ex.getMessage()); fail(ex.getMessage());
} }
} }
public void testTables() public void testTables()
{ {
try try
@ -422,20 +422,20 @@ public class DatabaseMetaDataTest extends TestCase
{ {
try try
{ {
assertTrue(con instanceof org.postgresql.PGConnection); assertTrue(con instanceof org.postgresql.PGConnection);
org.postgresql.jdbc2.AbstractJdbc2Connection pc = (org.postgresql.jdbc2.AbstractJdbc2Connection) con; org.postgresql.jdbc2.AbstractJdbc2Connection pc = (org.postgresql.jdbc2.AbstractJdbc2Connection) con;
DatabaseMetaData dbmd = con.getMetaData(); DatabaseMetaData dbmd = con.getMetaData();
assertNotNull(dbmd); assertNotNull(dbmd);
assertTrue(dbmd.getDatabaseProductName().equals("PostgreSQL")); assertTrue(dbmd.getDatabaseProductName().equals("PostgreSQL"));
//The test below doesn't make sense to me, it tests that //The test below doesn't make sense to me, it tests that
//the version of the driver = the version of the database it is connected to //the version of the driver = the version of the database it is connected to
//since the driver should be backwardly compatible this test is commented out //since the driver should be backwardly compatible this test is commented out
//assertTrue(dbmd.getDatabaseProductVersion().startsWith( //assertTrue(dbmd.getDatabaseProductVersion().startsWith(
// Integer.toString(pc.getDriver().getMajorVersion()) // Integer.toString(pc.getDriver().getMajorVersion())
// + "." // + "."
// + Integer.toString(pc.getDriver().getMinorVersion()))); // + Integer.toString(pc.getDriver().getMinorVersion())));
assertTrue(dbmd.getDriverName().equals("PostgreSQL Native Driver")); assertTrue(dbmd.getDriverName().equals("PostgreSQL Native Driver"));
} }

View File

@ -6,7 +6,7 @@ import java.sql.*;
import java.math.BigDecimal; import java.math.BigDecimal;
/* /*
* $Id: JBuilderTest.java,v 1.6 2002/08/14 20:35:40 barry Exp $ * $Id: JBuilderTest.java,v 1.7 2002/09/06 21:23:06 momjian Exp $
* *
* Some simple tests to check that the required components needed for JBuilder * Some simple tests to check that the required components needed for JBuilder
* stay working * stay working
@ -26,7 +26,7 @@ public class JBuilderTest extends TestCase
Connection con = TestUtil.openDB(); Connection con = TestUtil.openDB();
TestUtil.createTable( con, "test_c", TestUtil.createTable( con, "test_c",
"source text,cost money,imageid int4" ); "source text,cost money,imageid int4" );
TestUtil.closeDB(con); TestUtil.closeDB(con);
} }

View File

@ -63,7 +63,7 @@ public class Jdbc2TestSuite extends TestSuite
suite.addTestSuite( UpdateableResultTest.class ); suite.addTestSuite( UpdateableResultTest.class );
suite.addTestSuite( CallableStmtTest.class ); suite.addTestSuite( CallableStmtTest.class );
// That's all folks // That's all folks
return suite; return suite;
} }

View File

@ -5,7 +5,7 @@ import junit.framework.TestCase;
import java.sql.*; import java.sql.*;
/* /*
* $Id: MiscTest.java,v 1.7 2002/08/14 20:35:40 barry Exp $ * $Id: MiscTest.java,v 1.8 2002/09/06 21:23:06 momjian Exp $
* *
* Some simple tests based on problems reported by users. Hopefully these will * Some simple tests based on problems reported by users. Hopefully these will
* help prevent previous problems from re-occuring ;-) * help prevent previous problems from re-occuring ;-)
@ -52,28 +52,29 @@ public class MiscTest extends TestCase
} }
} }
public void testError() public void testError()
{ {
Connection con = TestUtil.openDB(); Connection con = TestUtil.openDB();
try try
{ {
// transaction mode // transaction mode
con.setAutoCommit(false); con.setAutoCommit(false);
Statement stmt = con.createStatement(); Statement stmt = con.createStatement();
stmt.execute("select 1/0"); stmt.execute("select 1/0");
fail( "Should not execute this, as a SQLException s/b thrown" ); fail( "Should not execute this, as a SQLException s/b thrown" );
con.commit(); con.commit();
} }
catch ( Exception ex ) catch ( Exception ex )
{}
try
{ {
con.commit();
con.close();
} }
try catch ( Exception ex)
{ {}
con.commit(); }
con.close();
}catch ( Exception ex) {}
}
public void xtestLocking() public void xtestLocking()
{ {
@ -90,7 +91,7 @@ public class MiscTest extends TestCase
con.setAutoCommit(false); con.setAutoCommit(false);
st.execute("lock table test_lock"); st.execute("lock table test_lock");
st2.executeUpdate( "insert into test_lock ( name ) values ('hello')" ); st2.executeUpdate( "insert into test_lock ( name ) values ('hello')" );
con.commit(); con.commit();
TestUtil.dropTable(con, "test_lock"); TestUtil.dropTable(con, "test_lock");
con.close(); con.close();
} }

View File

@ -63,24 +63,24 @@ public class ResultSetTest extends TestCase
stmt.close(); stmt.close();
} }
public void testEmptyResult() public void testEmptyResult()
{ {
try try
{ {
Statement stmt = con.createStatement(); Statement stmt = con.createStatement();
ResultSet rs = stmt.executeQuery("SELECT * FROM testrs where id=100"); ResultSet rs = stmt.executeQuery("SELECT * FROM testrs where id=100");
rs.beforeFirst(); rs.beforeFirst();
rs.afterLast(); rs.afterLast();
assertTrue(!rs.first()); assertTrue(!rs.first());
assertTrue(!rs.last()); assertTrue(!rs.last());
assertTrue(!rs.next()); assertTrue(!rs.next());
} }
catch ( Exception ex ) catch ( Exception ex )
{ {
fail( ex.getMessage() ); fail( ex.getMessage() );
} }
} }
} }

View File

@ -5,9 +5,9 @@ import junit.framework.TestCase;
import java.sql.*; import java.sql.*;
/* /*
* $Id: TimestampTest.java,v 1.8 2002/08/14 20:35:40 barry Exp $ * $Id: TimestampTest.java,v 1.9 2002/09/06 21:23:06 momjian Exp $
* *
* Test get/setTimestamp for both timestamp with time zone and * Test get/setTimestamp for both timestamp with time zone and
* timestamp without time zone datatypes * timestamp without time zone datatypes
* *
*/ */
@ -39,8 +39,8 @@ public class TimestampTest extends TestCase
/* /*
* Tests the timestamp methods in ResultSet on timestamp with time zone * Tests the timestamp methods in ResultSet on timestamp with time zone
* we insert a known string value (don't use setTimestamp) then see that * we insert a known string value (don't use setTimestamp) then see that
* we get back the same value from getTimestamp * we get back the same value from getTimestamp
*/ */
public void testGetTimestampWTZ() public void testGetTimestampWTZ()
{ {
@ -48,15 +48,15 @@ public class TimestampTest extends TestCase
{ {
Statement stmt = con.createStatement(); Statement stmt = con.createStatement();
//Insert the three timestamp values in raw pg format //Insert the three timestamp values in raw pg format
assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE,"'" + TS1WTZ_PGFORMAT + "'"))); assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE, "'" + TS1WTZ_PGFORMAT + "'")));
assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE,"'" + TS2WTZ_PGFORMAT + "'"))); assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE, "'" + TS2WTZ_PGFORMAT + "'")));
assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE,"'" + TS3WTZ_PGFORMAT + "'"))); assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWTZ_TABLE, "'" + TS3WTZ_PGFORMAT + "'")));
// Fall through helper // Fall through helper
timestampTestWTZ(); timestampTestWTZ();
assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE)); assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE));
stmt.close(); stmt.close();
} }
@ -68,9 +68,9 @@ public class TimestampTest extends TestCase
/* /*
* Tests the timestamp methods in PreparedStatement on timestamp with time zone * Tests the timestamp methods in PreparedStatement on timestamp with time zone
* we insert a value using setTimestamp then see that * we insert a value using setTimestamp then see that
* we get back the same value from getTimestamp (which we know works as it was tested * we get back the same value from getTimestamp (which we know works as it was tested
* independently of setTimestamp * independently of setTimestamp
*/ */
public void testSetTimestampWTZ() public void testSetTimestampWTZ()
{ {
@ -80,18 +80,18 @@ public class TimestampTest extends TestCase
PreparedStatement pstmt = con.prepareStatement(TestUtil.insertSQL(TSWTZ_TABLE, "?")); PreparedStatement pstmt = con.prepareStatement(TestUtil.insertSQL(TSWTZ_TABLE, "?"));
pstmt.setTimestamp(1, TS1WTZ); pstmt.setTimestamp(1, TS1WTZ);
assertEquals(1, pstmt.executeUpdate()); assertEquals(1, pstmt.executeUpdate());
pstmt.setTimestamp(1, TS2WTZ); pstmt.setTimestamp(1, TS2WTZ);
assertEquals(1, pstmt.executeUpdate()); assertEquals(1, pstmt.executeUpdate());
pstmt.setTimestamp(1, TS3WTZ); pstmt.setTimestamp(1, TS3WTZ);
assertEquals(1, pstmt.executeUpdate()); assertEquals(1, pstmt.executeUpdate());
// Fall through helper // Fall through helper
timestampTestWTZ(); timestampTestWTZ();
assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE)); assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWTZ_TABLE));
pstmt.close(); pstmt.close();
stmt.close(); stmt.close();
@ -104,8 +104,8 @@ public class TimestampTest extends TestCase
/* /*
* Tests the timestamp methods in ResultSet on timestamp without time zone * Tests the timestamp methods in ResultSet on timestamp without time zone
* we insert a known string value (don't use setTimestamp) then see that * we insert a known string value (don't use setTimestamp) then see that
* we get back the same value from getTimestamp * we get back the same value from getTimestamp
*/ */
public void testGetTimestampWOTZ() public void testGetTimestampWOTZ()
{ {
@ -113,15 +113,15 @@ public class TimestampTest extends TestCase
{ {
Statement stmt = con.createStatement(); Statement stmt = con.createStatement();
//Insert the three timestamp values in raw pg format //Insert the three timestamp values in raw pg format
assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE,"'" + TS1WOTZ_PGFORMAT + "'"))); assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE, "'" + TS1WOTZ_PGFORMAT + "'")));
assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE,"'" + TS2WOTZ_PGFORMAT + "'"))); assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE, "'" + TS2WOTZ_PGFORMAT + "'")));
assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE,"'" + TS3WOTZ_PGFORMAT + "'"))); assertEquals(1, stmt.executeUpdate(TestUtil.insertSQL(TSWOTZ_TABLE, "'" + TS3WOTZ_PGFORMAT + "'")));
// Fall through helper // Fall through helper
timestampTestWOTZ(); timestampTestWOTZ();
assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE)); assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE));
stmt.close(); stmt.close();
} }
@ -134,9 +134,9 @@ public class TimestampTest extends TestCase
/* /*
* Tests the timestamp methods in PreparedStatement on timestamp without time zone * Tests the timestamp methods in PreparedStatement on timestamp without time zone
* we insert a value using setTimestamp then see that * we insert a value using setTimestamp then see that
* we get back the same value from getTimestamp (which we know works as it was tested * we get back the same value from getTimestamp (which we know works as it was tested
* independently of setTimestamp * independently of setTimestamp
*/ */
public void testSetTimestampWOTZ() public void testSetTimestampWOTZ()
{ {
@ -146,18 +146,18 @@ public class TimestampTest extends TestCase
PreparedStatement pstmt = con.prepareStatement(TestUtil.insertSQL(TSWOTZ_TABLE, "?")); PreparedStatement pstmt = con.prepareStatement(TestUtil.insertSQL(TSWOTZ_TABLE, "?"));
pstmt.setTimestamp(1, TS1WOTZ); pstmt.setTimestamp(1, TS1WOTZ);
assertEquals(1, pstmt.executeUpdate()); assertEquals(1, pstmt.executeUpdate());
pstmt.setTimestamp(1, TS2WOTZ); pstmt.setTimestamp(1, TS2WOTZ);
assertEquals(1, pstmt.executeUpdate()); assertEquals(1, pstmt.executeUpdate());
pstmt.setTimestamp(1, TS3WOTZ); pstmt.setTimestamp(1, TS3WOTZ);
assertEquals(1, pstmt.executeUpdate()); assertEquals(1, pstmt.executeUpdate());
// Fall through helper // Fall through helper
timestampTestWOTZ(); timestampTestWOTZ();
assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE)); assertEquals(3, stmt.executeUpdate("DELETE FROM " + TSWOTZ_TABLE));
pstmt.close(); pstmt.close();
stmt.close(); stmt.close();
@ -178,22 +178,22 @@ public class TimestampTest extends TestCase
java.sql.Timestamp t; java.sql.Timestamp t;
rs = stmt.executeQuery("select ts from " + TSWTZ_TABLE + " order by ts"); rs = stmt.executeQuery("select ts from " + TSWTZ_TABLE + " order by ts");
assertNotNull(rs); assertNotNull(rs);
assertTrue(rs.next()); assertTrue(rs.next());
t = rs.getTimestamp(1); t = rs.getTimestamp(1);
assertNotNull(t); assertNotNull(t);
assertTrue(t.equals(TS1WTZ)); assertTrue(t.equals(TS1WTZ));
assertTrue(rs.next()); assertTrue(rs.next());
t = rs.getTimestamp(1); t = rs.getTimestamp(1);
assertNotNull(t); assertNotNull(t);
assertTrue(t.equals(TS2WTZ)); assertTrue(t.equals(TS2WTZ));
assertTrue(rs.next()); assertTrue(rs.next());
t = rs.getTimestamp(1); t = rs.getTimestamp(1);
assertNotNull(t); assertNotNull(t);
assertTrue(t.equals(TS3WTZ)); assertTrue(t.equals(TS3WTZ));
assertTrue(! rs.next()); // end of table. Fail if more entries exist. assertTrue(! rs.next()); // end of table. Fail if more entries exist.
@ -211,21 +211,21 @@ public class TimestampTest extends TestCase
java.sql.Timestamp t; java.sql.Timestamp t;
rs = stmt.executeQuery("select ts from " + TSWOTZ_TABLE + " order by ts"); rs = stmt.executeQuery("select ts from " + TSWOTZ_TABLE + " order by ts");
assertNotNull(rs); assertNotNull(rs);
assertTrue(rs.next()); assertTrue(rs.next());
t = rs.getTimestamp(1); t = rs.getTimestamp(1);
assertNotNull(t); assertNotNull(t);
assertTrue(t.toString().equals(TS1WOTZ_JAVAFORMAT)); assertTrue(t.toString().equals(TS1WOTZ_JAVAFORMAT));
assertTrue(rs.next()); assertTrue(rs.next());
t = rs.getTimestamp(1); t = rs.getTimestamp(1);
assertNotNull(t); assertNotNull(t);
assertTrue(t.toString().equals(TS2WOTZ_JAVAFORMAT)); assertTrue(t.toString().equals(TS2WOTZ_JAVAFORMAT));
assertTrue(rs.next()); assertTrue(rs.next());
t = rs.getTimestamp(1); t = rs.getTimestamp(1);
assertNotNull(t); assertNotNull(t);
assertTrue(t.toString().equals(TS3WOTZ_JAVAFORMAT)); assertTrue(t.toString().equals(TS3WOTZ_JAVAFORMAT));
assertTrue(! rs.next()); // end of table. Fail if more entries exist. assertTrue(! rs.next()); // end of table. Fail if more entries exist.
@ -236,57 +236,63 @@ public class TimestampTest extends TestCase
private static java.sql.Timestamp getTimestamp(int y, int m, int d, int h, int mn, int se, int f, String tz) private static java.sql.Timestamp getTimestamp(int y, int m, int d, int h, int mn, int se, int f, String tz)
{ {
java.sql.Timestamp l_return = null; java.sql.Timestamp l_return = null;
java.text.DateFormat l_df; java.text.DateFormat l_df;
try { try
String l_ts; {
l_ts = TestUtil.fix(y, 4) + "-" + String l_ts;
TestUtil.fix(m, 2) + "-" + l_ts = TestUtil.fix(y, 4) + "-" +
TestUtil.fix(d, 2) + " " + TestUtil.fix(m, 2) + "-" +
TestUtil.fix(h, 2) + ":" + TestUtil.fix(d, 2) + " " +
TestUtil.fix(mn, 2) + ":" + TestUtil.fix(h, 2) + ":" +
TestUtil.fix(se, 2) + " "; TestUtil.fix(mn, 2) + ":" +
TestUtil.fix(se, 2) + " ";
if (tz == null) { if (tz == null)
l_df = new java.text.SimpleDateFormat("y-M-d H:m:s"); {
} else { l_df = new java.text.SimpleDateFormat("y-M-d H:m:s");
l_ts = l_ts + tz; }
l_df = new java.text.SimpleDateFormat("y-M-d H:m:s z"); else
{
l_ts = l_ts + tz;
l_df = new java.text.SimpleDateFormat("y-M-d H:m:s z");
}
java.util.Date l_date = l_df.parse(l_ts);
l_return = new java.sql.Timestamp(l_date.getTime());
l_return.setNanos(f);
} }
java.util.Date l_date = l_df.parse(l_ts); catch (Exception ex)
l_return = new java.sql.Timestamp(l_date.getTime()); {
l_return.setNanos(f); fail(ex.getMessage());
} catch (Exception ex) { }
fail(ex.getMessage()); return l_return;
}
return l_return;
} }
private static final java.sql.Timestamp TS1WTZ = getTimestamp(1950, 2, 7, 15, 0, 0, 100000000, "PST"); private static final java.sql.Timestamp TS1WTZ = getTimestamp(1950, 2, 7, 15, 0, 0, 100000000, "PST");
private static final String TS1WTZ_PGFORMAT = "1950-02-07 15:00:00.1-08"; private static final String TS1WTZ_PGFORMAT = "1950-02-07 15:00:00.1-08";
private static final java.sql.Timestamp TS2WTZ = getTimestamp(2000, 2, 7, 15, 0, 0, 120000000, "GMT");
private static final String TS2WTZ_PGFORMAT = "2000-02-07 15:00:00.12+00";
private static final java.sql.Timestamp TS3WTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123000000, "GMT"); private static final java.sql.Timestamp TS2WTZ = getTimestamp(2000, 2, 7, 15, 0, 0, 120000000, "GMT");
private static final String TS3WTZ_PGFORMAT = "2000-07-07 15:00:00.123+00"; private static final String TS2WTZ_PGFORMAT = "2000-02-07 15:00:00.12+00";
private static final java.sql.Timestamp TS3WTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123000000, "GMT");
private static final String TS3WTZ_PGFORMAT = "2000-07-07 15:00:00.123+00";
private static final java.sql.Timestamp TS1WOTZ = getTimestamp(1950, 2, 7, 15, 0, 0, 100000000, null); private static final java.sql.Timestamp TS1WOTZ = getTimestamp(1950, 2, 7, 15, 0, 0, 100000000, null);
private static final String TS1WOTZ_PGFORMAT = "1950-02-07 15:00:00.1"; private static final String TS1WOTZ_PGFORMAT = "1950-02-07 15:00:00.1";
private static final String TS1WOTZ_JAVAFORMAT = "1950-02-07 15:00:00.1"; private static final String TS1WOTZ_JAVAFORMAT = "1950-02-07 15:00:00.1";
private static final java.sql.Timestamp TS2WOTZ = getTimestamp(2000, 2, 7, 15, 0, 0, 120000000, null);
private static final String TS2WOTZ_PGFORMAT = "2000-02-07 15:00:00.12";
//there is probably a bug here in that this needs to be .1 instead of .12, but I couldn't find it now
private static final String TS2WOTZ_JAVAFORMAT = "2000-02-07 15:00:00.1";
private static final java.sql.Timestamp TS3WOTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123000000, null); private static final java.sql.Timestamp TS2WOTZ = getTimestamp(2000, 2, 7, 15, 0, 0, 120000000, null);
private static final String TS3WOTZ_PGFORMAT = "2000-07-07 15:00:00.123"; private static final String TS2WOTZ_PGFORMAT = "2000-02-07 15:00:00.12";
//there is probably a bug here in that this needs to be .12 instead of .123, but I couldn't find it now //there is probably a bug here in that this needs to be .1 instead of .12, but I couldn't find it now
private static final String TS3WOTZ_JAVAFORMAT = "2000-07-07 15:00:00.12"; private static final String TS2WOTZ_JAVAFORMAT = "2000-02-07 15:00:00.1";
private static final String TSWTZ_TABLE = "testtimestampwtz"; private static final java.sql.Timestamp TS3WOTZ = getTimestamp(2000, 7, 7, 15, 0, 0, 123000000, null);
private static final String TSWOTZ_TABLE = "testtimestampwotz"; private static final String TS3WOTZ_PGFORMAT = "2000-07-07 15:00:00.123";
//there is probably a bug here in that this needs to be .12 instead of .123, but I couldn't find it now
private static final String TS3WOTZ_JAVAFORMAT = "2000-07-07 15:00:00.12";
private static final String TSWTZ_TABLE = "testtimestampwtz";
private static final String TSWOTZ_TABLE = "testtimestampwotz";
} }

View File

@ -16,120 +16,121 @@ import org.postgresql.test.TestUtil;
public class UpdateableResultTest extends TestCase public class UpdateableResultTest extends TestCase
{ {
public UpdateableResultTest( String name ) public UpdateableResultTest( String name )
{ {
super( name ); super( name );
} }
public void testUpdateable() public void testUpdateable()
{ {
try try
{ {
Connection con = TestUtil.openDB(); Connection con = TestUtil.openDB();
TestUtil.createTable(con, "updateable","id int primary key, name text, notselected text"); TestUtil.createTable(con, "updateable", "id int primary key, name text, notselected text");
TestUtil.createTable(con, "second","id1 int primary key, name1 text"); TestUtil.createTable(con, "second", "id1 int primary key, name1 text");
// put some dummy data into second // put some dummy data into second
Statement st2 = con.createStatement(); Statement st2 = con.createStatement();
st2.execute( "insert into second values (1,'anyvalue' )"); st2.execute( "insert into second values (1,'anyvalue' )");
st2.close(); st2.close();
Statement st = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE ); Statement st = con.createStatement( ResultSet.TYPE_SCROLL_INSENSITIVE, ResultSet.CONCUR_UPDATABLE );
ResultSet rs = st.executeQuery( "select * from updateable"); ResultSet rs = st.executeQuery( "select * from updateable");
assertNotNull( rs ); assertNotNull( rs );
rs.moveToInsertRow(); rs.moveToInsertRow();
rs.updateInt( 1, 1 ); rs.updateInt( 1, 1 );
rs.updateString( 2, "jake" ); rs.updateString( 2, "jake" );
rs.updateString( 3, "avalue" ); rs.updateString( 3, "avalue" );
rs.insertRow(); rs.insertRow();
rs.first(); rs.first();
rs.updateInt( "id",2 ); rs.updateInt( "id", 2 );
rs.updateString( "name","dave" ); rs.updateString( "name", "dave" );
rs.updateRow(); rs.updateRow();
assertTrue( rs.getInt("id") == 2 ); assertTrue( rs.getInt("id") == 2 );
assertTrue( rs.getString("name").equals("dave")); assertTrue( rs.getString("name").equals("dave"));
assertTrue( rs.getString("notselected").equals("avalue") ); assertTrue( rs.getString("notselected").equals("avalue") );
rs.deleteRow(); rs.deleteRow();
rs.moveToInsertRow(); rs.moveToInsertRow();
rs.updateInt("id",3); rs.updateInt("id", 3);
rs.updateString("name", "paul"); rs.updateString("name", "paul");
rs.insertRow(); rs.insertRow();
rs.refreshRow(); rs.refreshRow();
assertTrue( rs.getInt("id") == 3 ); assertTrue( rs.getInt("id") == 3 );
assertTrue( rs.getString("name").equals("paul")); assertTrue( rs.getString("name").equals("paul"));
assertTrue( rs.getString("notselected") == null ); assertTrue( rs.getString("notselected") == null );
rs.close(); rs.close();
rs = st.executeQuery("select id1, id, name, name1 from updateable, second" ); rs = st.executeQuery("select id1, id, name, name1 from updateable, second" );
try try
{ {
while( rs.next() ) while ( rs.next() )
{ {
rs.updateInt( "id",2 ); rs.updateInt( "id", 2 );
rs.updateString( "name","dave" ); rs.updateString( "name", "dave" );
rs.updateRow(); rs.updateRow();
} }
assertTrue( "should not get here, update should fail", false ); assertTrue( "should not get here, update should fail", false );
} }
catch (SQLException ex){} catch (SQLException ex)
{}
try try
{ {
rs = st.executeQuery("select oid,* from updateable"); rs = st.executeQuery("select oid,* from updateable");
if ( rs.first() ) if ( rs.first() )
{ {
rs.updateInt( "id", 3 ); rs.updateInt( "id", 3 );
rs.updateString( "name", "dave3"); rs.updateString( "name", "dave3");
rs.updateRow(); rs.updateRow();
assertTrue(rs.getInt("id") == 3 ); assertTrue(rs.getInt("id") == 3 );
assertTrue(rs.getString("name").equals("dave3")); assertTrue(rs.getString("name").equals("dave3"));
rs.moveToInsertRow(); rs.moveToInsertRow();
rs.updateInt( "id", 4 ); rs.updateInt( "id", 4 );
rs.updateString( "name", "dave4" ); rs.updateString( "name", "dave4" );
rs.insertRow(); rs.insertRow();
rs.updateInt("id", 5 ); rs.updateInt("id", 5 );
rs.updateString( "name", "dave5" ); rs.updateString( "name", "dave5" );
rs.insertRow(); rs.insertRow();
rs.moveToCurrentRow(); rs.moveToCurrentRow();
assertTrue(rs.getInt("id") == 3 ); assertTrue(rs.getInt("id") == 3 );
assertTrue(rs.getString("name").equals("dave3")); assertTrue(rs.getString("name").equals("dave3"));
assertTrue( rs.next() ); assertTrue( rs.next() );
assertTrue(rs.getInt("id") == 4 ); assertTrue(rs.getInt("id") == 4 );
assertTrue(rs.getString("name").equals("dave4")); assertTrue(rs.getString("name").equals("dave4"));
assertTrue( rs.next() ); assertTrue( rs.next() );
assertTrue(rs.getInt("id") == 5 ); assertTrue(rs.getInt("id") == 5 );
assertTrue(rs.getString("name").equals("dave5")); assertTrue(rs.getString("name").equals("dave5"));
} }
} }
catch(SQLException ex) catch (SQLException ex)
{ {
fail(ex.getMessage()); fail(ex.getMessage());
} }
st.close(); st.close();
TestUtil.dropTable( con,"updateable" ); TestUtil.dropTable( con, "updateable" );
TestUtil.closeDB( con ); TestUtil.closeDB( con );
} }
catch (Exception ex) catch (Exception ex)
{ {
fail(ex.getMessage()); fail(ex.getMessage());
} }
} }
} }

View File

@ -10,151 +10,179 @@ import java.sql.*;
/** /**
* Common tests for all the BaseDataSource implementations. This is * Common tests for all the BaseDataSource implementations. This is
* a small variety to make sure that a connection can be opened and * a small variety to make sure that a connection can be opened and
* some basic queries run. The different BaseDataSource subclasses * some basic queries run. The different BaseDataSource subclasses
* have different subclasses of this which add additional custom * have different subclasses of this which add additional custom
* tests. * tests.
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public abstract class BaseDataSourceTest extends TestCase { public abstract class BaseDataSourceTest extends TestCase
protected Connection con; {
protected BaseDataSource bds; protected Connection con;
protected BaseDataSource bds;
/** /**
* Constructor required by JUnit * Constructor required by JUnit
*/ */
public BaseDataSourceTest(String name) { public BaseDataSourceTest(String name)
super(name); {
} super(name);
}
/** /**
* Creates a test table using a standard connection (not from a * Creates a test table using a standard connection (not from a
* DataSource). * DataSource).
*/ */
protected void setUp() throws Exception { protected void setUp() throws Exception
con = JDBC2Tests.openDB(); {
JDBC2Tests.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)"); con = JDBC2Tests.openDB();
Statement stmt = con.createStatement(); JDBC2Tests.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)");
stmt.executeUpdate("INSERT INTO poolingtest VALUES (1, 'Test Row 1')"); Statement stmt = con.createStatement();
stmt.executeUpdate("INSERT INTO poolingtest VALUES (2, 'Test Row 2')"); stmt.executeUpdate("INSERT INTO poolingtest VALUES (1, 'Test Row 1')");
JDBC2Tests.closeDB(con); stmt.executeUpdate("INSERT INTO poolingtest VALUES (2, 'Test Row 2')");
} JDBC2Tests.closeDB(con);
}
/** /**
* Removes the test table using a standard connection (not from * Removes the test table using a standard connection (not from
* a DataSource) * a DataSource)
*/ */
protected void tearDown() throws Exception { protected void tearDown() throws Exception
con = JDBC2Tests.openDB(); {
JDBC2Tests.dropTable(con, "poolingtest"); con = JDBC2Tests.openDB();
JDBC2Tests.closeDB(con); JDBC2Tests.dropTable(con, "poolingtest");
} JDBC2Tests.closeDB(con);
}
/** /**
* Gets a connection from the current BaseDataSource * Gets a connection from the current BaseDataSource
*/ */
protected Connection getDataSourceConnection() throws SQLException { protected Connection getDataSourceConnection() throws SQLException
initializeDataSource(); {
return bds.getConnection(); initializeDataSource();
} return bds.getConnection();
}
/** /**
* Creates an instance of the current BaseDataSource for * Creates an instance of the current BaseDataSource for
* testing. Must be customized by each subclass. * testing. Must be customized by each subclass.
*/ */
protected abstract void initializeDataSource(); protected abstract void initializeDataSource();
/** /**
* Test to make sure you can instantiate and configure the * Test to make sure you can instantiate and configure the
* appropriate DataSource * appropriate DataSource
*/ */
public void testCreateDataSource() { public void testCreateDataSource()
initializeDataSource(); {
} initializeDataSource();
}
/** /**
* Test to make sure you can get a connection from the DataSource, * Test to make sure you can get a connection from the DataSource,
* which in turn means the DataSource was able to open it. * which in turn means the DataSource was able to open it.
*/ */
public void testGetConnection() { public void testGetConnection()
try { {
con = getDataSourceConnection(); try
con.close(); {
} catch (SQLException e) { con = getDataSourceConnection();
fail(e.getMessage()); con.close();
} }
} catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* A simple test to make sure you can execute SQL using the * A simple test to make sure you can execute SQL using the
* Connection from the DataSource * Connection from the DataSource
*/ */
public void testUseConnection() { public void testUseConnection()
try { {
con = getDataSourceConnection(); try
Statement st = con.createStatement(); {
ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM poolingtest"); con = getDataSourceConnection();
if(rs.next()) { Statement st = con.createStatement();
int count = rs.getInt(1); ResultSet rs = st.executeQuery("SELECT COUNT(*) FROM poolingtest");
if(rs.next()) { if (rs.next())
fail("Should only have one row in SELECT COUNT result set"); {
} int count = rs.getInt(1);
if(count != 2) { if (rs.next())
fail("Count returned "+count+" expecting 2"); {
} fail("Should only have one row in SELECT COUNT result set");
} else { }
fail("Should have one row in SELECT COUNT result set"); if (count != 2)
} {
rs.close(); fail("Count returned " + count + " expecting 2");
st.close(); }
con.close(); }
} catch (SQLException e) { else
fail(e.getMessage()); {
} fail("Should have one row in SELECT COUNT result set");
} }
rs.close();
st.close();
con.close();
}
catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* A test to make sure you can execute DDL SQL using the * A test to make sure you can execute DDL SQL using the
* Connection from the DataSource. * Connection from the DataSource.
*/ */
public void testDdlOverConnection() { public void testDdlOverConnection()
try { {
con = getDataSourceConnection(); try
JDBC2Tests.dropTable(con, "poolingtest"); {
JDBC2Tests.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)"); con = getDataSourceConnection();
con.close(); JDBC2Tests.dropTable(con, "poolingtest");
} catch (SQLException e) { JDBC2Tests.createTable(con, "poolingtest", "id int4 not null primary key, name varchar(50)");
fail(e.getMessage()); con.close();
} }
} catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* A test to make sure the connections are not being pooled by the * A test to make sure the connections are not being pooled by the
* current DataSource. Obviously need to be overridden in the case * current DataSource. Obviously need to be overridden in the case
* of a pooling Datasource. * of a pooling Datasource.
*/ */
public void testNotPooledConnection() { public void testNotPooledConnection()
try { {
con = getDataSourceConnection(); try
String name = con.toString(); {
con.close(); con = getDataSourceConnection();
con = getDataSourceConnection(); String name = con.toString();
String name2 = con.toString(); con.close();
con.close(); con = getDataSourceConnection();
assertTrue(!name.equals(name2)); String name2 = con.toString();
} catch (SQLException e) { con.close();
fail(e.getMessage()); assertTrue(!name.equals(name2));
} }
} catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* Eventually, we must test stuffing the DataSource in JNDI and * Eventually, we must test stuffing the DataSource in JNDI and
* then getting it back out and make sure it's still usable. This * then getting it back out and make sure it's still usable. This
* should ideally test both Serializable and Referenceable * should ideally test both Serializable and Referenceable
* mechanisms. Will probably be multiple tests when implemented. * mechanisms. Will probably be multiple tests when implemented.
*/ */
public void testJndi() { public void testJndi()
// TODO: Put the DS in JNDI, retrieve it, and try some of this stuff again {
} // TODO: Put the DS in JNDI, retrieve it, and try some of this stuff again
}
} }

View File

@ -11,317 +11,382 @@ import java.sql.*;
* interface to the PooledConnection is through the CPDS. * interface to the PooledConnection is through the CPDS.
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public class ConnectionPoolTest extends BaseDataSourceTest { public class ConnectionPoolTest extends BaseDataSourceTest
/** {
* Constructor required by JUnit /**
*/ * Constructor required by JUnit
public ConnectionPoolTest(String name) { */
super(name); public ConnectionPoolTest(String name)
} {
super(name);
}
/** /**
* Creates and configures a ConnectionPool * Creates and configures a ConnectionPool
*/ */
protected void initializeDataSource() { protected void initializeDataSource()
if(bds == null) { {
bds = new ConnectionPool(); if (bds == null)
String db = JDBC2Tests.getURL(); {
if(db.indexOf('/') > -1) { bds = new ConnectionPool();
db = db.substring(db.lastIndexOf('/')+1); String db = JDBC2Tests.getURL();
} else if(db.indexOf(':') > -1) { if (db.indexOf('/') > -1)
db = db.substring(db.lastIndexOf(':')+1); {
} db = db.substring(db.lastIndexOf('/') + 1);
bds.setDatabaseName(db); }
bds.setUser(JDBC2Tests.getUser()); else if (db.indexOf(':') > -1)
bds.setPassword(JDBC2Tests.getPassword()); {
} db = db.substring(db.lastIndexOf(':') + 1);
} }
bds.setDatabaseName(db);
bds.setUser(JDBC2Tests.getUser());
bds.setPassword(JDBC2Tests.getPassword());
}
}
/** /**
* Though the normal client interface is to grab a Connection, in * Though the normal client interface is to grab a Connection, in
* order to test the middleware/server interface, we need to deal * order to test the middleware/server interface, we need to deal
* with PooledConnections. Some tests use each. * with PooledConnections. Some tests use each.
*/ */
protected PooledConnection getPooledConnection() throws SQLException { protected PooledConnection getPooledConnection() throws SQLException
initializeDataSource(); {
return ((ConnectionPool)bds).getPooledConnection(); initializeDataSource();
} return ((ConnectionPool)bds).getPooledConnection();
}
/** /**
* Instead of just fetching a Connection from the ConnectionPool, * Instead of just fetching a Connection from the ConnectionPool,
* get a PooledConnection, add a listener to close it when the * get a PooledConnection, add a listener to close it when the
* Connection is closed, and then get the Connection. Without * Connection is closed, and then get the Connection. Without
* the listener the PooledConnection (and thus the physical connection) * the listener the PooledConnection (and thus the physical connection)
* would never by closed. Probably not a disaster during testing, but * would never by closed. Probably not a disaster during testing, but
* you never know. * you never know.
*/ */
protected Connection getDataSourceConnection() throws SQLException { protected Connection getDataSourceConnection() throws SQLException
initializeDataSource(); {
final PooledConnection pc = getPooledConnection(); initializeDataSource();
// Since the pooled connection won't be reused in these basic tests, close it when the connection is closed final PooledConnection pc = getPooledConnection();
pc.addConnectionEventListener(new ConnectionEventListener() { // Since the pooled connection won't be reused in these basic tests, close it when the connection is closed
public void connectionClosed(ConnectionEvent event) { pc.addConnectionEventListener(new ConnectionEventListener()
try { {
pc.close(); public void connectionClosed(ConnectionEvent event)
} catch (SQLException e) { {
fail("Unable to close PooledConnection: "+e); try
} {
} pc.close();
}
catch (SQLException e)
{
fail("Unable to close PooledConnection: " + e);
}
}
public void connectionErrorOccurred(ConnectionEvent event) { public void connectionErrorOccurred(ConnectionEvent event)
} {}
}); }
return pc.getConnection(); );
} return pc.getConnection();
}
/** /**
* Makes sure that if you get a connection from a PooledConnection, * Makes sure that if you get a connection from a PooledConnection,
* close it, and then get another one, you're really using the same * close it, and then get another one, you're really using the same
* physical connection. Depends on the implementation of toString * physical connection. Depends on the implementation of toString
* for the connection handle. * for the connection handle.
*/ */
public void testPoolReuse() { public void testPoolReuse()
try { {
PooledConnection pc = getPooledConnection(); try
con = pc.getConnection(); {
String name = con.toString(); PooledConnection pc = getPooledConnection();
con.close(); con = pc.getConnection();
con = pc.getConnection(); String name = con.toString();
String name2 = con.toString(); con.close();
con.close(); con = pc.getConnection();
pc.close(); String name2 = con.toString();
assertTrue("Physical connection doesn't appear to be reused across PooledConnection wrappers", name.equals(name2)); con.close();
} catch (SQLException e) { pc.close();
fail(e.getMessage()); assertTrue("Physical connection doesn't appear to be reused across PooledConnection wrappers", name.equals(name2));
} }
} catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* Makes sure that when you request a connection from the * Makes sure that when you request a connection from the
* PooledConnection, and previous connection it might have given * PooledConnection, and previous connection it might have given
* out is closed. See JDBC 2.0 Optional Package spec section * out is closed. See JDBC 2.0 Optional Package spec section
* 6.2.3 * 6.2.3
*/ */
public void testPoolCloseOldWrapper() { public void testPoolCloseOldWrapper()
try { {
PooledConnection pc = getPooledConnection(); try
con = pc.getConnection(); {
Connection con2 = pc.getConnection(); PooledConnection pc = getPooledConnection();
try { con = pc.getConnection();
con.createStatement(); Connection con2 = pc.getConnection();
fail("Original connection wrapper should be closed when new connection wrapper is generated"); try
} catch(SQLException e) {} {
try { con.createStatement();
con.close(); fail("Original connection wrapper should be closed when new connection wrapper is generated");
fail("Original connection wrapper should be closed when new connection wrapper is generated"); }
} catch(SQLException e) {} catch (SQLException e)
con2.close(); {}
pc.close(); try
} catch (SQLException e) { {
fail(e.getMessage()); con.close();
} fail("Original connection wrapper should be closed when new connection wrapper is generated");
} }
catch (SQLException e)
{}
con2.close();
pc.close();
}
catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* Makes sure that if you get two connection wrappers from the same * Makes sure that if you get two connection wrappers from the same
* PooledConnection, they are different, even though the represent * PooledConnection, they are different, even though the represent
* the same physical connection. See JDBC 2.0 Optional Pacakge spec * the same physical connection. See JDBC 2.0 Optional Pacakge spec
* section 6.2.2 * section 6.2.2
*/ */
public void testPoolNewWrapper() { public void testPoolNewWrapper()
try { {
PooledConnection pc = getPooledConnection(); try
con = pc.getConnection(); {
Connection con2 = pc.getConnection(); PooledConnection pc = getPooledConnection();
con2.close(); con = pc.getConnection();
pc.close(); Connection con2 = pc.getConnection();
assertTrue("Two calls to PooledConnection.getConnection should not return the same connection wrapper", con != con2); con2.close();
} catch (SQLException e) { pc.close();
fail(e.getMessage()); assertTrue("Two calls to PooledConnection.getConnection should not return the same connection wrapper", con != con2);
} }
} catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* Makes sure that exactly one close event is fired for each time a * Makes sure that exactly one close event is fired for each time a
* connection handle is closed. Also checks that events are not * connection handle is closed. Also checks that events are not
* fired after a given handle has been closed once. * fired after a given handle has been closed once.
*/ */
public void testCloseEvent() { public void testCloseEvent()
try { {
PooledConnection pc = getPooledConnection(); try
CountClose cc = new CountClose(); {
pc.addConnectionEventListener(cc); PooledConnection pc = getPooledConnection();
con = pc.getConnection(); CountClose cc = new CountClose();
assertTrue(cc.getCount() == 0); pc.addConnectionEventListener(cc);
assertTrue(cc.getErrorCount() == 0); con = pc.getConnection();
con.close(); assertTrue(cc.getCount() == 0);
assertTrue(cc.getCount() == 1); assertTrue(cc.getErrorCount() == 0);
assertTrue(cc.getErrorCount() == 0); con.close();
con = pc.getConnection(); assertTrue(cc.getCount() == 1);
assertTrue(cc.getCount() == 1); assertTrue(cc.getErrorCount() == 0);
assertTrue(cc.getErrorCount() == 0); con = pc.getConnection();
con.close(); assertTrue(cc.getCount() == 1);
assertTrue(cc.getCount() == 2); assertTrue(cc.getErrorCount() == 0);
assertTrue(cc.getErrorCount() == 0); con.close();
try { assertTrue(cc.getCount() == 2);
con.close(); assertTrue(cc.getErrorCount() == 0);
fail("Should not be able to close a connection wrapper twice"); try
} catch (SQLException e) {} {
assertTrue(cc.getCount() == 2); con.close();
assertTrue(cc.getErrorCount() == 0); fail("Should not be able to close a connection wrapper twice");
pc.close(); }
} catch (SQLException e) { catch (SQLException e)
fail(e.getMessage()); {}
} assertTrue(cc.getCount() == 2);
} assertTrue(cc.getErrorCount() == 0);
pc.close();
}
catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* Makes sure that close events are not fired after a listener has * Makes sure that close events are not fired after a listener has
* been removed. * been removed.
*/ */
public void testNoCloseEvent() { public void testNoCloseEvent()
try { {
PooledConnection pc = getPooledConnection(); try
CountClose cc = new CountClose(); {
pc.addConnectionEventListener(cc); PooledConnection pc = getPooledConnection();
con = pc.getConnection(); CountClose cc = new CountClose();
assertTrue(cc.getCount() == 0); pc.addConnectionEventListener(cc);
assertTrue(cc.getErrorCount() == 0); con = pc.getConnection();
con.close(); assertTrue(cc.getCount() == 0);
assertTrue(cc.getCount() == 1); assertTrue(cc.getErrorCount() == 0);
assertTrue(cc.getErrorCount() == 0); con.close();
pc.removeConnectionEventListener(cc); assertTrue(cc.getCount() == 1);
con = pc.getConnection(); assertTrue(cc.getErrorCount() == 0);
assertTrue(cc.getCount() == 1); pc.removeConnectionEventListener(cc);
assertTrue(cc.getErrorCount() == 0); con = pc.getConnection();
con.close(); assertTrue(cc.getCount() == 1);
assertTrue(cc.getCount() == 1); assertTrue(cc.getErrorCount() == 0);
assertTrue(cc.getErrorCount() == 0); con.close();
} catch (SQLException e) { assertTrue(cc.getCount() == 1);
fail(e.getMessage()); assertTrue(cc.getErrorCount() == 0);
} }
} catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* Makes sure that a listener can be removed while dispatching * Makes sure that a listener can be removed while dispatching
* events. Sometimes this causes a ConcurrentModificationException * events. Sometimes this causes a ConcurrentModificationException
* or something. * or something.
*/ */
public void testInlineCloseEvent() { public void testInlineCloseEvent()
try { {
PooledConnection pc = getPooledConnection(); try
RemoveClose rc1 = new RemoveClose(); {
RemoveClose rc2 = new RemoveClose(); PooledConnection pc = getPooledConnection();
RemoveClose rc3 = new RemoveClose(); RemoveClose rc1 = new RemoveClose();
pc.addConnectionEventListener(rc1); RemoveClose rc2 = new RemoveClose();
pc.addConnectionEventListener(rc2); RemoveClose rc3 = new RemoveClose();
pc.addConnectionEventListener(rc3); pc.addConnectionEventListener(rc1);
con = pc.getConnection(); pc.addConnectionEventListener(rc2);
con.close(); pc.addConnectionEventListener(rc3);
con = pc.getConnection(); con = pc.getConnection();
con.close(); con.close();
} catch (Exception e) { con = pc.getConnection();
fail(e.getMessage()); con.close();
} }
} catch (Exception e)
{
fail(e.getMessage());
}
}
/** /**
* Tests that a close event is not generated when a connection * Tests that a close event is not generated when a connection
* handle is closed automatically due to a new connection handle * handle is closed automatically due to a new connection handle
* being opened for the same PooledConnection. See JDBC 2.0 * being opened for the same PooledConnection. See JDBC 2.0
* Optional Package spec section 6.3 * Optional Package spec section 6.3
*/ */
public void testAutomaticCloseEvent() { public void testAutomaticCloseEvent()
try { {
PooledConnection pc = getPooledConnection(); try
CountClose cc = new CountClose(); {
pc.addConnectionEventListener(cc); PooledConnection pc = getPooledConnection();
con = pc.getConnection(); CountClose cc = new CountClose();
assertTrue(cc.getCount() == 0); pc.addConnectionEventListener(cc);
assertTrue(cc.getErrorCount() == 0); con = pc.getConnection();
con.close(); assertTrue(cc.getCount() == 0);
assertTrue(cc.getCount() == 1); assertTrue(cc.getErrorCount() == 0);
assertTrue(cc.getErrorCount() == 0); con.close();
con = pc.getConnection(); assertTrue(cc.getCount() == 1);
assertTrue(cc.getCount() == 1); assertTrue(cc.getErrorCount() == 0);
assertTrue(cc.getErrorCount() == 0); con = pc.getConnection();
// Open a 2nd connection, causing the first to be closed. No even should be generated. assertTrue(cc.getCount() == 1);
Connection con2 = pc.getConnection(); assertTrue(cc.getErrorCount() == 0);
assertTrue("Connection handle was not closed when new handle was opened", con.isClosed()); // Open a 2nd connection, causing the first to be closed. No even should be generated.
assertTrue(cc.getCount() == 1); Connection con2 = pc.getConnection();
assertTrue(cc.getErrorCount() == 0); assertTrue("Connection handle was not closed when new handle was opened", con.isClosed());
con2.close(); assertTrue(cc.getCount() == 1);
assertTrue(cc.getCount() == 2); assertTrue(cc.getErrorCount() == 0);
assertTrue(cc.getErrorCount() == 0); con2.close();
pc.close(); assertTrue(cc.getCount() == 2);
} catch (SQLException e) { assertTrue(cc.getErrorCount() == 0);
fail(e.getMessage()); pc.close();
} }
} catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* Makes sure the isClosed method on a connection wrapper does what * Makes sure the isClosed method on a connection wrapper does what
* you'd expect. Checks the usual case, as well as automatic * you'd expect. Checks the usual case, as well as automatic
* closure when a new handle is opened on the same physical connection. * closure when a new handle is opened on the same physical connection.
*/ */
public void testIsClosed() { public void testIsClosed()
try { {
PooledConnection pc = getPooledConnection(); try
Connection con = pc.getConnection(); {
assertTrue(!con.isClosed()); PooledConnection pc = getPooledConnection();
con.close(); Connection con = pc.getConnection();
assertTrue(con.isClosed()); assertTrue(!con.isClosed());
con = pc.getConnection(); con.close();
Connection con2 = pc.getConnection(); assertTrue(con.isClosed());
assertTrue(con.isClosed()); con = pc.getConnection();
assertTrue(!con2.isClosed()); Connection con2 = pc.getConnection();
con2.close(); assertTrue(con.isClosed());
assertTrue(con.isClosed()); assertTrue(!con2.isClosed());
pc.close(); con2.close();
} catch (SQLException e) { assertTrue(con.isClosed());
fail(e.getMessage()); pc.close();
} }
} catch (SQLException e)
{
fail(e.getMessage());
}
}
/** /**
* Helper class to remove a listener during event dispatching. * Helper class to remove a listener during event dispatching.
*/ */
private class RemoveClose implements ConnectionEventListener { private class RemoveClose implements ConnectionEventListener
public void connectionClosed(ConnectionEvent event) { {
((PooledConnection)event.getSource()).removeConnectionEventListener(this); public void connectionClosed(ConnectionEvent event)
} {
((PooledConnection)event.getSource()).removeConnectionEventListener(this);
}
public void connectionErrorOccurred(ConnectionEvent event) { public void connectionErrorOccurred(ConnectionEvent event)
((PooledConnection)event.getSource()).removeConnectionEventListener(this); {
} ((PooledConnection)event.getSource()).removeConnectionEventListener(this);
} }
}
/** /**
* Helper class that implements the event listener interface, and * Helper class that implements the event listener interface, and
* counts the number of events it sees. * counts the number of events it sees.
*/ */
private class CountClose implements ConnectionEventListener { private class CountClose implements ConnectionEventListener
private int count = 0, errorCount = 0; {
public void connectionClosed(ConnectionEvent event) { private int count = 0, errorCount = 0;
count++; public void connectionClosed(ConnectionEvent event)
} {
count++;
}
public void connectionErrorOccurred(ConnectionEvent event) { public void connectionErrorOccurred(ConnectionEvent event)
errorCount++; {
} errorCount++;
}
public int getCount() { public int getCount()
return count; {
} return count;
}
public int getErrorCount() { public int getErrorCount()
return errorCount; {
} return errorCount;
}
public void clear() { public void clear()
count = errorCount = 0; {
} count = errorCount = 0;
} }
}
} }

View File

@ -8,17 +8,19 @@ import junit.framework.TestSuite;
* PooledConnection implementations. * PooledConnection implementations.
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public class OptionalTestSuite extends TestSuite { public class OptionalTestSuite extends TestSuite
/** {
* Gets the test suite for the entire JDBC 2.0 Optional Package /**
* implementation. * Gets the test suite for the entire JDBC 2.0 Optional Package
*/ * implementation.
public static TestSuite suite() { */
TestSuite suite = new TestSuite(); public static TestSuite suite()
suite.addTestSuite(SimpleDataSourceTest.class); {
suite.addTestSuite(ConnectionPoolTest.class); TestSuite suite = new TestSuite();
return suite; suite.addTestSuite(SimpleDataSourceTest.class);
} suite.addTestSuite(ConnectionPoolTest.class);
return suite;
}
} }

View File

@ -4,35 +4,42 @@ import org.postgresql.test.JDBC2Tests;
import org.postgresql.jdbc2.optional.SimpleDataSource; import org.postgresql.jdbc2.optional.SimpleDataSource;
/** /**
* Performs the basic tests defined in the superclass. Just adds the * Performs the basic tests defined in the superclass. Just adds the
* configuration logic. * configuration logic.
* *
* @author Aaron Mulder (ammulder@chariotsolutions.com) * @author Aaron Mulder (ammulder@chariotsolutions.com)
* @version $Revision: 1.1 $ * @version $Revision: 1.2 $
*/ */
public class SimpleDataSourceTest extends BaseDataSourceTest { public class SimpleDataSourceTest extends BaseDataSourceTest
/** {
* Constructor required by JUnit /**
*/ * Constructor required by JUnit
public SimpleDataSourceTest(String name) { */
super(name); public SimpleDataSourceTest(String name)
} {
super(name);
}
/** /**
* Creates and configures a new SimpleDataSource. * Creates and configures a new SimpleDataSource.
*/ */
protected void initializeDataSource() { protected void initializeDataSource()
if(bds == null) { {
bds = new SimpleDataSource(); if (bds == null)
String db = JDBC2Tests.getURL(); {
if(db.indexOf('/') > -1) { bds = new SimpleDataSource();
db = db.substring(db.lastIndexOf('/')+1); String db = JDBC2Tests.getURL();
} else if(db.indexOf(':') > -1) { if (db.indexOf('/') > -1)
db = db.substring(db.lastIndexOf(':')+1); {
} db = db.substring(db.lastIndexOf('/') + 1);
bds.setDatabaseName(db); }
bds.setUser(JDBC2Tests.getUser()); else if (db.indexOf(':') > -1)
bds.setPassword(JDBC2Tests.getPassword()); {
} db = db.substring(db.lastIndexOf(':') + 1);
} }
bds.setDatabaseName(db);
bds.setUser(JDBC2Tests.getUser());
bds.setPassword(JDBC2Tests.getPassword());
}
}
} }

View File

@ -7,7 +7,7 @@ import junit.framework.Test;
import java.sql.*; import java.sql.*;
/* /*
* Executes all known tests for JDBC3 * Executes all known tests for JDBC3
*/ */
public class Jdbc3TestSuite extends TestSuite public class Jdbc3TestSuite extends TestSuite
{ {
@ -17,7 +17,7 @@ public class Jdbc3TestSuite extends TestSuite
*/ */
public static TestSuite suite() public static TestSuite suite()
{ {
//Currently there are no specific jdbc3 tests so just run the jdbc2 tests //Currently there are no specific jdbc3 tests so just run the jdbc2 tests
return org.postgresql.test.jdbc2.Jdbc2TestSuite.suite(); return org.postgresql.test.jdbc2.Jdbc2TestSuite.suite();
} }
} }

View File

@ -5,7 +5,7 @@ import java.sql.*;
/* /*
* Converts to and from the postgresql bytea datatype used by the backend. * Converts to and from the postgresql bytea datatype used by the backend.
* *
* $Id: PGbytea.java,v 1.5 2002/08/16 17:51:38 barry Exp $ * $Id: PGbytea.java,v 1.6 2002/09/06 21:23:06 momjian Exp $
*/ */
public class PGbytea public class PGbytea
@ -19,7 +19,7 @@ public class PGbytea
{ {
if (s == null) if (s == null)
return null; return null;
int slength = s.length; int slength = s.length;
byte[] buf = new byte[slength]; byte[] buf = new byte[slength];
int bufpos = 0; int bufpos = 0;
int thebyte; int thebyte;

View File

@ -78,6 +78,7 @@ public class PGtokenizer
// Don't forget the last token ;-) // Don't forget the last token ;-)
if (s < string.length()) if (s < string.length())
tokens.addElement(string.substring(s)); tokens.addElement(string.substring(s));

View File

@ -129,14 +129,16 @@ public class Serialize
try try
{ {
conn = c; conn = c;
if (Driver.logDebug) Driver.debug("Serialize: initializing instance for type: " + type); if (Driver.logDebug)
Driver.debug("Serialize: initializing instance for type: " + type);
tableName = toPostgreSQL(type); tableName = toPostgreSQL(type);
className = type; className = type;
ourClass = Class.forName(className); ourClass = Class.forName(className);
} }
catch (ClassNotFoundException cnfe) catch (ClassNotFoundException cnfe)
{ {
if (Driver.logDebug) Driver.debug("Serialize: " + className + " java class not found"); if (Driver.logDebug)
Driver.debug("Serialize: " + className + " java class not found");
throw new PSQLException("postgresql.serial.noclass", type); throw new PSQLException("postgresql.serial.noclass", type);
} }
@ -148,14 +150,16 @@ public class Serialize
if (rs.next()) if (rs.next())
{ {
status = true; status = true;
if (Driver.logDebug) Driver.debug("Serialize: " + tableName + " table found"); if (Driver.logDebug)
Driver.debug("Serialize: " + tableName + " table found");
} }
rs.close(); rs.close();
} }
// This should never occur, as org.postgresql has it's own internal checks // This should never occur, as org.postgresql has it's own internal checks
if (!status) if (!status)
{ {
if (Driver.logDebug) Driver.debug("Serialize: " + tableName + " table not found"); if (Driver.logDebug)
Driver.debug("Serialize: " + tableName + " table not found");
throw new PSQLException("postgresql.serial.table", type); throw new PSQLException("postgresql.serial.table", type);
} }
// Finally cache the fields within the table // Finally cache the fields within the table
@ -187,9 +191,11 @@ public class Serialize
{ {
try try
{ {
if (Driver.logDebug) Driver.debug("Serialize.fetch: " + "attempting to instantiate object of type: " + ourClass.getName() ); if (Driver.logDebug)
Driver.debug("Serialize.fetch: " + "attempting to instantiate object of type: " + ourClass.getName() );
Object obj = ourClass.newInstance(); Object obj = ourClass.newInstance();
if (Driver.logDebug) Driver.debug("Serialize.fetch: " + "instantiated object of type: " + ourClass.getName() ); if (Driver.logDebug)
Driver.debug("Serialize.fetch: " + "instantiated object of type: " + ourClass.getName() );
// NB: we use java.lang.reflect here to prevent confusion with // NB: we use java.lang.reflect here to prevent confusion with
// the org.postgresql.Field // the org.postgresql.Field
@ -220,7 +226,8 @@ public class Serialize
sb.append(" where oid="); sb.append(" where oid=");
sb.append(oid); sb.append(oid);
if (Driver.logDebug) Driver.debug("Serialize.fetch: " + sb.toString()); if (Driver.logDebug)
Driver.debug("Serialize.fetch: " + sb.toString());
ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).ExecSQL(sb.toString()); ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).ExecSQL(sb.toString());
if (rs != null) if (rs != null)
@ -270,13 +277,13 @@ public class Serialize
/* /*
* This stores an object into a table, returning it's OID.<p> * This stores an object into a table, returning it's OID.<p>
* This method was deprecated in 7.2 because the value of an OID * This method was deprecated in 7.2 because the value of an OID
* can be larger than a java signed int. * can be larger than a java signed int.
* @deprecated Replaced by storeObject() in 7.2 * @deprecated Replaced by storeObject() in 7.2
*/ */
public int store(Object o) throws SQLException public int store(Object o) throws SQLException
{ {
return (int) storeObject(o); return (int) storeObject(o);
} }
/* /*
@ -296,7 +303,7 @@ public class Serialize
* @param o Object to store (must implement Serializable) * @param o Object to store (must implement Serializable)
* @return oid of stored object * @return oid of stored object
* @exception SQLException on error * @exception SQLException on error
* @since 7.2 * @since 7.2
*/ */
public long storeObject(Object o) throws SQLException public long storeObject(Object o) throws SQLException
{ {
@ -389,7 +396,8 @@ public class Serialize
sb.append(')'); sb.append(')');
} }
if (Driver.logDebug) Driver.debug("Serialize.store: " + sb.toString() ); if (Driver.logDebug)
Driver.debug("Serialize.store: " + sb.toString() );
ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).ExecSQL(sb.toString()); ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)conn).ExecSQL(sb.toString());
// fetch the OID for returning // fetch the OID for returning
@ -496,13 +504,15 @@ public class Serialize
ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)con).ExecSQL("select relname from pg_class where relname = '" + tableName + "'"); ResultSet rs = ((org.postgresql.jdbc1.AbstractJdbc1Connection)con).ExecSQL("select relname from pg_class where relname = '" + tableName + "'");
if ( rs.next() ) if ( rs.next() )
{ {
if (Driver.logDebug) Driver.debug("Serialize.create: table " + tableName + " exists, skipping"); if (Driver.logDebug)
Driver.debug("Serialize.create: table " + tableName + " exists, skipping");
rs.close(); rs.close();
return; return ;
} }
// else table not found, so create it // else table not found, so create it
if (Driver.logDebug) Driver.debug("Serialize.create: table " + tableName + " not found, creating" ); if (Driver.logDebug)
Driver.debug("Serialize.create: table " + tableName + " not found, creating" );
// No entries returned, so the table doesn't exist // No entries returned, so the table doesn't exist
StringBuffer sb = new StringBuffer("create table "); StringBuffer sb = new StringBuffer("create table ");
@ -548,7 +558,8 @@ public class Serialize
sb.append(")"); sb.append(")");
// Now create the table // Now create the table
if (Driver.logDebug) Driver.debug("Serialize.create: " + sb ); if (Driver.logDebug)
Driver.debug("Serialize.create: " + sb );
((org.postgresql.jdbc1.AbstractJdbc1Connection)con).ExecSQL(sb.toString()); ((org.postgresql.jdbc1.AbstractJdbc1Connection)con).ExecSQL(sb.toString());
} }