Commit ba977c08 authored by Marc G. Fournier's avatar Marc G. Fournier

Peter's Mega-Patch for JDBC...

see README_6.3 for list of changes
parent 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
...@@ -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
{ {
...@@ -22,7 +20,7 @@ public class Field ...@@ -22,7 +20,7 @@ public class Field
String type_name = null;// The sql type name 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 conn the connection this field came from
* @param name the name of the field * @param name the name of the 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(); sql_type = getSQLType(result.getString(1));
type_name = result.getString(1); result.close();
if (type_name.equals("int2")) }
sql_type = Types.SMALLINT; return sql_type;
else if (type_name.equals("int4")) }
sql_type = Types.INTEGER;
else if (type_name.equals("int8")) /**
sql_type = Types.BIGINT; * This returns the SQL type. It is called by the Field and DatabaseMetaData classes
else if (type_name.equals("cash")) * @param type_name PostgreSQL type name
sql_type = Types.DECIMAL; * @return java.sql.Types value for oid
else if (type_name.equals("money")) */
sql_type = Types.DECIMAL; public static int getSQLType(String type_name)
else if (type_name.equals("float4")) {
sql_type = Types.REAL; int sql_type = Types.OTHER; // default value
else if (type_name.equals("float8")) for(int i=0;i<types.length;i++)
sql_type = Types.DOUBLE; if(type_name.equals(types[i]))
else if (type_name.equals("bpchar")) sql_type=typei[i];
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 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,35 +253,49 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta ...@@ -254,35 +253,49 @@ 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
{ {
StringBuffer b = new StringBuffer(); // if the passed string is null, then set this column to null
int i; if(x==null)
set(parameterIndex,"null");
b.append('\''); else {
for (i = 0 ; i < x.length() ; ++i) StringBuffer b = new StringBuffer();
{ int i;
char c = x.charAt(i);
if (c == '\\' || c == '\'') b.append('\'');
b.append((char)'\\'); for (i = 0 ; i < x.length() ; ++i)
b.append(c); {
} char c = x.charAt(i);
b.append('\''); if (c == '\\' || c == '\'')
set(parameterIndex, b.toString()); 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 * Set a parameter to a Java array of bytes. The driver converts this
* to a SQL VARBINARY or LONGVARBINARY (depending on the argument's * to a SQL VARBINARY or LONGVARBINARY (depending on the argument's
* 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.
* *
* @param parameterIndex the first parameter is 1... * <p>Implementation note:
* @param x the parameter value * <br>With postgresql, this creates a large object, and stores the
* @exception SQLException if a database access error occurs * objects oid in this column.
*/ *
public void setBytes(int parameterIndex, byte x[]) throws SQLException * @param parameterIndex the first parameter is 1...
{ * @param x the parameter value
throw new SQLException("Binary Data not supported"); * @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 * 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 ...@@ -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,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% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment