From ba977c086c01726affcc96219a79584a11ccc78e Mon Sep 17 00:00:00 2001
From: "Marc G. Fournier" <scrappy@hub.org>
Date: Sun, 11 Jan 1998 21:14:56 +0000
Subject: [PATCH] Peter's Mega-Patch for JDBC...

see README_6.3 for list of changes
---
 src/interfaces/jdbc/Makefile                  | 112 ++++-
 src/interfaces/jdbc/README                    |  22 +-
 src/interfaces/jdbc/README_6.3                |  78 +++
 .../jdbc/postgresql/CallableStatement.java    | 234 +++++++--
 .../jdbc/postgresql/Connection.java           | 244 +++++++++-
 .../jdbc/postgresql/DatabaseMetaData.java     | 452 +++++++++++++++---
 src/interfaces/jdbc/postgresql/Driver.java    |  40 +-
 src/interfaces/jdbc/postgresql/Field.java     | 122 +++--
 src/interfaces/jdbc/postgresql/PG_Stream.java |  36 ++
 .../jdbc/postgresql/PreparedStatement.java    | 125 +++--
 src/interfaces/jdbc/postgresql/ResultSet.java |  94 ++--
 .../jdbc/postgresql/ResultSetMetaData.java    |   3 -
 src/interfaces/jdbc/postgresql/Statement.java |  20 +-
 13 files changed, 1276 insertions(+), 306 deletions(-)
 create mode 100644 src/interfaces/jdbc/README_6.3

diff --git a/src/interfaces/jdbc/Makefile b/src/interfaces/jdbc/Makefile
index 469b552a699..928aafae5ef 100644
--- a/src/interfaces/jdbc/Makefile
+++ b/src/interfaces/jdbc/Makefile
@@ -4,7 +4,7 @@
 #    Makefile for Java JDBC interface
 #
 # IDENTIFICATION
-#    $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.2 1997/09/29 20:11:42 scrappy Exp $
+#    $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.3 1998/01/11 21:14:29 scrappy Exp $
 #
 #-------------------------------------------------------------------------
 
@@ -22,41 +22,70 @@ RM		= rm -f
 	$(JAVAC) $<
 
 .SUFFIXES:	.class .java
-.PHONY:		all clean doc
+.PHONY:		all clean doc examples
 
 all:	  postgresql.jar
+	@echo ------------------------------------------------------------
+	@echo The JDBC driver has now been built. To make it available to
+	@echo other applications, copy the postgresql.jar file to a public
+	@echo "place (under unix this could be /usr/local/lib) and add it"
+	@echo to the class path.
+	@echo
+	@echo Then either add -Djdbc.drivers=postgresql.Driver to the
+	@echo commandline when running your application, or edit the
+	@echo "properties file (~/.hotjava/properties under unix), and"
+	@echo add a line containing jdbc.drivers=postgresql.Driver
+	@echo
+	@echo More details are in the README file.
+	@echo ------------------------------------------------------------
+	@echo To build the examples, type:
+	@echo "  make examples"
+	@echo ------------------------------------------------------------
+	@echo
 
+# This rule builds the javadoc documentation
 doc:
-	$(JAVADOC) -public postgresql
+	export CLASSPATH=.;\
+		$(JAVADOC) -public \
+			postgresql \
+			postgresql.fastpath \
+			postgresql.largeobject
 
+# These classes form the driver. These, and only these are placed into
+# the jar file.
 OBJS=	postgresql/CallableStatement.class \
 	postgresql/Connection.class \
 	postgresql/DatabaseMetaData.class \
 	postgresql/Driver.class \
 	postgresql/Field.class \
-	postgresql/PG_Object.class \
 	postgresql/PG_Stream.class \
-	postgresql/PGbox.class \
-	postgresql/PGcircle.class \
-	postgresql/PGlobj.class \
-	postgresql/PGlseg.class \
-	postgresql/PGpath.class \
-	postgresql/PGpoint.class \
-	postgresql/PGpolygon.class \
-	postgresql/PGtokenizer.class \
 	postgresql/PreparedStatement.class \
 	postgresql/ResultSet.class \
 	postgresql/ResultSetMetaData.class \
-	postgresql/Statement.class
+	postgresql/Statement.class \
+	postgresql/fastpath/Fastpath.class \
+	postgresql/fastpath/FastpathArg.class \
+	postgresql/geometric/PGbox.class \
+	postgresql/geometric/PGcircle.class \
+	postgresql/geometric/PGlseg.class \
+	postgresql/geometric/PGpath.class \
+	postgresql/geometric/PGpoint.class \
+	postgresql/geometric/PGpolygon.class \
+	postgresql/largeobject/LargeObject.class \
+	postgresql/largeobject/LargeObjectManager.class \
+	postgresql/util/PGobject.class \
+	postgresql/util/PGtokenizer.class
 
 postgresql.jar: $(OBJS)
-	$(JAR) -c0vf $@ $^
+	$(JAR) -c0vf $@ $$($(FIND) postgresql -name "*.class" -print)
 
 # This rule removes any temporary and compiled files from the source tree.
 clean:
 	$(FIND) . -name "*~" -exec $(RM) {} \;
 	$(FIND) . -name "*.class" -exec $(RM) {} \;
+	$(FIND) . -name "*.html" -exec $(RM) {} \;
 	$(RM) postgresql.jar
+	-$(RM) -rf Package-postgresql *output
 
 #######################################################################
 # This helps make workout what classes are from what source files
@@ -69,21 +98,56 @@ postgresql/Connection.class:		postgresql/Connection.java
 postgresql/DatabaseMetaData.class:	postgresql/DatabaseMetaData.java
 postgresql/Driver.class:		postgresql/Driver.java
 postgresql/Field.class:			postgresql/Field.java
-postgresql/PG_Object.class:		postgresql/PG_Object.java
 postgresql/PG_Stream.class:		postgresql/PG_Stream.java
-postgresql/PGbox.class:			postgresql/PGbox.java
-postgresql/PGcircle.class:		postgresql/PGcircle.java
-postgresql/PGlobj.class:		postgresql/PGlobj.java
-postgresql/PGlseg.class:		postgresql/PGlseg.java
-postgresql/PGpath.class:		postgresql/PGpath.java
-postgresql/PGpoint.class:		postgresql/PGpoint.java
-postgresql/PGpolygon.class:		postgresql/PGpolygon.java
-postgresql/PGtokenizer.class:		postgresql/PGtokenizer.java
 postgresql/PreparedStatement.class:	postgresql/PreparedStatement.java
 postgresql/ResultSet.class:		postgresql/ResultSet.java
 postgresql/ResultSetMetaData.class:	postgresql/ResultSetMetaData.java
 postgresql/Statement.class:		postgresql/Statement.java
+postgresql/fastpath/Fastpath.class:	postgresql/fastpath/Fastpath.java
+postgresql/fastpath/FastpathArg.class:	postgresql/fastpath/FastpathArg.java
+postgresql/geometric/PGbox.class:	postgresql/geometric/PGbox.java
+postgresql/geometric/PGcircle.class:	postgresql/geometric/PGcircle.java
+postgresql/geometric/PGlseg.class:	postgresql/geometric/PGlseg.java
+postgresql/geometric/PGpath.class:	postgresql/geometric/PGpath.java
+postgresql/geometric/PGpoint.class:	postgresql/geometric/PGpoint.java
+postgresql/geometric/PGpolygon.class:	postgresql/geometric/PGpolygon.java
+postgresql/largeobject/LargeObject.class: postgresql/largeobject/LargeObject.java
+postgresql/largeobject/LargeObjectManager.class: postgresql/largeobject/LargeObjectManager.java
+postgresql/util/PGobject.class:		postgresql/util/PGobject.java
+postgresql/util/PGtokenizer.class:	postgresql/util/PGtokenizer.java
 
+#######################################################################
+# These classes are in the example directory, and form the examples
+EX=	example/basic.class \
+	example/blobtest.class \
+	example/datestyle.class \
+	example/psql.class \
+	example/ImageViewer.class
 
+# This rule builds the examples
+examples:	postgresql.jar $(EX)
+	@echo ------------------------------------------------------------
+	@echo The examples have been built.
+	@echo
+	@echo For instructions on how to use them, simply run them. For example:
+	@echo
+	@echo "  java example.blobtest"
+	@echo
+	@echo This would display instructions on how to run the example.
+	@echo ------------------------------------------------------------
+	@echo Available examples:
+	@echo
+	@echo "  example.basic        Basic JDBC useage"
+	@echo "  example.blobtest     Binary Large Object tests"
+	@echo "  example.datestyle    Shows how datestyles are handled"
+	@echo "  example.ImageViewer  Example application storing images"
+	@echo "  example.psql         Simple java implementation of psql"
+	@echo ------------------------------------------------------------
+	@echo
 
-
+example/basic.class:			example/basic.java
+example/blobtest.class:			example/blobtest.java
+example/datestyle.class:		example/datestyle.java
+example/psql.class:			example/psql.java
+example/ImageViewer.class:		example/ImageViewer.java
+#######################################################################
diff --git a/src/interfaces/jdbc/README b/src/interfaces/jdbc/README
index cd43a5af2f3..035ad008bf3 100644
--- a/src/interfaces/jdbc/README
+++ b/src/interfaces/jdbc/README
@@ -10,6 +10,14 @@ or the JDBC mailing list:
 
 	http://www.blackdown.org
 
+For problems with this driver, then refer to the postgres-interfaces email
+list:
+
+	http://www.postgresql.org
+
+By the time V6.3 is released, full documentation will be on the web, and in
+the distribution.
+
 ---------------------------------------------------------------------------
 
 COMPILING
@@ -115,15 +123,21 @@ them to the URL. eg:
 By default, the driver doesn't use password authentication. You can enable
 this by adding the argument auth. ie:
 
-	jdbc:postgresql:database?user=me&password=mypass&auth=y
+	jdbc:postgresql:database?user=me&password=mypass&auth=password
 
 or if passing the user & password directly via DriverManager.getConnection():
 
-	jdbc:postgresql:database?auth=y
+	jdbc:postgresql:database?auth=password
 
-PS: Password authentication is enabled if the value of auth starts with 'y'.
+PS: Password authentication is enabled if the value of auth starts with 'p'.
     It is case insensitive.
 
+As of postgresql 6.3, Ident (RFC 1413) authentication is also supported.
+Simply use auth=ident in the url.
+
+Also, as of 6.3, a system property of postgresql.auth is supported. This
+defines the default authentication to use. The auth property overides this.
+
 ---------------------------------------------------------------------------
 
 That's the basics related to this driver. You'll need to read the JDBC Docs
@@ -180,7 +194,7 @@ syntax for writing these to the database.
 
 ---------------------------------------------------------------------------
 
-Peter T Mount, October 28 1997
+Peter T Mount, January 11 1998
 home email: pmount@maidast.demon.co.uk	http://www.demon.co.uk/finder
 work email: peter@maidstone.gov.uk	http://www.maidstone.gov.uk
 
diff --git a/src/interfaces/jdbc/README_6.3 b/src/interfaces/jdbc/README_6.3
new file mode 100644
index 00000000000..797d3ff99b7
--- /dev/null
+++ b/src/interfaces/jdbc/README_6.3
@@ -0,0 +1,78 @@
+Ok, here's the JDBC patch.
+
+The jdbc6.3.tar.gz file that I've uploaded ftp.postgresql.org contains the
+following files:
+
+README_6.3 This message
+blob.patch The patch to src/backend/tcop/fastpath.c fixing large objects
+jdbc.tar   The entire jdbc driver
+
+I've put the entire driver here, rather than a patch, because its become
+too complicated to do one this time. Files have been moved, two files
+removed because they were obsolete, and there are a lot of new files.
+
+Heres what the patch does:
+
+* Memory overflow problem in the backend causing large objects to fail in
+  both libpq & jdbc (causing the backend to crash with a Segmentation
+  Violation)
+* Problem with equals() method on the geometric support classes if the
+  class being checked wasn't the same class
+* Fixed output of PGpath and PGpolygon support classes (missing , separator)
+* Optimised the geometric support classes
+* HTMLised the inline documentation, so the output of javadoc is easier
+  to read (mainly paragraphs)
+* Removed obsolete class PGlobj (it never worked, and has been replaced
+  to read (mainly paragraphs)
+* Removed obsolete class PGlobj (it never worked, and has been replaced
+  by the postgresql.largeobject package)
+* Removed obsolete example JDBC_Test.java (replaced by new examples)
+* Added < and > to nesting in PGtokenizer.
+* Added fastpath support as a new package
+* Added large object support as a new package
+* Added ability of user code to handle custom storage types.
+* Added new example testing the importing and exporting of a large object
+* Added example application showing how to store and display images stored
+  as large objects
+* Added example implementing part of psql client. This shows how to find out
+  what tables/columns are in a database (not yet complete)
+* ResultSet.getBytes() now returns large object if field is an oid
+* ResultSet.getString() now doesn't call getBytes() as this now would
+  cause an infinite loop because of large object support in getBytes()
+* PreparedStatement.setBytes() now create a large object, and store its
+  oid into the column
+* Reworked date style handling to make it easier to support new styles
+* Added german and ISO styles, now all styles supported by postgresql
+  are now supported by the driver
+* Fixed DatabaseMetaData.getTables()
+* DatabaseMetaData.getTableTypes() returns our supported types.
+* Fixed DatabaseMetaData.getColumns()
+
+These three are required for Borland's JBuilder to work. For now they
+return an empty result, as I'm not sure yet on how to get the
+required results.
+* DatabaseMetaData.getBestRowIdentifier()
+* DatabaseMetaData.getProcedureColumns()
+* DatabaseMetaData.getIndexInfo()
+
+Finally, one change that is incompatible with earlier versions of the
+driver. This change only affects any client code that uses the geometric
+classes (eg: PGpoint) or the getObject()/setObject() methods.
+
+Because of a problem with javac, if user code includes the line:
+
+import postgresql.*;
+
+then javac will fail, saying that interfaces cannot be instanciated.
+
+To fix this, I've moved these classes into a new sub package,
+postgresql.geometric and the PG_Object (renamed PGobject), and PGtokenizer
+to postgresql.util.So the above line would become:
+
+import postgresql.geometric.*;
+
+Anyhow, I'm going to start writing some proper documentation for the
+driver. For now, there is some available temporarily at:
+
+        http://www.demon.co.uk/finder/postgres/jdbc/packages.html
+
diff --git a/src/interfaces/jdbc/postgresql/CallableStatement.java b/src/interfaces/jdbc/postgresql/CallableStatement.java
index ede69bbb121..7f56a42b2a5 100644
--- a/src/interfaces/jdbc/postgresql/CallableStatement.java
+++ b/src/interfaces/jdbc/postgresql/CallableStatement.java
@@ -4,46 +4,114 @@ import java.sql.*;
 import java.math.*;
 
 /**
- * JDBC Interface to Postgres95 functions
+ * CallableStatement is used to execute SQL stored procedures.
+ *
+ * <p>JDBC provides a stored procedure SQL escape that allows stored
+ * procedures to be called in a standard way for all RDBMS's. This escape
+ * syntax has one form that includes a result parameter and one that does
+ * not. If used, the result parameter must be registered as an OUT
+ * parameter. The other parameters may be used for input, output or both.
+ * Parameters are refered to sequentially, by number. The first parameter
+ * is 1.
+ *
+ * {?= call <procedure-name>[<arg1>,<arg2>, ...]}                 
+ * {call <procedure-name>[<arg1>,<arg2>, ...]}       
+ *
+ *
+ * <p>IN parameter values are set using the set methods inherited from
+ * PreparedStatement. The type of all OUT parameters must be registered
+ * prior to executing the stored procedure; their values are retrieved
+ * after execution via the get methods provided here.
+ *
+ * <p>A Callable statement may return a ResultSet or multiple ResultSets.
+ * Multiple ResultSets are handled using operations inherited from
+ * Statement.
+ *
+ * <p>For maximum portability, a call's ResultSets and update counts should 
+ * be processed prior to getting the values of output parameters.        
+ *
+ * @see Connection#prepareCall
+ * @see ResultSet
  */
 
-// Copy methods from the Result set object here.
-
 public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement
 {
+  /**
+   * @exception SQLException on failure
+   */
   CallableStatement(Connection c,String q) throws SQLException
   {
     super(c,q);
   }
   
-  // Before executing a stored procedure call you must explicitly
-  // call registerOutParameter to register the java.sql.Type of each
-  // out parameter.
+  /**
+   * Before executing a stored procedure call you must explicitly
+   * call registerOutParameter to register the java.sql.Type of each
+   * out parameter.
+   *
+   * <p>Note: When reading the value of an out parameter, you must use
+   * the getXXX method whose Java type XXX corresponds to the
+   * parameter's registered SQL type.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @param sqlType SQL type code defined by java.sql.Types; for
+   * parameters of type Numeric or Decimal use the version of
+   * registerOutParameter that accepts a scale value
+   * @exception SQLException if a database-access error occurs.
+   */
   public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
   }
   
-  // You must also specify the scale for numeric/decimal types:	
+  /**
+   * You must also specify the scale for numeric/decimal types:
+   *
+   * <p>Note: When reading the value of an out parameter, you must use
+   * the getXXX method whose Java type XXX corresponds to the
+   * parameter's registered SQL type.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @param sqlType use either java.sql.Type.NUMERIC or java.sql.Type.DECIMAL
+   * @param scale a value greater than or equal to zero representing the
+   * desired number of digits to the right of the decimal point
+   * @exception SQLException if a database-access error occurs.
+   */
   public void registerOutParameter(int parameterIndex, int sqlType,
 				   int scale) throws SQLException
   {
   }
   
-  public boolean isNull(int parameterIndex) throws SQLException {
-    return true;
-  }
+  // Old api?
+  //public boolean isNull(int parameterIndex) throws SQLException {
+  //return true;
+  //}
   
-  // New API (JPM)
+  /**
+   * An OUT parameter may have the value of SQL NULL; wasNull
+   * reports whether the last value read has this special value.
+   *
+   * <p>Note: You must first call getXXX on a parameter to read its
+   * value and then call wasNull() to see if the value was SQL NULL.
+   * @return true if the last parameter read was SQL NULL
+   * @exception SQLException if a database-access error occurs.
+   */
   public boolean wasNull() throws SQLException {
     // check to see if the last access threw an exception
     return false; // fake it for now
   }
   
-  // Methods for retrieving OUT parameters from this statement.
-  public String getChar(int parameterIndex) throws SQLException {
-    return null;
-  }
+  // Old api?
+  //public String getChar(int parameterIndex) throws SQLException {
+  //return null;
+  //}
   
-  // New API (JPM)
+  /**
+   * Get the value of a CHAR, VARCHAR, or LONGVARCHAR parameter as a
+   * Java String.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is null
+   * @exception SQLException if a database-access error occurs.
+   */
   public String getString(int parameterIndex) throws SQLException {
     return null;
   }
@@ -51,64 +119,148 @@ public class CallableStatement extends PreparedStatement implements java.sql.Cal
   //   return null;
   //}
   
-  public String getLongVarChar(int parameterIndex) throws SQLException {
-    return null;
-  }
+  //public String getLongVarChar(int parameterIndex) throws SQLException {
+  //return null;
+  //}
   
-  // New API (JPM) (getBit)
+  /**
+   * Get the value of a BIT parameter as a Java boolean.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is false
+   * @exception SQLException if a database-access error occurs.
+   */
   public boolean getBoolean(int parameterIndex) throws SQLException {
     return false;
   }
   
-  // New API (JPM) (getTinyInt)
+  /**
+   * Get the value of a TINYINT parameter as a Java byte.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is 0
+   * @exception SQLException if a database-access error occurs.
+   */
   public byte getByte(int parameterIndex) throws SQLException {
     return 0;
   }
   
-  // New API (JPM) (getSmallInt)
+  /**
+   * Get the value of a SMALLINT parameter as a Java short.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is 0
+   * @exception SQLException if a database-access error occurs.
+   */
   public short getShort(int parameterIndex) throws SQLException {
     return 0;
   }
   
-  // New API (JPM) (getInteger)
-  public int getInt(int parameterIndex) throws SQLException {
+  /**
+   * Get the value of an INTEGER parameter as a Java int.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is 0
+   * @exception SQLException if a database-access error occurs.
+   */
+public int getInt(int parameterIndex) throws SQLException {
     return 0;
   }
   
-  // New API (JPM) (getBigInt)
+  /**
+   * Get the value of a BIGINT parameter as a Java long.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is 0
+   * @exception SQLException if a database-access error occurs.
+   */
   public long getLong(int parameterIndex) throws SQLException {
     return 0;
   }
   
+  /**
+   * Get the value of a FLOAT parameter as a Java float.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is 0
+   * @exception SQLException if a database-access error occurs.
+   */
   public float getFloat(int parameterIndex) throws SQLException {
     return (float) 0.0;
   }
   
+  /**
+   * Get the value of a DOUBLE parameter as a Java double.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is 0
+   * @exception SQLException if a database-access error occurs.
+   */
   public double getDouble(int parameterIndex) throws SQLException {
     return 0.0;
   }
   
+  /**
+   * Get the value of a NUMERIC parameter as a java.math.BigDecimal
+   * object.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @param scale a value greater than or equal to zero representing the
+   * desired number of digits to the right of the decimal point
+   * @return the parameter value; if the value is SQL NULL, the result is null
+   * @exception SQLException if a database-access error occurs.
+   */
   public BigDecimal getBigDecimal(int parameterIndex, int scale)
        throws SQLException {
 	 return null;
   }
   
-  // New API (JPM) (getBinary)
+  /**
+   * Get the value of a SQL BINARY or VARBINARY parameter as a Java
+   * byte[]
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is null
+   * @exception SQLException if a database-access error occurs.
+   */
   public byte[] getBytes(int parameterIndex) throws SQLException {
     return null;
   }
   
   // New API (JPM) (getLongVarBinary)
-  public byte[] getBinaryStream(int parameterIndex) throws SQLException {
-    return null;
-  }
+  //public byte[] getBinaryStream(int parameterIndex) throws SQLException {
+  //return null;
+  //}
   
+  /**
+   * Get the value of a SQL DATE parameter as a java.sql.Date object
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is null
+   * @exception SQLException if a database-access error occurs.
+   */
   public java.sql.Date getDate(int parameterIndex) throws SQLException {
     return null;
   }
+  
+  /**
+   * Get the value of a SQL TIME parameter as a java.sql.Time object.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is null
+   * @exception SQLException if a database-access error occurs.
+   */
   public java.sql.Time getTime(int parameterIndex) throws SQLException {
     return null;
   }
+  
+  /**
+   * Get the value of a SQL TIMESTAMP parameter as a java.sql.Timestamp object.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return the parameter value; if the value is SQL NULL, the result is null
+   * @exception SQLException if a database-access error occurs.
+   */
   public java.sql.Timestamp getTimestamp(int parameterIndex)
        throws SQLException {
 	 return null;
@@ -119,12 +271,30 @@ public class CallableStatement extends PreparedStatement implements java.sql.Cal
   
   // You can obtain a ParameterMetaData object to get information 
   // about the parameters to this CallableStatement.
-  public DatabaseMetaData getMetaData() {
-    return null;
-  }
+  //public DatabaseMetaData getMetaData() {
+  //return null;
+  //}
   
   // getObject returns a Java object for the parameter.
   // See the JDBC spec's "Dynamic Programming" chapter for details.
+  /**
+   * Get the value of a parameter as a Java object.
+   *
+   * <p>This method returns a Java object whose type coresponds to the
+   * SQL type that was registered for this parameter using
+   * registerOutParameter.
+   *
+   * <P>Note that this method may be used to read datatabase-specific,
+   * abstract data types. This is done by specifying a targetSqlType
+   * of java.sql.types.OTHER, which allows the driver to return a
+   * database-specific Java type.
+   *
+   * <p>See the JDBC spec's "Dynamic Programming" chapter for details.
+   *
+   * @param parameterIndex the first parameter is 1, the second is 2,...
+   * @return A java.lang.Object holding the OUT parameter value.
+   * @exception SQLException if a database-access error occurs.
+   */
   public Object getObject(int parameterIndex)
        throws SQLException {
 	 return null;
diff --git a/src/interfaces/jdbc/postgresql/Connection.java b/src/interfaces/jdbc/postgresql/Connection.java
index 09344e1fe08..1c13b520d5b 100644
--- a/src/interfaces/jdbc/postgresql/Connection.java
+++ b/src/interfaces/jdbc/postgresql/Connection.java
@@ -5,22 +5,21 @@ import java.lang.*;
 import java.net.*;
 import java.util.*;
 import java.sql.*;
-import postgresql.*;
+import postgresql.fastpath.*;
+import postgresql.largeobject.*;
+import postgresql.util.*;
 
 /**
- * @version 1.0 15-APR-1997
- * @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
- *
  * A Connection represents a session with a specific database.  Within the
  * context of a Connection, SQL statements are executed and results are
  * returned.
  *
- * A Connection's database is able to provide information describing
+ * <P>A Connection's database is able to provide information describing
  * its tables, its supported SQL grammar, its stored procedures, the
  * capabilities of this connection, etc.  This information is obtained
  * with the getMetaData method.
  *
- * <B>Note:</B> By default, the Connection automatically commits changes
+ * <p><B>Note:</B> By default, the Connection automatically commits changes
  * after executing each statement.  If auto-commit has been disabled, an
  * explicit commit must be done or database changes will not be saved.
  *
@@ -28,8 +27,12 @@ import postgresql.*;
  */
 public class Connection implements java.sql.Connection 
 {
+  // This is the network stream associated with this connection
   protected PG_Stream pg_stream;
   
+  // This is set by postgresql.Statement.setMaxRows()
+  protected int maxrows = 0;		// maximum no. of rows; 0 = unlimited
+  
   private String PG_HOST;
   private int PG_PORT;
   private String PG_USER;
@@ -59,7 +62,39 @@ public class Connection implements java.sql.Connection
   private String cursor = null;	// The positioned update cursor name
   
   // This is false for US, true for European date formats
-  protected boolean europeanDates = false;
+  //protected boolean europeanDates = false;
+  
+  /**
+   * This is the current date style of the backend
+   */
+  protected int currentDateStyle;
+  
+  /**
+   * This defines the formats for dates, according to the various date styles.
+   *
+   * <p>There are two strings for each entry. The first is the string to search
+   * for in the datestyle message, and the second the format to use.
+   *
+   * <p>To add a new date style, work out the format. Then with psql running
+   * in the date style you wish to add, type: show datestyle;
+   *
+   * <p>eg:
+   * <br><pre>
+   * => show datestyle;
+   * NOTICE:  Datestyle is SQL with European conventions
+   *                       ^^^^^^^^^^^^^^^^^
+   * </pre>The marked part of the string is the first string below. The second
+   * is your format. If a style (like ISO) ignores the US/European variants,
+   * then you can ignore the "with" part of the string.
+   */
+  protected static final String dateStyles[] = {
+    "Postgres with European",	"dd-MM-yyyy",
+    "Postgres with US",		"MM-dd-yyyy",
+    "ISO",			"yyyy-MM-dd",
+    "SQL with European",	"dd/MM/yyyy",
+    "SQL with US",		"MM/dd/yyyy",
+    "German",			"dd.MM.yyyy"
+  };
   
   // Now handle notices as warnings, so things like "show" now work
   protected SQLWarning firstWarning = null;
@@ -67,6 +102,13 @@ public class Connection implements java.sql.Connection
   /**
    * Connect to a PostgreSQL database back end.
    *
+   * <p><b>Important Notice</b>
+   *
+   * <br>Although this will connect to the database, user code should open
+   * the connection via the DriverManager.getConnection() methods only.
+   *
+   * <br>This should only be called from the postgresql.Driver class.
+   *
    * @param host the hostname of the database back end
    * @param port the port number of the postmaster process
    * @param info a Properties[] thing of the user and password
@@ -108,6 +150,7 @@ public class Connection implements java.sql.Connection
       STARTUP_CODE=STARTUP_USER;
     }
     
+    // Now make the initial connection
     try
       {
 	pg_stream = new PG_Stream(host, port);
@@ -148,6 +191,9 @@ public class Connection implements java.sql.Connection
 	clearWarnings();
 	ExecSQL("show datestyle");
 	
+	// Initialise object handling
+	initObjectTypes();
+	
 	// Mark the connection as ok, and cleanup
 	clearWarnings();
 	PG_STATUS = CONNECTION_OK;
@@ -468,10 +514,15 @@ public class Connection implements java.sql.Connection
   // **********************************************************
   
   /**
-   * This adds a warning to the warning chain
+   * This adds a warning to the warning chain.
+   * @param msg message to add
    */
   public void addWarning(String msg)
   {
+    //PrintStream log = DriverManager.getLogStream();
+    //if(log!=null) 
+    DriverManager.println(msg);
+    
     // Add the warning to the chain
     if(firstWarning!=null)
       firstWarning.setNextWarning(new SQLWarning(msg));
@@ -481,15 +532,24 @@ public class Connection implements java.sql.Connection
     // Now check for some specific messages
     
     // This is generated by the SQL "show datestyle"
-    if(msg.startsWith("NOTICE:DateStyle")) {
-      if(msg.indexOf("with US")==-1)
-	europeanDates=true;
-      else
-	europeanDates=false;
-      System.err.println("europeanDates="+europeanDates);
+    if(msg.startsWith("NOTICE:") && msg.indexOf("DateStyle")>0) {
+      // 13 is the length off "DateStyle is "
+      msg = msg.substring(msg.indexOf("DateStyle is ")+13);
+
+      for(int i=0;i<dateStyles.length;i+=2)
+	if(msg.startsWith(dateStyles[i]))
+	  currentDateStyle=i+1; // this is the index of the format
     }
   }
   
+  /**
+   * @return the date format for the current date style of the backend
+   */
+  public String getDateStyle()
+  {
+    return dateStyles[currentDateStyle];
+  }
+  
   /**
    * Send a query to the backend.  Returns one of the ResultSet
    * objects.
@@ -525,6 +585,8 @@ public class Connection implements java.sql.Connection
       
       while (!hfr || fqp > 0)
 	{
+	  Object tup=null;	// holds rows as they are recieved
+	  
 	  int c = pg_stream.ReceiveChar();
 	  
 	  switch (c)
@@ -536,7 +598,10 @@ public class Connection implements java.sql.Connection
 	    case 'B':	// Binary Data Transfer
 	      if (fields == null)
 		throw new SQLException("Tuple received before MetaData");
-	      tuples.addElement(pg_stream.ReceiveTuple(fields.length, true));
+	      tup = pg_stream.ReceiveTuple(fields.length, true);
+	      // This implements Statement.setMaxRows()
+	      if(maxrows==0 || tuples.size()<maxrows)
+		tuples.addElement(tup);
 	      break;
 	    case 'C':	// Command Status
 	      recv_status = pg_stream.ReceiveString(8192);
@@ -558,7 +623,10 @@ public class Connection implements java.sql.Connection
 	    case 'D':	// Text Data Transfer
 	      if (fields == null)
 		throw new SQLException("Tuple received before MetaData");
-	      tuples.addElement(pg_stream.ReceiveTuple(fields.length, false));
+	      tup = pg_stream.ReceiveTuple(fields.length, false);
+	      // This implements Statement.setMaxRows()
+	      if(maxrows==0 || tuples.size()<maxrows)
+		tuples.addElement(tup);
 	      break;
 	    case 'E':	// Error Message
 	      msg = pg_stream.ReceiveString(4096);
@@ -576,10 +644,7 @@ public class Connection implements java.sql.Connection
 		hfr = true;
 	      break;
 	    case 'N':	// Error Notification
-	      msg = pg_stream.ReceiveString(4096);
-	      PrintStream log = DriverManager.getLogStream();
-	      if(log!=null) log.println(msg);
-	      addWarning(msg);
+	      addWarning(pg_stream.ReceiveString(4096));
 	      break;
 	    case 'P':	// Portal Name
 	      String pname = pg_stream.ReceiveString(8192);
@@ -675,14 +740,143 @@ public class Connection implements java.sql.Connection
   }
   
   /**
-   * This method is not part of the Connection interface. Its is an extension
-   * that allows access to the PostgreSQL Large Object API
+   * This returns the Fastpath API for the current connection.
+   *
+   * <p><b>NOTE:</b> This is not part of JDBC, but allows access to
+   * functions on the postgresql backend itself.
+   *
+   * <p>It is primarily used by the LargeObject API
+   *
+   * <p>The best way to use this is as follows:
+   *
+   * <p><pre>
+   * import postgresql.fastpath.*;
+   * ...
+   * Fastpath fp = ((postgresql.Connection)myconn).getFastpathAPI();
+   * </pre>
+   *
+   * <p>where myconn is an open Connection to postgresql.
+   *
+   * @return Fastpath object allowing access to functions on the postgresql
+   * backend.
+   * @exception SQLException by Fastpath when initialising for first time
+   */
+  public Fastpath getFastpathAPI() throws SQLException
+  {
+    if(fastpath==null)
+      fastpath = new Fastpath(this,pg_stream);
+    return fastpath;
+  }
+  
+  // This holds a reference to the Fastpath API if already open
+  private Fastpath fastpath = null;
+  
+  /**
+   * This returns the LargeObject API for the current connection.
+   *
+   * <p><b>NOTE:</b> This is not part of JDBC, but allows access to
+   * functions on the postgresql backend itself.
+   *
+   * <p>The best way to use this is as follows:
+   *
+   * <p><pre>
+   * import postgresql.largeobject.*;
+   * ...
+   * LargeObjectManager lo = ((postgresql.Connection)myconn).getLargeObjectAPI();
+   * </pre>
+   *
+   * <p>where myconn is an open Connection to postgresql.
+   *
+   * @return LargeObject object that implements the API
+   * @exception SQLException by LargeObject when initialising for first time
+   */
+  public LargeObjectManager getLargeObjectAPI() throws SQLException
+  {
+    if(largeobject==null)
+      largeobject = new LargeObjectManager(this);
+    return largeobject;
+  }
+  
+  // This holds a reference to the LargeObject API if already open
+  private LargeObjectManager largeobject = null;
+  
+  /**
+   * This method is used internally to return an object based around
+   * postgresql's more unique data types.
+   *
+   * <p>It uses an internal Hashtable to get the handling class. If the
+   * type is not supported, then an instance of postgresql.util.PGobject
+   * is returned.
    *
-   * @return PGlobj class that implements the API
+   * You can use the getValue() or setValue() methods to handle the returned
+   * object. Custom objects can have their own methods.
+   *
+   * @return PGobject for this type, and set to value
+   * @exception SQLException if value is not correct for this type
    */
-  public PGlobj getLargeObjectAPI() throws SQLException
+  protected PGobject getObject(String type,String value) throws SQLException
+  {
+    PGobject obj = null;
+    try {
+      String name = (String)objectTypes.get(type);
+      obj = (PGobject)(Class.forName(name==null?"postgresql.util.PGobject":name).newInstance());
+    } catch(Exception ex) {
+      throw new SQLException("Failed to create object for "+type+": "+ex);
+    }
+    if(obj!=null) {
+      obj.setType(type);
+      obj.setValue(value);
+    }
+    return obj;
+  }
+  
+  /**
+   * This allows client code to add a handler for one of postgresql's
+   * more unique data types.
+   *
+   * <p><b>NOTE:</b> This is not part of JDBC, but an extension.
+   *
+   * <p>The best way to use this is as follows:
+   *
+   * <p><pre>
+   * ...
+   * ((postgresql.Connection)myconn).addDataType("mytype","my.class.name");
+   * ...
+   * </pre>
+   *
+   * <p>where myconn is an open Connection to postgresql.
+   *
+   * <p>The handling class must extend postgresql.util.PGobject
+   *
+   * @see postgresql.util.PGobject
+   */
+  public void addDataType(String type,String name)
+  {
+    objectTypes.put(type,name);
+  }
+  
+  // This holds the available types
+  private Hashtable objectTypes = new Hashtable();
+  
+  // This array contains the types that are supported as standard.
+  //
+  // The first entry is the types name on the database, the second
+  // the full class name of the handling class.
+  //
+  private static final String defaultObjectTypes[][] = {
+    {"box",	"postgresql.geometric.PGbox"},
+    {"circle",	"postgresql.geometric.PGcircle"},
+    {"lseg",	"postgresql.geometric.PGlseg"},
+    {"path",	"postgresql.geometric.PGpath"},
+    {"point",	"postgresql.geometric.PGpoint"},
+    {"polygon",	"postgresql.geometric.PGpolygon"}
+  };
+  
+  // This initialises the objectTypes hashtable
+  private void initObjectTypes()
   {
-    return new PGlobj(this);
+    for(int i=0;i<defaultObjectTypes.length;i++)
+      objectTypes.put(defaultObjectTypes[i][0],defaultObjectTypes[i][1]);
   }
 }
 
diff --git a/src/interfaces/jdbc/postgresql/DatabaseMetaData.java b/src/interfaces/jdbc/postgresql/DatabaseMetaData.java
index b5e8a985fb2..4e3894f66b6 100644
--- a/src/interfaces/jdbc/postgresql/DatabaseMetaData.java
+++ b/src/interfaces/jdbc/postgresql/DatabaseMetaData.java
@@ -4,17 +4,14 @@ import java.sql.*;
 import java.util.*;
 
 /**
- * @version 1.0 15-APR-1997
- * @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
- *
  * This class provides information about the database as a whole.
  *
- * Many of the methods here return lists of information in ResultSets.  You
+ * <p>Many of the methods here return lists of information in ResultSets.  You
  * can use the normal ResultSet methods such as getString and getInt to 
  * retrieve the data from these ResultSets.  If a given form of metadata is
  * not available, these methods should throw a SQLException.
  *
- * Some of these methods take arguments that are String patterns.  These
+ * <p>Some of these methods take arguments that are String patterns.  These
  * arguments all have names such as fooPattern.  Within a pattern String,
  * "%" means match any substring of 0 or more characters, and "_" means
  * match any one character.  Only metadata entries matching the search
@@ -22,7 +19,7 @@ import java.util.*;
  * ref, it means that argument's criteria should be dropped from the
  * search.
  *
- * A SQLException will be throws if a driver does not support a meta
+ * <p>A SQLException will be throws if a driver does not support a meta
  * data method.  In the case of methods that return a ResultSet, either
  * a ResultSet (which may be empty) is returned or a SQLException is
  * thrown.
@@ -33,6 +30,12 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
 {
   Connection connection;		// The connection association
   
+  // These define various OID's. Hopefully they will stay constant.
+  static final int iVarcharOid = 1043;	// OID for varchar
+  static final int iBoolOid = 16;	// OID for bool
+  static final int iInt2Oid = 21;	// OID for int2
+  static final int iInt4Oid = 23;	// OID for int4
+  
   public DatabaseMetaData(Connection conn)
   {
     this.connection = conn;
@@ -152,19 +155,21 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
   }
   
   /**
-   * What is the version of this database product.  Note that
-   * PostgreSQL 6.1 has a system catalog called pg_version - 
+   * What is the version of this database product.
+   *
+   * <p>Note that PostgreSQL 6.3 has a system catalog called pg_version - 
    * however, select * from pg_version on any database retrieves
-   * no rows.  For now, we will return the version 6.1 (in the
-   * hopes that we change this driver as often as we change the
-   * database)
+   * no rows.
+   *
+   * <p>For now, we will return the version 6.3 (in the hope that we change
+   * this driver as often as we change the database)
    *
    * @return the database version
    * @exception SQLException if a database access error occurs
    */
   public String getDatabaseProductVersion() throws SQLException
   {
-    return ("6.2");
+    return ("6.3");
   }
   
   /**
@@ -240,7 +245,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * as case sensitive and as a result store them in mixed case?
    * A JDBC-Compliant driver will always return false.
    *
-   * Predicament - what do they mean by "SQL identifiers" - if it
+   * <p>Predicament - what do they mean by "SQL identifiers" - if it
    * means the names of the tables and columns, then the answers
    * given below are correct - otherwise I don't know.
    *
@@ -290,7 +295,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * case sensitive and as a result store them in mixed case?  A
    * JDBC compliant driver will always return true. 
    *
-   * Predicament - what do they mean by "SQL identifiers" - if it
+   * <p>Predicament - what do they mean by "SQL identifiers" - if it
    * means the names of the tables and columns, then the answers
    * given below are correct - otherwise I don't know.
    *
@@ -340,7 +345,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * a space if identifier quoting isn't supported.  A JDBC Compliant
    * driver will always use a double quote character.
    *
-   * If an SQL identifier is a table name, column name, etc. then
+   * <p>If an SQL identifier is a table name, column name, etc. then
    * we do not support it.
    *
    * @return the quoting string
@@ -355,10 +360,12 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * Get a comma separated list of all a database's SQL keywords that
    * are NOT also SQL92 keywords.
    *
-   * Within PostgreSQL, the keywords are found in
+   * <p>Within PostgreSQL, the keywords are found in
    * 	src/backend/parser/keywords.c
-   * For SQL Keywords, I took the list provided at
-   * 	http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt
+   *
+   * <p>For SQL Keywords, I took the list provided at
+   * 	<a href="http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt">
+   * http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt</a>
    * which is for SQL3, not SQL-92, but it is close enough for
    * this purpose.
    *
@@ -410,7 +417,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * Get all the "extra" characters that can bew used in unquoted
    * identifier names (those beyond a-zA-Z0-9 and _)
    *
-   * From the file src/backend/parser/scan.l, an identifier is
+   * <p>From the file src/backend/parser/scan.l, an identifier is
    * {letter}{letter_or_digit} which makes it just those listed
    * above.
    *
@@ -449,14 +456,16 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
   /**
    * Is column aliasing supported?
    *
-   * If so, the SQL AS clause can be used to provide names for
+   * <p>If so, the SQL AS clause can be used to provide names for
    * computed columns or to provide alias names for columns as
    * required.  A JDBC Compliant driver always returns true.
    *
-   * e.g.
+   * <p>e.g.
    *
+   * <br><pre>
    * select count(C) as C_COUNT from T group by C;
    *
+   * </pre><br>
    * should return a column named as C_COUNT instead of count(C)
    *
    * @return true if so
@@ -506,7 +515,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
   /**
    * Are expressions in "ORCER BY" lists supported?
    * 
-   * e.g. select * from t order by a + b;
+   * <br>e.g. select * from t order by a + b;
    *
    * @return true if so
    * @exception SQLException if a database access error occurs
@@ -607,7 +616,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * Can columns be defined as non-nullable.  A JDBC Compliant driver
    * always returns true.
    *
-   * This changed from false to true in v6.2 of the driver, as this
+   * <p>This changed from false to true in v6.2 of the driver, as this
    * support was added to the backend.
    *
    * @return true if so
@@ -622,9 +631,9 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * Does this driver support the minimum ODBC SQL grammar.  This
    * grammar is defined at:
    *
-   * http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm
+   * <p><a href="http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm">http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm</a>
    *
-   * In Appendix C.  From this description, we seem to support the
+   * <p>In Appendix C.  From this description, we seem to support the
    * ODBC minimal (Level 0) grammar.
    *
    * @return true if so
@@ -1142,7 +1151,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * What is the maximum number of columns in a table? From the
    * create_table(l) manual page...
    *
-   * "The new class is created as a heap with no initial data.  A
+   * <p>"The new class is created as a heap with no initial data.  A
    * class can have no more than 1600 attributes (realistically,
    * this is limited by the fact that tuple sizes must be less than
    * 8192 bytes)..."
@@ -1393,6 +1402,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * Does a data definition statement within a transaction force
    * the transaction to commit?  I think this means something like:
    *
+   * <p><pre>
    * CREATE TABLE T (A INT);
    * INSERT INTO T (A) VALUES (2);
    * BEGIN;
@@ -1400,6 +1410,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * CREATE TABLE X (A INT);
    * SELECT A FROM T INTO X;
    * COMMIT;
+   * </pre><p>
    *
    * does the CREATE TABLE call cause a commit?  The answer is no.  
    *
@@ -1412,7 +1423,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
   }
   
   /**
-   *  Is a data definition statement within a transaction ignored?
+   * Is a data definition statement within a transaction ignored?
    * It seems to be (from experiment in previous method)
    *
    * @return true if so
@@ -1426,22 +1437,26 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
   /**
    * Get a description of stored procedures available in a catalog
    * 
-   * Only procedure descriptions matching the schema and procedure
+   * <p>Only procedure descriptions matching the schema and procedure
    * name criteria are returned.  They are ordered by PROCEDURE_SCHEM
    * and PROCEDURE_NAME
    *
-   * Each procedure description has the following columns:
-   * PROCEDURE_CAT String => procedure catalog (may be null)
-   * PROCEDURE_SCHEM String => procedure schema (may be null)
-   * PROCEDURE_NAME String => procedure name
-   * Field 4 reserved (make it null)
-   * Field 5 reserved (make it null)
-   * Field 6 reserved (make it null)
-   * REMARKS String => explanatory comment on the procedure
-   * PROCEDURE_TYPE short => kind of procedure
-   *	* procedureResultUnknown - May return a result
-   * 	* procedureNoResult - Does not return a result
-   *	* procedureReturnsResult - Returns a result
+   * <p>Each procedure description has the following columns:
+   * <ol>
+   * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
+   * <li><b>PROCEDURE_SCHEM</b> String => procedure schema (may be null)
+   * <li><b>PROCEDURE_NAME</b> String => procedure name
+   * <li><b>Field 4</b> reserved (make it null)
+   * <li><b>Field 5</b> reserved (make it null)
+   * <li><b>Field 6</b> reserved (make it null)
+   * <li><b>REMARKS</b> String => explanatory comment on the procedure
+   * <li><b>PROCEDURE_TYPE</b> short => kind of procedure
+   *	<ul>
+   *    <li> procedureResultUnknown - May return a result
+   * 	<li> procedureNoResult - Does not return a result
+   *	<li> procedureReturnsResult - Returns a result
+   *    </ul>
+   * </ol>
    *
    * @param catalog - a catalog name; "" retrieves those without a
    *	catalog; null means drop catalog name from criteria
@@ -1451,8 +1466,6 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * @return ResultSet - each row is a procedure description
    * @exception SQLException if a database access error occurs
    */
-  static final int iVarcharOid = 1043; // This is the OID for a varchar()
-  static final int iInt2Oid = 21;	 // This is the OID for an int2
   public java.sql.ResultSet getProcedures(String catalog, String schemaPattern, String procedureNamePattern) throws SQLException
   {
     // the field descriptors for the new ResultSet
@@ -1497,17 +1510,183 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
     return new ResultSet(connection, f, v, "OK", 1);
   }
   
+  /**
+   * Get a description of a catalog's stored procedure parameters
+   * and result columns.
+   *
+   * <p>Only descriptions matching the schema, procedure and parameter
+   * name criteria are returned. They are ordered by PROCEDURE_SCHEM
+   * and PROCEDURE_NAME. Within this, the return value, if any, is
+   * first. Next are the parameter descriptions in call order. The
+   * column descriptions follow in column number order.
+   *
+   * <p>Each row in the ResultSet is a parameter description or column 
+   * description with the following fields:
+   * <ol>
+   * <li><b>PROCEDURE_CAT</b> String => procedure catalog (may be null)
+   * <li><b>PROCEDURE_SCHE</b>M String => procedure schema (may be null)
+   * <li><b>PROCEDURE_NAME</b> String => procedure name
+   * <li><b>COLUMN_NAME</b> String => column/parameter name
+   * <li><b>COLUMN_TYPE</b> Short => kind of column/parameter:
+   * <ul><li>procedureColumnUnknown - nobody knows
+   * <li>procedureColumnIn - IN parameter
+   * <li>procedureColumnInOut - INOUT parameter
+   * <li>procedureColumnOut - OUT parameter
+   * <li>procedureColumnReturn - procedure return value
+   * <li>procedureColumnResult - result column in ResultSet
+   * </ul>
+   * <li><b>DATA_TYPE</b> short => SQL type from java.sql.Types
+   * <li><b>TYPE_NAME</b> String => SQL type name
+   * <li><b>PRECISION</b> int => precision
+   * <li><b>LENGTH</b> int => length in bytes of data
+   * <li><b>SCALE</b> short => scale
+   * <li><b>RADIX</b> short => radix
+   * <li><b>NULLABLE</b> short => can it contain NULL?
+   * <ul><li>procedureNoNulls - does not allow NULL values
+   * <li>procedureNullable - allows NULL values
+   * <li>procedureNullableUnknown - nullability unknown
+   * <li><b>REMARKS</b> String => comment describing parameter/column
+   * </ol>
+   * @param catalog This is ignored in postgresql, advise this is set to null
+   * @param schemaPattern This is ignored in postgresql, advise this is set to null
+   * @param procedureNamePattern a procedure name pattern
+   * @param columnNamePattern a column name pattern
+   * @return each row is a stored procedure parameter or column description
+   * @exception SQLException if a database-access error occurs
+   * @see #getSearchStringEscape
+   */
+  // Implementation note: This is required for Borland's JBuilder to work
   public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException
   {
-    // XXX-Not Implemented
-    return null;
+    // for now, this returns an empty result set.
+    Field f[] = new Field[13];
+    ResultSet r;	// ResultSet for the SQL query that we need to do
+    Vector v = new Vector();		// The new ResultSet tuple stuff
+    
+    f[0] = new Field(connection, new String("PROCEDURE_CAT"), iVarcharOid, 32);
+    f[1] = new Field(connection, new String("PROCEDURE_SCHEM"), iVarcharOid, 32);
+    f[2] = new Field(connection, new String("PROCEDURE_NAME"), iVarcharOid, 32);
+    f[3] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
+    f[4] = new Field(connection, new String("COLUMN_TYPE"), iInt2Oid, 2);
+    f[5] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
+    f[6] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
+    f[7] = new Field(connection, new String("PRECISION"), iInt4Oid, 4);
+    f[8] = new Field(connection, new String("LENGTH"), iInt4Oid, 4);
+    f[9] = new Field(connection, new String("SCALE"), iInt2Oid, 2);
+    f[10] = new Field(connection, new String("RADIX"), iInt2Oid, 2);
+    f[11] = new Field(connection, new String("NULLABLE"), iInt2Oid, 2);
+    f[12] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
+    
+    return new ResultSet(connection, f, v, "OK", 1);
   }
   
+  /**
+   * Get a description of tables available in a catalog.              
+   *
+   * <p>Only table descriptions matching the catalog, schema, table
+   * name and type criteria are returned. They are ordered by
+   * TABLE_TYPE, TABLE_SCHEM and TABLE_NAME.                      
+   * 
+   * <p>Each table description has the following columns:     
+   *
+   * <ol>
+   * <li><b>TABLE_CAT</b> String => table catalog (may be null)      
+   * <li><b>TABLE_SCHEM</b> String => table schema (may be null)         
+   * <li><b>TABLE_NAME</b> String => table name
+   * <li><b>TABLE_TYPE</b> String => table type. Typical types are "TABLE",
+   * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL
+   * TEMPORARY", "ALIAS", "SYNONYM".                             
+   * <li><b>REMARKS</b> String => explanatory comment on the table
+   * </ol>
+   *
+   * <p>The valid values for the types parameter are:
+   * "TABLE", "INDEX", "LARGE OBJECT", "SEQUENCE", "SYSTEM TABLE" and
+   * "SYSTEM INDEX"
+   *
+   * @param catalog a catalog name; For postgresql, this is ignored, and
+   * should be set to null
+   * @param schemaPattern a schema name pattern; For postgresql, this is ignored, and
+   * should be set to null
+   * @param tableNamePattern a table name pattern. For all tables this should be "%"
+   * @param types a list of table types to include; null returns
+   * all types
+   * @return each row is a table description      
+   * @exception SQLException if a database-access error occurs.                     
+   */
   public java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException
   {
-    return connection.createStatement().executeQuery("SELECT '' as TABLE_CAT,'' AS TABLE_SCHEM,relname AS TABLE_NAME,'TABLE' AS TABLE_TYPE,'' AS REMARKS FROM pg_class WHERE relkind = 'r' and relname !~ '^pg_' and relname !~ '^Inv' and relname ~ '"+tableNamePattern+"' ORDER BY TABLE_NAME");
+    // the field descriptors for the new ResultSet
+    Field f[] = new Field[5];
+    ResultSet r;	// ResultSet for the SQL query that we need to do
+    Vector v = new Vector();		// The new ResultSet tuple stuff
+    
+    f[0] = new Field(connection, new String("TABLE_CAT"), iVarcharOid, 32);
+    f[1] = new Field(connection, new String("TABLE_SCHEM"), iVarcharOid, 32);
+    f[2] = new Field(connection, new String("TABLE_NAME"), iVarcharOid, 32);
+    f[3] = new Field(connection, new String("TABLE_TYPE"), iVarcharOid, 32);
+    f[4] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
+    
+    // Now form the query
+    StringBuffer sql = new StringBuffer("select relname,oid from pg_class where ");
+    boolean notFirst=false;
+    for(int i=0;i<types.length;i++) {
+      if(notFirst)
+	sql.append(" or ");
+      for(int j=0;j<getTableTypes.length;j++)
+	if(getTableTypes[j][0].equals(types[i])) {
+	  sql.append(getTableTypes[j][1]);
+	  notFirst=true;
+	}
+    }
+    
+    // Now run the query
+    r = connection.ExecSQL(sql.toString());
+    
+    if (r.getColumnCount() != 2)
+      throw new SQLException("Unexpected return from query for table list");
+    
+    while (r.next())
+      {
+	byte[][] tuple = new byte[5][0];
+	
+	String name = r.getString(1);
+	String remarks = new String("no remarks");
+	
+	// Fetch the description for the table (if any)
+	ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(2));
+	if(dr.getTupleCount()==1) {
+	  dr.next();
+	  remarks=dr.getString(1);
+	}
+	dr.close();
+	
+	tuple[0] = null;			// Catalog name
+	tuple[1] = null;			// Schema name
+	tuple[2] = name.getBytes();		// Table name
+	tuple[3] = null;			// Table type
+	tuple[4] = remarks.getBytes();		// Remarks
+	v.addElement(tuple);
+      }
+    r.close();
+    return new ResultSet(connection, f, v, "OK", 1);
   }
   
+  // This array contains the valid values for the types argument
+  // in getTables().
+  //
+  // Each supported type consists of it's name, and the sql where
+  // clause to retrieve that value.
+  //
+  // IMPORTANT: the query must be enclosed in ( )
+  private static final String getTableTypes[][] = {
+    {"TABLE",		"(relkind='r' and relname !~ '^pg_' and relname !~ '^xinv')"},
+    {"INDEX",		"(relkind='i' and relname !~ '^pg_' and relname !~ '^xinx')"},
+    {"LARGE OBJECT",	"(relkind='r' and relname ~ '^xinv')"},
+    {"SEQUENCE",	"(relkind='S' and relname !~ '^pg_')"},
+    {"SYSTEM TABLE",	"(relkind='r' and relname ~ '^pg_')"},
+    {"SYSTEM INDEX",	"(relkind='i' and relname ~ '^pg_')"}
+  };
+  
   /**
    * Get the schema names available in this database.  The results
    * are ordered by schema name.
@@ -1522,8 +1701,15 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    */
   public java.sql.ResultSet getSchemas() throws SQLException
   {
-    // XXX-Not Implemented
-    return null;
+    // We don't use schemas, so we simply return a single schema name "".
+    //
+    Field f[] = new Field[1];
+    Vector v = new Vector();
+    byte[][] tuple = new byte[1][0];
+    f[0] = new Field(connection,new String("TABLE_SCHEM"),iVarcharOid,32);
+    tuple[0] = "".getBytes();
+    v.addElement(tuple);
+    return new ResultSet(connection,f,v,"OK",1);
   }
   
   /**
@@ -1538,10 +1724,16 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * @return ResultSet each row has a single String column that is a
    * catalog name
    */
-  // We don't use catalog names, so this returns a single catalog
   public java.sql.ResultSet getCatalogs() throws SQLException
   {
-    return connection.createStatement().executeQuery("SELECT '' as TABLE_CAT");
+    // We don't use catalogs, so we simply return a single catalog name "".
+    Field f[] = new Field[1];
+    Vector v = new Vector();
+    byte[][] tuple = new byte[1][0];
+    f[0] = new Field(connection,new String("TABLE_CAT"),iVarcharOid,32);
+    tuple[0] = "".getBytes();
+    v.addElement(tuple);
+    return new ResultSet(connection,f,v,"OK",1);
   }
   
   /**
@@ -1560,8 +1752,15 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    */
   public java.sql.ResultSet getTableTypes() throws SQLException
   {
-    // XXX-Not Implemented
-    return null;
+    Field f[] = new Field[1];
+    Vector v = new Vector();
+    byte[][] tuple = new byte[1][0];
+    f[0] = new Field(connection,new String("TABLE_TYPE"),iVarcharOid,32);
+    for(int i=0;i<getTableTypes.length;i++) {
+      tuple[0] = getTableTypes[i][0].getBytes();
+      v.addElement(tuple);
+    }
+    return new ResultSet(connection,f,v,"OK",1);
   }
   
   /**
@@ -1614,10 +1813,87 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    */
   public java.sql.ResultSet getColumns(String catalog, String schemaPattern, String tableNamePattern, String columnNamePattern) throws SQLException
   {
-    // XXX-Not Implemented
-    // PM: this will be implemented, as soon as I sort out how to convert the
-    // code from the other driver (private note: look at getProcedures() )
-    return null;
+    // the field descriptors for the new ResultSet
+    Field f[] = new Field[18];
+    ResultSet r;	// ResultSet for the SQL query that we need to do
+    Vector v = new Vector();		// The new ResultSet tuple stuff
+    
+    f[0] = new Field(connection, new String("TABLE_CAT"), iVarcharOid, 32);
+    f[1] = new Field(connection, new String("TABLE_SCHEM"), iVarcharOid, 32);
+    f[2] = new Field(connection, new String("TABLE_NAME"), iVarcharOid, 32);
+    f[3] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
+    f[4] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
+    f[5] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
+    f[6] = new Field(connection, new String("COLUMN_SIZE"), iInt4Oid, 4);
+    f[7] = new Field(connection, new String("BUFFER_LENGTH"), iVarcharOid, 32);
+    f[8] = new Field(connection, new String("DECIMAL_DIGITS"), iInt4Oid, 4);
+    f[9] = new Field(connection, new String("NUM_PREC_RADIX"), iInt4Oid, 4);
+    f[10] = new Field(connection, new String("NULLABLE"), iInt4Oid, 4);
+    f[11] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
+    f[12] = new Field(connection, new String("COLUMN_DEF"), iVarcharOid, 32);
+    f[13] = new Field(connection, new String("SQL_DATA_TYPE"), iInt4Oid, 4);
+    f[14] = new Field(connection, new String("SQL_DATETIME_SUB"), iInt4Oid, 4);
+    f[15] = new Field(connection, new String("CHAR_OCTET_LENGTH"), iVarcharOid, 32);
+    f[16] = new Field(connection, new String("ORDINAL_POSITION"), iInt4Oid,4);
+    f[17] = new Field(connection, new String("IS_NULLABLE"), iVarcharOid, 32);
+    
+    // Now form the query
+    r = connection.ExecSQL("select a.oid,c.relname,a.attname,a.atttypid,a.attnum,a.attnotnull,a.attlen from pg_class c, pg_attribute a where a.attrelid=c.oid and c.relname like '"+tableNamePattern+"' and a.attname like '"+columnNamePattern+"' and a.attnum>0 order by c.relname,a.attnum");
+    
+    while(r.next()) {
+	byte[][] tuple = new byte[18][0];
+	
+	String name = r.getString(1);
+	String remarks = new String("no remarks");
+	
+	// Fetch the description for the table (if any)
+	ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(1));
+	if(dr.getTupleCount()==1) {
+	  dr.next();
+	  remarks=dr.getString(1);
+	}
+	dr.close();
+	
+	tuple[0] = "".getBytes();	// Catalog name
+	tuple[1] = "".getBytes();	// Schema name
+	tuple[2] = r.getString(2).getBytes();	// Table name
+	tuple[3] = r.getString(3).getBytes();	// Column name
+	
+	dr = connection.ExecSQL("select typname from pg_type where oid = "+r.getString(4));
+	dr.next();
+	String typname=dr.getString(1);
+	dr.close();
+	tuple[4] = Integer.toString(Field.getSQLType(typname)).getBytes();	// Data type
+	tuple[5] = typname.getBytes();	// Type name
+	
+	tuple[6] = r.getString(7).getBytes();	// Column size
+	
+	tuple[7] = null;	// Buffer length
+	
+	tuple[8] = "0".getBytes();	// Decimal Digits - how to get this?
+	tuple[9] = "10".getBytes();	// Num Prec Radix - assume decimal
+	
+	// tuple[10] is below
+	
+	tuple[11] = remarks.getBytes();		// Remarks
+	
+	tuple[12] = null;	// column default
+	
+	tuple[13] = null;	// sql data type (unused)
+	tuple[14] = null;	// sql datetime sub (unused)
+	
+	tuple[15] = tuple[6];	// char octet length
+	
+	tuple[16] = r.getString(5).getBytes();	// ordinal position
+	
+	String nullFlag = r.getString(6);
+	tuple[10] = Integer.toString(nullFlag.equals("f")?java.sql.DatabaseMetaData.columnNullable:java.sql.DatabaseMetaData.columnNoNulls).getBytes();	// Nullable
+	tuple[17] = (nullFlag.equals("f")?"YES":"NO").getBytes();	// is nullable
+	
+	v.addElement(tuple);
+      }
+    r.close();
+    return new ResultSet(connection, f, v, "OK", 1);
   }
   
   /**
@@ -1649,8 +1925,30 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    */
   public java.sql.ResultSet getColumnPrivileges(String catalog, String schema, String table, String columnNamePattern) throws SQLException
   {
-    // XXX-Not Implemented
+    // XXX-Not Implemented as grant is broken
     return null;
+    //Field f[] = new Field[8];
+    //Vector v = new Vector();
+    //
+    //f[0] = new Field(connection,new String("TABLE_CAT"),iVarcharOid,32);
+    //f[1] = new Field(connection,new String("TABLE_SCHEM"),iVarcharOid,32);
+    //f[2] = new Field(connection,new String("TABLE_NAME"),iVarcharOid,32);
+    //f[3] = new Field(connection,new String("COLUMN_NAME"),iVarcharOid,32);
+    //f[4] = new Field(connection,new String("GRANTOR"),iVarcharOid,32);
+    //f[5] = new Field(connection,new String("GRANTEE"),iVarcharOid,32);
+    //f[6] = new Field(connection,new String("PRIVILEGE"),iVarcharOid,32);
+    //f[7] = new Field(connection,new String("IS_GRANTABLE"),iVarcharOid,32);
+    //
+    //// This is taken direct from the psql source
+    //ResultSet r = connection.ExecSQL("SELECT relname, relacl FROM pg_class, pg_user WHERE ( relkind = 'r' OR relkind = 'i') and relname !~ '^pg_' and relname !~ '^xin[vx][0-9]+' and usesysid = relowner ORDER BY relname");
+    //while(r.next()) {
+    //byte[][] tuple = new byte[8][0];
+    //tuple[0] = tuple[1]= "default".getBytes();
+    //
+    //v.addElement(tuple);
+    //}
+    //
+    //return new ResultSet(connection,f,v,"OK",1);
   }
   
   /**
@@ -1722,10 +2020,24 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    * @param nullable include columns that are nullable?
    * @return ResultSet each row is a column description
    */
+  // Implementation note: This is required for Borland's JBuilder to work
   public java.sql.ResultSet getBestRowIdentifier(String catalog, String schema, String table, int scope, boolean nullable) throws SQLException
   {
-    // XXX-Not Implemented
-    return null;
+    // for now, this returns an empty result set.
+    Field f[] = new Field[8];
+    ResultSet r;	// ResultSet for the SQL query that we need to do
+    Vector v = new Vector();		// The new ResultSet tuple stuff
+    
+    f[0] = new Field(connection, new String("SCOPE"), iInt2Oid, 2);
+    f[1] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
+    f[2] = new Field(connection, new String("DATA_TYPE"), iInt2Oid, 2);
+    f[3] = new Field(connection, new String("TYPE_NAME"), iVarcharOid, 32);
+    f[4] = new Field(connection, new String("COLUMN_SIZE"), iInt4Oid, 4);
+    f[5] = new Field(connection, new String("BUFFER_LENGTH"), iInt4Oid, 4);
+    f[6] = new Field(connection, new String("DECIMAL_DIGITS"), iInt2Oid, 2);
+    f[7] = new Field(connection, new String("PSEUDO_COLUMN"), iInt2Oid, 2);
+    
+    return new ResultSet(connection, f, v, "OK", 1);
   }
   
   /**
@@ -2078,9 +2390,29 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
    *     accurate
    * @return ResultSet each row is an index column description
    */
+  // Implementation note: This is required for Borland's JBuilder to work
   public java.sql.ResultSet getIndexInfo(String catalog, String schema, String table, boolean unique, boolean approximate) throws SQLException
   {
-    // XXX-Not Implemented
-    return null;
+    // for now, this returns an empty result set.
+    Field f[] = new Field[13];
+    ResultSet r;	// ResultSet for the SQL query that we need to do
+    Vector v = new Vector();		// The new ResultSet tuple stuff
+    
+    f[0] = new Field(connection, new String("TABLE_CAT"), iVarcharOid, 32);
+    f[1] = new Field(connection, new String("TABLE_SCHEM"), iVarcharOid, 32);
+    f[2] = new Field(connection, new String("TABLE_NAME"), iVarcharOid, 32);
+    f[3] = new Field(connection, new String("NON_UNIQUE"), iBoolOid, 1);
+    f[4] = new Field(connection, new String("INDEX_QUALIFIER"), iVarcharOid, 32);
+    f[5] = new Field(connection, new String("INDEX_NAME"), iVarcharOid, 32);
+    f[6] = new Field(connection, new String("TYPE"), iInt2Oid, 2);
+    f[7] = new Field(connection, new String("ORDINAL_POSITION"), iInt2Oid, 2);
+    f[8] = new Field(connection, new String("COLUMN_NAME"), iVarcharOid, 32);
+    f[9] = new Field(connection, new String("ASC_OR_DESC"), iVarcharOid, 32);
+    f[10] = new Field(connection, new String("CARDINALITY"), iInt4Oid, 4);
+    f[11] = new Field(connection, new String("PAGES"), iInt4Oid, 4);
+    f[12] = new Field(connection, new String("FILTER_CONDITION"), iVarcharOid, 32);
+    
+    return new ResultSet(connection, f, v, "OK", 1);
   }
 }
+
diff --git a/src/interfaces/jdbc/postgresql/Driver.java b/src/interfaces/jdbc/postgresql/Driver.java
index 7b711455ad3..4b1772c88ef 100644
--- a/src/interfaces/jdbc/postgresql/Driver.java
+++ b/src/interfaces/jdbc/postgresql/Driver.java
@@ -7,17 +7,17 @@ import java.util.*;
  * The Java SQL framework allows for multiple database drivers.  Each
  * driver should supply a class that implements the Driver interface
  *
- * The DriverManager will try to load as many drivers as it can find and then
- * for any given connection request, it will ask each driver in turn to try
- * to connect to the target URL.
+ * <p>The DriverManager will try to load as many drivers as it can find and
+ * then for any given connection request, it will ask each driver in turn
+ * to try to connect to the target URL.
  *
- * It is strongly recommended that each Driver class should be small and
+ * <p>It is strongly recommended that each Driver class should be small and
  * standalone so that the Driver class can be loaded and queried without
  * bringing in vast quantities of supporting code.
  *
- * When a Driver class is loaded, it should create an instance of itself and
- * register it with the DriverManager.  This means that a user can load and
- * register a driver by doing Class.forName("foo.bah.Driver")
+ * <p>When a Driver class is loaded, it should create an instance of itself
+ * and register it with the DriverManager.  This means that a user can load
+ * and register a driver by doing Class.forName("foo.bah.Driver")
  *
  * @see postgresql.Connection
  * @see java.sql.Driver
@@ -58,18 +58,18 @@ public class Driver implements java.sql.Driver
    * when the JDBC driverManager is asked to connect to a given URL,
    * it passes the URL to each loaded driver in turn.
    *
-   * The driver should raise an SQLException if it is the right driver
+   * <p>The driver should raise an SQLException if it is the right driver
    * to connect to the given URL, but has trouble connecting to the
    * database.
    *
-   * The java.util.Properties argument can be used to pass arbitrary
+   * <p>The java.util.Properties argument can be used to pass arbitrary
    * string tag/value pairs as connection arguments.  Normally, at least
    * "user" and "password" properties should be included in the 
    * properties.
    *
-   * Our protocol takes the form:
+   * Our protocol takes the forms:
    * <PRE>
-   *	jdbc:postgresql://host:port/database
+   *	jdbc:postgresql://host:port/database?param1=val1&...
    * </PRE>
    *
    * @param url the URL of the database to connect to
@@ -110,7 +110,8 @@ public class Driver implements java.sql.Driver
    * The getPropertyInfo method is intended to allow a generic GUI
    * tool to discover what properties it should prompt a human for
    * in order to get enough information to connect to a database.
-   * Note that depending on the values the human has supplied so
+   *
+   * <p>Note that depending on the values the human has supplied so
    * far, additional values may become necessary, so it may be necessary
    * to iterate through several calls to getPropertyInfo
    *
@@ -169,6 +170,9 @@ public class Driver implements java.sql.Driver
    * tests, otherwise it is required to return false.  JDBC compliance
    * requires full support for the JDBC API and full support for SQL 92
    * Entry Level.  
+   *
+   * <p>For PostgreSQL, this is not yet possible, as we are not SQL92
+   * compliant (yet).
    */
   public boolean jdbcCompliant()
   {
@@ -185,7 +189,7 @@ public class Driver implements java.sql.Driver
    * @param url JDBC URL to parse
    * @param defaults Default properties
    * @return Properties with elements added from the url
-   * @throws SQLException
+   * @exception SQLException
    */
   Properties parseURL(String url,Properties defaults) throws SQLException
   {
@@ -280,7 +284,7 @@ public class Driver implements java.sql.Driver
   }
   
   /**
-   * Returns the hostname portion of the URL
+   * @return the hostname portion of the URL
    */
   public String host()
   {
@@ -288,8 +292,7 @@ public class Driver implements java.sql.Driver
   }
   
   /**
-   * Returns the port number portion of the URL
-   * or -1 if no port was specified
+   * @return the port number portion of the URL or -1 if no port was specified
    */
   public int port()
   {
@@ -297,7 +300,7 @@ public class Driver implements java.sql.Driver
   }
   
   /**
-   * Returns the database name of the URL
+   * @return the database name of the URL
    */
   public String database()
   {
@@ -305,7 +308,8 @@ public class Driver implements java.sql.Driver
   }
   
   /**
-   * Returns any property
+   * @return the value of any property specified in the URL or properties
+   * passed to connect(), or null if not found.
    */
   public String property(String name)
   {
diff --git a/src/interfaces/jdbc/postgresql/Field.java b/src/interfaces/jdbc/postgresql/Field.java
index a4cc3c76e76..78553dd32eb 100644
--- a/src/interfaces/jdbc/postgresql/Field.java
+++ b/src/interfaces/jdbc/postgresql/Field.java
@@ -6,10 +6,8 @@ import java.util.*;
 import postgresql.*;
 
 /**
- * postgresql.Field is a class used to describe fields in a PostgreSQL ResultSet
- *
- * @version 1.0 15-APR-1997
- * @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
+ * postgresql.Field is a class used to describe fields in a PostgreSQL
+ * ResultSet
  */
 public class Field
 {
@@ -22,7 +20,7 @@ public class Field
   String type_name = null;// The sql type name
   
   /**
-   *	Construct a field based on the information fed to it.
+   * Construct a field based on the information fed to it.
    *
    * @param conn the connection this field came from
    * @param name the name of the field
@@ -37,6 +35,14 @@ public class Field
     this.length = length;
   }
   
+  /**
+   * @return the oid of this Field's data type
+   */
+  public int getOID()
+  {
+    return oid;
+  }
+  
   /**
    * the ResultSet and ResultMetaData both need to handle the SQL
    * type, which is gained from another query.  Note that we cannot
@@ -47,47 +53,77 @@ public class Field
    */
   public int getSQLType() throws SQLException
   {
-    if (sql_type == -1)
-      {
-	ResultSet result = (postgresql.ResultSet)conn.ExecSQL("select typname from pg_type where oid = " + oid);
-	if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
-	  throw new SQLException("Unexpected return from query for type");
-	result.next();
-	type_name = result.getString(1);
-	if (type_name.equals("int2"))
-	  sql_type = Types.SMALLINT;
-	else if (type_name.equals("int4"))
-	  sql_type = Types.INTEGER;
-	else if (type_name.equals("int8"))
-	  sql_type = Types.BIGINT;
-	else if (type_name.equals("cash"))
-	  sql_type = Types.DECIMAL;
-	else if (type_name.equals("money"))
-	  sql_type = Types.DECIMAL;
-	else if (type_name.equals("float4"))
-	  sql_type = Types.REAL;
-	else if (type_name.equals("float8"))
-	  sql_type = Types.DOUBLE;
-	else if (type_name.equals("bpchar"))
-	  sql_type = Types.CHAR;
-	else if (type_name.equals("varchar"))
-	  sql_type = Types.VARCHAR;
-	else if (type_name.equals("bool"))
-	  sql_type = Types.BIT;
-	else if (type_name.equals("date"))
-	  sql_type = Types.DATE;
-	else if (type_name.equals("time"))
-	  sql_type = Types.TIME;
-	else if (type_name.equals("abstime"))
-	  sql_type = Types.TIMESTAMP;
-	else if (type_name.equals("timestamp"))
-	  sql_type = Types.TIMESTAMP;
-	else
-	  sql_type = Types.OTHER;
-      }	
+    if(sql_type == -1) {
+      ResultSet result = (postgresql.ResultSet)conn.ExecSQL("select typname from pg_type where oid = " + oid);
+      if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
+	throw new SQLException("Unexpected return from query for type");
+      result.next();
+      sql_type = getSQLType(result.getString(1));
+      result.close();
+    }
+    return sql_type;
+  }
+  
+  /**
+   * This returns the SQL type. It is called by the Field and DatabaseMetaData classes
+   * @param type_name PostgreSQL type name
+   * @return java.sql.Types value for oid
+   */
+  public static int getSQLType(String type_name)
+  {
+    int sql_type = Types.OTHER; // default value
+    for(int i=0;i<types.length;i++)
+      if(type_name.equals(types[i]))
+	sql_type=typei[i];
     return sql_type;
   }
   
+  /**
+   * This table holds the 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 types[] = {
+    "int2",
+    "int4","oid",
+    "int8",
+    "cash","money",
+    "float4",
+    "float8",
+    "bpchar","char","char2","char4","char8","char16",
+    "varchar","text","name","filename",
+    "bool",
+    "date",
+    "time",
+    "abstime","timestamp"
+  };
+  
+  /**
+   * 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 typei[] = {
+    Types.SMALLINT,
+    Types.INTEGER,Types.INTEGER,
+    Types.BIGINT,
+    Types.DECIMAL,Types.DECIMAL,
+    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.BIT,
+    Types.DATE,
+    Types.TIME,
+    Types.TIMESTAMP,Types.TIMESTAMP
+  };
+  
   /**
    * We also need to get the type name as returned by the back end.
    * This is held in type_name AFTER a call to getSQLType.  Since
diff --git a/src/interfaces/jdbc/postgresql/PG_Stream.java b/src/interfaces/jdbc/postgresql/PG_Stream.java
index 59804c6dc6b..8c5f5215614 100644
--- a/src/interfaces/jdbc/postgresql/PG_Stream.java
+++ b/src/interfaces/jdbc/postgresql/PG_Stream.java
@@ -70,6 +70,28 @@ public class PG_Stream
     Send(buf);
   }
   
+  /**
+   * Sends an integer to the back end in reverse order.
+   *
+   * This is required when the backend uses the routines in the
+   * src/backend/libpq/pqcomprim.c module.
+   *
+   * @param val the integer to be sent
+   * @param siz the length of the integer in bytes (size of structure)
+   * @exception IOException if an I/O error occurs
+   */
+  public void SendIntegerReverse(int val, int siz) throws IOException
+  {
+    byte[] buf = new byte[siz];
+    int p=0;
+    while (siz-- > 0)
+      {
+	buf[p++] = (byte)(val & 0xff);
+	val >>= 8;
+      }
+    Send(buf);
+  }
+  
   /**
    * Send an array of bytes to the backend
    *
@@ -295,6 +317,20 @@ public class PG_Stream
       }
   }
   
+  /**
+   * This flushes any pending output to the backend. It is used primarily
+   * by the Fastpath code.
+   * @exception SQLException if an I/O error occurs
+   */
+  public void flush() throws SQLException
+  {
+    try {
+      pg_output.flush();
+    } catch (IOException e) {
+      throw new SQLException("Error flushing output: " + e.toString());
+    }
+  }
+  
   /**
    * Closes the connection
    *
diff --git a/src/interfaces/jdbc/postgresql/PreparedStatement.java b/src/interfaces/jdbc/postgresql/PreparedStatement.java
index 479f86eee92..659375064d3 100644
--- a/src/interfaces/jdbc/postgresql/PreparedStatement.java
+++ b/src/interfaces/jdbc/postgresql/PreparedStatement.java
@@ -5,21 +5,20 @@ import java.math.*;
 import java.sql.*;
 import java.text.*;
 import java.util.*;
+import postgresql.largeobject.*;
+import postgresql.util.*;
 
 /**
- * @version 6.3 15-APR-1997
- * @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A><A HREF="mailto:petermount@earthling.net">Peter Mount</A>
- *
  * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
  * This object can then be used to efficiently execute this statement multiple
  * times.
  *
- * <B>Note:</B> The setXXX methods for setting IN parameter values must
+ * <p><B>Note:</B> The setXXX methods for setting IN parameter values must
  * specify types that are compatible with the defined SQL type of the input
  * parameter.  For instance, if the IN parameter has SQL type Integer, then
  * setInt should be used.
  *
- * If arbitrary parameter type conversions are required, then the setObject 
+ * <p>If arbitrary parameter type conversions are required, then the setObject 
  * method should be used with a target SQL type.
  *
  * @see ResultSet
@@ -33,10 +32,10 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	Connection connection;
 
 	/**
-	 * Constructor for the PreparedStatement class.  Split the SQL statement
-	 * into segments - separated by the arguments.  When we rebuild the
-	 * thing with the arguments, we can substitute the args and join the
-	 * whole thing together.
+	 * Constructor for the PreparedStatement class.
+	 * Split the SQL statement into segments - separated by the arguments.
+	 * When we rebuild the thing with the arguments, we can substitute the
+	 * args and join the whole thing together.
 	 *
 	 * @param conn the instanatiating connection
 	 * @param sql the SQL statement with ? for IN markers
@@ -125,7 +124,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	/**
 	 * Set a parameter to SQL NULL
 	 *
-	 * <B>Note:</B> You must specify the parameters SQL type (although
+	 * <p><B>Note:</B> You must specify the parameters SQL type (although
 	 * PostgreSQL ignores it)
 	 *
 	 * @param parameterIndex the first parameter is 1, etc...
@@ -254,35 +253,49 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 */
 	public void setString(int parameterIndex, String x) throws SQLException
 	{
-		StringBuffer b = new StringBuffer();
-		int i;
-
-		b.append('\'');
-		for (i = 0 ; i < x.length() ; ++i)
-		{
-			char c = x.charAt(i);
-			if (c == '\\' || c == '\'')
-				b.append((char)'\\');
-			b.append(c);
-		}
-		b.append('\'');
-		set(parameterIndex, b.toString());
+	  // if the passed string is null, then set this column to null
+	  if(x==null)
+	    set(parameterIndex,"null");
+	  else {
+	    StringBuffer b = new StringBuffer();
+	    int i;
+	    
+	    b.append('\'');
+	    for (i = 0 ; i < x.length() ; ++i)
+	      {
+		char c = x.charAt(i);
+		if (c == '\\' || c == '\'')
+		  b.append((char)'\\');
+		b.append(c);
+	      }
+	    b.append('\'');
+	    set(parameterIndex, b.toString());
+	  }
 	}
 
-	/**
-	 * Set a parameter to a Java array of bytes.  The driver converts this
-	 * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
-	 * size relative to the driver's limits on VARBINARYs) when it sends
-	 * it to the database.
-	 *
-	 * @param parameterIndex the first parameter is 1...
-	 * @param x the parameter value
-	 * @exception SQLException if a database access error occurs
-	 */
-	public void setBytes(int parameterIndex, byte x[]) throws SQLException
-	{
-		throw new SQLException("Binary Data not supported");
-	}
+  /**
+   * Set a parameter to a Java array of bytes.  The driver converts this
+   * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
+   * size relative to the driver's limits on VARBINARYs) when it sends
+   * it to the database.
+   *
+   * <p>Implementation note:
+   * <br>With postgresql, this creates a large object, and stores the
+   * objects oid in this column.
+   *
+   * @param parameterIndex the first parameter is 1...
+   * @param x the parameter value
+   * @exception SQLException if a database access error occurs
+   */
+  public void setBytes(int parameterIndex, byte x[]) throws SQLException
+  {
+    LargeObjectManager lom = connection.getLargeObjectAPI();
+    int oid = lom.create();
+    LargeObject lob = lom.open(oid);
+    lob.write(x);
+    lob.close();
+    setInt(parameterIndex,oid);
+  }
 
 	/**
 	 * Set a parameter to a java.sql.Date value.  The driver converts this
@@ -294,16 +307,30 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 */
 	public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
 	{
-	  SimpleDateFormat df = new SimpleDateFormat(connection.europeanDates?"''dd-MM-yyyy''":"''MM-dd-yyyy''");
-	  
-	  set(parameterIndex, df.format(x));
+	  SimpleDateFormat df = new SimpleDateFormat("''"+connection.getDateStyle()+"''");
+	  	  
+	  // Ideally the following should work:
+	  //
+	  //    set(parameterIndex, df.format(x));
+	  //
+	  // however, SimpleDateFormat seems to format a date to the previous
+	  // day. So a fix (for now) is to add a day before formatting.
+	  // This needs more people to confirm this is really happening, or
+	  // possibly for us to implement our own formatting code.
+	  //
+	  // I've tested this with the Linux jdk1.1.3 and the Win95 JRE1.1.5
+	  //
+	  set(parameterIndex, df.format(new java.util.Date(x.getTime()+DAY)));
 	}
+  
+  // This equates to 1 day
+  private static final int DAY = 86400000;
 
 	/**
 	 * Set a parameter to a java.sql.Time value.  The driver converts
 	 * this to a SQL TIME value when it sends it to the database.
 	 *
-	 * @param parameterIndex the first parameter is 1...
+	 * @param parameterIndex the first parameter is 1...));
 	 * @param x the parameter value
 	 * @exception SQLException if a database access error occurs
 	 */
@@ -332,7 +359,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * end-of-file.  The JDBC driver will do any necessary conversion from
 	 * ASCII to the database char format.
 	 *
-	 * <B>Note:</B> This stream object can either be a standard Java
+	 * <P><B>Note:</B> This stream object can either be a standard Java
 	 * stream object or your own subclass that implements the standard
 	 * interface.
 	 *
@@ -353,7 +380,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * end-of-file.  The JDBC driver will do any necessary conversion from
 	 * UNICODE to the database char format.
 	 *
-	 * <B>Note:</B> This stream object can either be a standard Java
+	 * <P><B>Note:</B> This stream object can either be a standard Java
 	 * stream object or your own subclass that implements the standard
 	 * interface.
 	 *
@@ -372,7 +399,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * JDBC will read the data from the stream as needed, until it reaches
 	 * end-of-file.  
 	 *
-	 * <B>Note:</B> This stream object can either be a standard Java
+	 * <P><B>Note:</B> This stream object can either be a standard Java
 	 * stream object or your own subclass that implements the standard
 	 * interface.
 	 *
@@ -406,10 +433,10 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 	 * Set the value of a parameter using an object; use the java.lang
 	 * equivalent objects for integral values.
 	 *
-	 * The given Java object will be converted to the targetSqlType before
+	 * <P>The given Java object will be converted to the targetSqlType before
 	 * being sent to the database.
 	 *
-	 * note that this method may be used to pass database-specific
+	 * <P>note that this method may be used to pass database-specific
 	 * abstract data types.  This is done by using a Driver-specific
 	 * Java type and using a targetSqlType of java.sql.Types.OTHER
 	 *
@@ -450,7 +477,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 			case Types.TIMESTAMP:
 				setTimestamp(parameterIndex, (Timestamp)x);
 			case Types.OTHER:
-				setString(parameterIndex, ((PG_Object)x).value);
+				setString(parameterIndex, ((PGobject)x).getValue());
 			default:
 				throw new SQLException("Unknown Types value");
 		}
@@ -485,8 +512,8 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
 			setTimestamp(parameterIndex, (Timestamp)x);
 		else if (x instanceof Boolean)
 			setBoolean(parameterIndex, ((Boolean)x).booleanValue());
-		else if (x instanceof PG_Object)
-			setString(parameterIndex, ((PG_Object)x).value);
+		else if (x instanceof PGobject)
+			setString(parameterIndex, ((PGobject)x).getValue());
 		else
 			throw new SQLException("Unknown object type");
 	}
diff --git a/src/interfaces/jdbc/postgresql/ResultSet.java b/src/interfaces/jdbc/postgresql/ResultSet.java
index 017b0ad2927..f8eea22595e 100644
--- a/src/interfaces/jdbc/postgresql/ResultSet.java
+++ b/src/interfaces/jdbc/postgresql/ResultSet.java
@@ -6,31 +6,32 @@ import java.math.*;
 import java.text.*;
 import java.util.*;
 import java.sql.*;
-import postgresql.*;
+import postgresql.largeobject.*;
+import postgresql.util.*;
 
 /**
  * A ResultSet provides access to a table of data generated by executing a
  * Statement.  The table rows are retrieved in sequence.  Within a row its
  * column values can be accessed in any order.
  *
- * A ResultSet maintains a cursor pointing to its current row of data.  
+ * <P>A ResultSet maintains a cursor pointing to its current row of data.  
  * Initially the cursor is positioned before the first row.  The 'next'
  * method moves the cursor to the next row.
  *
- * The getXXX methods retrieve column values for the current row.  You can
+ * <P>The getXXX methods retrieve column values for the current row.  You can
  * retrieve values either using the index number of the column, or by using
  * the name of the column.  In general using the column index will be more
  * efficient.  Columns are numbered from 1.
  *
- * For maximum portability, ResultSet columns within each row should be read
+ * <P>For maximum portability, ResultSet columns within each row should be read
  * in left-to-right order and each column should be read only once.
  *
- * For the getXXX methods, the JDBC driver attempts to convert the underlying
- * data to the specified Java type and returns a suitable Java value.  See the
- * JDBC specification for allowable mappings from SQL types to Java types with
- * the ResultSet getXXX methods.
+ *<P> For the getXXX methods, the JDBC driver attempts to convert the
+ * underlying data to the specified Java type and returns a suitable Java
+ * value.  See the JDBC specification for allowable mappings from SQL types
+ * to Java types with the ResultSet getXXX methods.
  *
- * Column names used as input to getXXX methods are case insenstive.  When
+ * <P>Column names used as input to getXXX methods are case insenstive.  When
  * performing a getXXX using a column name, if several columns have the same
  * name, then the value of the first matching column will be returned.  The
  * column name option is designed to be used when column names are used in the
@@ -39,11 +40,11 @@ import postgresql.*;
  * the programmer to guarentee that they actually refer to the intended
  * columns.
  *
- * A ResultSet is automatically closed by the Statement that generated it 
+ * <P>A ResultSet is automatically closed by the Statement that generated it 
  * when that Statement is closed, re-executed, or is used to retrieve the 
  * next result from a sequence of multiple results.
  *
- * The number, types and properties of a ResultSet's columns are provided by
+ * <P>The number, types and properties of a ResultSet's columns are provided by
  * the ResultSetMetaData object returned by the getMetaData method.
  *
  * @see ResultSetMetaData
@@ -92,7 +93,7 @@ public class ResultSet implements java.sql.ResultSet
    * the first call to next makes the first row the current row;
    * the second call makes the second row the current row, etc.
    *
-   * If an input stream from the previous row is open, it is
+   * <p>If an input stream from the previous row is open, it is
    * implicitly closed.  The ResultSet's warning chain is cleared
    * when a new row is read
    *
@@ -114,7 +115,7 @@ public class ResultSet implements java.sql.ResultSet
    * when it is automatically closed.  The close method provides this
    * immediate release.
    *
-   * <B>Note:</B> A ResultSet is automatically closed by the Statement
+   * <p><B>Note:</B> A ResultSet is automatically closed by the Statement
    * the Statement that generated it when that Statement is closed,
    * re-executed, or is used to retrieve the next result from a sequence
    * of multiple results.  A ResultSet is also automatically closed 
@@ -150,11 +151,17 @@ public class ResultSet implements java.sql.ResultSet
    */
   public String getString(int columnIndex) throws SQLException
   {
-    byte[] bytes = getBytes(columnIndex);
-    
-    if (bytes == null)
+    //byte[] bytes = getBytes(columnIndex);
+    //
+    //if (bytes == null)
+    //return null;
+    //return new String(bytes);
+    if (columnIndex < 1 || columnIndex > fields.length)
+      throw new SQLException("Column Index out of range");
+    wasNullFlag = (this_row[columnIndex - 1] == null);
+    if(wasNullFlag)
       return null;
-    return new String(bytes);
+    return new String(this_row[columnIndex - 1]);
   }
   
   /**
@@ -347,8 +354,14 @@ public class ResultSet implements java.sql.ResultSet
   }
   
   /**
-   * Get the value of a column in the current row as a Java byte array
-   * The bytes represent the raw values returned by the driver.
+   * Get the value of a column in the current row as a Java byte array.
+   *
+   * <p>In normal use, the bytes represent the raw values returned by the
+   * backend. However, if the column is an OID, then it is assumed to
+   * refer to a Large Object, and that object is returned as a byte array.
+   *
+   * <p><b>Be warned</b> If the large object is huge, then you may run out
+   * of memory.
    *
    * @param columnIndex the first column is 1, the second is 2, ...
    * @return the column value; if the value is SQL NULL, the result
@@ -360,6 +373,17 @@ public class ResultSet implements java.sql.ResultSet
     if (columnIndex < 1 || columnIndex > fields.length)
       throw new SQLException("Column Index out of range");
     wasNullFlag = (this_row[columnIndex - 1] == null);
+    
+    // Handle OID's as BLOBS
+    if(!wasNullFlag)
+      if( fields[columnIndex - 1].getOID() == 26) {
+	LargeObjectManager lom = connection.getLargeObjectAPI();
+	LargeObject lob = lom.open(getInt(columnIndex));
+	byte buf[] = lob.read(lob.size());
+	lob.close();
+	return buf;
+      }
+    
     return this_row[columnIndex - 1];
   }
   
@@ -374,7 +398,7 @@ public class ResultSet implements java.sql.ResultSet
   public java.sql.Date getDate(int columnIndex) throws SQLException
   {
     String s = getString(columnIndex);
-    SimpleDateFormat df = new SimpleDateFormat(connection.europeanDates?"dd-MM-yyyy":"MM-dd-yyyy");
+    SimpleDateFormat df = new SimpleDateFormat(connection.getDateStyle());
     try {
       return new java.sql.Date(df.parse(s).getTime());
     } catch (ParseException e) {
@@ -449,13 +473,13 @@ public class ResultSet implements java.sql.ResultSet
    * The JDBC driver will do any necessary conversion from the
    * database format into ASCII.
    *
-   * <B>Note:</B> All the data in the returned stream must be read
+   * <p><B>Note:</B> All the data in the returned stream must be read
    * prior to getting the value of any other column.  The next call
    * to a get method implicitly closes the stream.  Also, a stream
    * may return 0 for available() whether there is data available
    * or not.
    *
-   * We implement an ASCII stream as a Binary stream - we should really
+   *<p> We implement an ASCII stream as a Binary stream - we should really
    * do the data conversion, but I cannot be bothered to implement this
    * right now.
    *
@@ -494,8 +518,8 @@ public class ResultSet implements java.sql.ResultSet
    *
    * @param columnIndex the first column is 1, the second is 2...
    * @return a Java InputStream that delivers the database column value
-   * 	as a stream of two byte Unicode characters.  If the value is
-   *	SQL NULL, then the result is null
+   * as a stream of bytes.  If the value is SQL NULL, then the result
+   * is null
    * @exception SQLException if a database access error occurs
    * @see getAsciiStream
    * @see getUnicodeStream
@@ -603,10 +627,10 @@ public class ResultSet implements java.sql.ResultSet
    * returned.  Subsequent ResultSet warnings will be chained
    * to this SQLWarning.
    *
-   * The warning chain is automatically cleared each time a new
+   * <p>The warning chain is automatically cleared each time a new
    * row is read.
    *
-   * <B>Note:</B> This warning chain only covers warnings caused by
+   * <p><B>Note:</B> This warning chain only covers warnings caused by
    * ResultSet methods.  Any warnings caused by statement methods
    * (such as reading OUT parameters) will be chained on the
    * Statement object.
@@ -633,16 +657,16 @@ public class ResultSet implements java.sql.ResultSet
   /**
    * Get the name of the SQL cursor used by this ResultSet
    *
-   * In SQL, a result table is retrieved though a cursor that is
+   * <p>In SQL, a result table is retrieved though a cursor that is
    * named.  The current row of a result can be updated or deleted
    * using a positioned update/delete statement that references
    * the cursor name.
    *
-   * JDBC supports this SQL feature by providing the name of the
+   * <p>JDBC supports this SQL feature by providing the name of the
    * SQL cursor used by a ResultSet.  The current row of a ResulSet
    * is also the current row of this SQL cursor.
    *
-   * <B>Note:</B> If positioned update is not supported, a SQLException
+   * <p><B>Note:</B> If positioned update is not supported, a SQLException
    * is thrown.
    *
    * @return the ResultSet's SQL cursor name.
@@ -668,12 +692,12 @@ public class ResultSet implements java.sql.ResultSet
   /**
    * Get the value of a column in the current row as a Java object
    *
-   * This method will return the value of the given column as a
+   * <p>This method will return the value of the given column as a
    * Java object.  The type of the Java object will be the default
    * Java Object type corresponding to the column's SQL type, following
    * the mapping specified in the JDBC specification.
    *
-   * This method may also be used to read database specific abstract
+   * <p>This method may also be used to read database specific abstract
    * data types.
    *
    * @param columnIndex the first column is 1, the second is 2...
@@ -714,19 +738,19 @@ public class ResultSet implements java.sql.ResultSet
       case Types.TIMESTAMP:
 	return getTimestamp(columnIndex);
       default:
-	return new PG_Object(field.getTypeName(), getString(columnIndex));
+	return connection.getObject(field.getTypeName(), getString(columnIndex));
       }
   }
   
   /**
    * Get the value of a column in the current row as a Java object
    *
-   * This method will return the value of the given column as a
+   *<p> This method will return the value of the given column as a
    * Java object.  The type of the Java object will be the default
    * Java Object type corresponding to the column's SQL type, following
    * the mapping specified in the JDBC specification.
    *
-   * This method may also be used to read database specific abstract
+   * <p>This method may also be used to read database specific abstract
    * data types.
    *
    * @param columnName is the SQL name of the column
@@ -816,8 +840,6 @@ public class ResultSet implements java.sql.ResultSet
    * particular, we need to know the number of rows and the
    * number of columns.  Rows are also known as Tuples
    *
-   * getTupleCount returns the number of rows
-   *
    * @return the number of rows
    */
   public int getTupleCount()
diff --git a/src/interfaces/jdbc/postgresql/ResultSetMetaData.java b/src/interfaces/jdbc/postgresql/ResultSetMetaData.java
index 7d2c1ceaf33..c4e54dbefaa 100644
--- a/src/interfaces/jdbc/postgresql/ResultSetMetaData.java
+++ b/src/interfaces/jdbc/postgresql/ResultSetMetaData.java
@@ -6,9 +6,6 @@ import java.util.*;
 import postgresql.*;
 
 /**
- * @version 1.0 15-APR-1997
- * @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
- *
  * A ResultSetMetaData object can be used to find out about the types and
  * properties of the columns in a ResultSet
  *
diff --git a/src/interfaces/jdbc/postgresql/Statement.java b/src/interfaces/jdbc/postgresql/Statement.java
index 464a263621f..177b8189f6c 100644
--- a/src/interfaces/jdbc/postgresql/Statement.java
+++ b/src/interfaces/jdbc/postgresql/Statement.java
@@ -3,13 +3,10 @@ package postgresql;
 import java.sql.*;
 
 /**
- * @version 1.0 15-APR-1997
- * @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
- *
  * A Statement object is used for executing a static SQL statement and
  * obtaining the results produced by it.
  *
- * Only one ResultSet per Statement can be open at any point in time.  
+ * <p>Only one ResultSet per Statement can be open at any point in time.  
  * Therefore, if the reading of one ResultSet is interleaved with the
  * reading of another, each must have been generated by different
  * Statements.  All statement execute methods implicitly close a
@@ -23,7 +20,6 @@ public class Statement implements java.sql.Statement
 	Connection connection;		// The connection who created us
 	ResultSet result = null;	// The current results
 	SQLWarning warnings = null;	// The warnings chain.
-	int maxrows = 0;		// maximum no. of rows; 0 = unlimited
 	int timeout = 0;		// The timeout for a query (not used)
 	boolean escapeProcessing = true;// escape processing flag
 
@@ -78,7 +74,7 @@ public class Statement implements java.sql.Statement
 	 * for this to happen when it is automatically closed.  The
 	 * close method provides this immediate release.
 	 *
-	 * <B>Note:</B> A Statement is automatically closed when it is 
+	 * <p><B>Note:</B> A Statement is automatically closed when it is 
 	 * garbage collected.  When a Statement is closed, its current 
 	 * ResultSet, if one exists, is also closed.
 	 *
@@ -126,7 +122,7 @@ public class Statement implements java.sql.Statement
 	 */
 	public int getMaxRows() throws SQLException
 	{
-		return maxrows;
+		return connection.maxrows;
 	}
 
 	/**
@@ -138,7 +134,7 @@ public class Statement implements java.sql.Statement
 	 */
 	public void setMaxRows(int max) throws SQLException
 	{
-		maxrows = max;
+	  connection.maxrows = max;
 	}
 
 	/**
@@ -197,10 +193,10 @@ public class Statement implements java.sql.Statement
 	 * chain.  Subsequent Statement warnings will be chained to this
 	 * SQLWarning.
 	 *
-	 * The Warning chain is automatically cleared each time a statement
+	 * <p>The Warning chain is automatically cleared each time a statement
 	 * is (re)executed.
 	 *
-	 * <B>Note:</B>  If you are processing a ResultSet then any warnings
+	 * <p><B>Note:</B>  If you are processing a ResultSet then any warnings
 	 * associated with ResultSet reads will be chained on the ResultSet
 	 * object.
 	 *
@@ -231,12 +227,12 @@ public class Statement implements java.sql.Statement
 	 * doesn't support positioned update/delete, this method is a
 	 * no-op.
 	 *
-	 * <B>Note:</B> By definition, positioned update/delete execution
+	 * <p><B>Note:</B> By definition, positioned update/delete execution
 	 * must be done by a different Statement than the one which
 	 * generated the ResultSet being used for positioning.  Also, cursor
 	 * names must be unique within a Connection.
 	 *
-	 * We throw an additional constriction.  There can only be one
+	 * <p>We throw an additional constriction.  There can only be one
 	 * cursor active at any one time.
 	 *
 	 * @param name the new cursor name
-- 
GitLab