Commit 6a061da2 authored by Marc G. Fournier's avatar Marc G. Fournier

Update patch from Peter <patches@maidast.demon.co.uk>

parent 0b6dc93b
package postgresql; package postgresql;
import java.math.*;
import java.sql.*; import java.sql.*;
import java.math.*;
/** /**
* @version 1.0 15-APR-1997 * JDBC Interface to Postgres95 functions
* @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
*/ */
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 CallableStatement(Connection c,String q) throws SQLException
{ {
// XXX-Not Implemented super(c,q);
} }
public void registerOutParameter (int parameterIndex, int sqlType, int scale) throws SQLException // Before executing a stored procedure call you must explicitly
{ // call registerOutParameter to register the java.sql.Type of each
// XXX-Not Implemented // out parameter.
public void registerOutParameter(int parameterIndex, int sqlType) throws SQLException {
} }
public boolean wasNull () throws SQLException // You must also specify the scale for numeric/decimal types:
public void registerOutParameter(int parameterIndex, int sqlType,
int scale) throws SQLException
{ {
// XXX-Not Implemented
} }
public String getString (int parameterIndex) throws SQLException public boolean isNull(int parameterIndex) throws SQLException {
{ return true;
// XXX-Not Implemented
} }
public boolean getBoolean (int parameterIndex) throws SQLException // New API (JPM)
{ public boolean wasNull() throws SQLException {
// XXX-Not Implemented // check to see if the last access threw an exception
return false; // fake it for now
} }
public byte getByte (int parameterIndex) throws SQLException // Methods for retrieving OUT parameters from this statement.
{ public String getChar(int parameterIndex) throws SQLException {
// XXX-Not Implemented return null;
} }
public short getShort (int parameterIndex) throws SQLException // New API (JPM)
{ public String getString(int parameterIndex) throws SQLException {
// XXX-Not Implemented return null;
} }
//public String getVarChar(int parameterIndex) throws SQLException {
// return null;
//}
public int getInt (int parameterIndex) throws SQLException public String getLongVarChar(int parameterIndex) throws SQLException {
{ return null;
// XXX-Not Implemented
} }
public long getLong (int parameterIndex) throws SQLException // New API (JPM) (getBit)
{ public boolean getBoolean(int parameterIndex) throws SQLException {
// XXX-Not Implemented return false;
} }
public float getFloat (int parameterIndex) throws SQLException // New API (JPM) (getTinyInt)
{ public byte getByte(int parameterIndex) throws SQLException {
// XXX-Not Implemented return 0;
} }
public double getDouble (int parameterIndex) throws SQLException // New API (JPM) (getSmallInt)
{ public short getShort(int parameterIndex) throws SQLException {
// XXX-Not Implemented return 0;
} }
public BigDecimal getBigDecimal (int parameterIndex, int scale) throws SQLException // New API (JPM) (getInteger)
{ public int getInt(int parameterIndex) throws SQLException {
// XXX-Not Implemented return 0;
} }
public byte[] getBytes (int parameterIndex) throws SQLException // New API (JPM) (getBigInt)
{ public long getLong(int parameterIndex) throws SQLException {
// XXX-Not Implemented return 0;
} }
public Date getDate (int parameterIndex) throws SQLException public float getFloat(int parameterIndex) throws SQLException {
{ return (float) 0.0;
// XXX-Not Implemented
} }
public Time getTime (int parameterIndex) throws SQLException public double getDouble(int parameterIndex) throws SQLException {
{ return 0.0;
// XXX-Not Implemented
} }
public Timestamp getTimestamp (int parameterIndex) throws SQLException public BigDecimal getBigDecimal(int parameterIndex, int scale)
{ throws SQLException {
// XXX-Not Implemented return null;
} }
public Object getObject (int parameterIndex) throws SQLException // New API (JPM) (getBinary)
{ public byte[] getBytes(int parameterIndex) throws SQLException {
// XXX-Not Implemented 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;
}
} }
...@@ -45,7 +45,7 @@ public class Connection implements java.sql.Connection ...@@ -45,7 +45,7 @@ public class Connection implements java.sql.Connection
private boolean autoCommit = true; private boolean autoCommit = true;
private boolean readOnly = false; private boolean readOnly = false;
private Driver this_driver; protected Driver this_driver;
private String this_url; private String this_url;
private String cursor = null; // The positioned update cursor name private String cursor = null; // The positioned update cursor name
...@@ -153,7 +153,7 @@ public class Connection implements java.sql.Connection ...@@ -153,7 +153,7 @@ public class Connection implements java.sql.Connection
public java.sql.CallableStatement prepareCall(String sql) throws SQLException public java.sql.CallableStatement prepareCall(String sql) throws SQLException
{ {
throw new SQLException("Callable Statements are not supported at this time"); throw new SQLException("Callable Statements are not supported at this time");
// return new CallableStatement(this, sql); // return new CallableStatement(this, sql);
} }
/** /**
...@@ -295,8 +295,7 @@ public class Connection implements java.sql.Connection ...@@ -295,8 +295,7 @@ public class Connection implements java.sql.Connection
*/ */
public java.sql.DatabaseMetaData getMetaData() throws SQLException public java.sql.DatabaseMetaData getMetaData() throws SQLException
{ {
// return new DatabaseMetaData(this); return new DatabaseMetaData(this);
throw new SQLException("DatabaseMetaData not supported");
} }
/** /**
......
...@@ -2,12 +2,8 @@ package postgresql; ...@@ -2,12 +2,8 @@ package postgresql;
import java.sql.*; import java.sql.*;
import java.util.*; 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 * The Java SQL framework allows for multiple database drivers. Each
* driver should supply a class that implements the Driver interface * driver should supply a class that implements the Driver interface
* *
...@@ -28,12 +24,19 @@ import postgresql.*; ...@@ -28,12 +24,19 @@ import postgresql.*;
*/ */
public class Driver implements java.sql.Driver public class Driver implements java.sql.Driver
{ {
// 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 static
{ {
try try {
{ // moved the registerDriver from the constructor to here
new Driver(); // 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) { } catch (SQLException e) {
e.printStackTrace(); e.printStackTrace();
} }
...@@ -46,7 +49,6 @@ public class Driver implements java.sql.Driver ...@@ -46,7 +49,6 @@ public class Driver implements java.sql.Driver
*/ */
public Driver() throws SQLException public Driver() throws SQLException
{ {
java.sql.DriverManager.registerDriver(this);
} }
/** /**
...@@ -79,19 +81,10 @@ public class Driver implements java.sql.Driver ...@@ -79,19 +81,10 @@ public class Driver implements java.sql.Driver
*/ */
public java.sql.Connection connect(String url, Properties info) throws SQLException public java.sql.Connection connect(String url, Properties info) throws SQLException
{ {
DriverURL dr = new DriverURL(url); if((props = parseURL(url,info))==null)
int port;
if (!(dr.protocol().equals("jdbc")))
return null; return null;
if (!(dr.subprotocol().equals("postgresql")))
return null; return new Connection (host(), port(), props, database(), url, this);
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);
} }
/** /**
...@@ -108,12 +101,9 @@ public class Driver implements java.sql.Driver ...@@ -108,12 +101,9 @@ public class Driver implements java.sql.Driver
*/ */
public boolean acceptsURL(String url) throws SQLException public boolean acceptsURL(String url) throws SQLException
{ {
DriverURL dr = new DriverURL(url); if(parseURL(url,null)==null)
if (dr.protocol().equals("jdbc"))
if (dr.subprotocol().equals("postgresql"))
return true;
return false; return false;
return true;
} }
/** /**
...@@ -146,7 +136,7 @@ public class Driver implements java.sql.Driver ...@@ -146,7 +136,7 @@ public class Driver implements java.sql.Driver
*/ */
public int getMajorVersion() public int getMajorVersion()
{ {
return 1; return MAJORVERSION;
} }
/** /**
...@@ -156,7 +146,7 @@ public class Driver implements java.sql.Driver ...@@ -156,7 +146,7 @@ public class Driver implements java.sql.Driver
*/ */
public int getMinorVersion() public int getMinorVersion()
{ {
return 0; return MINORVERSION;
} }
/** /**
...@@ -170,76 +160,105 @@ public class Driver implements java.sql.Driver ...@@ -170,76 +160,105 @@ public class Driver implements java.sql.Driver
{ {
return false; return false;
} }
}
/** private Properties props;
* The DriverURL class splits a JDBC URL into its subcomponents
* static private String[] protocols = { "jdbc","postgresql" };
* 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 * Constructs a new DriverURL, splitting the specified URL into its
* component parts * component parts
*/ */
public DriverURL(String url) throws SQLException Properties parseURL(String url,Properties defaults) throws SQLException
{ {
int a, b, c; int state = -1;
String tmp, hostport, dbportion; Properties urlProps = new Properties(defaults);
String key = new String();
String value = new String();
a = url.indexOf(':'); StringTokenizer st = new StringTokenizer(url, ":/;=&?", true);
if (a == -1) for (int count = 0; (st.hasMoreTokens()); count++) {
throw new SQLException("Bad URL Protocol specifier"); String token = st.nextToken();
b = url.indexOf(':', a+1);
if (b == -1) // PM June 29 1997
throw new SQLException("Bad URL Subprotocol specifier"); // Added this, to help me understand how this works.
protocol = new String(url.substring(0, a)); // Unless you want each token to be processed, leave this commented out
subprotocol = new String(url.substring(a+1, b)); // but don't delete it.
tmp = new String(url.substring(b+1, url.length())); //DriverManager.println("wellFormedURL: state="+state+" count="+count+" token='"+token+"'");
if (tmp.length() < 2)
throw new SQLException("Bad URL Database specifier"); // PM Aug 2 1997 - Modified to allow multiple backends
if (!tmp.substring(0, 2).equals("//")) if (count <= 3) {
{ if ((count % 2) == 1 && token.equals(":"))
host = new String("unknown"); ;
port = -1; else if((count % 2) == 0) {
database = new String(tmp.substring(1, tmp.length())); boolean found=(count==0)?true:false;
return; 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;
} }
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()));
} }
} }
/** if(found == false)
* Returns the protocol name of the DriverURL return null;
*/ } else return null;
public String protocol() }
{ else if (count > 3) {
return protocol; if (count == 4 && token.equals("/")) state = 0;
else if (count == 4) {
urlProps.put("PGDBNAME", token);
state = -2;
}
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;
}
}
else if ((count == 7 || count == 9) &&
(state == 1 || state == 2) && token.equals("/"))
state = -1;
else if (state == -1) {
urlProps.put("PGDBNAME", token);
state = -2;
}
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;
}
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
* Returns the subprotocol name of the DriverURL // This now outputs the properties only if we are logging
*/ if(DriverManager.getLogStream() != null)
public String subprotocol() urlProps.list(DriverManager.getLogStream());
{
return subprotocol; return urlProps;
} }
/** /**
...@@ -247,7 +266,7 @@ class DriverURL ...@@ -247,7 +266,7 @@ class DriverURL
*/ */
public String host() public String host()
{ {
return host; return props.getProperty("PGHOST","localhost");
} }
/** /**
...@@ -256,7 +275,7 @@ class DriverURL ...@@ -256,7 +275,7 @@ class DriverURL
*/ */
public int port() public int port()
{ {
return port; return Integer.parseInt(props.getProperty("PGPORT","5432"));
} }
/** /**
...@@ -264,6 +283,15 @@ class DriverURL ...@@ -264,6 +283,15 @@ class DriverURL
*/ */
public String database() public String database()
{ {
return database; return props.getProperty("PGDBNAME");
}
/**
* Returns any property
*/
public String property(String name)
{
return props.getProperty(name);
} }
} }
...@@ -54,20 +54,34 @@ public class Field ...@@ -54,20 +54,34 @@ public class Field
throw new SQLException("Unexpected return from query for type"); throw new SQLException("Unexpected return from query for type");
result.next(); result.next();
type_name = result.getString(1); type_name = result.getString(1);
if (type_name.equals("int2")) sql_type = Types.SMALLINT; if (type_name.equals("int2"))
else if (type_name.equals("int4")) sql_type = Types.INTEGER; sql_type = Types.SMALLINT;
else if (type_name.equals("int8")) sql_type = Types.BIGINT; else if (type_name.equals("int4"))
else if (type_name.equals("cash")) sql_type = Types.DECIMAL; sql_type = Types.INTEGER;
else if (type_name.equals("money")) sql_type = Types.DECIMAL; else if (type_name.equals("int8"))
else if (type_name.equals("float4")) sql_type = Types.REAL; sql_type = Types.BIGINT;
else if (type_name.equals("float8")) sql_type = Types.DOUBLE; else if (type_name.equals("cash"))
else if (type_name.equals("bpchar")) sql_type = Types.CHAR; sql_type = Types.DECIMAL;
else if (type_name.equals("varchar")) sql_type = Types.VARCHAR; else if (type_name.equals("money"))
else if (type_name.equals("bool")) sql_type = Types.BIT; sql_type = Types.DECIMAL;
else if (type_name.equals("date")) sql_type = Types.DATE; else if (type_name.equals("float4"))
else if (type_name.equals("time")) sql_type = Types.TIME; sql_type = Types.REAL;
else if (type_name.equals("abstime")) sql_type = Types.TIMESTAMP; else if (type_name.equals("float8"))
else sql_type = Types.OTHER; 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; return sql_type;
} }
......
...@@ -23,9 +23,123 @@ public class PG_Object ...@@ -23,9 +23,123 @@ public class PG_Object
* @param type a string describing the type of the object * @param type a string describing the type of the object
* @param value a string representation of the value of the object * @param value a string representation of the value of the object
*/ */
public PG_Object(String type, String value) public PG_Object(String type, String value) throws SQLException
{ {
this.type = type; this.type = type;
this.value = value; 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;
}
} }
...@@ -9,9 +9,6 @@ import java.sql.*; ...@@ -9,9 +9,6 @@ import java.sql.*;
import postgresql.*; import postgresql.*;
/** /**
* @version 1.0 15-APR-1997
* @author <A HREF="mailto:adrian@hottub.org">Adrian Hall</A>
*
* A ResultSet provides access to a table of data generated by executing a * A ResultSet provides access to a table of data generated by executing a
* Statement. The table rows are retrieved in sequence. Within a row its * Statement. The table rows are retrieved in sequence. Within a row its
* column values can be accessed in any order. * column values can be accessed in any order.
...@@ -843,3 +840,4 @@ public class ResultSet implements java.sql.ResultSet ...@@ -843,3 +840,4 @@ public class ResultSet implements java.sql.ResultSet
return fields.length; return fields.length;
} }
} }
...@@ -427,3 +427,4 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData ...@@ -427,3 +427,4 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData
return fields[columnIndex - 1]; return fields[columnIndex - 1];
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment