summaryrefslogtreecommitdiff
path: root/src/interfaces/jdbc/org/postgresql
diff options
context:
space:
mode:
Diffstat (limited to 'src/interfaces/jdbc/org/postgresql')
-rw-r--r--src/interfaces/jdbc/org/postgresql/Connection.java33
-rw-r--r--src/interfaces/jdbc/org/postgresql/Driver.java.in (renamed from src/interfaces/jdbc/org/postgresql/Driver.java)20
-rw-r--r--src/interfaces/jdbc/org/postgresql/PG_Stream.java206
-rw-r--r--src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java585
-rw-r--r--src/interfaces/jdbc/org/postgresql/errors.properties1
-rw-r--r--src/interfaces/jdbc/org/postgresql/errors_it.properties74
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java8
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java10
-rw-r--r--src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java5
9 files changed, 901 insertions, 41 deletions
diff --git a/src/interfaces/jdbc/org/postgresql/Connection.java b/src/interfaces/jdbc/org/postgresql/Connection.java
index f04f7fffe6b..e4c3537df77 100644
--- a/src/interfaces/jdbc/org/postgresql/Connection.java
+++ b/src/interfaces/jdbc/org/postgresql/Connection.java
@@ -10,7 +10,7 @@ import org.postgresql.largeobject.*;
import org.postgresql.util.*;
/**
- * $Id: Connection.java,v 1.8 2000/10/09 16:48:16 momjian Exp $
+ * $Id: Connection.java,v 1.9 2000/10/12 08:55:24 peter Exp $
*
* This abstract class is used by org.postgresql.Driver to open either the JDBC1 or
* JDBC2 versions of the Connection class.
@@ -81,6 +81,11 @@ public abstract class Connection
// The PID an cancellation key we get from the backend process
public int pid;
public int ckey;
+
+ // This receive_sbuf should be used by the different methods
+ // that call pg_stream.ReceiveString() in this Connection, so
+ // so we avoid uneccesary new allocations.
+ byte receive_sbuf[] = new byte[8192];
/**
* This is called by Class.forName() from within org.postgresql.Driver
@@ -165,7 +170,7 @@ public abstract class Connection
// "User authentication failed"
//
throw new SQLException(pg_stream.ReceiveString
- (4096, getEncoding()));
+ (receive_sbuf, 4096, getEncoding()));
case 'R':
// Get the type of request
@@ -236,7 +241,7 @@ public abstract class Connection
case 'E':
case 'N':
throw new SQLException(pg_stream.ReceiveString
- (4096, getEncoding()));
+ (receive_sbuf, 4096, getEncoding()));
default:
throw new PSQLException("postgresql.con.setup");
}
@@ -248,7 +253,7 @@ public abstract class Connection
break;
case 'E':
case 'N':
- throw new SQLException(pg_stream.ReceiveString(4096));
+ throw new SQLException(pg_stream.ReceiveString(receive_sbuf, 4096, getEncoding()));
default:
throw new PSQLException("postgresql.con.setup");
}
@@ -322,6 +327,12 @@ public abstract class Connection
{
// added Oct 7 1998 to give us thread safety.
synchronized(pg_stream) {
+ // Deallocate all resources in the stream associated
+ // with a previous request.
+ // This will let the driver reuse byte arrays that has already
+ // been allocated instead of allocating new ones in order
+ // to gain performance improvements.
+ pg_stream.deallocate();
Field[] fields = null;
Vector tuples = new Vector();
@@ -353,7 +364,7 @@ public abstract class Connection
{
pg_stream.SendChar('Q');
buf = sql.getBytes();
- pg_stream.Send(buf);
+ pg_stream.Send(sql.getBytes());
pg_stream.SendChar(0);
pg_stream.flush();
} catch (IOException e) {
@@ -370,7 +381,7 @@ public abstract class Connection
{
case 'A': // Asynchronous Notify
pid = pg_stream.ReceiveInteger(4);
- msg = pg_stream.ReceiveString(8192);
+ msg = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
break;
case 'B': // Binary Data Transfer
if (fields == null)
@@ -381,7 +392,7 @@ public abstract class Connection
tuples.addElement(tup);
break;
case 'C': // Command Status
- recv_status = pg_stream.ReceiveString(8192);
+ recv_status = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
// Now handle the update count correctly.
if(recv_status.startsWith("INSERT") || recv_status.startsWith("UPDATE") || recv_status.startsWith("DELETE")) {
@@ -423,7 +434,7 @@ public abstract class Connection
tuples.addElement(tup);
break;
case 'E': // Error Message
- msg = pg_stream.ReceiveString(4096);
+ msg = pg_stream.ReceiveString(receive_sbuf,4096,getEncoding());
final_error = new SQLException(msg);
hfr = true;
break;
@@ -438,10 +449,10 @@ public abstract class Connection
hfr = true;
break;
case 'N': // Error Notification
- addWarning(pg_stream.ReceiveString(4096));
+ addWarning(pg_stream.ReceiveString(receive_sbuf,4096,getEncoding()));
break;
case 'P': // Portal Name
- String pname = pg_stream.ReceiveString(8192);
+ String pname = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
break;
case 'T': // MetaData Field Description
if (fields != null)
@@ -474,7 +485,7 @@ public abstract class Connection
for (i = 0 ; i < nf ; ++i)
{
- String typname = pg_stream.ReceiveString(8192);
+ String typname = pg_stream.ReceiveString(receive_sbuf,8192,getEncoding());
int typid = pg_stream.ReceiveIntegerR(4);
int typlen = pg_stream.ReceiveIntegerR(2);
int typmod = pg_stream.ReceiveIntegerR(4);
diff --git a/src/interfaces/jdbc/org/postgresql/Driver.java b/src/interfaces/jdbc/org/postgresql/Driver.java.in
index 849bb71d54d..40e2a94956a 100644
--- a/src/interfaces/jdbc/org/postgresql/Driver.java
+++ b/src/interfaces/jdbc/org/postgresql/Driver.java.in
@@ -26,10 +26,6 @@ import org.postgresql.util.PSQLException;
*/
public class Driver implements java.sql.Driver
{
- // These should be in sync with the backend that the driver was
- // distributed with
- static final int MAJORVERSION = 7;
- static final int MINORVERSION = 0;
static
{
@@ -117,10 +113,8 @@ public class Driver implements java.sql.Driver
if((props = parseURL(url,info))==null)
return null;
- DriverManager.println("Using "+DriverClass.connectClass);
-
try {
- org.postgresql.Connection con = (org.postgresql.Connection)(Class.forName(DriverClass.connectClass).newInstance());
+ org.postgresql.Connection con = (org.postgresql.Connection)(Class.forName("%JDBCCONNECTCLASS%").newInstance());
con.openConnection (host(), port(), props, database(), url, this);
return (java.sql.Connection)con;
} catch(ClassNotFoundException ex) {
@@ -198,7 +192,7 @@ public class Driver implements java.sql.Driver
*/
public int getMajorVersion()
{
- return MAJORVERSION;
+ return %MAJORVERSION%;
}
/**
@@ -208,9 +202,17 @@ public class Driver implements java.sql.Driver
*/
public int getMinorVersion()
{
- return MINORVERSION;
+ return %MINORVERSION%;
}
+ /**
+ * Returns the VERSION variable from Makefile.global
+ */
+ public static String getVersion()
+ {
+ return "%VERSION%";
+ }
+
/**
* Report whether the driver is a genuine JDBC compliant driver. A
* driver may only report "true" here if it passes the JDBC compliance
diff --git a/src/interfaces/jdbc/org/postgresql/PG_Stream.java b/src/interfaces/jdbc/org/postgresql/PG_Stream.java
index 22c41bdb3a3..9a2b712ddae 100644
--- a/src/interfaces/jdbc/org/postgresql/PG_Stream.java
+++ b/src/interfaces/jdbc/org/postgresql/PG_Stream.java
@@ -23,6 +23,9 @@ public class PG_Stream
private InputStream pg_input;
private BufferedOutputStream pg_output;
+ BytePoolDim1 bytePoolDim1 = new BytePoolDim1();
+ BytePoolDim2 bytePoolDim2 = new BytePoolDim2();
+
/**
* Constructor: Connect to the PostgreSQL back end and return
* a stream connection.
@@ -70,7 +73,7 @@ public class PG_Stream
*/
public void SendInteger(int val, int siz) throws IOException
{
- byte[] buf = new byte[siz];
+ byte[] buf = bytePoolDim1.allocByte(siz);
while (siz-- > 0)
{
@@ -94,7 +97,7 @@ public class PG_Stream
*/
public void SendIntegerReverse(int val, int siz) throws IOException
{
- byte[] buf = new byte[siz];
+ byte[] buf = bytePoolDim1.allocByte(siz);
int p=0;
while (siz-- > 0)
{
@@ -236,15 +239,27 @@ public class PG_Stream
return n;
}
- public String ReceiveString(int maxsize) throws SQLException {
- return ReceiveString(maxsize, null);
- }
-
/**
* Receives a null-terminated string from the backend. Maximum of
* maxsiz bytes - if we don't see a null, then we assume something
* has gone wrong.
*
+ * @param maxsiz maximum length of string
+ * @return string from back end
+ * @exception SQLException if an I/O error occurs
+ */
+ public String ReceiveString(int maxsiz) throws SQLException
+ {
+ byte[] rst = bytePoolDim1.allocByte(maxsiz);
+ return ReceiveString(rst, maxsiz, null);
+ }
+
+ /**
+ * Receives a null-terminated string from the backend. Maximum of
+ * maxsiz bytes - if we don't see a null, then we assume something
+ * has gone wrong.
+ *
+ * @param maxsiz maximum length of string
* @param encoding the charset encoding to use.
* @param maxsiz maximum length of string in bytes
* @return string from back end
@@ -252,7 +267,25 @@ public class PG_Stream
*/
public String ReceiveString(int maxsiz, String encoding) throws SQLException
{
- byte[] rst = new byte[maxsiz];
+ byte[] rst = bytePoolDim1.allocByte(maxsiz);
+ return ReceiveString(rst, maxsiz, encoding);
+ }
+
+ /**
+ * Receives a null-terminated string from the backend. Maximum of
+ * maxsiz bytes - if we don't see a null, then we assume something
+ * has gone wrong.
+ *
+ * @param rst byte array to read the String into. rst.length must
+ * equal to or greater than maxsize.
+ * @param maxsiz maximum length of string in bytes
+ * @param encoding the charset encoding to use.
+ * @return string from back end
+ * @exception SQLException if an I/O error occurs
+ */
+ public String ReceiveString(byte rst[], int maxsiz, String encoding)
+ throws SQLException
+ {
int s = 0;
try
@@ -262,9 +295,10 @@ public class PG_Stream
int c = pg_input.read();
if (c < 0)
throw new PSQLException("postgresql.stream.eof");
- else if (c == 0)
- break;
- else
+ else if (c == 0) {
+ rst[s] = 0;
+ break;
+ } else
rst[s++] = (byte)c;
}
if (s >= maxsiz)
@@ -299,7 +333,7 @@ public class PG_Stream
{
int i, bim = (nf + 7)/8;
byte[] bitmask = Receive(bim);
- byte[][] answer = new byte[nf][0];
+ byte[][] answer = bytePoolDim2.allocByte(nf);
int whichbit = 0x80;
int whichbyte = 0;
@@ -337,7 +371,7 @@ public class PG_Stream
*/
private byte[] Receive(int siz) throws SQLException
{
- byte[] answer = new byte[siz];
+ byte[] answer = bytePoolDim1.allocByte(siz);
Receive(answer,0,siz);
return answer;
}
@@ -395,4 +429,152 @@ public class PG_Stream
pg_input.close();
connection.close();
}
+
+ /**
+ * Deallocate all resources that has been associated with any previous
+ * query.
+ */
+ public void deallocate(){
+ bytePoolDim1.deallocate();
+ bytePoolDim2.deallocate();
+ }
+}
+
+/**
+ * A simple and fast object pool implementation that can pool objects
+ * of any type. This implementation is not thread safe, it is up to the users
+ * of this class to assure thread safety.
+ */
+class ObjectPool {
+ int cursize = 0;
+ int maxsize = 16;
+ Object arr[] = new Object[maxsize];
+
+ public void add(Object o){
+ if(cursize >= maxsize){
+ Object newarr[] = new Object[maxsize*2];
+ System.arraycopy(arr, 0, newarr, 0, maxsize);
+ maxsize = maxsize * 2;
+ arr = newarr;
+ }
+ arr[cursize++] = o;
+ }
+
+ public Object remove(){
+ return arr[--cursize];
+ }
+ public boolean isEmpty(){
+ return cursize == 0;
+ }
+ public int size(){
+ return cursize;
+ }
+ public void addAll(ObjectPool pool){
+ int srcsize = pool.size();
+ if(srcsize == 0)
+ return;
+ int totalsize = srcsize + cursize;
+ if(totalsize > maxsize){
+ Object newarr[] = new Object[totalsize*2];
+ System.arraycopy(arr, 0, newarr, 0, cursize);
+ maxsize = maxsize = totalsize * 2;
+ arr = newarr;
+ }
+ System.arraycopy(pool.arr, 0, arr, cursize, srcsize);
+ cursize = totalsize;
+ }
+ public void clear(){
+ cursize = 0;
+ }
}
+
+/**
+ * A simple and efficient class to pool one dimensional byte arrays
+ * of different sizes.
+ */
+class BytePoolDim1 {
+ int maxsize = 256;
+ ObjectPool notusemap[] = new ObjectPool[maxsize];
+ ObjectPool inusemap[] = new ObjectPool[maxsize];
+ byte binit[][] = new byte[maxsize][0];
+
+ public BytePoolDim1(){
+ for(int i = 0; i < maxsize; i++){
+ binit[i] = new byte[i];
+ inusemap[i] = new ObjectPool();
+ notusemap[i] = new ObjectPool();
+ }
+ }
+
+ public byte[] allocByte(int size){
+ if(size > maxsize){
+ return new byte[size];
+ }
+
+ ObjectPool not_usel = notusemap[size];
+ ObjectPool in_usel = inusemap[size];
+ byte b[] = null;
+
+ if(!not_usel.isEmpty()) {
+ Object o = not_usel.remove();
+ b = (byte[]) o;
+ } else
+ b = new byte[size];
+ in_usel.add(b);
+
+ return b;
+ }
+
+ public void deallocate(){
+ for(int i = 0; i < maxsize; i++){
+ notusemap[i].addAll(inusemap[i]);
+ inusemap[i].clear();
+ }
+
+ }
+}
+
+
+
+/**
+ * A simple and efficient class to pool two dimensional byte arrays
+ * of different sizes.
+ */
+class BytePoolDim2 {
+ int maxsize = 32;
+ ObjectPool notusemap[] = new ObjectPool[maxsize];
+ ObjectPool inusemap[] = new ObjectPool[maxsize];
+
+ public BytePoolDim2(){
+ for(int i = 0; i < maxsize; i++){
+ inusemap[i] = new ObjectPool();
+ notusemap[i] = new ObjectPool();
+ }
+ }
+
+ public byte[][] allocByte(int size){
+ if(size > maxsize){
+ return new byte[size][0];
+ }
+ ObjectPool not_usel = notusemap[size];
+ ObjectPool in_usel = inusemap[size];
+
+ byte b[][] = null;
+
+ if(!not_usel.isEmpty()) {
+ Object o = not_usel.remove();
+ b = (byte[][]) o;
+ } else
+ b = new byte[size][0];
+ in_usel.add(b);
+ return b;
+ }
+
+ public void deallocate(){
+ for(int i = 0; i < maxsize; i++){
+ notusemap[i].addAll(inusemap[i]);
+ inusemap[i].clear();
+ }
+ }
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java b/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java
new file mode 100644
index 00000000000..e02d8126cc7
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/PostgresqlDataSource.java
@@ -0,0 +1,585 @@
+/**
+ * Redistribution and use of this software and associated documentation
+ * ("Software"), with or without modification, are permitted provided
+ * that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain copyright
+ * statements and notices. Redistributions must also contain a
+ * copy of this document.
+ *
+ * 2. Redistributions in binary form must reproduce the
+ * above copyright notice, this list of conditions and the
+ * following disclaimer in the documentation and/or other
+ * materials provided with the distribution.
+ *
+ * 3. The name "Exolab" must not be used to endorse or promote
+ * products derived from this Software without prior written
+ * permission of Exoffice Technologies. For written permission,
+ * please contact info@exolab.org.
+ *
+ * 4. Products derived from this Software may not be called "Exolab"
+ * nor may "Exolab" appear in their names without prior written
+ * permission of Exoffice Technologies. Exolab is a registered
+ * trademark of Exoffice Technologies.
+ *
+ * 5. Due credit should be given to the Exolab Project
+ * (http://www.exolab.org/).
+ *
+ * THIS SOFTWARE IS PROVIDED BY EXOFFICE TECHNOLOGIES AND CONTRIBUTORS
+ * ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
+ * NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * EXOFFICE TECHNOLOGIES OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Copyright 1999 (C) Exoffice Technologies Inc. All Rights Reserved.
+ *
+ * $Id: PostgresqlDataSource.java,v 1.1 2000/10/12 08:55:24 peter Exp $
+ */
+
+
+package org.postgresql;
+
+
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.util.Properties;
+import java.util.Hashtable;
+import java.sql.Connection;
+import java.sql.SQLException;
+import java.sql.DriverManager;
+import java.rmi.Remote;
+import javax.sql.DataSource;
+import javax.naming.Referenceable;
+import javax.naming.Reference;
+import javax.naming.StringRefAddr;
+import javax.naming.RefAddr;
+import javax.naming.Context;
+import javax.naming.Name;
+import javax.naming.NamingException;
+import javax.naming.spi.ObjectFactory;
+import postgresql.util.PSQLException;
+import postgresql.xa.XADataSourceImpl;
+
+
+/**
+ * Implements a JDBC 2.0 {@link javax.sql.DataSource} for the
+ * PostgreSQL driver with JNDI persistance support. XA and pooled
+ * connection support is also available, but the application must
+ * used the designated DataSource interface to obtain them.
+ * <p>
+ * The supported data source properties are:
+ * <pre>
+ * description (optional)
+ * databaseName (required)
+ * loginTimeout (optional)
+ * user (optional)
+ * password (optional)
+ * serverName (optional)
+ * portNumber (optional)
+ * transactionTimeout (optional for XA connections)
+ * </pre>
+ * This data source may be serialized and stored in a JNDI
+ * directory. Example of how to create a new data source and
+ * register it with JNDI:
+ * <pre>
+ * PostgresqlDataSource ds;
+ * InitialContext ctx;
+ *
+ * ds = new PostgresqlDataSource();
+ * ds.setDatabaseName( "test" );
+ * ds.setUser( "me" );
+ * ds.setPassword( "secret" );
+ * ctx = new InitialContext();
+ * ctx.rebind( "/comp/jdbc/test", ds );
+ * </pre>
+ * Example for obtaining the data source from JNDI and
+ * opening a new connections:
+ * <pre>
+ * InitialContext ctx;
+ * DataSource ds;
+ *
+ * ctx = new InitialContext();
+ * ds = (DataSource) ctx.lookup( "/comp/jdbc/test" );
+ * ds.getConnection();
+ * </pre>
+ *
+ *
+ * @author <a href="arkin@exoffice.com">Assaf Arkin</a>
+ * @version 1.0
+ * @see XADataSourceImpl
+ * @see DataSource
+ * @see Connection
+ */
+public class PostgresqlDataSource
+ extends XADataSourceImpl
+ implements DataSource, Referenceable,
+ ObjectFactory, Serializable
+{
+
+
+ /**
+ * Holds the timeout for opening a new connection, specified
+ * in seconds. The default is obtained from the JDBC driver.
+ */
+ private int _loginTimeout;
+
+
+ /**
+ * Holds the user's account name.
+ */
+ private String _user;
+
+
+ /**
+ * Holds the database password.
+ */
+ private String _password;
+
+
+ /**
+ * Holds the name of the particular database on the server.
+ */
+ private String _databaseName;
+
+
+ /**
+ * Description of this datasource.
+ */
+ private String _description = "PostgreSQL DataSource";
+
+
+ /**
+ * Holds the database server name. If null, this is
+ * assumed to be the localhost.
+ */
+ private String _serverName;
+
+
+ /**
+ * Holds the port number where a server is listening.
+ * The default value will open a connection with an
+ * unspecified port.
+ */
+ private int _portNumber = DEFAULT_PORT;
+
+
+ /**
+ * The default port number. Since we open the connection
+ * without specifying the port if it's the default one,
+ * this value can be meaningless.
+ */
+ private static final int DEFAULT_PORT = 0;
+
+
+ /**
+ * Holds the log writer to which all messages should be
+ * printed. The default writer is obtained from the driver
+ * manager, but it can be specified at the datasource level
+ * and will be passed to the driver. May be null.
+ */
+ private transient PrintWriter _logWriter;
+
+
+ /**
+ * Each datasource maintains it's own driver, in case of
+ * driver-specific setup (e.g. pools, log writer).
+ */
+ private transient postgresql.Driver _driver;
+
+
+
+
+ public PostgresqlDataSource()
+ {
+ _logWriter = DriverManager.getLogWriter();
+ _loginTimeout = DriverManager.getLoginTimeout();
+ }
+
+
+ public Connection getConnection()
+ throws SQLException
+ {
+ // Uses the username and password specified for the datasource.
+ return getConnection( _user, _password );
+ }
+
+
+ public synchronized Connection getConnection( String user, String password )
+ throws SQLException
+ {
+ Connection conn;
+ Properties info;
+ String url;
+
+ if ( _driver == null ) {
+ try {
+ // Constructs a driver for use just by this data source
+ // which will produce TwoPhaseConnection-s. This driver
+ // is not registered with the driver manager.
+ _driver = new postgresql.Driver();
+ _driver.setLogWriter( _logWriter );
+ } catch ( SQLException except ) {
+ if ( _logWriter != null )
+ _logWriter.println( "DataSource: Failed to initialize JDBC driver: " + except );
+ throw except;
+ }
+ }
+
+ // Use info to supply properties that are not in the URL.
+ info = new Properties();
+ info.put( "loginTimeout", Integer.toString( _loginTimeout ) );
+
+ // DriverManager will do that and not rely on the URL alone.
+ if ( user == null ) {
+ user = _user;
+ password = _password;
+ }
+ if ( user == null || password == null )
+ throw new PSQLException( "postgresql.ds.userpswd" );
+ info.put( "user", user );
+ info.put( "password", password );
+
+ if ( _serverName != null )
+ info.put( "PGHOST", _serverName );
+ if ( _portNumber != DEFAULT_PORT )
+ info.put( "PGPORT", Integer.toString( _portNumber ) );
+ if ( _databaseName != null )
+ info.put( "PGDBNAME", _databaseName );
+
+ // Construct the URL suitable for this driver.
+ url = "jdbc:postgresql:";
+
+ // Attempt to establish a connection. Report a successful
+ // attempt or a failure.
+ try {
+ conn = _driver.connect( url, info );
+ if ( ! ( conn instanceof postgresql.jdbc2.Connection ) ) {
+ if ( _logWriter != null )
+ _logWriter.println( "DataSource: JDBC 1 connections not supported" );
+ throw new PSQLException( "postgresql.ds.onlyjdbc2" );
+ }
+ } catch ( SQLException except ) {
+ if ( _logWriter != null )
+ _logWriter.println( "DataSource: getConnection failed " + except );
+ throw except;
+ }
+ if ( conn != null && _logWriter != null )
+ _logWriter.println( "DataSource: getConnection returning " + conn );
+ return conn;
+ }
+
+
+ public PrintWriter getLogWriter()
+ {
+ return _logWriter;
+ }
+
+
+ public synchronized void setLogWriter( PrintWriter writer )
+ {
+ // Once a log writer has been set, we cannot set it since some
+ // thread might be conditionally accessing it right now without
+ // synchronizing.
+ if ( writer != null ) {
+ if ( _driver != null )
+ _driver.setLogWriter( writer );
+ _logWriter = writer;
+ }
+ }
+
+
+ public void setLoginTimeout( int seconds )
+ {
+ _loginTimeout = seconds;
+ }
+
+
+ public synchronized int getLoginTimeout()
+ {
+ return _loginTimeout;
+ }
+
+
+ /**
+ * Sets the name of the particular database on the server.
+ * The standard name for this property is <tt>databaseName</tt>.
+ *
+ * @param databaseName The name of the particular database on the server
+ */
+ public synchronized void setDatabaseName( String databaseName )
+ {
+ if ( databaseName == null )
+ throw new NullPointerException( "DataSource: Argument 'databaseName' is null" );
+ _databaseName = databaseName;
+ }
+
+
+ /**
+ * Returns the name of the particular database on the server.
+ * The standard name for this property is <tt>databaseName</tt>.
+ *
+ * @return The name of the particular database on the server
+ */
+ public String getDatabaseName()
+ {
+ return _databaseName;
+ }
+
+
+ /**
+ * Sets the description of this datasource.
+ * The standard name for this property is <tt>description</tt>.
+ *
+ * @param description The description of this datasource
+ */
+ public synchronized void setDescription( String description )
+ {
+ if ( description == null )
+ throw new NullPointerException( "DataSource: Argument 'description' is null" );
+ _description = description;
+ }
+
+
+ /**
+ * Returns the description of this datasource.
+ * The standard name for this property is <tt>description</tt>.
+ *
+ * @return The description of this datasource
+ */
+ public String getDescription()
+ {
+ return _description;
+ }
+
+
+ /**
+ * Sets the database password.
+ * The standard name for this property is <tt>password</tt>.
+ *
+ * @param password The database password
+ */
+ public synchronized void setPassword( String password )
+ {
+ _password = password;
+ }
+
+
+ /**
+ * Returns the database password.
+ * The standard name for this property is <tt>password</tt>.
+ *
+ * @return The database password
+ */
+ public String getPassword()
+ {
+ return _password;
+ }
+
+
+ /**
+ * Sets the port number where a server is listening.
+ * The standard name for this property is <tt>portNumber</tt>.
+ *
+ * @param portNumber The port number where a server is listening
+ */
+ public synchronized void setPortNumber( int portNumber )
+ {
+ _portNumber = portNumber;
+ }
+
+
+ /**
+ * Returns the port number where a server is listening.
+ * The standard name for this property is <tt>portNumber</tt>.
+ *
+ * @return The port number where a server is listening
+ */
+ public int getPortNumber()
+ {
+ return _portNumber;
+ }
+
+
+ /**
+ * Sets the database server name.
+
+ * The standard name for this property is <tt>serverName</tt>.
+ *
+ * @param serverName The database server name
+ */
+ public synchronized void setServerName( String serverName )
+ {
+ _serverName = serverName;
+ }
+
+
+ /**
+ * Returns the database server name.
+ * The standard name for this property is <tt>serverName</tt>.
+ *
+ * @return The database server name
+ */
+ public String getServerName()
+ {
+ return _serverName;
+ }
+
+
+ /**
+ * Sets the user's account name.
+ * The standard name for this property is <tt>user</tt>.
+ *
+ * @param user The user's account name
+ */
+ public synchronized void setUser( String user )
+ {
+ _user = user;
+ }
+
+
+ /**
+ * Returns the user's account name.
+ * The standard name for this property is <tt>user</tt>.
+ *
+ * @return The user's account name
+ */
+ public String getUser()
+ {
+ return _user;
+ }
+
+
+ /**
+ * Returns true if this datasource and the other are equal.
+ * The two datasources are equal if and only if they will produce
+ * the exact same connections. Connection properties like database
+ * name, user name, etc are comapred. Setup properties like
+ * description, log writer, etc are not compared.
+ */
+ public synchronized boolean equals( Object other )
+ {
+ if ( other == this )
+ return true;
+ if ( other == null || ! ( other instanceof PostgresqlDataSource ) )
+ return false;
+
+ PostgresqlDataSource with;
+
+ with = (PostgresqlDataSource) other;
+ if ( _databaseName != null && _databaseName.equals( with._databaseName ) )
+ if ( _portNumber == with._portNumber &&
+ ( ( _serverName == null && with._serverName == null ) ||
+ ( _serverName != null && _serverName.equals( with._serverName ) ) ) )
+ if ( ( _user == null && with._user == null ) ||
+ ( _user != null && _password != null && _user.equals( with._user ) &&
+ _password.equals( with._password ) ) )
+ return true;
+ return false;
+ }
+
+
+ public String toString()
+ {
+ if ( _description != null )
+ return _description;
+ else {
+ String url;
+
+ url = "jdbc:postgresql:";
+ if ( _serverName != null ) {
+ if ( _portNumber == DEFAULT_PORT )
+ url = url + "//" + _serverName + "/";
+ else
+ url = url + "//" + _serverName + ":" + _portNumber + "/";
+ } else if ( _portNumber != DEFAULT_PORT )
+ url = url + "//localhost:" + _portNumber + "/";
+ if ( _databaseName != null )
+ url = url + _databaseName;
+ return "DataSource " + url;
+ }
+ }
+
+
+ public synchronized Reference getReference()
+ {
+ Reference ref;
+
+ // We use same object as factory.
+ ref = new Reference( getClass().getName(), getClass().getName(), null );
+ // Mandatory properties
+ ref.add( new StringRefAddr( "description", _description ) );
+ ref.add( new StringRefAddr( "databaseName", _databaseName ) );
+ ref.add( new StringRefAddr( "loginTimeout", Integer.toString( _loginTimeout ) ) );
+ // Optional properties
+ if ( _user != null )
+ ref.add( new StringRefAddr( "user", _user ) );
+ if ( _password != null )
+ ref.add( new StringRefAddr( "password", _password ) );
+ if ( _serverName != null )
+ ref.add( new StringRefAddr( "serverName", _serverName ) );
+ if ( _portNumber != DEFAULT_PORT )
+ ref.add( new StringRefAddr( "portNumber", Integer.toString( _portNumber ) ) );
+ ref.add( new StringRefAddr( "transactionTimeout", Integer.toString( getTransactionTimeout() ) ) );
+ return ref;
+ }
+
+
+ public Object getObjectInstance( Object refObj, Name name, Context nameCtx, Hashtable env )
+ throws NamingException
+ {
+ Reference ref;
+
+ // Can only reconstruct from a reference.
+ if ( refObj instanceof Reference ) {
+ ref = (Reference) refObj;
+ // Make sure reference is of datasource class.
+ if ( ref.getClassName().equals( getClass().getName() ) ) {
+
+ PostgresqlDataSource ds;
+ RefAddr addr;
+
+ try {
+ ds = (PostgresqlDataSource) Class.forName( ref.getClassName() ).newInstance();
+ } catch ( Exception except ) {
+ throw new NamingException( except.toString() );
+ }
+ // Mandatory properties
+ ds._description = (String) ref.get( "description" ).getContent();
+ ds._databaseName = (String) ref.get( "databaseName" ).getContent();
+ ds._loginTimeout = Integer.parseInt( (String) ref.get( "loginTimeout" ).getContent() );
+ // Optional properties
+ addr = ref.get( "user" );
+ if ( addr != null )
+ ds._user = (String) addr.getContent();
+ addr = ref.get( "password" );
+ if ( addr != null )
+ ds._password = (String) addr.getContent();
+ addr = ref.get( "serverName" );
+ if ( addr != null )
+ ds._serverName = (String) addr.getContent();
+ addr = ref.get( "portNumber" );
+ if ( addr != null )
+ ds._portNumber = Integer.parseInt( (String) addr.getContent() );
+ addr = ref.get( "transactionTimeout" );
+ if ( addr != null )
+ setTransactionTimeout( Integer.parseInt( (String) addr.getContent() ) );
+ return ds;
+
+ } else
+ throw new NamingException( "DataSource: Reference not constructed from class " + getClass().getName() );
+ } else if ( refObj instanceof Remote )
+ return refObj;
+ else
+ return null;
+ }
+
+
+}
+
diff --git a/src/interfaces/jdbc/org/postgresql/errors.properties b/src/interfaces/jdbc/org/postgresql/errors.properties
index 2de5802d5b4..c33a34aa7b1 100644
--- a/src/interfaces/jdbc/org/postgresql/errors.properties
+++ b/src/interfaces/jdbc/org/postgresql/errors.properties
@@ -1,4 +1,5 @@
# This is the default errors
+postgresql.drv.version:An internal error has occured. Please recompile the driver.
postgresql.con.auth:The authentication type {0} is not supported. Check that you have configured the pg_hba.conf file to include the client's IP address or Subnet, and that it is using an authentication scheme supported by the driver.
postgresql.con.authfail:An error occured while getting the authentication request.
postgresql.con.call:Callable Statements are not supported at this time.
diff --git a/src/interfaces/jdbc/org/postgresql/errors_it.properties b/src/interfaces/jdbc/org/postgresql/errors_it.properties
new file mode 100644
index 00000000000..9b7f7cdd69b
--- /dev/null
+++ b/src/interfaces/jdbc/org/postgresql/errors_it.properties
@@ -0,0 +1,74 @@
+# This is the italian version of some errors. Errors not in this file
+# are handled by the parent errors.properties file.
+#
+# Daniele Arduini <darduini@deis.unibo.it>
+# Wed Aug 9 12:18:31 CEST 2000
+#
+postgresql.con.auth:L'autenticazione di tipo {0} non è supportata. Verificare che nel file di configurazione pg_hba.conf sia presente l'indirizzo IP o la sotto-rete del client, e che lo schema di autenticazione utilizzato sia supportato dal driver.
+postgresql.con.authfail:Si è verificato un errore durante la richiesta di autenticazione.
+postgresql.con.call:I ``Callable Statements'' non sono supportati al momento.
+postgresql.con.creobj:Fallita la creazione dell'oggetto per {0} {1}
+postgresql.con.failed:Il tentativo di connessione è fallito perché {0}
+#postgresql.con.fathom:Unable to fathom update count {0}
+postgresql.con.garbled:Ricevuti dati incomprensibili.
+postgresql.con.ioerror:Si è verificato un errore di I/O nella spedizione di dati al backend - {0}
+postgresql.con.kerb4:L'autenticazione di tipo ``Kerberos 4'' non è supportata da questo driver.
+postgresql.con.kerb5:L'autenticazione di tipo ``Kerberos 5'' non è supportata da questo driver.
+postgresql.con.multres:Impossibile gestire gruppi multipli di risultati.
+postgresql.con.pass:La proprietà ``password'' è mancante. E` obbligatoria.
+postgresql.con.refused:Connessione rifiutata. Controllare che il nome dell'host e la porta siano corretti, e che il server (postmaster) è in esecuzione con l'opzione -i, che abilita le connessioni attraverso la rete TCP/IP.
+postgresql.con.setup:Errore di protocollo. Fallita l'impostazione della sessione.
+postgresql.con.strobj:L'oggetto potrebbe non essere stato memorizzato. Controllare che ogni tabella richiesta è stata creata nel database.
+postgresql.con.strobjex:Fallita la memorizzazione dell'oggetto - {0}
+postgresql.con.toolong:L'istruzione SQL è troppo lunga - {0}
+postgresql.con.isolevel:Il livello d'isolamento delle transazioni {0} non è supportato.
+postgresql.con.tuple:Tupla ricevuta prima del MetaData.
+postgresql.con.type:Tipo di risposta sconosciuta {0}
+postgresql.con.user:La proprietà ``user'' è mancante. E` obbligatoria.
+postgresql.fp.error:La chiamata a FastPath ha restituito {0}
+postgresql.fp.expint:Chiamata Fastpath {0} - Nessun risultato restituito mentre ci si aspettava un intero.
+postgresql.fp.protocol:Errore nel protocollo FastPath: {0}
+postgresql.fp.send:Fallita la spedizione della chiamata fastpath {0} {1}
+postgresql.fp.unknown:La funzione fastpath {0} è sconosciuta.
+postgresql.geo.box:Fallita la conversione di un ``box'' - {0}
+postgresql.geo.circle:Fallita la conversione di un ``circle'' - {0}
+postgresql.geo.line:Fallita la conversione di una ``line'' - {0}
+postgresql.geo.lseg:Fallita la conversione di un ``lseg'' - {0}
+postgresql.geo.path:Impossibile stabilire se il ``path'' è aperto o chiuso.
+postgresql.geo.point:Fallita la conversione di un ``point'' - {0}
+postgresql.jvm.version:Il file ``postgresql.jar'' non contiene le classi JDBC corrette per questa JVM. Provare a ricompilarle. Se il problema persiste, tentare di forzare la versione fornendola nella linea di comando con l'opzione -Djava.version=1.1 or -Djava.version=1.2\nL'eccezione ricevuta è stata {0}
+postgresql.lo.init:Inizializzazione di LargeObject API fallita.
+postgresql.money:Fallita la conversione di un ``money'' - {0}.
+postgresql.prep.is:InputStream come parametro non è supportato
+postgresql.prep.param:Nessun valore specificato come parametro {0}.
+postgresql.prep.range:Indice di parametro fuori dall'intervallo.
+postgresql.prep.type:Valore di tipo sconosciuto.
+postgresql.res.badbigdec:Cattivo BigDecimal {0}
+postgresql.res.badbyte:Cattivo Byte {0}
+postgresql.res.baddate:Cattivo Date Format a {0} in {1}
+postgresql.res.baddouble:Cattivo Double {0}
+postgresql.res.badfloat:Cattivo Float {0}
+postgresql.res.badint:Cattivo Integer {0}
+postgresql.res.badlong:Cattivo Long {0}
+postgresql.res.badshort:Cattivo Short {0}
+postgresql.res.badtime:Cattivo Time {0}
+postgresql.res.badtimestamp:Cattivo Timestamp Format a {0} in {1}
+postgresql.res.colname:Colonna denominata {0} non trovata.
+postgresql.res.colrange:Indice di colonna fuori dall'intervallo.
+postgresql.serial.interface:Impossibile serializzare una interfaccia.
+postgresql.serial.namelength:La lunghezza dei nomi per Class & Package non può essere superiore a 32 caratteri. {0} è di {1} caratteri.
+postgresql.serial.noclass:Nessuna classe trovata per {0}.
+postgresql.serial.table:La tabella per {0} non è nel database. Contattare il DBA, visto che il database è in uno stato incosistente.
+postgresql.serial.underscore:Il nome di una classe non può contenere il carattere ``_''. E` stato fornito {0}.
+postgresql.stat.batch.empty:La sequenza di operazioni è vuota. Non c'è niente da eseguire.
+postgresql.stat.batch.error:L'operazione {0} {1} della sequenza è stata annullata.
+postgresql.stat.maxfieldsize:Fallito un tentativo a setMaxFieldSize() - verrà utilizzato il valore predefinito a tempo di compilazione.
+postgresql.stat.noresult:Nessun risultato è stato restituito dalla query.
+postgresql.stat.result:Un risultato è stato restituito dallo statement, quando ci si aspettava nulla.
+postgresql.stream.eof:Il backend ha interrotto la connessione. Probabilmente la tua azione ha causato la sua uscita.
+postgresql.stream.flush:Si è verificato un errore di I/O mentre si svuotava il buffer d'uscita - {0}
+postgresql.stream.ioerror:Si è verificato un errore di I/O mentre si leggevano dati dal backend - {0}
+postgresql.stream.toomuch:Troppi dati ricevuti.
+postgresql.unusual:Qualcosa di insolito si è verificato causando il fallimento del driver. Per favore riferire allo sviluppatore questa eccezione: {0}
+postgresql.unimplemented:Questo metodo non è stato ancora implementato.
+postgresql.unexpected:Un risultato inaspettato è stato ricevuto dalla query.
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
index 674c0d16e10..b1f7e581bc6 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc1/DatabaseMetaData.java
@@ -179,7 +179,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
*/
public String getDatabaseProductVersion() throws SQLException
{
- return ("7.0.2");
+ return connection.this_driver.getVersion();
}
/**
@@ -203,7 +203,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
*/
public String getDriverVersion() throws SQLException
{
- return Integer.toString(connection.this_driver.getMajorVersion())+"."+Integer.toString(connection.this_driver.getMinorVersion());
+ return connection.this_driver.getVersion();
}
/**
@@ -453,14 +453,14 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
/**
* Is "ALTER TABLE" with a drop column supported?
- * Yes for PostgreSQL 6.1
+ * Peter 10/10/2000 This was set to true, but 7.1devel doesn't support it!
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean supportsAlterTableWithDropColumn() throws SQLException
{
- return true;
+ return false;
}
/**
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java b/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
index 4b8451d1fcc..051a99c630d 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/DatabaseMetaData.java
@@ -179,7 +179,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
*/
public String getDatabaseProductVersion() throws SQLException
{
- return ("7.0.2");
+ return connection.this_driver.getVersion();
}
/**
@@ -203,7 +203,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
*/
public String getDriverVersion() throws SQLException
{
- return Integer.toString(connection.this_driver.getMajorVersion())+"."+Integer.toString(connection.this_driver.getMinorVersion());
+ return connection.this_driver.getVersion();
}
/**
@@ -453,14 +453,14 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
/**
* Is "ALTER TABLE" with a drop column supported?
- * Yes for PostgreSQL 6.1
+ * Peter 10/10/2000 This was set to true, but 7.1devel doesn't support it!
*
* @return true if so
* @exception SQLException if a database access error occurs
*/
public boolean supportsAlterTableWithDropColumn() throws SQLException
{
- return true;
+ return false;
}
/**
@@ -523,7 +523,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
}
/**
- * Are expressions in "ORCER BY" lists supported?
+ * Are expressions in "ORDER BY" lists supported?
*
* <br>e.g. select * from t order by a + b;
*
diff --git a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
index e9f6c79f41b..5c73b6ed4f0 100644
--- a/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
+++ b/src/interfaces/jdbc/org/postgresql/jdbc2/ResultSet.java
@@ -730,6 +730,11 @@ public class ResultSet extends org.postgresql.ResultSet implements java.sql.Resu
if (columnIndex < 1 || columnIndex > fields.length)
throw new PSQLException("postgresql.res.colrange");
+
+ wasNullFlag = (this_row[columnIndex - 1] == null);
+ if(wasNullFlag)
+ return null;
+
field = fields[columnIndex - 1];
// some fields can be null, mainly from those returned by MetaData methods