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