diff --git a/src/interfaces/jdbc/Makefile b/src/interfaces/jdbc/Makefile index 469b552a699..928aafae5ef 100644 --- a/src/interfaces/jdbc/Makefile +++ b/src/interfaces/jdbc/Makefile @@ -4,7 +4,7 @@ # Makefile for Java JDBC interface # # IDENTIFICATION -# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.2 1997/09/29 20:11:42 scrappy Exp $ +# $Header: /cvsroot/pgsql/src/interfaces/jdbc/Attic/Makefile,v 1.3 1998/01/11 21:14:29 scrappy Exp $ # #------------------------------------------------------------------------- @@ -22,41 +22,70 @@ RM = rm -f $(JAVAC) $< .SUFFIXES: .class .java -.PHONY: all clean doc +.PHONY: all clean doc examples all: postgresql.jar + @echo ------------------------------------------------------------ + @echo The JDBC driver has now been built. To make it available to + @echo other applications, copy the postgresql.jar file to a public + @echo "place (under unix this could be /usr/local/lib) and add it" + @echo to the class path. + @echo + @echo Then either add -Djdbc.drivers=postgresql.Driver to the + @echo commandline when running your application, or edit the + @echo "properties file (~/.hotjava/properties under unix), and" + @echo add a line containing jdbc.drivers=postgresql.Driver + @echo + @echo More details are in the README file. + @echo ------------------------------------------------------------ + @echo To build the examples, type: + @echo " make examples" + @echo ------------------------------------------------------------ + @echo +# This rule builds the javadoc documentation doc: - $(JAVADOC) -public postgresql + export CLASSPATH=.;\ + $(JAVADOC) -public \ + postgresql \ + postgresql.fastpath \ + postgresql.largeobject +# These classes form the driver. These, and only these are placed into +# the jar file. OBJS= postgresql/CallableStatement.class \ postgresql/Connection.class \ postgresql/DatabaseMetaData.class \ postgresql/Driver.class \ postgresql/Field.class \ - postgresql/PG_Object.class \ postgresql/PG_Stream.class \ - postgresql/PGbox.class \ - postgresql/PGcircle.class \ - postgresql/PGlobj.class \ - postgresql/PGlseg.class \ - postgresql/PGpath.class \ - postgresql/PGpoint.class \ - postgresql/PGpolygon.class \ - postgresql/PGtokenizer.class \ postgresql/PreparedStatement.class \ postgresql/ResultSet.class \ postgresql/ResultSetMetaData.class \ - postgresql/Statement.class + postgresql/Statement.class \ + postgresql/fastpath/Fastpath.class \ + postgresql/fastpath/FastpathArg.class \ + postgresql/geometric/PGbox.class \ + postgresql/geometric/PGcircle.class \ + postgresql/geometric/PGlseg.class \ + postgresql/geometric/PGpath.class \ + postgresql/geometric/PGpoint.class \ + postgresql/geometric/PGpolygon.class \ + postgresql/largeobject/LargeObject.class \ + postgresql/largeobject/LargeObjectManager.class \ + postgresql/util/PGobject.class \ + postgresql/util/PGtokenizer.class postgresql.jar: $(OBJS) - $(JAR) -c0vf $@ $^ + $(JAR) -c0vf $@ $$($(FIND) postgresql -name "*.class" -print) # This rule removes any temporary and compiled files from the source tree. clean: $(FIND) . -name "*~" -exec $(RM) {} \; $(FIND) . -name "*.class" -exec $(RM) {} \; + $(FIND) . -name "*.html" -exec $(RM) {} \; $(RM) postgresql.jar + -$(RM) -rf Package-postgresql *output ####################################################################### # This helps make workout what classes are from what source files @@ -69,21 +98,56 @@ postgresql/Connection.class: postgresql/Connection.java postgresql/DatabaseMetaData.class: postgresql/DatabaseMetaData.java postgresql/Driver.class: postgresql/Driver.java postgresql/Field.class: postgresql/Field.java -postgresql/PG_Object.class: postgresql/PG_Object.java postgresql/PG_Stream.class: postgresql/PG_Stream.java -postgresql/PGbox.class: postgresql/PGbox.java -postgresql/PGcircle.class: postgresql/PGcircle.java -postgresql/PGlobj.class: postgresql/PGlobj.java -postgresql/PGlseg.class: postgresql/PGlseg.java -postgresql/PGpath.class: postgresql/PGpath.java -postgresql/PGpoint.class: postgresql/PGpoint.java -postgresql/PGpolygon.class: postgresql/PGpolygon.java -postgresql/PGtokenizer.class: postgresql/PGtokenizer.java postgresql/PreparedStatement.class: postgresql/PreparedStatement.java postgresql/ResultSet.class: postgresql/ResultSet.java postgresql/ResultSetMetaData.class: postgresql/ResultSetMetaData.java postgresql/Statement.class: postgresql/Statement.java +postgresql/fastpath/Fastpath.class: postgresql/fastpath/Fastpath.java +postgresql/fastpath/FastpathArg.class: postgresql/fastpath/FastpathArg.java +postgresql/geometric/PGbox.class: postgresql/geometric/PGbox.java +postgresql/geometric/PGcircle.class: postgresql/geometric/PGcircle.java +postgresql/geometric/PGlseg.class: postgresql/geometric/PGlseg.java +postgresql/geometric/PGpath.class: postgresql/geometric/PGpath.java +postgresql/geometric/PGpoint.class: postgresql/geometric/PGpoint.java +postgresql/geometric/PGpolygon.class: postgresql/geometric/PGpolygon.java +postgresql/largeobject/LargeObject.class: postgresql/largeobject/LargeObject.java +postgresql/largeobject/LargeObjectManager.class: postgresql/largeobject/LargeObjectManager.java +postgresql/util/PGobject.class: postgresql/util/PGobject.java +postgresql/util/PGtokenizer.class: postgresql/util/PGtokenizer.java +####################################################################### +# These classes are in the example directory, and form the examples +EX= example/basic.class \ + example/blobtest.class \ + example/datestyle.class \ + example/psql.class \ + example/ImageViewer.class +# This rule builds the examples +examples: postgresql.jar $(EX) + @echo ------------------------------------------------------------ + @echo The examples have been built. + @echo + @echo For instructions on how to use them, simply run them. For example: + @echo + @echo " java example.blobtest" + @echo + @echo This would display instructions on how to run the example. + @echo ------------------------------------------------------------ + @echo Available examples: + @echo + @echo " example.basic Basic JDBC useage" + @echo " example.blobtest Binary Large Object tests" + @echo " example.datestyle Shows how datestyles are handled" + @echo " example.ImageViewer Example application storing images" + @echo " example.psql Simple java implementation of psql" + @echo ------------------------------------------------------------ + @echo - +example/basic.class: example/basic.java +example/blobtest.class: example/blobtest.java +example/datestyle.class: example/datestyle.java +example/psql.class: example/psql.java +example/ImageViewer.class: example/ImageViewer.java +####################################################################### diff --git a/src/interfaces/jdbc/README b/src/interfaces/jdbc/README index cd43a5af2f3..035ad008bf3 100644 --- a/src/interfaces/jdbc/README +++ b/src/interfaces/jdbc/README @@ -10,6 +10,14 @@ or the JDBC mailing list: http://www.blackdown.org +For problems with this driver, then refer to the postgres-interfaces email +list: + + http://www.postgresql.org + +By the time V6.3 is released, full documentation will be on the web, and in +the distribution. + --------------------------------------------------------------------------- COMPILING @@ -115,15 +123,21 @@ them to the URL. eg: By default, the driver doesn't use password authentication. You can enable this by adding the argument auth. ie: - jdbc:postgresql:database?user=me&password=mypass&auth=y + jdbc:postgresql:database?user=me&password=mypass&auth=password or if passing the user & password directly via DriverManager.getConnection(): - jdbc:postgresql:database?auth=y + jdbc:postgresql:database?auth=password -PS: Password authentication is enabled if the value of auth starts with 'y'. +PS: Password authentication is enabled if the value of auth starts with 'p'. It is case insensitive. +As of postgresql 6.3, Ident (RFC 1413) authentication is also supported. +Simply use auth=ident in the url. + +Also, as of 6.3, a system property of postgresql.auth is supported. This +defines the default authentication to use. The auth property overides this. + --------------------------------------------------------------------------- That's the basics related to this driver. You'll need to read the JDBC Docs @@ -180,7 +194,7 @@ syntax for writing these to the database. --------------------------------------------------------------------------- -Peter T Mount, October 28 1997 +Peter T Mount, January 11 1998 home email: pmount@maidast.demon.co.uk http://www.demon.co.uk/finder work email: peter@maidstone.gov.uk http://www.maidstone.gov.uk diff --git a/src/interfaces/jdbc/README_6.3 b/src/interfaces/jdbc/README_6.3 new file mode 100644 index 00000000000..797d3ff99b7 --- /dev/null +++ b/src/interfaces/jdbc/README_6.3 @@ -0,0 +1,78 @@ +Ok, here's the JDBC patch. + +The jdbc6.3.tar.gz file that I've uploaded ftp.postgresql.org contains the +following files: + +README_6.3 This message +blob.patch The patch to src/backend/tcop/fastpath.c fixing large objects +jdbc.tar The entire jdbc driver + +I've put the entire driver here, rather than a patch, because its become +too complicated to do one this time. Files have been moved, two files +removed because they were obsolete, and there are a lot of new files. + +Heres what the patch does: + +* Memory overflow problem in the backend causing large objects to fail in + both libpq & jdbc (causing the backend to crash with a Segmentation + Violation) +* Problem with equals() method on the geometric support classes if the + class being checked wasn't the same class +* Fixed output of PGpath and PGpolygon support classes (missing , separator) +* Optimised the geometric support classes +* HTMLised the inline documentation, so the output of javadoc is easier + to read (mainly paragraphs) +* Removed obsolete class PGlobj (it never worked, and has been replaced + to read (mainly paragraphs) +* Removed obsolete class PGlobj (it never worked, and has been replaced + by the postgresql.largeobject package) +* Removed obsolete example JDBC_Test.java (replaced by new examples) +* Added < and > to nesting in PGtokenizer. +* Added fastpath support as a new package +* Added large object support as a new package +* Added ability of user code to handle custom storage types. +* Added new example testing the importing and exporting of a large object +* Added example application showing how to store and display images stored + as large objects +* Added example implementing part of psql client. This shows how to find out + what tables/columns are in a database (not yet complete) +* ResultSet.getBytes() now returns large object if field is an oid +* ResultSet.getString() now doesn't call getBytes() as this now would + cause an infinite loop because of large object support in getBytes() +* PreparedStatement.setBytes() now create a large object, and store its + oid into the column +* Reworked date style handling to make it easier to support new styles +* Added german and ISO styles, now all styles supported by postgresql + are now supported by the driver +* Fixed DatabaseMetaData.getTables() +* DatabaseMetaData.getTableTypes() returns our supported types. +* Fixed DatabaseMetaData.getColumns() + +These three are required for Borland's JBuilder to work. For now they +return an empty result, as I'm not sure yet on how to get the +required results. +* DatabaseMetaData.getBestRowIdentifier() +* DatabaseMetaData.getProcedureColumns() +* DatabaseMetaData.getIndexInfo() + +Finally, one change that is incompatible with earlier versions of the +driver. This change only affects any client code that uses the geometric +classes (eg: PGpoint) or the getObject()/setObject() methods. + +Because of a problem with javac, if user code includes the line: + +import postgresql.*; + +then javac will fail, saying that interfaces cannot be instanciated. + +To fix this, I've moved these classes into a new sub package, +postgresql.geometric and the PG_Object (renamed PGobject), and PGtokenizer +to postgresql.util.So the above line would become: + +import postgresql.geometric.*; + +Anyhow, I'm going to start writing some proper documentation for the +driver. For now, there is some available temporarily at: + + http://www.demon.co.uk/finder/postgres/jdbc/packages.html + diff --git a/src/interfaces/jdbc/postgresql/CallableStatement.java b/src/interfaces/jdbc/postgresql/CallableStatement.java index ede69bbb121..7f56a42b2a5 100644 --- a/src/interfaces/jdbc/postgresql/CallableStatement.java +++ b/src/interfaces/jdbc/postgresql/CallableStatement.java @@ -4,46 +4,114 @@ import java.sql.*; import java.math.*; /** - * JDBC Interface to Postgres95 functions + * CallableStatement is used to execute SQL stored procedures. + * + *
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 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;
diff --git a/src/interfaces/jdbc/postgresql/Connection.java b/src/interfaces/jdbc/postgresql/Connection.java
index 09344e1fe08..1c13b520d5b 100644
--- a/src/interfaces/jdbc/postgresql/Connection.java
+++ b/src/interfaces/jdbc/postgresql/Connection.java
@@ -5,22 +5,21 @@ import java.lang.*;
import java.net.*;
import java.util.*;
import java.sql.*;
-import postgresql.*;
+import postgresql.fastpath.*;
+import postgresql.largeobject.*;
+import postgresql.util.*;
/**
- * @version 1.0 15-APR-1997
- * @author 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
+ * 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:
+ * Important Notice
+ *
+ * It is primarily used by the LargeObject API
+ *
+ * The best way to use this is as follows:
+ *
+ * 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.
+ *
+ * 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:
+ *
+ * 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.
+ *
+ * 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.
+ *
+ * NOTE: This is not part of JDBC, but an extension.
+ *
+ * The best way to use this is as follows:
+ *
+ * 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()
+ {
+ for(int i=0;i 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.
*
+ * 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:
*
+ *
*
* 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:
+ * 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:
+ * 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:
+ *
+ * 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 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:
* 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)
{
diff --git a/src/interfaces/jdbc/postgresql/Field.java b/src/interfaces/jdbc/postgresql/Field.java
index a4cc3c76e76..78553dd32eb 100644
--- a/src/interfaces/jdbc/postgresql/Field.java
+++ b/src/interfaces/jdbc/postgresql/Field.java
@@ -6,10 +6,8 @@ import java.util.*;
import postgresql.*;
/**
- * postgresql.Field is a class used to describe fields in a PostgreSQL ResultSet
- *
- * @version 1.0 15-APR-1997
- * @author 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 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
+ * 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:
+ * 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
+ * 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
+ * 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");
}
diff --git a/src/interfaces/jdbc/postgresql/ResultSet.java b/src/interfaces/jdbc/postgresql/ResultSet.java
index 017b0ad2927..f8eea22595e 100644
--- a/src/interfaces/jdbc/postgresql/ResultSet.java
+++ b/src/interfaces/jdbc/postgresql/ResultSet.java
@@ -6,31 +6,32 @@ import java.math.*;
import java.text.*;
import java.util.*;
import java.sql.*;
-import postgresql.*;
+import postgresql.largeobject.*;
+import postgresql.util.*;
/**
* A ResultSet provides access to a table of data generated by executing a
* Statement. The table rows are retrieved in sequence. Within a row its
* column values can be accessed in any order.
*
- * A ResultSet maintains a cursor pointing to its current row of data.
+ * 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
+ * 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
+ * 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
+ * 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
+ * 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()
diff --git a/src/interfaces/jdbc/postgresql/ResultSetMetaData.java b/src/interfaces/jdbc/postgresql/ResultSetMetaData.java
index 7d2c1ceaf33..c4e54dbefaa 100644
--- a/src/interfaces/jdbc/postgresql/ResultSetMetaData.java
+++ b/src/interfaces/jdbc/postgresql/ResultSetMetaData.java
@@ -6,9 +6,6 @@ import java.util.*;
import postgresql.*;
/**
- * @version 1.0 15-APR-1997
- * @author Adrian Hall
- *
* A ResultSetMetaData object can be used to find out about the types and
* properties of the columns in a ResultSet
*
diff --git a/src/interfaces/jdbc/postgresql/Statement.java b/src/interfaces/jdbc/postgresql/Statement.java
index 464a263621f..177b8189f6c 100644
--- a/src/interfaces/jdbc/postgresql/Statement.java
+++ b/src/interfaces/jdbc/postgresql/Statement.java
@@ -3,13 +3,10 @@ package postgresql;
import java.sql.*;
/**
- * @version 1.0 15-APR-1997
- * @author 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
+ * 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
+ * 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
+ * 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
+ * => 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.
*
+ *
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
+ * import postgresql.fastpath.*;
+ * ...
+ * Fastpath fp = ((postgresql.Connection)myconn).getFastpathAPI();
+ *
+ *
+ *
+ * import postgresql.largeobject.*;
+ * ...
+ * LargeObjectManager lo = ((postgresql.Connection)myconn).getLargeObjectAPI();
+ *
+ *
+ *
+ * ...
+ * ((postgresql.Connection)myconn).addDataType("mytype","my.class.name");
+ * ...
+ *
+ *
+ *
* 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
+ *
* 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;
+ *
+ *
*
* @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.
+ *
+ *
+ *
+ *
+ *
+ * @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.
+ *
+ *
+ *
+ *
+ *
+ *
- * 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
+ *
+ *
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
+ *