提交 ba977c08 编写于 作者: M Marc G. Fournier

Peter's Mega-Patch for JDBC...

see README_6.3 for list of changes
上级 4bad5be7
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
# Makefile for Java JDBC interface # Makefile for Java JDBC interface
# #
# IDENTIFICATION # 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 ...@@ -22,41 +22,70 @@ RM = rm -f
$(JAVAC) $< $(JAVAC) $<
.SUFFIXES: .class .java .SUFFIXES: .class .java
.PHONY: all clean doc .PHONY: all clean doc examples
all: postgresql.jar 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: 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 \ OBJS= postgresql/CallableStatement.class \
postgresql/Connection.class \ postgresql/Connection.class \
postgresql/DatabaseMetaData.class \ postgresql/DatabaseMetaData.class \
postgresql/Driver.class \ postgresql/Driver.class \
postgresql/Field.class \ postgresql/Field.class \
postgresql/PG_Object.class \
postgresql/PG_Stream.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/PreparedStatement.class \
postgresql/ResultSet.class \ postgresql/ResultSet.class \
postgresql/ResultSetMetaData.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) postgresql.jar: $(OBJS)
$(JAR) -c0vf $@ $^ $(JAR) -c0vf $@ $$($(FIND) postgresql -name "*.class" -print)
# This rule removes any temporary and compiled files from the source tree. # This rule removes any temporary and compiled files from the source tree.
clean: clean:
$(FIND) . -name "*~" -exec $(RM) {} \; $(FIND) . -name "*~" -exec $(RM) {} \;
$(FIND) . -name "*.class" -exec $(RM) {} \; $(FIND) . -name "*.class" -exec $(RM) {} \;
$(FIND) . -name "*.html" -exec $(RM) {} \;
$(RM) postgresql.jar $(RM) postgresql.jar
-$(RM) -rf Package-postgresql *output
####################################################################### #######################################################################
# This helps make workout what classes are from what source files # This helps make workout what classes are from what source files
...@@ -69,21 +98,56 @@ postgresql/Connection.class: postgresql/Connection.java ...@@ -69,21 +98,56 @@ postgresql/Connection.class: postgresql/Connection.java
postgresql/DatabaseMetaData.class: postgresql/DatabaseMetaData.java postgresql/DatabaseMetaData.class: postgresql/DatabaseMetaData.java
postgresql/Driver.class: postgresql/Driver.java postgresql/Driver.class: postgresql/Driver.java
postgresql/Field.class: postgresql/Field.java postgresql/Field.class: postgresql/Field.java
postgresql/PG_Object.class: postgresql/PG_Object.java
postgresql/PG_Stream.class: postgresql/PG_Stream.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/PreparedStatement.class: postgresql/PreparedStatement.java
postgresql/ResultSet.class: postgresql/ResultSet.java postgresql/ResultSet.class: postgresql/ResultSet.java
postgresql/ResultSetMetaData.class: postgresql/ResultSetMetaData.java postgresql/ResultSetMetaData.class: postgresql/ResultSetMetaData.java
postgresql/Statement.class: postgresql/Statement.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
#######################################################################
...@@ -10,6 +10,14 @@ or the JDBC mailing list: ...@@ -10,6 +10,14 @@ or the JDBC mailing list:
http://www.blackdown.org 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 COMPILING
...@@ -115,15 +123,21 @@ them to the URL. eg: ...@@ -115,15 +123,21 @@ them to the URL. eg:
By default, the driver doesn't use password authentication. You can enable By default, the driver doesn't use password authentication. You can enable
this by adding the argument auth. ie: 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(): 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. 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 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. ...@@ -180,7 +194,7 @@ syntax for writing these to the database.
--------------------------------------------------------------------------- ---------------------------------------------------------------------------
Peter T Mount, October 28 1997 Peter T Mount, January 11 1998
home email: pmount@maidast.demon.co.uk http://www.demon.co.uk/finder home email: pmount@maidast.demon.co.uk http://www.demon.co.uk/finder
work email: peter@maidstone.gov.uk http://www.maidstone.gov.uk work email: peter@maidstone.gov.uk http://www.maidstone.gov.uk
......
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
...@@ -4,46 +4,114 @@ import java.sql.*; ...@@ -4,46 +4,114 @@ import java.sql.*;
import java.math.*; import java.math.*;
/** /**
* JDBC Interface to Postgres95 functions * CallableStatement is used to execute SQL stored procedures.
*
* <p>JDBC provides a stored procedure SQL escape that allows stored
* procedures to be called in a standard way for all RDBMS's. This escape
* syntax has one form that includes a result parameter and one that does
* not. If used, the result parameter must be registered as an OUT
* parameter. The other parameters may be used for input, output or both.
* Parameters are refered to sequentially, by number. The first parameter
* is 1.
*
* {?= call <procedure-name>[<arg1>,<arg2>, ...]}
* {call <procedure-name>[<arg1>,<arg2>, ...]}
*
*
* <p>IN parameter values are set using the set methods inherited from
* PreparedStatement. The type of all OUT parameters must be registered
* prior to executing the stored procedure; their values are retrieved
* after execution via the get methods provided here.
*
* <p>A Callable statement may return a ResultSet or multiple ResultSets.
* Multiple ResultSets are handled using operations inherited from
* Statement.
*
* <p>For maximum portability, a call's ResultSets and update counts should
* be processed prior to getting the values of output parameters.
*
* @see Connection#prepareCall
* @see ResultSet
*/ */
// Copy methods from the Result set object here.
public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement
{ {
/**
* @exception SQLException on failure
*/
CallableStatement(Connection c,String q) throws SQLException CallableStatement(Connection c,String q) throws SQLException
{ {
super(c,q); super(c,q);
} }
// Before executing a stored procedure call you must explicitly /**
// call registerOutParameter to register the java.sql.Type of each * Before executing a stored procedure call you must explicitly
// out parameter. * call registerOutParameter to register the java.sql.Type of each
* out parameter.
*
* <p>Note: When reading the value of an out parameter, you must use
* the getXXX method whose Java type XXX corresponds to the
* parameter's registered SQL type.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @param sqlType SQL type code defined by java.sql.Types; for
* parameters of type Numeric or Decimal use the version of
* registerOutParameter that accepts a scale value
* @exception SQLException if a database-access error occurs.
*/
public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException { public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
} }
// You must also specify the scale for numeric/decimal types: /**
* You must also specify the scale for numeric/decimal types:
*
* <p>Note: When reading the value of an out parameter, you must use
* the getXXX method whose Java type XXX corresponds to the
* parameter's registered SQL type.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @param sqlType use either java.sql.Type.NUMERIC or java.sql.Type.DECIMAL
* @param scale a value greater than or equal to zero representing the
* desired number of digits to the right of the decimal point
* @exception SQLException if a database-access error occurs.
*/
public void registerOutParameter(int parameterIndex, int sqlType, public void registerOutParameter(int parameterIndex, int sqlType,
int scale) throws SQLException int scale) throws SQLException
{ {
} }
public boolean isNull(int parameterIndex) throws SQLException { // Old api?
return true; //public boolean isNull(int parameterIndex) throws SQLException {
} //return true;
//}
// New API (JPM) /**
* An OUT parameter may have the value of SQL NULL; wasNull
* reports whether the last value read has this special value.
*
* <p>Note: You must first call getXXX on a parameter to read its
* value and then call wasNull() to see if the value was SQL NULL.
* @return true if the last parameter read was SQL NULL
* @exception SQLException if a database-access error occurs.
*/
public boolean wasNull() throws SQLException { public boolean wasNull() throws SQLException {
// check to see if the last access threw an exception // check to see if the last access threw an exception
return false; // fake it for now return false; // fake it for now
} }
// Methods for retrieving OUT parameters from this statement. // Old api?
public String getChar(int parameterIndex) throws SQLException { //public String getChar(int parameterIndex) throws SQLException {
return null; //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 { public String getString(int parameterIndex) throws SQLException {
return null; return null;
} }
...@@ -51,64 +119,148 @@ public class CallableStatement extends PreparedStatement implements java.sql.Cal ...@@ -51,64 +119,148 @@ public class CallableStatement extends PreparedStatement implements java.sql.Cal
// return null; // return null;
//} //}
public String getLongVarChar(int parameterIndex) throws SQLException { //public String getLongVarChar(int parameterIndex) throws SQLException {
return null; //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 { public boolean getBoolean(int parameterIndex) throws SQLException {
return false; 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 { public byte getByte(int parameterIndex) throws SQLException {
return 0; 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 { public short getShort(int parameterIndex) throws SQLException {
return 0; 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; 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 { public long getLong(int parameterIndex) throws SQLException {
return 0; 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 { public float getFloat(int parameterIndex) throws SQLException {
return (float) 0.0; 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 { public double getDouble(int parameterIndex) throws SQLException {
return 0.0; 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) public BigDecimal getBigDecimal(int parameterIndex, int scale)
throws SQLException { throws SQLException {
return null; 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 { public byte[] getBytes(int parameterIndex) throws SQLException {
return null; return null;
} }
// New API (JPM) (getLongVarBinary) // New API (JPM) (getLongVarBinary)
public byte[] getBinaryStream(int parameterIndex) throws SQLException { //public byte[] getBinaryStream(int parameterIndex) throws SQLException {
return null; //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 { public java.sql.Date getDate(int parameterIndex) throws SQLException {
return null; 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 { public java.sql.Time getTime(int parameterIndex) throws SQLException {
return null; 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) public java.sql.Timestamp getTimestamp(int parameterIndex)
throws SQLException { throws SQLException {
return null; return null;
...@@ -119,12 +271,30 @@ public class CallableStatement extends PreparedStatement implements java.sql.Cal ...@@ -119,12 +271,30 @@ public class CallableStatement extends PreparedStatement implements java.sql.Cal
// You can obtain a ParameterMetaData object to get information // You can obtain a ParameterMetaData object to get information
// about the parameters to this CallableStatement. // about the parameters to this CallableStatement.
public DatabaseMetaData getMetaData() { //public DatabaseMetaData getMetaData() {
return null; //return null;
} //}
// getObject returns a Java object for the parameter. // getObject returns a Java object for the parameter.
// See the JDBC spec's "Dynamic Programming" chapter for details. // See the JDBC spec's "Dynamic Programming" chapter for details.
/**
* Get the value of a parameter as a Java object.
*
* <p>This method returns a Java object whose type coresponds to the
* SQL type that was registered for this parameter using
* registerOutParameter.
*
* <P>Note that this method may be used to read datatabase-specific,
* abstract data types. This is done by specifying a targetSqlType
* of java.sql.types.OTHER, which allows the driver to return a
* database-specific Java type.
*
* <p>See the JDBC spec's "Dynamic Programming" chapter for details.
*
* @param parameterIndex the first parameter is 1, the second is 2,...
* @return A java.lang.Object holding the OUT parameter value.
* @exception SQLException if a database-access error occurs.
*/
public Object getObject(int parameterIndex) public Object getObject(int parameterIndex)
throws SQLException { throws SQLException {
return null; return null;
......
...@@ -5,22 +5,21 @@ import java.lang.*; ...@@ -5,22 +5,21 @@ import java.lang.*;
import java.net.*; import java.net.*;
import java.util.*; import java.util.*;
import java.sql.*; import java.sql.*;
import postgresql.*; import postgresql.fastpath.*;
import postgresql.largeobject.*;
import postgresql.util.*;
/** /**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A Connection represents a session with a specific database. Within the * A Connection represents a session with a specific database. Within the
* context of a Connection, SQL statements are executed and results are * context of a Connection, SQL statements are executed and results are
* returned. * returned.
* *
* A Connection's database is able to provide information describing * <P>A Connection's database is able to provide information describing
* its tables, its supported SQL grammar, its stored procedures, the * its tables, its supported SQL grammar, its stored procedures, the
* capabilities of this connection, etc. This information is obtained * capabilities of this connection, etc. This information is obtained
* with the getMetaData method. * with the getMetaData method.
* *
* <B>Note:</B> By default, the Connection automatically commits changes * <p><B>Note:</B> By default, the Connection automatically commits changes
* after executing each statement. If auto-commit has been disabled, an * after executing each statement. If auto-commit has been disabled, an
* explicit commit must be done or database changes will not be saved. * explicit commit must be done or database changes will not be saved.
* *
...@@ -28,8 +27,12 @@ import postgresql.*; ...@@ -28,8 +27,12 @@ import postgresql.*;
*/ */
public class Connection implements java.sql.Connection public class Connection implements java.sql.Connection
{ {
// This is the network stream associated with this connection
protected PG_Stream pg_stream; 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 String PG_HOST;
private int PG_PORT; private int PG_PORT;
private String PG_USER; private String PG_USER;
...@@ -59,7 +62,39 @@ public class Connection implements java.sql.Connection ...@@ -59,7 +62,39 @@ public class Connection implements java.sql.Connection
private String cursor = null; // The positioned update cursor name private String cursor = null; // The positioned update cursor name
// This is false for US, true for European date formats // This is false for US, true for European date formats
protected boolean europeanDates = false; //protected boolean europeanDates = false;
/**
* This is the current date style of the backend
*/
protected int currentDateStyle;
/**
* This defines the formats for dates, according to the various date styles.
*
* <p>There are two strings for each entry. The first is the string to search
* for in the datestyle message, and the second the format to use.
*
* <p>To add a new date style, work out the format. Then with psql running
* in the date style you wish to add, type: show datestyle;
*
* <p>eg:
* <br><pre>
* => show datestyle;
* NOTICE: Datestyle is SQL with European conventions
* ^^^^^^^^^^^^^^^^^
* </pre>The marked part of the string is the first string below. The second
* is your format. If a style (like ISO) ignores the US/European variants,
* then you can ignore the "with" part of the string.
*/
protected static final String dateStyles[] = {
"Postgres with European", "dd-MM-yyyy",
"Postgres with US", "MM-dd-yyyy",
"ISO", "yyyy-MM-dd",
"SQL with European", "dd/MM/yyyy",
"SQL with US", "MM/dd/yyyy",
"German", "dd.MM.yyyy"
};
// Now handle notices as warnings, so things like "show" now work // Now handle notices as warnings, so things like "show" now work
protected SQLWarning firstWarning = null; protected SQLWarning firstWarning = null;
...@@ -67,6 +102,13 @@ public class Connection implements java.sql.Connection ...@@ -67,6 +102,13 @@ public class Connection implements java.sql.Connection
/** /**
* Connect to a PostgreSQL database back end. * Connect to a PostgreSQL database back end.
* *
* <p><b>Important Notice</b>
*
* <br>Although this will connect to the database, user code should open
* the connection via the DriverManager.getConnection() methods only.
*
* <br>This should only be called from the postgresql.Driver class.
*
* @param host the hostname of the database back end * @param host the hostname of the database back end
* @param port the port number of the postmaster process * @param port the port number of the postmaster process
* @param info a Properties[] thing of the user and password * @param info a Properties[] thing of the user and password
...@@ -108,6 +150,7 @@ public class Connection implements java.sql.Connection ...@@ -108,6 +150,7 @@ public class Connection implements java.sql.Connection
STARTUP_CODE=STARTUP_USER; STARTUP_CODE=STARTUP_USER;
} }
// Now make the initial connection
try try
{ {
pg_stream = new PG_Stream(host, port); pg_stream = new PG_Stream(host, port);
...@@ -148,6 +191,9 @@ public class Connection implements java.sql.Connection ...@@ -148,6 +191,9 @@ public class Connection implements java.sql.Connection
clearWarnings(); clearWarnings();
ExecSQL("show datestyle"); ExecSQL("show datestyle");
// Initialise object handling
initObjectTypes();
// Mark the connection as ok, and cleanup // Mark the connection as ok, and cleanup
clearWarnings(); clearWarnings();
PG_STATUS = CONNECTION_OK; PG_STATUS = CONNECTION_OK;
...@@ -468,10 +514,15 @@ public class Connection implements java.sql.Connection ...@@ -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) public void addWarning(String msg)
{ {
//PrintStream log = DriverManager.getLogStream();
//if(log!=null)
DriverManager.println(msg);
// Add the warning to the chain // Add the warning to the chain
if(firstWarning!=null) if(firstWarning!=null)
firstWarning.setNextWarning(new SQLWarning(msg)); firstWarning.setNextWarning(new SQLWarning(msg));
...@@ -481,15 +532,24 @@ public class Connection implements java.sql.Connection ...@@ -481,15 +532,24 @@ public class Connection implements java.sql.Connection
// Now check for some specific messages // Now check for some specific messages
// This is generated by the SQL "show datestyle" // This is generated by the SQL "show datestyle"
if(msg.startsWith("NOTICE:DateStyle")) { if(msg.startsWith("NOTICE:") && msg.indexOf("DateStyle")>0) {
if(msg.indexOf("with US")==-1) // 13 is the length off "DateStyle is "
europeanDates=true; msg = msg.substring(msg.indexOf("DateStyle is ")+13);
else
europeanDates=false; for(int i=0;i<dateStyles.length;i+=2)
System.err.println("europeanDates="+europeanDates); 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 * Send a query to the backend. Returns one of the ResultSet
* objects. * objects.
...@@ -525,6 +585,8 @@ public class Connection implements java.sql.Connection ...@@ -525,6 +585,8 @@ public class Connection implements java.sql.Connection
while (!hfr || fqp > 0) while (!hfr || fqp > 0)
{ {
Object tup=null; // holds rows as they are recieved
int c = pg_stream.ReceiveChar(); int c = pg_stream.ReceiveChar();
switch (c) switch (c)
...@@ -536,7 +598,10 @@ public class Connection implements java.sql.Connection ...@@ -536,7 +598,10 @@ public class Connection implements java.sql.Connection
case 'B': // Binary Data Transfer case 'B': // Binary Data Transfer
if (fields == null) if (fields == null)
throw new SQLException("Tuple received before MetaData"); throw new SQLException("Tuple received before MetaData");
tuples.addElement(pg_stream.ReceiveTuple(fields.length, true)); tup = pg_stream.ReceiveTuple(fields.length, true);
// This implements Statement.setMaxRows()
if(maxrows==0 || tuples.size()<maxrows)
tuples.addElement(tup);
break; break;
case 'C': // Command Status case 'C': // Command Status
recv_status = pg_stream.ReceiveString(8192); recv_status = pg_stream.ReceiveString(8192);
...@@ -558,7 +623,10 @@ public class Connection implements java.sql.Connection ...@@ -558,7 +623,10 @@ public class Connection implements java.sql.Connection
case 'D': // Text Data Transfer case 'D': // Text Data Transfer
if (fields == null) if (fields == null)
throw new SQLException("Tuple received before MetaData"); throw new SQLException("Tuple received before MetaData");
tuples.addElement(pg_stream.ReceiveTuple(fields.length, false)); tup = pg_stream.ReceiveTuple(fields.length, false);
// This implements Statement.setMaxRows()
if(maxrows==0 || tuples.size()<maxrows)
tuples.addElement(tup);
break; break;
case 'E': // Error Message case 'E': // Error Message
msg = pg_stream.ReceiveString(4096); msg = pg_stream.ReceiveString(4096);
...@@ -576,10 +644,7 @@ public class Connection implements java.sql.Connection ...@@ -576,10 +644,7 @@ public class Connection implements java.sql.Connection
hfr = true; hfr = true;
break; break;
case 'N': // Error Notification case 'N': // Error Notification
msg = pg_stream.ReceiveString(4096); addWarning(pg_stream.ReceiveString(4096));
PrintStream log = DriverManager.getLogStream();
if(log!=null) log.println(msg);
addWarning(msg);
break; break;
case 'P': // Portal Name case 'P': // Portal Name
String pname = pg_stream.ReceiveString(8192); String pname = pg_stream.ReceiveString(8192);
...@@ -675,14 +740,143 @@ public class Connection implements java.sql.Connection ...@@ -675,14 +740,143 @@ public class Connection implements java.sql.Connection
} }
/** /**
* This method is not part of the Connection interface. Its is an extension * This returns the Fastpath API for the current connection.
* that allows access to the PostgreSQL Large Object API *
* <p><b>NOTE:</b> This is not part of JDBC, but allows access to
* functions on the postgresql backend itself.
*
* <p>It is primarily used by the LargeObject API
*
* <p>The best way to use this is as follows:
* *
* @return PGlobj class that implements the API * <p><pre>
* import postgresql.fastpath.*;
* ...
* Fastpath fp = ((postgresql.Connection)myconn).getFastpathAPI();
* </pre>
*
* <p>where myconn is an open Connection to postgresql.
*
* @return Fastpath object allowing access to functions on the postgresql
* backend.
* @exception SQLException by Fastpath when initialising for first time
*/ */
public PGlobj getLargeObjectAPI() throws SQLException public Fastpath getFastpathAPI() throws SQLException
{ {
return new PGlobj(this); if(fastpath==null)
fastpath = new Fastpath(this,pg_stream);
return fastpath;
}
// This holds a reference to the Fastpath API if already open
private Fastpath fastpath = null;
/**
* This returns the LargeObject API for the current connection.
*
* <p><b>NOTE:</b> This is not part of JDBC, but allows access to
* functions on the postgresql backend itself.
*
* <p>The best way to use this is as follows:
*
* <p><pre>
* import postgresql.largeobject.*;
* ...
* LargeObjectManager lo = ((postgresql.Connection)myconn).getLargeObjectAPI();
* </pre>
*
* <p>where myconn is an open Connection to postgresql.
*
* @return LargeObject object that implements the API
* @exception SQLException by LargeObject when initialising for first time
*/
public LargeObjectManager getLargeObjectAPI() throws SQLException
{
if(largeobject==null)
largeobject = new LargeObjectManager(this);
return largeobject;
}
// This holds a reference to the LargeObject API if already open
private LargeObjectManager largeobject = null;
/**
* This method is used internally to return an object based around
* postgresql's more unique data types.
*
* <p>It uses an internal Hashtable to get the handling class. If the
* type is not supported, then an instance of postgresql.util.PGobject
* is returned.
*
* 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
*/
protected PGobject getObject(String type,String value) throws SQLException
{
PGobject obj = null;
try {
String name = (String)objectTypes.get(type);
obj = (PGobject)(Class.forName(name==null?"postgresql.util.PGobject":name).newInstance());
} catch(Exception ex) {
throw new SQLException("Failed to create object for "+type+": "+ex);
}
if(obj!=null) {
obj.setType(type);
obj.setValue(value);
}
return obj;
}
/**
* This allows client code to add a handler for one of postgresql's
* more unique data types.
*
* <p><b>NOTE:</b> This is not part of JDBC, but an extension.
*
* <p>The best way to use this is as follows:
*
* <p><pre>
* ...
* ((postgresql.Connection)myconn).addDataType("mytype","my.class.name");
* ...
* </pre>
*
* <p>where myconn is an open Connection to postgresql.
*
* <p>The handling class must extend postgresql.util.PGobject
*
* @see postgresql.util.PGobject
*/
public void addDataType(String type,String name)
{
objectTypes.put(type,name);
}
// This holds the available types
private Hashtable objectTypes = new Hashtable();
// This array contains the types that are supported as standard.
//
// The first entry is the types name on the database, the second
// the full class name of the handling class.
//
private static final String defaultObjectTypes[][] = {
{"box", "postgresql.geometric.PGbox"},
{"circle", "postgresql.geometric.PGcircle"},
{"lseg", "postgresql.geometric.PGlseg"},
{"path", "postgresql.geometric.PGpath"},
{"point", "postgresql.geometric.PGpoint"},
{"polygon", "postgresql.geometric.PGpolygon"}
};
// This initialises the objectTypes hashtable
private void initObjectTypes()
{
for(int i=0;i<defaultObjectTypes.length;i++)
objectTypes.put(defaultObjectTypes[i][0],defaultObjectTypes[i][1]);
} }
} }
......
...@@ -7,17 +7,17 @@ import java.util.*; ...@@ -7,17 +7,17 @@ import java.util.*;
* The Java SQL framework allows for multiple database drivers. Each * The Java SQL framework allows for multiple database drivers. Each
* driver should supply a class that implements the Driver interface * 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 * <p>The DriverManager will try to load as many drivers as it can find and
* for any given connection request, it will ask each driver in turn to try * then for any given connection request, it will ask each driver in turn
* to connect to the target URL. * to try to connect to the target URL.
* *
* It is strongly recommended that each Driver class should be small and * <p>It is strongly recommended that each Driver class should be small and
* standalone so that the Driver class can be loaded and queried without * standalone so that the Driver class can be loaded and queried without
* bringing in vast quantities of supporting code. * bringing in vast quantities of supporting code.
* *
* When a Driver class is loaded, it should create an instance of itself and * <p>When a Driver class is loaded, it should create an instance of itself
* register it with the DriverManager. This means that a user can load and * and register it with the DriverManager. This means that a user can load
* register a driver by doing Class.forName("foo.bah.Driver") * and register a driver by doing Class.forName("foo.bah.Driver")
* *
* @see postgresql.Connection * @see postgresql.Connection
* @see java.sql.Driver * @see java.sql.Driver
...@@ -58,18 +58,18 @@ public class Driver implements 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, * when the JDBC driverManager is asked to connect to a given URL,
* it passes the URL to each loaded driver in turn. * it passes the URL to each loaded driver in turn.
* *
* The driver should raise an SQLException if it is the right driver * <p>The driver should raise an SQLException if it is the right driver
* to connect to the given URL, but has trouble connecting to the * to connect to the given URL, but has trouble connecting to the
* database. * database.
* *
* The java.util.Properties argument can be used to pass arbitrary * <p>The java.util.Properties argument can be used to pass arbitrary
* string tag/value pairs as connection arguments. Normally, at least * string tag/value pairs as connection arguments. Normally, at least
* "user" and "password" properties should be included in the * "user" and "password" properties should be included in the
* properties. * properties.
* *
* Our protocol takes the form: * Our protocol takes the forms:
* <PRE> * <PRE>
* jdbc:postgresql://host:port/database * jdbc:postgresql://host:port/database?param1=val1&...
* </PRE> * </PRE>
* *
* @param url the URL of the database to connect to * @param url the URL of the database to connect to
...@@ -110,7 +110,8 @@ public class Driver implements java.sql.Driver ...@@ -110,7 +110,8 @@ public class Driver implements java.sql.Driver
* The getPropertyInfo method is intended to allow a generic GUI * The getPropertyInfo method is intended to allow a generic GUI
* tool to discover what properties it should prompt a human for * tool to discover what properties it should prompt a human for
* in order to get enough information to connect to a database. * in order to get enough information to connect to a database.
* Note that depending on the values the human has supplied so *
* <p>Note that depending on the values the human has supplied so
* far, additional values may become necessary, so it may be necessary * far, additional values may become necessary, so it may be necessary
* to iterate through several calls to getPropertyInfo * to iterate through several calls to getPropertyInfo
* *
...@@ -169,6 +170,9 @@ public class Driver implements java.sql.Driver ...@@ -169,6 +170,9 @@ public class Driver implements java.sql.Driver
* tests, otherwise it is required to return false. JDBC compliance * tests, otherwise it is required to return false. JDBC compliance
* requires full support for the JDBC API and full support for SQL 92 * requires full support for the JDBC API and full support for SQL 92
* Entry Level. * Entry Level.
*
* <p>For PostgreSQL, this is not yet possible, as we are not SQL92
* compliant (yet).
*/ */
public boolean jdbcCompliant() public boolean jdbcCompliant()
{ {
...@@ -185,7 +189,7 @@ public class Driver implements java.sql.Driver ...@@ -185,7 +189,7 @@ public class Driver implements java.sql.Driver
* @param url JDBC URL to parse * @param url JDBC URL to parse
* @param defaults Default properties * @param defaults Default properties
* @return Properties with elements added from the url * @return Properties with elements added from the url
* @throws SQLException * @exception SQLException
*/ */
Properties parseURL(String url,Properties defaults) throws SQLException Properties parseURL(String url,Properties defaults) throws SQLException
{ {
...@@ -280,7 +284,7 @@ public class Driver implements java.sql.Driver ...@@ -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() public String host()
{ {
...@@ -288,8 +292,7 @@ public class Driver implements java.sql.Driver ...@@ -288,8 +292,7 @@ public class Driver implements java.sql.Driver
} }
/** /**
* Returns the port number portion of the URL * @return the port number portion of the URL or -1 if no port was specified
* or -1 if no port was specified
*/ */
public int port() public int port()
{ {
...@@ -297,7 +300,7 @@ public class Driver implements java.sql.Driver ...@@ -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() public String database()
{ {
...@@ -305,7 +308,8 @@ public class Driver implements java.sql.Driver ...@@ -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) public String property(String name)
{ {
......
...@@ -6,10 +6,8 @@ import java.util.*; ...@@ -6,10 +6,8 @@ import java.util.*;
import postgresql.*; import postgresql.*;
/** /**
* postgresql.Field is a class used to describe fields in a PostgreSQL ResultSet * postgresql.Field is a class used to describe fields in a PostgreSQL
* * ResultSet
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*/ */
public class Field public class Field
{ {
...@@ -37,6 +35,14 @@ public class Field ...@@ -37,6 +35,14 @@ public class Field
this.length = length; 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 * the ResultSet and ResultMetaData both need to handle the SQL
* type, which is gained from another query. Note that we cannot * type, which is gained from another query. Note that we cannot
...@@ -47,47 +53,77 @@ public class Field ...@@ -47,47 +53,77 @@ public class Field
*/ */
public int getSQLType() throws SQLException public int getSQLType() throws SQLException
{ {
if (sql_type == -1) if(sql_type == -1) {
{
ResultSet result = (postgresql.ResultSet)conn.ExecSQL("select typname from pg_type where oid = " + oid); ResultSet result = (postgresql.ResultSet)conn.ExecSQL("select typname from pg_type where oid = " + oid);
if (result.getColumnCount() != 1 || result.getTupleCount() != 1) if (result.getColumnCount() != 1 || result.getTupleCount() != 1)
throw new SQLException("Unexpected return from query for type"); throw new SQLException("Unexpected return from query for type");
result.next(); result.next();
type_name = result.getString(1); sql_type = getSQLType(result.getString(1));
if (type_name.equals("int2")) result.close();
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;
} }
return sql_type; return sql_type;
} }
/**
* This returns the SQL type. It is called by the Field and DatabaseMetaData classes
* @param type_name PostgreSQL type name
* @return java.sql.Types value for oid
*/
public static int getSQLType(String type_name)
{
int sql_type = Types.OTHER; // default value
for(int i=0;i<types.length;i++)
if(type_name.equals(types[i]))
sql_type=typei[i];
return sql_type;
}
/**
* This table holds the postgresql names for the types supported.
* Any types that map to Types.OTHER (eg POINT) don't go into this table.
* They default automatically to Types.OTHER
*
* Note: This must be in the same order as below.
*
* Tip: keep these grouped together by the Types. value
*/
private static final String types[] = {
"int2",
"int4","oid",
"int8",
"cash","money",
"float4",
"float8",
"bpchar","char","char2","char4","char8","char16",
"varchar","text","name","filename",
"bool",
"date",
"time",
"abstime","timestamp"
};
/**
* This table holds the JDBC type for each entry above.
*
* Note: This must be in the same order as above
*
* Tip: keep these grouped together by the Types. value
*/
private static final int typei[] = {
Types.SMALLINT,
Types.INTEGER,Types.INTEGER,
Types.BIGINT,
Types.DECIMAL,Types.DECIMAL,
Types.REAL,
Types.DOUBLE,
Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,Types.CHAR,
Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,Types.VARCHAR,
Types.BIT,
Types.DATE,
Types.TIME,
Types.TIMESTAMP,Types.TIMESTAMP
};
/** /**
* We also need to get the type name as returned by the back end. * 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 * This is held in type_name AFTER a call to getSQLType. Since
......
...@@ -70,6 +70,28 @@ public class PG_Stream ...@@ -70,6 +70,28 @@ public class PG_Stream
Send(buf); 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 * Send an array of bytes to the backend
* *
...@@ -295,6 +317,20 @@ public class PG_Stream ...@@ -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 * Closes the connection
* *
......
...@@ -5,21 +5,20 @@ import java.math.*; ...@@ -5,21 +5,20 @@ import java.math.*;
import java.sql.*; import java.sql.*;
import java.text.*; import java.text.*;
import java.util.*; import java.util.*;
import postgresql.largeobject.*;
import postgresql.util.*;
/** /**
* @version 6.3 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A><A HREF="mailto:petermount@earthling.net">Peter Mount</A>
*
* A SQL Statement is pre-compiled and stored in a PreparedStatement object. * A SQL Statement is pre-compiled and stored in a PreparedStatement object.
* This object can then be used to efficiently execute this statement multiple * This object can then be used to efficiently execute this statement multiple
* times. * times.
* *
* <B>Note:</B> The setXXX methods for setting IN parameter values must * <p><B>Note:</B> The setXXX methods for setting IN parameter values must
* specify types that are compatible with the defined SQL type of the input * 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 * parameter. For instance, if the IN parameter has SQL type Integer, then
* setInt should be used. * setInt should be used.
* *
* If arbitrary parameter type conversions are required, then the setObject * <p>If arbitrary parameter type conversions are required, then the setObject
* method should be used with a target SQL type. * method should be used with a target SQL type.
* *
* @see ResultSet * @see ResultSet
...@@ -33,10 +32,10 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -33,10 +32,10 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
Connection connection; Connection connection;
/** /**
* Constructor for the PreparedStatement class. Split the SQL statement * Constructor for the PreparedStatement class.
* into segments - separated by the arguments. When we rebuild the * Split the SQL statement into segments - separated by the arguments.
* thing with the arguments, we can substitute the args and join the * When we rebuild the thing with the arguments, we can substitute the
* whole thing together. * args and join the whole thing together.
* *
* @param conn the instanatiating connection * @param conn the instanatiating connection
* @param sql the SQL statement with ? for IN markers * @param sql the SQL statement with ? for IN markers
...@@ -125,7 +124,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -125,7 +124,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
/** /**
* Set a parameter to SQL NULL * Set a parameter to SQL NULL
* *
* <B>Note:</B> You must specify the parameters SQL type (although * <p><B>Note:</B> You must specify the parameters SQL type (although
* PostgreSQL ignores it) * PostgreSQL ignores it)
* *
* @param parameterIndex the first parameter is 1, etc... * @param parameterIndex the first parameter is 1, etc...
...@@ -254,6 +253,10 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -254,6 +253,10 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
*/ */
public void setString(int parameterIndex, String x) throws SQLException public void setString(int parameterIndex, String x) throws SQLException
{ {
// if the passed string is null, then set this column to null
if(x==null)
set(parameterIndex,"null");
else {
StringBuffer b = new StringBuffer(); StringBuffer b = new StringBuffer();
int i; int i;
...@@ -268,6 +271,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -268,6 +271,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
b.append('\''); b.append('\'');
set(parameterIndex, b.toString()); set(parameterIndex, b.toString());
} }
}
/** /**
* Set a parameter to a Java array of bytes. The driver converts this * Set a parameter to a Java array of bytes. The driver converts this
...@@ -275,13 +279,22 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -275,13 +279,22 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
* size relative to the driver's limits on VARBINARYs) when it sends * size relative to the driver's limits on VARBINARYs) when it sends
* it to the database. * it to the database.
* *
* <p>Implementation note:
* <br>With postgresql, this creates a large object, and stores the
* objects oid in this column.
*
* @param parameterIndex the first parameter is 1... * @param parameterIndex the first parameter is 1...
* @param x the parameter value * @param x the parameter value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
public void setBytes(int parameterIndex, byte x[]) throws SQLException public void setBytes(int parameterIndex, byte x[]) throws SQLException
{ {
throw new SQLException("Binary Data not supported"); LargeObjectManager lom = connection.getLargeObjectAPI();
int oid = lom.create();
LargeObject lob = lom.open(oid);
lob.write(x);
lob.close();
setInt(parameterIndex,oid);
} }
/** /**
...@@ -294,16 +307,30 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -294,16 +307,30 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
*/ */
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
{ {
SimpleDateFormat df = new SimpleDateFormat(connection.europeanDates?"''dd-MM-yyyy''":"''MM-dd-yyyy''"); SimpleDateFormat df = new SimpleDateFormat("''"+connection.getDateStyle()+"''");
set(parameterIndex, df.format(x)); // 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 * 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. * 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 * @param x the parameter value
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
*/ */
...@@ -332,7 +359,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -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 * end-of-file. The JDBC driver will do any necessary conversion from
* ASCII to the database char format. * ASCII to the database char format.
* *
* <B>Note:</B> This stream object can either be a standard Java * <P><B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard * stream object or your own subclass that implements the standard
* interface. * interface.
* *
...@@ -353,7 +380,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -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 * end-of-file. The JDBC driver will do any necessary conversion from
* UNICODE to the database char format. * UNICODE to the database char format.
* *
* <B>Note:</B> This stream object can either be a standard Java * <P><B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard * stream object or your own subclass that implements the standard
* interface. * interface.
* *
...@@ -372,7 +399,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -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 * JDBC will read the data from the stream as needed, until it reaches
* end-of-file. * end-of-file.
* *
* <B>Note:</B> This stream object can either be a standard Java * <P><B>Note:</B> This stream object can either be a standard Java
* stream object or your own subclass that implements the standard * stream object or your own subclass that implements the standard
* interface. * interface.
* *
...@@ -406,10 +433,10 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -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 * Set the value of a parameter using an object; use the java.lang
* equivalent objects for integral values. * equivalent objects for integral values.
* *
* The given Java object will be converted to the targetSqlType before * <P>The given Java object will be converted to the targetSqlType before
* being sent to the database. * being sent to the database.
* *
* note that this method may be used to pass database-specific * <P>note that this method may be used to pass database-specific
* abstract data types. This is done by using a Driver-specific * abstract data types. This is done by using a Driver-specific
* Java type and using a targetSqlType of java.sql.Types.OTHER * Java type and using a targetSqlType of java.sql.Types.OTHER
* *
...@@ -450,7 +477,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -450,7 +477,7 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
case Types.TIMESTAMP: case Types.TIMESTAMP:
setTimestamp(parameterIndex, (Timestamp)x); setTimestamp(parameterIndex, (Timestamp)x);
case Types.OTHER: case Types.OTHER:
setString(parameterIndex, ((PG_Object)x).value); setString(parameterIndex, ((PGobject)x).getValue());
default: default:
throw new SQLException("Unknown Types value"); throw new SQLException("Unknown Types value");
} }
...@@ -485,8 +512,8 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -485,8 +512,8 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
setTimestamp(parameterIndex, (Timestamp)x); setTimestamp(parameterIndex, (Timestamp)x);
else if (x instanceof Boolean) else if (x instanceof Boolean)
setBoolean(parameterIndex, ((Boolean)x).booleanValue()); setBoolean(parameterIndex, ((Boolean)x).booleanValue());
else if (x instanceof PG_Object) else if (x instanceof PGobject)
setString(parameterIndex, ((PG_Object)x).value); setString(parameterIndex, ((PGobject)x).getValue());
else else
throw new SQLException("Unknown object type"); throw new SQLException("Unknown object type");
} }
......
...@@ -6,31 +6,32 @@ import java.math.*; ...@@ -6,31 +6,32 @@ import java.math.*;
import java.text.*; import java.text.*;
import java.util.*; import java.util.*;
import java.sql.*; import java.sql.*;
import postgresql.*; import postgresql.largeobject.*;
import postgresql.util.*;
/** /**
* A ResultSet provides access to a table of data generated by executing a * 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 * Statement. The table rows are retrieved in sequence. Within a row its
* column values can be accessed in any order. * column values can be accessed in any order.
* *
* A ResultSet maintains a cursor pointing to its current row of data. * <P>A ResultSet maintains a cursor pointing to its current row of data.
* Initially the cursor is positioned before the first row. The 'next' * Initially the cursor is positioned before the first row. The 'next'
* method moves the cursor to the next row. * method moves the cursor to the next row.
* *
* The getXXX methods retrieve column values for the current row. You can * <P>The getXXX methods retrieve column values for the current row. You can
* retrieve values either using the index number of the column, or by using * 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 * the name of the column. In general using the column index will be more
* efficient. Columns are numbered from 1. * efficient. Columns are numbered from 1.
* *
* For maximum portability, ResultSet columns within each row should be read * <P>For maximum portability, ResultSet columns within each row should be read
* in left-to-right order and each column should be read only once. * 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 *<P> For the getXXX methods, the JDBC driver attempts to convert the
* data to the specified Java type and returns a suitable Java value. See the * underlying data to the specified Java type and returns a suitable Java
* JDBC specification for allowable mappings from SQL types to Java types with * value. See the JDBC specification for allowable mappings from SQL types
* the ResultSet getXXX methods. * to Java types with the ResultSet getXXX methods.
* *
* Column names used as input to getXXX methods are case insenstive. When * <P>Column names used as input to getXXX methods are case insenstive. When
* performing a getXXX using a column name, if several columns have the same * 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 * 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 * column name option is designed to be used when column names are used in the
...@@ -39,11 +40,11 @@ import postgresql.*; ...@@ -39,11 +40,11 @@ import postgresql.*;
* the programmer to guarentee that they actually refer to the intended * the programmer to guarentee that they actually refer to the intended
* columns. * columns.
* *
* A ResultSet is automatically closed by the Statement that generated it * <P>A ResultSet is automatically closed by the Statement that generated it
* when that Statement is closed, re-executed, or is used to retrieve the * when that Statement is closed, re-executed, or is used to retrieve the
* next result from a sequence of multiple results. * next result from a sequence of multiple results.
* *
* The number, types and properties of a ResultSet's columns are provided by * <P>The number, types and properties of a ResultSet's columns are provided by
* the ResultSetMetaData object returned by the getMetaData method. * the ResultSetMetaData object returned by the getMetaData method.
* *
* @see ResultSetMetaData * @see ResultSetMetaData
...@@ -92,7 +93,7 @@ public class ResultSet implements java.sql.ResultSet ...@@ -92,7 +93,7 @@ public class ResultSet implements java.sql.ResultSet
* the first call to next makes the first row the current row; * the first call to next makes the first row the current row;
* the second call makes the second row the current row, etc. * the second call makes the second row the current row, etc.
* *
* If an input stream from the previous row is open, it is * <p>If an input stream from the previous row is open, it is
* implicitly closed. The ResultSet's warning chain is cleared * implicitly closed. The ResultSet's warning chain is cleared
* when a new row is read * when a new row is read
* *
...@@ -114,7 +115,7 @@ public class ResultSet implements java.sql.ResultSet ...@@ -114,7 +115,7 @@ public class ResultSet implements java.sql.ResultSet
* when it is automatically closed. The close method provides this * when it is automatically closed. The close method provides this
* immediate release. * immediate release.
* *
* <B>Note:</B> A ResultSet is automatically closed by the Statement * <p><B>Note:</B> A ResultSet is automatically closed by the Statement
* the Statement that generated it when that Statement is closed, * the Statement that generated it when that Statement is closed,
* re-executed, or is used to retrieve the next result from a sequence * re-executed, or is used to retrieve the next result from a sequence
* of multiple results. A ResultSet is also automatically closed * of multiple results. A ResultSet is also automatically closed
...@@ -150,11 +151,17 @@ public class ResultSet implements java.sql.ResultSet ...@@ -150,11 +151,17 @@ public class ResultSet implements java.sql.ResultSet
*/ */
public String getString(int columnIndex) throws SQLException public String getString(int columnIndex) throws SQLException
{ {
byte[] bytes = getBytes(columnIndex); //byte[] bytes = getBytes(columnIndex);
//
if (bytes == null) //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 null;
return new String(bytes); return new String(this_row[columnIndex - 1]);
} }
/** /**
...@@ -347,8 +354,14 @@ public class ResultSet implements java.sql.ResultSet ...@@ -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 * 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. *
* <p>In normal use, the bytes represent the raw values returned by the
* backend. However, if the column is an OID, then it is assumed to
* refer to a Large Object, and that object is returned as a byte array.
*
* <p><b>Be warned</b> If the large object is huge, then you may run out
* of memory.
* *
* @param columnIndex the first column is 1, the second is 2, ... * @param columnIndex the first column is 1, the second is 2, ...
* @return the column value; if the value is SQL NULL, the result * @return the column value; if the value is SQL NULL, the result
...@@ -360,6 +373,17 @@ public class ResultSet implements java.sql.ResultSet ...@@ -360,6 +373,17 @@ public class ResultSet implements java.sql.ResultSet
if (columnIndex < 1 || columnIndex > fields.length) if (columnIndex < 1 || columnIndex > fields.length)
throw new SQLException("Column Index out of range"); throw new SQLException("Column Index out of range");
wasNullFlag = (this_row[columnIndex - 1] == null); 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]; return this_row[columnIndex - 1];
} }
...@@ -374,7 +398,7 @@ public class ResultSet implements java.sql.ResultSet ...@@ -374,7 +398,7 @@ public class ResultSet implements java.sql.ResultSet
public java.sql.Date getDate(int columnIndex) throws SQLException public java.sql.Date getDate(int columnIndex) throws SQLException
{ {
String s = getString(columnIndex); String s = getString(columnIndex);
SimpleDateFormat df = new SimpleDateFormat(connection.europeanDates?"dd-MM-yyyy":"MM-dd-yyyy"); SimpleDateFormat df = new SimpleDateFormat(connection.getDateStyle());
try { try {
return new java.sql.Date(df.parse(s).getTime()); return new java.sql.Date(df.parse(s).getTime());
} catch (ParseException e) { } catch (ParseException e) {
...@@ -449,13 +473,13 @@ public class ResultSet implements java.sql.ResultSet ...@@ -449,13 +473,13 @@ public class ResultSet implements java.sql.ResultSet
* The JDBC driver will do any necessary conversion from the * The JDBC driver will do any necessary conversion from the
* database format into ASCII. * database format into ASCII.
* *
* <B>Note:</B> All the data in the returned stream must be read * <p><B>Note:</B> All the data in the returned stream must be read
* prior to getting the value of any other column. The next call * prior to getting the value of any other column. The next call
* to a get method implicitly closes the stream. Also, a stream * to a get method implicitly closes the stream. Also, a stream
* may return 0 for available() whether there is data available * may return 0 for available() whether there is data available
* or not. * or not.
* *
* We implement an ASCII stream as a Binary stream - we should really *<p> We implement an ASCII stream as a Binary stream - we should really
* do the data conversion, but I cannot be bothered to implement this * do the data conversion, but I cannot be bothered to implement this
* right now. * right now.
* *
...@@ -494,8 +518,8 @@ public class ResultSet implements java.sql.ResultSet ...@@ -494,8 +518,8 @@ public class ResultSet implements java.sql.ResultSet
* *
* @param columnIndex the first column is 1, the second is 2... * @param columnIndex the first column is 1, the second is 2...
* @return a Java InputStream that delivers the database column value * @return a Java InputStream that delivers the database column value
* as a stream of two byte Unicode characters. If the value is * as a stream of bytes. If the value is SQL NULL, then the result
* SQL NULL, then the result is null * is null
* @exception SQLException if a database access error occurs * @exception SQLException if a database access error occurs
* @see getAsciiStream * @see getAsciiStream
* @see getUnicodeStream * @see getUnicodeStream
...@@ -603,10 +627,10 @@ public class ResultSet implements java.sql.ResultSet ...@@ -603,10 +627,10 @@ public class ResultSet implements java.sql.ResultSet
* returned. Subsequent ResultSet warnings will be chained * returned. Subsequent ResultSet warnings will be chained
* to this SQLWarning. * to this SQLWarning.
* *
* The warning chain is automatically cleared each time a new * <p>The warning chain is automatically cleared each time a new
* row is read. * row is read.
* *
* <B>Note:</B> This warning chain only covers warnings caused by * <p><B>Note:</B> This warning chain only covers warnings caused by
* ResultSet methods. Any warnings caused by statement methods * ResultSet methods. Any warnings caused by statement methods
* (such as reading OUT parameters) will be chained on the * (such as reading OUT parameters) will be chained on the
* Statement object. * Statement object.
...@@ -633,16 +657,16 @@ public class ResultSet implements java.sql.ResultSet ...@@ -633,16 +657,16 @@ public class ResultSet implements java.sql.ResultSet
/** /**
* Get the name of the SQL cursor used by this ResultSet * Get the name of the SQL cursor used by this ResultSet
* *
* In SQL, a result table is retrieved though a cursor that is * <p>In SQL, a result table is retrieved though a cursor that is
* named. The current row of a result can be updated or deleted * named. The current row of a result can be updated or deleted
* using a positioned update/delete statement that references * using a positioned update/delete statement that references
* the cursor name. * the cursor name.
* *
* JDBC supports this SQL feature by providing the name of the * <p>JDBC supports this SQL feature by providing the name of the
* SQL cursor used by a ResultSet. The current row of a ResulSet * SQL cursor used by a ResultSet. The current row of a ResulSet
* is also the current row of this SQL cursor. * is also the current row of this SQL cursor.
* *
* <B>Note:</B> If positioned update is not supported, a SQLException * <p><B>Note:</B> If positioned update is not supported, a SQLException
* is thrown. * is thrown.
* *
* @return the ResultSet's SQL cursor name. * @return the ResultSet's SQL cursor name.
...@@ -668,12 +692,12 @@ public class ResultSet implements java.sql.ResultSet ...@@ -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 * Get the value of a column in the current row as a Java object
* *
* This method will return the value of the given column as a * <p>This method will return the value of the given column as a
* Java object. The type of the Java object will be the default * Java object. The type of the Java object will be the default
* Java Object type corresponding to the column's SQL type, following * Java Object type corresponding to the column's SQL type, following
* the mapping specified in the JDBC specification. * the mapping specified in the JDBC specification.
* *
* This method may also be used to read database specific abstract * <p>This method may also be used to read database specific abstract
* data types. * data types.
* *
* @param columnIndex the first column is 1, the second is 2... * @param columnIndex the first column is 1, the second is 2...
...@@ -714,19 +738,19 @@ public class ResultSet implements java.sql.ResultSet ...@@ -714,19 +738,19 @@ public class ResultSet implements java.sql.ResultSet
case Types.TIMESTAMP: case Types.TIMESTAMP:
return getTimestamp(columnIndex); return getTimestamp(columnIndex);
default: 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 * Get the value of a column in the current row as a Java object
* *
* This method will return the value of the given column as a *<p> This method will return the value of the given column as a
* Java object. The type of the Java object will be the default * Java object. The type of the Java object will be the default
* Java Object type corresponding to the column's SQL type, following * Java Object type corresponding to the column's SQL type, following
* the mapping specified in the JDBC specification. * the mapping specified in the JDBC specification.
* *
* This method may also be used to read database specific abstract * <p>This method may also be used to read database specific abstract
* data types. * data types.
* *
* @param columnName is the SQL name of the column * @param columnName is the SQL name of the column
...@@ -816,8 +840,6 @@ public class ResultSet implements java.sql.ResultSet ...@@ -816,8 +840,6 @@ public class ResultSet implements java.sql.ResultSet
* particular, we need to know the number of rows and the * particular, we need to know the number of rows and the
* number of columns. Rows are also known as Tuples * number of columns. Rows are also known as Tuples
* *
* getTupleCount returns the number of rows
*
* @return the number of rows * @return the number of rows
*/ */
public int getTupleCount() public int getTupleCount()
......
...@@ -6,9 +6,6 @@ import java.util.*; ...@@ -6,9 +6,6 @@ import java.util.*;
import postgresql.*; import postgresql.*;
/** /**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A ResultSetMetaData object can be used to find out about the types and * A ResultSetMetaData object can be used to find out about the types and
* properties of the columns in a ResultSet * properties of the columns in a ResultSet
* *
......
...@@ -3,13 +3,10 @@ package postgresql; ...@@ -3,13 +3,10 @@ package postgresql;
import java.sql.*; import java.sql.*;
/** /**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A Statement object is used for executing a static SQL statement and * A Statement object is used for executing a static SQL statement and
* obtaining the results produced by it. * obtaining the results produced by it.
* *
* Only one ResultSet per Statement can be open at any point in time. * <p>Only one ResultSet per Statement can be open at any point in time.
* Therefore, if the reading of one ResultSet is interleaved with the * Therefore, if the reading of one ResultSet is interleaved with the
* reading of another, each must have been generated by different * reading of another, each must have been generated by different
* Statements. All statement execute methods implicitly close a * Statements. All statement execute methods implicitly close a
...@@ -23,7 +20,6 @@ public class Statement implements java.sql.Statement ...@@ -23,7 +20,6 @@ public class Statement implements java.sql.Statement
Connection connection; // The connection who created us Connection connection; // The connection who created us
ResultSet result = null; // The current results ResultSet result = null; // The current results
SQLWarning warnings = null; // The warnings chain. 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) int timeout = 0; // The timeout for a query (not used)
boolean escapeProcessing = true;// escape processing flag boolean escapeProcessing = true;// escape processing flag
...@@ -78,7 +74,7 @@ public class Statement implements java.sql.Statement ...@@ -78,7 +74,7 @@ public class Statement implements java.sql.Statement
* for this to happen when it is automatically closed. The * for this to happen when it is automatically closed. The
* close method provides this immediate release. * close method provides this immediate release.
* *
* <B>Note:</B> A Statement is automatically closed when it is * <p><B>Note:</B> A Statement is automatically closed when it is
* garbage collected. When a Statement is closed, its current * garbage collected. When a Statement is closed, its current
* ResultSet, if one exists, is also closed. * ResultSet, if one exists, is also closed.
* *
...@@ -126,7 +122,7 @@ public class Statement implements java.sql.Statement ...@@ -126,7 +122,7 @@ public class Statement implements java.sql.Statement
*/ */
public int getMaxRows() throws SQLException public int getMaxRows() throws SQLException
{ {
return maxrows; return connection.maxrows;
} }
/** /**
...@@ -138,7 +134,7 @@ public class Statement implements java.sql.Statement ...@@ -138,7 +134,7 @@ public class Statement implements java.sql.Statement
*/ */
public void setMaxRows(int max) throws SQLException public void setMaxRows(int max) throws SQLException
{ {
maxrows = max; connection.maxrows = max;
} }
/** /**
...@@ -197,10 +193,10 @@ public class Statement implements java.sql.Statement ...@@ -197,10 +193,10 @@ public class Statement implements java.sql.Statement
* chain. Subsequent Statement warnings will be chained to this * chain. Subsequent Statement warnings will be chained to this
* SQLWarning. * SQLWarning.
* *
* The Warning chain is automatically cleared each time a statement * <p>The Warning chain is automatically cleared each time a statement
* is (re)executed. * is (re)executed.
* *
* <B>Note:</B> If you are processing a ResultSet then any warnings * <p><B>Note:</B> If you are processing a ResultSet then any warnings
* associated with ResultSet reads will be chained on the ResultSet * associated with ResultSet reads will be chained on the ResultSet
* object. * object.
* *
...@@ -231,12 +227,12 @@ public class Statement implements java.sql.Statement ...@@ -231,12 +227,12 @@ public class Statement implements java.sql.Statement
* doesn't support positioned update/delete, this method is a * doesn't support positioned update/delete, this method is a
* no-op. * no-op.
* *
* <B>Note:</B> By definition, positioned update/delete execution * <p><B>Note:</B> By definition, positioned update/delete execution
* must be done by a different Statement than the one which * must be done by a different Statement than the one which
* generated the ResultSet being used for positioning. Also, cursor * generated the ResultSet being used for positioning. Also, cursor
* names must be unique within a Connection. * names must be unique within a Connection.
* *
* We throw an additional constriction. There can only be one * <p>We throw an additional constriction. There can only be one
* cursor active at any one time. * cursor active at any one time.
* *
* @param name the new cursor name * @param name the new cursor name
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册