Peter's Mega-Patch for JDBC...
authorMarc G. Fournier
Sun, 11 Jan 1998 21:14:56 +0000 (21:14 +0000)
committerMarc G. Fournier
Sun, 11 Jan 1998 21:14:56 +0000 (21:14 +0000)
see README_6.3 for list of changes

13 files changed:
src/interfaces/jdbc/Makefile
src/interfaces/jdbc/README
src/interfaces/jdbc/README_6.3 [new file with mode: 0644]
src/interfaces/jdbc/postgresql/CallableStatement.java
src/interfaces/jdbc/postgresql/Connection.java
src/interfaces/jdbc/postgresql/DatabaseMetaData.java
src/interfaces/jdbc/postgresql/Driver.java
src/interfaces/jdbc/postgresql/Field.java
src/interfaces/jdbc/postgresql/PG_Stream.java
src/interfaces/jdbc/postgresql/PreparedStatement.java
src/interfaces/jdbc/postgresql/ResultSet.java
src/interfaces/jdbc/postgresql/ResultSetMetaData.java
src/interfaces/jdbc/postgresql/Statement.java

index 469b552a69922d0567f0a0c854c40191c56d47c4..928aafae5ef51781fd534837e9d5b848b549cba4 100644 (file)
@@ -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
+#######################################################################
index cd43a5af2f3ac0459174f4dd745ce33c2b7e6f39..035ad008bf3a830f694b47a3a2c935055c13580d 100644 (file)
@@ -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: [email protected] http://www.demon.co.uk/finder
 work email: [email protected] 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 (file)
index 0000000..797d3ff
--- /dev/null
@@ -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
+
index ede69bbb121e82e6d6794dab6e2577514a8c9d76..7f56a42b2a539d93f4e7641d4425c3e7e1ebce9f 100644 (file)
@@ -4,46 +4,114 @@ import java.sql.*;
 import java.math.*;
 
 /**
- * JDBC Interface to Postgres95 functions
+ * CallableStatement is used to execute SQL stored procedures.
+ *
+ * 

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 [,, ...]}                 
+ * {call [,, ...]}       
+ *
+ *
+ * 

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.
+ *
+ * 

A Callable statement may return a ResultSet or multiple ResultSets.

+ * Multiple ResultSets are handled using operations inherited from
+ * Statement.
+ *
+ * 

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.
+   *
+   * 

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:
+   *
+   * 

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.
+   *
+   * 

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.
+   *
+   * 

This method returns a Java object whose type coresponds to the

+   * SQL type that was registered for this parameter using
+   * registerOutParameter.
+   *
+   * 

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.
+   *
+   * 

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;
index 09344e1fe08e3608f4917eebaf39b637270e1cb5..1c13b520d5b85376211c056151a3e3a7c46ad0ac 100644 (file)
@@ -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 Adrian Hall
- *
  * 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
+ * 

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.
  *
- * Note: By default, the Connection automatically commits changes
+ * <p><B>Note: 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.
+   *
+   * 

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.
+   *
+   * 

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;
+   *
+   * 

eg:

+   * 
+   * => show datestyle;
+   * NOTICE:  Datestyle is SQL with European conventions
+   *                       ^^^^^^^^^^^^^^^^^
+   * 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.
    *
+   * 

Important Notice

+   *
+   * 
Although this will connect to the database, user code should open
+   * the connection via the DriverManager.getConnection() methods only.
+   *
+   * 
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
+   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()
+       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()
+       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.
+   *
+   * 

NOTE: This is not part of JDBC, but allows access to

+   * functions on the postgresql backend itself.
+   *
+   * 

It is primarily used by the LargeObject API

+   *
+   * 

The best way to use this is as follows:

+   *
+   * 

+   * import postgresql.fastpath.*;
+   * ...
+   * Fastpath fp = ((postgresql.Connection)myconn).getFastpathAPI();
+   * 
+   *
+   * 

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.
+   *
+   * 

NOTE: This is not part of JDBC, but allows access to

+   * functions on the postgresql backend itself.
+   *
+   * 

The best way to use this is as follows:

+   *
+   * 

+   * import postgresql.largeobject.*;
+   * ...
+   * LargeObjectManager lo = ((postgresql.Connection)myconn).getLargeObjectAPI();
+   * 
+   *
+   * 

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.
+   *
+   * 

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.
+   *
+   * 

NOTE: This is not part of JDBC, but an extension.

+   *
+   * 

The best way to use this is as follows:

+   *
+   * 

+   * ...
+   * ((postgresql.Connection)myconn).addDataType("mytype","my.class.name");
+   * ...
+   * 
+   *
+   * 

where myconn is an open Connection to postgresql.

+   *
+   * 

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
+      objectTypes.put(defaultObjectTypes[i][0],defaultObjectTypes[i][1]);
   }
 }
 
index b5e8a985fb2a9ac6f24db53c674eddf8983e17e2..4e3894f66b6e170702b7dbb3afe94da049e5535f 100644 (file)
@@ -4,17 +4,14 @@ import java.sql.*;
 import java.util.*;
 
 /**
- * @version 1.0 15-APR-1997
- * @author Adrian Hall
- *
  * This class provides information about the database as a whole.
  *
- * Many of the methods here return lists of information in ResultSets.  You
+ * 

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
+ * 

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
+ * 

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.
+   *
+   * 

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.
+   *
+   * 

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
+   * 

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
+   * 

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
+   * 

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
+   * 

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
+   *
+   * 

For SQL Keywords, I took the list provided at

+   *   
+   * http://web.dementia.org/~shadow/sql/sql3bnf.sep93.txt
    * 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
+   * 

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
+   * 

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.
+   * 

e.g.

    *
+   * 
    * select count(C) as C_COUNT from T group by C;
    *
+   * 
    * 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;
+   * 
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
+   * 

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
+   * 

http://www.microsoft.com/msdn/sdk/platforms/doc/odbc/src/intropr.htm

    *
-   * In Appendix C.  From this description, we seem to support the
+   * 

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
+   * 

"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:
    *
+   * 

    * 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;
+   * 

    *
    * 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
+   * 

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
+   * 

Each procedure description has the following columns:

+   * 
    +   * 
  1. PROCEDURE_CAT String => procedure catalog (may be null)
  2. +   * 
  3. PROCEDURE_SCHEM String => procedure schema (may be null)
  4. +   * 
  5. PROCEDURE_NAME String => procedure name
  6. +   * 
  7. Field 4 reserved (make it null)
  8. +   * 
  9. Field 5 reserved (make it null)
  10. +   * 
  11. Field 6 reserved (make it null)
  12. +   * 
  13. REMARKS String => explanatory comment on the procedure
  14. +   * 
  15. PROCEDURE_TYPE short => kind of procedure
  16. +   *   
      +   *    
    •  procedureResultUnknown - May return a result
    • +   *   
    •  procedureNoResult - Does not return a result
    • +   *   
    •  procedureReturnsResult - Returns a result
    • +   *    
      +   * 
          *
          * @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.
      +   *
      +   * 

      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.
      +   *
      +   * 

      Each row in the ResultSet is a parameter description or column 

      +   * description with the following fields:
      +   * 
        +   * 
      1. PROCEDURE_CAT String => procedure catalog (may be null)
      2. +   * 
      3. PROCEDURE_SCHEM String => procedure schema (may be null)
      4. +   * 
      5. PROCEDURE_NAME String => procedure name
      6. +   * 
      7. COLUMN_NAME String => column/parameter name
      8. +   * 
      9. COLUMN_TYPE Short => kind of column/parameter:
      10. +   * 
        • procedureColumnUnknown - nobody knows
        +   * 
      11. procedureColumnIn - IN parameter
      12. +   * 
      13. procedureColumnInOut - INOUT parameter
      14. +   * 
      15. procedureColumnOut - OUT parameter
      16. +   * 
      17. procedureColumnReturn - procedure return value
      18. +   * 
      19. procedureColumnResult - result column in ResultSet
      20. +   * 
        +   * 
      21. DATA_TYPE short => SQL type from java.sql.Types
      22. +   * 
      23. TYPE_NAME String => SQL type name
      24. +   * 
      25. PRECISION int => precision
      26. +   * 
      27. LENGTH int => length in bytes of data
      28. +   * 
      29. SCALE short => scale
      30. +   * 
      31. RADIX short => radix
      32. +   * 
      33. NULLABLE short => can it contain NULL?
      34. +   * 
        • procedureNoNulls - does not allow NULL values
        +   * 
      35. procedureNullable - allows NULL values
      36. +   * 
      37. procedureNullableUnknown - nullability unknown
      38. +   * 
      39. REMARKS String => comment describing parameter/column
      40. +   * 
        +   * @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.              
        +   *
        +   * 

        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.                      
        +   * 
        +   * 

        Each table description has the following columns:     

        +   *
        +   * 
          +   * 
        1. TABLE_CAT String => table catalog (may be null)      
        2. +   * 
        3. TABLE_SCHEM String => table schema (may be null)         
        4. +   * 
        5. TABLE_NAME String => table name
        6. +   * 
        7. TABLE_TYPE String => table type. Typical types are "TABLE",
        8. +   * "VIEW", "SYSTEM TABLE", "GLOBAL TEMPORARY", "LOCAL
          +   * TEMPORARY", "ALIAS", "SYNONYM".                             
          +   * 
        9. REMARKS String => explanatory comment on the table
        10. +   * 
          +   *
          +   * 

          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
          +      if(notFirst)
          +   sql.append(" or ");
          +      for(int j=0;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
          +      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);
             }
           }
          +
          index 7b711455ad386af7d18711ea2328ea88781aebd0..4b1772c88efae0d06a01ff93545a77e1334e2fed 100644 (file)
          @@ -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.
          + * 

          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
          + * 

          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")
          + * 

          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
          +   * 

          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
          +   * 

          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:
              * 
          -   *   jdbc:postgresql://host:port/database
          +   *   jdbc:postgresql://host:port/database?param1=val1&...
              * 
              *
              * @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
          +   *
          +   * 

          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.  
          +   *
          +   * 

          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)
             {
          index a4cc3c76e76bff3436674d5a89b326eb128b64c5..78553dd32ebad25aa37f84c00558f3adc1d900b0 100644 (file)
          @@ -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 Adrian Hall
          + * 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
          +      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
          index 59804c6dc6b4ead83e65107d3df9c618b506dc62..8c5f521561465dfda55e4c0cf2c9fc2da2219593 100644 (file)
          @@ -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
              *
          index 479f86eee9215b6fae0f9a88730331d024d6c793..659375064d3df97e191c2a9513d0869d4247410f 100644 (file)
          @@ -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 Adrian HallPeter Mount
          - *
            * 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.
            *
          - * Note: The setXXX methods for setting IN parameter values must
          + * <p><B>Note: 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 
          + * 

          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
               *
          -    * Note: You must specify the parameters SQL type (although
          +    * <p><B>Note: 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.
          +   *
          +   * 

          Implementation note:

          +   * 
          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.
               *
          -    * Note: This stream object can either be a standard Java
          +    * <P><B>Note: 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.
               *
          -    * Note: This stream object can either be a standard Java
          +    * <P><B>Note: 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.  
               *
          -    * Note: This stream object can either be a standard Java
          +    * <P><B>Note: 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
          +    * 

          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
          +    * 

          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");
              }
          index 017b0ad29272997a055377ed14f1bb134eb6e9ae..f8eea22595e9e885faec1cf047992d910d10b2ba 100644 (file)
          @@ -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.  
          + * 

          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
          + * 

          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
          + * 

          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.
          + *

           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
          + * 

          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 
          + * 

          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
          + * 

          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
          +   * 

          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.
              *
          -   * Note: A ResultSet is automatically closed by the Statement
          +   * <p><B>Note: 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.
          +   *
          +   * 

          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.
          +   *
          +   * 

          Be warned 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.
              *
          -   * Note: All the data in the returned stream must be read
          +   * <p><B>Note: 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
          +   *

           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
          +   * 

          The warning chain is automatically cleared each time a new

              * row is read.
              *
          -   * Note: This warning chain only covers warnings caused by
          +   * <p><B>Note: 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
          +   * 

          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
          +   * 

          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.
              *
          -   * Note: If positioned update is not supported, a SQLException
          +   * <p><B>Note: 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
          +   * 

          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
          +   * 

          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
          +   *

           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
          +   * 

          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()
          index 7d2c1ceaf333352b3a09a1be08014b6bbe540069..c4e54dbefaaaf1922d441008820d00dfb1439b11 100644 (file)
          @@ -6,9 +6,6 @@ import java.util.*;
           import postgresql.*;
           
           /**
          - * @version 1.0 15-APR-1997
          - * @author Adrian Hall
          - *
            * A ResultSetMetaData object can be used to find out about the types and
            * properties of the columns in a ResultSet
            *
          index 464a263621f3979cd338c087beec63563228e662..177b8189f6c1e3e2db49a5999e8bf109eb450af1 100644 (file)
          @@ -3,13 +3,10 @@ package postgresql;
           import java.sql.*;
           
           /**
          - * @version 1.0 15-APR-1997
          - * @author Adrian Hall
          - *
            * 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.  
          + * 

          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.
               *
          -    * Note: A Statement is automatically closed when it is 
          +    * <p><B>Note: 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
          +    * 

          The Warning chain is automatically cleared each time a statement

               * is (re)executed.
               *
          -    * Note:  If you are processing a ResultSet then any warnings
          +    * <p><B>Note:  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.
               *
          -    * Note: By definition, positioned update/delete execution
          +    * <p><B>Note: 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
          +    * 

          We throw an additional constriction.  There can only be one

               * cursor active at any one time.
               *
               * @param name the new cursor name