mirror of
https://github.com/postgres/postgres.git
synced 2025-07-28 23:42:10 +03:00
New stuff from Peter Mount for jdbc.
This commit is contained in:
@ -123,7 +123,7 @@ public class psql
|
|||||||
if(rs.wasNull())
|
if(rs.wasNull())
|
||||||
System.out.print("{null}"+(i<cols?"\t":"\n"));
|
System.out.print("{null}"+(i<cols?"\t":"\n"));
|
||||||
else
|
else
|
||||||
System.out.print(rs.getObject(i).toString()+(i<cols?"\t":"\n"));
|
System.out.print(o.toString()+(i<cols?"\t":"\n"));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -34,6 +34,9 @@ public class Connection implements java.sql.Connection
|
|||||||
// This is set by postgresql.Statement.setMaxRows()
|
// This is set by postgresql.Statement.setMaxRows()
|
||||||
protected int maxrows = 0; // maximum no. of rows; 0 = unlimited
|
protected int maxrows = 0; // maximum no. of rows; 0 = unlimited
|
||||||
|
|
||||||
|
// This is a cache of the DatabaseMetaData instance for this connection
|
||||||
|
protected DatabaseMetaData metadata;
|
||||||
|
|
||||||
private String PG_HOST;
|
private String PG_HOST;
|
||||||
private int PG_PORT;
|
private int PG_PORT;
|
||||||
private String PG_USER;
|
private String PG_USER;
|
||||||
@ -44,17 +47,6 @@ public class Connection implements java.sql.Connection
|
|||||||
public boolean CONNECTION_OK = true;
|
public boolean CONNECTION_OK = true;
|
||||||
public boolean CONNECTION_BAD = false;
|
public boolean CONNECTION_BAD = false;
|
||||||
|
|
||||||
//private static final int STARTUP_LEN = 288; // Length of a startup packet
|
|
||||||
|
|
||||||
// These are defined in src/include/libpq/pqcomm.h
|
|
||||||
//private int STARTUP_CODE = STARTUP_USER;
|
|
||||||
//private static final int STARTUP_USER = 7; // User auth
|
|
||||||
//private static final int STARTUP_KRB4 = 10; // Kerberos 4 (unused)
|
|
||||||
//private static final int STARTUP_KRB5 = 11; // Kerberos 5 (unused)
|
|
||||||
//private static final int STARTUP_HBA = 12; // Host Based
|
|
||||||
//private static final int STARTUP_NONE = 13; // Unauthenticated (unused)
|
|
||||||
//private static final int STARTUP_PASS = 14; // Password auth
|
|
||||||
|
|
||||||
private boolean autoCommit = true;
|
private boolean autoCommit = true;
|
||||||
private boolean readOnly = false;
|
private boolean readOnly = false;
|
||||||
|
|
||||||
@ -88,12 +80,6 @@ public class Connection implements java.sql.Connection
|
|||||||
// be across all connections, which could be to different backends.
|
// be across all connections, which could be to different backends.
|
||||||
protected Hashtable fieldCache = new Hashtable();
|
protected Hashtable fieldCache = new Hashtable();
|
||||||
|
|
||||||
// This is used by Field to cache oid -> names.
|
|
||||||
// It's here, because it's shared across this connection only.
|
|
||||||
// Hence it cannot be static within the Field class, because it would then
|
|
||||||
// be across all connections, which could be to different backends.
|
|
||||||
protected Hashtable fieldCache = new Hashtable();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the current date style of the backend
|
* This is the current date style of the backend
|
||||||
*/
|
*/
|
||||||
@ -150,8 +136,6 @@ public class Connection implements java.sql.Connection
|
|||||||
*/
|
*/
|
||||||
public Connection(String host, int port, Properties info, String database, String url, Driver d) throws SQLException
|
public Connection(String host, int port, Properties info, String database, String url, Driver d) throws SQLException
|
||||||
{
|
{
|
||||||
//int len = STARTUP_LEN; // Length of a startup packet
|
|
||||||
|
|
||||||
// Throw an exception if the user or password properties are missing
|
// Throw an exception if the user or password properties are missing
|
||||||
// This occasionally occurs when the client uses the properties version
|
// This occasionally occurs when the client uses the properties version
|
||||||
// of getConnection(), and is a common question on the email lists
|
// of getConnection(), and is a common question on the email lists
|
||||||
@ -169,30 +153,15 @@ public class Connection implements java.sql.Connection
|
|||||||
PG_HOST = new String(host);
|
PG_HOST = new String(host);
|
||||||
PG_STATUS = CONNECTION_BAD;
|
PG_STATUS = CONNECTION_BAD;
|
||||||
|
|
||||||
// Pre 6.3 code
|
|
||||||
// This handles the auth property. Any value begining with p enables
|
|
||||||
// password authentication, while anything begining with i enables
|
|
||||||
// ident (RFC 1413) authentication. Any other values default to trust.
|
|
||||||
//
|
|
||||||
// Also, the postgresql.auth system property can be used to change the
|
|
||||||
// local default, if the auth property is not present.
|
|
||||||
//
|
|
||||||
//String auth = info.getProperty("auth",System.getProperty("postgresql.auth","trust")).toLowerCase();
|
|
||||||
//if(auth.startsWith("p")) {
|
|
||||||
//// Password authentication
|
|
||||||
//STARTUP_CODE=STARTUP_PASS;
|
|
||||||
//} else if(auth.startsWith("i")) {
|
|
||||||
//// Ident (RFC 1413) authentication
|
|
||||||
//STARTUP_CODE=STARTUP_HBA;
|
|
||||||
//} else {
|
|
||||||
//// Anything else defaults to trust authentication
|
|
||||||
//STARTUP_CODE=STARTUP_USER;
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Now make the initial connection
|
// Now make the initial connection
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
pg_stream = new PG_Stream(host, port);
|
pg_stream = new PG_Stream(host, port);
|
||||||
|
} catch (ConnectException cex) {
|
||||||
|
// Added by Peter Mount <peter@retep.org.uk>
|
||||||
|
// ConnectException is thrown when the connection cannot be made.
|
||||||
|
// we trap this an return a more meaningful message for the end user
|
||||||
|
throw new SQLException ("Connection refused. Check that the hostname and port is correct, and that the postmaster is running with the -i flag, which enables TCP/IP networking.");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SQLException ("Connection failed: " + e.toString());
|
throw new SQLException ("Connection failed: " + e.toString());
|
||||||
}
|
}
|
||||||
@ -200,30 +169,17 @@ public class Connection implements java.sql.Connection
|
|||||||
// Now we need to construct and send a startup packet
|
// Now we need to construct and send a startup packet
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Pre 6.3 code
|
|
||||||
//pg_stream.SendInteger(len, 4); len -= 4;
|
|
||||||
//pg_stream.SendInteger(STARTUP_CODE, 4); len -= 4;
|
|
||||||
//pg_stream.Send(database.getBytes(), 64); len -= 64;
|
|
||||||
//pg_stream.Send(PG_USER.getBytes(), len);
|
|
||||||
//
|
|
||||||
//// Send the password packet if required
|
|
||||||
//if(STARTUP_CODE == STARTUP_PASS) {
|
|
||||||
//len=STARTUP_LEN;
|
|
||||||
//pg_stream.SendInteger(len, 4); len -= 4;
|
|
||||||
//pg_stream.SendInteger(STARTUP_PASS, 4); len -= 4;
|
|
||||||
//pg_stream.Send(PG_USER.getBytes(), PG_USER.length());
|
|
||||||
//len-=PG_USER.length();
|
|
||||||
//pg_stream.SendInteger(0,1); len -= 1;
|
|
||||||
//pg_stream.Send(PG_PASSWORD.getBytes(), len);
|
|
||||||
//}
|
|
||||||
|
|
||||||
// Ver 6.3 code
|
// Ver 6.3 code
|
||||||
pg_stream.SendInteger(4+4+SM_DATABASE+SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY,4);
|
pg_stream.SendInteger(4+4+SM_DATABASE+SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY,4);
|
||||||
pg_stream.SendInteger(PG_PROTOCOL_LATEST_MAJOR,2);
|
pg_stream.SendInteger(PG_PROTOCOL_LATEST_MAJOR,2);
|
||||||
pg_stream.SendInteger(PG_PROTOCOL_LATEST_MINOR,2);
|
pg_stream.SendInteger(PG_PROTOCOL_LATEST_MINOR,2);
|
||||||
pg_stream.Send(database.getBytes(),SM_DATABASE);
|
pg_stream.Send(database.getBytes(),SM_DATABASE);
|
||||||
|
|
||||||
|
// This last send includes the unused fields
|
||||||
pg_stream.Send(PG_USER.getBytes(),SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY);
|
pg_stream.Send(PG_USER.getBytes(),SM_USER+SM_OPTIONS+SM_UNUSED+SM_TTY);
|
||||||
// The last send includes the unused fields
|
|
||||||
|
// now flush the startup packets to the backend
|
||||||
|
pg_stream.flush();
|
||||||
|
|
||||||
// Now get the response from the backend, either an error message
|
// Now get the response from the backend, either an error message
|
||||||
// or an authentication request
|
// or an authentication request
|
||||||
@ -233,6 +189,12 @@ public class Connection implements java.sql.Connection
|
|||||||
switch(beresp)
|
switch(beresp)
|
||||||
{
|
{
|
||||||
case 'E':
|
case 'E':
|
||||||
|
// An error occured, so pass the error message to the
|
||||||
|
// user.
|
||||||
|
//
|
||||||
|
// The most common one to be thrown here is:
|
||||||
|
// "User authentication failed"
|
||||||
|
//
|
||||||
throw new SQLException(pg_stream.ReceiveString(4096));
|
throw new SQLException(pg_stream.ReceiveString(4096));
|
||||||
|
|
||||||
case 'R':
|
case 'R':
|
||||||
@ -267,7 +229,7 @@ public class Connection implements java.sql.Connection
|
|||||||
pg_stream.SendInteger(5+PG_PASSWORD.length(),4);
|
pg_stream.SendInteger(5+PG_PASSWORD.length(),4);
|
||||||
pg_stream.Send(PG_PASSWORD.getBytes());
|
pg_stream.Send(PG_PASSWORD.getBytes());
|
||||||
pg_stream.SendInteger(0,1);
|
pg_stream.SendInteger(0,1);
|
||||||
//pg_stream.SendPacket(PG_PASSWORD.getBytes());
|
pg_stream.flush();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case AUTH_REQ_CRYPT:
|
case AUTH_REQ_CRYPT:
|
||||||
@ -276,11 +238,11 @@ public class Connection implements java.sql.Connection
|
|||||||
pg_stream.SendInteger(5+crypted.length(),4);
|
pg_stream.SendInteger(5+crypted.length(),4);
|
||||||
pg_stream.Send(crypted.getBytes());
|
pg_stream.Send(crypted.getBytes());
|
||||||
pg_stream.SendInteger(0,1);
|
pg_stream.SendInteger(0,1);
|
||||||
//pg_stream.SendPacket(UnixCrypt.crypt(salt,PG_PASSWORD).getBytes());
|
pg_stream.flush();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new SQLException("Authentication type "+areq+" not supported");
|
throw new SQLException("Authentication type "+areq+" not supported. Check that you have configured the pg_hba.conf file to include the client's IP address or Subnet, and is using a supported authentication scheme.");
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@ -511,7 +473,9 @@ 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);
|
if(metadata==null)
|
||||||
|
metadata = new DatabaseMetaData(this);
|
||||||
|
return metadata;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -631,8 +595,6 @@ public class Connection implements java.sql.Connection
|
|||||||
*/
|
*/
|
||||||
public void addWarning(String msg)
|
public void addWarning(String msg)
|
||||||
{
|
{
|
||||||
//PrintStream log = DriverManager.getLogStream();
|
|
||||||
//if(log!=null)
|
|
||||||
DriverManager.println(msg);
|
DriverManager.println(msg);
|
||||||
|
|
||||||
// Add the warning to the chain
|
// Add the warning to the chain
|
||||||
@ -691,6 +653,7 @@ public class Connection implements java.sql.Connection
|
|||||||
buf = sql.getBytes();
|
buf = sql.getBytes();
|
||||||
pg_stream.Send(buf);
|
pg_stream.Send(buf);
|
||||||
pg_stream.SendChar(0);
|
pg_stream.SendChar(0);
|
||||||
|
pg_stream.flush();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SQLException("I/O Error: " + e.toString());
|
throw new SQLException("I/O Error: " + e.toString());
|
||||||
}
|
}
|
||||||
@ -726,6 +689,7 @@ public class Connection implements java.sql.Connection
|
|||||||
pg_stream.SendChar('Q');
|
pg_stream.SendChar('Q');
|
||||||
pg_stream.SendChar(' ');
|
pg_stream.SendChar(' ');
|
||||||
pg_stream.SendChar(0);
|
pg_stream.SendChar(0);
|
||||||
|
pg_stream.flush();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SQLException("I/O Error: " + e.toString());
|
throw new SQLException("I/O Error: " + e.toString());
|
||||||
}
|
}
|
||||||
@ -964,6 +928,8 @@ public class Connection implements java.sql.Connection
|
|||||||
return ((Serialize)o).fetch(Integer.parseInt(value));
|
return ((Serialize)o).fetch(Integer.parseInt(value));
|
||||||
}
|
}
|
||||||
} catch(SQLException sx) {
|
} catch(SQLException sx) {
|
||||||
|
// rethrow the exception. Done because we capture any others next
|
||||||
|
sx.fillInStackTrace();
|
||||||
throw sx;
|
throw sx;
|
||||||
} catch(Exception ex) {
|
} catch(Exception ex) {
|
||||||
throw new SQLException("Failed to create object for "+type+": "+ex);
|
throw new SQLException("Failed to create object for "+type+": "+ex);
|
||||||
@ -999,14 +965,17 @@ public class Connection implements java.sql.Connection
|
|||||||
// If so, then call it's fetch method.
|
// If so, then call it's fetch method.
|
||||||
if(x instanceof Serialize)
|
if(x instanceof Serialize)
|
||||||
return ((Serialize)x).store(o);
|
return ((Serialize)x).store(o);
|
||||||
|
|
||||||
|
// Thow an exception because the type is unknown
|
||||||
|
throw new SQLException("The object could not be stored. Check that any tables required have already been created in the database.");
|
||||||
|
|
||||||
} catch(SQLException sx) {
|
} catch(SQLException sx) {
|
||||||
|
// rethrow the exception. Done because we capture any others next
|
||||||
|
sx.fillInStackTrace();
|
||||||
throw sx;
|
throw sx;
|
||||||
} catch(Exception ex) {
|
} catch(Exception ex) {
|
||||||
throw new SQLException("Failed to store object: "+ex);
|
throw new SQLException("Failed to store object: "+ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
// should never be reached
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1045,10 +1014,12 @@ public class Connection implements java.sql.Connection
|
|||||||
private static final String defaultObjectTypes[][] = {
|
private static final String defaultObjectTypes[][] = {
|
||||||
{"box", "postgresql.geometric.PGbox"},
|
{"box", "postgresql.geometric.PGbox"},
|
||||||
{"circle", "postgresql.geometric.PGcircle"},
|
{"circle", "postgresql.geometric.PGcircle"},
|
||||||
|
{"line", "postgresql.geometric.PGline"},
|
||||||
{"lseg", "postgresql.geometric.PGlseg"},
|
{"lseg", "postgresql.geometric.PGlseg"},
|
||||||
{"path", "postgresql.geometric.PGpath"},
|
{"path", "postgresql.geometric.PGpath"},
|
||||||
{"point", "postgresql.geometric.PGpoint"},
|
{"point", "postgresql.geometric.PGpoint"},
|
||||||
{"polygon", "postgresql.geometric.PGpolygon"}
|
{"polygon", "postgresql.geometric.PGpolygon"},
|
||||||
|
{"money", "postgresql.util.PGmoney"}
|
||||||
};
|
};
|
||||||
|
|
||||||
// This initialises the objectTypes hashtable
|
// This initialises the objectTypes hashtable
|
||||||
|
@ -37,6 +37,9 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
static final int iInt4Oid = 23; // OID for int4
|
static final int iInt4Oid = 23; // OID for int4
|
||||||
static final int VARHDRSZ = 4; // length for int4
|
static final int VARHDRSZ = 4; // length for int4
|
||||||
|
|
||||||
|
// This is a default value for remarks
|
||||||
|
private static final byte defaultRemarks[]="no remarks".getBytes();
|
||||||
|
|
||||||
public DatabaseMetaData(Connection conn)
|
public DatabaseMetaData(Connection conn)
|
||||||
{
|
{
|
||||||
this.connection = conn;
|
this.connection = conn;
|
||||||
@ -170,7 +173,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
*/
|
*/
|
||||||
public String getDatabaseProductVersion() throws SQLException
|
public String getDatabaseProductVersion() throws SQLException
|
||||||
{
|
{
|
||||||
return ("6.3");
|
return ("6.4");
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -1473,39 +1476,37 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
Field f[] = new Field[8];
|
Field f[] = new Field[8];
|
||||||
ResultSet r; // ResultSet for the SQL query that we need to do
|
ResultSet r; // ResultSet for the SQL query that we need to do
|
||||||
Vector v = new Vector(); // The new ResultSet tuple stuff
|
Vector v = new Vector(); // The new ResultSet tuple stuff
|
||||||
String remarks = new String("no remarks");
|
|
||||||
|
|
||||||
f[0] = new Field(connection, new String("PROCEDURE_CAT"), iVarcharOid, 32);
|
byte remarks[] = defaultRemarks;
|
||||||
f[1] = new Field(connection, new String("PROCEDURE_SCHEM"), iVarcharOid, 32);
|
|
||||||
f[2] = new Field(connection, new String("PROCEDURE_NAME"), iVarcharOid, 32);
|
f[0] = new Field(connection, "PROCEDURE_CAT", iVarcharOid, 32);
|
||||||
f[3] = null;
|
f[1] = new Field(connection, "PROCEDURE_SCHEM", iVarcharOid, 32);
|
||||||
f[4] = null;
|
f[2] = new Field(connection, "PROCEDURE_NAME", iVarcharOid, 32);
|
||||||
f[5] = null;
|
f[3] = f[4] = f[5] = null; // reserved, must be null for now
|
||||||
f[6] = new Field(connection, new String("REMARKS"), iVarcharOid, 8192);
|
f[6] = new Field(connection, "REMARKS", iVarcharOid, 8192);
|
||||||
f[7] = new Field(connection, new String("PROCEDURE_TYPE"), iInt2Oid, 2);
|
f[7] = new Field(connection, "PROCEDURE_TYPE", iInt2Oid, 2);
|
||||||
r = connection.ExecSQL("select proname, proretset from pg_proc order by proname");
|
|
||||||
if (r.getColumnCount() != 2 || r.getTupleCount() <= 1)
|
// If the pattern is null, then set it to the default
|
||||||
throw new SQLException("Unexpected return from query for procedure list");
|
if(procedureNamePattern==null)
|
||||||
|
procedureNamePattern="%";
|
||||||
|
|
||||||
|
r = connection.ExecSQL("select proname, proretset from pg_proc where proname like '"+procedureNamePattern.toLowerCase()+"' order by proname");
|
||||||
|
|
||||||
while (r.next())
|
while (r.next())
|
||||||
{
|
{
|
||||||
byte[][] tuple = new byte[8][0];
|
byte[][] tuple = new byte[8][0];
|
||||||
|
|
||||||
String name = r.getString(1);
|
|
||||||
remarks = new String("no remarks");
|
|
||||||
boolean retset = r.getBoolean(2);
|
|
||||||
|
|
||||||
tuple[0] = null; // Catalog name
|
tuple[0] = null; // Catalog name
|
||||||
tuple[1] = null; // Schema name
|
tuple[1] = null; // Schema name
|
||||||
tuple[2] = name.getBytes(); // Procedure name
|
tuple[2] = r.getBytes(1); // Procedure name
|
||||||
tuple[3] = null; // Reserved
|
tuple[3] = tuple[4] = tuple[5] = null; // Reserved
|
||||||
tuple[4] = null; // Reserved
|
tuple[6] = remarks; // Remarks
|
||||||
tuple[5] = null; // Reserved
|
|
||||||
tuple[6] = remarks.getBytes(); // Remarks
|
if (r.getBoolean(2))
|
||||||
tuple[7] = new byte[1];
|
tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureReturnsResult).getBytes();
|
||||||
if (retset)
|
|
||||||
tuple[7][0] = (byte)java.sql.DatabaseMetaData.procedureReturnsResult;
|
|
||||||
else
|
else
|
||||||
tuple[7][0] = (byte)java.sql.DatabaseMetaData.procedureNoResult;
|
tuple[7] = Integer.toString(java.sql.DatabaseMetaData.procedureNoResult).getBytes();
|
||||||
|
|
||||||
v.addElement(tuple);
|
v.addElement(tuple);
|
||||||
}
|
}
|
||||||
return new ResultSet(connection, f, v, "OK", 1);
|
return new ResultSet(connection, f, v, "OK", 1);
|
||||||
@ -1559,6 +1560,12 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
// Implementation note: This is required for Borland's JBuilder to work
|
// 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
|
public java.sql.ResultSet getProcedureColumns(String catalog, String schemaPattern, String procedureNamePattern, String columnNamePattern) throws SQLException
|
||||||
{
|
{
|
||||||
|
if(procedureNamePattern==null)
|
||||||
|
procedureNamePattern="%";
|
||||||
|
|
||||||
|
if(columnNamePattern==null)
|
||||||
|
columnNamePattern="%";
|
||||||
|
|
||||||
// for now, this returns an empty result set.
|
// for now, this returns an empty result set.
|
||||||
Field f[] = new Field[13];
|
Field f[] = new Field[13];
|
||||||
ResultSet r; // ResultSet for the SQL query that we need to do
|
ResultSet r; // ResultSet for the SQL query that we need to do
|
||||||
@ -1578,6 +1585,8 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
f[11] = new Field(connection, new String("NULLABLE"), iInt2Oid, 2);
|
f[11] = new Field(connection, new String("NULLABLE"), iInt2Oid, 2);
|
||||||
f[12] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
|
f[12] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
|
||||||
|
|
||||||
|
// add query loop here
|
||||||
|
|
||||||
return new ResultSet(connection, f, v, "OK", 1);
|
return new ResultSet(connection, f, v, "OK", 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1612,7 +1621,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
* @param types a list of table types to include; null returns
|
* @param types a list of table types to include; null returns
|
||||||
* all types
|
* all types
|
||||||
* @return each row is a table description
|
* @return each row is a table description
|
||||||
* @exception SQLException if a database-access error occurs.
|
* @exception SQLException if a database-access error occurs.
|
||||||
*/
|
*/
|
||||||
public java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException
|
public java.sql.ResultSet getTables(String catalog, String schemaPattern, String tableNamePattern, String types[]) throws SQLException
|
||||||
{
|
{
|
||||||
@ -1620,6 +1629,9 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
if(types==null)
|
if(types==null)
|
||||||
types = defaultTableTypes;
|
types = defaultTableTypes;
|
||||||
|
|
||||||
|
if(tableNamePattern==null)
|
||||||
|
tableNamePattern="%";
|
||||||
|
|
||||||
// the field descriptors for the new ResultSet
|
// the field descriptors for the new ResultSet
|
||||||
Field f[] = new Field[5];
|
Field f[] = new Field[5];
|
||||||
ResultSet r; // ResultSet for the SQL query that we need to do
|
ResultSet r; // ResultSet for the SQL query that we need to do
|
||||||
@ -1632,7 +1644,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
f[4] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
|
f[4] = new Field(connection, new String("REMARKS"), iVarcharOid, 32);
|
||||||
|
|
||||||
// Now form the query
|
// Now form the query
|
||||||
StringBuffer sql = new StringBuffer("select relname,oid from pg_class where ");
|
StringBuffer sql = new StringBuffer("select relname,oid from pg_class where (");
|
||||||
boolean notFirst=false;
|
boolean notFirst=false;
|
||||||
for(int i=0;i<types.length;i++) {
|
for(int i=0;i<types.length;i++) {
|
||||||
if(notFirst)
|
if(notFirst)
|
||||||
@ -1644,32 +1656,35 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Added by Stefan Andreasen <stefan@linux.kapow.dk>
|
||||||
|
// Now take the pattern into account
|
||||||
|
sql.append(") and relname like '");
|
||||||
|
sql.append(tableNamePattern.toLowerCase());
|
||||||
|
sql.append("'");
|
||||||
|
|
||||||
// Now run the query
|
// Now run the query
|
||||||
r = connection.ExecSQL(sql.toString());
|
r = connection.ExecSQL(sql.toString());
|
||||||
|
|
||||||
if (r.getColumnCount() != 2)
|
byte remarks[];
|
||||||
throw new SQLException("Unexpected return from query for table list");
|
|
||||||
|
|
||||||
while (r.next())
|
while (r.next())
|
||||||
{
|
{
|
||||||
byte[][] tuple = new byte[5][0];
|
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)
|
// Fetch the description for the table (if any)
|
||||||
ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(2));
|
ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(2));
|
||||||
if(dr.getTupleCount()==1) {
|
if(dr.getTupleCount()==1) {
|
||||||
dr.next();
|
dr.next();
|
||||||
remarks=dr.getString(1);
|
remarks = dr.getBytes(1);
|
||||||
}
|
} else
|
||||||
|
remarks = defaultRemarks;
|
||||||
dr.close();
|
dr.close();
|
||||||
|
|
||||||
tuple[0] = null; // Catalog name
|
tuple[0] = null; // Catalog name
|
||||||
tuple[1] = null; // Schema name
|
tuple[1] = null; // Schema name
|
||||||
tuple[2] = name.getBytes(); // Table name
|
tuple[2] = r.getBytes(1); // Table name
|
||||||
tuple[3] = null; // Table type
|
tuple[3] = null; // Table type
|
||||||
tuple[4] = remarks.getBytes(); // Remarks
|
tuple[4] = remarks; // Remarks
|
||||||
v.addElement(tuple);
|
v.addElement(tuple);
|
||||||
}
|
}
|
||||||
r.close();
|
r.close();
|
||||||
@ -1848,28 +1863,34 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
f[16] = new Field(connection, new String("ORDINAL_POSITION"), iInt4Oid,4);
|
f[16] = new Field(connection, new String("ORDINAL_POSITION"), iInt4Oid,4);
|
||||||
f[17] = new Field(connection, new String("IS_NULLABLE"), iVarcharOid, 32);
|
f[17] = new Field(connection, new String("IS_NULLABLE"), iVarcharOid, 32);
|
||||||
|
|
||||||
|
// Added by Stefan Andreasen <stefan@linux.kapow.dk>
|
||||||
|
// If the pattern are null then set them to %
|
||||||
|
if (tableNamePattern == null) tableNamePattern="%";
|
||||||
|
if (columnNamePattern == null) columnNamePattern="%";
|
||||||
|
|
||||||
// Now form the query
|
// Now form the query
|
||||||
r = connection.ExecSQL("select a.oid,c.relname,a.attname,a.atttypid,a.attnum,a.attnotnull,a.attlen,a.atttypmod 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");
|
// Modified by Stefan Andreasen <stefan@linux.kapow.dk>
|
||||||
|
r = connection.ExecSQL("select a.oid,c.relname,a.attname,a.atttypid,a.attnum,a.attnotnull,a.attlen,a.atttypmod from pg_class c, pg_attribute a where a.attrelid=c.oid and c.relname like '"+tableNamePattern.toLowerCase()+"' and a.attname like '"+columnNamePattern.toLowerCase()+"' and a.attnum>0 order by c.relname,a.attnum");
|
||||||
|
|
||||||
|
byte remarks[];
|
||||||
|
|
||||||
while(r.next()) {
|
while(r.next()) {
|
||||||
byte[][] tuple = new byte[18][0];
|
byte[][] tuple = new byte[18][0];
|
||||||
|
|
||||||
String name = r.getString(1);
|
|
||||||
String remarks = new String("no remarks");
|
|
||||||
String columnSize;
|
|
||||||
|
|
||||||
// Fetch the description for the table (if any)
|
// Fetch the description for the table (if any)
|
||||||
ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(1));
|
ResultSet dr = connection.ExecSQL("select description from pg_description where objoid="+r.getInt(1));
|
||||||
if(dr.getTupleCount()==1) {
|
if(dr.getTupleCount()==1) {
|
||||||
dr.next();
|
dr.next();
|
||||||
remarks=dr.getString(1);
|
tuple[11] = dr.getBytes(1);
|
||||||
}
|
} else
|
||||||
|
tuple[11] = defaultRemarks;
|
||||||
|
|
||||||
dr.close();
|
dr.close();
|
||||||
|
|
||||||
tuple[0] = "".getBytes(); // Catalog name
|
tuple[0] = "".getBytes(); // Catalog name
|
||||||
tuple[1] = "".getBytes(); // Schema name
|
tuple[1] = "".getBytes(); // Schema name
|
||||||
tuple[2] = r.getString(2).getBytes(); // Table name
|
tuple[2] = r.getBytes(2); // Table name
|
||||||
tuple[3] = r.getString(3).getBytes(); // Column name
|
tuple[3] = r.getBytes(3); // Column name
|
||||||
|
|
||||||
dr = connection.ExecSQL("select typname from pg_type where oid = "+r.getString(4));
|
dr = connection.ExecSQL("select typname from pg_type where oid = "+r.getString(4));
|
||||||
dr.next();
|
dr.next();
|
||||||
@ -1877,16 +1898,16 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
dr.close();
|
dr.close();
|
||||||
tuple[4] = Integer.toString(Field.getSQLType(typname)).getBytes(); // Data type
|
tuple[4] = Integer.toString(Field.getSQLType(typname)).getBytes(); // Data type
|
||||||
tuple[5] = typname.getBytes(); // Type name
|
tuple[5] = typname.getBytes(); // Type name
|
||||||
|
|
||||||
|
// Column size
|
||||||
// Looking at the psql source,
|
// Looking at the psql source,
|
||||||
// I think the length of a varchar as specified when the table was created
|
// I think the length of a varchar as specified when the table was created
|
||||||
// should be extracted from atttypmod which contains this length + sizeof(int32)
|
// should be extracted from atttypmod which contains this length + sizeof(int32)
|
||||||
if (typname.equals("bpchar") || typname.equals("varchar")) {
|
if (typname.equals("bpchar") || typname.equals("varchar")) {
|
||||||
int atttypmod = r.getInt(8);
|
int atttypmod = r.getInt(8);
|
||||||
columnSize = Integer.toString(atttypmod != -1 ? atttypmod - VARHDRSZ : 0);
|
tuple[6] = Integer.toString(atttypmod != -1 ? atttypmod - VARHDRSZ : 0).getBytes();
|
||||||
} else
|
} else
|
||||||
columnSize = r.getString(7);
|
tuple[6] = r.getBytes(7);
|
||||||
tuple[6] = columnSize.getBytes(); // Column size
|
|
||||||
|
|
||||||
tuple[7] = null; // Buffer length
|
tuple[7] = null; // Buffer length
|
||||||
|
|
||||||
@ -1894,8 +1915,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
tuple[9] = "10".getBytes(); // Num Prec Radix - assume decimal
|
tuple[9] = "10".getBytes(); // Num Prec Radix - assume decimal
|
||||||
|
|
||||||
// tuple[10] is below
|
// tuple[10] is below
|
||||||
|
// tuple[11] is above
|
||||||
tuple[11] = remarks.getBytes(); // Remarks
|
|
||||||
|
|
||||||
tuple[12] = null; // column default
|
tuple[12] = null; // column default
|
||||||
|
|
||||||
@ -1904,7 +1924,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
|
|
||||||
tuple[15] = tuple[6]; // char octet length
|
tuple[15] = tuple[6]; // char octet length
|
||||||
|
|
||||||
tuple[16] = r.getString(5).getBytes(); // ordinal position
|
tuple[16] = r.getBytes(5); // ordinal position
|
||||||
|
|
||||||
String nullFlag = r.getString(6);
|
String nullFlag = r.getString(6);
|
||||||
tuple[10] = Integer.toString(nullFlag.equals("f")?java.sql.DatabaseMetaData.columnNullable:java.sql.DatabaseMetaData.columnNoNulls).getBytes(); // Nullable
|
tuple[10] = Integer.toString(nullFlag.equals("f")?java.sql.DatabaseMetaData.columnNullable:java.sql.DatabaseMetaData.columnNoNulls).getBytes(); // Nullable
|
||||||
@ -1948,6 +1968,14 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
Field f[] = new Field[8];
|
Field f[] = new Field[8];
|
||||||
Vector v = new Vector();
|
Vector v = new Vector();
|
||||||
|
|
||||||
|
if(table==null)
|
||||||
|
table="%";
|
||||||
|
|
||||||
|
if(columnNamePattern==null)
|
||||||
|
columnNamePattern="%";
|
||||||
|
else
|
||||||
|
columnNamePattern=columnNamePattern.toLowerCase();
|
||||||
|
|
||||||
f[0] = new Field(connection,new String("TABLE_CAT"),iVarcharOid,32);
|
f[0] = new Field(connection,new String("TABLE_CAT"),iVarcharOid,32);
|
||||||
f[1] = new Field(connection,new String("TABLE_SCHEM"),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[2] = new Field(connection,new String("TABLE_NAME"),iVarcharOid,32);
|
||||||
@ -1958,11 +1986,13 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
f[7] = new Field(connection,new String("IS_GRANTABLE"),iVarcharOid,32);
|
f[7] = new Field(connection,new String("IS_GRANTABLE"),iVarcharOid,32);
|
||||||
|
|
||||||
// This is taken direct from the psql source
|
// 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");
|
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 and relname like '"+table.toLowerCase()+"' ORDER BY relname");
|
||||||
while(r.next()) {
|
while(r.next()) {
|
||||||
byte[][] tuple = new byte[8][0];
|
byte[][] tuple = new byte[8][0];
|
||||||
tuple[0] = tuple[1]= "".getBytes();
|
tuple[0] = tuple[1]= "".getBytes();
|
||||||
DriverManager.println("relname=\""+r.getString(1)+"\" relacl=\""+r.getString(2)+"\"");
|
DriverManager.println("relname=\""+r.getString(1)+"\" relacl=\""+r.getString(2)+"\"");
|
||||||
|
|
||||||
|
// For now, don't add to the result as relacl needs to be processed.
|
||||||
//v.addElement(tuple);
|
//v.addElement(tuple);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2122,7 +2152,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
"'1' as KEY_SEQ,"+ // -- fake it as a String for now
|
"'1' as KEY_SEQ,"+ // -- fake it as a String for now
|
||||||
"t.typname as PK_NAME " +
|
"t.typname as PK_NAME " +
|
||||||
" FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a, pg_type t " +
|
" FROM pg_class bc, pg_class ic, pg_index i, pg_attribute a, pg_type t " +
|
||||||
" WHERE relkind = 'r' " + // -- not indices
|
" WHERE bc.relkind = 'r' " + // -- not indices
|
||||||
" and bc.relname ~ '"+table+"'" +
|
" and bc.relname ~ '"+table+"'" +
|
||||||
" and i.indrelid = bc.oid" +
|
" and i.indrelid = bc.oid" +
|
||||||
" and i.indexrelid = ic.oid" +
|
" and i.indexrelid = ic.oid" +
|
||||||
@ -2379,22 +2409,30 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
f[16] = new Field(connection, new String("SQL_DATETIME_SUB"), iInt4Oid, 4);
|
f[16] = new Field(connection, new String("SQL_DATETIME_SUB"), iInt4Oid, 4);
|
||||||
f[17] = new Field(connection, new String("NUM_PREC_RADIX"), iInt4Oid, 4);
|
f[17] = new Field(connection, new String("NUM_PREC_RADIX"), iInt4Oid, 4);
|
||||||
|
|
||||||
|
// cache some results, this will keep memory useage down, and speed
|
||||||
|
// things up a little.
|
||||||
|
byte b9[] = "9".getBytes();
|
||||||
|
byte b10[] = "10".getBytes();
|
||||||
|
byte bf[] = "f".getBytes();
|
||||||
|
byte bnn[] = Integer.toString(typeNoNulls).getBytes();
|
||||||
|
byte bts[] = Integer.toString(typeSearchable).getBytes();
|
||||||
|
|
||||||
while(rs.next()) {
|
while(rs.next()) {
|
||||||
byte[][] tuple = new byte[18][];
|
byte[][] tuple = new byte[18][];
|
||||||
String typname=rs.getString(1);
|
String typname=rs.getString(1);
|
||||||
tuple[0] = typname.getBytes();
|
tuple[0] = typname.getBytes();
|
||||||
tuple[1] = Integer.toString(Field.getSQLType(typname)).getBytes();
|
tuple[1] = Integer.toString(Field.getSQLType(typname)).getBytes();
|
||||||
tuple[2] = "9".getBytes(); // for now
|
tuple[2] = b9; // for now
|
||||||
tuple[6] = Integer.toString(typeNoNulls).getBytes(); // for now
|
tuple[6] = bnn; // for now
|
||||||
tuple[7] = "f".getBytes(); // false for now - not case sensitive
|
tuple[7] = bf; // false for now - not case sensitive
|
||||||
tuple[8] = Integer.toString(typeSearchable).getBytes();
|
tuple[8] = bts;
|
||||||
tuple[9] = "f".getBytes(); // false for now - it's signed
|
tuple[9] = bf; // false for now - it's signed
|
||||||
tuple[10] = "f".getBytes(); // false for now - must handle money
|
tuple[10] = bf; // false for now - must handle money
|
||||||
tuple[11] = "f".getBytes(); // false for now - handle autoincrement
|
tuple[11] = bf; // false for now - handle autoincrement
|
||||||
// 12 - LOCAL_TYPE_NAME is null
|
// 12 - LOCAL_TYPE_NAME is null
|
||||||
// 13 & 14 ?
|
// 13 & 14 ?
|
||||||
// 15 & 16 are unused so we return null
|
// 15 & 16 are unused so we return null
|
||||||
tuple[17] = "10".getBytes(); // everything is base 10
|
tuple[17] = b10; // everything is base 10
|
||||||
v.addElement(tuple);
|
v.addElement(tuple);
|
||||||
}
|
}
|
||||||
rs.close();
|
rs.close();
|
||||||
@ -2431,7 +2469,7 @@ public class DatabaseMetaData implements java.sql.DatabaseMetaData
|
|||||||
* within index; zero when TYPE is tableIndexStatistic
|
* within index; zero when TYPE is tableIndexStatistic
|
||||||
* <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
|
* <LI><B>COLUMN_NAME</B> String => column name; null when TYPE is
|
||||||
* tableIndexStatistic
|
* tableIndexStatistic
|
||||||
* <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending,
|
* <LI><B>ASC_OR_DESC</B> String => column sort sequence, "A" => ascending
|
||||||
* "D" => descending, may be null if sort sequence is not supported;
|
* "D" => descending, may be null if sort sequence is not supported;
|
||||||
* null when TYPE is tableIndexStatistic
|
* null when TYPE is tableIndexStatistic
|
||||||
* <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatisic then
|
* <LI><B>CARDINALITY</B> int => When TYPE is tableIndexStatisic then
|
||||||
|
@ -27,7 +27,7 @@ public class Driver implements java.sql.Driver
|
|||||||
// These should be in sync with the backend that the driver was
|
// These should be in sync with the backend that the driver was
|
||||||
// distributed with
|
// distributed with
|
||||||
static final int MAJORVERSION = 6;
|
static final int MAJORVERSION = 6;
|
||||||
static final int MINORVERSION = 3;
|
static final int MINORVERSION = 4;
|
||||||
|
|
||||||
static
|
static
|
||||||
{
|
{
|
||||||
|
@ -20,7 +20,16 @@ public class PG_Stream
|
|||||||
{
|
{
|
||||||
private Socket connection;
|
private Socket connection;
|
||||||
private InputStream pg_input;
|
private InputStream pg_input;
|
||||||
private OutputStream pg_output;
|
private BufferedOutputStream pg_output;
|
||||||
|
|
||||||
|
// This is the error message returned when an EOF occurs
|
||||||
|
private static final String EOF_MSG = "The backend has broken the connection. Possibly the action you have attempted has caused it to close.";
|
||||||
|
|
||||||
|
// This is the error message returned when an IOException occurs
|
||||||
|
private static final String IOE_MSG = "IOError while reading from backend: ";
|
||||||
|
|
||||||
|
// This is the error message returned when flushing the stream.
|
||||||
|
private static final String FLUSH_MSG = "Error flushing output: ";
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Constructor: Connect to the PostgreSQL back end and return
|
* Constructor: Connect to the PostgreSQL back end and return
|
||||||
@ -33,8 +42,13 @@ public class PG_Stream
|
|||||||
public PG_Stream(String host, int port) throws IOException
|
public PG_Stream(String host, int port) throws IOException
|
||||||
{
|
{
|
||||||
connection = new Socket(host, port);
|
connection = new Socket(host, port);
|
||||||
|
|
||||||
|
// Submitted by Jason Venner <jason@idiom.com> adds a 10x speed
|
||||||
|
// improvement on FreeBSD machines (caused by a bug in their TCP Stack)
|
||||||
|
connection.setTcpNoDelay(true);
|
||||||
|
|
||||||
pg_input = connection.getInputStream();
|
pg_input = connection.getInputStream();
|
||||||
pg_output = connection.getOutputStream();
|
pg_output = new BufferedOutputStream(connection.getOutputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -45,7 +59,6 @@ public class PG_Stream
|
|||||||
*/
|
*/
|
||||||
public void SendChar(int val) throws IOException
|
public void SendChar(int val) throws IOException
|
||||||
{
|
{
|
||||||
//pg_output.write(val);
|
|
||||||
byte b[] = new byte[1];
|
byte b[] = new byte[1];
|
||||||
b[0] = (byte)val;
|
b[0] = (byte)val;
|
||||||
pg_output.write(b);
|
pg_output.write(b);
|
||||||
@ -165,9 +178,9 @@ public class PG_Stream
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
c = pg_input.read();
|
c = pg_input.read();
|
||||||
if (c < 0) throw new IOException("EOF");
|
if (c < 0) throw new IOException(EOF_MSG);
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SQLException("Error reading from backend: " + e.toString());
|
throw new SQLException(IOE_MSG + e.toString());
|
||||||
}
|
}
|
||||||
return c;
|
return c;
|
||||||
}
|
}
|
||||||
@ -190,11 +203,11 @@ public class PG_Stream
|
|||||||
int b = pg_input.read();
|
int b = pg_input.read();
|
||||||
|
|
||||||
if (b < 0)
|
if (b < 0)
|
||||||
throw new IOException("EOF");
|
throw new IOException(EOF_MSG);
|
||||||
n = n | (b << (8 * i)) ;
|
n = n | (b << (8 * i)) ;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SQLException("Error reading from backend: " + e.toString());
|
throw new SQLException(IOE_MSG + e.toString());
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@ -217,11 +230,11 @@ public class PG_Stream
|
|||||||
int b = pg_input.read();
|
int b = pg_input.read();
|
||||||
|
|
||||||
if (b < 0)
|
if (b < 0)
|
||||||
throw new IOException("EOF");
|
throw new IOException(EOF_MSG);
|
||||||
n = b | (n << 8);
|
n = b | (n << 8);
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SQLException("Error reading from backend: " + e.toString());
|
throw new SQLException(IOE_MSG + e.toString());
|
||||||
}
|
}
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
@ -246,7 +259,7 @@ public class PG_Stream
|
|||||||
{
|
{
|
||||||
int c = pg_input.read();
|
int c = pg_input.read();
|
||||||
if (c < 0)
|
if (c < 0)
|
||||||
throw new IOException("EOF");
|
throw new IOException(EOF_MSG);
|
||||||
else if (c == 0)
|
else if (c == 0)
|
||||||
break;
|
break;
|
||||||
else
|
else
|
||||||
@ -255,7 +268,7 @@ public class PG_Stream
|
|||||||
if (s >= maxsiz)
|
if (s >= maxsiz)
|
||||||
throw new IOException("Too Much Data");
|
throw new IOException("Too Much Data");
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SQLException("Error reading from backend: " + e.toString());
|
throw new SQLException(IOE_MSG + e.toString());
|
||||||
}
|
}
|
||||||
String v = new String(rst, 0, s);
|
String v = new String(rst, 0, s);
|
||||||
return v;
|
return v;
|
||||||
@ -314,21 +327,8 @@ public class PG_Stream
|
|||||||
private byte[] Receive(int siz) throws SQLException
|
private byte[] Receive(int siz) throws SQLException
|
||||||
{
|
{
|
||||||
byte[] answer = new byte[siz];
|
byte[] answer = new byte[siz];
|
||||||
int s = 0;
|
Receive(answer,0,siz);
|
||||||
|
return answer;
|
||||||
try
|
|
||||||
{
|
|
||||||
while (s < siz)
|
|
||||||
{
|
|
||||||
int w = pg_input.read(answer, s, siz - s);
|
|
||||||
if (w < 0)
|
|
||||||
throw new IOException("EOF");
|
|
||||||
s += w;
|
|
||||||
}
|
|
||||||
} catch (IOException e) {
|
|
||||||
throw new SQLException("Error reading from backend: " + e.toString());
|
|
||||||
}
|
|
||||||
return answer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -349,11 +349,11 @@ public class PG_Stream
|
|||||||
{
|
{
|
||||||
int w = pg_input.read(b, off+s, siz - s);
|
int w = pg_input.read(b, off+s, siz - s);
|
||||||
if (w < 0)
|
if (w < 0)
|
||||||
throw new IOException("EOF");
|
throw new IOException(EOF_MSG);
|
||||||
s += w;
|
s += w;
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SQLException("Error reading from backend: " + e.toString());
|
throw new SQLException(IOE_MSG + e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -367,7 +367,7 @@ public class PG_Stream
|
|||||||
try {
|
try {
|
||||||
pg_output.flush();
|
pg_output.flush();
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new SQLException("Error flushing output: " + e.toString());
|
throw new SQLException(FLUSH_MSG + e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -308,24 +308,21 @@ public class PreparedStatement extends Statement implements java.sql.PreparedSta
|
|||||||
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
|
public void setDate(int parameterIndex, java.sql.Date x) throws SQLException
|
||||||
{
|
{
|
||||||
SimpleDateFormat df = new SimpleDateFormat("''"+connection.getDateStyle()+"''");
|
SimpleDateFormat df = new SimpleDateFormat("''"+connection.getDateStyle()+"''");
|
||||||
|
|
||||||
// Ideally the following should work:
|
set(parameterIndex, df.format(x));
|
||||||
|
|
||||||
|
// The above is how the date should be handled.
|
||||||
//
|
//
|
||||||
// set(parameterIndex, df.format(x));
|
// However, in JDK's prior to 1.1.6 (confirmed with the
|
||||||
|
// Linux jdk1.1.3 and the Win95 JRE1.1.5), SimpleDateFormat seems
|
||||||
|
// to format a date to the previous day. So the fix is to add a day
|
||||||
|
// before formatting.
|
||||||
//
|
//
|
||||||
// however, SimpleDateFormat seems to format a date to the previous
|
// PS: 86400000 is one day
|
||||||
// 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()+86400000)));
|
||||||
//
|
|
||||||
set(parameterIndex, df.format(new java.util.Date(x.getTime()+DAY)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// This equates to 1 day
|
|
||||||
private static final int DAY = 86400000;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set a parameter to a java.sql.Time value. The driver converts
|
* Set a parameter to a java.sql.Time value. The driver converts
|
||||||
* this to a SQL TIME value when it sends it to the database.
|
* this to a SQL TIME value when it sends it to the database.
|
||||||
|
@ -714,6 +714,12 @@ public class ResultSet implements java.sql.ResultSet
|
|||||||
throw new SQLException("Column index out of range");
|
throw new SQLException("Column index out of range");
|
||||||
field = fields[columnIndex - 1];
|
field = fields[columnIndex - 1];
|
||||||
|
|
||||||
|
// some fields can be null, mainly from those returned by MetaData methods
|
||||||
|
if(field==null) {
|
||||||
|
wasNullFlag=true;
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
switch (field.getSQLType())
|
switch (field.getSQLType())
|
||||||
{
|
{
|
||||||
case Types.BIT:
|
case Types.BIT:
|
||||||
|
@ -121,11 +121,7 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData
|
|||||||
{
|
{
|
||||||
String type_name = getField(column).getTypeName();
|
String type_name = getField(column).getTypeName();
|
||||||
|
|
||||||
if (type_name.equals("cash"))
|
return type_name.equals("cash") || type_name.equals("money");
|
||||||
return true;
|
|
||||||
if (type_name.equals("money"))
|
|
||||||
return true;
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -214,11 +210,14 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData
|
|||||||
*
|
*
|
||||||
* @param column the first column is 1, the second is 2, etc.
|
* @param column the first column is 1, the second is 2, etc.
|
||||||
* @return the column name
|
* @return the column name
|
||||||
* @exception SQLException if a databvase access error occurs
|
* @exception SQLException if a database access error occurs
|
||||||
*/
|
*/
|
||||||
public String getColumnName(int column) throws SQLException
|
public String getColumnName(int column) throws SQLException
|
||||||
{
|
{
|
||||||
return getField(column).name;
|
Field f = getField(column);
|
||||||
|
if(f!=null)
|
||||||
|
return f.name;
|
||||||
|
return "field"+column;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -233,13 +232,7 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData
|
|||||||
*/
|
*/
|
||||||
public String getSchemaName(int column) throws SQLException
|
public String getSchemaName(int column) throws SQLException
|
||||||
{
|
{
|
||||||
String table_name = getTableName(column);
|
return "";
|
||||||
|
|
||||||
// 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.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -328,12 +321,7 @@ public class ResultSetMetaData implements java.sql.ResultSetMetaData
|
|||||||
*/
|
*/
|
||||||
public String getCatalogName(int column) throws SQLException
|
public String getCatalogName(int column) throws SQLException
|
||||||
{
|
{
|
||||||
String table_name = getTableName(column);
|
return "";
|
||||||
|
|
||||||
if (table_name.equals(""))
|
|
||||||
return "";
|
|
||||||
return ""; // As with getSchemaName(), this
|
|
||||||
// is just the start of it.
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user