Update patch from Peter <patches@maidast.demon.co.uk>
This commit is contained in:
parent
0b6dc93b32
commit
6a061da272
@ -1,126 +1,133 @@
|
||||
package postgresql;
|
||||
|
||||
import java.math.*;
|
||||
import java.sql.*;
|
||||
import java.math.*;
|
||||
|
||||
/**
|
||||
* @version 1.0 15-APR-1997
|
||||
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
|
||||
*
|
||||
* CallableStatement is used to execute SQL stored procedures.
|
||||
*
|
||||
* JDBC provides a stored procedure SQL escape that allows stored procedures
|
||||
* to be called in a standard way for all RDBMS's. This escape syntax has
|
||||
* one form that includes a result parameter and one that does not. If used,
|
||||
* the result parameter must be generated 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.
|
||||
*
|
||||
* <PRE>
|
||||
* {?= call <procedure-name>[<arg1>,<arg2>, ...]}
|
||||
* {call <procedure-name>[<arg1>,<arg2>, ...]}
|
||||
* </PRE>
|
||||
*
|
||||
* IN parameters are set using the set methods inherited from
|
||||
* PreparedStatement. The type of all OUT parameters must be registered
|
||||
* prior to executing the stored procedure; their values are retrieved
|
||||
* after execution via the get methods provided here.
|
||||
*
|
||||
* A CallableStatement may return a ResultSet or multiple ResultSets. Multiple
|
||||
* ResultSets are handled using operations inherited from Statement.
|
||||
*
|
||||
* For maximum portability, a call's ResultSets and update counts should be
|
||||
* processed prior to getting the values of output parameters.
|
||||
*
|
||||
* @see java.sql.Connection#prepareCall
|
||||
* @see java.sql.ResultSet
|
||||
* @see java.sql.CallableStatement
|
||||
* JDBC Interface to Postgres95 functions
|
||||
*/
|
||||
public class CallableStatement implements java.sql.CallableStatement
|
||||
|
||||
// Copy methods from the Result set object here.
|
||||
|
||||
public class CallableStatement extends PreparedStatement implements java.sql.CallableStatement
|
||||
{
|
||||
public void registerOutParameter (int paramterIndex, int sqlType) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public void registerOutParameter (int parameterIndex, int sqlType, int scale) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public boolean wasNull () throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public String getString (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public boolean getBoolean (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public byte getByte (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public short getShort (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public int getInt (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public long getLong (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public float getFloat (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public double getDouble (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public BigDecimal getBigDecimal (int parameterIndex, int scale) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public byte[] getBytes (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public Date getDate (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public Time getTime (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public Timestamp getTimestamp (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
public Object getObject (int parameterIndex) throws SQLException
|
||||
{
|
||||
// XXX-Not Implemented
|
||||
}
|
||||
|
||||
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.
|
||||
public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
|
||||
}
|
||||
|
||||
// You must also specify the scale for numeric/decimal types:
|
||||
public void registerOutParameter(int parameterIndex, int sqlType,
|
||||
int scale) throws SQLException
|
||||
{
|
||||
}
|
||||
|
||||
public boolean isNull(int parameterIndex) throws SQLException {
|
||||
return true;
|
||||
}
|
||||
|
||||
// New API (JPM)
|
||||
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;
|
||||
}
|
||||
|
||||
// New API (JPM)
|
||||
public String getString(int parameterIndex) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
//public String getVarChar(int parameterIndex) throws SQLException {
|
||||
// return null;
|
||||
//}
|
||||
|
||||
public String getLongVarChar(int parameterIndex) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
// New API (JPM) (getBit)
|
||||
public boolean getBoolean(int parameterIndex) throws SQLException {
|
||||
return false;
|
||||
}
|
||||
|
||||
// New API (JPM) (getTinyInt)
|
||||
public byte getByte(int parameterIndex) throws SQLException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// New API (JPM) (getSmallInt)
|
||||
public short getShort(int parameterIndex) throws SQLException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// New API (JPM) (getInteger)
|
||||
public int getInt(int parameterIndex) throws SQLException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// New API (JPM) (getBigInt)
|
||||
public long getLong(int parameterIndex) throws SQLException {
|
||||
return 0;
|
||||
}
|
||||
|
||||
public float getFloat(int parameterIndex) throws SQLException {
|
||||
return (float) 0.0;
|
||||
}
|
||||
|
||||
public double getDouble(int parameterIndex) throws SQLException {
|
||||
return 0.0;
|
||||
}
|
||||
|
||||
public BigDecimal getBigDecimal(int parameterIndex, int scale)
|
||||
throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
// New API (JPM) (getBinary)
|
||||
public byte[] getBytes(int parameterIndex) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
// New API (JPM) (getLongVarBinary)
|
||||
public byte[] getBinaryStream(int parameterIndex) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
public java.sql.Date getDate(int parameterIndex) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
public java.sql.Time getTime(int parameterIndex) throws SQLException {
|
||||
return null;
|
||||
}
|
||||
public java.sql.Timestamp getTimestamp(int parameterIndex)
|
||||
throws SQLException {
|
||||
return null;
|
||||
}
|
||||
|
||||
//----------------------------------------------------------------------
|
||||
// Advanced features:
|
||||
|
||||
// You can obtain a ParameterMetaData object to get information
|
||||
// about the parameters to this CallableStatement.
|
||||
public DatabaseMetaData getMetaData() {
|
||||
return null;
|
||||
}
|
||||
|
||||
// getObject returns a Java object for the parameter.
|
||||
// See the JDBC spec's "Dynamic Programming" chapter for details.
|
||||
public Object getObject(int parameterIndex)
|
||||
throws SQLException {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -2,12 +2,8 @@ package postgresql;
|
||||
|
||||
import java.sql.*;
|
||||
import java.util.*;
|
||||
import postgresql.*;
|
||||
|
||||
/**
|
||||
* @version 1.0 15-APR-1997
|
||||
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
|
||||
*
|
||||
* The Java SQL framework allows for multiple database drivers. Each
|
||||
* driver should supply a class that implements the Driver interface
|
||||
*
|
||||
@ -28,242 +24,274 @@ import postgresql.*;
|
||||
*/
|
||||
public class Driver implements java.sql.Driver
|
||||
{
|
||||
|
||||
static
|
||||
{
|
||||
try
|
||||
{
|
||||
new Driver();
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
// These should be in sync with the backend that the driver was
|
||||
// distributed with
|
||||
static final int MAJORVERSION = 6;
|
||||
static final int MINORVERSION = 2;
|
||||
|
||||
static
|
||||
{
|
||||
try {
|
||||
// moved the registerDriver from the constructor to here
|
||||
// because some clients call the driver themselves (I know, as
|
||||
// my early jdbc work did - and that was based on other examples).
|
||||
// Placing it here, means that the driver is registered once only.
|
||||
java.sql.DriverManager.registerDriver(new Driver());
|
||||
} catch (SQLException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new driver and register it with DriverManager
|
||||
*
|
||||
* @exception SQLException for who knows what!
|
||||
*/
|
||||
public Driver() throws SQLException
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to make a database connection to the given URL. The driver
|
||||
* should return "null" if it realizes it is the wrong kind of
|
||||
* driver to connect to the given URL. This will be common, as
|
||||
* 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
|
||||
* to connect to the given URL, but has trouble connecting to the
|
||||
* database.
|
||||
*
|
||||
* 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:
|
||||
* <PRE>
|
||||
* jdbc:postgresql://host:port/database
|
||||
* </PRE>
|
||||
*
|
||||
* @param url the URL of the database to connect to
|
||||
* @param info a list of arbitrary tag/value pairs as connection
|
||||
* arguments
|
||||
* @return a connection to the URL or null if it isnt us
|
||||
* @exception SQLException if a database access error occurs
|
||||
* @see java.sql.Driver#connect
|
||||
*/
|
||||
public java.sql.Connection connect(String url, Properties info) throws SQLException
|
||||
{
|
||||
if((props = parseURL(url,info))==null)
|
||||
return null;
|
||||
|
||||
return new Connection (host(), port(), props, database(), url, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the driver thinks it can open a connection to the
|
||||
* given URL. Typically, drivers will return true if they understand
|
||||
* the subprotocol specified in the URL and false if they don't. Our
|
||||
* protocols start with jdbc:postgresql:
|
||||
*
|
||||
* @see java.sql.Driver#acceptsURL
|
||||
* @param url the URL of the driver
|
||||
* @return true if this driver accepts the given URL
|
||||
* @exception SQLException if a database-access error occurs
|
||||
* (Dont know why it would *shrug*)
|
||||
*/
|
||||
public boolean acceptsURL(String url) throws SQLException
|
||||
{
|
||||
if(parseURL(url,null)==null)
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* far, additional values may become necessary, so it may be necessary
|
||||
* to iterate through several calls to getPropertyInfo
|
||||
*
|
||||
* @param url the Url of the database to connect to
|
||||
* @param info a proposed list of tag/value pairs that will be sent on
|
||||
* connect open.
|
||||
* @return An array of DriverPropertyInfo objects describing
|
||||
* possible properties. This array may be an empty array if
|
||||
* no properties are required
|
||||
* @exception SQLException if a database-access error occurs
|
||||
* @see java.sql.Driver#getPropertyInfo
|
||||
*/
|
||||
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
|
||||
{
|
||||
return null; // We don't need anything except
|
||||
// the username, which is a default
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the drivers major version number
|
||||
*
|
||||
* @return the drivers major version number
|
||||
*/
|
||||
public int getMajorVersion()
|
||||
{
|
||||
return MAJORVERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the drivers minor version number
|
||||
*
|
||||
* @return the drivers minor version number
|
||||
*/
|
||||
public int getMinorVersion()
|
||||
{
|
||||
return MINORVERSION;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report whether the driver is a genuine JDBC compliant driver. A
|
||||
* driver may only report "true" here if it passes the JDBC compliance
|
||||
* tests, otherwise it is required to return false. JDBC compliance
|
||||
* requires full support for the JDBC API and full support for SQL 92
|
||||
* Entry Level.
|
||||
*/
|
||||
public boolean jdbcCompliant()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
private Properties props;
|
||||
|
||||
static private String[] protocols = { "jdbc","postgresql" };
|
||||
|
||||
/**
|
||||
* Constructs a new DriverURL, splitting the specified URL into its
|
||||
* component parts
|
||||
*/
|
||||
Properties parseURL(String url,Properties defaults) throws SQLException
|
||||
{
|
||||
int state = -1;
|
||||
Properties urlProps = new Properties(defaults);
|
||||
String key = new String();
|
||||
String value = new String();
|
||||
|
||||
StringTokenizer st = new StringTokenizer(url, ":/;=&?", true);
|
||||
for (int count = 0; (st.hasMoreTokens()); count++) {
|
||||
String token = st.nextToken();
|
||||
|
||||
// PM June 29 1997
|
||||
// Added this, to help me understand how this works.
|
||||
// Unless you want each token to be processed, leave this commented out
|
||||
// but don't delete it.
|
||||
//DriverManager.println("wellFormedURL: state="+state+" count="+count+" token='"+token+"'");
|
||||
|
||||
// PM Aug 2 1997 - Modified to allow multiple backends
|
||||
if (count <= 3) {
|
||||
if ((count % 2) == 1 && token.equals(":"))
|
||||
;
|
||||
else if((count % 2) == 0) {
|
||||
boolean found=(count==0)?true:false;
|
||||
for(int tmp=0;tmp<protocols.length;tmp++) {
|
||||
if(token.equals(protocols[tmp])) {
|
||||
// PM June 29 1997 Added this property to enable the driver
|
||||
// to handle multiple backend protocols.
|
||||
if(count == 2 && tmp > 0) {
|
||||
urlProps.put("Protocol",token);
|
||||
found=true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(found == false)
|
||||
return null;
|
||||
} else return null;
|
||||
}
|
||||
else if (count > 3) {
|
||||
if (count == 4 && token.equals("/")) state = 0;
|
||||
else if (count == 4) {
|
||||
urlProps.put("PGDBNAME", token);
|
||||
state = -2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Construct a new driver and register it with DriverManager
|
||||
*
|
||||
* @exception SQLException for who knows what!
|
||||
*/
|
||||
public Driver() throws SQLException
|
||||
{
|
||||
java.sql.DriverManager.registerDriver(this);
|
||||
else if (count == 5 && state == 0 && token.equals("/"))
|
||||
state = 1;
|
||||
else if (count == 5 && state == 0)
|
||||
return null;
|
||||
else if (count == 6 && state == 1)
|
||||
urlProps.put("PGHOST", token);
|
||||
else if (count == 7 && token.equals(":")) state = 2;
|
||||
else if (count == 8 && state == 2) {
|
||||
try {
|
||||
Integer portNumber = Integer.decode(token);
|
||||
urlProps.put("PGPORT", portNumber.toString());
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Try to make a database connection to the given URL. The driver
|
||||
* should return "null" if it realizes it is the wrong kind of
|
||||
* driver to connect to the given URL. This will be common, as
|
||||
* 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
|
||||
* to connect to the given URL, but has trouble connecting to the
|
||||
* database.
|
||||
*
|
||||
* 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:
|
||||
* <PRE>
|
||||
* jdbc:postgresql://host:port/database
|
||||
* </PRE>
|
||||
*
|
||||
* @param url the URL of the database to connect to
|
||||
* @param info a list of arbitrary tag/value pairs as connection
|
||||
* arguments
|
||||
* @return a connection to the URL or null if it isnt us
|
||||
* @exception SQLException if a database access error occurs
|
||||
* @see java.sql.Driver#connect
|
||||
*/
|
||||
public java.sql.Connection connect(String url, Properties info) throws SQLException
|
||||
{
|
||||
DriverURL dr = new DriverURL(url);
|
||||
int port;
|
||||
|
||||
if (!(dr.protocol().equals("jdbc")))
|
||||
return null;
|
||||
if (!(dr.subprotocol().equals("postgresql")))
|
||||
return null;
|
||||
if (dr.host().equals("unknown"))
|
||||
return null;
|
||||
port = dr.port();
|
||||
if (port == -1)
|
||||
port = 5432; // Default PostgreSQL port
|
||||
return new Connection (dr.host(), port, info, dr.database(), url, this);
|
||||
else if ((count == 7 || count == 9) &&
|
||||
(state == 1 || state == 2) && token.equals("/"))
|
||||
state = -1;
|
||||
else if (state == -1) {
|
||||
urlProps.put("PGDBNAME", token);
|
||||
state = -2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if the driver thinks it can open a connection to the
|
||||
* given URL. Typically, drivers will return true if they understand
|
||||
* the subprotocol specified in the URL and false if they don't. Our
|
||||
* protocols start with jdbc:postgresql:
|
||||
*
|
||||
* @see java.sql.Driver#acceptsURL
|
||||
* @param url the URL of the driver
|
||||
* @return true if this driver accepts the given URL
|
||||
* @exception SQLException if a database-access error occurs
|
||||
* (Dont know why it would *shrug*)
|
||||
*/
|
||||
public boolean acceptsURL(String url) throws SQLException
|
||||
{
|
||||
DriverURL dr = new DriverURL(url);
|
||||
|
||||
if (dr.protocol().equals("jdbc"))
|
||||
if (dr.subprotocol().equals("postgresql"))
|
||||
return true;
|
||||
return false;
|
||||
else if (state <= -2 && (count % 2) == 1) {
|
||||
// PM Aug 2 1997 - added tests for ? and &
|
||||
if (token.equals(";") || token.equals("?") || token.equals("&") ) state = -3;
|
||||
else if (token.equals("=")) state = -5;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* far, additional values may become necessary, so it may be necessary
|
||||
* to iterate through several calls to getPropertyInfo
|
||||
*
|
||||
* @param url the Url of the database to connect to
|
||||
* @param info a proposed list of tag/value pairs that will be sent on
|
||||
* connect open.
|
||||
* @return An array of DriverPropertyInfo objects describing
|
||||
* possible properties. This array may be an empty array if
|
||||
* no properties are required
|
||||
* @exception SQLException if a database-access error occurs
|
||||
* @see java.sql.Driver#getPropertyInfo
|
||||
*/
|
||||
public DriverPropertyInfo[] getPropertyInfo(String url, Properties info) throws SQLException
|
||||
{
|
||||
return null; // We don't need anything except
|
||||
// the username, which is a default
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the drivers major version number
|
||||
*
|
||||
* @return the drivers major version number
|
||||
*/
|
||||
public int getMajorVersion()
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the drivers minor version number
|
||||
*
|
||||
* @return the drivers minor version number
|
||||
*/
|
||||
public int getMinorVersion()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Report whether the driver is a genuine JDBC compliant driver. A
|
||||
* driver may only report "true" here if it passes the JDBC compliance
|
||||
* tests, otherwise it is required to return false. JDBC compliance
|
||||
* requires full support for the JDBC API and full support for SQL 92
|
||||
* Entry Level.
|
||||
*/
|
||||
public boolean jdbcCompliant()
|
||||
{
|
||||
return false;
|
||||
else if (state <= -2 && (count % 2) == 0) {
|
||||
if (state == -3) key = token;
|
||||
else if (state == -5) {
|
||||
value = token;
|
||||
//DriverManager.println("put("+key+","+value+")");
|
||||
urlProps.put(key, value);
|
||||
state = -2;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// PM June 29 1997
|
||||
// This now outputs the properties only if we are logging
|
||||
if(DriverManager.getLogStream() != null)
|
||||
urlProps.list(DriverManager.getLogStream());
|
||||
|
||||
return urlProps;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hostname portion of the URL
|
||||
*/
|
||||
public String host()
|
||||
{
|
||||
return props.getProperty("PGHOST","localhost");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port number portion of the URL
|
||||
* or -1 if no port was specified
|
||||
*/
|
||||
public int port()
|
||||
{
|
||||
return Integer.parseInt(props.getProperty("PGPORT","5432"));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database name of the URL
|
||||
*/
|
||||
public String database()
|
||||
{
|
||||
return props.getProperty("PGDBNAME");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns any property
|
||||
*/
|
||||
public String property(String name)
|
||||
{
|
||||
return props.getProperty(name);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The DriverURL class splits a JDBC URL into its subcomponents
|
||||
*
|
||||
* protocol:subprotocol:/[/host[:port]/][database]
|
||||
*/
|
||||
class DriverURL
|
||||
{
|
||||
private String protocol, subprotocol, host, database;
|
||||
private int port = -1;
|
||||
|
||||
/**
|
||||
* Constructs a new DriverURL, splitting the specified URL into its
|
||||
* component parts
|
||||
*/
|
||||
public DriverURL(String url) throws SQLException
|
||||
{
|
||||
int a, b, c;
|
||||
String tmp, hostport, dbportion;
|
||||
|
||||
a = url.indexOf(':');
|
||||
if (a == -1)
|
||||
throw new SQLException("Bad URL Protocol specifier");
|
||||
b = url.indexOf(':', a+1);
|
||||
if (b == -1)
|
||||
throw new SQLException("Bad URL Subprotocol specifier");
|
||||
protocol = new String(url.substring(0, a));
|
||||
subprotocol = new String(url.substring(a+1, b));
|
||||
tmp = new String(url.substring(b+1, url.length()));
|
||||
if (tmp.length() < 2)
|
||||
throw new SQLException("Bad URL Database specifier");
|
||||
if (!tmp.substring(0, 2).equals("//"))
|
||||
{
|
||||
host = new String("unknown");
|
||||
port = -1;
|
||||
database = new String(tmp.substring(1, tmp.length()));
|
||||
return;
|
||||
}
|
||||
dbportion = new String(tmp.substring(2, tmp.length()));
|
||||
c = dbportion.indexOf('/');
|
||||
if (c == -1)
|
||||
throw new SQLException("Bad URL Database specifier");
|
||||
a = dbportion.indexOf(':');
|
||||
if (a == -1)
|
||||
{
|
||||
host = new String(dbportion.substring(0, c));
|
||||
port = -1;
|
||||
database = new String(dbportion.substring(c+1, dbportion.length()));
|
||||
} else {
|
||||
host = new String(dbportion.substring(0, a));
|
||||
port = Integer.valueOf(dbportion.substring(a+1, c)).intValue();
|
||||
database = new String(dbportion.substring(c+1, dbportion.length()));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the protocol name of the DriverURL
|
||||
*/
|
||||
public String protocol()
|
||||
{
|
||||
return protocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the subprotocol name of the DriverURL
|
||||
*/
|
||||
public String subprotocol()
|
||||
{
|
||||
return subprotocol;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hostname portion of the URL
|
||||
*/
|
||||
public String host()
|
||||
{
|
||||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the port number portion of the URL
|
||||
* or -1 if no port was specified
|
||||
*/
|
||||
public int port()
|
||||
{
|
||||
return port;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the database name of the URL
|
||||
*/
|
||||
public String database()
|
||||
{
|
||||
return database;
|
||||
}
|
||||
}
|
||||
|
@ -13,77 +13,91 @@ import postgresql.*;
|
||||
*/
|
||||
public class Field
|
||||
{
|
||||
int length; // Internal Length of this field
|
||||
int oid; // OID of the type
|
||||
Connection conn; // Connection Instantation
|
||||
String name; // Name of this field
|
||||
|
||||
int sql_type = -1; // The entry in java.sql.Types for this field
|
||||
String type_name = null;// The sql type name
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param oid the OID of the field
|
||||
* @param len the length of the field
|
||||
*/
|
||||
public Field(Connection conn, String name, int oid, int length)
|
||||
{
|
||||
this.conn = conn;
|
||||
this.name = name;
|
||||
this.oid = oid;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* the ResultSet and ResultMetaData both need to handle the SQL
|
||||
* type, which is gained from another query. Note that we cannot
|
||||
* use getObject() in this, since getObject uses getSQLType().
|
||||
*
|
||||
* @return the entry in Types that refers to this field
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
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 sql_type = Types.OTHER;
|
||||
}
|
||||
return sql_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* we get this information within getSQLType (if it isn't already
|
||||
* done), we can just call getSQLType and throw away the result.
|
||||
*
|
||||
* @return the String representation of the type of this field
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getTypeName() throws SQLException
|
||||
{
|
||||
int sql = getSQLType();
|
||||
return type_name;
|
||||
}
|
||||
int length; // Internal Length of this field
|
||||
int oid; // OID of the type
|
||||
Connection conn; // Connection Instantation
|
||||
String name; // Name of this field
|
||||
|
||||
int sql_type = -1; // The entry in java.sql.Types for this field
|
||||
String type_name = null;// The sql type name
|
||||
|
||||
/**
|
||||
* 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
|
||||
* @param oid the OID of the field
|
||||
* @param len the length of the field
|
||||
*/
|
||||
public Field(Connection conn, String name, int oid, int length)
|
||||
{
|
||||
this.conn = conn;
|
||||
this.name = name;
|
||||
this.oid = oid;
|
||||
this.length = length;
|
||||
}
|
||||
|
||||
/**
|
||||
* the ResultSet and ResultMetaData both need to handle the SQL
|
||||
* type, which is gained from another query. Note that we cannot
|
||||
* use getObject() in this, since getObject uses getSQLType().
|
||||
*
|
||||
* @return the entry in Types that refers to this field
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
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
|
||||
sql_type = Types.OTHER;
|
||||
}
|
||||
return sql_type;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* we get this information within getSQLType (if it isn't already
|
||||
* done), we can just call getSQLType and throw away the result.
|
||||
*
|
||||
* @return the String representation of the type of this field
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getTypeName() throws SQLException
|
||||
{
|
||||
int sql = getSQLType();
|
||||
return type_name;
|
||||
}
|
||||
}
|
||||
|
@ -14,18 +14,132 @@ import postgresql.*;
|
||||
*/
|
||||
public class PG_Object
|
||||
{
|
||||
public String type;
|
||||
public String value;
|
||||
|
||||
/**
|
||||
* Constructor for the PostgreSQL generic object
|
||||
*
|
||||
* @param type a string describing the type of the object
|
||||
* @param value a string representation of the value of the object
|
||||
*/
|
||||
public PG_Object(String type, String value)
|
||||
{
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
public String type;
|
||||
public String value;
|
||||
|
||||
/**
|
||||
* Constructor for the PostgreSQL generic object
|
||||
*
|
||||
* @param type a string describing the type of the object
|
||||
* @param value a string representation of the value of the object
|
||||
*/
|
||||
public PG_Object(String type, String value) throws SQLException
|
||||
{
|
||||
this.type = type;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns true if the object is a 'box'
|
||||
*/
|
||||
public boolean isBox()
|
||||
{
|
||||
return type.equals("box");
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a PGbox object, or null if it's not
|
||||
* @return PGbox
|
||||
*/
|
||||
public PGbox getBox() throws SQLException
|
||||
{
|
||||
if(isBox())
|
||||
return new PGbox(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns true if the object is a 'point'
|
||||
*/
|
||||
public boolean isCircle()
|
||||
{
|
||||
return type.equals("circle");
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a PGcircle object, or null if it's not
|
||||
* @return PGcircle
|
||||
*/
|
||||
public PGcircle getCircle() throws SQLException
|
||||
{
|
||||
if(isCircle())
|
||||
return new PGcircle(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns true if the object is a 'lseg' (line segment)
|
||||
*/
|
||||
public boolean isLseg()
|
||||
{
|
||||
return type.equals("lseg");
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a PGlsegobject, or null if it's not
|
||||
* @return PGlseg
|
||||
*/
|
||||
public PGlseg getLseg() throws SQLException
|
||||
{
|
||||
if(isLseg())
|
||||
return new PGlseg(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns true if the object is a 'path'
|
||||
*/
|
||||
public boolean isPath()
|
||||
{
|
||||
return type.equals("path");
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a PGpath object, or null if it's not
|
||||
* @return PGpath
|
||||
*/
|
||||
public PGpath getPath() throws SQLException
|
||||
{
|
||||
if(isPath())
|
||||
return new PGpath(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns true if the object is a 'point'
|
||||
*/
|
||||
public boolean isPoint()
|
||||
{
|
||||
return type.equals("point");
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a PGpoint object, or null if it's not
|
||||
* @return PGpoint object
|
||||
*/
|
||||
public PGpoint getPoint() throws SQLException
|
||||
{
|
||||
if(isPoint())
|
||||
return new PGpoint(value);
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns true if the object is a 'polygon'
|
||||
*/
|
||||
public boolean isPolygon()
|
||||
{
|
||||
return type.equals("polygon");
|
||||
}
|
||||
|
||||
/**
|
||||
* This returns a PGpolygon object, or null if it's not
|
||||
* @return PGpolygon
|
||||
*/
|
||||
public PGpolygon getPolygon() throws SQLException
|
||||
{
|
||||
if(isPolygon())
|
||||
return new PGpolygon(value);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -16,414 +16,415 @@ import postgresql.*;
|
||||
*/
|
||||
public class ResultSetMetaData implements java.sql.ResultSetMetaData
|
||||
{
|
||||
Vector rows;
|
||||
Field[] fields;
|
||||
|
||||
/**
|
||||
* Initialise for a result with a tuple set and
|
||||
* a field descriptor set
|
||||
*
|
||||
* @param rows the Vector of rows returned by the ResultSet
|
||||
* @param fields the array of field descriptors
|
||||
*/
|
||||
public ResultSetMetaData(Vector rows, Field[] fields)
|
||||
{
|
||||
this.rows = rows;
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whats the number of columns in the ResultSet?
|
||||
*
|
||||
* @return the number
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getColumnCount() throws SQLException
|
||||
{
|
||||
return fields.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the column automatically numbered (and thus read-only)
|
||||
* I believe that PostgreSQL does not support this feature.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isAutoIncrement(int column) throws SQLException
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a column's case matter? ASSUMPTION: Any field that is
|
||||
* not obviously case insensitive is assumed to be case sensitive
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isCaseSensitive(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.SMALLINT:
|
||||
case Types.INTEGER:
|
||||
case Types.FLOAT:
|
||||
case Types.REAL:
|
||||
case Types.DOUBLE:
|
||||
case Types.DATE:
|
||||
case Types.TIME:
|
||||
case Types.TIMESTAMP:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the column be used in a WHERE clause? Basically for
|
||||
* this, I split the functions into two types: recognised
|
||||
* types (which are always useable), and OTHER types (which
|
||||
* may or may not be useable). The OTHER types, for now, I
|
||||
* will assume they are useable. We should really query the
|
||||
* catalog to see if they are useable.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if they can be used in a WHERE clause
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isSearchable(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
// This switch is pointless, I know - but it is a set-up
|
||||
// for further expansion.
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.OTHER:
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the column a cash value? 6.1 introduced the cash/money
|
||||
* type, which haven't been incorporated as of 970414, so I
|
||||
* just check the type name for both 'cash' and 'money'
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if its a cash column
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isCurrency(int column) throws SQLException
|
||||
{
|
||||
String type_name = getField(column).getTypeName();
|
||||
|
||||
if (type_name.equals("cash"))
|
||||
return true;
|
||||
if (type_name.equals("money"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can you put a NULL in this column? I think this is always
|
||||
* true in 6.1's case. It would only be false if the field had
|
||||
* been defined NOT NULL (system catalogs could be queried?)
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return one of the columnNullable values
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int isNullable(int column) throws SQLException
|
||||
{
|
||||
return columnNullable; // We can always put NULL in
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the column a signed number? In PostgreSQL, all numbers
|
||||
* are signed, so this is trivial. However, strings are not
|
||||
* signed (duh!)
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isSigned(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.SMALLINT:
|
||||
case Types.INTEGER:
|
||||
case Types.FLOAT:
|
||||
case Types.REAL:
|
||||
case Types.DOUBLE:
|
||||
return true;
|
||||
case Types.DATE:
|
||||
case Types.TIME:
|
||||
case Types.TIMESTAMP:
|
||||
return false; // I don't know about these?
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the column's normal maximum width in characters?
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the maximum width
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getColumnDisplaySize(int column) throws SQLException
|
||||
{
|
||||
int max = getColumnLabel(column).length();
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < rows.size(); ++i)
|
||||
{
|
||||
byte[][] x = (byte[][])(rows.elementAt(i));
|
||||
int xl = x[column - 1].length;
|
||||
if (xl > max)
|
||||
max = xl;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the suggested column title for use in printouts and
|
||||
* displays? We suggest the ColumnName!
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the column label
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getColumnLabel(int column) throws SQLException
|
||||
{
|
||||
return getColumnName(column);
|
||||
}
|
||||
|
||||
/**
|
||||
* What's a column's name?
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the column name
|
||||
* @exception SQLException if a databvase access error occurs
|
||||
*/
|
||||
public String getColumnName(int column) throws SQLException
|
||||
{
|
||||
return getField(column).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* What is a column's table's schema? This relies on us knowing
|
||||
* the table name....which I don't know how to do as yet. The
|
||||
* JDBC specification allows us to return "" if this is not
|
||||
* applicable.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return the Schema
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getSchemaName(int column) throws SQLException
|
||||
{
|
||||
String table_name = getTableName(column);
|
||||
|
||||
// If the table name is invalid, so are we.
|
||||
if (table_name.equals(""))
|
||||
return "";
|
||||
return ""; // Ok, so I don't know how to
|
||||
// do this as yet.
|
||||
}
|
||||
|
||||
/**
|
||||
* What is a column's number of decimal digits.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return the precision
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getPrecision(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.SMALLINT:
|
||||
return 5;
|
||||
case Types.INTEGER:
|
||||
return 10;
|
||||
case Types.REAL:
|
||||
return 8;
|
||||
case Types.FLOAT:
|
||||
return 16;
|
||||
case Types.DOUBLE:
|
||||
return 16;
|
||||
default:
|
||||
throw new SQLException("no precision for non-numeric data types.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* What is a column's number of digits to the right of the
|
||||
* decimal point?
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return the scale
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getScale(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.SMALLINT:
|
||||
return 0;
|
||||
case Types.INTEGER:
|
||||
return 0;
|
||||
case Types.REAL:
|
||||
return 8;
|
||||
case Types.FLOAT:
|
||||
return 16;
|
||||
case Types.DOUBLE:
|
||||
return 16;
|
||||
default:
|
||||
throw new SQLException("no scale for non-numeric data types");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whats a column's table's name? How do I find this out? Both
|
||||
* getSchemaName() and getCatalogName() rely on knowing the table
|
||||
* Name, so we need this before we can work on them.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return column name, or "" if not applicable
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getTableName(int column) throws SQLException
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* What's a column's table's catalog name? As with getSchemaName(),
|
||||
* we can say that if getTableName() returns n/a, then we can too -
|
||||
* otherwise, we need to work on it.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return catalog name, or "" if not applicable
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getCatalogName(int column) throws SQLException
|
||||
{
|
||||
String table_name = getTableName(column);
|
||||
|
||||
if (table_name.equals(""))
|
||||
return "";
|
||||
return ""; // As with getSchemaName(), this
|
||||
// is just the start of it.
|
||||
}
|
||||
|
||||
/**
|
||||
* What is a column's SQL Type? (java.sql.Type int)
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the java.sql.Type value
|
||||
* @exception SQLException if a database access error occurs
|
||||
* @see postgresql.Field#getSQLType
|
||||
* @see java.sql.Types
|
||||
*/
|
||||
public int getColumnType(int column) throws SQLException
|
||||
{
|
||||
return getField(column).getSQLType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whats is the column's data source specific type name?
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the type name
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getColumnTypeName(int column) throws SQLException
|
||||
{
|
||||
return getField(column).getTypeName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the column definitely not writable? In reality, we would
|
||||
* have to check the GRANT/REVOKE stuff for this to be effective,
|
||||
* and I haven't really looked into that yet, so this will get
|
||||
* re-visited.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isReadOnly(int column) throws SQLException
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it possible for a write on the column to succeed? Again, we
|
||||
* would in reality have to check the GRANT/REVOKE stuff, which
|
||||
* I haven't worked with as yet. However, if it isn't ReadOnly, then
|
||||
* it is obviously writable.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isWritable(int column) throws SQLException
|
||||
{
|
||||
if (isReadOnly(column))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will a write on this column definately succeed? Hmmm...this
|
||||
* is a bad one, since the two preceding functions have not been
|
||||
* really defined. I cannot tell is the short answer. I thus
|
||||
* return isWritable() just to give us an idea.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc..
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isDefinitelyWritable(int column) throws SQLException
|
||||
{
|
||||
return isWritable(column);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
// END OF PUBLIC INTERFACE
|
||||
// ********************************************************
|
||||
|
||||
/**
|
||||
* For several routines in this package, we need to convert
|
||||
* a columnIndex into a Field[] descriptor. Rather than do
|
||||
* the same code several times, here it is.
|
||||
*
|
||||
* @param columnIndex the first column is 1, the second is 2...
|
||||
* @return the Field description
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
private Field getField(int columnIndex) throws SQLException
|
||||
{
|
||||
if (columnIndex < 1 || columnIndex > fields.length)
|
||||
throw new SQLException("Column index out of range");
|
||||
return fields[columnIndex - 1];
|
||||
}
|
||||
Vector rows;
|
||||
Field[] fields;
|
||||
|
||||
/**
|
||||
* Initialise for a result with a tuple set and
|
||||
* a field descriptor set
|
||||
*
|
||||
* @param rows the Vector of rows returned by the ResultSet
|
||||
* @param fields the array of field descriptors
|
||||
*/
|
||||
public ResultSetMetaData(Vector rows, Field[] fields)
|
||||
{
|
||||
this.rows = rows;
|
||||
this.fields = fields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whats the number of columns in the ResultSet?
|
||||
*
|
||||
* @return the number
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getColumnCount() throws SQLException
|
||||
{
|
||||
return fields.length;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the column automatically numbered (and thus read-only)
|
||||
* I believe that PostgreSQL does not support this feature.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isAutoIncrement(int column) throws SQLException
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Does a column's case matter? ASSUMPTION: Any field that is
|
||||
* not obviously case insensitive is assumed to be case sensitive
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isCaseSensitive(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.SMALLINT:
|
||||
case Types.INTEGER:
|
||||
case Types.FLOAT:
|
||||
case Types.REAL:
|
||||
case Types.DOUBLE:
|
||||
case Types.DATE:
|
||||
case Types.TIME:
|
||||
case Types.TIMESTAMP:
|
||||
return false;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Can the column be used in a WHERE clause? Basically for
|
||||
* this, I split the functions into two types: recognised
|
||||
* types (which are always useable), and OTHER types (which
|
||||
* may or may not be useable). The OTHER types, for now, I
|
||||
* will assume they are useable. We should really query the
|
||||
* catalog to see if they are useable.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if they can be used in a WHERE clause
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isSearchable(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
// This switch is pointless, I know - but it is a set-up
|
||||
// for further expansion.
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.OTHER:
|
||||
return true;
|
||||
default:
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the column a cash value? 6.1 introduced the cash/money
|
||||
* type, which haven't been incorporated as of 970414, so I
|
||||
* just check the type name for both 'cash' and 'money'
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if its a cash column
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isCurrency(int column) throws SQLException
|
||||
{
|
||||
String type_name = getField(column).getTypeName();
|
||||
|
||||
if (type_name.equals("cash"))
|
||||
return true;
|
||||
if (type_name.equals("money"))
|
||||
return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can you put a NULL in this column? I think this is always
|
||||
* true in 6.1's case. It would only be false if the field had
|
||||
* been defined NOT NULL (system catalogs could be queried?)
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return one of the columnNullable values
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int isNullable(int column) throws SQLException
|
||||
{
|
||||
return columnNullable; // We can always put NULL in
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the column a signed number? In PostgreSQL, all numbers
|
||||
* are signed, so this is trivial. However, strings are not
|
||||
* signed (duh!)
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isSigned(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.SMALLINT:
|
||||
case Types.INTEGER:
|
||||
case Types.FLOAT:
|
||||
case Types.REAL:
|
||||
case Types.DOUBLE:
|
||||
return true;
|
||||
case Types.DATE:
|
||||
case Types.TIME:
|
||||
case Types.TIMESTAMP:
|
||||
return false; // I don't know about these?
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the column's normal maximum width in characters?
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the maximum width
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getColumnDisplaySize(int column) throws SQLException
|
||||
{
|
||||
int max = getColumnLabel(column).length();
|
||||
int i;
|
||||
|
||||
for (i = 0 ; i < rows.size(); ++i)
|
||||
{
|
||||
byte[][] x = (byte[][])(rows.elementAt(i));
|
||||
int xl = x[column - 1].length;
|
||||
if (xl > max)
|
||||
max = xl;
|
||||
}
|
||||
return max;
|
||||
}
|
||||
|
||||
/**
|
||||
* What is the suggested column title for use in printouts and
|
||||
* displays? We suggest the ColumnName!
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the column label
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getColumnLabel(int column) throws SQLException
|
||||
{
|
||||
return getColumnName(column);
|
||||
}
|
||||
|
||||
/**
|
||||
* What's a column's name?
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the column name
|
||||
* @exception SQLException if a databvase access error occurs
|
||||
*/
|
||||
public String getColumnName(int column) throws SQLException
|
||||
{
|
||||
return getField(column).name;
|
||||
}
|
||||
|
||||
/**
|
||||
* What is a column's table's schema? This relies on us knowing
|
||||
* the table name....which I don't know how to do as yet. The
|
||||
* JDBC specification allows us to return "" if this is not
|
||||
* applicable.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return the Schema
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getSchemaName(int column) throws SQLException
|
||||
{
|
||||
String table_name = getTableName(column);
|
||||
|
||||
// If the table name is invalid, so are we.
|
||||
if (table_name.equals(""))
|
||||
return "";
|
||||
return ""; // Ok, so I don't know how to
|
||||
// do this as yet.
|
||||
}
|
||||
|
||||
/**
|
||||
* What is a column's number of decimal digits.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return the precision
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getPrecision(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.SMALLINT:
|
||||
return 5;
|
||||
case Types.INTEGER:
|
||||
return 10;
|
||||
case Types.REAL:
|
||||
return 8;
|
||||
case Types.FLOAT:
|
||||
return 16;
|
||||
case Types.DOUBLE:
|
||||
return 16;
|
||||
default:
|
||||
throw new SQLException("no precision for non-numeric data types.");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* What is a column's number of digits to the right of the
|
||||
* decimal point?
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return the scale
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public int getScale(int column) throws SQLException
|
||||
{
|
||||
int sql_type = getField(column).getSQLType();
|
||||
|
||||
switch (sql_type)
|
||||
{
|
||||
case Types.SMALLINT:
|
||||
return 0;
|
||||
case Types.INTEGER:
|
||||
return 0;
|
||||
case Types.REAL:
|
||||
return 8;
|
||||
case Types.FLOAT:
|
||||
return 16;
|
||||
case Types.DOUBLE:
|
||||
return 16;
|
||||
default:
|
||||
throw new SQLException("no scale for non-numeric data types");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Whats a column's table's name? How do I find this out? Both
|
||||
* getSchemaName() and getCatalogName() rely on knowing the table
|
||||
* Name, so we need this before we can work on them.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return column name, or "" if not applicable
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getTableName(int column) throws SQLException
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
/**
|
||||
* What's a column's table's catalog name? As with getSchemaName(),
|
||||
* we can say that if getTableName() returns n/a, then we can too -
|
||||
* otherwise, we need to work on it.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2...
|
||||
* @return catalog name, or "" if not applicable
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getCatalogName(int column) throws SQLException
|
||||
{
|
||||
String table_name = getTableName(column);
|
||||
|
||||
if (table_name.equals(""))
|
||||
return "";
|
||||
return ""; // As with getSchemaName(), this
|
||||
// is just the start of it.
|
||||
}
|
||||
|
||||
/**
|
||||
* What is a column's SQL Type? (java.sql.Type int)
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the java.sql.Type value
|
||||
* @exception SQLException if a database access error occurs
|
||||
* @see postgresql.Field#getSQLType
|
||||
* @see java.sql.Types
|
||||
*/
|
||||
public int getColumnType(int column) throws SQLException
|
||||
{
|
||||
return getField(column).getSQLType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Whats is the column's data source specific type name?
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return the type name
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public String getColumnTypeName(int column) throws SQLException
|
||||
{
|
||||
return getField(column).getTypeName();
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the column definitely not writable? In reality, we would
|
||||
* have to check the GRANT/REVOKE stuff for this to be effective,
|
||||
* and I haven't really looked into that yet, so this will get
|
||||
* re-visited.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isReadOnly(int column) throws SQLException
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is it possible for a write on the column to succeed? Again, we
|
||||
* would in reality have to check the GRANT/REVOKE stuff, which
|
||||
* I haven't worked with as yet. However, if it isn't ReadOnly, then
|
||||
* it is obviously writable.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc.
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isWritable(int column) throws SQLException
|
||||
{
|
||||
if (isReadOnly(column))
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Will a write on this column definately succeed? Hmmm...this
|
||||
* is a bad one, since the two preceding functions have not been
|
||||
* really defined. I cannot tell is the short answer. I thus
|
||||
* return isWritable() just to give us an idea.
|
||||
*
|
||||
* @param column the first column is 1, the second is 2, etc..
|
||||
* @return true if so
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
public boolean isDefinitelyWritable(int column) throws SQLException
|
||||
{
|
||||
return isWritable(column);
|
||||
}
|
||||
|
||||
// ********************************************************
|
||||
// END OF PUBLIC INTERFACE
|
||||
// ********************************************************
|
||||
|
||||
/**
|
||||
* For several routines in this package, we need to convert
|
||||
* a columnIndex into a Field[] descriptor. Rather than do
|
||||
* the same code several times, here it is.
|
||||
*
|
||||
* @param columnIndex the first column is 1, the second is 2...
|
||||
* @return the Field description
|
||||
* @exception SQLException if a database access error occurs
|
||||
*/
|
||||
private Field getField(int columnIndex) throws SQLException
|
||||
{
|
||||
if (columnIndex < 1 || columnIndex > fields.length)
|
||||
throw new SQLException("Column index out of range");
|
||||
return fields[columnIndex - 1];
|
||||
}
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user